Implement decided resolution of #304
- Remove self for normal callables - Retain self for methods (of course) - Add decorator to retrieve self for special callbacks that need it (Yes, the example is kinda stupid and would be unnecessary with #300)
This commit is contained in:
parent
3234897409
commit
aed169de4d
@ -1,3 +1,5 @@
|
||||
import inspect
|
||||
|
||||
from i3pystatus.core.settings import SettingsBase
|
||||
from i3pystatus.core.threading import Manager
|
||||
from i3pystatus.core.util import (convert_position,
|
||||
@ -6,6 +8,14 @@ from i3pystatus.core.command import execute
|
||||
from i3pystatus.core.command import run_through_shell
|
||||
|
||||
|
||||
def is_method_of(method, object):
|
||||
"""Decide whether ``method`` is contained within the MRO of ``object``."""
|
||||
for cls in inspect.getmro(object.__class__):
|
||||
if method in cls.__dict__.values():
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
class Module(SettingsBase):
|
||||
output = None
|
||||
position = 0
|
||||
@ -80,8 +90,11 @@ class Module(SettingsBase):
|
||||
else:
|
||||
args = []
|
||||
|
||||
if callable(cb):
|
||||
our_method = is_method_of(cb, self)
|
||||
if callable(cb) and not our_method:
|
||||
self.__log_button_event(button, cb, args, "Python callback")
|
||||
cb(*args)
|
||||
elif our_method:
|
||||
cb(self, *args)
|
||||
elif hasattr(self, cb):
|
||||
if cb is not "run":
|
||||
|
@ -3,7 +3,7 @@ import functools
|
||||
import re
|
||||
import socket
|
||||
import string
|
||||
|
||||
import inspect
|
||||
from threading import Timer, RLock
|
||||
|
||||
|
||||
@ -558,3 +558,32 @@ class MultiClickHandler(object):
|
||||
|
||||
self.clear_timer()
|
||||
return ret
|
||||
|
||||
|
||||
def get_module(function):
|
||||
"""Function decorator for retrieving the ``self`` argument from the stack.
|
||||
|
||||
Intended for use with callbacks that need access to a modules variables, for example:
|
||||
|
||||
.. code:: python
|
||||
|
||||
from i3pystatus import Status
|
||||
from i3pystatus.core.util import get_module
|
||||
from i3pystatus.core.command import execute
|
||||
status = Status(...)
|
||||
# other modules etc.
|
||||
@get_module
|
||||
def display_ip_verbose(module):
|
||||
execute('sh -c "ip addr show dev {dev} | xmessage -file -"'.format(dev=module.interface))
|
||||
status.register("network", interface="wlan1", on_leftclick=display_ip_verbose)
|
||||
"""
|
||||
@functools.wraps(function)
|
||||
def call_wrapper(*args, **kwargs):
|
||||
stack = inspect.stack()
|
||||
caller_frame_info = stack[1]
|
||||
self = caller_frame_info[0].f_locals["self"]
|
||||
# not completly sure whether this is necessary
|
||||
# see note in Python docs about stack frames
|
||||
del stack
|
||||
function(self, *args, **kwargs)
|
||||
return call_wrapper
|
||||
|
Loading…
Reference in New Issue
Block a user