urwid 2.6.16__py3-none-any.whl → 3.0.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of urwid might be problematic. Click here for more details.

Files changed (53) hide show
  1. urwid/__init__.py +1 -4
  2. urwid/canvas.py +19 -38
  3. urwid/command_map.py +4 -3
  4. urwid/container.py +1 -1
  5. urwid/decoration.py +1 -1
  6. urwid/display/_raw_display_base.py +8 -5
  7. urwid/display/_win32_raw_display.py +11 -13
  8. urwid/display/common.py +26 -55
  9. urwid/display/curses.py +1 -1
  10. urwid/display/escape.py +6 -8
  11. urwid/display/lcd.py +4 -6
  12. urwid/display/web.py +7 -12
  13. urwid/event_loop/asyncio_loop.py +33 -15
  14. urwid/event_loop/main_loop.py +13 -18
  15. urwid/event_loop/tornado_loop.py +4 -5
  16. urwid/event_loop/trio_loop.py +1 -1
  17. urwid/font.py +10 -15
  18. urwid/signals.py +2 -1
  19. urwid/str_util.py +15 -18
  20. urwid/text_layout.py +6 -7
  21. urwid/util.py +6 -17
  22. urwid/version.py +9 -4
  23. urwid/vterm.py +9 -44
  24. urwid/widget/__init__.py +0 -6
  25. urwid/widget/attr_wrap.py +8 -10
  26. urwid/widget/bar_graph.py +2 -7
  27. urwid/widget/big_text.py +9 -7
  28. urwid/widget/box_adapter.py +4 -4
  29. urwid/widget/columns.py +50 -81
  30. urwid/widget/container.py +29 -75
  31. urwid/widget/edit.py +8 -8
  32. urwid/widget/filler.py +6 -6
  33. urwid/widget/frame.py +28 -37
  34. urwid/widget/grid_flow.py +24 -109
  35. urwid/widget/line_box.py +13 -0
  36. urwid/widget/listbox.py +12 -50
  37. urwid/widget/monitored_list.py +6 -4
  38. urwid/widget/overlay.py +4 -37
  39. urwid/widget/padding.py +11 -48
  40. urwid/widget/pile.py +177 -156
  41. urwid/widget/popup.py +2 -2
  42. urwid/widget/progress_bar.py +0 -10
  43. urwid/widget/scrollable.py +24 -32
  44. urwid/widget/treetools.py +27 -48
  45. urwid/widget/widget.py +7 -124
  46. urwid/widget/widget_decoration.py +4 -33
  47. urwid/wimp.py +1 -1
  48. {urwid-2.6.16.dist-info → urwid-3.0.1.dist-info}/METADATA +10 -15
  49. urwid-3.0.1.dist-info/RECORD +74 -0
  50. {urwid-2.6.16.dist-info → urwid-3.0.1.dist-info}/WHEEL +1 -1
  51. urwid-2.6.16.dist-info/RECORD +0 -74
  52. {urwid-2.6.16.dist-info → urwid-3.0.1.dist-info/licenses}/COPYING +0 -0
  53. {urwid-2.6.16.dist-info → urwid-3.0.1.dist-info}/top_level.txt +0 -0
@@ -172,7 +172,8 @@ class MainLoop:
172
172
  def _set_widget(self, widget: Widget) -> None:
173
173
  warnings.warn(
174
174
  f"method `{self.__class__.__name__}._set_widget` is deprecated, "
175
- f"please use `{self.__class__.__name__}.widget` property",
175
+ f"please use `{self.__class__.__name__}.widget` property."
176
+ "API will be removed in version 4.0.",
176
177
  DeprecationWarning,
177
178
  stacklevel=2,
178
179
  )
@@ -193,7 +194,8 @@ class MainLoop:
193
194
  def _set_pop_ups(self, pop_ups: bool) -> None:
194
195
  warnings.warn(
195
196
  f"method `{self.__class__.__name__}._set_pop_ups` is deprecated, "
196
- f"please use `{self.__class__.__name__}.pop_ups` property",
197
+ f"please use `{self.__class__.__name__}.pop_ups` property."
198
+ "API will be removed in version 4.0.",
197
199
  DeprecationWarning,
198
200
  stacklevel=2,
199
201
  )
