Kozea / WeasyPrint

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

Table overflow gets an : AttributeError: 'TableCellBox' object has no attribute 'border_top_left_radius' #2296

Open ice3 opened 1 week ago

ice3 commented 1 week ago

Hello,

As we said at the pyconfr yesterday, I fill a bug for my strange behaviour.

Context

I generate reports with overflowing table, I have a layout algorithm to split them on multiple pages, I don't use weasyprint table splitting functionnality.

I detect that the table is on multiple pages when I get this error : AttributeError: 'TableCellBox' object has no attribute 'border_top_left_radius' (stacktrace below).

By the way, I realize it's not a terrible idea as this is completely a side effect, I could just... count the number of pages in the generated PDF 🀷

Test env

I managed to create a minimal reproducible build using the project evironment :

(.venv) ➜  minimal_repro_overflow git:(main) βœ— weasyprint --version                           [4/11/24 | 11:38:12]
WeasyPrint version 60.2

I also reproduced on the latest weasyprint version

(.venv) ➜  minimal_repro_overflow git:(main) βœ— weasyprint --version                          [4/11/24 | 11:40:35]
WeasyPrint version 63.0

And it's present for a long time (at least version 53.4).

I use the CLI interface (but also meet the issue with the python api): weasyprint overflow.html overflow.pdf

Files

I reduced the issue to 3 files :

Everything can be found here : https://github.com/ice3/weasyprint-repro-attributeerror

In overflow.html, I have a table with a lot of row, adding or removing one will crash the program (data are pingu redacted)

       <tr>
        <td class="col-variant">
                nootnoot
         <br/>
         nootnoot
        </td>
        <td class="col-clinical-id">
         <div style="margin-bottom: 5px">
          <a href="nootnootnootnootnootnoot">
                nootnootnootnoot
          </a>
         </div>
         <div>
                nootnoot
         </div>
        </td>
        <td class="col-location">
                nootnootnootnootn nootnoot
        </td>
        <td class="col-indication">
                nootnootnootnoot
        </td>
        <td class="col-therapy">
                nootnootnootnootnootnoot
        </td>
        <td class="col-contact">
                nootnootnootnootnootnoot nootnootnootnootnootnoot nootnootnootnoot
        </td>
       </tr>

It loads the file main.css. In this file, removing this rule crashes or not the program :

.table-col-1-6 {
    background-color: rgba(241, 244, 255, 1);
}

Stacktrace

Traceback (most recent call last):
  File "/Users/matthieufalce/Documents/projets/pro/03_omicure/omicure_pdf_report/.venv/bin/weasyprint", line 8, in <module>
    sys.exit(main())
             ^^^^^^
  File "/Users/matthieufalce/Documents/projets/pro/03_omicure/omicure_pdf_report/.venv/lib/python3.12/site-packages/weasyprint/__main__.py", line 194, in main
    html.write_pdf(output, **options)
  File "/Users/matthieufalce/Documents/projets/pro/03_omicure/omicure_pdf_report/.venv/lib/python3.12/site-packages/weasyprint/__init__.py", line 265, in write_pdf
    self.render(font_config, counter_style, **options)
  File "/Users/matthieufalce/Documents/projets/pro/03_omicure/omicure_pdf_report/.venv/lib/python3.12/site-packages/weasyprint/__init__.py", line 222, in render
    return Document._render(self, font_config, counter_style, options)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/matthieufalce/Documents/projets/pro/03_omicure/omicure_pdf_report/.venv/lib/python3.12/site-packages/weasyprint/document.py", line 266, in _render
    [Page(page_box) for page_box in page_boxes],
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/matthieufalce/Documents/projets/pro/03_omicure/omicure_pdf_report/.venv/lib/python3.12/site-packages/weasyprint/layout/__init__.py", line 214, in layout_document
    layout_backgrounds(page, context.get_image_from_uri)
  File "/Users/matthieufalce/Documents/projets/pro/03_omicure/omicure_pdf_report/.venv/lib/python3.12/site-packages/weasyprint/layout/background.py", line 231, in layout_backgrounds
    layout_box_backgrounds(page, page, get_image_from_uri)
  File "/Users/matthieufalce/Documents/projets/pro/03_omicure/omicure_pdf_report/.venv/lib/python3.12/site-packages/weasyprint/layout/background.py", line 45, in layout_box_backgrounds
    layout_box_backgrounds(page, child, get_image_from_uri)
  File "/Users/matthieufalce/Documents/projets/pro/03_omicure/omicure_pdf_report/.venv/lib/python3.12/site-packages/weasyprint/layout/background.py", line 45, in layout_box_backgrounds
    layout_box_backgrounds(page, child, get_image_from_uri)
  File "/Users/matthieufalce/Documents/projets/pro/03_omicure/omicure_pdf_report/.venv/lib/python3.12/site-packages/weasyprint/layout/background.py", line 45, in layout_box_backgrounds
    layout_box_backgrounds(page, child, get_image_from_uri)
  [Previous line repeated 6 more times]
  File "/Users/matthieufalce/Documents/projets/pro/03_omicure/omicure_pdf_report/.venv/lib/python3.12/site-packages/weasyprint/layout/background.py", line 83, in layout_box_backgrounds
    layout_background_layer(box, page, style['image_resolution'], *layer)
  File "/Users/matthieufalce/Documents/projets/pro/03_omicure/omicure_pdf_report/.venv/lib/python3.12/site-packages/weasyprint/layout/background.py", line 129, in layout_background_layer
    clipped_boxes = [cell.rounded_border_box() for cell in cells]
                     ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/matthieufalce/Documents/projets/pro/03_omicure/omicure_pdf_report/.venv/lib/python3.12/site-packages/weasyprint/formatting_structure/boxes.py", line 269, in rounded_border_box
    return self.rounded_box(0, 0, 0, 0)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/matthieufalce/Documents/projets/pro/03_omicure/omicure_pdf_report/.venv/lib/python3.12/site-packages/weasyprint/formatting_structure/boxes.py", line 214, in rounded_box
    tlrx, tlry = self.border_top_left_radius
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'TableCellBox' object has no attribute 'border_top_left_radius'
liZe commented 2 days ago

Thanks for the report!

Here’s a small sample to reproduce (size may depend on default system font):

<style>
  @page {size: 200mm 10em}
  .col {background: red}
</style>
<table>
  <colgroup>
    <col class="col"/>
  </colgroup>
  <tbody>
    <tr><td>cell</td></tr>
    <tr><td>cell</td></tr>
  </tbody>
</table>