Release 2.6

- Added support for new Vim modes.
- Added ability to control output padding.
- Added iTunes player segment.
- Added support for tmux development builds.
- Added a workaround for a fish bug sometimes occurring when using eval from
  config.fish (upstream status unknown).
- Added a workaround for tmux 2.4 bug: excessive CPU usage when having multiple
  panes (also fixed upstream).
- Fixed clean file status support in mercurial.
- Fixed error when battery capacity is zero and using DBus.
- Fixed mercurial command servers leakage.
- Refactored awesome bindings to use powerline daemon.
This commit is contained in:
Foo 2017-05-08 19:47:40 +03:00
commit c3261d4e57
136 changed files with 2159 additions and 1215 deletions

View File

@ -215,6 +215,13 @@ Common configuration is a subdictionary that is a value of ``ext`` key in
All components are enabled by default.
.. _config-ext-update_interval:
``update_interval``
Determines how often WM status bars need to be updated, in seconds. Only
valid for WM extensions which use ``powerline-daemon``. Defaults to
2 seconds.
.. _config-colors:
Color definitions
@ -361,6 +368,10 @@ ascii Theme without any unicode characters at all
is set in the local themes it will be ignored. This option may also be
ignored in some bindings.
``outer_padding``
Defines number of spaces at the end of output (on the right side) or at
the start of output (on the left side). Defaults to ``1``.
``dividers``
Defines the dividers used in all Powerline extensions.
@ -391,7 +402,7 @@ ascii Theme without any unicode characters at all
:ref:`display <config-themes-seg-display>`.
Key :ref:`args <config-themes-seg-args>` (only for function and
segments_list segments) is handled specially: unlike other values it is
segment_list segments) is handled specially: unlike other values it is
merged with all other values, except that a single ``{module}.{function}``
key if found prevents merging all ``{function}`` values.
@ -428,7 +439,7 @@ ascii Theme without any unicode characters at all
``type``
The segment type. Can be one of ``function`` (default), ``string`` or
``segments_list``:
``segment_list``:
``function``
The segment contents is the return value of the function defined in
@ -443,7 +454,7 @@ ascii Theme without any unicode characters at all
highlighting group is defined in the :ref:`highlight_groups option
<config-themes-seg-highlight_groups>`.
``segments_list``
``segment_list``
Sub-list of segments. This list only allows :ref:`function
<config-themes-seg-function>`, :ref:`segments
<config-themes-seg-segments>` and :ref:`args
@ -458,7 +469,7 @@ ascii Theme without any unicode characters at all
Segment name. If present allows referring to this segment in
:ref:`segment_data <config-themes-segment_data>` dictionary by this
name. If not ``string`` segments may not be referred there at all and
``function`` and ``segments_list`` segments may be referred there using
``function`` and ``segment_list`` segments may be referred there using
either ``{module}.{function_name}`` or ``{function_name}``, whichever
will be found first. Function name is taken from :ref:`function key
<config-themes-seg-function>`.

View File

@ -30,7 +30,7 @@ Generic requirements
with bazaar repositories.
* ``pyuv`` python package. Required for :ref:`libuv-based watcher
<config-common-watcher>` to work.
* ``i3-ipc`` python package. Required for i3wm bindings and segments.
* ``i3ipc`` python package. Required for i3wm bindings and segments.
* ``xrandr`` program. Required for the multi-monitor lemonbar binding and the
:py:func:`powerline.listers.i3wm.output_lister`.

View File

@ -111,7 +111,7 @@ following in ``~/.profile``:
.. code-block:: bash
if test "x$0" != "x${0#dash}" ; then
if test "$0" != "${0#dash}" ; then
export ENV={repository_root}/powerline/bindings/shell/powerline.sh
fi

View File

@ -419,6 +419,11 @@ def _get_log_keys(common_config):
))
DEFAULT_UPDATE_INTERVAL = 2
'''Default value for :ref:`update_interval <config-ext-update_interval>`
'''
class Powerline(object):
'''Main powerline class, entrance point for all powerline uses. Sets
powerline up and loads the configuration.
@ -514,6 +519,7 @@ class Powerline(object):
self.setup_args = ()
self.setup_kwargs = {}
self.imported_modules = set()
self.update_interval = DEFAULT_UPDATE_INTERVAL
get_encoding = staticmethod(get_preferred_output_encoding)
'''Get encoding used by the current application
@ -638,6 +644,7 @@ class Powerline(object):
or self.ext_config.get('local_themes') != self.prev_ext_config.get('local_themes')
):
self.renderer_options['local_themes'] = self.get_local_themes(self.ext_config.get('local_themes'))
self.update_interval = self.ext_config.get('update_interval', 2)
load_colorscheme = (
load_colorscheme
or not self.prev_ext_config

View File

@ -4,38 +4,17 @@ from __future__ import (unicode_literals, division, absolute_import, print_funct
import sys
from time import sleep
from subprocess import Popen, PIPE
from powerline.bindings.wm import DEFAULT_UPDATE_INTERVAL
from powerline.bindings.wm.awesome import run
from powerline import Powerline
from powerline.lib.monotonic import monotonic
powerline = Powerline('wm', renderer_module='pango_markup')
powerline.update_renderer()
try:
def main():
try:
interval = float(sys.argv[1])
except IndexError:
interval = 2
except IndexError:
interval = DEFAULT_UPDATE_INTERVAL
run(interval=interval)
def read_to_log(pl, client):
for line in client.stdout:
if line:
pl.info(line, prefix='awesome-client')
for line in client.stderr:
if line:
pl.error(line, prefix='awesome-client')
if client.wait():
pl.error('Client exited with {0}', client.returncode, prefix='awesome')
while True:
start_time = monotonic()
s = powerline.render(side='right')
request = 'powerline_widget:set_markup(\'' + s.replace('\\', '\\\\').replace('\'', '\\\'') + '\')\n'
client = Popen(['awesome-client'], shell=False, stdout=PIPE, stderr=PIPE, stdin=PIPE)
client.stdin.write(request.encode('utf-8'))
client.stdin.close()
read_to_log(powerline.pl, client)
sleep(max(interval - (monotonic() - start_time), 0.1))
if __name__ == '__main__':
main()

View File

@ -6,6 +6,5 @@ powerline_widget:set_align('right')
function powerline(mode, widget) end
bindings_path = string.gsub(debug.getinfo(1).source:match('@(.*)$'), '/[^/]+$', '')
powerline_cmd = bindings_path .. '/powerline-awesome.py'
awful.util.spawn_with_shell('ps -C powerline-awesome.py || ' .. powerline_cmd)
awful.util.spawn_with_shell('powerline-daemon -q')
awful.util.spawn_with_shell('powerline wm.awesome')

View File

@ -11,6 +11,7 @@ from argparse import ArgumentParser
from powerline.lemonbar import LemonbarPowerline
from powerline.lib.encoding import get_unicode_writer
from powerline.bindings.wm import DEFAULT_UPDATE_INTERVAL
if __name__ == '__main__':
@ -29,7 +30,7 @@ if __name__ == '__main__':
def render(reschedule=False):
if reschedule:
Timer(0.5, render, kwargs={'reschedule': True}).start()
Timer(DEFAULT_UPDATE_INTERVAL, render, kwargs={'reschedule': True}).start()
global lock
with lock:

View File

@ -21,7 +21,7 @@ _powerline_tmux_setenv() {
}
_powerline_tmux_set_pwd() {
if test "x$_POWERLINE_SAVED_PWD" != "x$PWD" ; then
if test "$_POWERLINE_SAVED_PWD" != "$PWD" ; then
_POWERLINE_SAVED_PWD="$PWD"
_powerline_tmux_setenv PWD "$PWD"
fi
@ -39,8 +39,8 @@ _powerline_init_tmux_support() {
trap '_powerline_tmux_set_columns' WINCH
_powerline_tmux_set_columns
test "x$PROMPT_COMMAND" != "x${PROMPT_COMMAND/_powerline_tmux_set_pwd}" ||
PROMPT_COMMAND="${PROMPT_COMMAND}"$'\n_powerline_tmux_set_pwd'
test "$PROMPT_COMMAND" != "${PROMPT_COMMAND/_powerline_tmux_set_pwd}" \
|| PROMPT_COMMAND="${PROMPT_COMMAND}"$'\n_powerline_tmux_set_pwd'
fi
}
@ -82,8 +82,8 @@ _powerline_setup_prompt() {
if test -z "${POWERLINE_COMMAND}" ; then
POWERLINE_COMMAND="$("$POWERLINE_CONFIG_COMMAND" shell command)"
fi
test "x$PROMPT_COMMAND" != "x${PROMPT_COMMAND%_powerline_set_prompt*}" ||
PROMPT_COMMAND=$'_powerline_set_prompt\n'"${PROMPT_COMMAND}"
test "$PROMPT_COMMAND" != "${PROMPT_COMMAND%_powerline_set_prompt*}" \
|| PROMPT_COMMAND=$'_powerline_set_prompt\n'"${PROMPT_COMMAND}"
PS2="$(_powerline_local_prompt left -r.bash 0 0 continuation)"
PS3="$(_powerline_local_prompt left '' 0 0 select)"
}

View File

@ -99,7 +99,7 @@ class EmptyArgs(object):
def init_tmux_environment(pl, args, set_tmux_environment=set_tmux_environment):
'''Initialize tmux environment from tmux configuration
'''
powerline = ShellPowerline(finish_args(os.environ, EmptyArgs('tmux', args.config_path)))
powerline = ShellPowerline(finish_args(None, os.environ, EmptyArgs('tmux', args.config_path)))
# TODO Move configuration files loading out of Powerline object and use it
# directly
powerline.update_renderer()

View File

@ -34,7 +34,7 @@ function powerline-setup
set -g POWERLINE_COMMAND (env $POWERLINE_CONFIG_COMMAND shell command)
end
function _powerline_set_default_mode --on-variable fish_key_bindings
if test x$fish_key_bindings != xfish_vi_key_bindings
if test $fish_key_bindings != fish_vi_key_bindings
set -g _POWERLINE_DEFAULT_MODE default
else
set -g -e _POWERLINE_DEFAULT_MODE
@ -62,7 +62,7 @@ function powerline-setup
set rpromptpast
set columnsexpr '(_powerline_columns)'
end
eval "
echo "
function fish_prompt
env \$POWERLINE_COMMAND $POWERLINE_COMMAND_ARGS shell $promptside $addargs
end
@ -73,7 +73,7 @@ function powerline-setup
function _powerline_set_columns --on-signal WINCH
set -g _POWERLINE_COLUMNS $columnsexpr
end
"
" | source
_powerline_set_columns
end
_powerline_set_default_mode

View File

@ -37,7 +37,7 @@ fn _powerline_common_setup {
}
fn _powerline_tmux_pane {
if (test x$TMUX_PANE '!=' x) {
if (test -n $TMUX_PANE) {
echo $TMUX_PANE | tr -d ' %'
} else {
TMUX=$_POWERLINE_TMUX tmux display -p '#D' | tr -d ' %'
@ -54,9 +54,9 @@ if (test -z $POWERLINE_CONFIG_COMMAND) {
echo powerline-config executable not found, unable to proceed >[2=1]
}
}
if (test x$POWERLINE_CONFIG_COMMAND '!=' x) {
if (test -n $POWERLINE_CONFIG_COMMAND) {
if ($POWERLINE_CONFIG_COMMAND shell --shell rcsh uses prompt) {
if (test x$POWERLINE_COMMAND_ARGS '!=' x) {
if (test -n $POWERLINE_COMMAND_ARGS) {
# Perform splitting
POWERLINE_COMMAND_ARGS=( `{echo $POWERLINE_COMMAND_ARGS} )
}
@ -75,11 +75,11 @@ if (test x$POWERLINE_CONFIG_COMMAND '!=' x) {
}
_powerline_common_setup
}
if (test x$TMUX '!=' x) {
if (test -n $TMUX) {
if ($POWERLINE_CONFIG_COMMAND shell --shell rcsh uses tmux) {
_POWERLINE_TMUX=$TMUX
fn _powerline_tmux_setenv {
if (test x$2 '!=' x) {
if (test -n $2) {
TMUX=$_POWERLINE_TMUX tmux setenv -g TMUX_$1^_`{
_powerline_tmux_pane
} $2

View File

@ -115,7 +115,7 @@ _powerline_tmux_setenv() {
}
_powerline_tmux_set_pwd() {
if test "x$_POWERLINE_SAVED_PWD" != "x$PWD" ; then
if test "$_POWERLINE_SAVED_PWD" != "$PWD" ; then
_POWERLINE_SAVED_PWD="$PWD"
_powerline_tmux_setenv PWD "$PWD"
fi

View File

@ -76,6 +76,8 @@ def get_tmux_version(pl):
version_string = get_tmux_output(pl, '-V')
_, version_string = version_string.split(' ')
version_string = version_string.strip()
if version_string == 'master':
return TmuxVersionInfo(float('inf'), 0, version_string)
major, minor = version_string.split('.')
suffix = DIGITS.subn('', minor)[0] or None
minor = NON_DIGITS.subn('', minor)[0]

View File

@ -1,11 +1,11 @@
set -g status on
set -g status-interval 2
set -g status-left-length 20
set -g status-right '#(env "$POWERLINE_COMMAND" $POWERLINE_COMMAND_ARGS tmux right -R pane_id=\"`tmux display -p "#D"`\")'
set -g status-right '#(env "$POWERLINE_COMMAND" $POWERLINE_COMMAND_ARGS tmux right -R pane_id=\"`tmux display -p "#""D"`\")'
set -g status-right-length 150
set -g window-status-format "#[$_POWERLINE_WINDOW_COLOR]$_POWERLINE_LEFT_HARD_DIVIDER_SPACES#I#F #[$_POWERLINE_WINDOW_DIVIDER_COLOR]$_POWERLINE_LEFT_SOFT_DIVIDER#[default]#W $_POWERLINE_LEFT_HARD_DIVIDER_SPACES"
set -g window-status-current-format "#[$_POWERLINE_WINDOW_CURRENT_HARD_DIVIDER_COLOR]$_POWERLINE_LEFT_HARD_DIVIDER#[$_POWERLINE_WINDOW_CURRENT_COLOR]#I#F $_POWERLINE_LEFT_SOFT_DIVIDER#[$_POWERLINE_WINDOW_NAME_COLOR]#W #[$_POWERLINE_WINDOW_CURRENT_HARD_DIVIDER_NEXT_COLOR]$_POWERLINE_LEFT_HARD_DIVIDER"
# Legacy status-left definition to be overwritten for tmux Versions 1.8+
set -g status-left "#[$_POWERLINE_SESSION_COLOR] #S #[$_POWERLINE_SESSION_HARD_DIVIDER_NEXT_COLOR]$_POWERLINE_LEFT_HARD_DIVIDER#(env \"\$POWERLINE_COMMAND\" tmux left -R pane_id=\"`tmux display -p '#D'`\")"
set -g status-left "#[$_POWERLINE_SESSION_COLOR] #S #[$_POWERLINE_SESSION_HARD_DIVIDER_NEXT_COLOR]$_POWERLINE_LEFT_HARD_DIVIDER#(env \"\$POWERLINE_COMMAND\" tmux left -R pane_id=\"`tmux display -p '#''D'`\")"
# vim: ft=tmux

View File

@ -1,3 +1,3 @@
set -g status-right '#(env "$POWERLINE_COMMAND" $POWERLINE_COMMAND_ARGS tmux right -R pane_id="`tmux display -p "#D"`" --width=`tmux display -p "#{client_width}"` -R width_adjust=`tmux show-options -g status-left-length | cut -d" " -f 2`)'
set -g status-left "#[$_POWERLINE_SESSION_COLOR] #S #[$_POWERLINE_SESSION_HARD_DIVIDER_NEXT_COLOR]$_POWERLINE_LEFT_HARD_DIVIDER#(env \"\$POWERLINE_COMMAND\" tmux left --width=`tmux display -p '#{client_width}'` -R width_adjust=`tmux show-options -g status-right-length | cut -d' ' -f2` -R pane_id=\"`tmux display -p '#D'`\")"
set -g status-right '#(env "$POWERLINE_COMMAND" $POWERLINE_COMMAND_ARGS tmux right -R pane_id="`tmux display -p "#""D"`" --width=`tmux display -p "#""{client_width}"` -R width_adjust=`tmux show-options -g status-left-length | cut -d" " -f 2`)'
set -g status-left "#[$_POWERLINE_SESSION_COLOR] #S #[$_POWERLINE_SESSION_HARD_DIVIDER_NEXT_COLOR]$_POWERLINE_LEFT_HARD_DIVIDER#(env \"\$POWERLINE_COMMAND\" tmux left --width=`tmux display -p '#''{client_width}'` -R width_adjust=`tmux show-options -g status-right-length | cut -d' ' -f2` -R pane_id=\"`tmux display -p '#''D'`\")"
# vim: ft=tmux

View File

@ -1,5 +1,5 @@
# powerline_tmux_1.8_plus.conf
# tmux Version 1.8 introduces the 'client_prefix' format variable, applicable
# for versions 1.8+
set -qg status-left "#{?client_prefix,#[fg=$_POWERLINE_SESSION_PREFIX_FG]#[bg=$_POWERLINE_SESSION_PREFIX_BG]#[$_POWERLINE_SESSION_PREFIX_ATTR],#[fg=$_POWERLINE_SESSION_FG]#[bg=$_POWERLINE_SESSION_BG]#[$_POWERLINE_SESSION_ATTR]} #S #{?client_prefix,#[fg=$_POWERLINE_SESSION_PREFIX_BG],#[fg=$_POWERLINE_SESSION_BG]}#[bg=$_POWERLINE_BACKGROUND_BG]#[nobold]$_POWERLINE_LEFT_HARD_DIVIDER#(env \$POWERLINE_COMMAND \$POWERLINE_COMMAND_ARGS tmux left --width=`tmux display -p '#{client_width}'` -R width_adjust=`tmux show-options -g status-right-length | cut -d' ' -f2` -R pane_id=\"`tmux display -p '#D'`\")"
set -qg status-left "#{?client_prefix,#[fg=$_POWERLINE_SESSION_PREFIX_FG]#[bg=$_POWERLINE_SESSION_PREFIX_BG]#[$_POWERLINE_SESSION_PREFIX_ATTR],#[fg=$_POWERLINE_SESSION_FG]#[bg=$_POWERLINE_SESSION_BG]#[$_POWERLINE_SESSION_ATTR]} #S #{?client_prefix,#[fg=$_POWERLINE_SESSION_PREFIX_BG],#[fg=$_POWERLINE_SESSION_BG]}#[bg=$_POWERLINE_BACKGROUND_BG]#[nobold]$_POWERLINE_LEFT_HARD_DIVIDER#(env \$POWERLINE_COMMAND \$POWERLINE_COMMAND_ARGS tmux left --width=`tmux display -p '#''{client_width}'` -R width_adjust=`tmux show-options -g status-right-length | cut -d' ' -f2` -R pane_id=\"`tmux display -p '#''D'`\")"
# vim: ft=tmux

View File

@ -1,2 +1,3 @@
# Starting from tmux-2.1 escaping of dollar signs inside #() is harmful
set -qg status-left "#{?client_prefix,#[fg=$_POWERLINE_SESSION_PREFIX_FG]#[bg=$_POWERLINE_SESSION_PREFIX_BG]#[$_POWERLINE_SESSION_PREFIX_ATTR],#[fg=$_POWERLINE_SESSION_FG]#[bg=$_POWERLINE_SESSION_BG]#[$_POWERLINE_SESSION_ATTR]} #S #{?client_prefix,#[fg=$_POWERLINE_SESSION_PREFIX_BG],#[fg=$_POWERLINE_SESSION_BG]}#[bg=$_POWERLINE_BACKGROUND_BG]#[nobold]$_POWERLINE_LEFT_HARD_DIVIDER#(env $POWERLINE_COMMAND $POWERLINE_COMMAND_ARGS tmux left --width=`tmux display -p '#{client_width}'` -R width_adjust=`tmux show-options -g status-right-length | cut -d' ' -f2` -R pane_id=\"`tmux display -p '#D'`\")"
set -qg status-left "#{?client_prefix,#[fg=$_POWERLINE_SESSION_PREFIX_FG]#[bg=$_POWERLINE_SESSION_PREFIX_BG]#[$_POWERLINE_SESSION_PREFIX_ATTR],#[fg=$_POWERLINE_SESSION_FG]#[bg=$_POWERLINE_SESSION_BG]#[$_POWERLINE_SESSION_ATTR]} #S #{?client_prefix,#[fg=$_POWERLINE_SESSION_PREFIX_BG],#[fg=$_POWERLINE_SESSION_BG]}#[bg=$_POWERLINE_BACKGROUND_BG]#[nobold]$_POWERLINE_LEFT_HARD_DIVIDER#(env $POWERLINE_COMMAND $POWERLINE_COMMAND_ARGS tmux left --width=`tmux display -p '#''{client_width}'` -R width_adjust=`tmux show-options -g status-right-length | cut -d' ' -f2` -R pane_id=\"`tmux display -p '#''D'`\")"
set -g window-status-format "#[$_POWERLINE_WINDOW_COLOR]$_POWERLINE_LEFT_HARD_DIVIDER_SPACES#I#{?window_flags,#F, } #[$_POWERLINE_WINDOW_DIVIDER_COLOR]$_POWERLINE_LEFT_SOFT_DIVIDER#[default]#W $_POWERLINE_LEFT_HARD_DIVIDER_SPACES"

View File

@ -5,6 +5,10 @@ import re
from powerline.theme import requires_segment_info
from powerline.lib.shell import run_cmd
from powerline.bindings.wm.awesome import AwesomeThread
DEFAULT_UPDATE_INTERVAL = 0.5
conn = None
@ -36,3 +40,8 @@ def get_connected_xrandr_outputs(pl):
return (match.groupdict() for match in XRANDR_OUTPUT_RE.finditer(
run_cmd(pl, ['xrandr', '-q'])
))
wm_threads = {
'awesome': AwesomeThread,
}

View File

@ -0,0 +1,59 @@
# vim:fileencoding=utf-8:noet
from __future__ import (unicode_literals, division, absolute_import, print_function)
import sys
from threading import Thread, Event
from time import sleep
from subprocess import Popen, PIPE
from powerline import Powerline
from powerline.lib.monotonic import monotonic
def read_to_log(pl, client):
for line in client.stdout:
if line:
pl.info(line, prefix='awesome-client')
for line in client.stderr:
if line:
pl.error(line, prefix='awesome-client')
if client.wait():
pl.error('Client exited with {0}', client.returncode, prefix='awesome')
def run(thread_shutdown_event=None, pl_shutdown_event=None, pl_config_loader=None,
interval=None):
powerline = Powerline(
'wm',
renderer_module='pango_markup',
shutdown_event=pl_shutdown_event,
config_loader=pl_config_loader,
)
powerline.update_renderer()
if not thread_shutdown_event:
thread_shutdown_event = powerline.shutdown_event
while not thread_shutdown_event.is_set():
# powerline.update_interval may change over time
used_interval = interval or powerline.update_interval
start_time = monotonic()
s = powerline.render(side='right')
request = 'powerline_widget:set_markup(\'' + s.translate({'\'': '\\\'', '\\': '\\\\'}) + '\')\n'
client = Popen(['awesome-client'], shell=False, stdout=PIPE, stderr=PIPE, stdin=PIPE)
client.stdin.write(request.encode('utf-8'))
client.stdin.close()
read_to_log(powerline.pl, client)
thread_shutdown_event.wait(max(used_interval - (monotonic() - start_time), 0.1))
class AwesomeThread(Thread):
__slots__ = ('powerline_shutdown_event',)
def __init__(self, **kwargs):
super(AwesomeThread, self).__init__()
self.powerline_run_kwargs = kwargs
def run(self):
run(**self.powerline_run_kwargs)

View File

@ -111,7 +111,7 @@ if hasattr(zsh, 'expand') and zsh.expand('${:-}') == '':
zsh_expand = zsh.expand
else:
def zsh_expand(s):
zsh.eval('_POWERLINE_REPLY="' + s + '"')
zsh.eval('local _POWERLINE_REPLY="' + s + '"')
ret = zsh.getvalue('_POWERLINE_REPLY')
zsh.setvalue('_POWERLINE_REPLY', None)
return ret

View File

@ -25,6 +25,11 @@ _powerline_tmux_pane() {
echo "${TMUX_PANE:-`tmux display -p "#D"`}" | tr -d ' %'
}
_powerline_tmux_pane() {
local -x TMUX="$_POWERLINE_TMUX"
echo "${TMUX_PANE:-`tmux display -p "#D"`}" | tr -d ' %'
}
_powerline_init_tmux_support() {
emulate -L zsh
if test -n "$TMUX" && tmux refresh -S &>/dev/null ; then

View File

@ -11,6 +11,7 @@ from powerline.lib.overrides import parsedotval, parse_override_var
from powerline.lib.dict import mergeargs
from powerline.lib.encoding import get_preferred_arguments_encoding
from powerline.lib.unicode import u, unicode
from powerline.bindings.wm import wm_threads
if sys.version_info < (3,):
@ -23,7 +24,7 @@ else:
return s
def finish_args(environ, args):
def finish_args(parser, environ, args, is_daemon=False):
'''Do some final transformations
Transforms ``*_override`` arguments into dictionaries, adding overrides from
@ -61,7 +62,13 @@ def finish_args(environ, args):
[path for path in environ.get('POWERLINE_CONFIG_PATHS', '').split(':') if path]
+ (args.config_path or [])
)
args.side = args.side[0]
if args.ext[0].startswith('wm.'):
if not is_daemon:
parser.error('WM bindings must be used with daemon only')
elif args.ext[0][3:] not in wm_threads:
parser.error('WM binding not found')
elif not args.side:
parser.error('expected one argument')
return args
@ -77,15 +84,16 @@ def get_argparser(ArgumentParser=argparse.ArgumentParser):
parser.add_argument(
'ext', nargs=1,
help='Extension: application for which powerline command is launched '
'(usually `shell\' or `tmux\').'
'(usually `shell\' or `tmux\'). Also supports `wm.\' extensions: '
+ ', '.join(('`wm.' + key + '\'' for key in wm_threads.keys())) + '.'
)
parser.add_argument(
'side', nargs=1, choices=('left', 'right', 'above', 'aboveleft'),
'side', nargs='?', choices=('left', 'right', 'above', 'aboveleft'),
help='Side: `left\' and `right\' represent left and right side '
'respectively, `above\' emits lines that are supposed to be printed '
'just above the prompt and `aboveleft\' is like concatenating '
'`above\' with `left\' with the exception that only one Python '
'instance is used in this case.'
'instance is used in this case. May be omitted for `wm.*\' extensions.'
)
parser.add_argument(
'-r', '--renderer-module', metavar='MODULE', type=str,

View File

@ -76,6 +76,50 @@
"branch:divider": { "fg": "darkcyan", "bg": "darkblue", "attrs": [] }
}
},
"ic": {
"colors": {
"gray0": "darkestblue",
"gray1": "darkestblue",
"gray2": "darkestblue",
"gray3": "darkblue",
"gray4": "darkblue",
"gray5": "darkestcyan",
"gray6": "darkestcyan",
"gray7": "darkestcyan",
"gray8": "mediumcyan",
"gray9": "mediumcyan",
"gray10": "mediumcyan",
"green_yellow_red": "gray5",
"dark_green_gray": "light_green_gray"
},
"groups": {
"mode": { "fg": "darkestcyan", "bg": "white", "attrs": ["bold"] },
"background:divider": { "fg": "darkcyan", "bg": "darkestblue", "attrs": [] },
"branch:divider": { "fg": "darkcyan", "bg": "darkblue", "attrs": [] }
}
},
"ix": {
"colors": {
"gray0": "darkestblue",
"gray1": "darkestblue",
"gray2": "darkestblue",
"gray3": "darkblue",
"gray4": "darkblue",
"gray5": "darkestcyan",
"gray6": "darkestcyan",
"gray7": "darkestcyan",
"gray8": "mediumcyan",
"gray9": "mediumcyan",
"gray10": "mediumcyan",
"green_yellow_red": "gray5",
"dark_green_gray": "light_green_gray"
},
"groups": {
"mode": { "fg": "darkestcyan", "bg": "white", "attrs": ["bold"] },
"background:divider": { "fg": "darkcyan", "bg": "darkestblue", "attrs": [] },
"branch:divider": { "fg": "darkcyan", "bg": "darkblue", "attrs": [] }
}
},
"v": {
"groups": {
"mode": { "fg": "darkorange", "bg": "brightestorange", "attrs": ["bold"] }
@ -95,6 +139,16 @@
"groups": {
"mode": { "fg": "white", "bg": "brightred", "attrs": ["bold"] }
}
},
"Rc": {
"groups": {
"mode": { "fg": "white", "bg": "brightred", "attrs": ["bold"] }
}
},
"Rx": {
"groups": {
"mode": { "fg": "white", "bg": "brightred", "attrs": ["bold"] }
}
}
}
}

View File

@ -73,6 +73,20 @@
"col_current": { "fg": "solarized:base0", "bg": "solarized:base3", "attrs": [] }
}
},
"ic": {
"groups": {
"background": { "fg": "solarized:base3", "bg": "solarized:base01", "attrs": [] },
"background:divider": { "fg": "solarized:base2", "bg": "solarized:base01", "attrs": [] },
"mode": { "fg": "solarized:base3", "bg": "solarized:blue", "attrs": ["bold"] }
}
},
"ix": {
"groups": {
"background": { "fg": "solarized:base3", "bg": "solarized:base01", "attrs": [] },
"background:divider": { "fg": "solarized:base2", "bg": "solarized:base01", "attrs": [] },
"mode": { "fg": "solarized:base3", "bg": "solarized:blue", "attrs": ["bold"] }
}
},
"v": {
"groups": {
"mode": { "fg": "solarized:base3", "bg": "solarized:orange", "attrs": ["bold"] }
@ -92,6 +106,16 @@
"groups": {
"mode": { "fg": "solarized:base3", "bg": "solarized:red", "attrs": ["bold"] }
}
},
"Rc": {
"groups": {
"mode": { "fg": "solarized:base3", "bg": "solarized:red", "attrs": ["bold"] }
}
},
"Rx": {
"groups": {
"mode": { "fg": "solarized:base3", "bg": "solarized:red", "attrs": ["bold"] }
}
}
}
}

