wicd-curses – Fix für „AttributeError: ‚Screen‘ object has no attribute ‚get_input_nonblocking'“

Hallo Leute,

als Arch-User hat man öfters (eigentlich nicht so oft)  mit Problemen zu kämpfen. Seit dem letzten Update von python-urwid läuft „wicd-curses“ nicht mehr. Da laut Arch-Wiki „wicd“ nicht mehr weiterentwickelt wird, hab ich mich an einem (erfolgreichen) Fix probiert.

Der Bug

Es handelt sich um folgende Fehlermeldung:

$> wicd-curses 
Traceback (most recent call last):
 File "/usr/share/wicd/curses/wicd-curses.py", line 1063, in <module>
 main()
 File "/usr/share/wicd/curses/wicd-curses.py", line 995, in main
 ui.run_wrapper(run)
 File "/usr/lib/python2.7/site-packages/urwid/display_common.py", line 757, in run_wrapper
 return fn()
 File "/usr/share/wicd/curses/wicd-curses.py", line 88, in wrapper
 return func(*args, **kargs)
 File "/usr/share/wicd/curses/wicd-curses.py", line 1003, in run
 app = appGUI()
 File "/usr/share/wicd/curses/wicd-curses.py", line 591, in __init__
 self.update_status()
 File "/usr/share/wicd/curses/wicd-curses.py", line 88, in wrapper
 return func(*args, **kargs)
 File "/usr/share/wicd/curses/wicd-curses.py", line 734, in update_status
 self.set_status):
 File "/usr/share/wicd/curses/wicd-curses.py", line 88, in wrapper
 return func(*args, **kargs)
 File "/usr/share/wicd/curses/wicd-curses.py", line 161, in check_for_wireless
 ('$C', ip))
 File "/usr/share/wicd/curses/wicd-curses.py", line 781, in set_status
 self.update_ui()
 File "/usr/share/wicd/curses/wicd-curses.py", line 88, in wrapper
 return func(*args, **kargs)
 File "/usr/share/wicd/curses/wicd-curses.py", line 930, in update_ui
 input_data = ui.get_input_nonblocking()
AttributeError: 'Screen' object has no attribute 'get_input_nonblocking'

Nach einem Blick in den Quellcode (Zeile 930) und etwas Backtracking der Funktionen/Variablen stößt man auf:

import urwid.raw_display
ui = urwid.raw_display.Screen()

Der Fix

Werfen wir doch mal einen Blick in die Dokumentation: http://urwid.org/reference/display_modules.html

Dort wird nur noch „get_input()“ für das raw_display genannt, so dass die Eingabe blockierend verarbeitet wird. Mein erster Gedanke war, einen Thread für die Eingabe zu schreiben, aber dann las ich diese Zeile:

If there is no input pending it will wait before returning an empty list. The wait time may be configured with the set_input_timeouts function.

Also habe ich einfach die dazu passende Zeile eingebaut:

ui.set_input_timeouts(max_wait=0, complete_wait=0)

Der Patch

Noch zwei weitere kleine Änderungen waren nötig. Am Ende kommt dann folgender Patch raus:

--- /usr/share/wicd/curses/wicd-curses.py	2013-08-20 15:09:54.000000000 -0400
+++ /tmp/wicd.py	2014-12-05 23:32:05.303349880 -0500
@@ -927,9 +927,11 @@
         if not ui._started:
             return False
 
-        input_data = ui.get_input_nonblocking()
+        # input_data = ui.get_input_nonblocking()
+        ui.set_input_timeouts(max_wait=0)
+        input_data = ui.get_input()
         # Resolve any "alarms" in the waiting
-        self.handle_keys(input_data[1])
+        self.handle_keys(input_data) # [1]
 
         # Update the screen
         canvas = self.frame.render( (self.size),True )

Diesen speichert man sich als Datei unter „/tmp/wicd.patch“ und führt danach folgendes Kommando aus:

sudo patch /usr/share/wicd/curses/wicd-curses.py < /tmp/wicd.patch

Danach sollte „wicd-curses“ wieder laufen.

Die Mankos

Dadurch, dass das Einlesen der Tastendrücke nicht mehr wirklich im Hintergrund läuft, kam es bei der Nutzung der „ESC“-Taste zu Problemen. Diese wurde erst nach einem weiteren Tastendruck (z.B. Pfeil-runter) verarbeitet. Aber nunja, besser als ein kaputtes wicd-curses ist es allemal :)

~ Sebastian