Kozea / WeasyPrint

The awesome document factory
https://weasyprint.org
BSD 3-Clause "New" or "Revised" License
7.22k stars 686 forks source link

Tables.py float division by zero #1190

Closed JohannesMunk closed 3 years ago

JohannesMunk commented 4 years ago

Hey Team!

In our current project we generate a lot of html-tables with text-content that we do not have direct control over.

We are running into weasyprint crashes, one of which is the following:

Callstack:
File "I:\xClients\WeasyPrint\weasyprint\layout\tables.py", line 709
in auto_table_layout (assignable_width - sum(lower_guess)) / sum(added_widths))
ZeroDivisionError: float division by zero
```"I:\yRuntimes-x64-msvc2017\Python\python.exe" -m weasyprint "J:\Daten\test.tmp_08_4_9_6.html" "J:\Daten\test.tmp_08_4_9_6.html.pdf" Traceback (most recent call last): File "I:\yRuntimes-x64-msvc2017\Python\lib\runpy.py", line 193, in _run_module_as_main "__main__", mod_spec) File "I:\yRuntimes-x64-msvc2017\Python\lib\runpy.py", line 85, in _run_code exec(code, run_globals) File "I:\xClients\WeasyPrint\weasyprint\__main__.py", line 248, in main() File "I:\xClients\WeasyPrint\weasyprint\__main__.py", line 239, in main main_doc = getattr(html, 'render')(**kwargsRender) File "I:\xClients\WeasyPrint\weasyprint\__init__.py", line 174, in render optimize_images, font_config, counter_style, image_cache) File "I:\xClients\WeasyPrint\weasyprint\document.py", line 401, in _render [Page(page_box, enable_hinting) for page_box in page_boxes], File "I:\xClients\WeasyPrint\weasyprint\document.py", line 401, in [Page(page_box, enable_hinting) for page_box in page_boxes], File "I:\xClients\WeasyPrint\weasyprint\layout\__init__.py", line 123, in layout_document pages = list(make_all_pages(context, root_box, html, pages)) File "I:\xClients\WeasyPrint\weasyprint\layout\pages.py", line 800, in make_all_pages page, resume_at = remake_page(i, context, root_box, html) File "I:\xClients\WeasyPrint\weasyprint\layout\pages.py", line 739, in remake_page page_number, page_state) File "I:\xClients\WeasyPrint\weasyprint\layout\pages.py", line 550, in make_page positioned_boxes, adjoining_margins) File "I:\xClients\WeasyPrint\weasyprint\layout\blocks.py", line 60, in block_level_layout page_is_empty, absolute_boxes, fixed_boxes, adjoining_margins) File "I:\xClients\WeasyPrint\weasyprint\layout\blocks.py", line 74, in block_level_layout_switch page_is_empty, absolute_boxes, fixed_boxes, adjoining_margins) File "I:\xClients\WeasyPrint\weasyprint\layout\blocks.py", line 127, in block_box_layout absolute_boxes, fixed_boxes, adjoining_margins) File "I:\xClients\WeasyPrint\weasyprint\layout\blocks.py", line 508, in block_container_layout absolute_boxes, fixed_boxes, adjoining_margins) File "I:\xClients\WeasyPrint\weasyprint\layout\blocks.py", line 60, in block_level_layout page_is_empty, absolute_boxes, fixed_boxes, adjoining_margins) File "I:\xClients\WeasyPrint\weasyprint\layout\blocks.py", line 74, in block_level_layout_switch page_is_empty, absolute_boxes, fixed_boxes, adjoining_margins) File "I:\xClients\WeasyPrint\weasyprint\layout\blocks.py", line 127, in block_box_layout absolute_boxes, fixed_boxes, adjoining_margins) File "I:\xClients\WeasyPrint\weasyprint\layout\blocks.py", line 508, in block_container_layout absolute_boxes, fixed_boxes, adjoining_margins) File "I:\xClients\WeasyPrint\weasyprint\layout\blocks.py", line 60, in block_level_layout page_is_empty, absolute_boxes, fixed_boxes, adjoining_margins) File "I:\xClients\WeasyPrint\weasyprint\layout\blocks.py", line 74, in block_level_layout_switch page_is_empty, absolute_boxes, fixed_boxes, adjoining_margins) File "I:\xClients\WeasyPrint\weasyprint\layout\blocks.py", line 127, in block_box_layout absolute_boxes, fixed_boxes, adjoining_margins) File "I:\xClients\WeasyPrint\weasyprint\layout\blocks.py", line 508, in block_container_layout absolute_boxes, fixed_boxes, adjoining_margins) File "I:\xClients\WeasyPrint\weasyprint\layout\blocks.py", line 60, in block_level_layout page_is_empty, absolute_boxes, fixed_boxes, adjoining_margins) File "I:\xClients\WeasyPrint\weasyprint\layout\blocks.py", line 74, in block_level_layout_switch page_is_empty, absolute_boxes, fixed_boxes, adjoining_margins) File "I:\xClients\WeasyPrint\weasyprint\layout\blocks.py", line 121, in block_box_layout context, box, (containing_block.width, containing_block.height)) File "I:\xClients\WeasyPrint\weasyprint\layout\tables.py", line 739, in table_wrapper_width auto_table_layout(context, wrapper, containing_block) File "I:\xClients\WeasyPrint\weasyprint\layout\tables.py", line 709, in auto_table_layout (assignable_width - sum(lower_guess)) / sum(added_widths)) ZeroDivisionError: float division by zero ```