View File

@ -74,6 +74,20 @@
"col_current": { "fg": "solarized:base00", "bg": "solarized:base03", "attrs": [] }
}
},
"ic": {
"groups": {
"background": { "fg": "solarized:base03", "bg": "solarized:base2", "attrs": [] },
"background:divider": { "fg": "solarized:base02", "bg": "solarized:base2", "attrs": [] },
"mode": { "fg": "solarized:base3", "bg": "solarized:blue", "attrs": ["bold"] }
}
},
"ix": {
"groups": {
"background": { "fg": "solarized:base03", "bg": "solarized:base2", "attrs": [] },
"background:divider": { "fg": "solarized:base02", "bg": "solarized:base2", "attrs": [] },
"mode": { "fg": "solarized:base3", "bg": "solarized:blue", "attrs": ["bold"] }
}
},
"v": {
"groups": {
"mode": { "fg": "solarized:base3", "bg": "solarized:orange", "attrs": ["bold"] }
@ -93,6 +107,16 @@
"groups": {
"mode": { "fg": "solarized:base3", "bg": "solarized:red", "attrs": ["bold"] }
}
},
"Rc": {
"groups": {
"mode": { "fg": "solarized:base3", "bg": "solarized:red", "attrs": ["bold"] }
}
},
"Rx": {
"groups": {
"mode": { "fg": "solarized:base3", "bg": "solarized:red", "attrs": ["bold"] }
}
}
}
}

View File

@ -46,7 +46,8 @@
},
"wm": {
"colorscheme": "default",
"theme": "default"
"theme": "default",
"update_interval": 2
}
}
}

View File

@ -105,8 +105,12 @@
"S": "S-LINE",
"^S": "S-BLCK",
"i": "INSERT",
"ic": "I-COMP",
"ix": "I-C_X ",
"R": "RPLACE",
"Rv": "V-RPLC",
"Rc": "R-COMP",
"Rx": "R-C_X ",
"c": "COMMND",
"cv": "VIM-EX",
"ce": "NRM-EX",

View File

@ -103,8 +103,12 @@
"S": "S·LINE",
"^S": "S·BLCK",
"i": "INSERT",
"ic": "I·COMP",
"ix": "I·C-X ",
"R": "RPLACE",
"Rv": "V·RPLC",
"Rc": "R·COMP",
"Rx": "R·C-X ",
"c": "COMMND",
"cv": "VIM·EX",
"ce": "NRM·EX",

View File

@ -103,8 +103,12 @@
"S": "S·LINE",
"^S": "S·BLCK",
"i": "INSERT",
"ic": "I·COMP",
"ix": "I·C-X ",
"R": "RPLACE",
"Rv": "V·RPLC",
"Rc": "R·COMP",
"Rx": "R·C-X ",
"c": "COMMND",
"cv": "VIM·EX",
"ce": "NRM·EX",

View File

@ -117,8 +117,12 @@
"S": "S·LINE",
"^S": "S·BLCK",
"i": "INSERT",
"ic": "I·COMP",
"ix": "I·C-X ",
"R": "RPLACE",
"Rv": "V·RPLC",
"Rc": "R·COMP",
"Rx": "R·C-X ",
"c": "COMMND",
"cv": "VIM·EX",
"ce": "NRM·EX",

View File

@ -103,8 +103,12 @@
"S": "S·LINE",
"^S": "S·BLCK",
"i": "INSERT",
"ic": "I·COMP",
"ix": "I·C-X ",
"R": "RPLACE",
"Rv": "V·RPLC",
"Rc": "R·COMP",
"Rx": "R·C-X ",
"c": "COMMND",
"cv": "VIM·EX",
"ce": "NRM·EX",

View File

@ -103,8 +103,12 @@
"S": "S·LINE",
"^S": "S·BLCK",
"i": "INSERT",
"ic": "I·COMP",
"ix": "I·C-X ",
"R": "RPLACE",
"Rv": "V·RPLC",
"Rc": "R·COMP",
"Rx": "R·C-X ",
"c": "COMMND",
"cv": "VIM·EX",
"ce": "NRM·EX",

