Your message dated Fri, 23 Jan 2026 11:45:37 +0000
with message-id <[email protected]>
and subject line Re: Bug#1125310: textual: FTBFS with rich 13.9.4-1.1
has caused the Debian Bug report #1125310,
regarding textual: FTBFS with rich 13.9.4-1.1
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact [email protected]
immediately.)


-- 
1125310: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1125310
Debian Bug Tracking System
Contact [email protected] with problems
--- Begin Message ---
Source: textual
Version: 2.1.2-1
Severity: serious
Tags: ftbfs, patch

rich 13.9.4-1.1 causes one test failure in textual:

__________________________________ test_demo ___________________________________

    async def test_demo():
        """Test the demo runs."""
        # Test he demo can at least run.
        # This exists mainly to catch screw-ups that might effect only certain 
Python versions.
        app = DemoApp()
>       async with app.run_test() as pilot:
                   ^^^^^^^^^^^^^^

tests/test_demo.py:9:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/usr/lib/python3.13/contextlib.py:221: in __aexit__
    await anext(self.gen)
/usr/lib/python3/dist-packages/textual/app.py:1991: in run_test
    raise self._exception
/usr/lib/python3/dist-packages/textual/message_pump.py:609: in 
_process_messages_loop
    await self._dispatch_message(message)
/usr/lib/python3/dist-packages/textual/message_pump.py:673: in _dispatch_message
    await self.on_event(message)
/usr/lib/python3/dist-packages/textual/message_pump.py:754: in on_event
    await self._on_message(event)
/usr/lib/python3/dist-packages/textual/message_pump.py:775: in _on_message
    await invoke(method, message)