which I boiled down to the following html:

<html lang="de">
    <body>
        <section>
            <h3>AAAAAAAAAAA</h3>
            <table>
                <tr>
                    <th rowspan="2">Ertragslage</th>
                    <th rowspan="2">2019</th>
                    <th colspan="2">Veränderung</th>
                </tr>
                <tr>
                    <th>Absolut</th>
                    <th>in %</th>
                </tr>
            </table>
        </section>
        <section>
            <h3>Abschlussprüfer</h3>
        </section>
    </body>
</html>

I hope the error is reproducible on your side, and does not depend on system fonts and the like.

The example is for sure not minimal yet, but any further changes I tried made the crash disappear. Including:

Should the division maybe just be guarded by a check if the added_widths are > 0?

Thanks for looking into this!

Johannes

liZe commented 4 years ago

Hello!

I hope the error is reproducible on your side, and does not depend on system fonts and the like.

I can’t reproduce, so I think that it relies on fonts. Could you tell me which font is used, or attach a PDF of a similar working example?

liZe commented 3 years ago

@JohannesMunk Can I close this issue?

JohannesMunk commented 3 years ago

Well, I added the following patch to tables.py:

diff -r 92bd319015e2 -r 179a3a95e21e weasyprint/layout/tables.py
--- a/weasyprint/layout/tables.py   Wed Aug 19 12:45:48 2020 +0200
+++ b/weasyprint/layout/tables.py   Wed Aug 19 12:45:59 2020 +0200
@@ -705,8 +705,12 @@
         else:
             added_widths = [
                 upper_guess[i] - lower_guess[i] for i in range(len(grid))]
+            added_widths_sum = sum(added_widths)
+            if added_widths_sum > 0:
             available_ratio = (
-                (assignable_width - sum(lower_guess)) / sum(added_widths))
+                    (assignable_width - sum(lower_guess)) / added_widths_sum)
+            else:
+                available_ratio = 0
             table.column_widths = [
                 lower_guess[i] + added_widths[i] * available_ratio
                 for i in range(len(grid))]

I assume that there could be numerous reasons, why the added_withs might be zero.. so I didnt track this any further. If needbe I can provide a working PDF of output that fails otherwise next week.

liZe commented 3 years ago

If needbe I can provide a working PDF of output that fails otherwise next week.

I’d love that :smile:. If you could use a specific font, that would be very helpful.

