@classmethod
    def csv2tree(cls, source,
                 resourcename=None,
                 extra_data=None,
                 hashtags=None,
                 delimiter=",",
                 quotechar='"'):
        """
            Convert a table-form CSV source into an element tree, consisting of
            <table name="format">, <row> and <col field="fieldname"> elements.

            @param source: the source (file-like object)
            @param resourcename: the resource name
            @param extra_data: dict of extra cols {key:value} to add to each row
            @param hashtags: dict of hashtags for extra cols {key:hashtag}
            @param delimiter: delimiter for values
            @param quotechar: quotation character

            @todo: add a character encoding parameter to skip the guessing
        """

        import csv

        # Increase field size to be able to import WKTs
        csv.field_size_limit(2**20 * 100)  # 100 megs

        # Shortcuts
        ATTRIBUTE = cls.ATTRIBUTE
        FIELD = ATTRIBUTE.field
        HASHTAG = ATTRIBUTE.hashtag
        TAG = cls.TAG
        COL = TAG.col
        SubElement = etree.SubElement

        root = etree.Element(TAG.table)
        if resourcename is not None:
            root.set(ATTRIBUTE.name, resourcename)

        def add_col(row, key, value, hashtags=None):
            col = SubElement(row, COL)
            col.set(FIELD, s3_unicode(key))
            if hashtags:
                hashtag = hashtags.get(key)
                if hashtag and hashtag[1:]:
                    col.set(HASHTAG, hashtag)
            if value:
                text = s3_unicode(value).strip()
                if text[:6].lower() not in ("null", "<null>"):
                    try:
                        col.text = text
                    except MemoryError:
                        current.log.error("S3XML: Unable to set value for key %s: MemoryError" % key)
            else:
                col.text = ""

        def utf_8_encode(source):
            """
                UTF-8-recode the source line by line, guessing the character
                encoding of the source.
            """
            # Make this a list of all encodings you need to support (as long as
            # they are supported by Python codecs), always starting with the most
            # likely.
            encodings = ("utf-8-sig", "iso-8859-1")
            e = encodings[0]
            for line in source:
                if e:
                    try:
                        yield unicode(line, e, "strict").encode("utf-8")
                    except:
                        pass
                    else:
                        continue
                for encoding in encodings:
                    try:
                        yield unicode(line, encoding, "strict").encode("utf-8")
                    except:
                        continue
                    else:
                        e = encoding
                        break

        hashtags = dict(hashtags) if hashtags else {}

        try:
            import StringIO
            if not isinstance(source, StringIO.StringIO):
                source = utf_8_encode(source)
            reader = csv.DictReader(source,
                                    delimiter=delimiter,
                                    quotechar=quotechar)
            ROW = TAG.row
            for i, r in enumerate(reader):
                # Skip empty rows
                if not any(r.values()):
                    continue
                if i == 0:
                    # Auto-detect hashtags
                    items = dict((k, s3_unicode(v.strip()))
                                 for k, v in r.items() if k and v and v.strip())
                    if all(v[0] == "#" for v in items.values()):
                        hashtags.update(items)
                        continue
                row = SubElement(root, ROW)
                for k in r:
                    if k:
                        add_col(row, k, r[k], hashtags=hashtags)
                if extra_data:
                    for key in extra_data:
                        if key not in r:
                            add_col(row, key, extra_data[key], hashtags=hashtags)
        except csv.Error:
            e = sys.exc_info()[1]
            raise HTTP(400, body=cls.json_message(False, 400, e))

        # Use this to debug the source tree if needed:
        #print >>sys.stderr, cls.tostring(root, pretty_print=True)

        return  etree.ElementTree(root)

# =============================================================================
dataset/ETHPy150Open sahana/eden/modules/s3/s3xml.py/S3XML.csv2tree/original