"""Common csv writer helper."""
import gws
import gws.types as t
# @TODO use locale-dependent formatting
[docs]class Config(t.WithType):
"""CSV format settings"""
decimal: str = '.' #: decimal sign
delimiter: str = ',' #: field delimiter
encoding: str = 'utf8' #: encoding for CSV files
formulaHack: bool = True #: prepend numeric strings with an equal sign
precision: int = 2 #: precision for floats
quote: str = '"' #: quote sign
quoteAll: bool = False #: quote all fields
rowDelimiter: str = '\n' #: row delimiter
[docs]class Object(gws.Object):
[docs] def writer(self):
return _Writer(self)
class _Writer:
def __init__(self, helper):
self.h: Object = helper
self.rows = []
self.headers = ''
def write_headers(self, headers: t.List[str]):
self.headers = self.h.delimiter.join(self._quote(s) for s in headers)
return self
def write_attributes(self, attributes: t.List[t.Attribute]):
self.rows.append(self.h.delimiter.join(self._format(a.value, a.type) for a in attributes))
return self
def as_str(self):
rows = []
if self.headers:
rows.append(self.headers)
rows.extend(self.rows)
return self.h.row_delimiter.join(rows)
def as_bytes(self, encoding=None):
return self.as_str().encode(encoding or self.h.encoding)
def _format(self, val, type):
if val is None:
return self._quote('')
if type == t.AttributeType.float:
s = '{:.{prec}f}'.format(float(val), prec=self.h.precision)
s = s.replace('.', self.h.decimal)
return self._quote(s) if self.h.quote_all else s
if type == t.AttributeType.int:
s = str(val)
return self._quote(s) if self.h.quote_all else s
val = gws.as_str(val)
if val and val.isdigit() and self.h.formula_hack:
val = '=' + self._quote(val)
return self._quote(val)
def _quote(self, val):
q = self.h.quote
s = gws.as_str(val).replace(q, q + q)
return q + s + q