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 __future__ import absolute_import
|
||||||
|
|
||||||
from powerline.lib.monotonic import monotonic
|
|
||||||
|
|
||||||
from threading import Thread, Lock, Event
|
from threading import Thread, Lock, Event
|
||||||
|
from types import MethodType
|
||||||
|
|
||||||
|
from powerline.lib.monotonic import monotonic
|
||||||
|
from powerline.segments import Segment
|
||||||
|
|
||||||
|
|
||||||
class MultiRunnedThread(object):
|
class MultiRunnedThread(object):
|
||||||
|
@ -28,12 +30,14 @@ class MultiRunnedThread(object):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
class ThreadedSegment(MultiRunnedThread):
|
class ThreadedSegment(Segment, MultiRunnedThread):
|
||||||
min_sleep_time = 0.1
|
min_sleep_time = 0.1
|
||||||
update_first = True
|
update_first = True
|
||||||
interval = 1
|
interval = 1
|
||||||
daemon = False
|
daemon = False
|
||||||
|
|
||||||
|
argmethods = ('render', 'set_state')
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(ThreadedSegment, self).__init__()
|
super(ThreadedSegment, self).__init__()
|
||||||
self.run_once = True
|
self.run_once = True
|
||||||
|
@ -145,10 +149,34 @@ class ThreadedSegment(MultiRunnedThread):
|
||||||
def debug(self, *args, **kwargs):
|
def debug(self, *args, **kwargs):
|
||||||
self.pl.debug(prefix=self.__class__.__name__, *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):
|
class KwThreadedSegment(ThreadedSegment):
|
||||||
update_first = True
|
update_first = True
|
||||||
|
|
||||||
|
argmethods = ('render', 'set_state', 'key', 'render_one')
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(KwThreadedSegment, self).__init__()
|
super(KwThreadedSegment, self).__init__()
|
||||||
self.updated = True
|
self.updated = True
|
||||||
|
|
|
@ -1,72 +1,63 @@
|
||||||
# vim:fileencoding=utf-8:noet
|
# vim:fileencoding=utf-8:noet
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
|
|
||||||
from inspect import ArgSpec, getargspec
|
from inspect import ArgSpec, getargspec
|
||||||
from powerline.lib.threaded import ThreadedSegment, KwThreadedSegment
|
|
||||||
from itertools import count
|
from itertools import count
|
||||||
|
|
||||||
|
from powerline.lib.threaded import ThreadedSegment, KwThreadedSegment
|
||||||
|
from powerline.segments import Segment
|
||||||
|
|
||||||
|
|
||||||
def getconfigargspec(obj):
|
def getconfigargspec(obj):
|
||||||
if isinstance(obj, ThreadedSegment):
|
if hasattr(obj, 'powerline_origin'):
|
||||||
args = ['interval']
|
obj = obj.powerline_origin
|
||||||
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))
|
|
||||||
else:
|
else:
|
||||||
if hasattr(obj, 'powerline_origin'):
|
obj = obj
|
||||||
obj = obj.powerline_origin
|
|
||||||
else:
|
|
||||||
obj = obj
|
|
||||||
|
|
||||||
remove_self = False
|
args = []
|
||||||
try:
|
defaults = []
|
||||||
argspec = getargspec(obj)
|
|
||||||
except TypeError: # Workaround for now_playing segment
|
if isinstance(obj, Segment):
|
||||||
# TODO For NowPlayingSegment for linter: merge in information about
|
additional_args = obj.additional_args()
|
||||||
# player-specific arguments
|
argspecobjs = obj.argspecobjs()
|
||||||
argspec = getargspec(obj.__call__)
|
get_omitted_args = obj.omitted_args
|
||||||
remove_self = True
|
else:
|
||||||
args = []
|
additional_args = ()
|
||||||
defaults = []
|
argspecobjs = ((None, obj),)
|
||||||
for i, arg in zip(count(1), reversed(argspec.args)):
|
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 (
|
if (
|
||||||
(arg == 'segment_info' and getattr(obj, 'powerline_requires_segment_info', None))
|
largs - (i + 1) in omitted_args
|
||||||
or arg == 'pl'
|
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
|
continue
|
||||||
if argspec.defaults and len(argspec.defaults) >= i:
|
if argspec.defaults and len(argspec.defaults) > i:
|
||||||
default = 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)
|
defaults.append(default)
|
||||||
args.append(arg)
|
args.append(arg)
|
||||||
else:
|
else:
|
||||||
args.insert(0, arg)
|
if arg not in args:
|
||||||
argspec = ArgSpec(args=args, varargs=argspec.varargs, keywords=argspec.keywords, defaults=tuple(defaults))
|
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
|
# vim:fileencoding=utf-8:noet
|
||||||
|
|
||||||
from __future__ import absolute_import, unicode_literals, division, print_function
|
from __future__ import absolute_import, unicode_literals, division, print_function
|
||||||
|
|
||||||
from powerline.lib.file_watcher import create_file_watcher
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
from powerline.lib.file_watcher import create_file_watcher
|
||||||
|
|
||||||
|
|
||||||
def list_segment_key_values(segment, theme_configs, key, module=None, default=None):
|
def list_segment_key_values(segment, theme_configs, key, module=None, default=None):
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -1,2 +1,51 @@
|
||||||
|
# vim:fileencoding=utf-8:noet
|
||||||
|
from __future__ import absolute_import
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
from pkgutil import extend_path
|
from pkgutil import extend_path
|
||||||
|
from types import MethodType
|
||||||
|
|
||||||
|
|
||||||
__path__ = extend_path(__path__, __name__)
|
__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.humanize_bytes import humanize_bytes
|
||||||
from powerline.lib.unicode import u
|
from powerline.lib.unicode import u
|
||||||
from powerline.theme import requires_segment_info, requires_filesystem_watcher
|
from powerline.theme import requires_segment_info, requires_filesystem_watcher
|
||||||
|
from powerline.segments import Segment
|
||||||
from collections import namedtuple
|
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):
|
def __call__(self, player='mpd', format='{state_symbol} {artist} - {title} ({total})', state_symbols=STATE_SYMBOLS, **kwargs):
|
||||||
player_func = getattr(self, 'player_{0}'.format(player))
|
player_func = getattr(self, 'player_{0}'.format(player))
|
||||||
stats = {
|
stats = {
|
||||||
|
|
Loading…
Reference in New Issue