Skip to content

Commit

Permalink
fix parse_csv in templates to parse numbers (#205)
Browse files Browse the repository at this point in the history
  • Loading branch information
Alex Pavlovich authored Aug 22, 2021
1 parent cc0cf83 commit 247d045
Show file tree
Hide file tree
Showing 6 changed files with 38 additions and 10 deletions.
2 changes: 1 addition & 1 deletion fpdf/fpdf.py
Original file line number Diff line number Diff line change
Expand Up @@ -1766,7 +1766,7 @@ def _preload_font_styles(self, txt, markdown):
to avoid repeating this processing later on.
"""
if not txt or not markdown:
return ((txt, self.font_style, bool(self.underline)),)
return tuple([[txt, self.font_style, bool(self.underline)]])
prev_font_style = self.font_style
styled_txt_frags = tuple(self._markdown_parse(txt))
page = self.page
Expand Down
16 changes: 12 additions & 4 deletions fpdf/template.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@
__license__ = "LGPL 3.0"

import csv
import locale
import warnings

from .errors import FPDFException
from .fpdf import FPDF
from .util import try_to_type


def rgb(col):
Expand Down Expand Up @@ -64,7 +66,7 @@ def load_elements(self, elements):
self.elements = elements
self.keys = [v["name"].lower() for v in self.elements]

def parse_csv(self, infile, delimiter=",", decimal_sep="."):
def parse_csv(self, infile, delimiter=",", decimal_sep=".", encoding=None):
"""Parse template format csv file and create elements dict"""
keys = (
"name",
Expand All @@ -87,13 +89,17 @@ def parse_csv(self, infile, delimiter=",", decimal_sep="."):
)
self.elements = []
self.pg_no = 0
with open(infile) as f:
if encoding is None:
encoding = locale.getpreferredencoding()
with open(infile, encoding=encoding) as f:
for row in csv.reader(f, delimiter=delimiter):
kargs = {}
for i, v in enumerate(row):
if not v.startswith("'") and decimal_sep != ".":
v = v.replace(decimal_sep, ".")
kargs[keys[i]] = v.strip()
stripped_value = v.strip()
typed_value = try_to_type(stripped_value)
kargs[keys[i]] = typed_value
self.elements.append(kargs)
self.keys = [v["name"].lower() for v in self.elements]

Expand Down Expand Up @@ -174,7 +180,9 @@ def render(self, outfile=None, dest=None):
pdf.set_font("helvetica", "B", 16)
pdf.set_auto_page_break(False, margin=0)

for element in sorted(self.elements, key=lambda x: x["priority"]):
sorted_elements = sorted(self.elements, key=lambda x: x["priority"])

for element in sorted_elements:
element = element.copy()
element["text"] = self.texts[pg].get(
element["name"].lower(), element["text"]
Expand Down
14 changes: 14 additions & 0 deletions fpdf/util.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,20 @@
import locale
from typing import Union, Iterable

try_to_type_known_types = [
int,
float,
]


def try_to_type(value):
for known_type in try_to_type_known_types:
try:
return known_type(value)
except ValueError:
pass
return value


def substr(s, start, length=-1):
if length < 0:
Expand Down
8 changes: 4 additions & 4 deletions test/template/mycsvfile.csv
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
line0;T;20.0;13.0;190.0;13.0;times;10.0;0;0;0;0;65535;C;;0
line1;T;20.0;67.0;190.0;67.0;times;10.0;0;0;0;0;65535;C;;0
name0;T;21;14;104;25;times;16.0;0;0;0;0;0;C;;2
title0;T;64;26;104;30;times;10.0;0;0;0;0;0;C;;2
line0;L;20.0;12.0;190.0;12.0;times;0.5;0;0;0;0;65535;C;;0
line1;L;20.0;36.0;190.0;36.0;times;0.5;0;0;0;0;65535;C;;0
name0;T;21;14;104;25;times;16.0;0;0;0;0;0;L;name;2
title0;T;21;26;104;30;times;10.0;0;0;0;0;0;L;title;2
Binary file modified test/template/template_nominal_csv.pdf
Binary file not shown.
8 changes: 7 additions & 1 deletion test/template/test_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,13 @@ def test_template_nominal_csv(tmp_path):
tmpl = Template(format="A4", title="Sample Invoice")
tmpl.parse_csv(HERE / "mycsvfile.csv", delimiter=";")
tmpl.add_page()
assert_pdf_equal(tmpl, HERE / "template_nominal_csv.pdf", tmp_path)
tmpl.render()
assert_pdf_equal(tmpl.pdf, HERE / "template_nominal_csv.pdf", tmp_path)
tmpl = Template(format="A4", title="Sample Invoice")
tmpl.parse_csv(HERE / "mycsvfile.csv", delimiter=";", encoding="utf-8")
tmpl.add_page()
tmpl.render()
assert_pdf_equal(tmpl.pdf, HERE / "template_nominal_csv.pdf", tmp_path)


def test_template_code39(tmp_path): # issue-161
Expand Down

0 comments on commit 247d045

Please sign in to comment.