Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-textual for openSUSE:Factory 
checked in at 2026-04-18 21:35:17
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-textual (Old)
 and      /work/SRC/openSUSE:Factory/.python-textual.new.11940 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-textual"

Sat Apr 18 21:35:17 2026 rev:9 rq:1347831 version:8.2.3

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-textual/python-textual.changes    
2026-03-30 18:34:37.315392832 +0200
+++ /work/SRC/openSUSE:Factory/.python-textual.new.11940/python-textual.changes 
2026-04-18 21:35:27.611326621 +0200
@@ -1,0 +2,7 @@
+Thu Apr 16 13:07:57 UTC 2026 - John Paul Adrian Glaubitz 
<[email protected]>
+
+- Update to 8.2.2
+  * Reduce lag when resizing window, by moving resize from
+    idle to a timer
+
+-------------------------------------------------------------------

Old:
----
  textual-8.2.1.tar.gz

New:
----
  textual-8.2.3.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-textual.spec ++++++
--- /var/tmp/diff_new_pack.DpFIoP/_old  2026-04-18 21:35:28.311355151 +0200
+++ /var/tmp/diff_new_pack.DpFIoP/_new  2026-04-18 21:35:28.311355151 +0200
@@ -26,7 +26,7 @@
 %endif
 %{?sle15_python_module_pythons}
 Name:           python-textual%{psuffix}
-Version:        8.2.1
+Version:        8.2.3
 Release:        0
 Summary:        TUI framework for Python
 License:        MIT

++++++ textual-8.2.1.tar.gz -> textual-8.2.3.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/textual-8.2.1/PKG-INFO new/textual-8.2.3/PKG-INFO
--- old/textual-8.2.1/PKG-INFO  1970-01-01 01:00:00.000000000 +0100
+++ new/textual-8.2.3/PKG-INFO  1970-01-01 01:00:00.000000000 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 2.4
 Name: textual
-Version: 8.2.1
+Version: 8.2.3
 Summary: Modern Text User Interface framework
 License: MIT
 License-File: LICENSE
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/textual-8.2.1/pyproject.toml 
new/textual-8.2.3/pyproject.toml
--- old/textual-8.2.1/pyproject.toml    1970-01-01 01:00:00.000000000 +0100
+++ new/textual-8.2.3/pyproject.toml    1970-01-01 01:00:00.000000000 +0100
@@ -1,6 +1,6 @@
 [tool.poetry]
 name = "textual"
-version = "8.2.1"
+version = "8.2.3"
 homepage = "https://github.com/Textualize/textual";
 repository = "https://github.com/Textualize/textual";
 documentation = "https://textual.textualize.io/";
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/textual-8.2.1/src/textual/app.py 
new/textual-8.2.3/src/textual/app.py
--- old/textual-8.2.1/src/textual/app.py        1970-01-01 01:00:00.000000000 
+0100
+++ new/textual-8.2.3/src/textual/app.py        1970-01-01 01:00:00.000000000 
+0100
@@ -876,6 +876,9 @@
                     )
                 )
 
+        self._resize_timer: Timer | None = None
+        """Timer used to invoke screen resize."""
+
     def get_line_filters(self) -> Sequence[LineFilter]:
         """Get currently enabled line filters.
 
@@ -1630,6 +1633,8 @@
             width, height = self._driver._size
         else:
             width, height = self.console.size
+            if self._driver is not None:
+                self._driver._size = (width, height)
         return Size(width, height)
 
     @property
@@ -4308,8 +4313,16 @@
 
     async def _on_resize(self, event: events.Resize) -> None:
         event.stop()
-        self._size = event.size
         self._resize_event = event
+        if self._size is None:
+            self._size = event.size
+            self._check_resize()
+            return
+        if self._size == event.size:
+            return
+        self._size = event.size
+        if self._resize_timer is None:
+            self._resize_timer = self.set_timer(1 / 120, self._check_resize)
 
     async def _on_app_focus(self, event: events.AppFocus) -> None:
         """App has focus."""
@@ -4976,9 +4989,20 @@
         self.log.debug(message)
 
     def _on_idle(self) -> None:
-        """Send app resize events on idle, so we don't do more resizing that 
necessary."""
+        if self._resize_event is not None and self._resize_timer is None:
+            self._check_resize()
+
+    def _check_resize(self) -> None:
+        """Send a resize event to screen(s) (invoked from 
`self._resize_timer`)."""
         event = self._resize_event
+        if self._resize_timer is not None:
+            self._resize_timer.stop()
+            self._resize_timer = None
         if event is not None:
+            try:
+                self.screen
+            except ScreenError:
+                return
             self._resize_event = None
             self.screen.post_message(event)
             for screen in self._background_screens:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/textual-8.2.1/src/textual/dom.py 
new/textual-8.2.3/src/textual/dom.py
--- old/textual-8.2.1/src/textual/dom.py        1970-01-01 01:00:00.000000000 
+0100
+++ new/textual-8.2.3/src/textual/dom.py        1970-01-01 01:00:00.000000000 
+0100
@@ -125,8 +125,9 @@
         else:
             class_names = set(classes)
         check_identifiers("class name", *class_names)
-        obj._classes = class_names
-        obj.update_node_styles()
+        if obj._classes != class_names:
+            obj._classes = class_names
+            obj.update_node_styles()
 
 
 @rich.repr.auto
@@ -1795,10 +1796,9 @@
             Self.
         """
         check_identifiers("class name", *class_names)
-        old_classes = self._classes.copy()
-        self._classes.update(class_names)
-        if old_classes == self._classes:
+        if self._classes.issuperset(class_names):
             return self