/usr/lib/python3/dist-packages/textual/_callback.py:93: in invoke
    return await _invoke(callback, *params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
/usr/lib/python3/dist-packages/textual/_callback.py:53: in _invoke
    result = callback(*params[:parameter_count])
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
/usr/lib/python3/dist-packages/textual/screen.py:1335: in _on_screen_resume
    self._refresh_layout(size)
/usr/lib/python3/dist-packages/textual/screen.py:1255: in _refresh_layout
    self._compositor_refresh()
/usr/lib/python3/dist-packages/textual/screen.py:1091: in _compositor_refresh
    update = self._compositor.render_update(
/usr/lib/python3/dist-packages/textual/_compositor.py:1082: in render_update
    return self.render_full_update(simplify=simplify)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
/usr/lib/python3/dist-packages/textual/_compositor.py:1118: in 
render_full_update
    chops = self._render_chops(crop, lambda y: True)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
/usr/lib/python3/dist-packages/textual/_compositor.py:1188: in _render_chops
    for region, clip, strips in renders:
                                ^^^^^^^
/usr/lib/python3/dist-packages/textual/_compositor.py:1037: in _get_renders
    widget.render_lines(
/usr/lib/python3/dist-packages/textual/widget.py:3919: in render_lines
    strips = self._styles_cache.render_widget(self, crop)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
/usr/lib/python3/dist-packages/textual/_styles_cache.py:127: in render_widget
    strips = self.render(
/usr/lib/python3/dist-packages/textual/_styles_cache.py:230: in render
    strip = render_line(
/usr/lib/python3/dist-packages/textual/_styles_cache.py:449: in render_line
    line = render_content_line(y - gutter.top)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
/usr/lib/python3/dist-packages/textual/widget.py:3902: in render_line
    self._render_content()
/usr/lib/python3/dist-packages/textual/widget.py:3888: in _render_content
    strips = Visual.to_strips(self, visual, width, height, self.visual_style)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
/usr/lib/python3/dist-packages/textual/visual.py:199: in to_strips
    strips = visual.render_strips(
/usr/lib/python3/dist-packages/textual/content.py:520: in render_strips
    strip_lines = [Strip(*line.to_strip(style)) for line in lines]
                          ^^^^^^^^^^^^^^^^^^^^
/usr/lib/python3/dist-packages/textual/content.py:1376: in to_strip
    _Segment(text, (style + text_style).rich_style_with_offset(x, y))
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
/usr/lib/python3/dist-packages/textual/style.py:365: in rich_style_with_offset
    meta={**self.meta, "offset": (x, y)},
            ^^^^^^^^^
/usr/lib/python3.13/functools.py:1025: in __get__
    val = self.func(instance)
          ^^^^^^^^^^^^^^^^^^^
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <[ValueError('bad marshal data (unknown type code)') raised in repr()] 
Style object at 0x7fa0743a8050>

    @cached_property
    def meta(self) -> Mapping[str, Any]:
        """Get meta information (can not be changed after construction)."""
>       return {} if self._meta is None else loads(self._meta)
                                             ^^^^^^^^^^^^^^^^^
E       ValueError: bad marshal data (unknown type code)

/usr/lib/python3/dist-packages/textual/style.py:396: ValueError


This was my NMU, so I'm sorry for not spotting the problem in advance; I 
thought the rich changes were small enough to avoid compatibility issues 
in textual and missed the fact that they switched from marshal to pickle 
for style meta information.  However, I don't think the compatibility 
breakage could really have been avoided anyway: the change that caused 
this was part of upstream changes to support Python 3.14, and when I 
experimented locally I also couldn't find a way to get marshal.dumps to 
do the right thing on Python 3.14 so I can absolutely see why they 
switched to pickle instead.

The corresponding upstream fix to textual is in a commit unhelpfully 
labelled just "optimization" 
(https://github.com/Textualize/textual/pull/6169); as far as I can see 
upstream failed to label either side of this as affecting compatibility 
between rich and textual.  I think the only sensible way forward is to 
cherry-pick the relevant part of the textual change as well, add a 
Depends to textual for the new rich, and add a Breaks on old textual 
versions to rich.

https://salsa.debian.org/morph/textual/-/merge_requests/1 has the 
necessary changes to textual, and I've attached a debdiff here too.  The 
change to rich would then just be adding "Breaks: python3-textual (<< 
2.1.2-1.1~)".

Thanks,

-- 
Colin Watson (he/him)                              [[email protected]]
diff -Nru textual-2.1.2/debian/changelog textual-2.1.2/debian/changelog
--- textual-2.1.2/debian/changelog      2025-03-16 21:27:22.000000000 +0000
+++ textual-2.1.2/debian/changelog      2026-01-12 11:18:59.000000000 +0000
@@ -1,3 +1,10 @@
+textual (2.1.2-1.1) UNRELEASED; urgency=medium
+
+  * Non-maintainer upload.
+  * Use pickle for style meta information to match rich 13.9.4-1.1.
+
+ -- Colin Watson <[email protected]>  Mon, 12 Jan 2026 11:18:59 +0000
+
 textual (2.1.2-1) unstable; urgency=medium
 
   * New upstream release
diff -Nru textual-2.1.2/debian/control textual-2.1.2/debian/control
--- textual-2.1.2/debian/control        2025-03-16 21:27:22.000000000 +0000
+++ textual-2.1.2/debian/control        2026-01-12 11:18:59.000000000 +0000
@@ -12,7 +12,7 @@
                python3-pytest (>= 6.2.3) <!nocheck>,
                python3-pytest-asyncio <!nocheck>,
                python3-pytest-xdist <!nocheck>,
-               python3-rich (>= 10.7.0) <!nocheck>,
+               python3-rich (>= 13.9.4-1.1~) <!nocheck>,
                python3-syrupy <!nocheck>,
                python3-typing-extensions <!nocheck>,
 Standards-Version: 4.6.2
diff -Nru textual-2.1.2/debian/patches/pickle-style-meta.patch 
textual-2.1.2/debian/patches/pickle-style-meta.patch
--- textual-2.1.2/debian/patches/pickle-style-meta.patch        1970-01-01 
01:00:00.000000000 +0100
+++ textual-2.1.2/debian/patches/pickle-style-meta.patch        2026-01-12 
11:18:59.000000000 +0000
@@ -0,0 +1,25 @@
+From: Colin Watson <[email protected]>
+Date: Mon, 12 Jan 2026 11:18:22 +0000
+Subject: Use pickle for style meta information
+
+Backported from https://github.com/Textualize/textual/pull/6169; needed
+to match rich 14.2.0 / 13.9.4-1.1.
+
+Last-Update: 2026-01-12
+---
+ src/textual/style.py | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/textual/style.py b/src/textual/style.py
+index c96c9b7..7df24da 100644
+--- a/src/textual/style.py
++++ b/src/textual/style.py
+@@ -9,7 +9,7 @@ from __future__ import annotations
+ 
+ from dataclasses import dataclass
+ from functools import cached_property, lru_cache
+-from marshal import dumps, loads
++from pickle import dumps, loads
+ from typing import TYPE_CHECKING, Any, Iterable, Mapping
+ 
+ import rich.repr
diff -Nru textual-2.1.2/debian/patches/series 
textual-2.1.2/debian/patches/series
--- textual-2.1.2/debian/patches/series 1970-01-01 01:00:00.000000000 +0100
+++ textual-2.1.2/debian/patches/series 2026-01-12 11:18:29.000000000 +0000
@@ -0,0 +1 @@
+pickle-style-meta.patch

--- End Message ---
--- Begin Message ---
Source: textual
Source-Version: 2.1.2-1.1

textual (2.1.2-1.1) unstable; urgency=medium

  * Non-maintainer upload.
  * Use pickle for style meta information to match rich 13.9.4-1.1 (closes:
    #1125310).

 -- Colin Watson <[email protected]>  Mon, 19 Jan 2026 11:09:00 +0000

--
Colin Watson (he/him)                              [[email protected]]

--- End Message ---

Reply via email to