Your message dated Sun, 04 Oct 2026 23:37:33 +0000
with message-id <[email protected]>
and subject line Bug#1146532: fixed in python-blessed 1.25-2
has caused the Debian Bug report #1146532,
regarding python-blessed: FTBFS against python 3.15rc1
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.)


-- 
1146532: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1146532
Debian Bug Tracking System
Contact [email protected] with problems
--- Begin Message ---
Package: src:python-blessed
Version: 1.25-1
User: [email protected]
Usertags: python3.15
Tags: patch, ftbfs, forky, sid

Hi!

While rebuilding the python related packages against the Python 3.15rc1
version we found that python-blessed fails to build from source [1].

The error is: DeprecationWarning: This process (pid=1990) is
multi-threaded, use of forkpty() may lead to deadlocks in the child.

In order to fix it, I had to apply two changes:
- Upstream Commit cee680f: Ignore deprecation warnings fro pty.fork [2]
- Run tests against the tests directory (otherwise a patch in the tests
  tries to run the tests in .pc)

I applied these fixes in the sandbox [3] to be able to build the
packages that depend on python-blessed, please consider applying the
patch to support the upcoming 3.15 version.

Happy hacking,

[1]: https://debusine.debian.net/debian/r-python-python3.15/artifact/4434437/
[2]: 
https://github.com/jquast/blessed/commit/cee680ff7fb3ad31f42ae98582ba74629f1fd6b0
[3]: https://debusine.debian.net/debian/r-python-python3.15/

