Package: src:pypdf
Version: 5.4.0-1
Severity: serious
Tags: ftbfs forky sid

Dear maintainer:

During a rebuild of all packages in unstable, this package failed to build.

Below you will find the last part of the build log (probably the most
relevant part, but not necessarily). If required, the full build log
is available here:

https://people.debian.org/~sanvila/build-logs/202601/

About the archive rebuild: The build was made on virtual machines from AWS,
using sbuild and a reduced chroot with only build-essential packages.

If you cannot reproduce the bug please contact me privately, as I
am willing to provide ssh access to a virtual machine where the bug is
fully reproducible.

If this is really a bug in one of the build-depends, please use
reassign and add an affects on src:pypdf, so that this is still
visible in the BTS web page for this package.

Thanks.

--------------------------------------------------------------------------------
[...]
 debian/rules clean
dh clean --buildsystem=pybuild
   dh_auto_clean -O--buildsystem=pybuild
   dh_autoreconf_clean -O--buildsystem=pybuild
   dh_clean -O--buildsystem=pybuild
 debian/rules binary
dh binary --buildsystem=pybuild
   dh_update_autotools_config -O--buildsystem=pybuild
   dh_autoreconf -O--buildsystem=pybuild
   dh_auto_configure -O--buildsystem=pybuild
   dh_auto_build -O--buildsystem=pybuild
I: pybuild plugin_pyproject:139: Building wheel for python3.14 with "build" 
module
I: pybuild base:384: python3.14 -m build --skip-dependency-check --no-isolation 
--wheel --outdir /<<PKGBUILDDIR>>/.pybuild/cpython3_3.14  
* Building wheel...
Successfully built pypdf-5.4.0-py3-none-any.whl

[... snipped ...]

=================================== FAILURES ===================================
______________________________ test_replace_image ______________________________

tmp_path = PosixPath('/tmp/pytest-of-sbuild/pytest-1/test_replace_image0')

    def test_replace_image(tmp_path):
        writer = PdfWriter(clone_from=RESOURCE_ROOT / 
"labeled-edges-center-image.pdf")
        reader = PdfReader(RESOURCE_ROOT / "jpeg.pdf")
        img = reader.pages[0].images[0].image
        if int(pil_version.split(".")[0]) < 9:
            img = img.convert("RGB")
        writer.pages[0].images[0].replace(img)
        b = BytesIO()
        writer.write(b)
        reader2 = PdfReader(b)
        if int(pil_version.split(".")[0]) >= 9:
            assert reader2.pages[0].images[0].image.mode == "RGBA"
        # very simple image distance evaluation
        diff = ImageChops.difference(reader2.pages[0].images[0].image, img)
>       d = sum(diff.convert("L").getdata()) / (diff.size[0] * diff.size[1])
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^

tests/test_workflows.py:969: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
/usr/lib/python3/dist-packages/PIL/Image.py:1438: in getdata
    deprecate("Image.Image.getdata", 14, "get_flattened_data")
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

deprecated = 'Image.Image.getdata', when = 14
replacement = 'get_flattened_data'

    def deprecate(
        deprecated: str,
        when: int | None,
        replacement: str | None = None,
        *,
        action: str | None = None,
        plural: bool = False,
        stacklevel: int = 3,
    ) -> None:
        """
        Deprecations helper.
    
        :param deprecated: Name of thing to be deprecated.
        :param when: Pillow major version to be removed in.
        :param replacement: Name of replacement.
        :param action: Instead of "replacement", give a custom call to action
            e.g. "Upgrade to new thing".
        :param plural: if the deprecated thing is plural, needing "are" instead 
of "is".
    
        Usually of the form:
    
            "[deprecated] is deprecated and will be removed in Pillow [when] 
(yyyy-mm-dd).
            Use [replacement] instead."
    
        You can leave out the replacement sentence:
    
            "[deprecated] is deprecated and will be removed in Pillow [when] 
(yyyy-mm-dd)"
    
        Or with another call to action:
    
            "[deprecated] is deprecated and will be removed in Pillow [when] 
(yyyy-mm-dd).
            [action]."
        """
    
        is_ = "are" if plural else "is"
    
        if when is None:
            removed = "a future version"
        elif when <= int(__version__.split(".")[0]):
            msg = f"{deprecated} {is_} deprecated and should be removed."
            raise RuntimeError(msg)
        elif when == 13:
            removed = "Pillow 13 (2026-10-15)"
        elif when == 14:
            removed = "Pillow 14 (2027-10-15)"
        else:
            msg = f"Unknown removal version: {when}. Update {__name__}?"
            raise ValueError(msg)
    
        if replacement and action:
            msg = "Use only one of 'replacement' and 'action'"
            raise ValueError(msg)
    
        if replacement:
            action = f". Use {replacement} instead."
        elif action:
            action = f". {action.rstrip('.')}."
        else:
            action = ""
    
