af32c471b9a1 draft — Alain Leufroy 11 months ago
wip python3.11 and urwid 2.1 compat
M lairucrem/__init__.py +21 -13
@@ 9,6 9,12 @@ import contextlib
 import imp
 
 import urwid
+
+try:
+    from urwid import event_loop as urwid_event_loop
+except ImportError:
+    from urwid import main_loop as urwid_event_loop
+
 from pkg_resources import DistributionNotFound, get_distribution
 
 from . import config

          
@@ 42,14 48,15 @@ def _MAIN_WIDGET_FACTORY():
 
 
 def _get_raw_main_loop():
+    from urwid.raw_display import Screen
+
     from .widgets.mainwidget import popuplauncher
-    from urwid.raw_display import Screen
     screen = Screen()
     screen.set_terminal_properties(colors=256)
     screen.set_mouse_tracking(config.has_mouse_keybindings())
     return urwid.MainLoop(
         popuplauncher(_MAIN_WIDGET_FACTORY()),
-        event_loop=urwid.main_loop.AsyncioEventLoop(),
+        event_loop=urwid_event_loop.AsyncioEventLoop(),
         handle_mouse=config.has_mouse_keybindings(),
         screen=screen,
         palette=config.PALETTE, pop_ups=True)

          
@@ 109,15 116,16 @@ def interrupt_mainloop():
 
 def _get_curses_main_loop():    # noqa: C901
     """hugly workaround to make asyncio works with curses in urwid."""
-    from .widgets.mainwidget import popuplauncher
-    import urwid.main_loop
-    import urwid.curses_display
+    import asyncio
     import functools
     import heapq
     import time
-    import asyncio
+
+    import urwid.curses_display
 
-    class mainloop(urwid.main_loop.MainLoop):
+    from .widgets.mainwidget import popuplauncher
+
+    class mainloop(urwid_event_loop.MainLoop):
 
         def _run(self):
             self.start()

          
@@ 189,7 197,7 @@ def _get_curses_main_loop():    # noqa: 
     class screen(urwid.curses_display.Screen):
         hook_event_loop = None
 
-    class eventloop(urwid.main_loop.AsyncioEventLoop):
+    class eventloop(urwid_event_loop.AsyncioEventLoop):
 
         def __init__(self, **kwargs):
             self._alarms = []

          
@@ 197,22 205,22 @@ def _get_curses_main_loop():    # noqa: 
             super().__init__(**kwargs)
 
         def alarm(self, seconds, callback):
