zeth / inputs

Cross-platform Python support for keyboards, mice and gamepads
BSD 3-Clause "New" or "Revised" License
267 stars 88 forks source link

KeyError whenever I try to create a device manager #66

Open jgarvin opened 5 years ago

jgarvin commented 5 years ago

If I just import devices everything works fine, but I decided I wanted to loop trying over and over again if the joystick couldn't be found, and I was getting the same device list over and over again even after plugging in my device so I figured I needed to create my own device manager in order to get a refreshed device list. Then I discovered I can never construct my own DeviceManager, I always get this traceback.

Dec 20 15:12:56 eruv bash[11092]: File "/home/prophet/mandimus/joystick.py", line 110, in joystick_event_loop Dec 20 15:12:56 eruv bash[11092]: device_manager = DeviceManager() # re-create every loop in case plugged in Dec 20 15:12:56 eruv bash[11092]: File "/home/prophet/.local/lib/python2.7/site-packages/inputs.py", line 3188, in init Dec 20 15:12:56 eruv bash[11092]: self._post_init() Dec 20 15:12:56 eruv bash[11092]: File "/home/prophet/.local/lib/python2.7/site-packages/inputs.py", line 3200, in _post_init Dec 20 15:12:56 eruv bash[11092]: self._find_leds() Dec 20 15:12:56 eruv bash[11092]: File "/home/prophet/.local/lib/python2.7/site-packages/inputs.py", line 3359, in _find_leds Dec 20 15:12:56 eruv bash[11092]: self._parse_led_path(path) Dec 20 15:12:56 eruv bash[11092]: File "/home/prophet/.local/lib/python2.7/site-packages/inputs.py", line 3366, in _parse_led_path Dec 20 15:12:56 eruv bash[11092]: self.leds.append(SystemLED(self, path, name)) Dec 20 15:12:56 eruv bash[11092]: File "/home/prophet/.local/lib/python2.7/site-packages/inputs.py", line 3082, in init Dec 20 15:12:56 eruv bash[11092]: super(SystemLED, self).init(manager, path, name) Dec 20 15:12:56 eruv bash[11092]: File "/home/prophet/.local/lib/python2.7/site-packages/inputs.py", line 3003, in init Dec 20 15:12:56 eruv bash[11092]: self._post_init() Dec 20 15:12:56 eruv bash[11092]: File "/home/prophet/.local/lib/python2.7/site-packages/inputs.py", line 3086, in _post_init Dec 20 15:12:56 eruv bash[11092]: self._led_type_code = self.manager.get_typecode('LED') Dec 20 15:12:56 eruv bash[11092]: File "/home/prophet/.local/lib/python2.7/site-packages/inputs.py", line 3421, in get_typecode Dec 20 15:12:56 eruv bash[11092]: return self.codes['type_codes'][name] Dec 20 15:12:56 eruv bash[11092]: KeyError: 'LED'

dkumor commented 5 years ago

I get the same error in Python 3.7, arch linux, with pip version of inputs.

j3kestrel commented 3 years ago

inputs.EVENT_MAP['type_codes'] is a generator. As such, the value of inputs.EVENT_MAP can only be used once. Since it is used as part of DeviceManager.__init__(), only one DeviceManager can be constructed. If the generator is replaced with a tuple, then DeviceManager can be constructed an arbitrary number of times to re-scan for devices.

Below is my hack to use the standard distribution. The correct fix would be to change the distributed file to use a tuple for type_codes as I have done below. I will try to submit a pull-request for this. ...but this project doesn't appear to be getting much love for the past years.


import inputs

inputs.EVENT_MAP = (
    ('types', inputs.EVENT_TYPES),
    ('type_codes', tuple((value, key) for key, value in inputs.EVENT_TYPES)),
    ('wincodes', inputs.WINCODES),
    ('specials', inputs.SPECIAL_DEVICES),
    ('xpad', inputs.XINPUT_MAPPING),
    ('Sync', inputs.SYNCHRONIZATION_EVENTS),
    ('Key', inputs.KEYS_AND_BUTTONS),
    ('Relative', inputs.RELATIVE_AXES),
    ('Absolute', inputs.ABSOLUTE_AXES),
    ('Misc', inputs.MISC_EVENTS),
    ('Switch', inputs.SWITCH_EVENTS),
    ('LED', inputs.LEDS),
    ('LED_type_codes', inputs.LED_TYPE_CODES),
    ('Sound', inputs.SOUNDS),
    ('Repeat', inputs.AUTOREPEAT_VALUES),
    ('ForceFeedback', inputs.FORCE_FEEDBACK),
    ('Power', inputs.POWER),
    ('ForceFeedbackStatus', inputs.FORCE_FEEDBACK_STATUS),
    ('Max', inputs.MAX),
    ('Current', inputs.CURRENT))

def rescan_devices():
    inputs.devices = inputs.DeviceManager()