View File

@ -104,8 +104,12 @@
"S": "SLN",
"^S": "SBL",
"i": "INS",
"ic": "I-C",
"ix": "I^X",
"R": "REP",
"Rv": "VRP",
"Rc": "R-C",
"Rx": "R^X",
"c": "CMD",
"cv": "VEX",
"ce": " EX",

View File

@ -25,7 +25,7 @@ class Repository(object):
# hg status -> (powerline file status, repo status flag)
statuses = {
b'M': ('M', 1), b'A': ('A', 1), b'R': ('R', 1), b'!': ('D', 1),
b'?': ('U', 2), b'I': ('I', 0)
b'?': ('U', 2), b'I': ('I', 0), b'C': ('', 0),
}
repo_statuses_str = (None, 'D ', ' U', 'DU')
@ -63,7 +63,7 @@ class Repository(object):
return self.do_status(self.directory, path)
def do_status(self, directory, path):
repo = self._repo(directory)
with self._repo(directory) as repo:
if path:
path = os.path.join(directory, path)
statuses = repo.status(include=path, all=True)

View File

@ -130,7 +130,8 @@ main_spec = (Spec(
local_themes=Spec().unknown_spec(
Spec().re('^[0-9A-Za-z-]+$'),
ext_theme_spec()
).optional()
).optional(),
update_interval=Spec().cmp('gt', 0.0).optional(),
).optional(),
).unknown_spec(
check_ext,

View File

@ -458,7 +458,7 @@ class Renderer(object):
segment is first_segment
if side == 'left' else
segment is last_segment
))
)) * theme.outer_padding
draw_divider = segment['draw_' + divider_type + '_divider']
segment_len += outer_padding
@ -519,7 +519,7 @@ class Renderer(object):
segment is first_segment
if side == 'left' else
segment is last_segment
)) * ' '
)) * theme.outer_padding * ' '
divider_type = 'soft' if compare_segment['highlight']['bg'] == segment['highlight']['bg'] else 'hard'
divider_highlighted = ''

View File

@ -72,7 +72,10 @@ def _fetch_battery_info(pl):
devtype_name,
'State'
) != 2
if energy_full > 0:
return (energy * 100.0 / energy_full), state
else:
return 0.0, state
return _flatten_battery
pl.debug('Not using DBUS+UPower as no batteries were found')

View File