liZe commented 3 years ago

Closing, because it’s really hard to reproduce (and fix) without fonts, and a lots of things changed lately about text rendering. If anyone meets this bug with 53.0+, feel free to reopen!

Arrendify commented 1 year ago

Hello, I have the same problem, I reproduce the problem with the width of a column, that is, if I put rent amount, the error appears, but if I only write rent, the error disappears, apparently it does not adapt well to the text, my html is without problems. I hope you can help me solve it, I'm using the most recent version I think it's 59 because I really needed to put "rent amount"

liZe commented 1 year ago

@Arrendify Could you please provide a sample (HTML + CSS) that reproduces the problem?

Arrendify commented 1 year ago

HTML.

<tr>
        <td style="border-top: 1px solid #000000; border-left: 1px solid #000000; border-bottom: 1px solid #000000; border-right: 1px solid #000000;" class="table_headers2"  colspan=2>DESCRIPCIÓN</td>
        <td style="border-top: 1px solid #000000; border-bottom: 1px solid #000000; border-right: 1px solid #000000;" class="table_headers2">MONTO - RENTA</td>
        <td style="border-top: 1px solid #000000; border-bottom: 1px solid #000000; border-right: 1px solid #000000;" class="table_headers2">AÑOS</td>
        <td style="border-top: 1px solid #000000; border-bottom: 1px solid #000000; border-right: 1px solid #000000;" class="table_headers2">COBERTURAS</td>
        <td style="border-top: 1px solid #000000; border-bottom: 1px solid #000000; border-right: 1px solid #000000;" class="table_headers2">TOTAL</td>
    </tr>

CSS

    body,div,table,thead,tbody,tfoot,tr,th,td,p { 
            font-family:"Trebuchet MS"; 
            font-size:10px}
        a.comment-indicator:hover + comment { 
            background:#ffd; 
            position:absolute; 
            display:block; 
            border:1px solid black; 
            padding:0.5em;  } 
        a.comment-indicator { 
            background:red; 
            display:inline-block; 
            border:1px solid black; 
            width:0.5em; 
            height:0.5em;  } 
        comment { display:none;  } 
        col.fondo {
            background-color: lightblue;
          }
          .table_headers1{
            align:left; 
            vertical-align: bottom; 
            background-color:#7860B4; 
            height:17; 
            color:#FFFFFF; 
            font-weight: bold; 
            font-family: Arial;
            font-size: 11px;
          }
          .table_headers2{
            align:center; 
            text-align: center;
            vertical-align: middle; 
            background-color:#7860B4; 
            height:17; 
            color:#FFFFFF; 
            font-weight: bold; 
            font-family: Arial;
          }
          .impar{
            {% comment %} background-color:#d9d5db; {% endcomment %}
            background-color:#F2F2F2;
          }
          @page {
            size: A4;
            margin: 0.1cm 1 1 0.1cm
        }

when I remove the - from "MONTO - RENTA" the error occurs, if I leave the -, there is no problem

liZe commented 1 year ago

I’m sorry, but I can’t reproduce with your sample. Could you please share the stacktrace you get?

Arrendify commented 1 year ago

sorry for the delay, Sure, here it is. Environment:

Request Method: GET Request URL: http://192.168.2.24:8001/pdf_descarga/

