changeset 2877:e0afda75944f

enhance csv parser - add a header row to thead rather than tbody
author RogerHaase <haaserd@gmail.com>
date Wed, 14 Jan 2015 07:55:17 -0700
parents 81cf2be555cb
children 41f12b86b046
files MoinMoin/converter/_table.py MoinMoin/converter/_tests/test_csv_in.py MoinMoin/converter/text_csv_in.py MoinMoin/static/css/common.css
diffstat 4 files changed, 63 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/MoinMoin/converter/_table.py	Tue Jan 13 09:31:43 2015 -0700
+++ b/MoinMoin/converter/_table.py	Wed Jan 14 07:55:17 2015 -0700
@@ -40,7 +40,7 @@
             table_row = moin_page.table_row()
             for idx, cell in enumerate(head):
                 table_cell = moin_page.table_cell(children=[cell, ],)
-                if rows:
+                if rows and len(rows[0]) == len(head):
                     # add "align: right" to heading cell if cell in first data row is numeric
                     self.add_numeric_class(rows[0][idx], table_cell)
                 table_row.append(table_cell)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MoinMoin/converter/_tests/test_csv_in.py	Wed Jan 14 07:55:17 2015 -0700
@@ -0,0 +1,49 @@
+# Copyright: 2015 MoinMoin:RogerHaase
+# License: GNU GPL v2 (or any later version), see LICENSE.txt for details.
+
+"""
+MoinMoin - Tests for MoinMoin.converter.text_csv_in
+"""
+
+
+import re
+
+from MoinMoin.util.tree import moin_page, xlink, html, xinclude
+
+from ..text_csv_in import Converter
+
+
+class TestConverter(object):
+    namespaces = {
+        moin_page: '',
+        xlink: 'xlink',
+        html: 'xhtml',
+        xinclude: 'xinclude',
+    }
+
+    output_re = re.compile(r'\s+xmlns(:\S+)?="[^"]+"')
+
+    def setup_class(self):
+        self.conv = Converter()
+
+    def test_csv(self):
+        data = [
+            # first row not recognized as a header by Python csv module
+            (u'Head A,Head B\na,bb\nccc,dddd',
+                '<page><body><table><table-body><table-row><table-cell>Head A</table-cell><table-cell>Head B</table-cell></table-row><table-row><table-cell>a</table-cell><table-cell>bb</table-cell></table-row><table-row><table-cell>ccc</table-cell><table-cell>dddd</table-cell></table-row></table-body></table></body></page>'),
+            # first row recognized as header
+            (u'Head A;Head B\n1;2\n3;4',
+                '<page><body><table class="moin-sortable"><table-header><table-row><table-cell class="moin-integer">Head A</table-cell><table-cell class="moin-integer">Head B</table-cell></table-row></table-header><table-body><table-row><table-cell class="moin-integer">1</table-cell><table-cell class="moin-integer">2</table-cell></table-row><table-row><table-cell class="moin-integer">3</table-cell><table-cell class="moin-integer">4</table-cell></table-row></table-body></table></body></page>'),
+        ]
+        for i in data:
+            yield (self.do, ) + i
+
+    def serialize(self, elem, **options):
+        from StringIO import StringIO
+        buffer = StringIO()
+        elem.write(buffer.write, namespaces=self.namespaces, **options)
+        return self.output_re.sub(u'', buffer.getvalue())
+
+    def do(self, input, output, args={}):
+        out = self.conv(input, 'text/csv;charset=utf-8', **args)
+        assert self.serialize(out) == output
--- a/MoinMoin/converter/text_csv_in.py	Tue Jan 13 09:31:43 2015 -0700
+++ b/MoinMoin/converter/text_csv_in.py	Wed Jan 14 07:55:17 2015 -0700
@@ -13,6 +13,7 @@
 from ._table import TableMixin
 from ._util import decode_data, normalize_split_text
 from MoinMoin.util.tree import moin_page
+from MoinMoin.i18n import _, L_, N_
 
 
 class Converter(TableMixin):
@@ -40,7 +41,17 @@
                 row.append(encoded_cell.decode('utf-8'))
             if row:
                 rows.append(row)
-        table = self.build_dom_table(rows)
+        head = None
+        cls = None
+        try:
+            # fragile function throws errors when csv file is incorrectly formatted
+            if csv.Sniffer().has_header('\n'.join(content)):
+                head = rows[0]
+                rows = rows[1:]
+                cls = 'moin-sortable'
+        except csv.Error as e:
+            head = [_('Error parsing CSV file:'), str(e)]
+        table = self.build_dom_table(rows, head=head, cls=cls)
         body = moin_page.body(children=(table, ))
         return moin_page.page(children=(body, ))
 
--- a/MoinMoin/static/css/common.css	Tue Jan 13 09:31:43 2015 -0700
+++ b/MoinMoin/static/css/common.css	Wed Jan 14 07:55:17 2015 -0700
@@ -188,6 +188,7 @@
 table { margin: 1%; }
 tr > th,
 tr > td { padding: .3em .4em; vertical-align: middle; text-align: left; }
+thead > tr > td,
 tr > th { border: 1px solid #4e7da9; background-color: #81bbf2; text-align: left; color: #000; }
 tr > td { border: 1px solid #4e7da9; }
 td p { margin: 0; padding: 0; }