urwid 2.6.9__py3-none-any.whl → 2.6.10__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.
- urwid/version.py +2 -2
- urwid/widget/listbox.py +25 -5
- urwid/widget/scrollable.py +22 -10
- {urwid-2.6.9.dist-info → urwid-2.6.10.dist-info}/METADATA +1 -1
- {urwid-2.6.9.dist-info → urwid-2.6.10.dist-info}/RECORD +8 -8
- {urwid-2.6.9.dist-info → urwid-2.6.10.dist-info}/COPYING +0 -0
- {urwid-2.6.9.dist-info → urwid-2.6.10.dist-info}/WHEEL +0 -0
- {urwid-2.6.9.dist-info → urwid-2.6.10.dist-info}/top_level.txt +0 -0
urwid/version.py
CHANGED
urwid/widget/listbox.py
CHANGED
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
|
|
21
21
|
from __future__ import annotations
|
|
22
22
|
|
|
23
|
+
import operator
|
|
23
24
|
import typing
|
|
24
25
|
import warnings
|
|
25
26
|
from collections.abc import Iterable, Sized
|
|
@@ -77,6 +78,18 @@ class ScrollSupportingBody(Protocol):
|
|
|
77
78
|
def get_prev(self, position: _K) -> tuple[Widget, _K] | tuple[None, None]: ...
|
|
78
79
|
|
|
79
80
|
|
|
81
|
+
@runtime_checkable
|
|
82
|
+
class EstimatedSized(Protocol):
|
|
83
|
+
"""Widget can estimate it's size.
|
|
84
|
+
|
|
85
|
+
PEP 424 defines API for memory-efficiency.
|
|
86
|
+
For the ListBox it's a sign of the limited body length.
|
|
87
|
+
The main use-case is lazy-load, where real length calculation is expensive.
|
|
88
|
+
"""
|
|
89
|
+
|
|
90
|
+
def __length_hint__(self) -> int: ...
|
|
91
|
+
|
|
92
|
+
|
|
80
93
|
class ListWalker(metaclass=signals.MetaSignals): # pylint: disable=no-member, unsubscriptable-object
|
|
81
94
|
# mixin not named as mixin
|
|
82
95
|
signals: typing.ClassVar[list[str]] = ["modified"]
|
|
@@ -431,11 +444,18 @@ class ListBox(Widget, WidgetContainerMixin):
|
|
|
431
444
|
)
|
|
432
445
|
self.body = body
|
|
433
446
|
|
|
434
|
-
|
|
447
|
+
@property
|
|
448
|
+
def __len__(self) -> Callable[[], int]:
|
|
435
449
|
if isinstance(self._body, Sized):
|
|
436
|
-
return
|
|
450
|
+
return self._body.__len__
|
|
437
451
|
raise AttributeError(f"{self._body.__class__.__name__} is not Sized")
|
|
438
452
|
|
|
453
|
+
@property
|
|
454
|
+
def __length_hint__(self) -> Callable[[], int]: # pylint: disable=invalid-length-hint-returned
|
|
455
|
+
if isinstance(self._body, (Sized, EstimatedSized)):
|
|
456
|
+
return lambda: operator.length_hint(self._body)
|
|
457
|
+
raise AttributeError(f'{self._body.__class__.__name__} is not Sized and do not implement "__length_hint__"')
|
|
458
|
+
|
|
439
459
|
def calculate_visible(
|
|
440
460
|
self,
|
|
441
461
|
size: tuple[int, int],
|
|
@@ -577,9 +597,9 @@ class ListBox(Widget, WidgetContainerMixin):
|
|
|
577
597
|
if not isinstance(self._body, ScrollSupportingBody):
|
|
578
598
|
raise ListBoxError(f"{self} body do not implement methods required for scrolling protocol")
|
|
579
599
|
|
|
580
|
-
if not isinstance(self._body, (Sized, TreeWalker)):
|
|
600
|
+
if not isinstance(self._body, (Sized, EstimatedSized, TreeWalker)):
|
|
581
601
|
raise ListBoxError(
|
|
582
|
-
f"{self} body is not a Sized and not a TreeWalker."
|
|
602
|
+
f"{self} body is not a Sized, can not estimate it's size and not a TreeWalker."
|
|
583
603
|
f"Scroll is not allowed due to risk of infinite cycle of widgets load."
|
|
584
604
|
)
|
|
585
605
|
|
|
@@ -643,7 +663,7 @@ class ListBox(Widget, WidgetContainerMixin):
|
|
|
643
663
|
|
|
644
664
|
def require_relative_scroll(self, size: tuple[int, int], focus: bool = False) -> bool:
|
|
645
665
|
"""Widget require relative scroll due to performance limitations of real lines count calculation."""
|
|
646
|
-
return isinstance(self._body, Sized) and (size[1] * 3 <
|
|
666
|
+
return isinstance(self._body, (Sized, EstimatedSized)) and (size[1] * 3 < operator.length_hint(self.body))
|
|
647
667
|
|
|
648
668
|
def get_first_visible_pos(self, size: tuple[int, int], focus: bool = False) -> int:
|
|
649
669
|
self._check_support_scrolling()
|
urwid/widget/scrollable.py
CHANGED
|
@@ -130,8 +130,6 @@ class SupportsScroll(WidgetProto, Protocol):
|
|
|
130
130
|
class SupportsRelativeScroll(WidgetProto, Protocol):
|
|
131
131
|
"""Relative scroll-specific methods."""
|
|
132
132
|
|
|
133
|
-
def __len__(self) -> int: ...
|
|
134
|
-
|
|
135
133
|
def require_relative_scroll(self, size: tuple[int, int], focus: bool = False) -> bool: ...
|
|
136
134
|
|
|
137
135
|
def get_first_visible_pos(self, size: tuple[int, int], focus: bool = False) -> int: ...
|
|
@@ -516,18 +514,32 @@ class ScrollBar(WidgetDecoration[WrappedWidget]):
|
|
|
516
514
|
ow = self._original_widget
|
|
517
515
|
ow_base = self.scrolling_base_widget
|
|
518
516
|
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
517
|
+
# Use hasattr instead of protocol: hasattr will return False in case of getattr raise AttributeError
|
|
518
|
+
# Use __length_hint__ first since it's less resource intensive
|
|
519
|
+
use_relative = (
|
|
520
|
+
isinstance(ow_base, SupportsRelativeScroll)
|
|
521
|
+
and any(hasattr(ow_base, attrib) for attrib in ("__length_hint__", "__len__"))
|
|
522
|
+
and ow_base.require_relative_scroll(size, focus)
|
|
523
|
+
)
|
|
523
524
|
|
|
525
|
+
if use_relative:
|
|
526
|
+
# `operator.length_hint` is Protocol (Spec) over class based and can end false-negative on the instance
|
|
527
|
+
# use length_hint-like approach with safe `AttributeError` handling
|
|
528
|
+
ow_len = getattr(ow_base, "__len__", getattr(ow_base, "__length_hint__", lambda: 0))()
|
|
524
529
|
ow_canv = render_for_scrollbar()
|
|
525
|
-
visible_amount =
|
|
530
|
+
visible_amount = ow_base.get_visible_amount(ow_size, focus)
|
|
526
531
|
pos = ow_base.get_first_visible_pos(ow_size, focus)
|
|
527
|
-
posmax = len(ow) - visible_amount
|
|
528
|
-
thumb_weight = min(1.0, visible_amount / max(1, len(ow)))
|
|
529
532
|
|
|
530
|
-
|
|
533
|
+
# in the case of estimated length, it can be smaller than real widget length
|
|
534
|
+
ow_len = max(ow_len, visible_amount, pos)
|
|
535
|
+
posmax = ow_len - visible_amount
|
|
536
|
+
thumb_weight = min(1.0, visible_amount / max(1, ow_len))
|
|
537
|
+
|
|
538
|
+
if ow_len == visible_amount:
|
|
539
|
+
# Corner case: formally all contents indexes should be visible, but this does not mean all rows
|
|
540
|
+
use_relative = False
|
|
541
|
+
|
|
542
|
+
if not use_relative:
|
|
531
543
|
ow_rows_max = ow_base.rows_max(size, focus)
|
|
532
544
|
if ow_rows_max <= maxrow:
|
|
533
545
|
# Canvas fits without scrolling - no scrollbar needed
|
|
@@ -11,7 +11,7 @@ urwid/split_repr.py,sha256=pXzuddzQ4RnfIl537Gvoe8PVaBRHCPnxgdYvKK0qm8k,3899
|
|
|
11
11
|
urwid/str_util.py,sha256=1ss-LHAhjXTynTVBcoSgYWIpBeN_RirqHYhP7fq7MrA,10844
|
|
12
12
|
urwid/text_layout.py,sha256=lHiGfo7clmwHt5dMl_AaQSs2ov9IbY9JySTATZBm7h0,22821
|
|
13
13
|
urwid/util.py,sha256=pGXnma03_IBx3v6_qN9cDWPXPj_YjkhQ9IxLjm_0TpU,15747
|
|
14
|
-
urwid/version.py,sha256=
|
|
14
|
+
urwid/version.py,sha256=Q6B6SJpzx7ArqUrw_2w87t72hs-NzqHnm-ERmJDUGVM,413
|
|
15
15
|
urwid/vterm.py,sha256=q9-8dxJpVr_7a0Bj_z_FYDiRgzos3IS17BjhYcy1RDw,58410
|
|
16
16
|
urwid/wimp.py,sha256=o1YsjL_tBLXba8ZRr1MTHH0poLSlXT_atY3-uD_Ualg,567
|
|
17
17
|
urwid/display/__init__.py,sha256=y90WbHPNRHlimPrXhzsSfFsBbBHy8QErmB1y4Xza-xo,1732
|
|
@@ -53,22 +53,22 @@ urwid/widget/filler.py,sha256=EEnyAawdKXuwf79pErfNuvqsU1SVTutcMUrwWkU4wfo,14665
|
|
|
53
53
|
urwid/widget/frame.py,sha256=AOe4FwjvwcIwrpXqyZkCwSZWwAALNl1XRMAKx6ZXYWs,21834
|
|
54
54
|
urwid/widget/grid_flow.py,sha256=otujeOTWYDr4gwuDikBm9zZd8SUgma9yvQ1hDWI-dGk,21514
|
|
55
55
|
urwid/widget/line_box.py,sha256=V750xiZtkw6_uRXLhNY91ER3pXwwrZstVv_IJUZd_YY,6884
|
|
56
|
-
urwid/widget/listbox.py,sha256=
|
|
56
|
+
urwid/widget/listbox.py,sha256=EaGo13fpt4Oy9V00n27U-2PhOWa7-nmsTgnddKv9GII,74392
|
|
57
57
|
urwid/widget/monitored_list.py,sha256=8lBb8kowLAqKMKByiBZp4jt9PSnXjYAoAjXFXm-7xcg,18773
|
|
58
58
|
urwid/widget/overlay.py,sha256=7EtTHOomIF4xzwYiY7SiMCQZF2IHrmO88YeosFOMFo0,34505
|
|
59
59
|
urwid/widget/padding.py,sha256=tdBJybrKJqR8OLo5DHixn6KZA3tefYlfo9kkqvxYLEc,21252
|
|
60
60
|
urwid/widget/pile.py,sha256=aIzKYNrSQtbHVk_bn2PElHUiSdsO_NKnL4mTu-sXm4I,38628
|
|
61
61
|
urwid/widget/popup.py,sha256=UQ1MTzt8RNcfIvmwIqDM4mypxxXUOMsGoiozom8HfTg,5814
|
|
62
62
|
urwid/widget/progress_bar.py,sha256=HRnIu2V2_4wgsnAdrhK-GVVToyLaXRH0gtlkWllA4Mo,4767
|
|
63
|
-
urwid/widget/scrollable.py,sha256=
|
|
63
|
+
urwid/widget/scrollable.py,sha256=yB3S3k5dOdZ-wrQMlgxQH-1AZONSf5X6Y2accIa9tpk,24279
|
|
64
64
|
urwid/widget/solid_fill.py,sha256=NZRDSRK0lP4r7gXcKDgVaKEoeOcWvtrY5k2aueQEEL4,1260
|
|
65
65
|
urwid/widget/text.py,sha256=jy15hL6rCBoJdZviq2jJ-i9eO6vEcxvzCIVAZs12AUw,12187
|
|
66
66
|
urwid/widget/treetools.py,sha256=5s3Dnp2PCz4wQccutmdvsTTbAROJMLehXe4moB5POY0,17387
|
|
67
67
|
urwid/widget/widget.py,sha256=dMGNVewj2NGFdGKAtDJYgOzhuJAtrr_BALOMwNzUyj0,29550
|
|
68
68
|
urwid/widget/widget_decoration.py,sha256=aHP9Y7JKVCI2dw2OdRrzMj9p--C1pMIbxSJskWBLIgc,5633
|
|
69
69
|
urwid/widget/wimp.py,sha256=4wfzTQBLMbhicSlL64hBPb-1W5FAFrIKfb43i10MKSY,27305
|
|
70
|
-
urwid-2.6.
|
|
71
|
-
urwid-2.6.
|
|
72
|
-
urwid-2.6.
|
|
73
|
-
urwid-2.6.
|
|
74
|
-
urwid-2.6.
|
|
70
|
+
urwid-2.6.10.dist-info/COPYING,sha256=NrbT-keRaUP9X-wxPFhHhJRgR-wTN6eLRA5ZkstZX4k,26434
|
|
71
|
+
urwid-2.6.10.dist-info/METADATA,sha256=o9GKYe-Nt5Hkz7EF_S6E3DXp8CblUs66umXNmAj5-jI,11043
|
|
72
|
+
urwid-2.6.10.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
73
|
+
urwid-2.6.10.dist-info/top_level.txt,sha256=AwxQA43kNkjHbhYELXHBKrQ01X5CR2KnDzU07cVqilY,6
|
|
74
|
+
urwid-2.6.10.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|