urwid 2.6.15__py3-none-any.whl → 3.0.0__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.
- urwid/__init__.py +1 -4
- urwid/canvas.py +27 -46
- urwid/command_map.py +6 -4
- urwid/container.py +1 -1
- urwid/decoration.py +1 -1
- urwid/display/_posix_raw_display.py +16 -4
- urwid/display/_raw_display_base.py +8 -5
- urwid/display/_win32_raw_display.py +16 -17
- urwid/display/common.py +26 -55
- urwid/display/curses.py +1 -1
- urwid/display/escape.py +15 -12
- urwid/display/lcd.py +4 -6
- urwid/display/web.py +7 -12
- urwid/event_loop/asyncio_loop.py +1 -2
- urwid/event_loop/main_loop.py +13 -18
- urwid/event_loop/tornado_loop.py +4 -5
- urwid/event_loop/trio_loop.py +1 -1
- urwid/font.py +13 -18
- urwid/signals.py +2 -1
- urwid/str_util.py +15 -18
- urwid/text_layout.py +6 -7
- urwid/util.py +7 -18
- urwid/version.py +9 -4
- urwid/vterm.py +18 -45
- urwid/widget/__init__.py +0 -6
- urwid/widget/attr_wrap.py +8 -10
- urwid/widget/bar_graph.py +3 -8
- urwid/widget/big_text.py +9 -7
- urwid/widget/box_adapter.py +4 -4
- urwid/widget/columns.py +52 -83
- urwid/widget/container.py +29 -75
- urwid/widget/edit.py +8 -8
- urwid/widget/filler.py +6 -6
- urwid/widget/frame.py +28 -37
- urwid/widget/grid_flow.py +25 -110
- urwid/widget/line_box.py +13 -0
- urwid/widget/listbox.py +12 -50
- urwid/widget/monitored_list.py +6 -4
- urwid/widget/overlay.py +4 -37
- urwid/widget/padding.py +11 -48
- urwid/widget/pile.py +179 -158
- urwid/widget/popup.py +2 -2
- urwid/widget/progress_bar.py +10 -11
- urwid/widget/scrollable.py +25 -33
- urwid/widget/treetools.py +27 -48
- urwid/widget/widget.py +7 -124
- urwid/widget/widget_decoration.py +4 -33
- urwid/wimp.py +1 -1
- {urwid-2.6.15.dist-info → urwid-3.0.0.dist-info}/METADATA +18 -18
- urwid-3.0.0.dist-info/RECORD +74 -0
- {urwid-2.6.15.dist-info → urwid-3.0.0.dist-info}/WHEEL +1 -1
- urwid-2.6.15.dist-info/RECORD +0 -74
- {urwid-2.6.15.dist-info → urwid-3.0.0.dist-info/licenses}/COPYING +0 -0
- {urwid-2.6.15.dist-info → urwid-3.0.0.dist-info}/top_level.txt +0 -0
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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 = []
|
|
@@ -410,7 +405,7 @@ class BarGraph(Widget, metaclass=BarGraphMeta):
|
|
|
410
405
|
if len(bar_type) == 3:
|
|
411
406
|
# vertical eighths
|
|
412
407
|
fg, bg, k = bar_type
|
|
413
|
-
a = self.satt[
|
|
408
|
+
a = self.satt[fg, bg]
|
|
414
409
|
t = self.eighths[k] * width
|
|
415
410
|
else:
|
|
416
411
|
# horizontal lines
|
|
@@ -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)
|
|
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
|
-
|
|
74
|
-
if
|
|
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:
|
urwid/widget/box_adapter.py
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
urwid/widget/columns.py
CHANGED
|
@@ -121,7 +121,8 @@ class Columns(Widget, WidgetContainerMixin, WidgetContainerListContentsMixin):
|
|
|
121
121
|
flow_fixed = _ContainerElementSizingFlag.FLOW | _ContainerElementSizingFlag.FIXED
|
|
122
122
|
given_box = _ContainerElementSizingFlag.BOX | _ContainerElementSizingFlag.WH_GIVEN
|
|
123
123
|
|
|
124
|
-
|
|
124
|
+
# This is a set of _ContainerElementSizingFlag ORed together.
|
|
125
|
+
flags: set[int] = set()
|
|
125
126
|
|
|
126
127
|
for idx, (widget, (size_kind, _size_weight, is_box)) in enumerate(self.contents):
|
|
127
128
|
w_sizing = widget.sizing()
|
|
@@ -190,7 +191,7 @@ class Columns(Widget, WidgetContainerMixin, WidgetContainerListContentsMixin):
|
|
|
190
191
|
if not supported:
|
|
191
192
|
warnings.warn(
|
|
192
193
|
f"Columns widget contents flags not allow to determine supported render kind:\n"
|
|
193
|
-
f"{', '.join(sorted(
|
|
194
|
+
f"{', '.join(sorted(_ContainerElementSizingFlag.log_string(flag) for flag in flags))}\n"
|
|
194
195
|
f"Using fallback hardcoded BOX|FLOW sizing kind.",
|
|
195
196
|
ColumnsWarning,
|
|
196
197
|
stacklevel=3,
|
|
@@ -372,8 +373,9 @@ class Columns(Widget, WidgetContainerMixin, WidgetContainerListContentsMixin):
|
|
|
372
373
|
standard container property :attr:`contents`.
|
|
373
374
|
"""
|
|
374
375
|
warnings.warn(
|
|
375
|
-
"only for backwards compatibility. You should use the new standard container `contents
|
|
376
|
-
|
|
376
|
+
"only for backwards compatibility. You should use the new standard container `contents`."
|
|
377
|
+
"API will be removed in version 5.0.",
|
|
378
|
+
DeprecationWarning,
|
|
377
379
|
stacklevel=2,
|
|
378
380
|
)
|
|
379
381
|
ml = MonitoredList(w for w, t in self.contents)
|
|
@@ -387,8 +389,9 @@ class Columns(Widget, WidgetContainerMixin, WidgetContainerListContentsMixin):
|
|
|
387
389
|
@widget_list.setter
|
|
388
390
|
def widget_list(self, widgets):
|
|
389
391
|
warnings.warn(
|
|
390
|
-
"only for backwards compatibility. You should use the new standard container `contents
|
|
391
|
-
|
|
392
|
+
"only for backwards compatibility. You should use the new standard container `contents`."
|
|
393
|
+
"API will be removed in version 5.0.",
|
|
394
|
+
DeprecationWarning,
|
|
392
395
|
stacklevel=2,
|
|
393
396
|
)
|
|
394
397
|
focus_position = self.focus_position
|
|
@@ -400,7 +403,7 @@ class Columns(Widget, WidgetContainerMixin, WidgetContainerListContentsMixin):
|
|
|
400
403
|
chain(self.contents, repeat((None, (WHSettings.WEIGHT, 1, False)))),
|
|
401
404
|
)
|
|
402
405
|
]
|
|
403
|
-
if focus_position < len(widgets):
|
|
406
|
+
if focus_position < len(widgets):
|
|
404
407
|
self.focus_position = focus_position
|
|
405
408
|
|
|
406
409
|
@property
|
|
@@ -412,8 +415,9 @@ class Columns(Widget, WidgetContainerMixin, WidgetContainerListContentsMixin):
|
|
|
412
415
|
"""
|
|
413
416
|
warnings.warn(
|
|
414
417
|
"for backwards compatibility only."
|
|
415
|
-
"You should use the new standard container property .contents to modify Pile contents."
|
|
416
|
-
|
|
418
|
+
"You should use the new standard container property .contents to modify Pile contents."
|
|
419
|
+
"API will be removed in version 5.0.",
|
|
420
|
+
DeprecationWarning,
|
|
417
421
|
stacklevel=2,
|
|
418
422
|
)
|
|
419
423
|
ml = MonitoredList(
|
|
@@ -432,8 +436,9 @@ class Columns(Widget, WidgetContainerMixin, WidgetContainerListContentsMixin):
|
|
|
432
436
|
def column_types(self, column_types):
|
|
433
437
|
warnings.warn(
|
|
434
438
|
"for backwards compatibility only."
|
|
435
|
-
"You should use the new standard container property .contents to modify Pile contents."
|
|
436
|
-
|
|
439
|
+
"You should use the new standard container property .contents to modify Pile contents."
|
|
440
|
+
"API will be removed in version 5.0.",
|
|
441
|
+
DeprecationWarning,
|
|
437
442
|
stacklevel=2,
|
|
438
443
|
)
|
|
439
444
|
focus_position = self.focus_position
|
|
@@ -441,7 +446,7 @@ class Columns(Widget, WidgetContainerMixin, WidgetContainerListContentsMixin):
|
|
|
441
446
|
(w, ({Sizing.FIXED: WHSettings.GIVEN, Sizing.FLOW: WHSettings.PACK}.get(new_t, new_t), new_n, b))
|
|
442
447
|
for ((new_t, new_n), (w, (t, n, b))) in zip(column_types, self.contents)
|
|
443
448
|
]
|
|
444
|
-
if focus_position < len(column_types):
|
|
449
|
+
if focus_position < len(column_types):
|
|
445
450
|
self.focus_position = focus_position
|
|
446
451
|
|
|
447
452
|
@property
|
|
@@ -454,8 +459,9 @@ class Columns(Widget, WidgetContainerMixin, WidgetContainerListContentsMixin):
|
|
|
454
459
|
standard container property :attr:`contents`.
|
|
455
460
|
"""
|
|
456
461
|
warnings.warn(
|
|
457
|
-
"only for backwards compatibility.You should use the new standard container property `contents
|
|
458
|
-
|
|
462
|
+
"only for backwards compatibility.You should use the new standard container property `contents`."
|
|
463
|
+
"API will be removed in version 5.0.",
|
|
464
|
+
DeprecationWarning,
|
|
459
465
|
stacklevel=2,
|
|
460
466
|
)
|
|
461
467
|
ml = MonitoredList(i for i, (w, (t, n, b)) in enumerate(self.contents) if b)
|
|
@@ -469,8 +475,9 @@ class Columns(Widget, WidgetContainerMixin, WidgetContainerListContentsMixin):
|
|
|
469
475
|
@box_columns.setter
|
|
470
476
|
def box_columns(self, box_columns):
|
|
471
477
|
warnings.warn(
|
|
472
|
-
"only for backwards compatibility.You should use the new standard container property `contents
|
|
473
|
-
|
|
478
|
+
"only for backwards compatibility.You should use the new standard container property `contents`."
|
|
479
|
+
"API will be removed in version 5.0.",
|
|
480
|
+
DeprecationWarning,
|
|
474
481
|
stacklevel=2,
|
|
475
482
|
)
|
|
476
483
|
box_columns = set(box_columns)
|
|
@@ -482,7 +489,7 @@ class Columns(Widget, WidgetContainerMixin, WidgetContainerListContentsMixin):
|
|
|
482
489
|
.. deprecated:: 1.0 Read values from :attr:`contents` instead.
|
|
483
490
|
"""
|
|
484
491
|
warnings.warn(
|
|
485
|
-
".has_flow_type is deprecated, read values from .contents instead.",
|
|
492
|
+
".has_flow_type is deprecated, read values from .contents instead. API will be removed in version 4.0.",
|
|
486
493
|
DeprecationWarning,
|
|
487
494
|
stacklevel=2,
|
|
488
495
|
)
|
|
@@ -491,7 +498,7 @@ class Columns(Widget, WidgetContainerMixin, WidgetContainerListContentsMixin):
|
|
|
491
498
|
@has_flow_type.setter
|
|
492
499
|
def has_flow_type(self, value):
|
|
493
500
|
warnings.warn(
|
|
494
|
-
".has_flow_type is deprecated, read values from .contents instead.",
|
|
501
|
+
".has_flow_type is deprecated, read values from .contents instead. API will be removed in version 4.0.",
|
|
495
502
|
DeprecationWarning,
|
|
496
503
|
stacklevel=2,
|
|
497
504
|
)
|
|
@@ -582,8 +589,9 @@ class Columns(Widget, WidgetContainerMixin, WidgetContainerListContentsMixin):
|
|
|
582
589
|
standard container property :attr:`focus_position` to set the focus.
|
|
583
590
|
"""
|
|
584
591
|
warnings.warn(
|
|
585
|
-
"only for backwards compatibility.You may also use the new standard container property `focus_position
|
|
586
|
-
|
|
592
|
+
"only for backwards compatibility.You may also use the new standard container property `focus_position`."
|
|
593
|
+
"API will be removed in version 5.0.",
|
|
594
|
+
DeprecationWarning,
|
|
587
595
|
stacklevel=2,
|
|
588
596
|
)
|
|
589
597
|
self.focus_position = num
|
|
@@ -596,8 +604,9 @@ class Columns(Widget, WidgetContainerMixin, WidgetContainerListContentsMixin):
|
|
|
596
604
|
standard container property :attr:`focus_position` to get the focus.
|
|
597
605
|
"""
|
|
598
606
|
warnings.warn(
|
|
599
|
-
"only for backwards compatibility.You may also use the new standard container property `focus_position
|
|
600
|
-
|
|
607
|
+
"only for backwards compatibility.You may also use the new standard container property `focus_position`."
|
|
608
|
+
"API will be removed in version 5.0.",
|
|
609
|
+
DeprecationWarning,
|
|
601
610
|
stacklevel=2,
|
|
602
611
|
)
|
|
603
612
|
return self.focus_position
|
|
@@ -612,8 +621,9 @@ class Columns(Widget, WidgetContainerMixin, WidgetContainerListContentsMixin):
|
|
|
612
621
|
:param item: widget or integer index"""
|
|
613
622
|
warnings.warn(
|
|
614
623
|
"only for backwards compatibility."
|
|
615
|
-
"You may also use the new standard container property `focus_position` to get the focus."
|
|
616
|
-
|
|
624
|
+
"You may also use the new standard container property `focus_position` to get the focus."
|
|
625
|
+
"API will be removed in version 5.0.",
|
|
626
|
+
DeprecationWarning,
|
|
617
627
|
stacklevel=2,
|
|
618
628
|
)
|
|
619
629
|
if isinstance(item, int):
|
|
@@ -638,17 +648,6 @@ class Columns(Widget, WidgetContainerMixin, WidgetContainerListContentsMixin):
|
|
|
638
648
|
return None
|
|
639
649
|
return self.contents[self.focus_position][0]
|
|
640
650
|
|
|
641
|
-
def _get_focus(self) -> Widget:
|
|
642
|
-
warnings.warn(
|
|
643
|
-
f"method `{self.__class__.__name__}._get_focus` is deprecated, "
|
|
644
|
-
f"please use `{self.__class__.__name__}.focus` property",
|
|
645
|
-
DeprecationWarning,
|
|
646
|
-
stacklevel=3,
|
|
647
|
-
)
|
|
648
|
-
if not self.contents:
|
|
649
|
-
return None
|
|
650
|
-
return self.contents[self.focus_position][0]
|
|
651
|
-
|
|
652
651
|
def get_focus(self):
|
|
653
652
|
"""
|
|
654
653
|
Return the widget in focus, for backwards compatibility.
|
|
@@ -658,8 +657,9 @@ class Columns(Widget, WidgetContainerMixin, WidgetContainerListContentsMixin):
|
|
|
658
657
|
"""
|
|
659
658
|
warnings.warn(
|
|
660
659
|
"only for backwards compatibility."
|
|
661
|
-
"You may also use the new standard container property `focus` to get the focus."
|
|
662
|
-
|
|
660
|
+
"You may also use the new standard container property `focus` to get the focus."
|
|
661
|
+
"API will be removed in version 5.0.",
|
|
662
|
+
DeprecationWarning,
|
|
663
663
|
stacklevel=2,
|
|
664
664
|
)
|
|
665
665
|
if not self.contents:
|
|
@@ -692,38 +692,6 @@ class Columns(Widget, WidgetContainerMixin, WidgetContainerListContentsMixin):
|
|
|
692
692
|
) from exc
|
|
693
693
|
self.contents.focus = position
|
|
694
694
|
|
|
695
|
-
def _get_focus_position(self) -> int | None:
|
|
696
|
-
warnings.warn(
|
|
697
|
-
f"method `{self.__class__.__name__}._get_focus_position` is deprecated, "
|
|
698
|
-
f"please use `{self.__class__.__name__}.focus_position` property",
|
|
699
|
-
DeprecationWarning,
|
|
700
|
-
stacklevel=3,
|
|
701
|
-
)
|
|
702
|
-
if not self.contents:
|
|
703
|
-
raise IndexError("No focus_position, Columns is empty")
|
|
704
|
-
return self.contents.focus
|
|
705
|
-
|
|
706
|
-
def _set_focus_position(self, position: int) -> None:
|
|
707
|
-
"""
|
|
708
|
-
Set the widget in focus.
|
|
709
|
-
|
|
710
|
-
position -- index of child widget to be made focus
|
|
711
|
-
"""
|
|
712
|
-
warnings.warn(
|
|
713
|
-
f"method `{self.__class__.__name__}._set_focus_position` is deprecated, "
|
|
714
|
-
f"please use `{self.__class__.__name__}.focus_position` property",
|
|
715
|
-
DeprecationWarning,
|
|
716
|
-
stacklevel=3,
|
|
717
|
-
)
|
|
718
|
-
try:
|
|
719
|
-
if position < 0 or position >= len(self.contents):
|
|
720
|
-
raise IndexError(f"No Columns child widget at position {position}")
|
|
721
|
-
except TypeError as exc:
|
|
722
|
-
raise IndexError(f"No Columns child widget at position {position}").with_traceback(
|
|
723
|
-
exc.__traceback__
|
|
724
|
-
) from exc
|
|
725
|
-
self.contents.focus = position
|
|
726
|
-
|
|
727
695
|
@property
|
|
728
696
|
def focus_col(self):
|
|
729
697
|
"""
|
|
@@ -735,8 +703,9 @@ class Columns(Widget, WidgetContainerMixin, WidgetContainerListContentsMixin):
|
|
|
735
703
|
"""
|
|
736
704
|
warnings.warn(
|
|
737
705
|
"only for backwards compatibility."
|
|
738
|
-
"You may also use the new standard container property `focus_position` to get the focus."
|
|
739
|
-
|
|
706
|
+
"You may also use the new standard container property `focus_position` to get the focus."
|
|
707
|
+
"API will be removed in version 5.0.",
|
|
708
|
+
DeprecationWarning,
|
|
740
709
|
stacklevel=2,
|
|
741
710
|
)
|
|
742
711
|
return self.focus_position
|
|
@@ -745,8 +714,9 @@ class Columns(Widget, WidgetContainerMixin, WidgetContainerListContentsMixin):
|
|
|
745
714
|
def focus_col(self, new_position) -> None:
|
|
746
715
|
warnings.warn(
|
|
747
716
|
"only for backwards compatibility."
|
|
748
|
-
"You may also use the new standard container property `focus_position` to get the focus."
|
|
749
|
-
|
|
717
|
+
"You may also use the new standard container property `focus_position` to get the focus."
|
|
718
|
+
"API will be removed in version 5.0.",
|
|
719
|
+
DeprecationWarning,
|
|
750
720
|
stacklevel=2,
|
|
751
721
|
)
|
|
752
722
|
self.focus_position = new_position
|
|
@@ -1032,7 +1002,7 @@ class Columns(Widget, WidgetContainerMixin, WidgetContainerListContentsMixin):
|
|
|
1032
1002
|
|
|
1033
1003
|
if not data:
|
|
1034
1004
|
if size:
|
|
1035
|
-
return SolidCanvas(" ", size[0], (size[1:]
|
|
1005
|
+
return SolidCanvas(" ", size[0], (*size[1:], 1)[0])
|
|
1036
1006
|
raise ColumnsError("No data to render")
|
|
1037
1007
|
|
|
1038
1008
|
canvas = CanvasJoin(data)
|
|
@@ -1053,13 +1023,12 @@ class Columns(Widget, WidgetContainerMixin, WidgetContainerListContentsMixin):
|
|
|
1053
1023
|
if len(widths) <= self.focus_position:
|
|
1054
1024
|
return None
|
|
1055
1025
|
|
|
1056
|
-
coords
|
|
1057
|
-
|
|
1058
|
-
|
|
1026
|
+
if (coords := w.get_cursor_coords(size_args[self.focus_position])) is not None:
|
|
1027
|
+
x, y = coords
|
|
1028
|
+
x += sum(self.dividechars + wc for wc in widths[: self.focus_position] if wc > 0)
|
|
1029
|
+
return x, y
|
|
1059
1030
|
|
|
1060
|
-
|
|
1061
|
-
x += sum(self.dividechars + wc for wc in widths[: self.focus_position] if wc > 0)
|
|
1062
|
-
return x, y
|
|
1031
|
+
return None
|
|
1063
1032
|
|
|
1064
1033
|
def move_cursor_to_coords(
|
|
1065
1034
|
self,
|
|
@@ -1103,8 +1072,8 @@ class Columns(Widget, WidgetContainerMixin, WidgetContainerListContentsMixin):
|
|
|
1103
1072
|
move_x = min(max(0, col - x), end - x - 1)
|
|
1104
1073
|
else:
|
|
1105
1074
|
move_x = col
|
|
1106
|
-
|
|
1107
|
-
if
|
|
1075
|
+
|
|
1076
|
+
if w.move_cursor_to_coords(size_args[i], move_x, row) is False:
|
|
1108
1077
|
return False
|
|
1109
1078
|
|
|
1110
1079
|
self.focus_position = i
|
|
@@ -1176,7 +1145,7 @@ class Columns(Widget, WidgetContainerMixin, WidgetContainerListContentsMixin):
|
|
|
1176
1145
|
col += sum(widths[: self.focus_position])
|
|
1177
1146
|
return col
|
|
1178
1147
|
|
|
1179
|
-
def rows(self, size: tuple[int]
|
|
1148
|
+
def rows(self, size: tuple[int], focus: bool = False) -> int:
|
|
1180
1149
|
"""
|
|
1181
1150
|
Return the number of rows required by the columns.
|
|
1182
1151
|
This only makes sense if :attr:`widget_list` contains flow widgets.
|
urwid/widget/container.py
CHANGED
|
@@ -3,7 +3,6 @@ from __future__ import annotations
|
|
|
3
3
|
import abc
|
|
4
4
|
import enum
|
|
5
5
|
import typing
|
|
6
|
-
import warnings
|
|
7
6
|
|
|
8
7
|
from .constants import Sizing, WHSettings
|
|
9
8
|
|
|
@@ -13,39 +12,45 @@ if typing.TYPE_CHECKING:
|
|
|
13
12
|
from .widget import Widget
|
|
14
13
|
|
|
15
14
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
15
|
+
# Ideally, we would like to use an IntFlag coupled with enum.auto().
|
|
16
|
+
# However, doing many bitwise operations (which happens when nesting too many
|
|
17
|
+
# widgets ...) on IntFlag is orders of magnitude slower than doing the same
|
|
18
|
+
# operations on IntEnum.
|
|
19
|
+
class _ContainerElementSizingFlag(enum.IntEnum):
|
|
20
|
+
# fmt: off
|
|
21
|
+
NONE = 0b000000
|
|
22
|
+
BOX = 0b000001
|
|
23
|
+
FLOW = 0b000010
|
|
24
|
+
FIXED = 0b000100
|
|
25
|
+
WH_WEIGHT = 0b001000
|
|
26
|
+
WH_PACK = 0b010000
|
|
27
|
+
WH_GIVEN = 0b100000
|
|
28
|
+
# fmt: on
|
|
29
|
+
|
|
30
|
+
@staticmethod
|
|
31
|
+
def reverse_flag(bitfield: int) -> tuple[frozenset[Sizing], WHSettings | None]:
|
|
27
32
|
"""Get flag in public API format."""
|
|
28
33
|
sizing: set[Sizing] = set()
|
|
29
34
|
|
|
30
|
-
if
|
|
35
|
+
if bitfield & _ContainerElementSizingFlag.BOX:
|
|
31
36
|
sizing.add(Sizing.BOX)
|
|
32
|
-
if
|
|
37
|
+
if bitfield & _ContainerElementSizingFlag.FLOW:
|
|
33
38
|
sizing.add(Sizing.FLOW)
|
|
34
|
-
if
|
|
39
|
+
if bitfield & _ContainerElementSizingFlag.FIXED:
|
|
35
40
|
sizing.add(Sizing.FIXED)
|
|
36
41
|
|
|
37
|
-
if
|
|
42
|
+
if bitfield & _ContainerElementSizingFlag.WH_WEIGHT:
|
|
38
43
|
return frozenset(sizing), WHSettings.WEIGHT
|
|
39
|
-
if
|
|
44
|
+
if bitfield & _ContainerElementSizingFlag.WH_PACK:
|
|
40
45
|
return frozenset(sizing), WHSettings.PACK
|
|
41
|
-
if
|
|
46
|
+
if bitfield & _ContainerElementSizingFlag.WH_GIVEN:
|
|
42
47
|
return frozenset(sizing), WHSettings.GIVEN
|
|
43
48
|
return frozenset(sizing), None
|
|
44
49
|
|
|
45
|
-
@
|
|
46
|
-
def log_string(
|
|
50
|
+
@staticmethod
|
|
51
|
+
def log_string(bitfield: int) -> str:
|
|
47
52
|
"""Get desctiprion in public API format."""
|
|
48
|
-
sizing, render =
|
|
53
|
+
sizing, render = _ContainerElementSizingFlag.reverse_flag(bitfield)
|
|
49
54
|
render_string = f" {render.upper()}" if render else ""
|
|
50
55
|
return "|".join(sorted(mode.upper() for mode in sizing)) + render_string
|
|
51
56
|
|
|
@@ -115,12 +120,11 @@ class WidgetContainerMixin:
|
|
|
115
120
|
"""
|
|
116
121
|
out = []
|
|
117
122
|
w = self
|
|
118
|
-
while
|
|
119
|
-
w = w.base_widget.focus
|
|
120
|
-
if w is None:
|
|
121
|
-
return out
|
|
123
|
+
while (w := w.base_widget.focus) is not None:
|
|
122
124
|
out.append(w)
|
|
123
125
|
|
|
126
|
+
return out
|
|
127
|
+
|
|
124
128
|
@property
|
|
125
129
|
@abc.abstractmethod
|
|
126
130
|
def focus(self) -> Widget:
|
|
@@ -130,15 +134,6 @@ class WidgetContainerMixin:
|
|
|
130
134
|
always returns ``None``, indicating that this widget has no children.
|
|
131
135
|
"""
|
|
132
136
|
|
|
133
|
-
def _get_focus(self) -> Widget:
|
|
134
|
-
warnings.warn(
|
|
135
|
-
f"method `{self.__class__.__name__}._get_focus` is deprecated, "
|
|
136
|
-
f"please use `{self.__class__.__name__}.focus` property",
|
|
137
|
-
DeprecationWarning,
|
|
138
|
-
stacklevel=3,
|
|
139
|
-
)
|
|
140
|
-
return self.focus
|
|
141
|
-
|
|
142
137
|
|
|
143
138
|
class WidgetContainerListContentsMixin:
|
|
144
139
|
"""
|
|
@@ -172,24 +167,6 @@ class WidgetContainerListContentsMixin:
|
|
|
172
167
|
def contents(self, new_contents: list[tuple[Widget, typing.Any]]) -> None:
|
|
173
168
|
"""The contents of container as a list of (widget, options)"""
|
|
174
169
|
|
|
175
|
-
def _get_contents(self) -> list[tuple[Widget, typing.Any]]:
|
|
176
|
-
warnings.warn(
|
|
177
|
-
f"method `{self.__class__.__name__}._get_contents` is deprecated, "
|
|
178
|
-
f"please use `{self.__class__.__name__}.contents` property",
|
|
179
|
-
DeprecationWarning,
|
|
180
|
-
stacklevel=2,
|
|
181
|
-
)
|
|
182
|
-
return self.contents
|
|
183
|
-
|
|
184
|
-
def _set_contents(self, c: list[tuple[Widget, typing.Any]]) -> None:
|
|
185
|
-
warnings.warn(
|
|
186
|
-
f"method `{self.__class__.__name__}._set_contents` is deprecated, "
|
|
187
|
-
f"please use `{self.__class__.__name__}.contents` property",
|
|
188
|
-
DeprecationWarning,
|
|
189
|
-
stacklevel=2,
|
|
190
|
-
)
|
|
191
|
-
self.contents = c
|
|
192
|
-
|
|
193
170
|
@property
|
|
194
171
|
@abc.abstractmethod
|
|
195
172
|
def focus_position(self) -> int | None:
|
|
@@ -202,26 +179,3 @@ class WidgetContainerListContentsMixin:
|
|
|
202
179
|
"""
|
|
203
180
|
index of child widget in focus.
|
|
204
181
|
"""
|
|
205
|
-
|
|
206
|
-
def _get_focus_position(self) -> int | None:
|
|
207
|
-
warnings.warn(
|
|
208
|
-
f"method `{self.__class__.__name__}._get_focus_position` is deprecated, "
|
|
209
|
-
f"please use `{self.__class__.__name__}.focus_position` property",
|
|
210
|
-
DeprecationWarning,
|
|
211
|
-
stacklevel=3,
|
|
212
|
-
)
|
|
213
|
-
return self.focus_position
|
|
214
|
-
|
|
215
|
-
def _set_focus_position(self, position: int) -> None:
|
|
216
|
-
"""
|
|
217
|
-
Set the widget in focus.
|
|
218
|
-
|
|
219
|
-
position -- index of child widget to be made focus
|
|
220
|
-
"""
|
|
221
|
-
warnings.warn(
|
|
222
|
-
f"method `{self.__class__.__name__}._set_focus_position` is deprecated, "
|
|
223
|
-
f"please use `{self.__class__.__name__}.focus_position` property",
|
|
224
|
-
DeprecationWarning,
|
|
225
|
-
stacklevel=3,
|
|
226
|
-
)
|
|
227
|
-
self.focus_position = position
|
urwid/widget/edit.py
CHANGED
|
@@ -595,7 +595,7 @@ class Edit(Text):
|
|
|
595
595
|
>>> c.cursor
|
|
596
596
|
(5, 0)
|
|
597
597
|
"""
|
|
598
|
-
self._shift_view_to_cursor = bool(focus)
|
|
598
|
+
self._shift_view_to_cursor = bool(focus)
|
|
599
599
|
|
|
600
600
|
canv: TextCanvas | CompositeCanvas = super().render(size, focus)
|
|
601
601
|
if focus:
|
|
@@ -698,15 +698,15 @@ class IntEdit(Edit):
|
|
|
698
698
|
>>> print(e.edit_text)
|
|
699
699
|
2
|
|
700
700
|
"""
|
|
701
|
-
unhandled
|
|
701
|
+
if unhandled := super().keypress(size, key):
|
|
702
|
+
return unhandled
|
|
702
703
|
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
self.set_edit_text(self.edit_text[1:])
|
|
704
|
+
# trim leading zeros
|
|
705
|
+
while self.edit_pos > 0 and self.edit_text[:1] == "0":
|
|
706
|
+
self.set_edit_pos(self.edit_pos - 1)
|
|
707
|
+
self.set_edit_text(self.edit_text[1:])
|
|
708
708
|
|
|
709
|
-
return
|
|
709
|
+
return None
|
|
710
710
|
|
|
711
711
|
def value(self) -> int:
|
|
712
712
|
"""
|