Refactor powerline.lint.inspect: do not special-case *ThreadedSegment
Fixes now_playing segment handling in python-3.4
This commit is contained in:
parent
d4735c87df
commit
1a87006310
|
@ -2,9 +2,11 @@
|
|||
|
||||
from __future__ import absolute_import
|
||||
|
||||
from powerline.lib.monotonic import monotonic
|
||||
|
||||
from threading import Thread, Lock, Event
|
||||
from types import MethodType
|
||||
|
||||
from powerline.lib.monotonic import monotonic
|
||||
from powerline.segments import Segment
|
||||
|
||||
|
||||
class MultiRunnedThread(object):
|
||||
|
@ -28,12 +30,14 @@ class MultiRunnedThread(object):
|
|||
return None
|
||||
|
||||
|
||||
class ThreadedSegment(MultiRunnedThread):
|
||||
class ThreadedSegment(Segment, MultiRunnedThread):
|
||||
min_sleep_time = 0.1
|
||||
update_first = True
|
||||
interval = 1
|
||||
daemon = False
|
||||
|
||||
argmethods = ('render', 'set_state')
|
||||
|
||||
def __init__(self):
|
||||
super(ThreadedSegment, self).__init__()
|
||||
self.run_once = True
|
||||
|
@ -145,10 +149,34 @@ class ThreadedSegment(MultiRunnedThread):
|
|||
def debug(self, *args, **kwargs):
|
||||
self.pl.debug(prefix=self.__class__.__name__, *args, **kwargs)
|
||||
|
||||
def argspecobjs(self):
|
||||
for name in self.argmethods:
|
||||
try:
|
||||
yield name, getattr(self, name)
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
def additional_args(self):
|
||||
return (('interval', self.interval),)
|
||||
|
||||
def omitted_args(self, name, method):
|
||||
if isinstance(getattr(self, name, None), MethodType):
|
||||
omitted_indexes = (0,)
|
||||
else:
|
||||
omitted_indexes = ()
|
||||
if name.startswith('render'):
|
||||
if omitted_indexes:
|
||||
omitted_indexes += (1,)
|
||||
else:
|
||||
omitted_indexes = (0,)
|
||||
return omitted_indexes
|
||||
|
||||
|
||||
class KwThreadedSegment(ThreadedSegment):
|
||||
update_first = True
|
||||
|
||||
argmethods = ('render', 'set_state', 'key', 'render_one')
|
||||
|
||||
def __init__(self):
|
||||
super(KwThreadedSegment, self).__init__()
|
||||
self.updated = True
|
||||
|
|
|
@ -1,72 +1,63 @@
|
|||
# vim:fileencoding=utf-8:noet
|
||||
from __future__ import absolute_import
|
||||
|
||||
from inspect import ArgSpec, getargspec
|
||||
from powerline.lib.threaded import ThreadedSegment, KwThreadedSegment
|
||||
from itertools import count
|
||||
|
||||
from powerline.lib.threaded import ThreadedSegment, KwThreadedSegment
|
||||
from powerline.segments import Segment
|
||||
|
||||
|
||||
def getconfigargspec(obj):
|
||||
if isinstance(obj, ThreadedSegment):
|
||||
args = ['interval']
|
||||
defaults = [getattr(obj, 'interval', 1)]
|
||||
if obj.update_first:
|
||||
args.append('update_first')
|
||||
defaults.append(True)
|
||||
methods = ['render', 'set_state']
|
||||
if isinstance(obj, KwThreadedSegment):
|
||||
methods += ['key', 'render_one']
|
||||
|
||||
for method in methods:
|
||||
if hasattr(obj, method):
|
||||
# Note: on <python-2.6 it may return simple tuple, not
|
||||
# ArgSpec instance.
|
||||
argspec = getargspec(getattr(obj, method))
|
||||
for i, arg in zip(count(1), reversed(argspec.args)):
|
||||
if (arg == 'self' or
|
||||
(arg == 'segment_info' and
|
||||
getattr(obj, 'powerline_requires_segment_info', None)) or
|
||||
(arg == 'create_watcher' and
|
||||
getattr(obj, 'powerline_requires_filesystem_watcher', None)) or
|
||||
(arg == 'pl') or
|
||||
(method.startswith('render') and (1 if argspec.args[0] == 'self' else 0) + i == len(argspec.args)) or
|
||||
arg in args):
|
||||
continue
|
||||
if argspec.defaults and len(argspec.defaults) >= i:
|
||||
default = argspec.defaults[-i]
|
||||
defaults.append(default)
|
||||
args.append(arg)
|
||||
else:
|
||||
args.insert(0, arg)
|
||||
argspec = ArgSpec(args=args, varargs=None, keywords=None, defaults=tuple(defaults))
|
||||
if hasattr(obj, 'powerline_origin'):
|
||||
obj = obj.powerline_origin
|
||||
else:
|
||||
if hasattr(obj, 'powerline_origin'):
|
||||
obj = obj.powerline_origin
|
||||
else:
|
||||
obj = obj
|
||||
obj = obj
|
||||
|
||||
remove_self = False
|
||||
try:
|
||||
argspec = getargspec(obj)
|
||||
except TypeError: # Workaround for now_playing segment
|
||||
# TODO For NowPlayingSegment for linter: merge in information about
|
||||
# player-specific arguments
|
||||
argspec = getargspec(obj.__call__)
|
||||
remove_self = True
|
||||
args = []
|
||||
defaults = []
|
||||
for i, arg in zip(count(1), reversed(argspec.args)):
|
||||
args = []
|
||||
defaults = []
|
||||
|
||||
if isinstance(obj, Segment):
|
||||
additional_args = obj.additional_args()
|
||||
argspecobjs = obj.argspecobjs()
|
||||
get_omitted_args = obj.omitted_args
|
||||
else:
|
||||
additional_args = ()
|
||||
argspecobjs = ((None, obj),)
|
||||
get_omitted_args = lambda *args: ()
|
||||
|
||||
for arg in additional_args:
|
||||
args.append(arg[0])
|
||||
if len(arg) > 1:
|
||||
defaults.append(arg[1])
|
||||
|
||||
requires_segment_info = getattr(obj, 'powerline_requires_segment_info', False)
|
||||
requires_filesystem_watcher = getattr(obj, 'powerline_requires_filesystem_watcher', False)
|
||||
|
||||
for name, method in argspecobjs:
|
||||
argspec = getargspec(method)
|
||||
omitted_args = get_omitted_args(name, method)
|
||||
largs = len(argspec.args)
|
||||
for i, arg in enumerate(reversed(argspec.args)):
|
||||
if (
|
||||
(arg == 'segment_info' and getattr(obj, 'powerline_requires_segment_info', None))
|
||||
largs - (i + 1) in omitted_args
|
||||
or arg == 'pl'
|
||||
or (arg == 'self' and remove_self)
|
||||
or (arg == 'create_watcher' and requires_filesystem_watcher)
|
||||
or (arg == 'segment_info' and requires_segment_info)
|
||||
):
|
||||
continue
|
||||
if argspec.defaults and len(argspec.defaults) >= i:
|
||||
default = argspec.defaults[-i]
|
||||
if argspec.defaults and len(argspec.defaults) > i:
|
||||
if arg in args:
|
||||
idx = args.index(arg)
|
||||
if len(args) - idx > len(defaults):
|
||||
args.pop(idx)
|
||||
else:
|
||||
continue
|
||||
default = argspec.defaults[-(i + 1)]
|
||||
defaults.append(default)
|
||||
args.append(arg)
|
||||
else:
|
||||
args.insert(0, arg)
|
||||
argspec = ArgSpec(args=args, varargs=argspec.varargs, keywords=argspec.keywords, defaults=tuple(defaults))
|
||||
if arg not in args:
|
||||
args.insert(0, arg)
|
||||
|
||||
return argspec
|
||||
return ArgSpec(args=args, varargs=None, keywords=None, defaults=tuple(defaults))
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
# vim:fileencoding=utf-8:noet
|
||||
|
||||
from __future__ import absolute_import, unicode_literals, division, print_function
|
||||
|
||||
from powerline.lib.file_watcher import create_file_watcher
|
||||
import sys
|
||||
|
||||
from powerline.lib.file_watcher import create_file_watcher
|
||||
|
||||
|
||||
def list_segment_key_values(segment, theme_configs, key, module=None, default=None):
|
||||
try:
|
||||
|
|
|
@ -1,2 +1,51 @@
|
|||
# vim:fileencoding=utf-8:noet
|
||||
from __future__ import absolute_import
|
||||
|
||||
import sys
|
||||
|
||||
from pkgutil import extend_path
|
||||
from types import MethodType
|
||||
|
||||
|
||||
__path__ = extend_path(__path__, __name__)
|
||||
|
||||
|
||||
class Segment(object):
|
||||
'''Base class for any segment that is not a function
|
||||
|
||||
Required for powerline.lint.inspect to work properly.
|
||||
'''
|
||||
if sys.version_info < (3, 4):
|
||||
def argspecobjs(self):
|
||||
yield '__call__', self.__call__
|
||||
else:
|
||||
def argspecobjs(self): # NOQA
|
||||
yield '__call__', self
|
||||
|
||||
argspecobjs.__doc__ = (
|
||||
'''Return a list of valid arguments for inspect.getargspec
|
||||
|
||||
Used to determine function arguments.
|
||||
'''
|
||||
)
|
||||
|
||||
def omitted_args(self, name, method):
|
||||
'''List arguments which should be omitted
|
||||
|
||||
Returns a tuple with indexes of omitted arguments.
|
||||
|
||||
.. note::``segment_info``, ``create_watcher`` and ``pl`` will be omitted
|
||||
regardless of the below return (for ``segment_info`` and
|
||||
``create_watcher``: only if object was marked to require segment
|
||||
info or filesystem watcher).
|
||||
'''
|
||||
if isinstance(self.__call__, MethodType):
|
||||
return (0,)
|
||||
else:
|
||||
return ()
|
||||
|
||||
@staticmethod
|
||||
def additional_args():
|
||||
'''Returns a list of (additional argument name[, default value]) tuples.
|
||||
'''
|
||||
return ()
|
||||
|
|
|
@ -19,6 +19,7 @@ from powerline.lib.monotonic import monotonic
|
|||
from powerline.lib.humanize_bytes import humanize_bytes
|
||||
from powerline.lib.unicode import u
|
||||
from powerline.theme import requires_segment_info, requires_filesystem_watcher
|
||||
from powerline.segments import Segment
|
||||
from collections import namedtuple
|
||||
|
||||
|
||||
|
@ -904,7 +905,7 @@ STATE_SYMBOLS = {
|
|||
}
|
||||
|
||||
|
||||
class NowPlayingSegment(object):
|
||||
class NowPlayingSegment(Segment):
|
||||
def __call__(self, player='mpd', format='{state_symbol} {artist} - {title} ({total})', state_symbols=STATE_SYMBOLS, **kwargs):
|
||||
player_func = getattr(self, 'player_{0}'.format(player))
|
||||
stats = {
|
||||
|
|
Loading…
Reference in New Issue