>       warnings.warn(
            f"{deprecated} {is_} deprecated and will be removed in 
{removed}{action}",
            DeprecationWarning,
            stacklevel=stacklevel,
        )
E       DeprecationWarning: Image.Image.getdata is deprecated and will be 
removed in Pillow 14 (2027-10-15). Use get_flattened_data instead.

/usr/lib/python3/dist-packages/PIL/_deprecate.py:68: DeprecationWarning
_______________________ test_handle_flate__image_mode_1 ________________________

caplog = <_pytest.logging.LogCaptureFixture object at 0x7fa99d4b7930>

    def test_handle_flate__image_mode_1(caplog):
        data = b"\x00\xe0\x00"
        lookup = DecodedStreamObject()
        expected_data = [
            (66, 66, 66),
            (66, 66, 66),
            (66, 66, 66),
            (0, 19, 55),
            (0, 19, 55),
            (0, 19, 55),
            (66, 66, 66),
            (66, 66, 66),
            (66, 66, 66),
        ]
    
        # No trailing data.
        lookup.set_data(b"\x42\x42\x42\x00\x13\x37")
        result = _handle_flate(
            size=(3, 3),
            data=data,
            mode="1",
            color_space=ArrayObject(
                [NameObject("/Indexed"), NameObject("/DeviceRGB"), 
NumberObject(1), lookup]
            ),
            colors=2,
            obj_as_text="dummy",
        )
>       assert expected_data == list(result[0].getdata())
                                     ^^^^^^^^^^^^^^^^^^^

tests/test_xobject_image_helpers.py:59: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
/usr/lib/python3/dist-packages/PIL/Image.py:1438: in getdata
    deprecate("Image.Image.getdata", 14, "get_flattened_data")
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

deprecated = 'Image.Image.getdata', when = 14
replacement = 'get_flattened_data'

    def deprecate(
        deprecated: str,
        when: int | None,
        replacement: str | None = None,
        *,
        action: str | None = None,
        plural: bool = False,
        stacklevel: int = 3,
    ) -> None:
        """
        Deprecations helper.
    
        :param deprecated: Name of thing to be deprecated.
        :param when: Pillow major version to be removed in.
        :param replacement: Name of replacement.
        :param action: Instead of "replacement", give a custom call to action
            e.g. "Upgrade to new thing".
        :param plural: if the deprecated thing is plural, needing "are" instead 
of "is".
    
        Usually of the form:
    
            "[deprecated] is deprecated and will be removed in Pillow [when] 
(yyyy-mm-dd).
            Use [replacement] instead."
    
        You can leave out the replacement sentence:
    
            "[deprecated] is deprecated and will be removed in Pillow [when] 
(yyyy-mm-dd)"
    
        Or with another call to action:
    
            "[deprecated] is deprecated and will be removed in Pillow [when] 
(yyyy-mm-dd).
            [action]."
        """
    
        is_ = "are" if plural else "is"
    
        if when is None:
            removed = "a future version"
        elif when <= int(__version__.split(".")[0]):
            msg = f"{deprecated} {is_} deprecated and should be removed."
            raise RuntimeError(msg)
        elif when == 13:
            removed = "Pillow 13 (2026-10-15)"
        elif when == 14:
            removed = "Pillow 14 (2027-10-15)"
        else:
            msg = f"Unknown removal version: {when}. Update {__name__}?"
            raise ValueError(msg)
    
        if replacement and action:
            msg = "Use only one of 'replacement' and 'action'"
            raise ValueError(msg)
    
        if replacement:
            action = f". Use {replacement} instead."
        elif action:
            action = f". {action.rstrip('.')}."
        else:
            action = ""
    