+        self._classes.update(class_names)
         if update:
             self.update_node_styles()
         return self
@@ -1814,10 +1814,9 @@
             Self.
         """
         check_identifiers("class name", *class_names)
-        old_classes = self._classes.copy()
-        self._classes.difference_update(class_names)
-        if old_classes == self._classes:
+        if self._classes.isdisjoint(class_names):
             return self
+        self._classes.difference_update(class_names)
         if update:
             self.update_node_styles()
         return self
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/textual-8.2.1/src/textual/drivers/linux_driver.py 
new/textual-8.2.3/src/textual/drivers/linux_driver.py
--- old/textual-8.2.1/src/textual/drivers/linux_driver.py       1970-01-01 
01:00:00.000000000 +0100
+++ new/textual-8.2.3/src/textual/drivers/linux_driver.py       1970-01-01 
01:00:00.000000000 +0100
@@ -241,6 +241,7 @@
                 send_size_event()
 
         signal.signal(signal.SIGWINCH, on_terminal_resize)
+        send_size_event()
 
         self.write("\x1b[?1049h")  # Alt screen
 
@@ -277,7 +278,7 @@
 
         self.flush()
         self._key_thread = Thread(target=self._run_input_thread, 
name="textual-input")
-        send_size_event()
+
         self._key_thread.start()
         self._request_terminal_sync_mode_support()
         self._query_in_band_window_resize()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/textual-8.2.1/src/textual/screen.py 
new/textual-8.2.3/src/textual/screen.py
--- old/textual-8.2.1/src/textual/screen.py     1970-01-01 01:00:00.000000000 
+0100
+++ new/textual-8.2.3/src/textual/screen.py     1970-01-01 01:00:00.000000000 
+0100
@@ -1528,27 +1528,52 @@
         ) or []
 
         width, height = event.size
-        if horizontal_breakpoints:
-            self._set_breakpoints(width, horizontal_breakpoints)
-        if vertical_breakpoints:
-            self._set_breakpoints(height, vertical_breakpoints)
 
-    def _set_breakpoints(
+        if horizontal_breakpoints or vertical_breakpoints:
+
+            remove_breakpoint_classes = {
+                breakpoint for _, breakpoint in horizontal_breakpoints
+            } | {breakpoint for _, breakpoint in vertical_breakpoints}
+            remove_breakpoint_classes = self._classes.intersection(
+                remove_breakpoint_classes
+            )
+
+            breakpoint_classes: set[str] = set()
+
+            if horizontal_breakpoints:
+                breakpoint_classes |= self._get_breakpoint_classes(
+                    width, horizontal_breakpoints
+                )
+            if vertical_breakpoints:
+                breakpoint_classes |= self._get_breakpoint_classes(
+                    height, vertical_breakpoints
+                )
+
+            remove_breakpoint_classes -= breakpoint_classes
+            classes = self._classes.copy()
+            if remove_breakpoint_classes:
+                self._classes.difference_update(remove_breakpoint_classes)
+            if breakpoint_classes:
+                self._classes.update(breakpoint_classes)
+            if self._classes != classes:
+                self.update_node_styles(animate=False)
+
+    def _get_breakpoint_classes(
         self, dimension: int, breakpoints: list[tuple[int, str]]
-    ) -> None:
-        """Set horizontal or vertical breakpoints.
+    ) -> set[str]:
+        """Get breakpoint classes for given dimension.
 
         Args:
-            dimension: Either the width or the height.
-            breakpoints: A list of breakpoints.
+            dimension: Size in cells.
+            breakpoints: Associated breakpoints.
 
+        Returns:
+            A set containing a breakpoint, or an empty set if none apply.
         """
-        class_names = [class_name for _breakpoint, class_name in breakpoints]
-        self.remove_class(*class_names)
         for breakpoint, class_name in sorted(breakpoints, reverse=True):
             if dimension >= breakpoint:
-                self.add_class(class_name)
-                return
+                return {class_name}
+        return set()
 
     def _update_tooltip(self, widget: Widget) -> None:
         """Update the content of the tooltip."""
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/textual-8.2.1/src/textual/selection.py 
new/textual-8.2.3/src/textual/selection.py
--- old/textual-8.2.1/src/textual/selection.py  1970-01-01 01:00:00.000000000 
+0100
+++ new/textual-8.2.3/src/textual/selection.py  1970-01-01 01:00:00.000000000 
+0100
@@ -40,10 +40,10 @@
         if not lines:
             return ""
         if self.start is None:
-            start_line = 0
+            start_line_index = 0
             start_offset = 0
         else:
-            start_line, start_offset = self.start.transpose
+            start_line_index, start_offset = self.start.transpose
 
         if self.end is None:
             end_line = len(lines)
@@ -52,18 +52,21 @@
             end_line, end_offset = self.end.transpose
         end_line = min(len(lines), end_line)
 
-        if start_line == end_line:
-            return lines[start_line][start_offset:end_offset]
+        if start_line_index == end_line:
+            return lines[start_line_index][start_offset:end_offset]
 
         selection: list[str] = []
-        selected_lines = lines[start_line : end_line + 1]
+        selected_lines = lines[start_line_index : end_line + 1]
         if len(selected_lines) >= 2:
             first_line, *mid_lines, last_line = selected_lines
             selection.append(first_line[start_offset:])
             selection.extend(mid_lines)
             selection.append(last_line[:end_offset])
         else:
-            return lines[start_line][start_offset:end_offset]
+            try:
+                
selection.append(lines[start_line_index][start_offset:end_offset])
+            except IndexError:
+                pass
         return "\n".join(selection)
 
     def get_span(self, y: int) -> tuple[int, int] | None:

Reply via email to