--
"Can you imagine what I would do if I could do all I can?" -- Sun Tzu
Saludos /\/\ /\ >< `/
diff -Nru python-blessed-1.25/debian/changelog 
python-blessed-1.25/debian/changelog
--- python-blessed-1.25/debian/changelog        2025-12-24 16:26:02.000000000 
+0100
+++ python-blessed-1.25/debian/changelog        2026-09-02 16:19:03.000000000 
+0200
@@ -1,3 +1,12 @@
+python-blessed (1.25-2) UNRELEASED; urgency=medium
+
+  * Team upload.
+  * Add more upstream patch:
+    0002-Update-wrap-logic-and-add-optional-testing-for-Python-3.15.patch
+  * Avoid running tests from .pc
+
+ -- Maximiliano Curia <[email protected]>  Wed, 02 Sep 2026 16:19:03 +0200
+
 python-blessed (1.25-1) unstable; urgency=medium
 
   * Team Upload
diff -Nru 
python-blessed-1.25/debian/patches/0002-Update-wrap-logic-and-add-optional-testing-for-Python-3.15.patch
 
python-blessed-1.25/debian/patches/0002-Update-wrap-logic-and-add-optional-testing-for-Python-3.15.patch
--- 
python-blessed-1.25/debian/patches/0002-Update-wrap-logic-and-add-optional-testing-for-Python-3.15.patch
    1970-01-01 01:00:00.000000000 +0100
+++ 
python-blessed-1.25/debian/patches/0002-Update-wrap-logic-and-add-optional-testing-for-Python-3.15.patch
    2026-09-02 16:19:03.000000000 +0200
@@ -0,0 +1,253 @@
+From: Avram Lubkin <[email protected]>
+Date: Thu, 4 Dec 2025 11:55:11 -0500
+Subject: Update wrap() logic and add optional testing for Python 3.15 (#311)
+
+* Add optional testing for Python 3.15
+
+* Ignore deprecation warnings for pty.fork()
+
+* Update wrap logic to match 3.15
+
+* Add test for placeholder in wrap()
+
+* Ignore deprecation warnings for pty_test()
+Origin: upstream, 
https://github.com/jquast/blessed/commit/cee680ff7fb3ad31f42ae98582ba74629f1fd6b0
+---
+ blessed/sequences.py | 78 +++++++++++++++++++++++++++++++++++++-------
+ tests/accessories.py | 12 ++++---
+ tests/test_wrap.py   | 55 +++++++++++++++++++++++++++++++
+ 3 files changed, 129 insertions(+), 16 deletions(-)
+
+--- a/blessed/sequences.py
++++ b/blessed/sequences.py
+@@ -155,6 +155,7 @@ class SequenceTextWrapper(textwrap.TextW
+         self.term = term
+         textwrap.TextWrapper.__init__(self, width, **kwargs)
+ 
++    # pylint: disable-next=too-complex,too-many-branches
+     def _wrap_chunks(self, chunks):    # type: ignore[no-untyped-def]
+         """
+         Sequence-aware variant of :meth:`textwrap.TextWrapper._wrap_chunks`.
+@@ -174,29 +175,82 @@ class SequenceTextWrapper(textwrap.TextW
+                 f"invalid width {self.width!r}({type(self.width)!r}) (must be 
integer > 0)"
+             )
+ 
++        if self.max_lines is not None:
++            indent = self.subsequent_indent if self.max_lines > 1 else 
self.initial_indent
++            if len(indent) + len(self.placeholder.lstrip()) > self.width:
++                raise ValueError("placeholder too large for max width")
++
+         term = self.term
+-        drop_whitespace = not hasattr(self, 'drop_whitespace'
+-                                      ) or self.drop_whitespace
++
++        # Arrange in reverse order so items can be efficiently popped from a 
stack of chucks.
+         chunks.reverse()
+-        while chunks:
+-            cur_line: List[str] = []
+-            cur_len = 0
++        while chunks:  # pylint: disable=too-many-nested-blocks
++
++            cur_line = []  # Current line.
++            cur_len = 0  # Length of all the chunks in cur_line
++
++            # Figure out which static string will prefix this line.
+             indent = self.subsequent_indent if lines else self.initial_indent
++            # Maximum width for this line.
+             width = self.width - len(indent)
+-            if drop_whitespace and lines and not Sequence(chunks[-1], 
term).strip():
++
++            # First chunk on line is whitespace -- drop it, unless this
++            # is the very beginning of the text (ie. no lines started yet).
++            if self.drop_whitespace and lines and not Sequence(chunks[-1], 
term).strip():
+                 del chunks[-1]
++
+             while chunks:
+                 chunk_len = Sequence(chunks[-1], term).length()
+                 if cur_len + chunk_len > width:
+-                    if chunk_len > width:
+-                        self._handle_long_word(chunks, cur_line, cur_len, 
width)
+                     break
++
+                 cur_line.append(chunks.pop())
+                 cur_len += chunk_len
+-            if drop_whitespace and (cur_line and not Sequence(cur_line[-1], 
term).strip()):
+-                del cur_line[-1]
++
++            # The current line is full, and the next chunk is too big to fit 
on *any* line
++            if chunks and Sequence(chunks[-1], term).length() > width:
++                self._handle_long_word(chunks, cur_line, cur_len, width)
++                cur_len = sum(Sequence(chunk, term).length() for chunk in 
cur_line)
++
++            # If the last chunk on this line is all whitespace, drop it.
++            if self.drop_whitespace and cur_line:
++                chunk = Sequence(cur_line[-1], term)
++                if not chunk.strip():
++                    cur_len -= chunk.length()
++                    del cur_line[-1]
++
+             if cur_line:
+-                lines.append(f'{indent}{"".join(cur_line)}')
++                if (  # pylint: disable=too-many-boolean-expressions
++                    self.max_lines is None
++                    or len(lines) + 1 < self.max_lines
++                    or (
++                        not chunks
++                        or self.drop_whitespace
++                        and len(chunks) == 1
++                        and not chunks[0].strip()
++                    )
++                    and cur_len <= width
++                ):
++                    lines.append(indent + ''.join(cur_line))
++
++                else:
++                    while cur_line:
++                        chunk = Sequence(cur_line[-1], term)
++                        if (chunk.strip() and cur_len + len(self.placeholder) 
<= width):
++                            cur_line.append(self.placeholder)
++                            lines.append(indent + ''.join(cur_line))
++                            break
++                        cur_len -= chunk.length()
++                        del cur_line[-1]
++                    else:
++                        if lines:
++                            prev_line = lines[-1].rstrip()
++                            if len(prev_line) + len(self.placeholder) <= 
self.width:
++                                lines[-1] = prev_line + self.placeholder
++                                break
++                        lines.append(indent + self.placeholder.lstrip())
++                    break
++
+         return lines
+ 
+     def _handle_long_word(self,  # type: ignore[no-untyped-def]
+@@ -223,7 +277,7 @@ class SequenceTextWrapper(textwrap.TextW
+         # If we're allowed to break long words, then do so: put as much
+         # of the next chunk onto the current line as will fit.
+ 
+-        if self.break_long_words:
++        if self.break_long_words and space_left > 0:
+             term = self.term
+             chunk = reversed_chunks[-1]
+             idx = nxt = seq_length = 0
+--- a/tests/accessories.py
++++ b/tests/accessories.py
+@@ -8,6 +8,7 @@ import traceback
+ import contextlib
+ import time
+ import signal
++import warnings
+ 
+ # local
+ from blessed import Terminal
+@@ -92,7 +93,10 @@ class as_subprocess():  # pylint: disabl
+             return
+ 
+         pid_testrunner = os.getpid()
+-        pid, master_fd = pty.fork()  # pylint: 
disable=possibly-used-before-assignment
++        with warnings.catch_warnings():
++            warnings.filterwarnings("ignore", category=DeprecationWarning)
++            pid, master_fd = pty.fork()  # pylint: 
disable=possibly-used-before-assignment
++
+         if pid == self._CHILD_PID:
+             # child process executes function, raises exception
+             # if failed, causing a non-zero exit code, using the
+@@ -321,12 +325,12 @@ def pty_test(child_func, parent_func=Non
+         result = child_func(term)
+         return result.decode('utf-8') if isinstance(result, bytes) else 
(result or '')
+ 
+-    import pty as pty_module  # pylint: disable=import-outside-toplevel
+-
+     if test_name is None:
+         test_name = getattr(child_func, '__name__', 'pty_test')
+ 
+-    pid, master_fd = pty_module.fork()
++    with warnings.catch_warnings():
++        warnings.filterwarnings("ignore", category=DeprecationWarning)
++        pid, master_fd = pty.fork()  # pylint: 
disable=possibly-used-before-assignment
+ 
+     # Set PTY window size in parent before child starts reading
+     if pid != 0:
+--- a/tests/test_wrap.py
++++ b/tests/test_wrap.py
+@@ -1,6 +1,7 @@
+ """Tests for Terminal.wrap()"""
+ 
+ # std imports
++import sys
+ import textwrap
+ 
+ # 3rd party
+@@ -19,6 +20,10 @@ TEXTWRAP_KEYWORD_COMBINATIONS = [
+     {'break_long_words': True, 'drop_whitespace': True, 'subsequent_indent': 
''},
+     {'break_long_words': True, 'drop_whitespace': False, 'subsequent_indent': 
' '},
+     {'break_long_words': True, 'drop_whitespace': True, 'subsequent_indent': 
' '},
++    {
++        'break_long_words': True, 'drop_whitespace': False,
++        'subsequent_indent': '', 'max_lines': 4, 'placeholder': '~',
++    },
+ ]
+ if TEST_QUICK:
+     # test only one feature: everything on
+@@ -71,6 +76,18 @@ def test_SequenceWrapper(many_columns, k
+         my_wrapped = term.wrap(pgraph, width=width, **kwargs)
+         my_wrapped_colored = term.wrap(pgraph_colored, width=width, **kwargs)
+ 
++        # Older versions of textwrap could leave a preceding all whitespace 
line
++        # https://github.com/python/cpython/issues/140627
++        if (
++            kwargs.get('drop_whitespace') and
++            sys.version_info[:2] < (3, 15) and
++            not internal_wrapped[0].strip()
++        ):
++            internal_wrapped = internal_wrapped[1:]
++            # # This also means any subsequent indent got applied to the 
first line
++            if kwargs.get('subsequent_indent'):
++                internal_wrapped[0] = 
internal_wrapped[0][len(kwargs['subsequent_indent']):]
++
+         # ensure we textwrap ascii the same as python
+         assert internal_wrapped == my_wrapped
+ 
+@@ -179,3 +196,41 @@ def test_greedy_join_with_cojoining():
+         assert result == ['ca', 'fe\u0301', '-l', 'at', 'te']
+ 
+     child()
++
++
++def test_placeholder():
++    """ENsure placeholder behavior matches stdlib"""
++
++    @as_subprocess
++    def child():
++        term = TestTerminal()
++        text = 'The quick brown fox jumps over the lazy dog'
++        kwargs = {'width': 1, 'max_lines': 3, 'placeholder': '...'}
++
++        try:
++            textwrap.wrap(text, **kwargs)
++        except Exception as e:  # pylint: disable=broad-exception-caught
++            stdlib_exc = e
++        else:
++            stdlib_exc = None
++
++        with pytest.raises(stdlib_exc.__class__) as exc:
++            term.wrap(text, **kwargs)
++        assert exc.value.args == stdlib_exc.args
++
++        kwargs = {'width': 10, 'max_lines': 3, 'placeholder': '...'}
++        assert term.wrap(text, **kwargs) == textwrap.wrap(text, **kwargs)
++
++        text = '1234567890 1234567890 extra'
++        kwargs = {'width': 10, 'max_lines': 2, 'placeholder': '...'}
++        assert term.wrap(text, **kwargs) == textwrap.wrap(text, **kwargs)
++
++        text = '1234567890 1234567890'
++        kwargs = {'width': 10, 'max_lines': 1, 'placeholder': '...'}
++        assert term.wrap(text, **kwargs) == textwrap.wrap(text, **kwargs)
++
++        text = 'short 1234567890 extra'
++        kwargs = {'width': 10, 'max_lines': 2, 'placeholder': '...'}
++        assert term.wrap(text, **kwargs) == textwrap.wrap(text, **kwargs)
++
++    child()
diff -Nru python-blessed-1.25/debian/patches/series 
python-blessed-1.25/debian/patches/series
--- python-blessed-1.25/debian/patches/series   2025-12-24 15:53:31.000000000 
+0100
+++ python-blessed-1.25/debian/patches/series   2026-09-02 16:19:03.000000000 
+0200
@@ -1 +1,2 @@
 0001-Get-rid-of-sphinxcontrib-manpage-needs-for-now.patch
+0002-Update-wrap-logic-and-add-optional-testing-for-Python-3.15.patch
diff -Nru python-blessed-1.25/debian/rules python-blessed-1.25/debian/rules
--- python-blessed-1.25/debian/rules    2025-12-24 16:26:02.000000000 +0100
+++ python-blessed-1.25/debian/rules    2026-09-02 16:19:03.000000000 +0200
@@ -14,5 +14,5 @@
 
 override_dh_auto_test:
 ifeq (,$(filter nocheck,$(DEB_BUILD_OPTIONS)))
-       PYBUILD_SYSTEM=custom PYBUILD_TEST_ARGS="{interpreter} -m pytest -v -x 
-rs -k 'not SequenceWrapper'" dh_auto_test
+       PYBUILD_SYSTEM=custom PYBUILD_TEST_ARGS="{interpreter} -m pytest -v -x 
-rs tests" dh_auto_test
 endif
diff -Nru python-blessed-1.25/debian/tests/python3-blessed 
python-blessed-1.25/debian/tests/python3-blessed
--- python-blessed-1.25/debian/tests/python3-blessed    2025-12-24 
16:26:02.000000000 +0100
+++ python-blessed-1.25/debian/tests/python3-blessed    2026-09-02 
16:19:03.000000000 +0200
@@ -7,5 +7,5 @@
 ln -s /usr/lib/python3/dist-packages/blessed blessed
 
 for python3 in $python3_versions; do
-    $python3 -m pytest -v -x -rs -k 'not SequenceWrapper' || exit 1
+    $python3 -m pytest -v -x -rs tests || exit 1
 done

--- End Message ---
--- Begin Message ---
Source: python-blessed
Source-Version: 1.25-2
Done: Alexandre Detiste <[email protected]>

We believe that the bug you reported is fixed in the latest version of
python-blessed, which is due to be installed in the Debian FTP archive.

A summary of the changes between this version and the previous one is
attached.

Thank you for reporting the bug, which will now be closed.  If you
have further comments please address them to [email protected],
and the maintainer will reopen the bug report if appropriate.

Debian distribution maintenance software
pp.
Alexandre Detiste <[email protected]> (supplier of updated python-blessed 
package)

(This message was generated automatically at their request; if you
believe that there is a problem with it please contact the archive
administrators by mailing [email protected])


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

Format: 1.8
Date: Mon, 05 Oct 2026 00:39:49 +0200
Source: python-blessed
Architecture: source
Version: 1.25-2
Distribution: unstable
Urgency: medium
Maintainer: Debian Python Team <[email protected]>
Changed-By: Alexandre Detiste <[email protected]>
Closes: 1146532
Changes:
 python-blessed (1.25-2) unstable; urgency=medium
 .
   * Team Upload
   * build-depends on python3-flit instead of the whole 'flit' toolbox
   * Salsa CI: test nocheck & nodoc profiles
 .
   [ Maximiliano Curia ]
   * Run tests against the tests directory
     (otherwise a patch in the tests tries to run the tests in .pc)
   * Avoid FTBFS with python 3.15 (Closes: #1146532)
Checksums-Sha1:
 1a50d4ded271dceb0c9489e85cdbae2f197b5f33 2504 python-blessed_1.25-2.dsc
 90fab87f539a6f51dcdbb10c4b3f40e9b1403ce0 9396 
python-blessed_1.25-2.debian.tar.xz
 87eba7d4d64088a49cd74d6a2812626cc6449c89 9764 
python-blessed_1.25-2_source.buildinfo
Checksums-Sha256:
 f978e71a7abf2c8e2bd39238414be75a22a58058fbd91844d28942b29d7edf5e 2504 
python-blessed_1.25-2.dsc
 40e56f68d8ef47db91ae020f45199d7959a1adfbeebec14b48729571cf90efe8 9396 
python-blessed_1.25-2.debian.tar.xz
 10b255fa613376feb4a245b250158926a276d6adf3d2446e21f1a4b81a4ae9d6 9764 
python-blessed_1.25-2_source.buildinfo
Files:
 cd5e78efae91130375d3f215d3cd3cd9 2504 python optional python-blessed_1.25-2.dsc
 2116c92e152b8a07766a5bd3e9da0f69 9396 python optional 
python-blessed_1.25-2.debian.tar.xz
 f4a45179d6a4080ca85295b1a67c81b1 9764 python optional 
python-blessed_1.25-2_source.buildinfo

-----BEGIN PGP SIGNATURE-----

iQJFBAEBCgAvFiEEj23hBDd/OxHnQXSHMfMURUShdBoFAmrC3BgRHHRjaGV0QGRl
Ymlhbi5vcmcACgkQMfMURUShdBqy4A//WKKr6UJWUWrPrRnKlGMsJupaLlVhQxzK
K4F64X5GEieWZiXXLehYjV15H4Nq4boQyqj+bx2n1t7vwqsBHHuI+sh3VqMJIbGS
Qq2vze43Y1kkkv6TAZxqvW4ehPIhGi7LiFlCXqJcGv/SCVScVzpgdzMpuC9TSNDn
VryzWcWXIixxMnmb1De5mFzCu+pCDamtI2g59QhNBXaQ0X6uLcGrombEpWBiFL0Z
VZ0u4qU9oDBnQhkv22S/WgIZdc4FOKFzo/oPbozRqzlCT9gK/snqISJMuVwmiSSz
bH19HYipiCm2aQ4jwfhmqA3LL6HgHjsq59lTe4pkjWZudql8rEaXTlFQrSZojeoY
M8wqUacFh7hR506e1401+Tmtrxf+9p73PfLEYdmwirG7PgkDxgpn50kNS1Wj5yD8
8iVTNraAQslYsfQ+utLdlxhK+LnVOYGLALSPi9nxuSqYwypD26cAu+66stKm8una
Cts7EgycR3+hBfDmg2UJ5JytG89/3fsD04rZlWYXnZ/X4lSTkNaiR5xNKj7ud2Ke
Q/mU5MGbW6BOUfD0ng6Xb4+ZNw8i1u5mZCcQh3N8yMlGTOQBKQ9+8/PHayhMedhP
tpmpYg4LVPfsxDOp86OlJtVX4Fh+8nF+zuv7BL9mkv2GSJ+Lpa+uu8GlkPUBYWlE
F3EwK1k6Fts=
=hQZ9
-----END PGP SIGNATURE-----

Attachment: pgpcjrKLJYXWh.pgp
Description: PGP signature


--- End Message ---

Reply via email to