tryexceptpass / sofi

an OS agnostic UI module for Python
MIT License
387 stars 49 forks source link

app.unregister() fails for instance method callbacks #83

Closed nocarryr closed 7 years ago

nocarryr commented 7 years ago

In app.py, the key used for callbacks relies on the id() function of the callback. The internal id for instance methods defined with async def apparently does not seem to be persistent.

import asyncio

class A(object):
    async def foo(self):
        print(id(self.bar))
    async def bar(self):
        pass    

loop = asyncio.get_event_loop()

async def test():
    a = A()
    await a.foo()
    await a.foo()

loop.run_until_complete(test())

# 140002553590152
# 140002529194440

Would it be a reasonable solution to check callbacks during register() for isinstance(callback, types.MethodType) and use a combination of id(callback.__func__) and id(callback.__self__) as a key?

nocarryr commented 7 years ago

Update... So for some reason now I cannot seem to duplicate the results from the snippet above. The issue is still present in my application though (the first line is the output from print(id(self.on_click)):

140280319751880
2017-01-06 16:29:39,069 [ERROR] - default_exception_handler: Task exception was never retrieved
future: <Task finished coro=<SofiEventProtocol.onMessage() done, defined at /home/nocarrier/programs/vidhub-control/venv3/lib/python3.5/site-packages/sofi/app/app.py:162> exception=KeyError('140280319750728',)>
Traceback (most recent call last):
  File "/usr/lib/python3.5/asyncio/tasks.py", line 239, in _step
    result = coro.send(None)
  File "/home/nocarrier/programs/vidhub-control/venv3/lib/python3.5/site-packages/sofi/app/app.py", line 170, in onMessage
    await self.processor.process(self, body)
  File "/home/nocarrier/programs/vidhub-control/venv3/lib/python3.5/site-packages/sofi/app/app.py", line 145, in process
    await handler(event)
  File "vidhubcontrol/sofi_ui/main.py", line 335, in on_device_select_click
    self.app.unregister('click', self.on_click, selector='button')
  File "/home/nocarrier/programs/vidhub-control/venv3/lib/python3.5/site-packages/sofi/app/app.py", line 29, in unregister
    self.interface.unregister(event, callback, selector)
  File "/home/nocarrier/programs/vidhub-control/venv3/lib/python3.5/site-packages/sofi/app/app.py", line 125, in unregister
    self.handlers[event].pop(str(id(callback)))
KeyError: '140280319750728'

Also, directly before the call to register(), the id of the callback was 140280320379592

tryexceptpass commented 7 years ago

I'm ok with using some other mechanism as the key, just need something unique that's easy to access.