urwid 2.6.0.post0__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 (75) hide show
  1. urwid/__init__.py +333 -0
  2. urwid/canvas.py +1413 -0
  3. urwid/command_map.py +137 -0
  4. urwid/container.py +59 -0
  5. urwid/decoration.py +65 -0
  6. urwid/display/__init__.py +97 -0
  7. urwid/display/_posix_raw_display.py +413 -0
  8. urwid/display/_raw_display_base.py +914 -0
  9. urwid/display/_web.css +12 -0
  10. urwid/display/_web.js +462 -0
  11. urwid/display/_win32.py +171 -0
  12. urwid/display/_win32_raw_display.py +269 -0
  13. urwid/display/common.py +1219 -0
  14. urwid/display/curses.py +690 -0
  15. urwid/display/escape.py +624 -0
  16. urwid/display/html_fragment.py +251 -0
  17. urwid/display/lcd.py +518 -0
  18. urwid/display/raw.py +37 -0
  19. urwid/display/web.py +636 -0
  20. urwid/event_loop/__init__.py +55 -0
  21. urwid/event_loop/abstract_loop.py +175 -0
  22. urwid/event_loop/asyncio_loop.py +231 -0
  23. urwid/event_loop/glib_loop.py +294 -0
  24. urwid/event_loop/main_loop.py +721 -0
  25. urwid/event_loop/select_loop.py +230 -0
  26. urwid/event_loop/tornado_loop.py +206 -0
  27. urwid/event_loop/trio_loop.py +302 -0
  28. urwid/event_loop/twisted_loop.py +269 -0
  29. urwid/event_loop/zmq_loop.py +275 -0
  30. urwid/font.py +695 -0
  31. urwid/graphics.py +96 -0
  32. urwid/highlight.css +19 -0
  33. urwid/listbox.py +1899 -0
  34. urwid/monitored_list.py +522 -0
  35. urwid/numedit.py +376 -0
  36. urwid/signals.py +330 -0
  37. urwid/split_repr.py +130 -0
  38. urwid/str_util.py +358 -0
  39. urwid/text_layout.py +632 -0
  40. urwid/treetools.py +515 -0
  41. urwid/util.py +557 -0
  42. urwid/version.py +16 -0
  43. urwid/vterm.py +1806 -0
  44. urwid/widget/__init__.py +181 -0
  45. urwid/widget/attr_map.py +161 -0
  46. urwid/widget/attr_wrap.py +140 -0
  47. urwid/widget/bar_graph.py +649 -0
  48. urwid/widget/big_text.py +77 -0
  49. urwid/widget/box_adapter.py +126 -0
  50. urwid/widget/columns.py +1145 -0
  51. urwid/widget/constants.py +574 -0
  52. urwid/widget/container.py +227 -0
  53. urwid/widget/divider.py +110 -0
  54. urwid/widget/edit.py +718 -0
  55. urwid/widget/filler.py +403 -0
  56. urwid/widget/frame.py +539 -0
  57. urwid/widget/grid_flow.py +539 -0
  58. urwid/widget/line_box.py +194 -0
  59. urwid/widget/overlay.py +829 -0
  60. urwid/widget/padding.py +597 -0
  61. urwid/widget/pile.py +971 -0
  62. urwid/widget/popup.py +170 -0
  63. urwid/widget/progress_bar.py +141 -0
  64. urwid/widget/scrollable.py +597 -0
  65. urwid/widget/solid_fill.py +44 -0
  66. urwid/widget/text.py +354 -0
  67. urwid/widget/widget.py +852 -0
  68. urwid/widget/widget_decoration.py +166 -0
  69. urwid/widget/wimp.py +792 -0
  70. urwid/wimp.py +23 -0
  71. urwid-2.6.0.post0.dist-info/COPYING +504 -0
  72. urwid-2.6.0.post0.dist-info/METADATA +332 -0
  73. urwid-2.6.0.post0.dist-info/RECORD +75 -0
  74. urwid-2.6.0.post0.dist-info/WHEEL +5 -0
  75. urwid-2.6.0.post0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,181 @@