Django Version: 3.2.6 Python Version: 3.10.1 Installed Applications: ['django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'apps.home', 'apps.api', 'rest_framework', 'rest_framework.authtoken', 'corsheaders', 'rest_auth', 'storages'] Installed Middleware: ['django.middleware.security.SecurityMiddleware', 'whitenoise.middleware.WhiteNoiseMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', 'corsheaders.middleware.CorsMiddleware']

Traceback (most recent call last): File "C:\Users\me\Downloads\Arrendy\Api\API\Back-end\venv\lib\site-packages\django\core\handlers\exception.py", line 47, in inner response = get_response(request) File "C:\Users\me\Downloads\Arrendy\Api\API\Back-end\venv\lib\site-packages\django\core\handlers\base.py", line 181, in _get_response response = wrapped_callback(request, *callback_args, callback_kwargs) File "C:\Users\me\Downloads\Arrendy\Api\API\Back-end - wesy\apps\home\views.py", line 83, in pdf_descarga pdf_file = HTML(string=html_string).write_pdf() File "C:\Users\me\Downloads\Arrendy\Api\API\Back-end\venv\lib\site-packages\weasyprint__init__.py", line 252, in write_pdf self.render(font_config, counter_style, options) File "C:\Users\me\Downloads\Arrendy\Api\API\Back-end\venv\lib\site-packages\weasyprint__init.py", line 209, in render return Document._render(self, font_config, counter_style, options) File "C:\Users\me\Downloads\Arrendy\Api\API\Back-end\venv\lib\site-packages\weasyprint\document.py", line 270, in _render [Page(page_box) for page_box in page_boxes], File "C:\Users\me\Downloads\Arrendy\Api\API\Back-end\venv\lib\site-packages\weasyprint\document.py", line 270, in [Page(page_box) for page_box in page_boxes], File "C:\Users\me\Downloads\Arrendy\Api\API\Back-end\venv\lib\site-packages\weasyprint\layout\init__.py", line 130, in layout_document pages = list(make_all_pages(context, root_box, html, pages)) File "C:\Users\me\Downloads\Arrendy\Api\API\Back-end\venv\lib\site-packages\weasyprint\layout\page.py", line 857, in make_all_pages page, resume_at = remake_page(i, context, root_box, html) File "C:\Users\me\Downloads\Arrendy\Api\API\Back-end\venv\lib\site-packages\weasyprint\layout\page.py", line 793, in remake_page page, resume_at, next_page = make_page( File "C:\Users\me\Downloads\Arrendy\Api\API\Back-end\venv\lib\site-packages\weasyprint\layout\page.py", line 591, in make_page root_box, resume_at, nextpage, , , = block_level_layout( File "C:\Users\me\Downloads\Arrendy\Api\API\Back-end\venv\lib\site-packages\weasyprint\layout\block.py", line 59, in block_level_layout return block_level_layout_switch( File "C:\Users\GM Integraciones\Downloads\Arrendy\Api\API\Back-end\venv\lib\site-packages\weasyprint\layout\block.py", line 75, in block_level_layout_switch return block_box_layout( File "C:\Users\me\Downloads\Arrendy\Api\API\Back-end\venv\lib\site-packages\weasyprint\layout\block.py", line 120, in block_box_layout result = block_container_layout( File "C:\Users\me\Downloads\Arrendy\Api\API\Back-end\venv\lib\site-packages\weasyprint\layout\block.py", line 686, in block_container_layout next_page, new_children, new_max_lines) = _in_flow_layout( File "C:\Users\me\Downloads\Arrendy\Api\API\Back-end\venv\lib\site-packages\weasyprint\layout\block.py", line 482, in _in_flow_layout collapsing_through, max_lines) = block_level_layout( File "C:\Users\me\Downloads\Arrendy\Api\API\Back-end\venv\lib\site-packages\weasyprint\layout\block.py", line 59, in block_level_layout return block_level_layout_switch( File "C:\Users\GM Integraciones\Downloads\Arrendy\Api\API\Back-end\venv\lib\site-packages\weasyprint\layout\block.py", line 75, in block_level_layout_switch return block_box_layout( File "C:\Users\me\Downloads\Arrendy\Api\API\Back-end\venv\lib\site-packages\weasyprint\layout\block.py", line 120, in block_box_layout result = block_container_layout( File "C:\Users\me\Downloads\Arrendy\Api\API\Back-end\venv\lib\site-packages\weasyprint\layout\block.py", line 686, in block_container_layout next_page, new_children, new_max_lines) = _in_flow_layout( File "C:\Users\me\Downloads\Arrendy\Api\API\Back-end\venv\lib\site-packages\weasyprint\layout\block.py", line 482, in _in_flow_layout collapsing_through, max_lines) = block_level_layout( File "C:\Users\me\Downloads\Arrendy\Api\API\Back-end\venv\lib\site-packages\weasyprint\layout\block.py", line 59, in block_level_layout return block_level_layout_switch( File "C:\Users\me\Downloads\Arrendy\Api\API\Back-end\venv\lib\site-packages\weasyprint\layout\block.py", line 75, in block_level_layout_switch return block_box_layout( File "C:\Users\me\Downloads\Arrendy\Api\API\Back-end\venv\lib\site-packages\weasyprint\layout\block.py", line 116, in block_box_layout table_wrapper_width( File "C:\Users\me\Downloads\Arrendy\Api\API\Back-end\venv\lib\site-packages\weasyprint\layout\table.py", line 812, in table_wrapper_width auto_table_layout(context, wrapper, containing_block) File "C:\Users\me\Downloads\Arrendy\Api\API\Back-end\venv\lib\site-packages\weasyprint\layout\table.py", line 782, in auto_table_layout (assignable_width - sum(lower_guess)) / sum(added_widths))

Exception Type: ZeroDivisionError at /pdf_descarga/ Exception Value: float division by zero

Arrendify commented 1 year ago

sorry for the delay, Sure, here it is. Environment:

Request Method: GET Request URL: http://192.168.2.24:8001/pdf_descarga/

Django Version: 3.2.6 Python Version: 3.10.1 Installed Applications: ['django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'apps.home', 'apps.api', 'rest_framework', 'rest_framework.authtoken', 'corsheaders', 'rest_auth', 'storages'] Installed Middleware: ['django.middleware.security.SecurityMiddleware', 'whitenoise.middleware.WhiteNoiseMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', 'corsheaders.middleware.CorsMiddleware']

Traceback (most recent call last): File "C:\Users\me\Downloads\Arrendy\Api\API\Back-end\venv\lib\site-packages\django\core\handlers\exception.py", line 47, in inner response = get_response(request) File "C:\Users\me\Downloads\Arrendy\Api\API\Back-end\venv\lib\site-packages\django\core\handlers\base.py", line 181, in _get_response response = wrapped_callback(request, *callback_args, callback_kwargs) File "C:\Users\me\Downloads\Arrendy\Api\API\Back-end - wesy\apps\home\views.py", line 83, in pdf_descarga pdf_file = HTML(string=html_string).write_pdf() File "C:\Users\me\Downloads\Arrendy\Api\API\Back-end\venv\lib\site-packages\weasyprint__init__.py", line 252, in write_pdf self.render(font_config, counter_style, options) File "C:\Users\me\Downloads\Arrendy\Api\API\Back-end\venv\lib\site-packages\weasyprint__init.py", line 209, in render return Document._render(self, font_config, counter_style, options) File "C:\Users\me\Downloads\Arrendy\Api\API\Back-end\venv\lib\site-packages\weasyprint\document.py", line 270, in _render [Page(page_box) for page_box in page_boxes], File "C:\Users\me\Downloads\Arrendy\Api\API\Back-end\venv\lib\site-packages\weasyprint\document.py", line 270, in [Page(page_box) for page_box in page_boxes], File "C:\Users\me\Downloads\Arrendy\Api\API\Back-end\venv\lib\site-packages\weasyprint\layout\init__.py", line 130, in layout_document pages = list(make_all_pages(context, root_box, html, pages)) File "C:\Users\me\Downloads\Arrendy\Api\API\Back-end\venv\lib\site-packages\weasyprint\layout\page.py", line 857, in make_all_pages page, resume_at = remake_page(i, context, root_box, html) File "C:\Users\me\Downloads\Arrendy\Api\API\Back-end\venv\lib\site-packages\weasyprint\layout\page.py", line 793, in remake_page page, resume_at, next_page = make_page( File "C:\Users\me\Downloads\Arrendy\Api\API\Back-end\venv\lib\site-packages\weasyprint\layout\page.py", line 591, in make_page root_box, resume_at, nextpage, , , = block_level_layout( File "C:\Users\me\Downloads\Arrendy\Api\API\Back-end\venv\lib\site-packages\weasyprint\layout\block.py", line 59, in block_level_layout return block_level_layout_switch( File "C:\Users\GM Integraciones\Downloads\Arrendy\Api\API\Back-end\venv\lib\site-packages\weasyprint\layout\block.py", line 75, in block_level_layout_switch return block_box_layout( File "C:\Users\me\Downloads\Arrendy\Api\API\Back-end\venv\lib\site-packages\weasyprint\layout\block.py", line 120, in block_box_layout result = block_container_layout( File "C:\Users\me\Downloads\Arrendy\Api\API\Back-end\venv\lib\site-packages\weasyprint\layout\block.py", line 686, in block_container_layout next_page, new_children, new_max_lines) = _in_flow_layout( File "C:\Users\me\Downloads\Arrendy\Api\API\Back-end\venv\lib\site-packages\weasyprint\layout\block.py", line 482, in _in_flow_layout collapsing_through, max_lines) = block_level_layout( File "C:\Users\me\Downloads\Arrendy\Api\API\Back-end\venv\lib\site-packages\weasyprint\layout\block.py", line 59, in block_level_layout return block_level_layout_switch( File "C:\Users\GM Integraciones\Downloads\Arrendy\Api\API\Back-end\venv\lib\site-packages\weasyprint\layout\block.py", line 75, in block_level_layout_switch return block_box_layout( File "C:\Users\me\Downloads\Arrendy\Api\API\Back-end\venv\lib\site-packages\weasyprint\layout\block.py", line 120, in block_box_layout result = block_container_layout( File "C:\Users\me\Downloads\Arrendy\Api\API\Back-end\venv\lib\site-packages\weasyprint\layout\block.py", line 686, in block_container_layout next_page, new_children, new_max_lines) = _in_flow_layout( File "C:\Users\me\Downloads\Arrendy\Api\API\Back-end\venv\lib\site-packages\weasyprint\layout\block.py", line 482, in _in_flow_layout collapsing_through, max_lines) = block_level_layout( File "C:\Users\me\Downloads\Arrendy\Api\API\Back-end\venv\lib\site-packages\weasyprint\layout\block.py", line 59, in block_level_layout return block_level_layout_switch( File "C:\Users\me\Downloads\Arrendy\Api\API\Back-end\venv\lib\site-packages\weasyprint\layout\block.py", line 75, in block_level_layout_switch return block_box_layout( File "C:\Users\me\Downloads\Arrendy\Api\API\Back-end\venv\lib\site-packages\weasyprint\layout\block.py", line 116, in block_box_layout table_wrapper_width( File "C:\Users\me\Downloads\Arrendy\Api\API\Back-end\venv\lib\site-packages\weasyprint\layout\table.py", line 812, in table_wrapper_width auto_table_layout(context, wrapper, containing_block) File "C:\Users\me\Downloads\Arrendy\Api\API\Back-end\venv\lib\site-packages\weasyprint\layout\table.py", line 782, in auto_table_layout (assignable_width - sum(lower_guess)) / sum(added_widths))

Exception Type: ZeroDivisionError at /pdf_descarga/ Exception Value: float division by zero

On Thu, Jun 29, 2023 at 2:29 PM Guillaume Ayoub @.***> wrote:

I’m sorry, but I can’t reproduce with your sample. Could you please share the stacktrace you get?

— Reply to this email directly, view it on GitHub https://github.com/Kozea/WeasyPrint/issues/1190#issuecomment-1613771214, or unsubscribe https://github.com/notifications/unsubscribe-auth/A2VX635UAN4U7AFTEFDBDKDXNXQS3ANCNFSM4P7J3YKQ . You are receiving this because you were mentioned.Message ID: @.***>