Fix break_pane forcing 'libtmux' window name on tmux 3.7a/3.7b#699
Merged
Conversation
why: On tmux 3.7a/3.7b, break_pane() without window_name forces the
"libtmux" placeholder as the window name instead of tmux's default.
has_version("3.7") matches 3.7a/3.7b because get_version() strips the
letter suffix, so the 3.7 crash workaround still fires even though the
crash was fixed in 3.7a.
what:
- Add test_break_pane_no_name_uses_natural_name asserting the natural
name ("sleep"), not the placeholder
- Mark strict xfail gated on has_version("3.7") -- the buggy 3.7 family
- Import has_version in test_pane.py
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #699 +/- ##
==========================================
- Coverage 51.89% 51.78% -0.11%
==========================================
Files 25 25
Lines 3623 3638 +15
Branches 733 733
==========================================
+ Hits 1880 1884 +4
- Misses 1439 1448 +9
- Partials 304 306 +2 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
why: break_pane() without window_name forced the "libtmux" placeholder
on tmux 3.7a/3.7b. The crash workaround is gated on has_version("3.7"),
which matches 3.7a/3.7b because get_version() strips the letter suffix
-- but those releases already fixed the crash, so the placeholder leaked
as the window name instead of tmux's default.
what:
- Narrow breaks_without_name to the literal 3.7 release via the raw
tmux -V string (only checked when has_version("3.7") already matched)
- 3.7a/3.7b/master now keep tmux's auto-generated window name
- Correct the stale "gated on exactly 3.7" comment
why: The natural-name regression test is no longer expected to fail -- the fix keeps tmux's default window name on 3.7a/3.7b, so the strict xfail now XPASSes and must be removed. what: - Remove the strict xfail from test_break_pane_no_name_uses_natural_name - Revert the now-unused has_version import
why: break_pane() gated its 3.7 crash workaround on has_version("3.7")
and then ran a second, un-memoized `tmux -V` to recover the letter
suffix get_version() strips -- so every call forked `tmux -V` again.
what:
- Extract an uncached _query_version() and layer both get_version and a
new memoized get_version_str() on it, so `tmux -V` runs once per
process regardless of how many callers need the raw version
- break_pane() now gates on get_version_str(...) == "3.7" (one memoized
lookup, no per-call fork); behavior is unchanged
- Flush get_version_str's cache in the autouse test fixture
tony
force-pushed
the
fix/break-pane-3.7-placeholder-name
branch
from
July 4, 2026 11:20
c94c26b to
0d998db
Compare
Member
Author
Code reviewNo issues found. Checked for bugs and CLAUDE.md compliance. 🤖 Generated with Claude Code |
why: break_pane needs the raw tmux version string (letter suffix intact) to gate its workaround on the literal 3.7 release, which get_version can't express -- it strips the suffix for numeric comparison. get_version also re-detected the OpenBSD "<max>-openbsd" synthetic by string value, which could diverge from the pre-refactor result on a contrived token. what: - Route the OpenBSD/no--V fallback through a private _TmuxVersionUnavailable signal so get_version applies re.sub to real version tokens only -- byte-identical to master across every tmux -V variation (real releases, master, next-3.8, openbsd, error paths) - get_version and get_version_str are two plain @functools.cache functions with native cache_clear()/cache_info(), no shared-cache machinery - conftest clears both independent caches; format-tokens documents both
tony
force-pushed
the
fix/break-pane-3.7-placeholder-name
branch
from
July 4, 2026 12:37
b928ed3 to
71fe4cf
Compare
why: The new public raw-version helper is a user-facing addition on this branch and belongs under What's new. what: - Add ### What's new note for get_version_str() above the break_pane fix
tony
added a commit
to tmux-python/tmuxp
that referenced
this pull request
Jul 4, 2026
libtmux 0.61.0 hardens support for the tmux 3.7 patch line. tmuxp inherits the fix and adopts the one new helper it benefits from, so `tmuxp debug-info` now reports the exact tmux patch release. - **Bump**: libtmux `~=0.60.0` -> `~=0.61.0`; no breaking changes, tmux 3.2a-3.6 unaffected. - **debug-info**: report the raw tmux version, keeping the point-release letter (`3.7a`/`3.7b`) via libtmux's new `get_version_str()`. `get_version()` strips the letter for numeric comparison, so bug reports previously lost the exact patch release -- which can differ in behavior. - **Inherited fix**: libtmux's `Pane.break_pane()` keeps tmux's own default window name on tmux 3.7a/3.7b; tmuxp never calls `break_pane`, so this is behavior-only. `plugin.py` keeps `get_version()` for `LooseVersion` version-gate comparisons, where the letter suffix must not participate in ordering. Release: https://github.com/tmux-python/libtmux/releases/tag/v0.61.0 Changelog: https://libtmux.git-pull.com/history.html#libtmux-0-61-0-2026-07-04 See also: tmux-python/libtmux#699, tmux-python/libtmux#698
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Pane.break_pane()forcing the window name tolibtmuxon tmux 3.7a/3.7b when called without an explicitwindow_name— it now keeps tmux's natural auto-name.libtmux.common.get_version_str()— the raw tmux version string with its point-release suffix intact ("3.7a"), for telling patch releases apart whereget_version()can't.@functools.cachehelpers;get_versionoutput stays byte-identical.The bug
break_pane()works around a tmux 3.7 NULL-deref (break-pane with no-ncrashes the server) by injecting a placeholder-n libtmuxand renaming afterward. The gate washas_version("3.7")— butget_version()strips the letter suffix for numeric comparison, so it also matched 3.7a/3.7b, where the crash was already reverted upstream (tmux166267c8, shipped in 3.7a). With no explicit name, the placeholder leaked as the window name.Shipped in v0.59.0/v0.60.0. Reproduced on tmux 3.7b: an unnamed
break_pane()produced a window namedlibtmuxinstead of the running command's name.The fix
Gate the workaround on the raw version string being exactly
"3.7"— which the numericget_version()can't express.get_version_str()exposes that raw token, andbreak_panenow comparesget_version_str(...) == "3.7", so 3.7a/3.7b (and master, and older tmux) keep tmux's natural window naming.Version-cache design
get_versionandget_version_strare two plain@functools.cachefunctions deriving from a shared uncached_query_version, each with native.cache_clear()/.cache_info()— no shared-cache machinery, noobject.__setattr__, no callable-class wrapper.get_versionstays byte-identical across everytmux -Vvariation (real releases,master,next-3.8, OpenBSD, and both error paths); the OpenBSD/no--Vsynthetic is distinguished by control flow (an internal exception), not a value sentinel that could collide.Test plan
test_break_pane_no_name_uses_natural_name— regression test, added as a strictxfailthen un-xfail'd once the fix landed (the fix commit's CI went red on exactly the 3.7a/3.7b cells, proving it)get_versionverified byte-identical to the prior implementation across alltmux -Vvariationsuv run mypy src testsclean (zero# type: ignore);ruffcleanget_version/get_version_strrender in the API docs with signatures