@@ -460,9 +462,7 @@ class MainLoop:
460
462
  widget.mouse_event((15, 5), 'mouse press', 1, 5, 4, focus=True)
461
463
  >>> ml._update([], [])
462
464
  """
463
- keys = self.input_filter(keys, raw)
464
-
465
- if keys:
465
+ if keys := self.input_filter(keys, raw):
466
466
  self.process_input(keys)
467
467
  if "window resize" in keys:
468
468
  self.screen_size = None
@@ -493,19 +493,14 @@ class MainLoop:
493
493
  else:
494
494
  self.screen.set_input_timeouts(None)
495
495
  keys, raw = self.screen.get_input(True)
496
- if not keys and next_alarm:
497
- sec = next_alarm[0] - time.time()
498
- if sec <= 0:
499
- break
500
-
501
- keys = self.input_filter(keys, raw)
496
+ if not keys and next_alarm and next_alarm[0] - time.time() <= 0:
497
+ break
502
498
 
503
- if keys:
499
+ if keys := self.input_filter(keys, raw):
504
500
  self.process_input(keys)
505
501
 
506
502
  while next_alarm:
507
- sec = next_alarm[0] - time.time()
508
- if sec > 0:
503
+ if (next_alarm[0] - time.time()) > 0:
509
504
  break
510
505
  _tm, _tie_break, callback = next_alarm
511
506
  callback()
@@ -563,13 +558,13 @@ class MainLoop:
563
558
 
564
559
  if isinstance(key, str):
565
560
  if self._topmost_widget.selectable():
566
- handled_key = self._topmost_widget.keypress(self.screen_size, key)
567
- if not handled_key:
561
+ if handled_key := self._topmost_widget.keypress(self.screen_size, key):
562
+ key = handled_key # noqa: PLW2901
563
+
564
+ else:
568
565
  something_handled = True
569
566
  continue
570
567
 
571
- key = handled_key # noqa: PLW2901
572
-
573
568
  elif is_mouse_event(key):
574
569
  event, button, col, row = key
575
570
  if hasattr(self._topmost_widget, "mouse_event") and self._topmost_widget.mouse_event(
@@ -155,12 +155,11 @@ class TornadoEventLoop(EventLoop):
155
155
  return handle
156
156
 
157
157
  def remove_watch_file(self, handle: int) -> bool:
158
- fd = self._watch_handles.pop(handle, None)
159
- if fd is None:
160
- return False
158
+ if (fd := self._watch_handles.pop(handle, None)) is not None:
159
+ self._loop.remove_handler(fd)
160
+ return True
161
161
 
162
- self._loop.remove_handler(fd)
163
- return True
162
+ return False
164
163
 
165
164
  def enter_idle(self, callback: Callable[[], typing.Any]) -> int:
166
165
  """
