diff --git a/CHANGES.rst b/CHANGES.rst index 6cac396f..f29e8f18 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,7 +4,9 @@ Changelog 2.0.dev0 (unreleased) --------------------- -- Remove b'' from values in py3 csv export +- Use csv23 for py2/3 csv export. + Make export charset configurable. + Do not convert point to comma for numbers in export. [agitator] - Add contact information to export diff --git a/setup.py b/setup.py index e4b6b3df..5e0dc8a9 100644 --- a/setup.py +++ b/setup.py @@ -45,6 +45,7 @@ "setuptools", "simplejson>=2.1", # able to serialize Decimal "six", + "csv23", "yafowil.plone>2.999", "yafowil.widget.array", "yafowil.widget.datetime", diff --git a/src/bda/plone/orders/browser/export.py b/src/bda/plone/orders/browser/export.py index cd379e12..c75dc51f 100644 --- a/src/bda/plone/orders/browser/export.py +++ b/src/bda/plone/orders/browser/export.py @@ -29,25 +29,28 @@ from repoze.catalog.query import Eq from repoze.catalog.query import Ge from repoze.catalog.query import Le -from six import StringIO +from io import BytesIO from yafowil.base import ExtractionError from yafowil.controller import Controller from yafowil.plone.form import YAMLForm import csv +import csv23 import datetime import plone.api import uuid import yafowil.loader # noqa -import six class DialectExcelWithColons(csv.excel): delimiter = ";" -csv.register_dialect("excel-colon", DialectExcelWithColons) +csv23.register_dialect("excel-colon", DialectExcelWithColons) +EXPORT_DT_FORMAT = DT_FORMAT + +EXPORT_CHARSET = "UTF-8" ORDER_EXPORT_ATTRS = [ "uid", @@ -133,12 +136,10 @@ def cleanup_for_csv(value): """Cleanup a value for CSV export. """ if isinstance(value, datetime.datetime): - value = value.strftime(DT_FORMAT) + value = value.strftime(EXPORT_DT_FORMAT) if value == "-": value = "" - if isinstance(value, float) or isinstance(value, Decimal): - value = str(value).replace(".", ",") - return safe_encode(value) + return value class ExportOrdersForm(YAMLForm, BrowserView): @@ -218,8 +219,9 @@ def csv(self, request): if customer: query = query & Eq("creator", customer) # prepare csv writer - sio = StringIO() - ex = csv.writer(sio, dialect="excel-colon", quoting=csv.QUOTE_MINIMAL) + bio = BytesIO() + ex = csv23.writer(bio, dialect="excel-colon", + encoding=EXPORT_CHARSET) # exported column keys as first line ex.writerow( ORDER_EXPORT_ATTRS @@ -272,13 +274,7 @@ def csv(self, request): val = cb(self.context, booking) val = cleanup_for_csv(val) booking_attrs.append(val) - if six.PY3: - ex.writerow( - [x.decode() if isinstance(x, six.binary_type) else x - for x in order_attrs + contact_attrs + booking_attrs] - ) - else: - ex.writerow(order_attrs + contact_attrs + booking_attrs) + ex.writerow(order_attrs + contact_attrs + booking_attrs) booking.attrs["exported"] = True bookings_soup.reindex(booking) # create and return response @@ -289,8 +285,8 @@ def csv(self, request): self.request.response.setHeader( "Content-Disposition", "attachment; filename=%s" % filename ) - ret = sio.getvalue() - sio.close() + ret = bio.getvalue() + bio.close() return ret @@ -311,7 +307,8 @@ def __call__(self): ) filename = safe_filename(filename) resp = self.request.response - resp.setHeader("content-type", "text/csv; charset=utf-8") + resp.setHeader( + "content-type", "text/csv; charset={0}".format(EXPORT_CHARSET)) resp.setHeader("content-disposition", "attachment;filename={}".format(filename)) return self.get_csv() @@ -326,8 +323,9 @@ def get_csv(self): context = self.context # prepare csv writer - sio = StringIO() - ex = csv.writer(sio, dialect="excel-colon", quoting=csv.QUOTE_MINIMAL) + bio = BytesIO() + ex = csv23.writer(bio, dialect="excel-colon", + encoding=EXPORT_CHARSET) # exported column keys as first line ex.writerow( ORDER_EXPORT_ATTRS @@ -390,6 +388,6 @@ def get_csv(self): # booking.attrs['exported'] = True # bookings_soup.reindex(booking) - ret = sio.getvalue() - sio.close() + ret = bio.getvalue() + bio.close() return ret