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
foofile",
+ expected_contents = "