@@ -261,7 +261,7 @@ class TrioEventLoop(EventLoop):
261
261
  """
262
262
  for task, scope, args in self._pending_tasks:
263
263
  self._nursery.start_soon(task, scope, *args)
264
- del self._pending_tasks[:]
264
+ self._pending_tasks.clear()
265
265
 
266
266
  def _start_task(
267
267
  self,
urwid/font.py CHANGED
@@ -29,7 +29,7 @@ from urwid.display.escape import SAFE_ASCII_DEC_SPECIAL_RE
29
29
  from urwid.util import apply_target_encoding, str_util
30
30
 
31
31
  if typing.TYPE_CHECKING:
32
- from collections.abc import Iterable, Iterator, Sequence
32
+ from collections.abc import Iterator, Sequence
33
33
 
34
34
  from typing_extensions import Literal
35
35
 
@@ -206,12 +206,10 @@ class Font(metaclass=FontRegistry):
206
206
  self.canvas: dict[str, TextCanvas] = {}
207
207
  self.utf8_required = False
208
208
  if isinstance(self.data, str):
209
- self.add_glyphs(self._to_text(self.data))
209
+ self.add_glyphs(self.data)
210
210
 
211
211
  else:
212
- data: Iterable[str] = (self._to_text(block) for block in self.data)
213
-
214
- for gdata in data:
212
+ for gdata in self.data:
215
213
  self.add_glyphs(gdata)
216
214
 
217
215
  def __repr__(self) -> str:
@@ -223,22 +221,19 @@ class Font(metaclass=FontRegistry):
223
221
 
224
222
  @staticmethod
225
223
  def _to_text(
226
- obj: str | bytes,
224
+ obj: str,
227
225
  encoding: str = "utf-8",
228
226
  errors: Literal["strict", "ignore", "replace"] = "strict",
229
227
  ) -> str:
228
+ warnings.warn(
229
+ "_to_text is deprecated: only text fonts are supported. API will be removed in version 4.0.",
230
+ DeprecationWarning,
231
+ stacklevel=3,
232
+ )
230
233
  if isinstance(obj, str):
231
234
  return obj
232
235
 
233
- if isinstance(obj, bytes):
234
- warnings.warn(
235
- "Bytes based fonts are deprecated, please switch to the text one",
236
- DeprecationWarning,
237
- stacklevel=3,
238
- )
239
- return obj.decode(encoding, errors)
240
-
241
- raise TypeError(f"{obj!r} is not str|bytes")
236
+ raise TypeError(f"{obj!r} is not str")
242
237
 
243
238
  def add_glyphs(self, gdata: str) -> None:
244
239
  d, utf8_required = separate_glyphs(gdata, self.height)
urwid/signals.py CHANGED
@@ -20,6 +20,7 @@
20
20
 
21
21
  from __future__ import annotations
22
22
 
23
+ import abc
23
24
  import itertools
24
25
  import typing
25
26
  import warnings
@@ -29,7 +30,7 @@ if typing.TYPE_CHECKING:
29
30
  from collections.abc import Callable, Collection, Container, Hashable, Iterable
30
31
 
31
32
 
32
- class MetaSignals(type):
33
+ class MetaSignals(abc.ABCMeta):
33
34
  """
34
35
  register the list of signals in the class variable signals,
35
36
  including signals in superclasses.
urwid/str_util.py CHANGED
@@ -29,17 +29,17 @@ import wcwidth
29
29
  if typing.TYPE_CHECKING:
30
30
  from typing_extensions import Literal
31
31
 
32
- SAFE_ASCII_RE = re.compile("^[ -~]*$")
33
- SAFE_ASCII_BYTES_RE = re.compile(b"^[ -~]*$")
32
+ SAFE_ASCII_RE = re.compile(r"^[ -~]*$")
33
+ SAFE_ASCII_BYTES_RE = re.compile(rb"^[ -~]*$")
34
34
 
35
35
  _byte_encoding: Literal["utf8", "narrow", "wide"] = "narrow"
36
36
 
37
37
 
38
38
  def get_char_width(char: str) -> Literal[0, 1, 2]:
39
- width = wcwidth.wcwidth(char)
40
- if width < 0:
41
- return 0
42
- return width
39
+ if (width := wcwidth.wcwidth(char)) >= 0:
40
+ return width
41
+
42
+ return 0
43
43
 
44
44
 
45
45
  def get_width(o: int) -> Literal[0, 1, 2]:
@@ -86,10 +86,9 @@ def decode_one(text: bytes | str, pos: int) -> tuple[int, int]:
86
86
  if b1 & 0xE0 == 0xC0:
87
87
  if b2 & 0xC0 != 0x80:
88
88
  return error
89
- o = ((b1 & 0x1F) << 6) | (b2 & 0x3F)
90
- if o < 0x80:
91
- return error
92
- return o, pos + 2
89
+ if (o := ((b1 & 0x1F) << 6) | (b2 & 0x3F)) >= 0x80:
90
+ return o, pos + 2
91
+ return error
93
92
  if lt < 3:
94
93
  return error
95
94
  if b1 & 0xF0 == 0xE0:
@@ -97,10 +96,9 @@ def decode_one(text: bytes | str, pos: int) -> tuple[int, int]:
97
96
  return error
98
97
  if b3 & 0xC0 != 0x80:
99
98
  return error
100
- o = ((b1 & 0x0F) << 12) | ((b2 & 0x3F) << 6) | (b3 & 0x3F)
101
- if o < 0x800:
102
- return error
103
- return o, pos + 3
99
+ if (o := ((b1 & 0x0F) << 12) | ((b2 & 0x3F) << 6) | (b3 & 0x3F)) >= 0x800:
100
+ return o, pos + 3
101
+ return error
104
102
  if lt < 4:
