fix: Char namedtuple save/restore — use blink not width, construct new Char objects

pyte.screens.Char is a namedtuple (immutable), so fields can't be
mutated directly. Also 'width' doesn't exist — the correct field is
'blink'. Now creates new Char(...) objects for buffer restoration.
Fixes server switching being completely broken (AttributeError on save).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
chrome-storm-c442
2026-02-24 03:25:36 -05:00
parent afa75b6d9c
commit 4b505f39d1
2 changed files with 12 additions and 11 deletions

View File

@@ -364,6 +364,7 @@ class TerminalWidget(tk.Frame):
def get_current_buffer(self) -> bytes:
"""Export full pyte screen state as serialized data for session pool."""
import pickle
from pyte.screens import Char
screen_state = {
'buffer': {},
@@ -380,11 +381,12 @@ class TerminalWidget(tk.Frame):
line_dict = {}
for x in range(self._screen.columns):
c = self._screen.buffer[y][x]
# Char is a namedtuple — store all fields
line_dict[x] = {
'data': c.data, 'fg': c.fg, 'bg': c.bg,
'bold': c.bold, 'italics': c.italics,
'underscore': c.underscore, 'reverse': c.reverse,
'strikethrough': c.strikethrough, 'width': c.width,
'strikethrough': c.strikethrough, 'blink': c.blink,
}
screen_state['buffer'][y] = line_dict
@@ -393,6 +395,7 @@ class TerminalWidget(tk.Frame):
def restore_buffer(self, buffer_data: bytes):
"""Restore full pyte screen state from serialized data."""
import pickle
from pyte.screens import Char
try:
state = pickle.loads(buffer_data)
@@ -403,22 +406,20 @@ class TerminalWidget(tk.Frame):
self._screen.reset()
self._screen.resize(rows, cols)
# Char is a namedtuple — must replace entire objects
for y, line_dict in state['buffer'].items():
if y >= self._screen.lines:
continue
for x, cd in line_dict.items():
if x >= self._screen.columns:
continue
ch = self._screen.buffer[y][x]
ch.data = cd['data']
ch.fg = cd['fg']
ch.bg = cd['bg']
ch.bold = cd['bold']
ch.italics = cd['italics']
ch.underscore = cd['underscore']
ch.reverse = cd['reverse']
ch.strikethrough = cd['strikethrough']
ch.width = cd['width']
self._screen.buffer[y][x] = Char(
data=cd['data'], fg=cd['fg'], bg=cd['bg'],
bold=cd['bold'], italics=cd['italics'],
underscore=cd['underscore'], reverse=cd['reverse'],
strikethrough=cd['strikethrough'],
blink=cd.get('blink', False),
)
self._screen.cursor.x = state.get('cursor_x', 0)
self._screen.cursor.y = state.get('cursor_y', 0)