1
+ from __future__ import annotations
2
+
3
+ from .attr_map import AttrMap, AttrMapError
4
+ from .attr_wrap import AttrWrap
5
+ from .bar_graph import BarGraph, BarGraphError, BarGraphMeta, GraphVScale, scale_bar_values
6
+ from .big_text import BigText
7
+ from .box_adapter import BoxAdapter, BoxAdapterError
8
+ from .columns import Columns, ColumnsError, ColumnsWarning
9
+ from .constants import (
10
+ RELATIVE_100,
11
+ Align,
12
+ Sizing,
13
+ VAlign,
14
+ WHSettings,
15
+ WrapMode,
16
+ normalize_align,
17
+ normalize_height,
18
+ normalize_valign,
19
+ normalize_width,
20
+ simplify_align,
21
+ simplify_height,
22
+ simplify_valign,
23
+ simplify_width,
24
+ )
25
+ from .container import WidgetContainerListContentsMixin, WidgetContainerMixin
26
+ from .divider import Divider
27
+ from .edit import Edit, EditError, IntEdit
28
+ from .filler import Filler, FillerError, calculate_top_bottom_filler
29
+ from .frame import Frame, FrameError
30
+ from .grid_flow import GridFlow, GridFlowError
31
+ from .line_box import LineBox
32
+ from .overlay import Overlay, OverlayError, OverlayWarning
33
+ from .padding import Padding, PaddingError, PaddingWarning, calculate_left_right_padding
34
+ from .pile import Pile, PileError, PileWarning
35
+ from .popup import PopUpLauncher, PopUpTarget
36
+ from .progress_bar import ProgressBar
37
+ from .scrollable import Scrollable, ScrollableError, ScrollBar
38
+ from .solid_fill import SolidFill
39
+ from .text import Text, TextError
40
+ from .widget import (
41
+ BoxWidget,
42
+ FixedWidget,
43
+ FlowWidget,
44
+ Widget,
45
+ WidgetError,
46
+ WidgetMeta,
47
+ WidgetWarning,
48
+ WidgetWrap,
49
+ WidgetWrapError,
50
+ delegate_to_widget_mixin,
51
+ fixed_size,
52
+ nocache_widget_render,
53
+ nocache_widget_render_instance,
54
+ )
55
+ from .widget_decoration import WidgetDecoration, WidgetDisable, WidgetPlaceholder
56
+ from .wimp import Button, CheckBox, CheckBoxError, RadioButton, SelectableIcon
57
+
58
+ __all__ = (
59
+ "ANY",
60
+ "BOTTOM",
61
+ "BOX",
62
+ "CENTER",
63
+ "CLIP",
64
+ "ELLIPSIS",
65
+ "FIXED",
66
+ "FLOW",
67
+ "GIVEN",
68
+ "LEFT",
69
+ "MIDDLE",
70
+ "PACK",
71
+ "RELATIVE",
72
+ "RELATIVE_100",
73
+ "RIGHT",
74
+ "SPACE",
75
+ "TOP",
76
+ "WEIGHT",
77
+ "Align",
78
+ "AttrMap",
79
+ "AttrMapError",
80
+ "AttrWrap",
81
+ "BarGraph",
82
+ "BarGraphError",
83
+ "BarGraphMeta",
84
+ "BigText",
85
+ "BoxAdapter",
86
+ "BoxAdapterError",
87
+ "BoxWidget",
88
+ "Button",
89
+ "CheckBox",
90
+ "CheckBoxError",
91
+ "Columns",
92
+ "ColumnsError",
93
+ "ColumnsWarning",
94
+ "Divider",
95
+ "Edit",
96
+ "EditError",
97
+ "Filler",
98
+ "FillerError",
99
+ "FixedWidget",
100
+ "FlowWidget",
101
+ "Frame",
102
+ "FrameError",
103
+ "GraphVScale",
104
+ "GridFlow",
105
+ "GridFlowError",
106
+ "IntEdit",
107
+ "LineBox",
108
+ "Overlay",
109
+ "OverlayError",
110
+ "OverlayWarning",
111
+ "Padding",
112
+ "PaddingError",
113
+ "PaddingWarning",
114
+ "Pile",
115
+ "PileError",
116
+ "PileWarning",
117
+ "PopUpLauncher",
118
+ "PopUpTarget",
119
+ "ProgressBar",
120
+ "RadioButton",
121
+ "ScrollBar",
122
+ "Scrollable",
123
+ "ScrollableError",
124
+ "SelectableIcon",
125
+ "Sizing",
126
+ "SolidFill",
127
+ "Text",
128
+ "TextError",
129
+ "VAlign",
130
+ "WHSettings",
131
+ "Widget",
132
+ "WidgetContainerListContentsMixin",
133
+ "WidgetContainerMixin",
134
+ "WidgetDecoration",
135
+ "WidgetDisable",
136
+ "WidgetError",
137
+ "WidgetMeta",
138
+ "WidgetPlaceholder",
139
+ "WidgetWarning",
140
+ "WidgetWrap",
141
+ "WidgetWrapError",
142
+ "WrapMode",
143
+ "calculate_left_right_padding",
144
+ "calculate_top_bottom_filler",
145
+ "delegate_to_widget_mixin",
146
+ "fixed_size",
147
+ "nocache_widget_render",
148
+ "nocache_widget_render_instance",
149
+ "normalize_align",
150
+ "normalize_height",
151
+ "normalize_valign",
152
+ "normalize_width",
153
+ "scale_bar_values",
154
+ "simplify_align",
155
+ "simplify_height",
156
+ "simplify_valign",
157
+ "simplify_width",
158
+ )
159
+
160
+ # Backward compatibility
161
+ FLOW = Sizing.FLOW
162
+ BOX = Sizing.BOX
163
+ FIXED = Sizing.FIXED
164
+
165
+ LEFT = Align.LEFT
166
+ RIGHT = Align.RIGHT
167
+ CENTER = Align.CENTER
168
+
169
+ TOP = VAlign.TOP
170
+ MIDDLE = VAlign.MIDDLE
171
+ BOTTOM = VAlign.BOTTOM
172
+
173
+ SPACE = WrapMode.SPACE
174
+ ANY = WrapMode.ANY
175
+ CLIP = WrapMode.CLIP
176
+ ELLIPSIS = WrapMode.ELLIPSIS
177
+
178
+ PACK = WHSettings.PACK
179
+ GIVEN = WHSettings.GIVEN
180
+ RELATIVE = WHSettings.RELATIVE
181
+ WEIGHT = WHSettings.WEIGHT
@@ -0,0 +1,161 @@
1
+ from __future__ import annotations
2
+
3
+ import typing
4
+ from collections.abc import Hashable, Mapping
5
+
6
+ from urwid.canvas import CompositeCanvas
7
+
8
+ from .widget import WidgetError, delegate_to_widget_mixin
9
+ from .widget_decoration import WidgetDecoration
10
+
11
+ WrappedWidget = typing.TypeVar("WrappedWidget")
12
+
13
+
14
+ class AttrMapError(WidgetError):
15
+ pass
16
+
17
+
18
+ class AttrMap(delegate_to_widget_mixin("_original_widget"), WidgetDecoration[WrappedWidget]):
19
+ """
20
+ AttrMap is a decoration that maps one set of attributes to another.
21
+ This object will pass all function calls and variable references to the
22
+ wrapped widget.
23
+ """
24
+
25
+ def __init__(
26
+ self,
27
+ w: WrappedWidget,
28
+ attr_map: Hashable | Mapping[Hashable | None, Hashable] | None,
29
+ focus_map: Hashable | Mapping[Hashable | None, Hashable] | None = None,
30
+ ) -> None:
31
+ """
32
+ :param w: widget to wrap (stored as self.original_widget)
33
+ :type w: widget
34
+
35
+ :param attr_map: attribute to apply to *w*, or dict of old display
36
+ attribute: new display attribute mappings
37
+ :type attr_map: display attribute or dict
38
+
39
+ :param focus_map: attribute to apply when in focus or dict of
40
+ old display attribute: new display attribute mappings;
41
+ if ``None`` use *attr*
42
+ :type focus_map: display attribute or dict
43
+
44
+ >>> from urwid import Divider, Edit, Text
45
+ >>> AttrMap(Divider(u"!"), 'bright')
46
+ <AttrMap flow widget <Divider flow widget '!'> attr_map={None: 'bright'}>
47
+ >>> AttrMap(Edit(), 'notfocus', 'focus').attr_map
48
+ {None: 'notfocus'}
49
+ >>> AttrMap(Edit(), 'notfocus', 'focus').focus_map
50
+ {None: 'focus'}
51
+ >>> size = (5,)
52
+ >>> am = AttrMap(Text(u"hi"), 'greeting', 'fgreet')
53
+ >>> next(am.render(size, focus=False).content()) # ... = b in Python 3
54
+ [('greeting', None, ...'hi ')]
55
+ >>> next(am.render(size, focus=True).content())
56
+ [('fgreet', None, ...'hi ')]
57
+ >>> am2 = AttrMap(Text(('word', u"hi")), {'word':'greeting', None:'bg'})
58
+ >>> am2
59
+ <AttrMap fixed/flow widget <Text fixed/flow widget 'hi'> attr_map={'word': 'greeting', None: 'bg'}>
60
+ >>> next(am2.render(size).content())
61
+ [('greeting', None, ...'hi'), ('bg', None, ...' ')]
62
+ """
63
+ super().__init__(w)
64
+
65
+ if isinstance(attr_map, Mapping):
66
+ self.attr_map = dict(attr_map)
67
+ else:
68
+ self.attr_map = {None: attr_map}
69
+
70
+ if isinstance(focus_map, Mapping):
71
+ self.focus_map = dict(focus_map)
72
+ elif focus_map is None:
73
+ self.focus_map = focus_map
74
+ else:
75
+ self.focus_map = {None: focus_map}
76
+
77
+ def _repr_attrs(self) -> dict[str, typing.Any]:
78
+ # only include the focus_attr when it takes effect (not None)
79
+ d = {**super()._repr_attrs(), "attr_map": self._attr_map}
80
+ if self._focus_map is not None:
81
+ d["focus_map"] = self._focus_map
82
+ return d
83
+
84
+ def get_attr_map(self) -> dict[Hashable | None, Hashable]:
85
+ # make a copy so ours is not accidentally modified
86
+ # FIXME: a dictionary that detects modifications would be better
87
+ return dict(self._attr_map)
88
+
89
+ def set_attr_map(self, attr_map: dict[Hashable | None, Hashable] | None) -> None:
90
+ """
91
+ Set the attribute mapping dictionary {from_attr: to_attr, ...}
92
+
93
+ Note this function does not accept a single attribute the way the
94
+ constructor does. You must specify {None: attribute} instead.
95
+
96
+ >>> from urwid import Text
97
+ >>> w = AttrMap(Text(u"hi"), None)
98
+ >>> w.set_attr_map({'a':'b'})
99
+ >>> w
100
+ <AttrMap fixed/flow widget <Text fixed/flow widget 'hi'> attr_map={'a': 'b'}>
101
+ """
102
+ for from_attr, to_attr in attr_map.items():
103
+ if not isinstance(from_attr, Hashable) or not isinstance(to_attr, Hashable):
104
+ raise AttrMapError(
105
+ f"{from_attr!r}:{to_attr!r} attribute mapping is invalid. Attributes must be hashable"
106
+ )
107
+
108
+ self._attr_map = attr_map
109
+ self._invalidate()
110
+
111
+ attr_map = property(get_attr_map, set_attr_map)
112
+
113
+ def get_focus_map(self) -> dict[Hashable | None, Hashable] | None:
114
+ # make a copy so ours is not accidentally modified
115
+ # FIXME: a dictionary that detects modifications would be better
116
+ if self._focus_map:
117
+ return dict(self._focus_map)
118
+ return None
119
+
120
+ def set_focus_map(self, focus_map: dict[Hashable | None, Hashable] | None) -> None:
121
+ """
122
+ Set the focus attribute mapping dictionary
123
+ {from_attr: to_attr, ...}
124
+
125
+ If None this widget will use the attr mapping instead (no change
126
+ when in focus).
127
+
128
+ Note this function does not accept a single attribute the way the
129
+ constructor does. You must specify {None: attribute} instead.
130
+
131
+ >>> from urwid import Text
132
+ >>> w = AttrMap(Text(u"hi"), {})
133
+ >>> w.set_focus_map({'a':'b'})
134
+ >>> w
135
+ <AttrMap fixed/flow widget <Text fixed/flow widget 'hi'> attr_map={} focus_map={'a': 'b'}>
136
+ >>> w.set_focus_map(None)
137
+ >>> w
138
+ <AttrMap fixed/flow widget <Text fixed/flow widget 'hi'> attr_map={}>
139
+ """
140
+ if focus_map is not None:
141
+ for from_attr, to_attr in focus_map.items():
142
+ if not isinstance(from_attr, Hashable) or not isinstance(to_attr, Hashable):
143
+ raise AttrMapError(
144
+ f"{from_attr!r}:{to_attr!r} attribute mapping is invalid. Attributes must be hashable"
145
+ )
146
+ self._focus_map = focus_map
147
+ self._invalidate()
148
+
149
+ focus_map = property(get_focus_map, set_focus_map)
150
+
151
+ def render(self, size, focus: bool = False) -> CompositeCanvas:
152
+ """
153
+ Render wrapped widget and apply attribute. Return canvas.
154
+ """
155
+ attr_map = self._attr_map
156
+ if focus and self._focus_map is not None:
157
+ attr_map = self._focus_map
158
+ canv = self._original_widget.render(size, focus=focus)
159
+ canv = CompositeCanvas(canv)
160
+ canv.fill_attr_apply(attr_map)
161
+ return canv
@@ -0,0 +1,140 @@
1
+ from __future__ import annotations
2
+
3
+ import typing
4
+ import warnings
5
+
6
+ from .attr_map import AttrMap
7
+
8
+ if typing.TYPE_CHECKING:
9
+ from .constants import Sizing
10
+ from .widget import Widget
11
+
12
+
13
+ class AttrWrap(AttrMap):
14
+ def __init__(self, w: Widget, attr, focus_attr=None):
15
+ """
16
+ w -- widget to wrap (stored as self.original_widget)
17
+ attr -- attribute to apply to w
18
+ focus_attr -- attribute to apply when in focus, if None use attr
19
+
20
+ This widget is a special case of the new AttrMap widget, and it
21
+ will pass all function calls and variable references to the wrapped
22
+ widget. This class is maintained for backwards compatibility only,
23
+ new code should use AttrMap instead.
24
+
25
+ >>> from urwid import Divider, Edit, Text
26
+ >>> AttrWrap(Divider(u"!"), 'bright')
27
+ <AttrWrap flow widget <Divider flow widget '!'> attr='bright'>
28
+ >>> AttrWrap(Edit(), 'notfocus', 'focus')
29
+ <AttrWrap selectable flow widget <Edit selectable flow widget '' edit_pos=0> attr='notfocus' focus_attr='focus'>
30
+ >>> size = (5,)
31
+ >>> aw = AttrWrap(Text(u"hi"), 'greeting', 'fgreet')
32
+ >>> next(aw.render(size, focus=False).content())
33
+ [('greeting', None, ...'hi ')]
34
+ >>> next(aw.render(size, focus=True).content())
35
+ [('fgreet', None, ...'hi ')]
36
+ """
37
+ warnings.warn(
38
+ "AttrWrap is maintained for backwards compatibility only, new code should use AttrMap instead.",
39
+ PendingDeprecationWarning,
40
+ stacklevel=2,
41
+ )
42
+ super().__init__(w, attr, focus_attr)
43
+
44
+ def _repr_attrs(self) -> dict[str, typing.Any]:
45
+ # only include the focus_attr when it takes effect (not None)
46
+ d = {**super()._repr_attrs(), "attr": self.attr}
47
+ del d["attr_map"]
48
+ if "focus_map" in d:
49
+ del d["focus_map"]
50
+ if self.focus_attr is not None:
51
+ d["focus_attr"] = self.focus_attr
52
+ return d
53
+
54
+ @property
55
+ def w(self) -> Widget:
56
+ """backwards compatibility, widget used to be stored as w"""
57
+ warnings.warn(
58
+ "backwards compatibility, widget used to be stored as original_widget",
59
+ PendingDeprecationWarning,
60
+ stacklevel=2,
61
+ )
62
+ return self.original_widget
63
+
64
+ @w.setter
65
+ def w(self, new_widget: Widget) -> None:
66
+ warnings.warn(
67
+ "backwards compatibility, widget used to be stored as original_widget",
68
+ PendingDeprecationWarning,
69
+ stacklevel=2,
70
+ )
71
+ self.original_widget = new_widget
72
+
73
+ def get_w(self):
74
+ warnings.warn(
75
+ "backwards compatibility, widget used to be stored as original_widget",
76
+ DeprecationWarning,
77
+ stacklevel=2,
78
+ )
79
+ return self.original_widget
80
+
81
+ def set_w(self, new_widget: Widget) -> None:
82
+ warnings.warn(
83
+ "backwards compatibility, widget used to be stored as original_widget",
84
+ DeprecationWarning,
85
+ stacklevel=2,
86
+ )
87
+ self.original_widget = new_widget
88
+
89
+ def get_attr(self):
90
+ return self.attr_map[None]
91
+
92
+ def set_attr(self, attr):
93
+ """
94
+ Set the attribute to apply to the wrapped widget
95
+
96
+ >> w = AttrWrap(Divider("-"), None)
97
+ >> w.set_attr('new_attr')
98
+ >> w
99
+ <AttrWrap flow widget <Divider flow widget '-'> attr='new_attr'>
100
+ """
101
+ self.set_attr_map({None: attr})
102
+
103
+ attr = property(get_attr, set_attr)
104
+
105
+ def get_focus_attr(self):
106
+ focus_map = self.focus_map
107
+ if focus_map:
108
+ return focus_map[None]
109
+ return None
110
+
111
+ def set_focus_attr(self, focus_attr):
112
+ """
113
+ Set the attribute to apply to the wapped widget when it is in
114
+ focus
115
+
116
+ If None this widget will use the attr instead (no change when in
117
+ focus).
118
+
119
+ >> w = AttrWrap(Divider("-"), 'old')
120
+ >> w.set_focus_attr('new_attr')
121
+ >> w
122
+ <AttrWrap flow widget <Divider flow widget '-'> attr='old' focus_attr='new_attr'>
123
+ >> w.set_focus_attr(None)
124
+ >> w
125
+ <AttrWrap flow widget <Divider flow widget '-'> attr='old'>
126
+ """
127
+ self.set_focus_map({None: focus_attr})
128
+
129
+ focus_attr = property(get_focus_attr, set_focus_attr)
130
+
131
+ def __getattr__(self, name: str):
132
+ """
133
+ Call getattr on wrapped widget. This has been the longstanding
134
+ behaviour of AttrWrap, but is discouraged. New code should be
135
+ using AttrMap and .base_widget or .original_widget instead.
136
+ """
137
+ return getattr(self._original_widget, name)
138
+
139
+ def sizing(self) -> frozenset[Sizing]:
140
+ return self._original_widget.sizing()