From e6fbbfec41e85af362d870709d5aa17ad54f4af7 Mon Sep 17 00:00:00 2001 From: Dan Helfman Date: Fri, 20 Feb 2009 15:22:23 -0800 Subject: [PATCH] Several minor improvements to CSV importing and exporting. --- NEWS | 1 + plugins/export_csv/__init__.py | 16 ++++++++++++++-- plugins/export_csv/test/Test_export_csv.py | 19 +++++++++++++++++-- plugins/export_html/Html_file.py | 2 ++ 4 files changed, 34 insertions(+), 4 deletions(-) diff --git a/NEWS b/NEWS index 25596f7..3fee715 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,7 @@ * When you export your notebook as an HTML or CSV file, the saved filename is now based on the name of your notebook, for instance "my-to-do-list.html" or "ideas-for-my-novel.csv". + * Several minor improvements to CSV importing and exporting. * Converted the existing HTML and CSV export features to work as separate export plugins. This means that a new export format can be implemented as a new plugin. diff --git a/plugins/export_csv/__init__.py b/plugins/export_csv/__init__.py index 7a971d8..ff8ca76 100644 --- a/plugins/export_csv/__init__.py +++ b/plugins/export_csv/__init__.py @@ -1,18 +1,30 @@ +import re import csv from cStringIO import StringIO from model.User import User +FILE_LINK_PATTERN = re.compile( u']*>', re.IGNORECASE ) +IMAGE_PATTERN = re.compile( u']* ?/?>', re.IGNORECASE ) +NEWLINE_PATTERN = re.compile( u'[\r\n]+' ) + + def export( database, notebook, notes, response_headers ): """ Format the given notes as a CSV file and return it as a streaming generator. """ buffer = StringIO() - writer = csv.writer( buffer ) + writer = csv.writer( buffer, quoting = csv.QUOTE_NONNUMERIC ) response_headers[ u"Content-Disposition" ] = u"attachment; filename=%s.csv" % notebook.friendly_id response_headers[ u"Content-Type" ] = u"text/csv;charset=utf-8" + def prepare_contents( contents ): + contents = FILE_LINK_PATTERN.sub( '', contents ) + contents = IMAGE_PATTERN.sub( '', contents ) + contents = NEWLINE_PATTERN.sub( ' ', contents ) + return contents.strip() + def stream(): writer.writerow( ( u"contents", u"title", u"note_id", u"startup", u"username", u"revision_date" ) ) yield buffer.getvalue() @@ -24,7 +36,7 @@ def export( database, notebook, notes, response_headers ): user = database.load( User, note.user_id ) writer.writerow( ( - note.contents and note.contents.strip().encode( "utf8" ) or None, + note.contents and prepare_contents( note.contents ).encode( "utf8" ) or None, note.title and note.title.strip().encode( "utf8" ) or None, note.object_id, note.startup and 1 or 0, diff --git a/plugins/export_csv/test/Test_export_csv.py b/plugins/export_csv/test/Test_export_csv.py index 9110d49..7491d1f 100644 --- a/plugins/export_csv/test/Test_export_csv.py +++ b/plugins/export_csv/test/Test_export_csv.py @@ -41,7 +41,7 @@ class Test_export_csv( object ): self.note2 = Note.create( note_id, u"

other title

whee", notebook_id = self.notebook.object_id, user_id = self.user.object_id ) self.database.save( self.note2, commit = False ) - def test_export_csv( self, note_contents = None ): + def test_export_csv( self, note_contents = None, expected_contents = None ): if not note_contents: note_contents = u"

blah

foo" @@ -87,7 +87,10 @@ class Test_export_csv( object ): expected_note = expected_notes[ note_count ] assert expected_note - assert contents.decode( "utf8" ) == expected_note.contents.strip() + if expected_contents and note_id == note3.object_id: + assert contents.decode( "utf8" ) == expected_contents.replace( "\n", " " ).strip() + else: + assert contents.decode( "utf8" ) == expected_note.contents.replace( "\n", " " ).strip() if expected_note.title: assert title.decode( "utf8" ) == expected_note.title.strip() @@ -115,6 +118,18 @@ class Test_export_csv( object ): def test_export_csv_with_trailing_newline_in_contents( self ): self.test_export_csv( note_contents = u"

blah

foo\n" ) + def test_export_csv_with_file_attachment_in_contents( self ): + self.test_export_csv( + note_contents = u"

blah

foo
file", + expected_contents = "

blah

foofile", + ) + + def test_export_csv_with_image_in_contents( self ): + self.test_export_csv( + note_contents = u"

blah

foo", + expected_contents = "

blah

foo", + ) + def test_export_csv_with_blank_username( self ): self.user._User__username = None self.database.save( self.user ) diff --git a/plugins/export_html/Html_file.py b/plugins/export_html/Html_file.py index b160d48..041899e 100644 --- a/plugins/export_html/Html_file.py +++ b/plugins/export_html/Html_file.py @@ -5,6 +5,7 @@ from view.Tags import Html, Head, Title, Style, Meta, Body, H1, Div, Span, Hr, A class Html_file( Html ): NOTE_LINK_PATTERN = re.compile( u']+[?&]note_id=([a-z0-9]*)"[^>]*>', re.IGNORECASE ) + FILE_LINK_PATTERN = re.compile( u']*>', re.IGNORECASE ) IMAGE_PATTERN = re.compile( u']* ?/?>', re.IGNORECASE ) def __init__( self, notebook, notes ): @@ -14,6 +15,7 @@ class Html_file( Html ): # images since they're not presently included with the download for note in notes: contents = self.NOTE_LINK_PATTERN.sub( r'', note.contents ) + contents = self.FILE_LINK_PATTERN.sub( '', contents ) contents = self.IMAGE_PATTERN.sub( '', contents ) relinked_notes[ note.object_id ] = contents