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.settings import SettingsBase
|
||||||
from i3pystatus.core.threading import Manager
|
from i3pystatus.core.threading import Manager
|
||||||
from i3pystatus.core.util import (convert_position,
|
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
|
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):
|
class Module(SettingsBase):
|
||||||
output = None
|
output = None
|
||||||
position = 0
|
position = 0
|
||||||
@ -80,8 +90,11 @@ class Module(SettingsBase):
|
|||||||
else:
|
else:
|
||||||
args = []
|
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")
|
self.__log_button_event(button, cb, args, "Python callback")
|
||||||
|
cb(*args)
|
||||||
|
elif our_method:
|
||||||
cb(self, *args)
|
cb(self, *args)
|
||||||
elif hasattr(self, cb):
|
elif hasattr(self, cb):
|
||||||
if cb is not "run":
|
if cb is not "run":
|
||||||
|
@ -3,7 +3,7 @@ import functools
|
|||||||
import re
|
import re
|
||||||
import socket
|
import socket
|
||||||
import string
|
import string
|
||||||
|
import inspect
|
||||||
from threading import Timer, RLock
|
from threading import Timer, RLock
|
||||||
|
|
||||||
|
|
||||||
@ -558,3 +558,32 @@ class MultiClickHandler(object):
|
|||||||
|
|
||||||
self.clear_timer()
|
self.clear_timer()
|
||||||
return ret
|
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