105
103
  return error
106
104
  if b1 & 0xF8 == 0xF0:
@@ -110,10 +108,9 @@ def decode_one(text: bytes | str, pos: int) -> tuple[int, int]:
110
108
  return error
111
109
  if b4 & 0xC0 != 0x80:
112
110
  return error
113
- o = ((b1 & 0x07) << 18) | ((b2 & 0x3F) << 12) | ((b3 & 0x3F) << 6) | (b4 & 0x3F)
114
- if o < 0x10000:
115
- return error
116
- return o, pos + 4
111
+ if (o := ((b1 & 0x07) << 18) | ((b2 & 0x3F) << 12) | ((b3 & 0x3F) << 6) | (b4 & 0x3F)) >= 0x10000:
112
+ return o, pos + 4
113
+ return error
117
114
  return error
118
115
 
119
116
 
urwid/text_layout.py CHANGED
@@ -461,7 +461,7 @@ def shift_line(
461
461
  # existing shift
462
462
  amount += segs[0][0]
463
463
  if amount:
464
- return [(amount, None)] + segs[1:]
464
+ return [(amount, None), *segs[1:]]
465
465
  return segs[1:]
466
466
 
467
467
  if amount:
@@ -581,8 +581,7 @@ def calc_pos(
581
581
  if row < 0 or row >= len(layout):
582
582
  raise ValueError("calculate_pos: out of layout row range")
583
583
 
584
- pos = calc_line_pos(text, layout[row], pref_col)
585
- if pos is not None:
584
+ if (pos := calc_line_pos(text, layout[row], pref_col)) is not None:
586
585
  return pos
587
586
 
588
587
  rows_above = list(range(row - 1, -1, -1))
@@ -590,14 +589,14 @@ def calc_pos(
590
589
  while rows_above and rows_below:
591
590
  if rows_above:
592
591
  r = rows_above.pop(0)
593
- pos = calc_line_pos(text, layout[r], pref_col)
594
- if pos is not None:
592
+ if (pos := calc_line_pos(text, layout[r], pref_col)) is not None:
595
593
  return pos
594
+
596
595
  if rows_below:
597
596
  r = rows_below.pop(0)
598
- pos = calc_line_pos(text, layout[r], pref_col)
599
- if pos is not None:
597
+ if (pos := calc_line_pos(text, layout[r], pref_col)) is not None:
600
598
  return pos
599
+
601
600
  return 0
602
601
 
603
602
 
urwid/util.py CHANGED
@@ -493,24 +493,13 @@ def is_mouse_press(ev: str) -> bool:
493
493
 
494
494
 
495
495
  class MetaSuper(type):
496
- """adding .__super"""
496
+ """Deprecated metaclass.
497
497
 
498
- def __init__(cls, name: str, bases, d):
499
- super().__init__(name, bases, d)
500
- if hasattr(cls, f"_{name}__super"):
501
- raise AttributeError("Class has same name as one of its super classes")
502
-
503
- @property
504
- def _super(self):
505
- warnings.warn(
506
- f"`{name}.__super` was a deprecated feature for old python versions."
507
- f"Please use `super()` call instead.",
508
- DeprecationWarning,
509
- stacklevel=3,
510
- )
511
- return super(cls, self)
498
+ Present only for code compatibility, all logic has been removed.
499
+ Please move to the last position in the class bases to allow future changes.
500
+ """
512
501
 
513
- setattr(cls, f"_{name}__super", _super)
502
+ __slots__ = ()
514
503
 
515
504
 
516
505
  def int_scale(val: int, val_range: int, out_range: int) -> int:
@@ -534,7 +523,7 @@ def int_scale(val: int, val_range: int, out_range: int) -> int:
534
523
  return num // dem
535
524
 
536
525
 
537
- class StoppingContext(typing.ContextManager["StoppingContext"]):
526
+ class StoppingContext(contextlib.AbstractContextManager["StoppingContext"]):
538
527
  """Context manager that calls ``stop`` on a given object on exit. Used to
539
528
  make the ``start`` method on `MainLoop` and `BaseScreen` optionally act as
540
529
  context managers.
urwid/version.py CHANGED
@@ -1,8 +1,13 @@
1
- # file generated by setuptools_scm
1
+ # file generated by setuptools-scm
2
2
  # don't change, don't track in version control
3
+
4
+ __all__ = ["__version__", "__version_tuple__", "version", "version_tuple"]
5
+
3
6
  TYPE_CHECKING = False
4
7
  if TYPE_CHECKING:
5
- from typing import Tuple, Union
8
+ from typing import Tuple
9
+ from typing import Union
10
+
6
11
  VERSION_TUPLE = Tuple[Union[int, str], ...]
7
12
  else:
8
13
  VERSION_TUPLE = object
@@ -12,5 +17,5 @@ __version__: str
12
17
  __version_tuple__: VERSION_TUPLE
13
18
  version_tuple: VERSION_TUPLE
14
19
 
15
- __version__ = version = '2.6.16'
16
- __version_tuple__ = version_tuple = (2, 6, 16)
20
+ __version__ = version = '3.0.1'
21
+ __version_tuple__ = version_tuple = (3, 0, 1)
urwid/vterm.py CHANGED
@@ -35,7 +35,6 @@ import termios
35
35
  import time
36
36
  import traceback
37
37
  import typing
38
- import warnings
39
38
  from collections import deque
40
39
  from contextlib import suppress
41
40
  from dataclasses import dataclass
@@ -248,8 +247,7 @@ class TermCharset:
248
247
 
249
248
  def apply_mapping(self, char: bytes) -> bytes:
250
249
  if self._sgr_mapping or self._g[self.active] == "ibmpc":
251
- dec_pos = DEC_SPECIAL_CHARS.find(char.decode("cp437"))
252
- if dec_pos >= 0:
250
+ if (dec_pos := DEC_SPECIAL_CHARS.find(char.decode("cp437"))) >= 0:
253
251
  self.current = "0"
254
252
  return ALT_DEC_SPECIAL_CHARS[dec_pos].encode("cp437")
255
253
 
@@ -259,39 +257,6 @@ class TermCharset:
259
257
  return char
260
258
 
261
259
 
262
- class TermScroller(list):
263
- """
264
- List subclass that handles the terminal scrollback buffer,
265
- truncating it as necessary.
266
- """
267
-
268
- SCROLLBACK_LINES = 10000
269
-
270
- def __init__(self, iterable: Iterable[typing.Any]) -> None:
271
- warnings.warn(
272
- "`TermScroller` is deprecated. Please use `collections.deque` with non-zero `maxlen` instead.",
273
- DeprecationWarning,
274
- stacklevel=3,
275
- )
276
- super().__init__(iterable)
277
-
278
- def trunc(self) -> None:
279
- if len(self) >= self.SCROLLBACK_LINES:
280
- self.pop(0)
281
-
282
- def append(self, obj) -> None:
283
- self.trunc()
284
- super().append(obj)
285
-
286
- def insert(self, idx: typing.SupportsIndex, obj) -> None:
287
- self.trunc()
288
- super().insert(idx, obj)
289
-
290
- def extend(self, seq) -> None:
291
- self.trunc()
292
- super().extend(seq)
293
-
294
-
295
260
  class TermCanvas(Canvas):
296
261
  cacheable = False
297
262
 
@@ -489,8 +454,7 @@ class TermCanvas(Canvas):
489
454
  continue
490
455
 
491
456
  # adjust x axis of scrollback buffer to the current width
492
- padding = self.width - len(last_line)
493
- if padding > 0:
457
+ if (padding := self.width - len(last_line)) > 0:
494
458
  last_line += [self.empty_char()] * padding
495
459
  else:
496
460
  last_line = last_line[: self.width]
@@ -549,8 +513,7 @@ class TermCanvas(Canvas):
549
513
 
550
514
  escbuf.append(num)
551
515
 
552
- cmd_ = CSI_COMMANDS[char]
553
- if cmd_ is not None:
516
+ if (cmd_ := CSI_COMMANDS[char]) is not None:
554
517
  if isinstance(cmd_, CSIAlias):
555
518
  csi_cmd: CSICommand = CSI_COMMANDS[cmd_.alias] # type: ignore[assignment]
556
519
  elif isinstance(cmd_, CSICommand):
@@ -699,11 +662,13 @@ class TermCanvas(Canvas):
699
662
 
700
663
  # end multibyte sequence
701
664
  self.utf8_eat_bytes = None
702
- sequence = (self.utf8_buffer + bytes([byte])).decode("utf-8", "ignore")
703
- if not sequence:
665
+
666
+ if sequence := (self.utf8_buffer + bytes([byte])).decode("utf-8", "ignore"):
667
+ char = sequence.encode(util.get_encoding(), "replace")
668
+
669
+ else:
704
670
  # invalid multibyte sequence, stop processing
705
671
  return
706
- char = sequence.encode(util.get_encoding(), "replace")
707
672
  else:
708
673
  self.utf8_eat_bytes = None
709
674
  char = bytes([byte])
@@ -1272,7 +1237,7 @@ class TermCanvas(Canvas):
1272
1237
  for x in range(self.width):
1273
1238
  char = self.term[y][x]
1274
1239
  attrs = self.reverse_attrspec(char[0], undo=undo)
1275
- self.term[y][x] = (attrs,) + char[1:]
1240
+ self.term[y][x] = (attrs, *char[1:])
1276
1241
 
1277
1242
  def set_mode(
1278
1243
  self,
urwid/widget/__init__.py CHANGED
@@ -41,9 +41,6 @@ from .solid_fill import SolidFill
41
41
  from .text import Text, TextError
42
42
  from .treetools import ParentNode, TreeListBox, TreeNode, TreeWalker, TreeWidget, TreeWidgetError
43
43
  from .widget import (
44
- BoxWidget,
45
- FixedWidget,
46
- FlowWidget,
47
44
  Widget,
48
45
  WidgetError,
49
46
  WidgetMeta,
@@ -87,7 +84,6 @@ __all__ = (
87
84
  "BigText",
88
85
  "BoxAdapter",
89
86
  "BoxAdapterError",
90
- "BoxWidget",
91
87
  "Button",
92
88
  "CheckBox",
93
89
  "CheckBoxError",
@@ -99,8 +95,6 @@ __all__ = (
99
95
  "EditError",
100
96
  "Filler",
101
97
  "FillerError",
102
- "FixedWidget",
103
- "FlowWidget",
104
98
  "Frame",
105
99
  "FrameError",
106
100
  "GraphVScale",
urwid/widget/attr_wrap.py CHANGED
@@ -47,8 +47,7 @@ class AttrWrap(AttrMap):
47
47
  # only include the focus_attr when it takes effect (not None)
48
48
  d = {**super()._repr_attrs(), "attr": self.attr}
49
49
  del d["attr_map"]
50
- if "focus_map" in d:
51
- del d["focus_map"]
50
+ d.pop("focus_map", None)
52
51
  if self.focus_attr is not None:
53
52
  d["focus_attr"] = self.focus_attr
54
53
  return d
@@ -57,8 +56,8 @@ class AttrWrap(AttrMap):
57
56
  def w(self) -> Widget:
58
57
  """backwards compatibility, widget used to be stored as w"""
59
58
  warnings.warn(
60
- "backwards compatibility, widget used to be stored as original_widget",
61
- PendingDeprecationWarning,
59
+ "backwards compatibility, widget used to be stored as original_widget. API will be removed in version 5.0.",
60
+ DeprecationWarning,
62
61
  stacklevel=2,
63
62
  )
64
63
  return self.original_widget
@@ -66,15 +65,15 @@ class AttrWrap(AttrMap):
66
65
  @w.setter
67
66
  def w(self, new_widget: Widget) -> None:
68
67
  warnings.warn(
69
- "backwards compatibility, widget used to be stored as original_widget",
70
- PendingDeprecationWarning,
68
+ "backwards compatibility, widget used to be stored as original_widget. API will be removed in version 5.0.",
69
+ DeprecationWarning,
71
70
  stacklevel=2,
72
71
  )
73
72
  self.original_widget = new_widget
74
73
 
75
74
  def get_w(self):
76
75
  warnings.warn(
77
- "backwards compatibility, widget used to be stored as original_widget",
76
+ "backwards compatibility, widget used to be stored as original_widget. API will be removed in version 4.0.",
78
77
  DeprecationWarning,
79
78
  stacklevel=2,
80
79
  )
@@ -82,7 +81,7 @@ class AttrWrap(AttrMap):
82
81
 
83
82
  def set_w(self, new_widget: Widget) -> None:
84
83
  warnings.warn(
85
- "backwards compatibility, widget used to be stored as original_widget",
84
+ "backwards compatibility, widget used to be stored as original_widget. API will be removed in version 4.0.",
86
85
  DeprecationWarning,
87
86
  stacklevel=2,
88
87
  )
@@ -105,8 +104,7 @@ class AttrWrap(AttrMap):
105
104
  attr = property(get_attr, set_attr)
106
105
 
107
106
  def get_focus_attr(self) -> Hashable | None:
108
- focus_map = self.focus_map
109
- if focus_map:
107
+ if focus_map := self.focus_map:
110
108
  return focus_map[None]
111
109
  return None
112
110
 
urwid/widget/bar_graph.py CHANGED
@@ -269,12 +269,7 @@ class BarGraph(Widget, metaclass=BarGraphMeta):
269
269
  ]
270
270
 
271
271
  # reverse the hlines to match screen ordering
272
- rhl = []
273
- for h in hlines:
274
- rh = float(top - h) * maxrow / top - shiftr
275
- if rh < 0:
276
- continue
277
- rhl.append(rh)
272
+ rhl = [rh for h in hlines if (rh := float(top - h) * maxrow / top - shiftr) >= 0]
278
273
 
279
274
  # build a list of rows that will have hlines
280
275
  hrows = []
@@ -562,7 +557,7 @@ def calculate_bargraph_display(bardata, top: float, bar_widths: list[int], maxro
562
557
  la, ln = last[i]
563
558
 
564
559
  if i < len(last):
565
- o += [(la, ln)] + last[i + 1 :]
560
+ o += [(la, ln), *last[i + 1 :]]
566
561
  last = o
567
562
  y_count += 1
568
563
 
urwid/widget/big_text.py CHANGED
@@ -70,15 +70,17 @@ class BigText(Widget):
70
70
  a, ak = attrib[ai]
71
71
  ai += 1
72
72
  ak -= 1
73
- width = self.font.char_width(ch)
74
- if not width:
73
+
74
+ if width := self.font.char_width(ch):
75
+ c: TextCanvas | CompositeCanvas = self.font.render(ch)
76
+ if a is not None:
77
+ c = CompositeCanvas(c)
78
+ c.fill_attr(a)
79
+ o.append((c, None, False, width))
80
+
81
+ else:
75
82
  # ignore invalid characters
76
83
  continue
77
- c: TextCanvas | CompositeCanvas = self.font.render(ch)
78
- if a is not None:
79
- c = CompositeCanvas(c)
80
- c.fill_attr(a)
81
- o.append((c, None, False, width))
82
84
  if o:
83
85
  canv = CanvasJoin(o)
84
86
  else:
@@ -48,8 +48,8 @@ class BoxAdapter(WidgetDecoration[WrappedWidget]):
48
48
  @property
49
49
  def box_widget(self) -> WrappedWidget:
50
50
  warnings.warn(
51
- "original stored as original_widget, keep for compatibility",
52
- PendingDeprecationWarning,
51
+ "original stored as original_widget, keep for compatibility. API will be removed in version 5.0.",
52
+ DeprecationWarning,
53
53
  stacklevel=2,
54
54
  )
55
55
  return self.original_widget
@@ -57,8 +57,8 @@ class BoxAdapter(WidgetDecoration[WrappedWidget]):
57
57
  @box_widget.setter
58
58
  def box_widget(self, widget: WrappedWidget) -> None:
59
59
  warnings.warn(
60
- "original stored as original_widget, keep for compatibility",
61
- PendingDeprecationWarning,
60
+ "original stored as original_widget, keep for compatibility. API will be removed in version 5.0.",
61
+ DeprecationWarning,
62
62
  stacklevel=2,
63
63
  )
64
64
  self.original_widget = widget