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,275 @@
1
+ # Urwid main loop code using ZeroMQ queues
2
+ # Copyright (C) 2019 Dave Jones
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
+ """ZeroMQ based urwid EventLoop implementation.
21
+
22
+ `ZeroMQ <https://zeromq.org>`_ library is required.
23
+ """
24
+
25
+ from __future__ import annotations
26
+
27
+ import contextlib
28
+ import errno
29
+ import heapq
30
+ import logging
31
+ import os
32
+ import time
33
+ import typing
34
+ from itertools import count
35
+
36
+ import zmq
37
+
38
+ from .abstract_loop import EventLoop, ExitMainLoop
39
+
40
+ if typing.TYPE_CHECKING:
41
+ from collections.abc import Callable
42
+ from concurrent.futures import Executor, Future
43
+
44
+ from typing_extensions import ParamSpec
45
+
46
+ ZMQAlarmHandle = typing.TypeVar("ZMQAlarmHandle")
47
+ _T = typing.TypeVar("_T")
48
+ _Spec = ParamSpec("_Spec")
49
+
50
+
51
+ class ZMQEventLoop(EventLoop):
52
+ """
53
+ This class is an urwid event loop for `ZeroMQ`_ applications. It is very
54
+ similar to :class:`SelectEventLoop`, supporting the usual :meth:`alarm`
55
+ events and file watching (:meth:`watch_file`) capabilities, but also
56
+ incorporates the ability to watch zmq queues for events
57
+ (:meth:`watch_queue`).
58
+
59
+ .. _ZeroMQ: https://zeromq.org/
60
+ """
61
+
62
+ _alarm_break = count()
63
+
64
+ def __init__(self):
65
+ super().__init__()
66
+ self.logger = logging.getLogger(__name__).getChild(self.__class__.__name__)
67
+ self._did_something = True
68
+ self._alarms = []
69
+ self._poller = zmq.Poller()
70
+ self._queue_callbacks = {}
71
+ self._idle_handle = 0
72
+ self._idle_callbacks = {}
73
+
74
+ def run_in_executor(
75
+ self,
76
+ executor: Executor,
77
+ func: Callable[_Spec, _T],
78
+ *args: _Spec.args,
79
+ **kwargs: _Spec.kwargs,
80
+ ) -> Future[_T]:
81
+ """Run callable in executor.
82
+
83
+ :param executor: Executor to use for running the function
84
+ :type executor: concurrent.futures.Executor
85
+ :param func: function to call
86
+ :type func: Callable
87
+ :param args: positional arguments to function
88
+ :type args: object
89
+ :param kwargs: keyword arguments to function
90
+ :type kwargs: object
91
+ :return: future object for the function call outcome.
92
+ :rtype: concurrent.futures.Future
93
+ """
94
+ return executor.submit(func, *args, **kwargs)
95
+
96
+ def alarm(self, seconds: float, callback: Callable[[], typing.Any]) -> ZMQAlarmHandle:
97
+ """
98
+ Call *callback* a given time from now. No parameters are passed to
99
+ callback. Returns a handle that may be passed to :meth:`remove_alarm`.
100
+
101
+ :param float seconds:
102
+ floating point time to wait before calling callback.
103
+
104
+ :param callback:
105
+ function to call from event loop.
106
+ """
107
+ handle = (time.time() + seconds, next(self._alarm_break), callback)
108
+ heapq.heappush(self._alarms, handle)
109
+ return handle
110
+
111
+ def remove_alarm(self, handle: ZMQAlarmHandle) -> bool:
112
+ """
113
+ Remove an alarm. Returns ``True`` if the alarm exists, ``False``
114
+ otherwise.
115
+ """
116
+ try:
117
+ self._alarms.remove(handle)
118
+ heapq.heapify(self._alarms)
119
+
120
+ except ValueError:
121
+ return False
122
+
123
+ return True
124
+
125
+ def watch_queue(
126
+ self,
127
+ queue: zmq.Socket,
128
+ callback: Callable[[], typing.Any],
129
+ flags: int = zmq.POLLIN,
130
+ ) -> zmq.Socket:
131
+ """
132
+ Call *callback* when zmq *queue* has something to read (when *flags* is
133
+ set to ``POLLIN``, the default) or is available to write (when *flags*
134
+ is set to ``POLLOUT``). No parameters are passed to the callback.
135
+ Returns a handle that may be passed to :meth:`remove_watch_queue`.
136
+
137
+ :param queue:
138
+ The zmq queue to poll.
139
+
140
+ :param callback:
141
+ The function to call when the poll is successful.
142
+
143
+ :param int flags:
144
+ The condition to monitor on the queue (defaults to ``POLLIN``).
145
+ """
146
+ if queue in self._queue_callbacks:
147
+ raise ValueError(f"already watching {queue!r}")
148
+ self._poller.register(queue, flags)
149
+ self._queue_callbacks[queue] = callback
150
+ return queue
151
+
152
+ def watch_file(
153
+ self,
154
+ fd: int,
155
+ callback: Callable[[], typing.Any],
156
+ flags: int = zmq.POLLIN,
157
+ ) -> int:
158
+ """
159
+ Call *callback* when *fd* has some data to read. No parameters are
160
+ passed to the callback. The *flags* are as for :meth:`watch_queue`.
161
+ Returns a handle that may be passed to :meth:`remove_watch_file`.
162
+
163
+ :param fd:
164
+ The file-like object, or fileno to monitor.
165
+
166
+ :param callback:
167
+ The function to call when the file has data available.
168
+
169
+ :param int flags:
170
+ The condition to monitor on the file (defaults to ``POLLIN``).
171
+ """
172
+ if isinstance(fd, int):
173
+ fd = os.fdopen(fd)
174
+ self._poller.register(fd, flags)
175
+ self._queue_callbacks[fd.fileno()] = callback
176
+ return fd
177
+
178
+ def remove_watch_queue(self, handle: zmq.Socket) -> bool:
179
+ """
180
+ Remove a queue from background polling. Returns ``True`` if the queue
181
+ was being monitored, ``False`` otherwise.
182
+ """
183
+ try:
184
+ try:
185
+ self._poller.unregister(handle)
186
+ finally:
187
+ self._queue_callbacks.pop(handle, None)
188
+
189
+ except KeyError:
190
+ return False
191
+
192
+ return True
193
+
194
+ def remove_watch_file(self, handle: int) -> bool:
195
+ """
196
+ Remove a file from background polling. Returns ``True`` if the file was
197
+ being monitored, ``False`` otherwise.
198
+ """
199
+ try:
200
+ try:
201
+ self._poller.unregister(handle)
202
+ finally:
203
+ self._queue_callbacks.pop(handle.fileno(), None)
204
+
205
+ except KeyError:
206
+ return False
207
+
208
+ return True
209
+
210
+ def enter_idle(self, callback: Callable[[], typing.Any]) -> int:
211
+ """
212
+ Add a *callback* to be executed when the event loop detects it is idle.
213
+ Returns a handle that may be passed to :meth:`remove_enter_idle`.
214
+ """
215
+ self._idle_handle += 1
216
+ self._idle_callbacks[self._idle_handle] = callback
217
+ return self._idle_handle
218
+
219
+ def remove_enter_idle(self, handle: int) -> bool:
220
+ """
221
+ Remove an idle callback. Returns ``True`` if *handle* was removed,
222
+ ``False`` otherwise.
223
+ """
224
+ try:
225
+ del self._idle_callbacks[handle]
226
+ except KeyError:
227
+ return False
228
+
229
+ return True
230
+
231
+ def _entering_idle(self) -> None:
232
+ for callback in list(self._idle_callbacks.values()):
233
+ callback()
234
+
235
+ def run(self) -> None:
236
+ """
237
+ Start the event loop. Exit the loop when any callback raises an
238
+ exception. If :exc:`ExitMainLoop` is raised, exit cleanly.
239
+ """
240
+ with contextlib.suppress(ExitMainLoop):
241
+ while True:
242
+ try:
243
+ self._loop()
244
+ except zmq.error.ZMQError as exc: # noqa: PERF203
245
+ if exc.errno != errno.EINTR:
246
+ raise
247
+
248
+ def _loop(self) -> None:
249
+ """
250
+ A single iteration of the event loop.
251
+ """
252
+ if self._alarms or self._did_something:
253
+ if self._alarms:
254
+ state = "alarm"
255
+ timeout = max(0, self._alarms[0][0] - time.time())
256
+ if self._did_something and (not self._alarms or (self._alarms and timeout > 0)):
257
+ state = "idle"
258
+ timeout = 0
259
+ ready = dict(self._poller.poll(timeout * 1000))
260
+ else:
261
+ state = "wait"
262
+ ready = dict(self._poller.poll())
263
+
264
+ if not ready:
265
+ if state == "idle":
266
+ self._entering_idle()
267
+ self._did_something = False
268
+ elif state == "alarm":
269
+ _due, _tie_break, callback = heapq.heappop(self._alarms)
270
+ callback()
271
+ self._did_something = True
272
+
273
+ for queue in ready:
274
+ self._queue_callbacks[queue]()
275
+ self._did_something = True