>       warnings.warn(
            f"{deprecated} {is_} deprecated and will be removed in 
{removed}{action}",
            DeprecationWarning,
            stacklevel=stacklevel,
        )
E       DeprecationWarning: Image.Image.getdata is deprecated and will be 
removed in Pillow 14 (2027-10-15). Use get_flattened_data instead.

/usr/lib/python3/dist-packages/PIL/_deprecate.py:68: DeprecationWarning

---------- coverage: platform linux, python 3.13.11-final-0 ----------
Name                                                         Stmts   Miss 
Branch BrPart  Cover   Missing
--------------------------------------------------------------------------------------------------------
pypdf/__init__.py                                               18      2      
0      0    89%   26-27
pypdf/_cmap.py                                                 279     46    
124     14    82%   138->137, 150, 165-171, 175-180, 191->195, 193-194, 256, 
275, 310-311, 326-340, 348-359, 383->387, 418, 427-429, 442-446, 517, 527, 
534-541
pypdf/_codecs/__init__.py                                       32      0      
6      0   100%
pypdf/_codecs/_codecs.py                                       129      2     
40      0    99%   170-171
pypdf/_codecs/adobe_glyphs.py                                    6      0      
2      0   100%
pypdf/_codecs/pdfdoc.py                                          2      0      
0      0   100%
pypdf/_codecs/std.py                                             1      0      
0      0   100%
pypdf/_codecs/symbol.py                                          2      0      
0      0   100%
pypdf/_codecs/zapfding.py                                        2      0      
0      0   100%
pypdf/_crypt_providers/__init__.py                              11      4      
0      0    64%   42-44, 61-62
pypdf/_crypt_providers/_base.py                                  3      0      
0      0   100%
pypdf/_crypt_providers/_cryptography.py                         61     59      
4      0     3%   31-118
pypdf/_crypt_providers/_fallback.py                             43     25      
4      0    38%   39-43, 46-55, 58, 63, 66, 69, 73, 77, 81, 85, 89, 93
pypdf/_crypt_providers/_pycryptodome.py                         43      0      
4      0   100%
pypdf/_doc_common.py                                           635    118    
286     34    77%   324-334, 402, 410, 412, 441-447, 449->458, 484, 487->490, 
505, 508-509, 515, 517->501, 520-529, 573, 587, 623, 633->639, 649-652, 
682->666, 690, 717, 729->728, 731, 759-800, 862, 865->867, 875->879, 882->885, 
907-911, 1019-1026, 1029->1045, 1048-1049, 1077, 1173, 1181->1183, 1184->1179, 
1188-1189, 1192->exit, 1199->1203, 1224-1247, 1319-1332, 1361
pypdf/_encryption.py                                           385      9    
106      9    96%   73-74, 199, 848, 946, 955-956, 1014, 1023, 1111->1113, 
1113->1115, 1115->1118
pypdf/_merger.py                                                 4      0      
0      0   100%
pypdf/_page.py                                                1016    157    
436     47    83%   102-104, 114->118, 119, 378, 390, 392, 394, 441, 444, 
459-462, 466, 470, 472, 476-477, 601->603, 605, 610->612, 612->614, 623, 627, 
637->639, 640, 642, 649, 653, 668-669, 744-748, 755, 792, 794, 822->790, 
995-1000, 1035, 1083-1091, 1167-1168, 1171-1172, 1178->1175, 1243, 1307, 
1343-1344, 1372->1374, 1422-1423, 1455->1457, 1597-1636, 1647, 1659-1661, 
1672->exit, 1696, 1701-1702, 1755-1758, 1848, 1852-1855, 1857->1860, 
1873->1881, 1875-1876, 1954-1955, 2001-2008, 2011-2012, 2088->2149, 2104, 2109, 
2121-2139, 2153, 2245, 2413, 2533-2577, 2651-2652
pypdf/_page_labels.py                                           98     42     
48      8    49%   92->exit, 139-145, 157-159, 176, 179, 180->207, 184->207, 
188-201, 227-238, 257-265, 282-289
pypdf/_protocols.py                                             39      0      
0      0   100%
pypdf/_reader.py                                               680    142    
286     38    78%   219, 223->232, 226-227, 233-242, 259, 352, 361-364, 407, 
416-441, 444-445, 453, 462, 481-484, 490-511, 547, 558-559, 565-568, 625-626, 
687-688, 691, 726, 733, 753-759, 766, 775-776, 792-815, 861, 868-869, 875-878, 
895-898, 903, 916-917, 943-965, 984, 995-997, 1021, 1026, 1036, 1039, 
1064-1086, 1128-1129, 1159, 1265->1269, 1269->1273
pypdf/_text_extraction/__init__.py                             110     15     
54      1    83%   53-65, 129->132, 184-188
pypdf/_text_extraction/_layout_mode/__init__.py                  3      0      
0      0   100%
pypdf/_text_extraction/_layout_mode/_fixed_width_page.py       175     15     
76     11    89%   96-97, 103, 112, 114, 118->122, 133, 151->153, 236-239, 
285-292, 297-298, 306, 389->393
pypdf/_text_extraction/_layout_mode/_font.py                    55     23     
22      3    56%   44, 50, 63-127
pypdf/_text_extraction/_layout_mode/_font_widths.py              7      0      
0      0   100%
pypdf/_text_extraction/_layout_mode/_text_state_manager.py      84      2     
14      0    98%   106-107
pypdf/_text_extraction/_layout_mode/_text_state_params.py       52      5      
6      2    88%   58-62, 66-67, 129
pypdf/_utils.py                                                230      8     
90      5    95%   57, 62, 369-371, 416, 452->451, 578, 585
pypdf/_version.py                                                1      0      
0      0   100%
pypdf/_writer.py                                              1369    257    
646     69    79%   217->219, 220, 291, 353, 358-364, 545-549, 705->exit, 952, 
959, 1096, 1147-1180, 1197->1195, 1244->1258, 1395, 1458->1464, 1492, 1495, 
1630-1686, 1835, 1844->1847, 1856-1868, 1906, 1911, 1916, 1917->1922, 
1920-1921, 1923-1927, 2022-2023, 2037->2039, 2041, 2058-2060, 2064, 2066, 2070, 
2169-2170, 2204, 2431, 2439, 2468, 2518, 2523, 2541-2548, 2604->2606, 
2608-2610, 2677, 2687->2692, 2695, 2730, 2734-2745, 2746->exit, 2777->2786, 
2796, 2805->2802, 2807-2812, 2817->exit, 2838-2883, 2904-2905, 2909-2916, 2925, 
2928-2929, 2932-2933, 2944, 2958-2969, 2973, 2976->2947, 2979-2986, 3009, 3012, 
3025, 3028, 3033->3038, 3045->3051, 3049, 3051->3058, 3070, 3091->exit, 
3133-3146, 3184-3197, 3232-3262, 3285->3289, 3289->3293, 3327->3329, 3336, 
3342->3344, 3344->3346
pypdf/_xobj_image_helpers.py                                   186     95     
96     20    44%   24, 29-30, 55, 62-104, 126-140, 155-159, 183-184, 186-187, 
190->192, 193, 195, 216-227, 238-260, 265-267, 269-270, 288->291, 292, 297-300, 
307, 334, 339, 362
pypdf/annotations/__init__.py                                    4      0      
0      0   100%
pypdf/annotations/_base.py                                      15      0      
0      0   100%
pypdf/annotations/_markup_annotations.py                       110      5     
36      2    95%   24, 223-224, 275-276, 287->exit
pypdf/annotations/_non_markup_annotations.py                    37      0     
14      1    98%   96->exit
pypdf/constants.py                                             423      0     
14      0   100%
pypdf/errors.py                                                 13      0      
0      0   100%
pypdf/filters.py                                               347    100    
140     25    68%   89-98, 132-133, 162-168, 182, 192, 195-196, 201-231, 
287->289, 349-372, 381, 384, 404, 548->550, 550->553, 636, 651, 655, 659, 
661-662, 667-668, 712, 718, 720, 722, 728-729, 745, 751, 773-782, 791, 798, 
805, 834-835
pypdf/generic/__init__.py                                       15      0      
0      0   100%
pypdf/generic/_base.py                                         383     13     
92      3    97%   40, 265, 309, 352-354, 377, 386-387, 400, 664-669
pypdf/generic/_data_structures.py                              950     85    
370     37    90%   98, 257-259, 385->392, 398, 501->504, 539-540, 552, 568, 
584, 586-593, 597-603, 609-615, 624, 628, 645, 692, 725->exit, 768, 770, 777, 
783, 787-797, 827->exit, 1047-1049, 1081-1092, 1188, 1194->1181, 1252->1257, 
1349, 1353, 1355, 1359, 1363, 1388-1391, 1444->exit, 1452, 1530-1537, 1648, 
1650, 1652, 1670-1671, 1675-1676, 1678, 1759, 1770, 1781
pypdf/generic/_files.py                                         72     10     
22      2    83%   44, 49, 70, 80, 85, 90, 141-146, 147->exit
pypdf/generic/_fit.py                                           32      0      
0      0   100%
pypdf/generic/_image_inline.py                                 170     10     
72      6    93%   158->160, 161, 168, 171-179, 187, 234-235
pypdf/generic/_outline.py                                       20      0      
2      0   100%
pypdf/generic/_rectangle.py                                     67      1      
2      0    99%   34
pypdf/generic/_utils.py                                        127      7     
54      2    95%   101-102, 175-179
pypdf/generic/_viewerpref.py                                    72     55     
10      0    21%   43-49, 52, 55, 58, 61-65, 68, 71-79, 82, 85, 89, 92-164
pypdf/pagerange.py                                              63      0     
26      0   100%
pypdf/papersizes.py                                             16      0      
0      0   100%
pypdf/types.py                                                  17      1      
2      1    89%   10
pypdf/xmp.py                                                   214     60     
74     11    64%   114, 117-122, 134-151, 160-175, 186, 188->194, 190, 
194->196, 218-219, 232, 236->235, 239, 244->243, 248, 256->255, 375-394
--------------------------------------------------------------------------------------------------------
TOTAL                                                         8928   1373   
3280    351    82%

=========================== short test summary info ============================
FAILED tests/test_workflows.py::test_replace_image - DeprecationWarning: 
Image.Image.getdata is deprecated and will be removed in Pillow 14 
(2027-10-15). Use get_flattened_data instead.
FAILED tests/test_xobject_image_helpers.py::test_handle_flate__image_mode_1 - 
DeprecationWarning: Image.Image.getdata is deprecated and will be removed in 
Pillow 14 (2027-10-15). Use get_flattened_data instead.
========== 2 failed, 571 passed, 13 skipped, 368 deselected in 16.57s ==========
E: pybuild pybuild:483: test: plugin pyproject failed with: exit code=1: cd 
/<<PKGBUILDDIR>>/.pybuild/cpython3_3.13/build; python3.13 -m pytest --cov 
--cov-report term-missing -vv -m 'not samples and not enable_socket'
dh_auto_test: error: pybuild --test --test-pytest -i python{version} -p "3.14 
3.13" returned exit code 13
make: *** [debian/rules:7: binary] Error 25
dpkg-buildpackage: error: debian/rules binary subprocess failed with exit 
status 2
--------------------------------------------------------------------------------

Reply via email to