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,269 @@
1
+ # Urwid raw display module
2
+ # Copyright (C) 2004-2009 Ian Ward
3
+ #
4
+ # This library is free software; you can redistribute it and/or
5
+ # modify it under the terms of the GNU Lesser General Public
6
+ # License as published by the Free Software Foundation; either
7
+ # version 2.1 of the License, or (at your option) any later version.
8
+ #
9
+ # This library is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
+ # Lesser General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU Lesser General Public
15
+ # License along with this library; if not, write to the Free Software
16
+ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
+ #
18
+ # Urwid web site: https://urwid.org/
19
+
20
+
21
+ """
22
+ Direct terminal UI implementation
23
+ """
24
+
25
+ from __future__ import annotations
26
+
27
+ import contextlib
28
+ import functools
29
+ import logging
30
+ import selectors
31
+ import socket
32
+ import sys
33
+ import threading
34
+ import typing
35
+ from ctypes import byref
36
+ from ctypes.wintypes import DWORD
37
+
38
+ from urwid import signals
39
+
40
+ from . import _raw_display_base, _win32, escape
41
+ from .common import INPUT_DESCRIPTORS_CHANGED
42
+
43
+ if typing.TYPE_CHECKING:
44
+ import io
45
+ from collections.abc import Callable
46
+
47
+ from urwid.event_loop import EventLoop
48
+
49
+
50
+ class Screen(_raw_display_base.Screen):
51
+ _term_input_file: socket.socket
52
+
53
+ def __init__(
54
+ self,
55
+ input: socket.socket | None = None, # noqa: A002 # pylint: disable=redefined-builtin
56
+ output: io.TextIOBase = sys.stdout,
57
+ ) -> None:
58
+ """Initialize a screen that directly prints escape codes to an output
59
+ terminal.
60
+ """
61
+ if input is None:
62
+ input, self._send_input = socket.socketpair() # noqa: A001
63
+
64
+ super().__init__(input, output)
65
+
66
+ _dwOriginalOutMode = None
67
+ _dwOriginalInMode = None
68
+
69
+ def _start(self, alternate_buffer: bool = True) -> None:
70
+ """
71
+ Initialize the screen and input mode.
72
+
73
+ alternate_buffer -- use alternate screen buffer
74
+ """
75
+ if alternate_buffer:
76
+ self.write(escape.SWITCH_TO_ALTERNATE_BUFFER)
77
+ self._rows_used = None
78
+ else:
79
+ self._rows_used = 0
80
+
81
+ handle_out = _win32.GetStdHandle(_win32.STD_OUTPUT_HANDLE)
82
+ handle_in = _win32.GetStdHandle(_win32.STD_INPUT_HANDLE)
83
+ self._dwOriginalOutMode = DWORD()
84
+ self._dwOriginalInMode = DWORD()
85
+ _win32.GetConsoleMode(handle_out, byref(self._dwOriginalOutMode))
86
+ _win32.GetConsoleMode(handle_in, byref(self._dwOriginalInMode))
87
+ # TODO: Restore on exit
88
+
89
+ dword_out_mode = DWORD(
90
+ self._dwOriginalOutMode.value
91
+ | _win32.ENABLE_VIRTUAL_TERMINAL_PROCESSING
92
+ | _win32.DISABLE_NEWLINE_AUTO_RETURN
93
+ )
94
+ dword_in_mode = DWORD(
95
+ self._dwOriginalInMode.value | _win32.ENABLE_WINDOW_INPUT | _win32.ENABLE_VIRTUAL_TERMINAL_INPUT
96
+ )
97
+
98
+ ok = _win32.SetConsoleMode(handle_out, dword_out_mode)
99
+ if not ok:
100
+ raise RuntimeError(f"ConsoleMode set failed for output. Err: {ok!r}")
101
+ ok = _win32.SetConsoleMode(handle_in, dword_in_mode)
102
+ if not ok:
103
+ raise RuntimeError(f"ConsoleMode set failed for input. Err: {ok!r}")
104
+ self._alternate_buffer = alternate_buffer
105
+ self._next_timeout = self.max_wait
106
+
107
+ signals.emit_signal(self, INPUT_DESCRIPTORS_CHANGED)
108
+ # restore mouse tracking to previous state
109
+ self._mouse_tracking(self._mouse_tracking_enabled)
110
+
111
+ return super()._start()
112
+
113
+ def _stop(self) -> None:
114
+ """
115
+ Restore the screen.
116
+ """
117
+ self.clear()
118
+
119
+ signals.emit_signal(self, INPUT_DESCRIPTORS_CHANGED)
120
+
121
+ self._stop_mouse_restore_buffer()
122
+
123
+ handle_out = _win32.GetStdHandle(_win32.STD_OUTPUT_HANDLE)
124
+ handle_in = _win32.GetStdHandle(_win32.STD_INPUT_HANDLE)
125
+ ok = _win32.SetConsoleMode(handle_out, self._dwOriginalOutMode)
126
+ if not ok:
127
+ raise RuntimeError(f"ConsoleMode set failed for output. Err: {ok!r}")
128
+ ok = _win32.SetConsoleMode(handle_in, self._dwOriginalInMode)
129
+ if not ok:
130
+ raise RuntimeError(f"ConsoleMode set failed for input. Err: {ok!r}")
131
+
132
+ super()._stop()
133
+
134
+ def unhook_event_loop(self, event_loop: EventLoop) -> None:
135
+ """
136
+ Remove any hooks added by hook_event_loop.
137
+ """
138
+ if self._input_thread is not None:
139
+ self._input_thread.should_exit = True
140
+
141
+ with contextlib.suppress(RuntimeError):
142
+ self._input_thread.join(5)
143
+
144
+ self._input_thread = None
145
+
146
+ for handle in self._current_event_loop_handles:
147
+ event_loop.remove_watch_file(handle)
148
+
149
+ if self._input_timeout:
150
+ event_loop.remove_alarm(self._input_timeout)
151
+ self._input_timeout = None
152
+
153
+ def hook_event_loop(
154
+ self,
155
+ event_loop: EventLoop,
156
+ callback: Callable[[list[str], list[int]], typing.Any],
157
+ ) -> None:
158
+ """
159
+ Register the given callback with the event loop, to be called with new
160
+ input whenever it's available. The callback should be passed a list of
161
+ processed keys and a list of unprocessed keycodes.
162
+
163
+ Subclasses may wish to use parse_input to wrap the callback.
164
+ """
165
+ self._input_thread = ReadInputThread(self._send_input, lambda: self._sigwinch_handler(28))
166
+ self._input_thread.start()
167
+ if hasattr(self, "get_input_nonblocking"):
168
+ wrapper = self._make_legacy_input_wrapper(event_loop, callback)
169
+ else:
170
+
171
+ @functools.wraps(callback)
172
+ def wrapper() -> tuple[list[str], typing.Any] | None:
173
+ return self.parse_input(event_loop, callback, self.get_available_raw_input())
174
+
175
+ fds = self.get_input_descriptors()
176
+ handles = [event_loop.watch_file(fd if isinstance(fd, int) else fd.fileno(), wrapper) for fd in fds]
177
+ self._current_event_loop_handles = handles
178
+
179
+ _input_thread: ReadInputThread | None = None
180
+
181
+ def _read_raw_input(self, timeout: int) -> bytearray:
182
+ ready = self._wait_for_input_ready(timeout)
183
+
184
+ fd = self._input_fileno()
185
+ chars = bytearray()
186
+
187
+ if fd is None or fd not in ready:
188
+ return chars
189
+
190
+ with selectors.DefaultSelector() as selector:
191
+ selector.register(fd, selectors.EVENT_READ)
192
+ input_ready = selector.select(0)
193
+ while input_ready:
194
+ chars.extend(self._term_input_file.recv(1024))
195
+ input_ready = selector.select(0)
196
+
197
+ return chars
198
+
199
+ def get_cols_rows(self) -> tuple[int, int]:
200
+ """Return the terminal dimensions (num columns, num rows)."""
201
+ y, x = super().get_cols_rows()
202
+ with contextlib.suppress(OSError): # Term size could not be determined
203
+ if hasattr(self._term_output_file, "fileno"):
204
+ if self._term_output_file != sys.stdout:
205
+ raise RuntimeError("Unexpected terminal output file")
206
+ handle = _win32.GetStdHandle(_win32.STD_OUTPUT_HANDLE)
207
+ info = _win32.CONSOLE_SCREEN_BUFFER_INFO()
208
+ ok = _win32.GetConsoleScreenBufferInfo(handle, byref(info))
209
+ if ok:
210
+ # Fallback will be used in case of term size could not be determined
211
+ y, x = info.dwSize.Y, info.dwSize.X
212
+
213
+ self.maxrow = y
214
+ return x, y
215
+
216
+
217
+ class ReadInputThread(threading.Thread):
218
+ name = "urwid Windows input reader"
219
+ daemon = True
220
+ should_exit: bool = False
221
+
222
+ def __init__(
223
+ self,
224
+ input_socket: socket.socket,
225
+ resize: Callable[[], typing.Any],
226
+ ) -> None:
227
+ self._input = input_socket
228
+ self._resize = resize
229
+ self.logger = logging.getLogger(__name__).getChild(self.__class__.__name__)
230
+ super().__init__()
231
+
232
+ def run(self) -> None:
233
+ hIn = _win32.GetStdHandle(_win32.STD_INPUT_HANDLE)
234
+ MAX = 2048
235
+
236
+ read = DWORD(0)
237
+ arrtype = _win32.INPUT_RECORD * MAX
238
+ input_records = arrtype()
239
+
240
+ while True:
241
+ _win32.ReadConsoleInputW(hIn, byref(input_records), MAX, byref(read))
242
+ if self.should_exit:
243
+ return
244
+ for i in range(read.value):
245
+ inp = input_records[i]
246
+ if inp.EventType == _win32.EventType.KEY_EVENT:
247
+ if not inp.Event.KeyEvent.bKeyDown:
248
+ continue
249
+
250
+ input_data = inp.Event.KeyEvent.uChar.AsciiChar
251
+ # On Windows atomic press/release of modifier keys produce phantom input with code NULL
252
+ # This input cannot be decoded and should be handled as garbage.
253
+ if input_data != b"\x00":
254
+ self._input.send(input_data)
255
+
256
+ elif inp.EventType == _win32.EventType.WINDOW_BUFFER_SIZE_EVENT:
257
+ self._resize()
258
+ else:
259
+ pass # TODO: handle mouse events
260
+
261
+
262
+ def _test():
263
+ import doctest
264
+
265
+ doctest.testmod()
266
+
267
+
268
+ if __name__ == "__main__":
269
+ _test()