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-26 21:11:27 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-textual (Old) and /work/SRC/openSUSE:Factory/.python-textual.new.11940 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-textual" Sun Apr 26 21:11:27 2026 rev:10 rq:1349279 version:8.2.4 Changes: -------- --- /work/SRC/openSUSE:Factory/python-textual/python-textual.changes 2026-04-18 21:35:27.611326621 +0200 +++ /work/SRC/openSUSE:Factory/.python-textual.new.11940/python-textual.changes 2026-04-26 21:14:05.908249001 +0200 @@ -1,0 +2,8 @@ +Sat Apr 25 20:25:45 UTC 2026 - Dirk Müller <[email protected]> + +- update to 8.2.4: + * Small potatoes update, to fix a glitch with anchor. + * Added `DOM.update_classes` + * Fixed anchor released when scrolling down with the trackpad + +------------------------------------------------------------------- Old: ---- textual-8.2.3.tar.gz New: ---- textual-8.2.4.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-textual.spec ++++++ --- /var/tmp/diff_new_pack.efMh6z/_old 2026-04-26 21:14:06.400269103 +0200 +++ /var/tmp/diff_new_pack.efMh6z/_new 2026-04-26 21:14:06.400269103 +0200 @@ -26,7 +26,7 @@ %endif %{?sle15_python_module_pythons} Name: python-textual%{psuffix} -Version: 8.2.3 +Version: 8.2.4 Release: 0 Summary: TUI framework for Python License: MIT ++++++ textual-8.2.3.tar.gz -> textual-8.2.4.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/textual-8.2.3/PKG-INFO new/textual-8.2.4/PKG-INFO --- old/textual-8.2.3/PKG-INFO 1970-01-01 01:00:00.000000000 +0100 +++ new/textual-8.2.4/PKG-INFO 1970-01-01 01:00:00.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 2.4 Name: textual -Version: 8.2.3 +Version: 8.2.4 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.3/pyproject.toml new/textual-8.2.4/pyproject.toml --- old/textual-8.2.3/pyproject.toml 1970-01-01 01:00:00.000000000 +0100 +++ new/textual-8.2.4/pyproject.toml 1970-01-01 01:00:00.000000000 +0100 @@ -1,6 +1,6 @@ [tool.poetry] name = "textual" -version = "8.2.3" +version = "8.2.4" 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.3/src/textual/dom.py new/textual-8.2.4/src/textual/dom.py --- old/textual-8.2.3/src/textual/dom.py 1970-01-01 01:00:00.000000000 +0100 +++ new/textual-8.2.4/src/textual/dom.py 1970-01-01 01:00:00.000000000 +0100 @@ -16,6 +16,7 @@ Callable, ClassVar, Iterable, + Mapping, Sequence, Type, TypeVar, @@ -1762,6 +1763,34 @@ self.remove_class(*class_names, update=update) return self + def update_classes( + self, classes: Mapping[str, bool], update: bool = True, animate: bool = True + ) -> Self: + """Update classes in an atomic batch. + + Args: + classes: A mapping of class name on to a boolean where `True` adds + to the current classes, and `False` removes. + update: Also update styles. + animate: Enable any CSS animation? + + Returns: + Self + """ + + add_classes: set[str] = set() + remove_classes: set[str] = set() + adds = (remove_classes.add, add_classes.add) + for class_name, add in classes.items(): + adds[add](class_name) + + new_classes = (self._classes | add_classes) - remove_classes + if self._classes != new_classes: + self._classes = new_classes + if update: + self.update_node_styles(animate=animate) + return self + def set_classes(self, classes: str | Iterable[str]) -> Self: """Replace all classes. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/textual-8.2.3/src/textual/layouts/grid.py new/textual-8.2.4/src/textual/layouts/grid.py --- old/textual-8.2.3/src/textual/layouts/grid.py 1970-01-01 01:00:00.000000000 +0100 +++ new/textual-8.2.4/src/textual/layouts/grid.py 1970-01-01 01:00:00.000000000 +0100 @@ -318,6 +318,8 @@ max_column = len(columns) - 1 max_row = len(rows) - 1 + stretch_height = self.stretch_height and len(children) > 1 + for widget, (column, row, column_span, row_span) in cell_size_map.items(): x = columns[column][0] if row > max_row: @@ -336,9 +338,8 @@ greedy=greedy, ) - if self.stretch_height and len(children) > 1: - if box_height <= cell_size.height: - box_height = Fraction(cell_size.height) + if stretch_height and box_height <= cell_size.height: + box_height = Fraction(cell_size.height) region = ( Region( diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/textual-8.2.3/src/textual/screen.py new/textual-8.2.4/src/textual/screen.py --- old/textual-8.2.3/src/textual/screen.py 1970-01-01 01:00:00.000000000 +0100 +++ new/textual-8.2.4/src/textual/screen.py 1970-01-01 01:00:00.000000000 +0100 @@ -1527,36 +1527,24 @@ else self.VERTICAL_BREAKPOINTS ) or [] - width, height = event.size - if horizontal_breakpoints or vertical_breakpoints: + width, height = event.size + breakpoints = { + breakpoint: False + for _, breakpoint in (horizontal_breakpoints + vertical_breakpoints) + } + + for breakpoint in self._get_breakpoint_classes( + width, horizontal_breakpoints + ): + breakpoints[breakpoint] = True + + for breakpoint in self._get_breakpoint_classes( + height, vertical_breakpoints + ): + breakpoints[breakpoint] = True - 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) + self.update_classes(breakpoints, animate=False) def _get_breakpoint_classes( self, dimension: int, breakpoints: list[tuple[int, str]] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/textual-8.2.3/src/textual/widget.py new/textual-8.2.4/src/textual/widget.py --- old/textual-8.2.3/src/textual/widget.py 1970-01-01 01:00:00.000000000 +0100 +++ new/textual-8.2.4/src/textual/widget.py 1970-01-01 01:00:00.000000000 +0100 @@ -2746,6 +2746,7 @@ Returns: `True` if the scroll position changed, otherwise `False`. """ + if release_anchor: self.release_anchor() maybe_scroll_x = x is not None and (self.allow_horizontal_scroll or force) @@ -3305,6 +3306,7 @@ force=force, on_complete=on_complete, level=level, + release_anchor=False, ) def scroll_up(
