Package: urwid Version: 2.6.4-1 Severity: normal Tags: patch User: ubuntu-de...@lists.ubuntu.com Usertags: origin-ubuntu noble ubuntu-patch
Dear Maintainer, With the version of urwid 2.6.4-1 currently in trixie, the following code fails with an exception: ```python from urwid import Pile Pile([ ("pack", Pile([])), ]).render((10,)) ``` File "/usr/lib/python3/dist-packages/urwid/widget/widget.py", line 112, in cached_render canv = fn(self, size, focus=focus) ^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3/dist-packages/urwid/widget/pile.py", line 822, in render _widths, heights, size_args = self.get_rows_sizes(size, focus) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3/dist-packages/urwid/widget/pile.py", line 730, in get_rows_sizes heights.append(w.pack(w_h_arg, item_focus)[1]) ^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3/dist-packages/urwid/widget/pile.py", line 744, in pack return super().pack(size, focus) ^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3/dist-packages/urwid/widget/widget.py", line 401, in pack raise WidgetError(f"Cannot pack (maxcol,) size, this is not a flow widget: {self!r}") urwid.widget.widget.WidgetError: Cannot pack (maxcol,) size, this is not a flow widget: <Pile widget> The same code used to work with urwid 2.1.2-4 in bookworm. I applied a fix from upstream [1] that was included in urwid 2.6.5. I think the proper way forward would be to take a more recent upstream version of urwid. That said, we are in feature freeze downstream in Ubuntu so I skipped the refactoring bits. In Ubuntu, the attached patch was applied to achieve the following: * Apply upstream patch to fix a crash when rendering an empty Pile or an empty Columns as a flow widget. (LP: #2058388) + d/patches/fix-crash-empty-pile.patch Thanks for considering the patch. -- System Information: Debian Release: trixie/sid APT prefers noble APT policy: (500, 'noble'), (100, 'noble-proposed') Architecture: amd64 (x86_64) Foreign Architectures: i386 Kernel: Linux 6.8.0-11-generic (SMP w/8 CPU threads; PREEMPT) Kernel taint flags: TAINT_PROPRIETARY_MODULE, TAINT_OOT_MODULE Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8), LANGUAGE not set Shell: /bin/sh linked to /usr/bin/dash Init: systemd (via /run/systemd/system) LSM: AppArmor: enabled [1] https://github.com/urwid/urwid/commit/83c278b53de431a9b41d7ddadf5f318914246593
diff -Nru urwid-2.6.4/debian/patches/fix-crash-empty-pile.patch urwid-2.6.4/debian/patches/fix-crash-empty-pile.patch --- urwid-2.6.4/debian/patches/fix-crash-empty-pile.patch 1970-01-01 01:00:00.000000000 +0100 +++ urwid-2.6.4/debian/patches/fix-crash-empty-pile.patch 2024-03-19 14:23:31.000000000 +0100 @@ -0,0 +1,158 @@ +Description: Fix crash when rendering empty Pile or Columns as a flow widget + Special case: in case of `Columns`/`Pile` empty - use fallback sizing (#843) + . + * Extend `repr` to provide brief info about contents + . +Author: Aleksei Stepanov <aleks...@nvidia.com> +Origin: upstream, https://github.com/urwid/urwid/commit/83c278b53de431a9b41d7ddadf5f318914246593 +Bug-Ubuntu: https://launchpad.net/bugs/2058388 +Last-Update: 2024-03-19 +--- +This patch header follows DEP-3: http://dep.debian.net/deps/dep3/ +diff --git a/urwid/widget/columns.py b/urwid/widget/columns.py +index e3fa134..5a3421f 100644 +--- a/urwid/widget/columns.py ++++ b/urwid/widget/columns.py +@@ -66,40 +66,47 @@ class Columns(Widget, WidgetContainerMixin, WidgetContainerListContentsMixin): + + # BOX-only widget + >>> Columns((SolidFill("#"),)) +- <Columns box widget> ++ <Columns box widget with 1 item> + + # BOX-only widget with "get height from max" + >>> Columns((SolidFill("#"),), box_columns=(0,)) +- <Columns box widget> ++ <Columns box widget with 1 item> + + # FLOW-only + >>> Columns((Edit(),)) +- <Columns selectable flow widget> ++ <Columns selectable flow widget with 1 item> + + # FLOW allowed by "box_columns" + >>> Columns((Edit(), SolidFill("#")), box_columns=(1,)) +- <Columns selectable flow widget> ++ <Columns selectable flow widget with 2 items> + + # FLOW/FIXED + >>> Columns((Text("T"),)) +- <Columns fixed/flow widget> ++ <Columns fixed/flow widget with 1 item> + + # GIVEN BOX only -> BOX only + >>> Columns(((5, SolidFill("#")),), box_columns=(0,)) +- <Columns box widget> ++ <Columns box widget with 1 item> + + # No FLOW - BOX only + >>> Columns(((5, SolidFill("#")), SolidFill("*")), box_columns=(0, 1)) +- <Columns box widget> ++ <Columns box widget with 2 items> + + # FIXED only -> FIXED + >>> Columns(((WHSettings.PACK, BigText("1", font)),)) +- <Columns fixed widget> ++ <Columns fixed widget with 1 item> + + # Invalid sizing combination -> use fallback settings (and produce warning) + >>> Columns(((WHSettings.PACK, SolidFill("#")),)) +- <Columns box/flow widget> ++ <Columns box/flow widget with 1 item> ++ ++ # Special case: empty columns widget sizing is impossible to calculate ++ >>> Columns(()) ++ <Columns box/flow widget without contents> + """ ++ if not self.contents: ++ return frozenset((urwid.BOX, urwid.FLOW)) ++ + strict_box = False + has_flow = False + +@@ -280,6 +287,13 @@ class Columns(Widget, WidgetContainerMixin, WidgetContainerListContentsMixin): + self.min_width = min_width + self._cache_maxcol = None + ++ def _repr_words(self) -> list[str]: ++ if len(self.contents) > 1: ++ return [*super()._repr_words(), f"with {len(self.contents)} items"] ++ if self.contents: ++ return [*super()._repr_words(), "with 1 item"] ++ return [*super()._repr_words(), "without contents"] ++ + def _contents_modified(self) -> None: + """ + Recalculate whether this widget should be selectable whenever the +diff --git a/urwid/widget/pile.py b/urwid/widget/pile.py +index 2ee27fb..a1fc37f 100644 +--- a/urwid/widget/pile.py ++++ b/urwid/widget/pile.py +@@ -58,36 +58,42 @@ class Pile(Widget, WidgetContainerMixin, WidgetContainerListContentsMixin): + + # BOX-only widget + >>> Pile((SolidFill("#"),)) +- <Pile box widget> ++ <Pile box widget with 1 item> + + # GIVEN BOX -> BOX/FLOW + >>> Pile(((10, SolidFill("#")),)) +- <Pile box/flow widget> ++ <Pile box/flow widget with 1 item> + + # FLOW-only + >>> Pile((ProgressBar(None, None),)) +- <Pile flow widget> ++ <Pile flow widget with 1 item> + + # FIXED -> FIXED + >>> Pile(((WHSettings.PACK, BigText("0", font)),)) +- <Pile fixed widget> ++ <Pile fixed widget with 1 item> + + # FLOW/FIXED -> FLOW/FIXED + >>> Pile(((WHSettings.PACK, Text("text")),)) +- <Pile fixed/flow widget> ++ <Pile fixed/flow widget with 1 item> + + # FLOW + FIXED widgets -> FLOW/FIXED + >>> Pile((ProgressBar(None, None), (WHSettings.PACK, BigText("0", font)))) +- <Pile fixed/flow widget> ++ <Pile fixed/flow widget with 2 items> + + # GIVEN BOX + FIXED widgets -> BOX/FLOW/FIXED (GIVEN BOX allows overriding its height & allows any width) + >>> Pile(((10, SolidFill("#")), (WHSettings.PACK, BigText("0", font)))) +- <Pile widget> ++ <Pile widget with 2 items> + + # Invalid sizing combination -> use fallback settings (and produce warning) + >>> Pile(((WHSettings.WEIGHT, 1, BigText("0", font)),)) +- <Pile box/flow widget> ++ <Pile box/flow widget with 1 item> ++ ++ # Special case: empty pile widget sizing is impossible to calculate ++ >>> Pile(()) ++ <Pile box/flow widget without contents> + """ ++ if not self.contents: ++ return frozenset((Sizing.BOX, Sizing.FLOW)) + strict_box = False + has_flow = False + +@@ -225,6 +231,13 @@ class Pile(Widget, WidgetContainerMixin, WidgetContainerListContentsMixin): + + self.pref_col = 0 + ++ def _repr_words(self) -> list[str]: ++ if len(self.contents) > 1: ++ return [*super()._repr_words(), f"with {len(self.contents)} items"] ++ if self.contents: ++ return [*super()._repr_words(), "with 1 item"] ++ return [*super()._repr_words(), "without contents"] ++ + def _contents_modified(self) -> None: + """Recalculate whether this widget should be selectable whenever the contents has been changed.""" + self._selectable = any(w.selectable() for w, o in self.contents) +-- +2.43.0 + diff -Nru urwid-2.6.4/debian/patches/series urwid-2.6.4/debian/patches/series --- urwid-2.6.4/debian/patches/series 2024-02-24 20:58:30.000000000 +0100 +++ urwid-2.6.4/debian/patches/series 2024-03-19 14:23:31.000000000 +0100 @@ -1,2 +1,3 @@ no-sphinx-changelog.diff #version-module.diff +fix-crash-empty-pile.patch