def process_bulk_add(ctx, param, value):
    if value is None:
        return value

    # This is our object name (e.g. 'devices')
    parent_resource_name = ctx.obj.parent_resource_name
    objects = []

    # Value is already an open file handle
    reader = csv.DictReader(value, delimiter=b':')
    for row in reader:
        lineno = reader.line_num

        # Make sure the file is correctly formatted.
        if len(row) != len(reader.fieldnames):
            msg = 'File has wrong number of fields on line %d' % (lineno,)
            raise click.BadParameter(msg)

        # Transform attributes for eligible resource types
        if parent_resource_name not in NO_ATTRIBUTES:
            # FIXME(jathan): This IS going to break at some point. We need to
            # considered how to take in complex a/v pairs in this context.
            # Naively split on ',' for now.
            incoming_attributes = row['attributes'].split(',')
            outgoing_attributes = transform_attributes(
                ctx, param, incoming_attributes
            )
            row['attributes'] = outgoing_attributes

        # Transform True, False into booleans
        log.debug('FILE ROW: %r', row)
        for key, val in row.iteritems():
            # Don't evaluate dicts
            if isinstance(val, dict):
                continue

            # Evaluate strings and if they are booleans, convert them.
            if not isinstance(val, basestring):
                msg = 'Error parsing file on line %d' % (lineno,)
                raise click.BadParameter(msg)
            if val.title() in ('True', 'False'):
                row[key] = ast.literal_eval(val)
        objects.append(row)

    log.debug('PARSED BULK DATA = %r' % (objects,))

    # Return a list of dicts
    return objects
Callback to parse bulk addition of objects from a colon-delimited file.
dataset/ETHPy150Open dropbox/pynsot/pynsot/commands/callbacks.py/process_bulk_add