-            _handle = urwid.main_loop.SelectEventLoop.alarm(
+            _handle = urwid_event_loop.SelectEventLoop.alarm(
                 self, seconds, callback)
 
             def cb():
                 out = callback()
-                urwid.main_loop.SelectEventLoop.remove_alarm(self, _handle)
+                urwid_event_loop.SelectEventLoop.remove_alarm(self, _handle)
                 return out
 
-            handle = urwid.main_loop.AsyncioEventLoop.alarm(self, seconds, cb)
+            handle = urwid_event_loop.AsyncioEventLoop.alarm(self, seconds, cb)
             self._select_handles[handle] = _handle
             return handle
 
         def remove_alarm(self, handle):
             _handle = self._select_handles[handle]
-            urwid.main_loop.SelectEventLoop.remove_alarm(self, _handle)
-            return urwid.main_loop.AsyncioEventLoop.remove_alarm(self, handle)
+            urwid_event_loop.SelectEventLoop.remove_alarm(self, _handle)
+            return urwid_event_loop.AsyncioEventLoop.remove_alarm(self, handle)
 
     return mainloop(
         popuplauncher(_MAIN_WIDGET_FACTORY()),

          
M lairucrem/config.py +2 -1
@@ 170,7 170,8 @@ PALETTE = [
     ('diff.deleted', 'dark red', '', '', '#f00', ''),
     ('diff.deleted.focus', 'dark red,standout', '', 'standout', '#f00,bold', '#333'),
     ('diff.deleted.unchanged', 'dark red', '', '', '#fbb', ''),
-    ('diff.deleted.unchanged.focus', 'dark red,standout', '', 'dark red,standout', '#fff', '#fdd'),
+    ('diff.deleted.unchanged.focus', 'dark red,standout', '', '', '#fff', '#fbb'),
+    # ('diff.deleted.unchanged.focus', 'dark red,standout', '', 'dark red,standout', '#fff', '#fdd'),
     ('diff.deleted.changed', 'dark red', '', '', '#f00', ''),
     ('diff.deleted.changed.focus', 'light red,standout', '', 'standout', '#f00,bold', '#333'),
 

          
M lairucrem/mixin.py +2 -1
@@ 5,6 5,7 @@ 
 """UI widgets for lairucrem."""
 
 import asyncio
+import asyncio.tasks
 import itertools
 import re
 from functools import reduce

          
@@ 319,7 320,7 @@ class commandable_listbox(_key_to_signal
 
     async def _on_commandlist(self, *args):
         from .widgets import dialog  # prevent cyclic import
-        tasks = [getter(self.current_node, selectors=self._commands_selectors)
+        tasks = [asyncio.tasks.Task(getter(self.current_node, selectors=self._commands_selectors))
                  for getter in commands.cset_command_getters]
         cmd = await dialog.async_choices(tasks)
         if not cmd:

          
M lairucrem/patch_urwid.py +28 -24
@@ 2,35 2,39 @@ 
 import sys
 
 from urwid import ExitMainLoop
-from urwid.canvas import (
-    LayoutSegment, TextCanvas, apply_target_encoding, rle_append_modify,
-    rle_join_modify, rle_len, trim_line)
-from urwid.main_loop import AsyncioEventLoop
+from urwid.canvas import (LayoutSegment, TextCanvas, apply_target_encoding,
+                          rle_append_modify, rle_join_modify, rle_len,
+                          trim_line)
+
+try:
+    from urwid.event_loop import AsyncioEventLoop
+except ImportError:
+    from urwid.main_loop import AsyncioEventLoop
+
 from urwid.raw_display import Screen
 
 from .utils import monkeypatch
 
-
-# https://github.com/urwid/urwid/issues/221
-@monkeypatch(Screen, 'hook_event_loop')
-def fix_issue_221(self, event_loop, callback):
-    """
-    Register the given callback with the event loop, to be called with new
-    input whenever it's available.  The callback should be passed a list of
-    processed keys and a list of unprocessed keycodes.
+# # https://github.com/urwid/urwid/issues/221
+# @monkeypatch(Screen, 'hook_event_loop')
+# def fix_issue_221(self, event_loop, callback):
+#     """
+#     Register the given callback with the event loop, to be called with new
+#     input whenever it's available.  The callback should be passed a list of
+#     processed keys and a list of unprocessed keycodes.
 
-    Subclasses may wish to use parse_input to wrap the callback.
-    """
-    if hasattr(self, 'get_input_nonblocking'):
-        wrapper = self._make_legacy_input_wrapper(event_loop, callback)
-    else:
-        wrapper = lambda: self.parse_input(
-            event_loop, callback, self.get_available_raw_input())
-    fds = self.get_input_descriptors()
-    handles = [
-        event_loop.watch_file(fd, wrapper)
-        for fd in fds]
-    self._current_event_loop_handles = handles
+#     Subclasses may wish to use parse_input to wrap the callback.
+#     """
+#     if hasattr(self, 'get_input_nonblocking'):
+#         wrapper = self._make_legacy_input_wrapper(event_loop, callback)
+#     else:
+#         wrapper = lambda: self.parse_input(
+#             event_loop, callback, self.get_available_raw_input())
+#     fds = self.get_input_descriptors()
+#     handles = [
+#         event_loop.watch_file(fd, wrapper)
+#         for fd in fds]
+#     self._current_event_loop_handles = handles
 
 # Fix exception handling
 # https://github.com/urwid/urwid/pull/92 exists but not merged

          
M lairucrem/widgets/dialog.py +3 -1
@@ 1,4 1,5 @@ 
 import asyncio
+import asyncio.tasks
 import itertools
 import re
 from concurrent.futures import FIRST_COMPLETED

          
@@ 369,9 370,10 @@ async def async_choices(tasks):
     prolog = 'Theses action(s) can be applied to the selected changeset:'
     diag = choices([], title='ACTIONS', prolog=prolog)
     # also add the dialog task to break if the user responds early
-    tasks.append(diag.__await__())
+    tasks.append(asyncio.tasks.Task(diag.__await__()))
     while tasks:
         # consum tasks
+        config.logger.error(repr(tasks))
         dones, tasks = await asyncio.wait(tasks, return_when=FIRST_COMPLETED)
         if diag.done():  # user already answered ⇒ ignore new actions
             break