From 247d045cc9c31702bead726aae32e731d4398959 Mon Sep 17 00:00:00 2001 From: Alex Pavlovich Date: Sun, 22 Aug 2021 05:16:38 -0400 Subject: [PATCH] fix parse_csv in templates to parse numbers (#205) --- fpdf/fpdf.py | 2 +- fpdf/template.py | 16 ++++++++++++---- fpdf/util.py | 14 ++++++++++++++ test/template/mycsvfile.csv | 8 ++++---- test/template/template_nominal_csv.pdf | Bin 902 -> 1139 bytes test/template/test_template.py | 8 +++++++- 6 files changed, 38 insertions(+), 10 deletions(-) diff --git a/fpdf/fpdf.py b/fpdf/fpdf.py index ad1c352d7..8068b5d85 100644 --- a/fpdf/fpdf.py +++ b/fpdf/fpdf.py @@ -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 diff --git a/fpdf/template.py b/fpdf/template.py index 130c071f6..38c2011d7 100644 --- a/fpdf/template.py +++ b/fpdf/template.py @@ -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): @@ -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", @@ -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] @@ -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"] diff --git a/fpdf/util.py b/fpdf/util.py index ca29b4244..e48778641 100644 --- a/fpdf/util.py +++ b/fpdf/util.py @@ -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: diff --git a/test/template/mycsvfile.csv b/test/template/mycsvfile.csv index 4d99c712c..0b541b671 100644 --- a/test/template/mycsvfile.csv +++ b/test/template/mycsvfile.csv @@ -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 diff --git a/test/template/template_nominal_csv.pdf b/test/template/template_nominal_csv.pdf index 7327a5840c92861f14ca1d21abd0ac2dc07319f2..c68cbed8357798a73221f6daa418eca0c7b99ea0 100644 GIT binary patch delta 393 zcmZo;|I9I=uHMkZ+|G`xxTGjGF_)`iPHo>ou0sX_F7JPKS-wiW>pLr@STy8=+B0^R ztr}|=i2SK-4vliGiY%LPJXvR3+evquvqs4q#XJQ4wE4V60v1Y-91u~w> zQ5DOde4Q=*=Ktr5s+Y1J*jGMCEs-zXfB4^<9gEeorx-;PF$OBOhD_+6ahLCHW?zl2 zO4(($ov2IX)ZereK55^`| zeK#Wov&lyp6&cMZKWFr1w3uwllxt$iWdH{XW~QdbrV42aFfn5T69urWLLOYq)WUM| zH6}}YV@m@JITK4m3^8*9V@xp%!^u|6(uS5?`a${mB?=Y_1`0u3`kr}d`3mM>HaMIU Vi%KerQq#CBEKImmRbBnvxB#zpgp>dP delta 243 zcmey&(Z)WZ&dAup&W@|Nq$o8pm#boqanOfHMi-1t!!@24aRpu|Hx4l{xom6@z~LEO z!26JiA%>GpVX_>fDWk&VV8$7feVKeFFJ_XN{F;$#@<}EaM)S#h%(;vflWUk|#0@P? z6bwK>Ay0t|%rG!8wlJE!p4qb8$ifgq&cwnDL(J3+$&8Ys#LS%3A}$*nF8$!ls#FCF vF8!eV{1OFo1p|d3E`86uw0s4i89+AJONm7#6-B9OTxMqGT&k+B{%%|V9o;~J diff --git a/test/template/test_template.py b/test/template/test_template.py index 8957cb74c..2298e415c 100644 --- a/test/template/test_template.py +++ b/test/template/test_template.py @@ -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