[PATCH b4 1/2] review-tui: fall back to '(no subject)' for null Patchwork series names

Christian Brauner <[email protected]> Tue, 30 Jun 2026 15:41:32 +0200
Newsgroups org.kernel.linux.tools
Message-ID <20260630-review-tui-null-series-name-v1-1-67d7c9334454@kernel.org>
Patchwork returns "name": null for a series posted without a cover letter.
Several spots in the Patchwork app read it with
series.get('name', '(no subject)'), whose default only applies when the key
is *absent* -- a present-but-None name passes straight through as None.

On the bulk set-state path that None reached ApplyStateModal and was handed
to a Label, which Textual cannot render:

    VisualError: unable to display 'NoneType' type; must be a str, Rich
    renderable, or Textual Visual object

so opening the apply-state dialog for such a series crashed the whole TUI
during layout. The track/hide/unhide notification paths shared the same
latent bug, displaying a literal "None" in place of the placeholder.

Use the `series.get('name') or '(no subject)'` idiom already used by the
list-row renderer so a null name consistently becomes the placeholder.

Signed-off-by: Christian Brauner (Amutable) <[email protected]>
---
 src/b4/review_tui/_pw_app.py | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/b4/review_tui/_pw_app.py b/src/b4/review_tui/_pw_app.py
index e70d017..9faf785 100644
--- a/src/b4/review_tui/_pw_app.py
+++ b/src/b4/review_tui/_pw_app.py
@@ -766,7 +766,7 @@ class PwApp(LoreNodeShutdownMixin, App[None]):
             return
 
         if len(targets) == 1:
-            label = targets[0].get('name', '(no subject)')
+            label = targets[0].get('name') or '(no subject)'
         else:
             label = f'{len(targets)} series ({len(patch_ids)} patches)'
         self.push_screen(
@@ -822,7 +822,7 @@ class PwApp(LoreNodeShutdownMixin, App[None]):
             self.notify('Series already tracked', severity='information')
             return
 
-        series_name = item.series.get('name', '(no subject)')
+        series_name = item.series.get('name') or '(no subject)'
         msgid = item.series.get('msgid', '')
         if not msgid:
             self.notify('No message-id available for this series', severity='error')
@@ -932,7 +932,7 @@ class PwApp(LoreNodeShutdownMixin, App[None]):
             return
         self._hidden_ids.add(sid)
         self._save_local_data()
-        title = item.series.get('name', '(no subject)')
+        title = item.series.get('name') or '(no subject)'
         self.notify(f'Hidden: {title}', timeout=3)
         await self._refresh_list()
 
@@ -955,7 +955,7 @@ class PwApp(LoreNodeShutdownMixin, App[None]):
             return
         self._hidden_ids.discard(sid)
         self._save_local_data()
-        title = item.series.get('name', '(no subject)')
+        title = item.series.get('name') or '(no subject)'
         self.notify(f'Restored: {title}', timeout=3)
         await self._refresh_list()
 

-- 
2.53.0