Breaking Changes ⚠
- Drop Python 3.9 and 3.10: urwid requires Python 3.11 or newer by @penguinolog in #1401
- Allow display attributes to inherit colors and settings: canvas content and
Text.get_text()carryLayeredAttrfor nested attributes, custom screens have to callBaseScreen.resolve_attr()instead of reading the palette, and an attribute anAttrMapmaps toNoneshows the map'sNoneattribute by @penguinolog in #1409 - 🗹
AttrSpecforeground and background default to'inherit'; also a new feature, see "Major features" below: Draw OSC 8 hyperlinks from display attributes by @penguinolog in #1415 - Drop code planned for removal in 5.0: the
Columns,Pile,GridFlow,FrameandListBoxget_focus/set_focusmethods and 1.1-era list attributes, theFrameheader/body/footer getters and setters,ListBox.contents()called as a method,content_delta,shards_delta,shard_cviews_delta,BaseScreen.run_wrapper,font.add_font,WidgetWrap._set_w,AttrWrap.wandFiller.body;MonitoredDeque.insert()with an index without__index__raisesTypeErrorby @penguinolog in #1402 - ⚡ Remove the
vtermescape compatibility constants and plain-tupleCSI_COMMANDSentries, returnWHSettingsmembers fromPile.options()for'given'and'weight', and requiretyping_extensionson Python older than 3.13; also see "Deprecations" below: Unify deprecation warnings and removal versions by @penguinolog in #1421 - Stop re-exporting unrelated names from
urwid.graphicsby @penguinolog in #1163 - 🗹
ANSITextkeeps bold as a setting of its own:ESC[1;31mis'dark red,bold', no longer'light red,bold'; also a new feature, see "New features" below: Read the raw display's attributes back in ANSIText by @penguinolog in #1502 - 🗹 The raw display can detect more colors than before: the
colorscapability of the terminfo entry raises the count (mintty,vscodeand others from 16 to 256); also a new feature, see "New features" below: Read colour depth from terminfo in the raw display by @penguinolog in #1464 - 🗹 Pickles of
MonitoredListwritten at protocol 2 or higher no longer load in older urwid releases; also a new feature, see "New features" below: Make focus lists and list walkers picklable by @penguinolog in #1469 - 🕷
Terminalreturns a key with noTERM=linuxform (shift up,meta f5,focus in) unhandled instead of typing its name into the child; also bug fixes, see "Bug fixes" below by @luantaraschi in #1473 and by @penguinolog in #1498 - Drop GraalPy 3.11 (GraalPy 24): its
osmodule has noO_NOFOLLOWand its ASCII and Latin-1 codecs ignore registered error handlers. GraalPy 3.12 stays experimental, and GraalPy 3.13 is listed as experimental too by @penguinolog in #1510
Major features 🗹
- ⚠ Draw OSC 8 hyperlinks from display attributes (
Hyperlink,AttrSpec(hyperlink=...),set_terminal_properties(hyperlinks=True)); see "Breaking Changes" above by @penguinolog in #1415 - Parse OSC 8 hyperlinks in ANSIText and Terminal by @penguinolog in #1419
- Report extended keys via the kitty and modifyOtherKeys protocols:
Screen(extended_keys=True)tellsctrl ifromtabandctrl enterfromenter, and adds thesuperandhypermodifiers by @penguinolog in #1504 - Alternate screen and kitty keyboard protocol in Terminal by @penguinolog in #1505
- Forward mouse events to the Terminal child by @penguinolog in #1501
- Add DropDown choice widget and anchored pop-up placement by @penguinolog in #1471
- Add
urwid.testing: render widgets to text and attribute runs, check their sizing, feed keys and mouse events, and run aMainLooponScriptedScreenwithout a terminal by @penguinolog in #1481 - Add
MainLoop.paused()to run another program, such as$EDITOR, in the terminal by @penguinolog in #1485 - Add tree navigation helpers and keyword-only walker positions by @penguinolog in #1451
- Add opt-in Tab navigation to standard containers:
Pile,Columns,Frame,ListBoxandGridFlowcreated withselect_navigation=Truemove the focus ontab,shift tab,ctrl nandctrl p;SelectNavigationMixinandSelectNavigationListContentsMixingive other containers the same behaviour by @penguinolog in #1478
New features 🗹
- Add ScrollBar visible option and fix scrollbar mouse handling by @penguinolog in #1462
- Add ScrollBar end markers and attributes by @penguinolog in #1470
- Render ListBox and ScrollBar at a flow size by @penguinolog in #1488
- ⚠ Read colour depth from terminfo in the raw display, and add
detect_term_colors(); see "Breaking Changes" above by @penguinolog in #1464 and in #1466 - ⚠ Make focus lists and list walkers picklable; see "Breaking Changes" above by @penguinolog in #1469
- Add
set_ascii_fallbacks()for characters the encoding rejects by @penguinolog in #1479 - Add
CommandMap.bind()that refuses a key bound twice by @penguinolog in #1472 - Accept plain foreground canvases in CanvasOverlay by @IlyaKhalafi in #1428
- Name DEC private modes and act on DECRQM replies by @penguinolog in #1500
- ⚠ Read the raw display's attributes back in ANSIText; see "Breaking Changes" above by @penguinolog in #1502
- Add PopUpLauncher
close_on_menu,pop_up_widgetandlauncher_sizeby @penguinolog in #1513 - Add
ListBox.scroll_to_top(),scroll_to_bottom()andfocus_next_match()by @penguinolog in #1514 - Add
Edit.set_edit_text(..., edit_pos=...), theEditsignal"submit"and readline editing commands forEditby @penguinolog in #1515 - Add
follow_endtoSimpleFocusListWalker,SimpleFocusDequeWalker,MonitoredFocusListandMonitoredFocusDequeby @penguinolog in #1516 - Add
Text(..., selectable=True),SelectableIcon(cursor_position=None)andButtonleft,rightandcursor_positionby @penguinolog in #1517 - Add
WidgetDisable(..., disabled=False)and a settableWidgetDisable.disabledproperty by @penguinolog in #1518 LineBoxtitles accept text markup:LineBox(w, title=[("key", "F1"), " Help"])andset_title()by @penguinolog in #1519- Add
ListBox(..., focus_when_empty=False), so an empty list does not take the focus, and an opt-indelegate_selectablethat makesScrollBarandScrollablereport the wrapped widget'sselectable()by @penguinolog in #1520 - Add the
Thin5x4FontBigText font, letters forHalfBlock6x5FontandHalfBlockHeavy6x5Font, and the missing ASCII punctuation for every BigText font that has letters by @penguinolog in #1521 - Add
Edit(..., max_length=None)and a settableEdit.max_lengthproperty: a key that would go over it is returned unhandled, and longer text from the constructor,set_edit_text()orinsert_text(), or a limit below the current text, raisesValueErrorby @penguinolog in #1524 - Add the
"focus changed"signal toPile,ColumnsandGridFlow, sent with the old and the new focus position after the focus moved, andMonitoredFocusList.set_focus_moved_callback()by @penguinolog in #1528
Deprecations ⚡
- ⚠ Unify deprecation warnings and removal versions: every deprecation names its removal release, and APIs still used by pudb, mitmproxy, khal, zulip-terminal and others are postponed to 7.0; also removes APIs, see "Breaking Changes" above by @penguinolog in #1421
- Deprecate a positional
reverseinpositions()of theSimple*ListWalkerandSimple*DequeWalkerclasses (removal in 8.0) by @penguinolog in #1451 - Deprecate the private
_MOUSE_*_FLAGconstants in favour ofMouseBit(removal in 6.0) by @penguinolog in #1500
Bug fixes 🕷
Text layout and canvas rendering
- Do not crash on a zero-width line with clip or ellipsis wrap by @luantaraschi in #1403
- Do not crash on zero-width text before a break in wrap modes by @penguinolog in #1404
- Fix
shard_tailgap errors from canvas shards of no rows by @penguinolog in #1483 - Fix the ListBox
rows_maxcache and overlays of rowless canvases by @penguinolog in #1486 - Keep mixed-width characters in place on the last screen row by @nk-batman21 in #1506
- Keep zero-width runs and raw sequences intact on the last row by @penguinolog in #1511
Raw and curses displays
- Fix terminal input after stop and Linux console palette by @penguinolog in #1463
- Keep mouse tracking across a screen stop and restart by @penguinolog in #1484
- Fix the swapped 80x24 fallback size in raw displays by @penguinolog in #1491
- Use and track the visible Windows console window size by @penguinolog in #1492
- Fix BytesWarning when restoring tty signal keys by @luantaraschi in #1448
- Fix bytes/str leftovers and typing in displays and event loops by @penguinolog in #1456
- Fix curses input waits longer than 25.5 seconds by @hengweiyv in #1394
Escape sequences and key decoding
- Fix escape sequence handling in Terminal, ANSIText and raw display by @penguinolog in #1497
- Strip whole CSI sequences with sub-parameters or intermediate bytes by @nk-batman21 in #1496
- Decode st Insert and Delete key sequences by @IlyaKhalafi in #1423
- Decode modified Insert and the remaining xterm keypad keys by @penguinolog in #1499
Terminal widget
- Fix vterm hangs, crashes and leaks by @penguinolog in #1406
- ⚠ Send ESC before the key for meta keys in Terminal; see "Breaking Changes" above by @luantaraschi in #1473
- ⚠ Send Terminal keys as
TERM=linuxdefines them; see "Breaking Changes" above by @penguinolog in #1498 - Cancel a pending wrap when the Terminal cursor moves by @ybai08 in #1474
- Do not scroll the Terminal region when wrapping below it by @ybai08 in #1475
- Fix Terminal keypress before the first render by @penguinolog in #1490
Event loops
- Skip closing an already closed asyncio loop in
__del__by @penguinolog in #1417 - Log and survive exceptions raised by alarm callbacks by @charan-rathore in #1418
- Run expired select alarms while input stays readable by @IlyaKhalafi in #1424
- Run expired ZMQ alarms while input stays readable by @IlyaKhalafi in #1427
- Fix event loop callback races and idle handling by @penguinolog in #1461
- Wait for input on a descriptor opened from
/dev/ttyon macOS, whichkqueuerefuses withEINVAL, inSelectEventLoopand the raw display by falling back toselect()by @penguinolog in #1522
Containers, lists and walkers
- Use the index protocol in monitored containers by @IlyaKhalafi in #1441
- Preserve deque walker bounds when copying by @IlyaKhalafi in #1446
- Preserve focused object identity when sorting by @IlyaKhalafi in #1454
- Notify after partially extending a list by @IlyaKhalafi in #1460
- Preserve focus for empty forward slices by @IlyaKhalafi in #1455
- Preserve nested focus after undirected ListBox jumps by @IlyaKhalafi in #1425
- Return Tab at the ends of a
wrap_aroundwalker in ListBox by @penguinolog in #1495 - Keep the correct parent during offscreen tree navigation by @IlyaKhalafi in #1431
- Fix Columns cursor and positions for hidden columns by @penguinolog in #1467
- Stop
base_widgetat mock objects by @penguinolog in #1468 - Pickle widgets with protocols 0 and 1 on GraalPy, which built them from
typing.Genericand failed by @penguinolog in #1510 - Report a
GridFlowmouse event as handled only when a cell handled it or the focus moved, so a parentListBoxscrolls on the wheel over it; a click on empty space now reachesunhandled_input, as forPileandColumnsby @penguinolog in #1526 - Fix the errors that precise widget typing exposed:
FrameandOverlayget_cursor_coords()andget_focus_path()no longer crash on a missing focus part or a top widget without a cursor,Columns.pack(())raisesColumnsError, an unknownfocus_columnraisesValueError,TreeListBox.focus_end()andFiller.move_cursor_to_coords()no longer use the column count as the row count,Overlayrejectsclipandweightwidths andflowandweightheights, andPileandColumnsreject a float'given'amount by @penguinolog in #1443 - Skip a child sized
(GIVEN, 0), which is not drawn, when the arrow keys or Tab move the focus inPile,ColumnsandGridFlowby @penguinolog in #1526
ScrollBar
- Fix ScrollBar keypress before the first render by @penguinolog in #1465
- Render ScrollBar with no rows at a size of no rows by @penguinolog in #1482
Edit widget
- Move the
Editcursor before"postchange"is sent for an editing key, throughset_edit_pos()so that an override still sees every move by @penguinolog in #1523 - Scroll a focused
Editwithwrap="ellipsis"to the cursor: the row with the cursor is clipped and the other rows keep their ellipsis by @penguinolog in #1523
Numeric edit widgets
- Accept negative string defaults in IntegerEdit by @IlyaKhalafi in #1436
- Apply FloatEdit separators to default values by @IlyaKhalafi in #1434
- Fix FloatEdit exponent defaults and long-value quantization by @charan-rathore in #1447
- Refuse a second decimal separator in FloatEdit by @nk-batman21 in #1493
- Keep a lone zero in numeric edit widgets by @nk-batman21 in #1487
- Trim leading zeros after the minus sign in NumEdit by @penguinolog in #1489
- Send
IntEditchange signals at most once per key: not again for the leading zeros it removes, and not at all when the text stays the same by @penguinolog in #1523
Progress bar
- Preserve Unicode labels in progress bars by @IlyaKhalafi in #1432
- Fix early completion for very large finite progress values by @charan-rathore in #1507
BigText fonts
- Draw
0,S,Iand|of the BigText fonts apart fromO,5andl, which they matched, and slope the Half Block 5x4 backtick the right way by @penguinolog in #1521
Other displays and utilities
- Send the web display's "polling child" update as UTF-8 bytes, which
socket.sendall()requires, watch the LCD serial port by itsfileno(), and stopsplit_reprfrom recursing in subclasses by @penguinolog in #1410
Documentation 🕮
- Complete the parameter, return, exception and warning fields in docstrings by @penguinolog in #1494
- Forward the mouse to the child in the terminal demo by @penguinolog in #1503
- Document receiving Ctrl+S and Ctrl+Q as keys through
tty_signal_keys(start="undefined", stop="undefined")by @penguinolog in #1293
Refactoring 🛠
- Cover all refurb warnings by @penguinolog in #1185
New Contributors
- @hengweiyv made their first contribution in #1394
- @IlyaKhalafi made their first contribution in #1424
- @ybai08 made their first contribution in #1474
- @nk-batman21 made their first contribution in #1487
Full Changelog: 4.2.5...5.0.0