@ -477,3 +477,54 @@ Requires ``osascript`` available in $PATH.
{0}
''').format(_common_args.format('rdio')))
class ITunesPlayerSegment(PlayerSegment):
def get_player_status(self, pl):
status_delimiter = '-~`/='
ascript = '''
tell application "System Events"
set process_list to (name of every process)
end tell
if process_list contains "iTunes" then
tell application "iTunes"
if player state is playing then
set t_title to name of current track
set t_artist to artist of current track
set t_album to album of current track
set t_duration to duration of current track
set t_elapsed to player position
set t_state to player state
return t_title & "{0}" & t_artist & "{0}" & t_album & "{0}" & t_elapsed & "{0}" & t_duration & "{0}" & t_state
end if
end tell
end if
'''.format(status_delimiter)
now_playing = asrun(pl, ascript)
if not now_playing:
return
now_playing = now_playing.split(status_delimiter)
if len(now_playing) != 6:
return
title, artist, album = now_playing[0], now_playing[1], now_playing[2]
state = _convert_state(now_playing[5])
total = _convert_seconds(now_playing[4])
elapsed = _convert_seconds(now_playing[3])
return {
'title': title,
'artist': artist,
'album': album,
'total': total,
'elapsed': elapsed,
'state': state
}
itunes = with_docstring(ITunesPlayerSegment(),
('''Return iTunes now playing information
Requires ``osascript``.
{0}
''').format(_common_args.format('itunes')))

View File

@ -50,15 +50,19 @@ vim_modes = {
'S': 'S-LINE',
'^S': 'S-BLCK',
'i': 'INSERT',
'R': 'REPLACE',
'Rv': 'V-RPLCE',
'ic': 'I-COMP',
'ix': 'I-C_X ',
'R': 'RPLACE',
'Rv': 'V-RPLC',
'Rc': 'R-COMP',
'Rx': 'R-C_X ',
'c': 'COMMND',
'cv': 'VIM EX',
'ce': 'EX',
'cv': 'VIM-EX',
'ce': 'NRM-EX',
'r': 'PROMPT',
'rm': 'MORE',
'r?': 'CONFIRM',
'!': 'SHELL',
'rm': '-MORE-',
'r?': 'CNFIRM',
'!': '!SHELL',
}
@ -87,18 +91,27 @@ def window_cached(func):
def mode(pl, segment_info, override=None):
'''Return the current vim mode.
If mode (returned by ``mode()`` VimL function, see ``:h mode()`` in Vim)
consists of multiple characters and necessary mode is not known to powerline
then it will fall back to mode with last character(s) ignored.
:param dict override:
dict for overriding default mode strings, e.g. ``{ 'n': 'NORM' }``
'''
mode = segment_info['mode']
if mode == 'nc':
return None
while mode:
try:
if not override:
return vim_modes[mode]
try:
return override[mode]
except KeyError:
return vim_modes[mode]
except KeyError:
mode = mode[:-1]
return 'BUG'
@window_cached

View File

@ -69,6 +69,7 @@ class Theme(object):
self.cursor_space_multiplier = None
self.cursor_columns = theme_config.get('cursor_columns')
self.spaces = theme_config['spaces']
self.outer_padding = int(theme_config.get('outer_padding', 1))
self.segments = []
self.EMPTY_SEGMENT = {
'contents': None,

View File

@ -6,6 +6,9 @@ import socket
import os
import errno
import sys
import fcntl
import atexit
import stat
from argparse import ArgumentParser
from select import select
@ -13,21 +16,21 @@ from signal import signal, SIGTERM
from time import sleep
from functools import partial
from io import BytesIO
from threading import Event
from itertools import chain
from logging import StreamHandler
from powerline.shell import ShellPowerline
from powerline.commands.main import finish_args, write_output
from powerline.lib.monotonic import monotonic
from powerline.lib.encoding import get_preferred_output_encoding, get_preferred_arguments_encoding, get_unicode_writer
from powerline.bindings.wm import wm_threads
from powerline.commands.main import get_argparser as get_main_argparser
from powerline.commands.daemon import get_argparser as get_daemon_argparser
is_daemon = False
use_filesystem = not sys.platform.lower().startswith('linux')
address = None
pidfile = None
USE_FILESYSTEM = not sys.platform.lower().startswith('linux')
class NonInteractiveArgParser(ArgumentParser):
@ -44,31 +47,48 @@ class NonInteractiveArgParser(ArgumentParser):
raise Exception(self.format_usage())
parser = get_main_argparser(NonInteractiveArgParser)
EOF = b'EOF\0\0'
powerlines = {}
logger = None
config_loader = None
home = os.path.expanduser('~')
class State(object):
__slots__ = ('powerlines', 'logger', 'config_loader', 'started_wm_threads',
'ts_shutdown_event')
def __init__(self, **kwargs):
self.logger = None
self.config_loader = None
self.started_wm_threads = {}
self.powerlines = {}
self.ts_shutdown_event = Event()
class PowerlineDaemon(ShellPowerline):
HOME = os.path.expanduser('~')
class NonDaemonShellPowerline(ShellPowerline):
def get_log_handler(self):
if not is_daemon:
import logging
return logging.StreamHandler()
return super(PowerlineDaemon, self).get_log_handler()
return StreamHandler()
def render(args, environ, cwd):
global logger
global config_loader
cwd = cwd or environ.get('PWD', '/')
def start_wm(args, environ, cwd, is_daemon, state):
wm_name = args.ext[0][3:]
if wm_name in state.started_wm_threads:
return b''
thread_shutdown_event = Event()
thread = wm_threads[wm_name](
thread_shutdown_event=thread_shutdown_event,
pl_shutdown_event=state.ts_shutdown_event,
pl_config_loader=state.config_loader,
)
thread.start()
state.started_wm_threads[wm_name] = (thread, thread_shutdown_event)
return b''
def render(args, environ, cwd, is_daemon, state):
segment_info = {
'getcwd': lambda: cwd,
'home': environ.get('HOME', home),
'home': environ.get('HOME', HOME),
'environ': environ,
'args': args,
}
@ -82,22 +102,24 @@ def render(args, environ, cwd):
environ.get('POWERLINE_CONFIG_OVERRIDES', ''),
environ.get('POWERLINE_CONFIG_PATHS', ''),
)
finish_args(environ, args)
PowerlineClass = ShellPowerline if is_daemon else NonDaemonShellPowerline
powerline = None
try:
powerline = powerlines[key]
powerline = state.powerlines[key]
except KeyError:
try:
powerline = powerlines[key] = PowerlineDaemon(
powerline = state.powerlines[key] = PowerlineClass(
args,
logger=logger,
config_loader=config_loader,
logger=state.logger,
config_loader=state.config_loader,
run_once=False,
shutdown_event=state.ts_shutdown_event,
)
if logger is None:
logger = powerline.logger
if config_loader is None:
config_loader = powerline.config_loader
if state.logger is None:
state.logger = powerline.logger
if state.config_loader is None:
state.config_loader = powerline.config_loader
except SystemExit:
# Somebody thought raising system exit was a good idea,
return ''
@ -168,23 +190,30 @@ def safe_bytes(o, encoding=get_preferred_output_encoding()):
return safe_bytes(str(e), encoding)
def parse_args(req, encoding=get_preferred_arguments_encoding()):
def parse_args(req, parser, encoding=get_preferred_arguments_encoding()):
args = [x.decode(encoding) for x in req.split(b'\0') if x]
numargs = int(args[0], 16)
shell_args = parser.parse_args(args[1:numargs + 1])
cwd = args[numargs + 1]
environ = dict(((k, v) for k, v in (x.partition('=')[0::2] for x in args[numargs + 2:])))
cwd = cwd or environ.get('PWD', '/')
return shell_args, environ, cwd
def do_render(req):
def get_answer(req, is_daemon, argparser, state):
try:
return safe_bytes(render(*parse_args(req)))
args, environ, cwd = parse_args(req, argparser)
finish_args(argparser, environ, args, is_daemon=True)
if args.ext[0].startswith('wm.'):
return safe_bytes(start_wm(args, environ, cwd, is_daemon, state))
else:
return safe_bytes(render(args, environ, cwd, is_daemon, state))
except Exception as e:
return safe_bytes(str(e))
def do_one(sock, read_sockets, write_sockets, result_map):
def do_one(sock, read_sockets, write_sockets, result_map, is_daemon, argparser,
state):
r, w, e = select(
tuple(read_sockets) + (sock,),
tuple(write_sockets),
@ -214,7 +243,7 @@ def do_one(sock, read_sockets, write_sockets, result_map):
if req == EOF:
raise SystemExit(0)
elif req:
ans = do_render(req)
ans = get_answer(req, is_daemon, argparser, state)
result_map[s] = ans
write_sockets.add(s)
else:
@ -230,17 +259,61 @@ def do_one(sock, read_sockets, write_sockets, result_map):
s.close()
def main_loop(sock):
def shutdown(sock, read_sockets, write_sockets, state):
'''Perform operations necessary for nicely shutting down daemon
Specifically it
#. Closes all sockets.
#. Notifies segments based on
:py:class:`powerline.lib.threaded.ThreadedSegment` and WM-specific
threads that daemon is shutting down.
#. Waits for threads to finish, but no more then 2 seconds total.
#. Waits so that total execution time of this function is 2 seconds in order
to allow ThreadedSegments to finish.
'''
total_wait_time = 2
shutdown_start_time = monotonic()
for s in chain((sock,), read_sockets, write_sockets):
s.close()
# Notify ThreadedSegments
state.ts_shutdown_event.set()
for thread, shutdown_event in state.started_wm_threads.values():
shutdown_event.set()
for thread, shutdown_event in state.started_wm_threads.values():
wait_time = total_wait_time - (monotonic() - shutdown_start_time)
if wait_time > 0:
thread.join(wait_time)
wait_time = total_wait_time - (monotonic() - shutdown_start_time)
sleep(wait_time)
def main_loop(sock, is_daemon):
sock.listen(128)
sock.setblocking(0)
read_sockets, write_sockets = set(), set()
result_map = {}
parser = get_main_argparser(NonInteractiveArgParser)
state = State()
try:
try:
while True:
do_one(sock, read_sockets, write_sockets, result_map)
do_one(
sock, read_sockets, write_sockets, result_map,
is_daemon=is_daemon,
argparser=parser,
state=state,
)
except KeyboardInterrupt:
raise SystemExit(0)
except SystemExit as e:
shutdown(sock, read_sockets, write_sockets, state)
raise e
return 0
@ -249,10 +322,10 @@ def daemonize(stdin=os.devnull, stdout=os.devnull, stderr=os.devnull):
pid = os.fork()
if pid > 0:
# exit first parent
sys.exit(0)
raise SystemExit(0)
except OSError as e:
sys.stderr.write("fork #1 failed: %d (%s)\n" % (e.errno, e.strerror))
sys.exit(1)
raise SystemExit(1)
# decouple from parent environment
os.chdir("/")
@ -264,10 +337,10 @@ def daemonize(stdin=os.devnull, stdout=os.devnull, stderr=os.devnull):
pid = os.fork()
if pid > 0:
# exit from second parent
sys.exit(0)
raise SystemExit(0)
except OSError as e:
sys.stderr.write("fork #2 failed: %d (%s)\n" % (e.errno, e.strerror))
sys.exit(1)
raise SystemExit(1)
# Redirect standard file descriptors.
si = open(stdin, 'rb')
@ -276,12 +349,11 @@ def daemonize(stdin=os.devnull, stdout=os.devnull, stderr=os.devnull):
os.dup2(si.fileno(), sys.stdin.fileno())
os.dup2(so.fileno(), sys.stdout.fileno())
os.dup2(se.fileno(), sys.stderr.fileno())
global is_daemon
is_daemon = True
return True
def check_existing():
if use_filesystem:
def check_existing(address):
if USE_FILESYSTEM:
# We cannot bind if the socket file already exists so remove it, we
# already have a lock on pidfile, so this should be safe.
try:
@ -299,7 +371,7 @@ def check_existing():
return sock
def kill_daemon():
def kill_daemon(address):
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
try:
try:
@ -313,7 +385,7 @@ def kill_daemon():
return True
def cleanup_lockfile(fd, *args):
def cleanup_lockfile(pidfile, fd, *args):
try:
# Remove the directory entry for the lock file
os.unlink(pidfile)
@ -326,10 +398,7 @@ def cleanup_lockfile(fd, *args):
raise SystemExit(1)
def lockpidfile():
import fcntl
import atexit
import stat
def lockpidfile(pidfile):
fd = os.open(
pidfile,
os.O_WRONLY | os.O_CREAT,
@ -344,24 +413,25 @@ def lockpidfile():
os.ftruncate(fd, 0)
os.write(fd, ('%d' % os.getpid()).encode('ascii'))
os.fsync(fd)
cleanup = partial(cleanup_lockfile, fd)
cleanup = partial(cleanup_lockfile, pidfile, fd)
signal(SIGTERM, cleanup)
atexit.register(cleanup)
return fd
def main():
global address
global pidfile
parser = get_daemon_argparser()
args = parser.parse_args()
is_daemon = False
address = None
pidfile = None
if args.socket:
address = args.socket
if not use_filesystem:
if not USE_FILESYSTEM:
address = '\0' + address
else:
if use_filesystem:
if USE_FILESYSTEM:
address = '/tmp/powerline-ipc-%d'
else:
# Use the abstract namespace for sockets rather than the filesystem
@ -370,13 +440,13 @@ def main():
address = address % os.getuid()
if use_filesystem:
if USE_FILESYSTEM:
pidfile = address + '.pid'
if args.kill:
if args.foreground or args.replace:
parser.error('--kill and --foreground/--replace cannot be used together')
if kill_daemon():
if kill_daemon(address):
if not args.quiet:
print ('Kill command sent to daemon, if it does not die in a couple of seconds use kill to kill it')
raise SystemExit(0)
@ -386,19 +456,19 @@ def main():
raise SystemExit(1)
if args.replace:
while kill_daemon():
while kill_daemon(address):
if not args.quiet:
print ('Kill command sent to daemon, waiting for daemon to exit, press Ctrl-C to terminate wait and exit')
sleep(2)
if use_filesystem and not args.foreground:
if USE_FILESYSTEM and not args.foreground:
# We must daemonize before creating the locked pidfile, unfortunately,
# this means further print statements are discarded
daemonize()
is_daemon = daemonize()
if use_filesystem:
if USE_FILESYSTEM:
# Create a locked pid file containing the daemons PID
if lockpidfile() is None:
if lockpidfile(pidfile) is None:
if not args.quiet:
sys.stderr.write(
'The daemon is already running. Use %s -k to kill it.\n' % (
@ -406,7 +476,7 @@ def main():
raise SystemExit(1)
# Bind to address or bail if we cannot bind
sock = check_existing()
sock = check_existing(address)
if sock is None:
if not args.quiet:
sys.stderr.write(
@ -414,14 +484,11 @@ def main():
os.path.basename(sys.argv[0])))
raise SystemExit(1)
if args.foreground:
return main_loop(sock)
if not use_filesystem:
if not USE_FILESYSTEM and not args.foreground:
# We daemonize on linux
daemonize()
is_daemon = daemonize()
main_loop(sock)
return main_loop(sock, is_daemon)
if __name__ == '__main__':

View File

@ -23,8 +23,9 @@ else:
if __name__ == '__main__':
args = get_argparser().parse_args()
finish_args(os.environ, args)
parser = get_argparser()
args = parser.parse_args()
finish_args(parser, os.environ, args)
powerline = ShellPowerline(args, run_once=True)
segment_info = {'args': args, 'environ': os.environ}
write_output(args, powerline, segment_info, get_unicode_writer())

View File

@ -59,7 +59,7 @@ else:
def get_version():
base_version = '2.5.2'
base_version = '2.6'
base_version += '.dev9999'
try:
return base_version + '+git.' + str(subprocess.check_output(['git', 'rev-parse', 'HEAD']).strip())
@ -70,7 +70,7 @@ def get_version():
setup(
name='powerline-status',
version='2.5.2',
version='2.6',
description='The ultimate statusline/prompt utility.',
long_description=README,
classifiers=[

View File

@ -1,11 +0,0 @@
# vim:fileencoding=utf-8:noet
from __future__ import (unicode_literals, division, absolute_import, print_function)
import sys
if sys.version_info < (2, 7):
from unittest2 import TestCase, main # NOQA
from unittest2.case import SkipTest # NOQA
else:
from unittest import TestCase, main # NOQA
from unittest.case import SkipTest # NOQA

View File

@ -1,42 +0,0 @@
. tests/bot-ci/scripts/common/main.sh
set +x
: ${PYTHON:=python}
FAILED=0
FAIL_SUMMARY=""
enter_suite() {
local suite_name="$1"
export POWERLINE_CURRENT_SUITE="${POWERLINE_CURRENT_SUITE}/$suite_name"
}
exit_suite() {
if test $FAILED -ne 0 ; then
echo "Suite ${POWERLINE_CURRENT_SUITE} failed, summary:"
echo "${FAIL_SUMMARY}"
fi
export POWERLINE_CURRENT_SUITE="${POWERLINE_CURRENT_SUITE%/*}"
if test "x$1" != "x--continue" ; then
exit $FAILED
fi
}
fail() {
local allow_failure=
if test "x$1" = "x--allow-failure" ; then
shift
allow_failure=A
fi
local test_name="$1"
local fail_char="$allow_failure$2"
local message="$3"
local full_msg="$fail_char $POWERLINE_CURRENT_SUITE|$test_name :: $message"
FAIL_SUMMARY="${FAIL_SUMMARY}${NL}${full_msg}"
echo "Failed: $full_msg"
echo "$full_msg" >> tests/failures
if test "x$allow_failure" = "x" ; then
FAILED=1
fi
}

View File

@ -1,6 +1,7 @@
#!/bin/bash
set -e
set -x
remote_master_hex() {
local url="$1"
@ -16,7 +17,7 @@ checkout_cached_dir() {
fi
if ! test -d "$target" ; then
git clone --depth=1 "$url" "$target"
mv "$target"/.git/refs/heads/master .version
git rev-parse HEAD > "$target/.version"
rm -rf "$target"/.git
fi
}

View File

@ -1,67 +0,0 @@
# vim:fileencoding=utf-8:noet
from __future__ import (unicode_literals, division, absolute_import, print_function)
import threading
from time import sleep
import pexpect
from tests.lib.vterm import VTerm
class ExpectProcess(threading.Thread):
def __init__(self, lib, rows, cols, cmd, args, cwd=None, env=None):
super(ExpectProcess, self).__init__()
self.vterm = VTerm(lib, rows, cols)
self.lock = threading.Lock()
self.rows = rows
self.cols = cols
self.cmd = cmd
self.args = args
self.cwd = cwd
self.env = env
self.buffer = []
self.child_lock = threading.Lock()
def run(self):
child = pexpect.spawn(self.cmd, self.args, cwd=self.cwd, env=self.env)
sleep(0.5)
child.setwinsize(self.rows, self.cols)
sleep(0.5)
self.child = child
status = None
while status is None:
try:
with self.child_lock:
s = child.read_nonblocking(size=1024, timeout=0)
status = child.status
except pexpect.TIMEOUT:
pass
except pexpect.EOF:
break
else:
with self.lock:
self.vterm.push(s)
self.buffer.append(s)
def resize(self, rows, cols):
with self.child_lock:
self.rows = rows
self.cols = cols
self.child.setwinsize(rows, cols)
self.vterm.resize(rows, cols)
def __getitem__(self, position):
with self.lock:
return self.vterm.vtscreen[position]
def read(self):
with self.lock:
ret = b''.join(self.buffer)
del self.buffer[:]
return ret
def send(self, data):
with self.child_lock:
self.child.send(data)

11
tests/modules/__init__.py Normal file
View File

@ -0,0 +1,11 @@
# vim:fileencoding=utf-8:noet
from __future__ import (unicode_literals, division, absolute_import, print_function)
import sys
if sys.version_info < (2, 7):
from unittest2 import TestCase, main # NOQA
from unittest2.case import SkipTest # NOQA
else:
from unittest import TestCase, main # NOQA
from unittest.case import SkipTest # NOQA

View File

@ -12,7 +12,7 @@ from powerline.renderer import Renderer
from powerline.lib.config import ConfigLoader
from powerline import Powerline, get_default_theme
from tests.lib import Args, replace_attr
from tests.modules.lib import Args, replace_attr
UT = get_default_theme(is_unicode=True)
@ -175,7 +175,7 @@ def get_powerline(config, **kwargs):
TestPowerline,
_helpers=helpers,
ext='test',
renderer_module='tests.lib.config_mock',
renderer_module='tests.modules.lib.config_mock',
logger=Logger(),
**kwargs
)

View File

@ -59,7 +59,7 @@ class FSTree(object):
self.p = TestPowerline(
_paths=self.get_config_paths(self.root),
ext='test',
renderer_module='tests.lib.config_mock',
renderer_module='tests.modules.lib.config_mock',
**self.p_kwargs
)
if os.environ.get('POWERLINE_RUN_LINT_DURING_TESTS'):

View File

@ -0,0 +1,269 @@
# vim:fileencoding=utf-8:noet
from __future__ import (unicode_literals, division, absolute_import, print_function)
import threading
import os
from time import sleep
from itertools import groupby
from signal import SIGKILL
from difflib import ndiff
import pexpect
from powerline.lib.unicode import u
from tests.modules.lib.vterm import VTerm, Dimensions
class MutableDimensions(object):
def __init__(self, rows, cols):
super(MutableDimensions, self).__init__()
self._list = [rows, cols]
def __getitem__(self, idx):
return self._list[idx]
def __setitem__(self, idx, val):
self._list[idx] = val
def __iter__(self):
return iter(self._list)
def __len__(self):
return 2
def __nonzero__(self):
return True
__bool__ = __nonzero__
rows = property(
fget = lambda self: self._list[0],
fset = lambda self, val: self._list.__setitem__(0, val),
)
cols = property(
fget = lambda self: self._list[1],
fset = lambda self, val: self._list.__setitem__(1, val),
)
class ExpectProcess(threading.Thread):
def __init__(self, lib, dim, cmd, args, cwd=None, env=None):
super(ExpectProcess, self).__init__()
self.vterm = VTerm(lib, dim)
self.lock = threading.Lock()
self.dim = Dimensions(*dim)
self.cmd = cmd
self.args = args
self.cwd = cwd
self.env = env
self.buffer = []
self.child_lock = threading.Lock()
self.shutdown_event = threading.Event()
def run(self):
child = pexpect.spawn(self.cmd, self.args, cwd=self.cwd, env=self.env)
sleep(0.5)
child.setwinsize(self.dim.rows, self.dim.cols)
sleep(0.5)
self.child = child
status = None
while status is None and not self.shutdown_event.is_set():
try:
with self.child_lock:
s = child.read_nonblocking(size=1024, timeout=0)
status = child.status
except pexpect.TIMEOUT:
pass
except pexpect.EOF:
break
else:
with self.lock:
self.vterm.push(s)
self.buffer.append(s)
if status is None:
child.kill(SIGKILL)
def kill(self):
self.shutdown_event.set()
def resize(self, dim):
with self.child_lock:
self.dim = Dimensions(*dim)
self.child.setwinsize(self.dim.rows, self.dim.cols)
self.vterm.resize(self.dim)
def __getitem__(self, position):
with self.lock:
return self.vterm.vtscreen[position]
def read(self):
with self.lock:
ret = b''.join(self.buffer)
del self.buffer[:]
return ret
def send(self, data):
with self.child_lock:
self.child.send(data)
def get_highlighted_text(self, text, attrs, default_props=()):
ret = []
new_attrs = attrs.copy()
for cell_properties, segment_text in text:
segment_text = segment_text.translate({'{': '{{', '}': '}}'})
if cell_properties not in new_attrs:
new_attrs[cell_properties] = len(new_attrs) + 1
props_name = new_attrs[cell_properties]
if props_name in default_props:
ret.append(segment_text)
else:
ret.append('{' + str(props_name) + ':' + segment_text + '}')
return ''.join(ret), new_attrs
def get_row(self, row, attrs, default_props=()):
with self.lock:
return self.get_highlighted_text((
(key, ''.join((cell.text for cell in subline)))
for key, subline in groupby((
self.vterm.vtscreen[row, col]
for col in range(self.dim.cols)
), lambda cell: cell.cell_properties_key)
), attrs, default_props)
def get_screen(self, attrs, default_props=()):
lines = []
for row in range(self.dim.rows):
line, attrs = self.get_row(row, attrs, default_props)
lines.append(line)
return '\n'.join(lines), attrs
def test_expected_result(p, test, last_attempt, last_attempt_cb=None):
expected_text, attrs = test['expected_result']
attempts = 3
result = None
while attempts:
actual_text, all_attrs = p.get_row(test['row'], attrs)
if actual_text == expected_text:
return True
attempts -= 1
print('Actual result does not match expected. Attempts left: {0}.'.format(attempts))
sleep(2)
print('Result:')
print(actual_text)
print('Expected:')
print(expected_text)
print('Attributes:')
print(all_attrs)
print('Screen:')
screen, screen_attrs = p.get_screen(attrs)
print(screen)
print(screen_attrs)
print('_' * 80)
print('Diff:')
print('=' * 80)
print(''.join((
u(line) for line in ndiff([actual_text + '\n'], [expected_text + '\n']))
))
if last_attempt and last_attempt_cb:
last_attempt_cb()
return False
ENV_BASE = {
# Reasoning:
# 1. vt* TERMs (used to be vt100 here) make tmux-1.9 use different and
# identical colors for inactive windows. This is not like tmux-1.6:
# foreground color is different from separator color and equal to (0,
# 102, 153) for some reason (separator has correct color). tmux-1.8 is
# fine, so are older versions (though tmux-1.6 and tmux-1.7 do not have
# highlighting for previously active window) and my system tmux-1.9a.
# 2. screen, xterm and some other non-256color terminals both have the same
# issue and make libvterm emit complains like `Unhandled CSI SGR 3231`.
# 3. screen-256color, xterm-256color and other -256color terminals make
# libvterm emit complains about unhandled escapes to stderr.
# 4. `st-256color` does not have any of the above problems, but it may be
# not present on the target system because it is installed with
# x11-terms/st and not with sys-libs/ncurses.
#
# For the given reasons decision was made: to fix tmux-1.9 tests and not
# make libvterm emit any data to stderr st-256color $TERM should be used, up
# until libvterm has its own terminfo database entry (if it ever will). To
# make sure that relevant terminfo entry is present on the target system it
# should be distributed with powerline test package. To make distribution
# not require modifying anything outside of powerline test directory
# TERMINFO variable is set.
#
# This fix propagates to non-tmux vterm tests just in case.
'TERM': 'st-256color',
# Also $TERMINFO definition in get_env
'POWERLINE_CONFIG_PATHS': os.path.abspath('powerline/config_files'),
'POWERLINE_COMMAND': 'powerline-render',
'LD_LIBRARY_PATH': os.environ.get('LD_LIBRARY_PATH', ''),
'PYTHONPATH': os.environ.get('PYTHONPATH', ''),
}
def get_env(vterm_path, test_dir, *args, **kwargs):
env = ENV_BASE.copy()
env.update({
'TERMINFO': os.path.join(test_dir, 'terminfo'),
'PATH': vterm_path,
'SHELL': os.path.join(vterm_path, 'bash'),
})
env.update(*args, **kwargs)
return env
def do_terminal_tests(tests, cmd, dim, args, env, cwd=None, fin_cb=None,
last_attempt_cb=None, attempts=3):
lib = os.environ.get('POWERLINE_LIBVTERM')
if not lib:
if os.path.exists('tests/bot-ci/deps/libvterm/libvterm.so'):
lib = 'tests/bot-ci/deps/libvterm/libvterm.so'
else:
lib = 'libvterm.so'
while attempts:
try:
p = ExpectProcess(
lib=lib,
dim=dim,
cmd=cmd,
args=args,
cwd=cwd,
env=env,
)
p.start()
ret = True
for test in tests:
try:
test_prep = test['prep_cb']
except KeyError:
pass
else:
test_prep(p)
ret = (
ret
and test_expected_result(p, test, attempts == 0,
last_attempt_cb)
)
if ret:
return ret
finally:
if fin_cb:
fin_cb(p=p, cmd=cmd, env=env)
p.kill()
p.join(10)
assert(not p.isAlive())
attempts -= 1
return False

View File

@ -3,9 +3,14 @@ from __future__ import (unicode_literals, division, absolute_import, print_funct
import ctypes
from collections import namedtuple
from powerline.lib.unicode import unicode, unichr, tointiter
Dimensions = namedtuple('Dimensions', ('rows', 'cols'))
class CTypesFunction(object):
def __init__(self, library, name, rettype, args):
self.name = name
@ -165,9 +170,9 @@ class VTermScreen(object):
class VTerm(object):
def __init__(self, lib, rows, cols):
def __init__(self, lib, dim):
self.functions = get_functions(lib)
self.vt = self.functions.vterm_new(rows, cols)
self.vt = self.functions.vterm_new(dim.rows, dim.cols)
self.vtscreen = VTermScreen(self.functions, self.functions.vterm_obtain_screen(self.vt))
self.vtscreen.reset(True)
@ -176,8 +181,8 @@ class VTerm(object):
data = data.encode('utf-8')
return self.functions.vterm_input_write(self.vt, data, len(data))
def resize(self, rows, cols):
self.functions.vterm_set_size(self.vt, rows, cols)
def resize(self, dim):
self.functions.vterm_set_size(self.vt, dim.rows, dim.cols)
def __del__(self):
try:

View File

@ -1,40 +0,0 @@
#!/bin/sh
. tests/common.sh
enter_suite daemon
export ADDRESS="powerline-ipc-test-$$"
echo "Powerline address: $ADDRESS"
if $PYTHON scripts/powerline-daemon -s$ADDRESS ; then
sleep 1
if ! ( \
$PYTHON client/powerline.py --socket $ADDRESS -p/dev/null shell left | \
grep 'file not found'
) ; then
fail "devnull" F "-p/dev/null argument ignored or not treated properly"
fi
if ( \
$PYTHON client/powerline.py --socket $ADDRESS \
-p$PWD/powerline/config_files shell left | \
grep 'file not found'
) ; then
fail "nodevnull" F "-p/dev/null argument remembered while it should not"
fi
if ! ( \
cd tests && \
$PYTHON ../client/powerline.py --socket $ADDRESS \
-p$PWD/../powerline/config_files shell left | \
grep 'tests'
) ; then
fail "segment" F "Output lacks string “tests”"
fi
else
fail "exitcode" E "Daemon exited with status $?"
fi
if $PYTHON scripts/powerline-daemon -s$ADDRESS -k ; then
:
else
fail "-k" F "powerline-daemon -k failed with exit code $?"
fi
exit_suite

View File

@ -1,10 +0,0 @@
#!/bin/sh
. tests/common.sh
enter_suite lint
if ! ${PYTHON} scripts/powerline-lint -p powerline/config_files ; then
fail "test" F "Running powerline-lint failed"
fi
exit_suite

View File

@ -1,7 +0,0 @@
#!/bin/sh
FAILED=0
if ! sh tests/test_shells/test.sh --fast ; then
echo "Failed shells"
FAILED=1
fi
exit $FAILED

View File

@ -1,71 +0,0 @@
#!/bin/sh
. tests/common.sh
enter_suite vim
if test -z "$VIM" ; then
if test -n "$USE_UCS2_PYTHON" ; then
NEW_VIM="$ROOT/tests/bot-ci/deps/vim/master-$UCS2_PYTHON_VARIANT-ucs2-double/vim"
OLD_VIM="$ROOT/tests/bot-ci/deps/vim/v7.0.112-$UCS2_PYTHON_VARIANT-ucs2/vim"
opt_dir="$HOME/opt/cpython-ucs2-$UCS2_PYTHON_VARIANT"
main_path="$opt_dir/lib/python$UCS2_PYTHON_VARIANT"
site_path="$main_path/site-packages"
venv_main_path="$VIRTUAL_ENV/lib/python$UCS2_PYTHON_VARIANT"
venv_site_path="$venv_main_path/site-packages"
new_paths="${main_path}:${site_path}:${venv_main_path}:${venv_site_path}"
export PYTHONPATH="$new_paths${PYTHONPATH:+:}$PYTHONPATH"
else
if test "$PYTHON_IMPLEMENTATION" != "CPython" ; then
exit 0
fi
if test -d "$ROOT/tests/bot-ci/deps" ; then
NEW_VIM="$ROOT/tests/bot-ci/deps/vim/master-$PYTHON_MM/vim"
OLD_VIM="$ROOT/tests/bot-ci/deps/vim/v7.0.112-$PYTHON_MM/vim"
else
NEW_VIM="vim"
fi
if test -e "$OLD_VIM" ; then
VIMS="NEW_VIM OLD_VIM"
else
VIMS="NEW_VIM"
fi
fi
else
NEW_VIM="$VIM"
OLD_VIM="$VIM"
fi
# Define some overrides. These ones must be ignored and do not affect Vim
# status/tab lines.
export POWERLINE_CONFIG_OVERRIDES='common.default_top_theme=ascii'
export POWERLINE_THEME_OVERRIDES='default.segments.left=[]'
test_script() {
local vim="$1"
local script="$2"
local test_name_prefix="$3"
echo "Running script $script with $vim"
if ! test -e "$vim" ; then
return 0
fi
if ! "$vim" -u NONE -S $script || test -f message.fail ; then
local test_name="$test_name_prefix-${script##*/}"
fail "${test_name%.vim}" F "Failed script $script run with $VIM"
cat message.fail >&2
rm message.fail
fi
}
for script in tests/test_*.vim ; do
if test "${script%.old.vim}" = "${script}" ; then
test_script "$NEW_VIM" "$script" new
fi
done
if test -e "$OLD_VIM" ; then
for script in tests/test_*.old.vim ; do
test_script "$OLD_VIM" "$script" old
done
fi
exit_suite

98
tests/shlib/common.sh Normal file
View File

@ -0,0 +1,98 @@
. tests/bot-ci/scripts/common/main.sh
set +x
: ${PYTHON:=python}
: ${USER:=`id -un`}
: ${HOME:=`getent passwd $USER | cut -d: -f6`}
export USER HOME
if test -z "$FAILED" ; then
FAILED=0
FAIL_SUMMARY=""
TMP_ROOT="$ROOT/tests/tmp"
FAILURES_FILE="$ROOT/tests/failures"
fi
ANSI_CLEAR="\033[0K"
travis_fold() {
local action="$1"
local name="$2"
name="$(echo -n "$name" | tr '\n\0' '--' | sed -r 's/[^A-Za-z0-9]+/-/g')"
name="$(echo -n "$name" | sed -r 's/-$//')"
echo -en "travis_fold:${action}:${name}\r${ANSI_CLEAR}"
}
enter_suite() {
local suite_name="$1" ; shift
export POWERLINE_CURRENT_SUITE="${POWERLINE_CURRENT_SUITE}/$suite_name"
travis_fold start "$POWERLINE_CURRENT_SUITE"
}
exit_suite() {
if test "$POWERLINE_CURRENT_SUITE" = "$POWERLINE_TMP_DIR_SUITE" ; then
rm_test_root
fi
if test $FAILED -ne 0 ; then
echo "Suite ${POWERLINE_CURRENT_SUITE} failed, summary:"
echo "${FAIL_SUMMARY}"
fi
travis_fold end "$POWERLINE_CURRENT_SUITE"
export POWERLINE_CURRENT_SUITE="${POWERLINE_CURRENT_SUITE%/*}"
if test "$1" != "--continue" ; then
exit $FAILED
fi
}
fail() {
local allow_failure=
if test "$1" = "--allow-failure" ; then
shift
allow_failure=A
fi
local test_name="$1" ; shift
local fail_char="$allow_failure$1" ; shift
local message="$1" ; shift
local full_msg="$fail_char $POWERLINE_CURRENT_SUITE|$test_name :: $message"
FAIL_SUMMARY="${FAIL_SUMMARY}${NL}${full_msg}"
echo "Failed: $full_msg"
echo "$full_msg" >> "$FAILURES_FILE"
if test -z "$allow_failure" ; then
FAILED=1
fi
}
make_test_root() {
local suffix="${POWERLINE_CURRENT_SUITE##*/}"
local tmpdir="$TMP_ROOT/$suffix/"
export POWERLINE_TMP_DIR_SUITE="$POWERLINE_CURRENT_SUITE"
if test -d "$tmpdir" ; then
rm -r "$tmpdir"
fi
mkdir -p "$tmpdir"
export TEST_ROOT="$tmpdir"
}
rm_test_root() {
if test -e "$FAILURES_FILE" ; then
return 0
fi
local suffix="${POWERLINE_CURRENT_SUITE##*/}"
if test -d "$TMP_ROOT/$suffix" ; then
rm -r "$TMP_ROOT/$suffix"
rmdir "$TMP_ROOT" &>/dev/null || true
fi
}
if ! which realpath ; then
realpath() {
$PYTHON -c 'import os, sys; print(os.path.realpath(sys.argv[1]))' "$1"
}
fi

33
tests/shlib/vim.sh Normal file
View File

@ -0,0 +1,33 @@
. tests/bot-ci/scripts/common/main.sh
if test -z "$POWERLINE_VIM_EXE" ; then
if test -n "$USE_UCS2_PYTHON" ; then
NEW_VIM="$ROOT/tests/bot-ci/deps/vim/master-$UCS2_PYTHON_VARIANT-ucs2-double/vim"
OLD_VIM="$ROOT/tests/bot-ci/deps/vim/v7.0.112-$UCS2_PYTHON_VARIANT-ucs2/vim"
opt_dir="$HOME/opt/cpython-ucs2-$UCS2_PYTHON_VARIANT"
main_path="$opt_dir/lib/python$UCS2_PYTHON_VARIANT"
site_path="$main_path/site-packages"
venv_main_path="$VIRTUAL_ENV/lib/python$UCS2_PYTHON_VARIANT"
venv_site_path="$venv_main_path/site-packages"
new_paths="${main_path}:${site_path}:${venv_main_path}:${venv_site_path}"
export PYTHONPATH="$new_paths${PYTHONPATH:+:}$PYTHONPATH"
else
if test "$PYTHON_IMPLEMENTATION" != "CPython" ; then
exit 0
fi
if test -d "$ROOT/tests/bot-ci/deps" ; then
NEW_VIM="$ROOT/tests/bot-ci/deps/vim/master-$PYTHON_MM/vim"
OLD_VIM="$ROOT/tests/bot-ci/deps/vim/v7.0.112-$PYTHON_MM/vim"
else
NEW_VIM="vim"
fi
if test -e "$OLD_VIM" ; then
VIMS="NEW_VIM OLD_VIM"
else
VIMS="NEW_VIM"
fi
fi
else
NEW_VIM="$POWERLINE_VIM_EXE"
OLD_VIM="$POWERLINE_VIM_EXE"
fi

26
tests/shlib/vterm.sh Normal file
View File

@ -0,0 +1,26 @@
. tests/shlib/common.sh
. tests/bot-ci/scripts/common/main.sh
set +x
vterm_setup() {
local test_dir="$1" ; shift
rm -rf "$test_dir"
mkdir "$test_dir"
mkdir "$test_dir/path"
ln -s "$(which "${PYTHON}")" "$test_dir/path/python"
ln -s "$(which bash)" "$test_dir/path"
cp -r "$ROOT/tests/terminfo" "$test_dir"
}
vterm_shutdown() {
local test_dir="$1" ; shift
if test $FAILED -eq 0 ; then
rm -rf "$test_dir"
else
echo "$FAIL_SUMMARY"
fi
}

View File

@ -1,13 +1,8 @@
#!/bin/bash
. tests/common.sh
. tests/shlib/common.sh
enter_suite root
: ${USER:=`id -un`}
: ${HOME:=`getent passwd $USER | cut -d: -f6`}
export USER HOME
if test "$TRAVIS" = true ; then
export PATH="$HOME/opt/fish/bin:${PATH}"
export PATH="$PWD/tests/bot-ci/deps/rc:$PATH"
@ -22,18 +17,16 @@ if test "$TRAVIS" = true ; then
. virtualenvwrapper.sh
workon cpython-ucs2-$UCS2_PYTHON_VARIANT
set -e
else
LIBRARY_PATH="$(ldd "$(which python)" | grep libpython | sed 's/^.* => //;s/ .*$//')"
LIBRARY_DIR="$(dirname "${LIBRARY_PATH}")"
export LD_LIBRARY_PATH="$LIBRARY_DIR${LD_LIBRARY_PATH:+:}$LD_LIBRARY_PATH"
fi
fi
if ! which realpath ; then
realpath() {
$PYTHON -c 'import os, sys; print(os.path.realpath(sys.argv[1]))' "$1"
}
fi
export PYTHON="${PYTHON:=python}"
export PYTHONPATH="${PYTHONPATH}${PYTHONPATH:+:}`realpath .`"
for script in tests/run_*_tests.sh ; do
for script in "$ROOT"/tests/test_*/test.sh ; do
test_name="${script##*/run_}"
if ! sh $script ; then
fail "${test_name%_tests.sh}" F "Failed $script"

View File

@ -0,0 +1,3 @@
#!/bin/sh
echo "$@" >> "$TEST_ROOT/results/args"
cat >> "$TEST_ROOT/results/requests"

View File

@ -0,0 +1,7 @@
{
"ext": {
"wm": {
"update_interval": 0.5
}
}
}

View File

@ -0,0 +1,18 @@
{
"segments": {
"left": [
{
"type": "string",
"highlight_groups": ["time"],
"contents": "default-left"
}
],
"right": [
{
"type": "string",
"highlight_groups": ["time"],
"contents": "default-right"
}
]
}
}

View File

@ -0,0 +1,18 @@
{
"segments": {
"left": [
{
"type": "string",
"highlight_groups": ["time"],
"contents": "dvi-left"
}
],
"right": [
{
"type": "string",
"highlight_groups": ["time"],
"contents": "dvi-right"
}
]
}
}

188
tests/test_awesome/test.sh Executable file
View File

@ -0,0 +1,188 @@
#!/bin/sh
. tests/shlib/common.sh
enter_suite awesome
make_test_root
TEST_PATH="$TEST_ROOT/path"
TEST_STATIC_ROOT="$ROOT/tests/test_awesome"
cp -r "$TEST_STATIC_ROOT/path" "$TEST_ROOT"
cp -r "$TEST_STATIC_ROOT/powerline" "$TEST_ROOT"
export PYTHONPATH="$ROOT${PYTHONPATH:+:}$PYTHONPATH"
ln -s "$(which "${PYTHON}")" "$TEST_PATH"/python
ln -s "$(which cat)" "$TEST_PATH"
ln -s "$(which sh)" "$TEST_PATH"
ln -s "$(which env)" "$TEST_PATH"
if which socat ; then
ln -s "$(which socat)" "$TEST_PATH"
fi
for pexe in powerline powerline.sh powerline.py ; do
if test -e scripts/$pexe ; then
ln -s "$PWD/scripts/$pexe" $TEST_ROOT/path
elif test -e client/$pexe ; then
ln -s "$PWD/client/$pexe" $TEST_ROOT/path
elif which $pexe ; then
ln -s "$(which $pexe)" $TEST_ROOT/path
else
continue
fi
if test "$pexe" != 'powerline.sh' || test -e "$TEST_PATH/socat" ; then
POWERLINE_COMMAND="$pexe"
break
fi
done
DEPRECATED_SCRIPT="$ROOT/powerline/bindings/awesome/powerline-awesome.py"
POWERLINE_DAEMON="scripts/powerline-daemon"
run() {
env -i \
LANG=C \
PATH="$TEST_PATH" \
XDG_CONFIG_HOME="$TEST_ROOT" \
XDG_CONFIG_DIRS="$TEST_ROOT/dummy" \
PYTHONPATH="$PYTHONPATH" \
TEST_ROOT="$TEST_ROOT" \
LD_LIBRARY_PATH="$LD_LIBRARY_PATH" \
"$@" || true
}
display_log() {
local log_file="$1"
echo "$log_file:"
echo '============================================================'
cat -v "$log_file"
echo
echo '____________________________________________________________'
}
check_log() {
local args_file="$TEST_ROOT/results/args"
local log_file="$TEST_ROOT/results/requests"
local line="$(head -n1 "$log_file")"
local linenum="$(cat "$log_file" | wc -l)"
echo "Number of runs: $linenum (expected approx 5 / 0.5 = 10 runs)"
if test $linenum -lt 5 ; then
fail "log:lt" F "Script was run not enough times: $linenum < 5"
return 1
elif test $linenum -gt 15 ; then
fail "log:gt" E "Script was run too many times: $linenum > 15"
return 1
fi
local expline="powerline_widget:set_markup('<span foreground=\"#303030\"> </span><span foreground=\"#d0d0d0\" background=\"#303030\" font_weight=\"bold\"> default-right </span>')"
if test "$expline" != "$line" ; then
echo "Line: '$line'"
echo "Expected: '$expline'"
fail "log:line" F "Unexpected line"
return 1
fi
local ret=0
while test $linenum -gt 0 ; do
echo "$line" >> "$TEST_ROOT/ok"
linenum=$(( linenum - 1 ))
done
if ! diff "$TEST_ROOT/ok" "$log_file" ; then
fail "log:diff" F "Unexpected output"
ret=1
fi
rm "$TEST_ROOT/ok"
return $ret
}
killscript() {
kill -KILL $1 || true
}
if ! test -e "$DEPRECATED_SCRIPT" ; then
# TODO: uncomment when skip is available
# skip "deprecated" "Missing deprecated bar bindings script"
:
else
enter_suite "deprecated"
for args in "" "0.5"; do
rm -rf "$TEST_ROOT/results"
mkdir "$TEST_ROOT/results"
DEPRECATED_LOG="$TEST_ROOT/deprecated.log"
run env \
DEPRECATED_SCRIPT="$DEPRECATED_SCRIPT" \
args="$args" \
DEPRECATED_LOG="$DEPRECATED_LOG" \
TEST_ROOT="$TEST_ROOT" \
sh -c '
echo $$ > "$TEST_ROOT/$args-pid"
exec "$DEPRECATED_SCRIPT" $args > "$DEPRECATED_LOG" 2>&1
' &
sleep 5
killscript "$(cat "$TEST_ROOT/$args-pid")"
rm "$TEST_ROOT/$args-pid"
if test -n "$(cat "$DEPRECATED_LOG")" ; then
display_log "$DEPRECATED_LOG"
fail "output" E "Nonempty $DEPRECATED_SCRIPT output"
fi
rm "$DEPRECATED_LOG"
if ! check_log ; then
display_log "$TEST_ROOT/results/args"
fail "log" F "Checking log failed"
fi
done
exit_suite --continue
fi
enter_suite "awesome"
ADDRESS="powerline-ipc-test-$$"
echo "Powerline address: $ADDRESS"
rm -rf "$TEST_ROOT/results"
mkdir "$TEST_ROOT/results"
run env \
POWERLINE_DAEMON="$POWERLINE_DAEMON" \
TEST_ROOT="$TEST_ROOT" \
ADDRESS="$ADDRESS" \
sh -c '
echo $$ > "$TEST_ROOT/dpid"
exec python "$POWERLINE_DAEMON" --socket $ADDRESS --foreground > "$TEST_ROOT/daemon.log" 2>&1
' &
DPID=$!
sleep 2
run "$POWERLINE_COMMAND" --socket $ADDRESS wm.awesome > "$TEST_ROOT/output.log.1" 2>&1
run "$POWERLINE_COMMAND" --socket $ADDRESS wm.awesome > "$TEST_ROOT/output.log.2" 2>&1
run "$POWERLINE_COMMAND" --socket $ADDRESS wm.awesome > "$TEST_ROOT/output.log.3" 2>&1
run "$POWERLINE_COMMAND" --socket $ADDRESS wm.awesome > "$TEST_ROOT/output.log.4" 2>&1
run "$POWERLINE_COMMAND" --socket $ADDRESS wm.awesome > "$TEST_ROOT/output.log.5" 2>&1
for log_file in "$TEST_ROOT"/output.log.* ; do
if test -n "$(cat "$log_file")" ; then
display_log "$log_file"
fail "output" E "Nonempty $POWERLINE_COMMAND output at run ${log_file#*.}"
fi
rm "$log_file"
done
sleep 5
run python "$POWERLINE_DAEMON" --socket $ADDRESS --quiet --kill > "$TEST_ROOT/kill.log" 2>&1
if test -n "$(cat "$TEST_ROOT/kill.log")" ; then
display_log "$TEST_ROOT/kill.log"
fail "daemonlog" E "Nonempty kill log"
fi
rm "$TEST_ROOT/kill.log"
wait $DPID
if test -n "$(cat "$TEST_ROOT/daemon.log")" ; then
display_log "$TEST_ROOT/daemon.log"
fail "daemonlog" E "Nonempty daemon log"
fi
rm "$TEST_ROOT/daemon.log"
if ! check_log ; then
display_log "$TEST_ROOT/results/args"
fail "log" F "Checking log failed"
fi
exit_suite --continue
if ! powerline-lint \
-p "$ROOT/powerline/config_files" \
-p "$TEST_STATIC_ROOT/powerline"
then
fail "lint" F "Checking test config failed"
fi
exit_suite

View File

@ -1,14 +1,12 @@
#!/bin/sh
. tests/common.sh
. tests/shlib/common.sh
enter_suite bar
TEST_ROOT="$ROOT/tests/bar"
make_test_root
TEST_PATH="$TEST_ROOT/path"
TEST_STATIC_ROOT="$ROOT/tests/test_bar"
test -d "$TEST_ROOT" && rm -r "$TEST_ROOT"
mkdir "$TEST_ROOT"
cp -r "$TEST_STATIC_ROOT/path" "$TEST_ROOT"
cp -r "$TEST_STATIC_ROOT/powerline" "$TEST_ROOT"
@ -51,7 +49,7 @@ check_log() {
if test "$warns" = "warns" ; then
local warning="$(head -n1 "$log_file" | sed 's/.*://')"
local expwarning="The 'bar' bindings are deprecated, please switch to 'lemonbar'"
if test "x$warning" != "x$expwarning" ; then
if test "$warning" != "$expwarning" ; then
echo "Got: $warning"
echo "Exp: $expwarning"
fail "warn" F "Expected warning"
@ -68,7 +66,7 @@ check_log() {
return 1
fi
local expline="%{l}%{F#ffd0d0d0}%{B#ff303030} $text-left %{F-B--u}%{F#ff303030} %{F-B--u}%{r}%{F#ff303030} %{F-B--u}%{F#ffd0d0d0}%{B#ff303030} $text-right %{F-B--u}"
if test "x$expline" != "x$line" ; then
if test "$expline" != "$line" ; then
echo "Line: '$line'"
echo "Expected: '$expline'"
fail "log:line" F "Unexpected line"
@ -151,14 +149,14 @@ else
if test "$fnum" -ne 2 ; then
fail "fnum" F "Expected two output files"
fi
if test "x${args#--height}" != "x$args" ; then
if test "${args#--height}" != "$args" ; then
height="${args#--height}"
height="${height# }"
height="${height#=}"
height="${height%% *}"
fi
command="lemonbar"
if test "x${args#--bar-command}" != "x$args" ; then
if test "${args#--bar-command}" != "$args" ; then
command="${args#--bar-command}"
command="${command# }"
command="${command#=}"
@ -168,11 +166,11 @@ else
rm "$TEST_ROOT/args.log"
script_args="${args#*-- }"
script_args="${script_args# }"
if test "x${script_args}" '=' "x$args" ; then
if test "${script_args}" = "$args" ; then
script_args=
fi
expected_args="$command -g 1920x$height+0${script_args:+ }$script_args${NL}$command -g 1920x$height+1${script_args:+ }$script_args"
if test "x$expected_args" != "x$received_args" ; then
if test "$expected_args" != "$received_args" ; then
echo "args:${NL}<$received_args>"
echo "expected:${NL}<$expected_args>"
fail "args" F "Expected different args"
@ -194,8 +192,4 @@ then
fail "lint" F "Checking test config failed"
fi
if test $FAILED -eq 0 ; then
rm -r "$TEST_ROOT"
fi
exit_suite

41
tests/test_daemon/test.sh Executable file
View File

@ -0,0 +1,41 @@
#!/bin/sh
. tests/shlib/common.sh
enter_suite daemon
export ADDRESS="powerline-ipc-test-$$"
echo "Powerline address: $ADDRESS"
if "$PYTHON" "$ROOT/scripts/powerline-daemon" -s"$ADDRESS" ; then
sleep 1
if ! ( \
"$PYTHON" "$ROOT/client/powerline.py" \
--socket "$ADDRESS" -p/dev/null shell left \
| grep "file not found"
) ; then
fail "devnull" F "-p/dev/null argument ignored or not treated properly"
fi
if ( \
"$PYTHON" "$ROOT/client/powerline.py" --socket "$ADDRESS" \
-p"$ROOT/powerline/config_files" shell left \
| grep "file not found"
) ; then
fail "nodevnull" F "-p/dev/null argument remembered while it should not"
fi
if ! ( \
cd "$ROOT/tests/test_daemon" \
&& "$PYTHON" "$ROOT/client/powerline.py" --socket "$ADDRESS" \
-p"$ROOT/powerline/config_files" shell left \
| grep "test_daemon"
) ; then
fail "segment" F "Output lacks string “tests”"
fi
else
fail "exitcode" E "Daemon exited with status $?"
fi
if "$PYTHON" "$ROOT/scripts/powerline-daemon" -s"$ADDRESS" -k ; then
:
else
fail "-k" F "powerline-daemon -k failed with exit code $?"
fi
exit_suite

View File

@ -1,11 +1,11 @@
#!/bin/sh
. tests/common.sh
. tests/shlib/common.sh
enter_suite vterm
for t in tests/test_in_vterm/test_*.sh ; do
for t in "$ROOT"/tests/test_in_vterm/test_*.sh ; do
test_name="${t##*/test_}"
if ! sh "$t" ; then
if ! "$t" ; then
fail "${test_name%.sh}" F "Failed running $t"
fi
done

View File

@ -4,317 +4,241 @@ from __future__ import (unicode_literals, division, absolute_import, print_funct
import os
import sys
import json
from time import sleep
from subprocess import check_call
from itertools import groupby
from difflib import ndiff
from glob import glob1
from traceback import print_exc
from powerline.lib.unicode import u
from powerline.lib.dict import updated
from powerline.bindings.tmux import get_tmux_version
from powerline import get_fallback_logger
from tests.lib.terminal import ExpectProcess
from tests.modules.lib.terminal import (ExpectProcess, MutableDimensions,
do_terminal_tests, get_env)
VTERM_TEST_DIR = os.path.abspath('tests/vterm_tmux')
def cell_properties_key_to_shell_escape(cell_properties_key):
fg, bg, bold, underline, italic = cell_properties_key
return('\x1b[38;2;{0};48;2;{1}{bold}{underline}{italic}m'.format(
';'.join((str(i) for i in fg)),
';'.join((str(i) for i in bg)),
bold=(';1' if bold else ''),
underline=(';4' if underline else ''),
italic=(';3' if italic else ''),
))
def tmux_logs_iter(test_dir):
for tail in glob1(test_dir, '*.log'):
yield os.path.join(test_dir, tail)
def test_expected_result(p, expected_result, cols, rows, print_logs):
last_line = []
for col in range(cols):
last_line.append(p[rows - 1, col])
attempts = 3
result = None
while attempts:
result = tuple((
(key, ''.join((i.text for i in subline)))
for key, subline in groupby(last_line, lambda i: i.cell_properties_key)
))
if result == expected_result:
return True
attempts -= 1
print('Actual result does not match expected. Attempts left: {0}.'.format(attempts))
sleep(2)
print('Result:')
shesc_result = ''.join((
'{0}{1}\x1b[m'.format(cell_properties_key_to_shell_escape(key), text)
for key, text in result
))
print(shesc_result)
print(result)
print('Expected:')
shesc_expected_result = ''.join((
'{0}{1}\x1b[m'.format(cell_properties_key_to_shell_escape(key), text)
for key, text in expected_result
))
print(shesc_expected_result)
p.send(b'powerline-config tmux setup\n')
sleep(5)
print('Screen:')
screen = []
for i in range(rows):
screen.append([])
for j in range(cols):
screen[-1].append(p[i, j])
print('\n'.join(
''.join((
'{0}{1}\x1b[m'.format(
cell_properties_key_to_shell_escape(i.cell_properties_key),
i.text
) for i in line
))
for line in screen
))
a = shesc_result.replace('\x1b', '\\e') + '\n'
b = shesc_expected_result.replace('\x1b', '\\e') + '\n'
print('_' * 80)
print('Diff:')
print('=' * 80)
print(''.join((u(line) for line in ndiff([a], [b]))))
if print_logs:
for f in glob1(VTERM_TEST_DIR, '*.log'):
def print_tmux_logs():
for f in tmux_logs_iter(VTERM_TEST_DIR):
print('_' * 80)
print(os.path.basename(f) + ':')
print('=' * 80)
with open(f, 'r') as F:
for line in F:
with open(f, 'r') as fp:
for line in fp:
sys.stdout.write(line)
os.unlink(f)
return False
def get_expected_result(tmux_version, expected_result_old, expected_result_1_7=None, expected_result_new=None, expected_result_2_0=None):
def get_expected_result(tmux_version,
expected_result_old,
expected_result_1_7=None,
expected_result_1_8=None,
expected_result_2_0=None):
if tmux_version >= (2, 0) and expected_result_2_0:
return expected_result_2_0
elif tmux_version >= (1, 8) and expected_result_new:
return expected_result_new
elif tmux_version >= (1, 8) and expected_result_1_8:
return expected_result_1_8
elif tmux_version >= (1, 7) and expected_result_1_7:
return expected_result_1_7
else:
return expected_result_old
def tmux_fin_cb(p, cmd, env):
try:
check_call([
cmd, '-S', env['POWERLINE_TMUX_SOCKET_PATH'], 'kill-server'
], env=env, cwd=VTERM_TEST_DIR)
except Exception:
print_exc()
for f in tmux_logs_iter(VTERM_TEST_DIR):
os.unlink(f)
def main(attempts=3):
vterm_path = os.path.join(VTERM_TEST_DIR, 'path')
socket_path = 'tmux-socket'
rows = 50
cols = 200
tmux_exe = os.path.join(vterm_path, 'tmux')
if os.path.exists('tests/bot-ci/deps/libvterm/libvterm.so'):
lib = 'tests/bot-ci/deps/libvterm/libvterm.so'
else:
lib = os.environ.get('POWERLINE_LIBVTERM', 'libvterm.so')
socket_path = os.path.abspath('tmux-socket-{0}'.format(attempts))
if os.path.exists(socket_path):
os.unlink(socket_path)
try:
p = ExpectProcess(
lib=lib,
rows=rows,
cols=cols,
cmd=tmux_exe,
args=[
# Specify full path to tmux socket (testing tmux instance must
# not interfere with user one)
env = get_env(vterm_path, VTERM_TEST_DIR, {
'POWERLINE_THEME_OVERRIDES': ';'.join((
key + '=' + json.dumps(val)
for key, val in (
('default.segments.right', [{
'type': 'string',
'name': 's1',
'highlight_groups': ['cwd'],
'priority':50,
}]),
('default.segments.left', [{
'type': 'string',
'name': 's2',
'highlight_groups': ['background'],
'priority':20,
}]),
('default.segment_data.s1.contents', 'S1 string here'),
('default.segment_data.s2.contents', 'S2 string here'),
)
)),
'POWERLINE_TMUX_SOCKET_PATH': socket_path,
})
conf_path = os.path.abspath('powerline/bindings/tmux/powerline.conf')
conf_line = 'source "' + (
conf_path.replace('\\', '\\\\').replace('"', '\\"')) + '"\n'
conf_file = os.path.realpath(os.path.join(VTERM_TEST_DIR, 'tmux.conf'))
with open(conf_file, 'w') as cf_fd:
cf_fd.write(conf_line)
tmux_version = get_tmux_version(get_fallback_logger())
dim = MutableDimensions(rows=50, cols=200)
def prepare_test_1(p):
sleep(5)
def prepare_test_2(p):
dim.cols = 40
p.resize(dim)
sleep(5)
base_attrs = {
((0, 0, 0), (243, 243, 243), 1, 0, 0): 'lead',
((243, 243, 243), (11, 11, 11), 0, 0, 0): 'leadsep',
((255, 255, 255), (11, 11, 11), 0, 0, 0): 'bg',
((199, 199, 199), (88, 88, 88), 0, 0, 0): 'cwd',
((88, 88, 88), (11, 11, 11), 0, 0, 0): 'cwdhsep',
((0, 0, 0), (0, 224, 0), 0, 0, 0): 'defstl',
}
tests = (
{
'expected_result': get_expected_result(
tmux_version,
expected_result_old=(
'{lead: 0 }{leadsep: }{bg: S2 string here }'
'{4: 0 }{cwdhsep:| }{6:bash }'
'{bg: }{4: 1- }{cwdhsep:| }{6:bash }'
'{bg: }{7: }{8:2* | }{9:bash }{10: }'
'{bg:' + (' ' * 124) + '}'
'{cwdhsep: }{cwd: S1 string here }', updated(base_attrs, {
((133, 133, 133), (11, 11, 11), 0, 0, 0): 4,
((188, 188, 188), (11, 11, 11), 0, 0, 0): 6,
((11, 11, 11), (0, 102, 153), 0, 0, 0): 7,
((102, 204, 255), (0, 102, 153), 0, 0, 0): 8,
((255, 255, 255), (0, 102, 153), 1, 0, 0): 9,
((0, 102, 153), (11, 11, 11), 0, 0, 0): 10,
})),
expected_result_1_8=(
'{lead: 0 }{leadsep: }{bg: S2 string here }'
'{4: 0 }{cwdhsep:| }{6:bash }'
'{bg: }{4: 1- }{cwdhsep:| }{7:bash }'
'{bg: }{8: }{9:2* | }{10:bash }{7: }'
'{bg:' + (' ' * 124) + '}'
'{cwdhsep: }{cwd: S1 string here }', updated(base_attrs, {
((133, 133, 133), (11, 11, 11), 0, 0, 0): 4,
((188, 188, 188), (11, 11, 11), 0, 0, 0): 6,
((0, 102, 153), (11, 11, 11), 0, 0, 0): 7,
((11, 11, 11), (0, 102, 153), 0, 0, 0): 8,
((102, 204, 255), (0, 102, 153), 0, 0, 0): 9,
((255, 255, 255), (0, 102, 153), 1, 0, 0): 10,
})),
expected_result_2_0=(
'{lead: 0 }{leadsep: }{bg: S2 string here }'
'{4: 0 }{cwdhsep:| }{6:bash }'
'{bg: }{4: 1- }{cwdhsep:| }{7:bash }'
'{bg: }{8: }{9:2* | }{10:bash }{7: }'
'{bg:' + (' ' * 125) + '}'
'{cwdhsep: }{cwd: S1 string here }', updated(base_attrs, {
((133, 133, 133), (11, 11, 11), 0, 0, 0): 4,
((188, 188, 188), (11, 11, 11), 0, 0, 0): 6,
((0, 102, 153), (11, 11, 11), 0, 0, 0): 7,
((11, 11, 11), (0, 102, 153), 0, 0, 0): 8,
((102, 204, 255), (0, 102, 153), 0, 0, 0): 9,
((255, 255, 255), (0, 102, 153), 1, 0, 0): 10,
})),
),
'prep_cb': prepare_test_1,
'row': dim.rows - 1,
}, {
'expected_result': get_expected_result(
tmux_version,
expected_result_old=('{bg:' + (' ' * 40) + '}', base_attrs),
expected_result_1_7=(
'{lead: 0 }'
'{leadsep: }{bg: <}{4:h }{bg: }{5: }'
'{6:2* | }{7:bash }{8: }{bg: }{cwdhsep: }'
'{cwd: S1 string here }', updated(base_attrs, {
((188, 188, 188), (11, 11, 11), 0, 0, 0): 4,
((11, 11, 11), (0, 102, 153), 0, 0, 0): 5,
((102, 204, 255), (0, 102, 153), 0, 0, 0): 6,
((255, 255, 255), (0, 102, 153), 1, 0, 0): 7,
((0, 102, 153), (11, 11, 11), 0, 0, 0): 8,
})),
expected_result_1_8=(
'{lead: 0 }'
'{leadsep: }{bg: <}{4:h }{bg: }{5: }'
'{6:2* | }{7:bash }{4: }{bg: }{cwdhsep: }'
'{cwd: S1 string here }', updated(base_attrs, {
((0, 102, 153), (11, 11, 11), 0, 0, 0): 4,
((11, 11, 11), (0, 102, 153), 0, 0, 0): 5,
((102, 204, 255), (0, 102, 153), 0, 0, 0): 6,
((255, 255, 255), (0, 102, 153), 1, 0, 0): 7,
})),
expected_result_2_0=(
'{lead: 0 }'
'{leadsep: }{bg:<}{4:ash }{bg: }{5: }'
'{6:2* | }{7:bash }{4: }{cwdhsep: }'
'{cwd: S1 string here }', updated(base_attrs, {
((0, 102, 153), (11, 11, 11), 0, 0, 0): 4,
((11, 11, 11), (0, 102, 153), 0, 0, 0): 5,
((102, 204, 255), (0, 102, 153), 0, 0, 0): 6,
((255, 255, 255), (0, 102, 153), 1, 0, 0): 7,
})),
),
'prep_cb': prepare_test_2,
'row': dim.rows - 1,
}
)
args = [
# Specify full path to tmux socket (testing tmux instance must not
# interfere with user one)
'-S', socket_path,
# Force 256-color mode
'-2',
# Request verbose logging just in case
'-v',
# Specify configuration file
'-f', os.path.abspath('powerline/bindings/tmux/powerline.conf'),
'-f', conf_file,
# Run bash three times
'new-session', 'bash --norc --noprofile -i', ';',
'new-window', 'bash --norc --noprofile -i', ';',
'new-window', 'bash --norc --noprofile -i', ';',
],
]
return do_terminal_tests(
tests=tests,
cmd=tmux_exe,
dim=dim,
args=args,
env=env,
cwd=VTERM_TEST_DIR,
env={
# Reasoning:
# 1. vt* TERMs (used to be vt100 here) make tmux-1.9 use
# different and identical colors for inactive windows. This
# is not like tmux-1.6: foreground color is different from
# separator color and equal to (0, 102, 153) for some reason
# (separator has correct color). tmux-1.8 is fine, so are
# older versions (though tmux-1.6 and tmux-1.7 do not have
# highlighting for previously active window) and my system
# tmux-1.9a.
# 2. screen, xterm and some other non-256color terminals both
# have the same issue and make libvterm emit complains like
# `Unhandled CSI SGR 3231`.
# 3. screen-256color, xterm-256color and other -256color
# terminals make libvterm emit complains about unhandled
# escapes to stderr.
# 4. `st-256color` does not have any of the above problems, but
# it may be not present on the target system because it is
# installed with x11-terms/st and not with sys-libs/ncurses.
#
# For the given reasons decision was made: to fix tmux-1.9 tests
# and not make libvterm emit any data to stderr st-256color
# $TERM should be used, up until libvterm has its own terminfo
# database entry (if it ever will). To make sure that relevant
# terminfo entry is present on the target system it should be
# distributed with powerline test package. To make distribution
# not require modifying anything outside of powerline test
# directory TERMINFO variable is set.
'TERMINFO': os.path.join(VTERM_TEST_DIR, 'terminfo'),
'TERM': 'st-256color',
'PATH': vterm_path,
'SHELL': os.path.join(VTERM_TEST_DIR, 'path', 'bash'),
'POWERLINE_CONFIG_PATHS': os.path.abspath('powerline/config_files'),
'POWERLINE_COMMAND': 'powerline-render',
'POWERLINE_THEME_OVERRIDES': (
'default.segments.right=[{"type":"string","name":"s1","highlight_groups":["cwd"],"priority":50}];'
'default.segments.left=[{"type":"string","name":"s2","highlight_groups":["background"],"priority":20}];'
'default.segment_data.s1.contents=S1 string here;'
'default.segment_data.s2.contents=S2 string here;'
),
'LD_LIBRARY_PATH': os.environ.get('LD_LIBRARY_PATH', ''),
'PYTHONPATH': os.environ.get('PYTHONPATH', ''),
},
fin_cb=tmux_fin_cb,
last_attempt_cb=print_tmux_logs,
)
p.start()
sleep(5)
tmux_version = get_tmux_version(get_fallback_logger())
expected_result = get_expected_result(tmux_version, expected_result_old=(
(((0, 0, 0), (243, 243, 243), 1, 0, 0), ' 0 '),
(((243, 243, 243), (11, 11, 11), 0, 0, 0), ' '),
(((255, 255, 255), (11, 11, 11), 0, 0, 0), ' S2 string here '),
(((133, 133, 133), (11, 11, 11), 0, 0, 0), ' 0 '),
(((88, 88, 88), (11, 11, 11), 0, 0, 0), '| '),
(((188, 188, 188), (11, 11, 11), 0, 0, 0), 'bash '),
(((255, 255, 255), (11, 11, 11), 0, 0, 0), ' '),
(((133, 133, 133), (11, 11, 11), 0, 0, 0), ' 1- '),
(((88, 88, 88), (11, 11, 11), 0, 0, 0), '| '),
(((188, 188, 188), (11, 11, 11), 0, 0, 0), 'bash '),
(((255, 255, 255), (11, 11, 11), 0, 0, 0), ' '),
(((11, 11, 11), (0, 102, 153), 0, 0, 0), ' '),
(((102, 204, 255), (0, 102, 153), 0, 0, 0), '2* | '),
(((255, 255, 255), (0, 102, 153), 1, 0, 0), 'bash '),
(((0, 102, 153), (11, 11, 11), 0, 0, 0), ' '),
(((255, 255, 255), (11, 11, 11), 0, 0, 0), ' ' * 124),
(((88, 88, 88), (11, 11, 11), 0, 0, 0), ' '),
(((199, 199, 199), (88, 88, 88), 0, 0, 0), ' S1 string here '),
), expected_result_new=(
(((0, 0, 0), (243, 243, 243), 1, 0, 0), ' 0 '),
(((243, 243, 243), (11, 11, 11), 0, 0, 0), ' '),
(((255, 255, 255), (11, 11, 11), 0, 0, 0), ' S2 string here '),
(((133, 133, 133), (11, 11, 11), 0, 0, 0), ' 0 '),
(((88, 88, 88), (11, 11, 11), 0, 0, 0), '| '),
(((188, 188, 188), (11, 11, 11), 0, 0, 0), 'bash '),
(((255, 255, 255), (11, 11, 11), 0, 0, 0), ' '),
(((133, 133, 133), (11, 11, 11), 0, 0, 0), ' 1- '),
(((88, 88, 88), (11, 11, 11), 0, 0, 0), '| '),
(((0, 102, 153), (11, 11, 11), 0, 0, 0), 'bash '),
(((255, 255, 255), (11, 11, 11), 0, 0, 0), ' '),
(((11, 11, 11), (0, 102, 153), 0, 0, 0), ' '),
(((102, 204, 255), (0, 102, 153), 0, 0, 0), '2* | '),
(((255, 255, 255), (0, 102, 153), 1, 0, 0), 'bash '),
(((0, 102, 153), (11, 11, 11), 0, 0, 0), ' '),
(((255, 255, 255), (11, 11, 11), 0, 0, 0), ' ' * 124),
(((88, 88, 88), (11, 11, 11), 0, 0, 0), ' '),
(((199, 199, 199), (88, 88, 88), 0, 0, 0), ' S1 string here '),
), expected_result_2_0=(
(((0, 0, 0), (243, 243, 243), 1, 0, 0), ' 0 '),
(((243, 243, 243), (11, 11, 11), 0, 0, 0), ' '),
(((255, 255, 255), (11, 11, 11), 0, 0, 0), ' S2 string here '),
(((133, 133, 133), (11, 11, 11), 0, 0, 0), ' 0 '),
(((88, 88, 88), (11, 11, 11), 0, 0, 0), '| '),
(((188, 188, 188), (11, 11, 11), 0, 0, 0), 'bash '),
(((255, 255, 255), (11, 11, 11), 0, 0, 0), ' '),
(((133, 133, 133), (11, 11, 11), 0, 0, 0), ' 1- '),
(((88, 88, 88), (11, 11, 11), 0, 0, 0), '| '),
(((0, 102, 153), (11, 11, 11), 0, 0, 0), 'bash '),
(((255, 255, 255), (11, 11, 11), 0, 0, 0), ' '),
(((11, 11, 11), (0, 102, 153), 0, 0, 0), ' '),
(((102, 204, 255), (0, 102, 153), 0, 0, 0), '2* | '),
(((255, 255, 255), (0, 102, 153), 1, 0, 0), 'bash '),
(((0, 102, 153), (11, 11, 11), 0, 0, 0), ' '),
(((255, 255, 255), (11, 11, 11), 0, 0, 0), ' ' * 125),
(((88, 88, 88), (11, 11, 11), 0, 0, 0), ' '),
(((199, 199, 199), (88, 88, 88), 0, 0, 0), ' S1 string here '),
))
ret = None
if not test_expected_result(p, expected_result, cols, rows, not attempts):
if attempts:
pass
# Will rerun main later.
else:
ret = False
elif ret is not False:
ret = True
cols = 40
p.resize(rows, cols)
sleep(5)
expected_result = get_expected_result(tmux_version, (
(((255, 255, 255), (11, 11, 11), 0, 0, 0), ' ' * cols),
), expected_result_1_7=(
(((0, 0, 0), (243, 243, 243), 1, 0, 0), ' 0 '),
(((243, 243, 243), (11, 11, 11), 0, 0, 0), ' '),
(((255, 255, 255), (11, 11, 11), 0, 0, 0), ' <'),
(((188, 188, 188), (11, 11, 11), 0, 0, 0), 'h '),
(((255, 255, 255), (11, 11, 11), 0, 0, 0), ' '),
(((11, 11, 11), (0, 102, 153), 0, 0, 0), ' '),
(((102, 204, 255), (0, 102, 153), 0, 0, 0), '2* | '),
(((255, 255, 255), (0, 102, 153), 1, 0, 0), 'bash '),
(((0, 102, 153), (11, 11, 11), 0, 0, 0), ' '),
(((255, 255, 255), (11, 11, 11), 0, 0, 0), ' '),
(((88, 88, 88), (11, 11, 11), 0, 0, 0), ' '),
(((199, 199, 199), (88, 88, 88), 0, 0, 0), ' S1 string here ')
), expected_result_new=(
(((0, 0, 0), (243, 243, 243), 1, 0, 0), ' 0 '),
(((243, 243, 243), (11, 11, 11), 0, 0, 0), ' '),
(((255, 255, 255), (11, 11, 11), 0, 0, 0), ' <'),
(((0, 102, 153), (11, 11, 11), 0, 0, 0), 'h '),
(((255, 255, 255), (11, 11, 11), 0, 0, 0), ' '),
(((11, 11, 11), (0, 102, 153), 0, 0, 0), ' '),
(((102, 204, 255), (0, 102, 153), 0, 0, 0), '2* | '),
(((255, 255, 255), (0, 102, 153), 1, 0, 0), 'bash '),
(((0, 102, 153), (11, 11, 11), 0, 0, 0), ' '),
(((255, 255, 255), (11, 11, 11), 0, 0, 0), ' '),
(((88, 88, 88), (11, 11, 11), 0, 0, 0), ' '),
(((199, 199, 199), (88, 88, 88), 0, 0, 0), ' S1 string here ')
), expected_result_2_0=(
(((0, 0, 0), (243, 243, 243), 1, 0, 0), ' 0 '),
(((243, 243, 243), (11, 11, 11), 0, 0, 0), ' '),
(((255, 255, 255), (11, 11, 11), 0, 0, 0), '<'),
(((0, 102, 153), (11, 11, 11), 0, 0, 0), 'ash '),
(((255, 255, 255), (11, 11, 11), 0, 0, 0), ' '),
(((11, 11, 11), (0, 102, 153), 0, 0, 0), ' '),
(((102, 204, 255), (0, 102, 153), 0, 0, 0), '2* | '),
(((255, 255, 255), (0, 102, 153), 1, 0, 0), 'bash '),
(((0, 102, 153), (11, 11, 11), 0, 0, 0), ' '),
(((88, 88, 88), (11, 11, 11), 0, 0, 0), ' '),
(((199, 199, 199), (88, 88, 88), 0, 0, 0), ' S1 string here ')
))
if not test_expected_result(p, expected_result, cols, rows, not attempts):
if attempts:
pass
else:
ret = False
elif ret is not False:
ret = True
if ret is not None:
return ret
finally:
check_call([tmux_exe, '-S', socket_path, 'kill-server'], env={
'PATH': vterm_path,
'LD_LIBRARY_PATH': os.environ.get('LD_LIBRARY_PATH', ''),
}, cwd=VTERM_TEST_DIR)
return main(attempts=(attempts - 1))
if __name__ == '__main__':

View File

@ -1,20 +1,17 @@
#!/bin/sh
. tests/common.sh
. tests/shlib/common.sh
. tests/shlib/vterm.sh
enter_suite tmux
rm -rf tests/vterm_tmux
mkdir tests/vterm_tmux
mkdir tests/vterm_tmux/path
VTERM_TEST_DIR="$ROOT/tests/vterm_tmux"
ln -s "$(which "${PYTHON}")" tests/vterm_tmux/path/python
ln -s "$(which bash)" tests/vterm_tmux/path
ln -s "$(which env)" tests/vterm_tmux/path
ln -s "$(which cut)" tests/vterm_tmux/path
ln -s "$PWD/scripts/powerline-render" tests/vterm_tmux/path
ln -s "$PWD/scripts/powerline-config" tests/vterm_tmux/path
vterm_setup "$VTERM_TEST_DIR"
cp -r tests/terminfo tests/vterm_tmux
ln -s "$(which env)" "$VTERM_TEST_DIR/path"
ln -s "$(which cut)" "$VTERM_TEST_DIR/path"
ln -s "$ROOT/scripts/powerline-render" "$VTERM_TEST_DIR/path"
ln -s "$ROOT/scripts/powerline-config" "$VTERM_TEST_DIR/path"
test_tmux() {
if test "$PYTHON_IMPLEMENTATION" = PyPy; then
@ -25,17 +22,18 @@ test_tmux() {
if ! which "${POWERLINE_TMUX_EXE}" ; then
return 0
fi
ln -sf "$(which "${POWERLINE_TMUX_EXE}")" tests/vterm_tmux/path
f=tests/test_in_vterm/test_tmux.py
if ! "${PYTHON}" $f ; then
ln -sf "$(which "${POWERLINE_TMUX_EXE}")" "$VTERM_TEST_DIR/path/tmux"
f="$ROOT/tests/test_in_vterm/test_tmux.py"
if ! "${PYTHON}" "$f" ; then
local test_name="$("$POWERLINE_TMUX_EXE" -V 2>&1 | cut -d' ' -f2)"
fail "$test_name" F "Failed vterm test $f"
fi
}
if test -z "$POWERLINE_TMUX_EXE" && test -d tests/bot-ci/deps/tmux ; then
for tmux in tests/bot-ci/deps/tmux/tmux-*/tmux ; do
export POWERLINE_TMUX_EXE="$PWD/$tmux"
if test -z "$POWERLINE_TMUX_EXE" && test -d "$ROOT/tests/bot-ci/deps/tmux"
then
for tmux in "$ROOT"/tests/bot-ci/deps/tmux/tmux-*/tmux ; do
export POWERLINE_TMUX_EXE="$tmux"
test_tmux || true
done
else
@ -43,10 +41,6 @@ else
test_tmux || true
fi
if test $FAILED -eq 0 ; then
rm -rf tests/vterm_tmux
else
echo "$FAIL_SUMMARY"
fi
vterm_shutdown "$VTERM_TEST_DIR"
exit_suite

49
tests/test_in_vterm/test_vim.py Executable file
View File

@ -0,0 +1,49 @@
#!/usr/bin/env python
# vim:fileencoding=utf-8:noet
from __future__ import (unicode_literals, division, absolute_import, print_function)
import os
import sys
import json
from time import sleep
from subprocess import check_call
from glob import glob1
from traceback import print_exc
from tests.modules.lib.terminal import (ExpectProcess, MutableDimensions,
do_terminal_tests, get_env)
VTERM_TEST_DIR = os.path.abspath('tests/vterm_vim')
def main(attempts=3):
vterm_path = os.path.join(VTERM_TEST_DIR, 'path')
vim_exe = os.path.join(vterm_path, 'vim')
env = get_env(vterm_path, VTERM_TEST_DIR)
dim = MutableDimensions(rows=50, cols=200)
tests = (
)
args = []
return do_terminal_tests(
tests=tests,
cmd=vim_exe,
dim=dim,
args=args,
env=env,
cwd=VTERM_TEST_DIR,
)
if __name__ == '__main__':
if main():
raise SystemExit(0)
else:
raise SystemExit(1)

41
tests/test_in_vterm/test_vim.sh Executable file
View File

@ -0,0 +1,41 @@
#!/bin/sh
. tests/shlib/common.sh
. tests/shlib/vterm.sh
. tests/shlib/vim.sh
enter_suite vim
VTERM_TEST_DIR="$ROOT/tests/vterm_vim"
vterm_setup "$VTERM_TEST_DIR"
test_vim() {
if test "$PYTHON_IMPLEMENTATION" != CPython ; then
# Can only link with cpython
return 0
fi
if ! which "$POWERLINE_VIM_EXE" ; then
return 0
fi
ln -sf "$(which "${POWERLINE_VIM_EXE}")" "$VTERM_TEST_DIR/path/vim"
f="$ROOT/tests/test_in_vterm/test_vim.py"
if ! "${PYTHON}" "$f" ; then
local test_name="$(LANG=C "$POWERLINE_VIM_EXE" --cmd 'echo version' --cmd qa 2>&1)"
fail "$test_name" F "Failed vterm test $f"
fi
}
if test -z "$POWERLINE_VIM_EXE" && test -d "$ROOT/tests/bot-ci/deps/vim"
then
for vim in "$OLD_VIM" "$NEW_VIM" ; do
export POWERLINE_VIM_EXE="$vim"
test_vim || true
done
else
export POWERLINE_VIM_EXE="${POWERLINE_VIM_EXE:-vim}"
test_vim || true
fi
vterm_shutdown "$VTERM_TEST_DIR"
exit_suite

10
tests/test_lint/test.sh Executable file
View File

@ -0,0 +1,10 @@
#!/bin/sh
. tests/shlib/common.sh
enter_suite lint
if ! "$PYTHON" "$ROOT/scripts/powerline-lint" -p "$ROOT/powerline/config_files" ; then
fail "test" F "Running powerline-lint failed"
fi
exit_suite

View File

@ -1,11 +1,11 @@
#!/bin/sh
. tests/common.sh
. tests/shlib/common.sh
enter_suite python
for file in tests/test_*.py ; do
for file in "$ROOT"/tests/test_python/test_*.py ; do
test_name="${file##*/test_}"
if ! ${PYTHON} $file --verbose --catch ; then
if ! "$PYTHON" "$file" --verbose --catch ; then
fail "${test_name%.py}" F "Failed test(s) from $file"
fi
done

View File

@ -13,8 +13,8 @@ else:
from powerline.commands.main import get_argparser, finish_args
from tests import TestCase
from tests.lib import replace_attr
from tests.modules import TestCase
from tests.modules.lib import replace_attr
class TestParser(TestCase):
@ -127,7 +127,7 @@ class TestParser(TestCase):
}),
]:
args = parser.parse_args(argv)
finish_args({}, args)
finish_args(parser, {}, args)
for key, val in expargs.items():
self.assertEqual(getattr(args, key), val)
for key, val in args.__dict__.items():
@ -140,5 +140,5 @@ class TestParser(TestCase):
if __name__ == '__main__':
from tests import main
from tests.modules import main
main()

View File

@ -11,8 +11,8 @@ from shutil import rmtree
from powerline.lib.dict import mergedicts_copy as mdc
from powerline import Powerline
from tests import TestCase
from tests.lib.config_mock import select_renderer, UT
from tests.modules import TestCase
from tests.modules.lib.config_mock import select_renderer, UT
CONFIG_DIR = 'tests/config'
@ -139,7 +139,7 @@ class WithConfigTree(object):
select_renderer(simpler_renderer=True)
self.p = TestPowerline(
ext='test',
renderer_module='tests.lib.config_mock',
renderer_module='tests.modules.lib.config_mock',
**self.p_kwargs
)
if os.environ.get('POWERLINE_RUN_LINT_DURING_TESTS'):
@ -266,5 +266,5 @@ class TestMerging(TestCase):
if __name__ == '__main__':
from tests import main
from tests.modules import main
main()

View File

@ -5,8 +5,8 @@ from time import sleep
from copy import deepcopy
from functools import wraps
from tests import TestCase
from tests.lib.config_mock import get_powerline, add_watcher_events, UT
from tests.modules import TestCase
from tests.modules.lib.config_mock import get_powerline, add_watcher_events, UT
config = {
@ -315,5 +315,5 @@ class TestConfigReload(TestCase):
if __name__ == '__main__':
from tests import main
from tests.modules import main
main()

View File

@ -7,11 +7,12 @@ import os
from functools import wraps
from copy import deepcopy
import tests.vim as vim_module
import tests.modules.vim as vim_module
from tests import TestCase
from tests.lib.config_mock import get_powerline, get_powerline_raw, swap_attributes, UT
from tests.lib import Args, replace_item
from tests.modules import TestCase
from tests.modules.lib.config_mock import (get_powerline, get_powerline_raw,
swap_attributes, UT)
from tests.modules.lib import Args, replace_item
def highlighted_string(s, group, **kwargs):
@ -550,6 +551,28 @@ class TestDisplayCondition(TestRender):
self.assertRenderEqual(p, '{56} s1{6-}>>{--}', mode='m1')
class TestOuterPadding(TestRender):
@add_args
def test_outer_padding_left(self, p, config):
config['themes/' + UT]['outer_padding'] = 5
self.assertRenderEqual(p, '{121} s{24}>>{344}g{4-}>>{--}', side='left')
@add_args
def test_outer_padding_right(self, p, config):
config['themes/' + UT]['outer_padding'] = 5
self.assertRenderEqual(p, '{4-}<<{344}f {--}', side='right')
@add_args
def test_outer_padding_ten(self, p, config):
config['themes/' + UT]['outer_padding'] = 10
self.assertRenderEqual(p, '{121} s {24}>>{344}g{34}>{34}|{344} f {--}', width=30)
@add_args
def test_outer_padding_zero(self, p, config):
config['themes/' + UT]['outer_padding'] = 0
self.assertRenderEqual(p, '{121}s {24}>>{344}g{34}>{34}|{344} f{--}', width=30)
class TestSegmentAttributes(TestRender):
@add_args
def test_no_attributes(self, p, config):
@ -775,7 +798,6 @@ class TestVim(TestCase):
def test_environ_update(self):
# Regression test: test that segment obtains environment from vim, not
# from os.environ.
import tests.vim as vim_module
with vim_module._with('globals', powerline_config_paths=['/']):
from powerline.vim import VimPowerline
import powerline as powerline_module
@ -795,7 +817,7 @@ class TestVim(TestCase):
import powerline as powerline_module
with swap_attributes(config, powerline_module):
with get_powerline_raw(config, VimPowerline, replace_gcp=True) as powerline:
powerline.add_local_theme('tests.matchers.always_true', {
powerline.add_local_theme('tests.modules.matchers.always_true', {
'segment_data': {
'foo': {
'contents': '“bar”'
@ -818,7 +840,7 @@ class TestVim(TestCase):
@classmethod
def setUpClass(cls):
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), 'path')))
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(os.path.dirname(__file__)), 'vim_sys_path')))
@classmethod
def tearDownClass(cls):
@ -851,5 +873,5 @@ class TestLemonbar(TestRender):
if __name__ == '__main__':
from tests import main
from tests.modules import main
main()

View File

@ -21,8 +21,8 @@ from powerline.lib.shell import run_cmd
import powerline.lib.unicode as plu
from tests.lib import Pl, replace_attr
from tests import TestCase, SkipTest
from tests.modules.lib import Pl, replace_attr
from tests.modules import TestCase, SkipTest
try:
@ -704,7 +704,7 @@ class TestVCS(TestCase):
@classmethod
def setUpClass(cls):
cls.powerline_old_cwd = os.getcwd()
os.chdir(os.path.dirname(__file__))
os.chdir(os.path.dirname(os.path.dirname(__file__)))
call(['git', 'init', '--quiet', GIT_REPO])
assert os.path.isdir(GIT_REPO)
call(['git', 'config', '--local', 'user.name', 'Foo'], cwd=GIT_REPO)
@ -736,5 +736,5 @@ class TestVCS(TestCase):
if __name__ == '__main__':
from tests import main
from tests.modules import main
main()

View File

@ -5,11 +5,11 @@ import os
from powerline.lib.config import ConfigLoader
from tests import TestCase
from tests.lib.fsconfig import FSTree
from tests.modules import TestCase
from tests.modules.lib.fsconfig import FSTree
FILE_ROOT = os.path.join(os.path.dirname(__file__), 'cfglib')
FILE_ROOT = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'cfglib')
class LoadedList(list):
@ -48,5 +48,5 @@ class TestLoaderCondition(TestCase):
if __name__ == '__main__':
from tests import main
from tests.modules import main
main()

View File

@ -3,8 +3,8 @@ from __future__ import (unicode_literals, division, absolute_import, print_funct
import powerline.listers.i3wm as i3wm
from tests.lib import Args, replace_attr, Pl
from tests import TestCase
from tests.modules.lib import Args, replace_attr, Pl
from tests.modules import TestCase
class TestI3WM(TestCase):
@ -223,5 +223,5 @@ class TestI3WM(TestCase):
if __name__ == '__main__':
from tests import main
from tests.modules import main
main()

View File

@ -14,8 +14,8 @@ from shutil import rmtree
from powerline import finish_common_config, create_logger
from tests import TestCase
from tests.lib import replace_attr
from tests.modules import TestCase
from tests.modules.lib import replace_attr
TIMESTAMP_RE = r'\d{4}-\d\d-\d\d \d\d:\d\d:\d\d,\d{3}'
@ -454,7 +454,7 @@ def setUpModule():
global __file__
old_cwd = os.getcwd()
__file__ = os.path.abspath(__file__)
os.chdir(os.path.dirname(__file__))
os.chdir(os.path.dirname(os.path.dirname(__file__)))
def tearDownModule():
@ -463,5 +463,5 @@ def tearDownModule():
if __name__ == '__main__':
from tests import main
from tests.modules import main
main()

View File

@ -9,10 +9,10 @@ import os
import json
import logging
import tests.vim as vim_module
import tests.modules.vim as vim_module
from tests.lib import Args, urllib_read, replace_attr
from tests import TestCase
from tests.modules.lib import Args, urllib_read, replace_attr
from tests.modules import TestCase
from powerline import NotInterceptedError
from powerline.segments.common import wthr
@ -46,7 +46,7 @@ def get_logger(stream=None):
class TestVimConfig(TestCase):
def test_vim(self):
from powerline.vim import VimPowerline
cfg_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'powerline', 'config_files')
cfg_path = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), 'powerline', 'config_files')
buffers = (
(('bufoptions',), {'buftype': 'help'}),
(('bufname', '[Command Line]'), {}),
@ -101,7 +101,7 @@ class TestVimConfig(TestCase):
@classmethod
def setUpClass(cls):
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), 'path')))
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(os.path.dirname(__file__)), 'vim_sys_path')))
@classmethod
def tearDownClass(cls):
@ -182,7 +182,7 @@ def setUpModule():
global saved_get_config_paths
import powerline
saved_get_config_paths = powerline.get_config_paths
path = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'powerline', 'config_files')
path = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), 'powerline', 'config_files')
powerline.get_config_paths = lambda: [path]
old_cwd = os.getcwd()
@ -197,5 +197,5 @@ def tearDownModule():
if __name__ == '__main__':
from tests import main
from tests.modules import main
main()

View File

@ -13,10 +13,11 @@ from powerline.segments import shell, tmux, pdb, i3wm
from powerline.lib.vcs import get_fallback_create_watcher
from powerline.lib.unicode import out_u
import tests.vim as vim_module
import tests.modules.vim as vim_module
from tests.lib import Args, urllib_read, replace_attr, new_module, replace_module_module, replace_env, Pl
from tests import TestCase, SkipTest
from tests.modules.lib import (Args, urllib_read, replace_attr, new_module,
replace_module_module, replace_env, Pl)
from tests.modules import TestCase, SkipTest
def get_dummy_guess(**kwargs):
@ -1159,6 +1160,8 @@ class TestVim(TestCase):
self.assertEqual(self.vim.mode(pl=pl, segment_info=segment_info, override={'n': 'NORM'}), 'NORM')
with vim_module._with('mode', 'i') as segment_info:
self.assertEqual(self.vim.mode(pl=pl, segment_info=segment_info), 'INSERT')
with vim_module._with('mode', 'i\0') as segment_info:
self.assertEqual(self.vim.mode(pl=pl, segment_info=segment_info), 'INSERT')
with vim_module._with('mode', chr(ord('V') - 0x40)) as segment_info:
self.assertEqual(self.vim.mode(pl=pl, segment_info=segment_info), 'V-BLCK')
self.assertEqual(self.vim.mode(pl=pl, segment_info=segment_info, override={'^V': 'VBLK'}), 'VBLK')
@ -1288,7 +1291,11 @@ class TestVim(TestCase):
pl = Pl()
segment_info = vim_module._get_segment_info()
self.assertEqual(self.vim.file_size(pl=pl, segment_info=segment_info), '0 B')
with vim_module._with('buffer', os.path.join(os.path.dirname(__file__), 'empty')) as segment_info:
with vim_module._with(
'buffer',
os.path.join(
os.path.dirname(os.path.dirname(__file__)), 'empty')
) as segment_info:
self.assertEqual(self.vim.file_size(pl=pl, segment_info=segment_info), '0 B')
def test_file_opts(self):
@ -1596,7 +1603,7 @@ class TestVim(TestCase):
@classmethod
def setUpClass(cls):
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), 'path')))
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(os.path.dirname(__file__)), 'vim_sys_path')))
from powerline.segments import vim
cls.vim = vim
from powerline.segments.common import vcs
@ -1661,7 +1668,7 @@ def setUpModule():
global __file__
old_cwd = os.getcwd()
__file__ = os.path.abspath(__file__)
os.chdir(os.path.dirname(__file__))
os.chdir(os.path.dirname(os.path.dirname(__file__)))
def tearDownModule():
@ -1670,5 +1677,5 @@ def tearDownModule():
if __name__ == '__main__':
from tests import main
from tests.modules import main
main()

View File

@ -6,10 +6,10 @@ import sys
from functools import partial
import tests.vim as vim_module
import tests.modules.vim as vim_module
from tests.lib import Pl
from tests import TestCase
from tests.modules.lib import Pl
from tests.modules import TestCase
class TestVim(TestCase):
@ -22,7 +22,7 @@ class TestVim(TestCase):
@classmethod
def setUpClass(cls):
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), 'path')))
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(os.path.dirname(__file__)), 'vim_sys_path')))
from powerline.selectors import vim
cls.vim = vim
@ -32,5 +32,5 @@ class TestVim(TestCase):
if __name__ == '__main__':
from tests import main
from tests.modules import main
main()

View File

@ -13,7 +13,7 @@ from powerline.lib.watcher.uv import UvNotFound
from powerline import get_fallback_logger
from powerline.lib.monotonic import monotonic
from tests import TestCase, SkipTest
from tests.modules import TestCase, SkipTest
INOTIFY_DIR = 'inotify' + os.path.basename(os.environ.get('PYTHON', ''))
@ -231,7 +231,7 @@ old_cwd = None
def setUpModule():
global old_cwd
old_cwd = os.getcwd()
os.chdir(os.path.dirname(__file__))
os.chdir(os.path.dirname(os.path.dirname(__file__)))
os.mkdir(INOTIFY_DIR)
@ -241,5 +241,5 @@ def tearDownModule():
if __name__ == '__main__':
from tests import main
from tests.modules import main
main()

View File

@ -1,7 +0,0 @@
print ('cd ' + 'tests/shell/3rd') # Start of the test marker
bool 42
bool 44
class Test(object):
pass
exit

View File

@ -32,7 +32,7 @@ ABOVE_FULL='[{
set_theme default_leftonly
export VIRTUAL_ENV=
source powerline/bindings/bash/powerline.sh
cd tests/shell/3rd
cd "$TEST_ROOT"/3rd
cd .git
cd ..
VIRTUAL_ENV="$HOME/.virtenvs/some-virtual-environment"

View File

@ -8,7 +8,7 @@ set_theme_option default_leftonly.segment_data.hostname.args.only_if_ssh false
set_theme default_leftonly
. powerline/bindings/shell/powerline.sh
export VIRTUAL_ENV=
cd tests/shell/3rd
cd "$TEST_ROOT"/3rd
cd .git
cd ..
VIRTUAL_ENV="$HOME/.virtenvs/some-virtual-environment"

View File

@ -8,7 +8,7 @@ set_theme_option default_leftonly.segment_data.hostname.args.only_if_ssh false
set_theme default_leftonly
. powerline/bindings/shell/powerline.sh
export VIRTUAL_ENV=
cd tests/shell/3rd
cd "$TEST_ROOT"/3rd
cd .git
cd ..
VIRTUAL_ENV="$HOME/.virtenvs/some-virtual-environment"

View File

@ -37,7 +37,7 @@ while jobs | grep fish_update_completions
end
powerline-setup
setenv VIRTUAL_ENV
cd tests/shell/3rd
cd "$TEST_ROOT"/3rd
cd .git
cd ..
setenv VIRTUAL_ENV "$HOME/.virtenvs/some-virtual-environment"

View File

@ -0,0 +1,7 @@
print ('cd ' + '"$TEST_ROOT"/3rd') # Start of the test marker
bool 42
bool 44
class Test(object):
pass
exit

View File

@ -8,7 +8,7 @@ set_theme default_leftonly
set_theme_option default_leftonly.segment_data.hostname.args.only_if_ssh false
. powerline/bindings/shell/powerline.sh
export VIRTUAL_ENV=
cd tests/shell/3rd
cd "$TEST_ROOT"/3rd
cd .git
cd ..
VIRTUAL_ENV="$HOME/.virtenvs/some-virtual-environment"

View File

@ -5,7 +5,8 @@ set_theme_option default_leftonly.segment_data.hostname.args.only_if_ssh false
POWERLINE_CONFIG_OVERRIDES = 'ext.shell.theme=default_leftonly'
. powerline/bindings/rc/powerline.rc
VIRTUAL_ENV = ()
cd tests/shell/3rd
cd $TEST_ROOT/3rd
true cd "$TEST_ROOT"/3rd # Test start marker
cd .git
cd ..
VIRTUAL_ENV = '/home/foo/.virtenvs/some-virtual-environment'

View File

@ -2,7 +2,7 @@ setenv POWERLINE_THEME_OVERRIDES "default_leftonly.segment_data.hostname.args.on
setenv POWERLINE_CONFIG_OVERRIDES "ext.shell.theme=default_leftonly"
source powerline/bindings/tcsh/powerline.tcsh
unsetenv VIRTUAL_ENV
cd tests/shell/3rd
cd "$TEST_ROOT"/3rd
cd .git
cd ..
setenv VIRTUAL_ENV "/home/foo/.virtenvs/some-virtual-environment"

Some files were not shown because too many files have changed in this diff Show More