github urwid/urwid 5.0.0

10 hours ago

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() carry LayeredAttr for nested attributes, custom screens have to call BaseScreen.resolve_attr() instead of reading the palette, and an attribute an AttrMap maps to None shows the map's None attribute by @penguinolog in #1409
  • 🗹 AttrSpec foreground 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, Frame and ListBox get_focus/set_focus methods and 1.1-era list attributes, the Frame header/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.w and Filler.body; MonitoredDeque.insert() with an index without __index__ raises TypeError by @penguinolog in #1402
  • ⚡ Remove the vterm escape compatibility constants and plain-tuple CSI_COMMANDS entries, return WHSettings members from Pile.options() for 'given' and 'weight', and require typing_extensions on 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.graphics by @penguinolog in #1163
  • 🗹 ANSIText keeps bold as a setting of its own: ESC[1;31m is '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 colors capability of the terminfo entry raises the count (mintty, vscode and 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 MonitoredList written 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
  • 🕷 Terminal returns a key with no TERM=linux form (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 os module has no O_NOFOLLOW and 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) tells ctrl i from tab and ctrl enter from enter, and adds the super and hyper modifiers 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 a MainLoop on ScriptedScreen without 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, ListBox and GridFlow created with select_navigation=True move the focus on tab, shift tab, ctrl n and ctrl p; SelectNavigationMixin and SelectNavigationListContentsMixin give 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_widget and launcher_size by @penguinolog in #1513
  • Add ListBox.scroll_to_top(), scroll_to_bottom() and focus_next_match() by @penguinolog in #1514
  • Add Edit.set_edit_text(..., edit_pos=...), the Edit signal "submit" and readline editing commands for Edit by @penguinolog in #1515
  • Add follow_end to SimpleFocusListWalker, SimpleFocusDequeWalker, MonitoredFocusList and MonitoredFocusDeque by @penguinolog in #1516
  • Add Text(..., selectable=True), SelectableIcon(cursor_position=None) and Button left, right and cursor_position by @penguinolog in #1517
  • Add WidgetDisable(..., disabled=False) and a settable WidgetDisable.disabled property by @penguinolog in #1518
  • LineBox titles accept text markup: LineBox(w, title=[("key", "F1"), " Help"]) and set_title() by @penguinolog in #1519
  • Add ListBox(..., focus_when_empty=False), so an empty list does not take the focus, and an opt-in delegate_selectable that makes ScrollBar and Scrollable report the wrapped widget's selectable() by @penguinolog in #1520
  • Add the Thin5x4Font BigText font, letters for HalfBlock6x5Font and HalfBlockHeavy6x5Font, and the missing ASCII punctuation for every BigText font that has letters by @penguinolog in #1521
  • Add Edit(..., max_length=None) and a settable Edit.max_length property: a key that would go over it is returned unhandled, and longer text from the constructor, set_edit_text() or insert_text(), or a limit below the current text, raises ValueError by @penguinolog in #1524
  • Add the "focus changed" signal to Pile, Columns and GridFlow, sent with the old and the new focus position after the focus moved, and MonitoredFocusList.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 reverse in positions() of the Simple*ListWalker and Simple*DequeWalker classes (removal in 8.0) by @penguinolog in #1451
  • Deprecate the private _MOUSE_*_FLAG constants in favour of MouseBit (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_tail gap errors from canvas shards of no rows by @penguinolog in #1483
  • Fix the ListBox rows_max cache 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

Escape sequences and key decoding

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=linux defines 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/tty on macOS, which kqueue refuses with EINVAL, in SelectEventLoop and the raw display by falling back to select() 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_around walker 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_widget at mock objects by @penguinolog in #1468
  • Pickle widgets with protocols 0 and 1 on GraalPy, which built them from typing.Generic and failed by @penguinolog in #1510
  • Report a GridFlow mouse event as handled only when a cell handled it or the focus moved, so a parent ListBox scrolls on the wheel over it; a click on empty space now reaches unhandled_input, as for Pile and Columns by @penguinolog in #1526
  • Fix the errors that precise widget typing exposed: Frame and Overlay get_cursor_coords() and get_focus_path() no longer crash on a missing focus part or a top widget without a cursor, Columns.pack(()) raises ColumnsError, an unknown focus_column raises ValueError, TreeListBox.focus_end() and Filler.move_cursor_to_coords() no longer use the column count as the row count, Overlay rejects clip and weight widths and flow and weight heights, and Pile and Columns reject 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 in Pile, Columns and GridFlow by @penguinolog in #1526

ScrollBar

Edit widget

  • Move the Edit cursor before "postchange" is sent for an editing key, through set_edit_pos() so that an override still sees every move by @penguinolog in #1523
  • Scroll a focused Edit with wrap="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

Progress bar

BigText fonts

  • Draw 0, S, I and | of the BigText fonts apart from O, 5 and l, 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 its fileno(), and stop split_repr from 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 🛠

New Contributors

Full Changelog: 4.2.5...5.0.0

Don't miss a new urwid release

NewReleases is sending notifications on new releases.