Re: Error in table column sizing with Platypus
Robin Becker <[email protected]> Sun, 21 Dec 2025 10:59:49 +0000
| Newsgroups | gmane.comp.python.reportlab.user |
|---|---|
| Message-ID | <CAOBYczroz1LwgJ60AS=FrT5dzEKiUshXqwvm95r+rBcpYQB5AA@mail.gmail.com> |
--===============6012344371152731635== Content-Type: multipart/alternative; boundary="0000000000003c6eae06467436c6" --0000000000003c6eae06467436c6 Content-Type: text/plain; charset="UTF-8" Hi Andy, thanks for the report. It is a bug so perhaps this is a rare case as tests did not catch it. I have added a fix and another test. They will be in the release. On Sat, 20 Dec 2025 at 16:52, Andy Hagar <[email protected]> wrote: > Hello! > > I recently ran into an issue with table column sizing. Initially, the > error message was for: > AttributeError: 'float' object has no attribute 'endswith' > > An example setup is below to show the error happening. > > To get to this code path, I happened to have the following in my table > using Platypus > -At least 1 entry in a row uses Paragraph for formatting > -Specifying colWidth with one entry using percentage "%" > -Data in columns causing total column width to exceed availableWidth > > The error occurs at line 940 in tables.py: > if w.endswith('%'): > > Watching at execution, w is indeed a float. > Just changing to using the already existing _endswidth(w,'%') function > does allow the pdf to build, but it is ignoring the "X%" specified. > > Changing line 940 and the following has it look at W where the actual "X%" > value exists, but also changes the calculation on line 941 to handle the > percentage calc (assuming it is meant to be a % out of 100). > > Current: > if w.endswith('%'): > W[colNo] = w = availWidth*float(w[:-1])/percentTotal > > Updated: > if _endswith(W[colNo], '%'): > W[colNo] = w = availWidth * float(W[colNo][:-1]) / 100 > > > This change works fine to a point. When you specify a large-ish % and have > columns that are "wide", other errors start showing up. For the below > script, 88 or higher % causes errors elsewhere. > > This error is already called out in > https://groups.google.com/g/reportlab-users/c/k7GS01u3jrU > Error: > TypeError: '>' not supported between instances of 'NoneType' and 'int' > > Caused by Line 440: > tallest = '(tallest row %d)' % int(max(rh)) > > Changing to: > tallest = '(tallest row %d)' % int(max([i for i in rh if i], default=0)) > > Next error: > ValueError: <Table@0x20017F3A270 2 rows x 3 cols(tallest row 18)> with > cell(0,0) containing > 'Header 1': flowable given negative availWidth=-0.779770753733942 == > width=11.220229246266058 - leftPadding=6 - rightPadding=6 > > > At this point, as I was changing the % for testing and errors started > getting out of my depth, I just said "don't use silly %" and went about my > business :) > > --- > > Example script to hit this code path: > > from reportlab.platypus import SimpleDocTemplate, Table, Paragraph > from reportlab.lib.pagesizes import letter > from reportlab.lib.styles import getSampleStyleSheet > > styles = getSampleStyleSheet() > > data = [ > ['Header 1', 'Header 2', 'Header 3'], > [Paragraph('Row 1, Col 1 wide data wide data wide data wide data', > styles['Normal']), 'Row 1, Col 2 wide data wide data wide data', 'Row 1, > Col 3 wide data wide data wide data'] > ] > > doc = SimpleDocTemplate("table_endswidth.pdf", pagesize=letter) > story = [] > > colwidths = [None, "20%", None] > table = Table(data, colWidths=colwidths) > > story.append(table) > doc.build(story) > -- Robin Becker --0000000000003c6eae06467436c6 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr"><div>Hi Andy, thanks for the report. It is a bug so perhap= s this is a rare case as tests did not catch it.</div><div><br></div><div>I= have added a fix and another test. They will be in the release.</div></div= ><br><div class=3D"gmail_quote gmail_quote_container"><div dir=3D"ltr" clas= s=3D"gmail_attr">On Sat, 20 Dec 2025 at 16:52, Andy Hagar <<a href=3D"ma= ilto:[email protected]">[email protected]</a>> wrote:<br></div><bloc= kquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left:= 1px solid rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr">Hello!<br><br= >I recently ran into an issue with table column sizing. Initially, the erro= r message was for:<br>AttributeError: 'float' object has no attribu= te 'endswith'<br><br>An example setup is below to show the error ha= ppening.<br><br>To get to this code path, I happened to have the following = in my table using Platypus<br>-At least 1 entry in a row uses Paragraph for= formatting<br>-Specifying colWidth with one entry using percentage "%= "<br>-Data in columns causing total column width to exceed availableWi= dth<br><br>The error occurs at line 940 in tables.py:<br>if w.endswith('= ;%'):<br><br>Watching at execution, w is indeed a float.<br>Just changi= ng to using the already existing _endswidth(w,'%') function does al= low the pdf to build, but it is ignoring the "X%" specified.<br><= br>Changing line 940 and the following has it look at W where the actual &q= uot;X%" value exists, but also changes the calculation on line 941 to = handle the percentage calc (assuming it is meant to be a % out of 100).<br>= <br>Current:<br>if w.endswith('%'):<br> W[colNo] =3D w =3D availWid= th*float(w[:-1])/percentTotal<br><br>Updated:<br>if _endswith(W[colNo], = 9;%'):<br> W[colNo] =3D w =3D availWidth * float(W[colNo][:-1]) / 100<b= r><br><br>This change works fine to a point. When you specify a large-ish %= and have columns that are "wide", other errors start showing up.= For the below script, 88 or higher % causes errors elsewhere.<br><br>This = error is already called out in <a href=3D"https://groups.google.com/g/repor= tlab-users/c/k7GS01u3jrU" target=3D"_blank">https://groups.google.com/g/rep= ortlab-users/c/k7GS01u3jrU</a><br>Error:<br>TypeError: '>' not s= upported between instances of 'NoneType' and 'int'<br><br>C= aused by Line 440:<br>tallest =3D '(tallest row %d)' % int(max(rh))= <br><br>Changing to:<br>tallest =3D '(tallest row %d)' % int(max([i= for i in rh if i], default=3D0))<br><br>Next error:<br>ValueError: <Tab= le@0x20017F3A270 2 rows x 3 cols(tallest row 18)> with cell(0,0) contain= ing<br>'Header 1': flowable given negative availWidth=3D-0.77977075= 3733942 =3D=3D width=3D11.220229246266058 - leftPadding=3D6 - rightPadding= =3D6<br><br><br>At this point, as I was changing the % for testing and erro= rs started getting out of my depth, I just said "don't use silly %= " and went about my business :)=C2=A0<br><br>---<br><br>Example script= to hit this code path:<br><br>from reportlab.platypus import SimpleDocTemp= late, Table, Paragraph<br>from reportlab.lib.pagesizes import letter<br>fro= m reportlab.lib.styles import getSampleStyleSheet<br><br>styles =3D getSamp= leStyleSheet()<br><br>data =3D [<br>=C2=A0 =C2=A0 ['Header 1', '= ;Header 2', 'Header 3'],<br>=C2=A0 =C2=A0 [Paragraph('Row 1= , Col 1 wide data wide data wide data wide data', styles['Normal= 9;]), 'Row 1, Col 2 wide data wide data wide data', 'Row 1, Col= 3 wide data wide data wide data']<br>]<br><br>doc =3D SimpleDocTemplat= e("table_endswidth.pdf", pagesize=3Dletter)<br>story =3D []<br><b= r>colwidths =3D [None, "20%", None] <br>table =3D Table(data, col= Widths=3Dcolwidths)<br><br>story.append(table)<br>doc.build(story)</div> </blockquote></div><div><br clear=3D"all"></div><br><span class=3D"gmail_si= gnature_prefix">-- </span><br><div dir=3D"ltr" class=3D"gmail_signature">Ro= bin Becker<br></div> --0000000000003c6eae06467436c6-- --===============6012344371152731635== Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline