Release 2.1

- Added [BAR](https://github.com/LemonBoy/bar) support.
- Added support for pdb (Python debugger) prompt.
- Added more highlight groups to solarized colorscheme.
- Updated zpython bindings.
- Fixed C version of the client on non-Linux platforms.
- Fixed some errors in powerline-lint code.
- Fixed Python-2.6 incompatibilities in setup.py.
This commit is contained in:
ZyX 2015-02-19 02:56:51 +03:00
commit 8164f42fb9
58 changed files with 1799 additions and 224 deletions

View File

@ -42,6 +42,26 @@ void do_write(int sd, const char *raw, size_t len) {
} }
} }
inline size_t true_sun_len(const struct sockaddr_un *ptr) {
#ifdef __linux__
/* Because SUN_LEN uses strlen and abstract namespace paths begin
* with a null byte, SUN_LEN is broken for these. Passing the full
* struct size also fails on Linux, so compute manually. The
* abstract namespace is Linux-only. */
if (ptr->sun_path[0] == '\0') {
return sizeof(ptr->sun_family) + strlen(ptr->sun_path + 1) + 1;
}
#endif
#ifdef SUN_LEN
/* If the vendor provided SUN_LEN, we may as well use it. */
return SUN_LEN(ptr);
#else
/* SUN_LEN is not POSIX, so if it was not provided, use the struct
* size as a fallback. */
return sizeof(struct sockaddr_un);
#endif
}
#ifdef __linux__ #ifdef __linux__
# define ADDRESS_TEMPLATE "powerline-ipc-%d" # define ADDRESS_TEMPLATE "powerline-ipc-%d"
# define A +1 # define A +1
@ -91,7 +111,7 @@ int main(int argc, char *argv[]) {
server.sun_family = AF_UNIX; server.sun_family = AF_UNIX;
strncpy(server.sun_path A, address, strlen(address)); strncpy(server.sun_path A, address, strlen(address));
if (connect(sd, (struct sockaddr *) &server, (socklen_t) (sizeof(server.sun_family) + strlen(address) A)) < 0) { if (connect(sd, (struct sockaddr *) &server, true_sun_len(&server)) < 0) {
close(sd); close(sd);
/* We failed to connect to the daemon, execute powerline instead */ /* We failed to connect to the daemon, execute powerline instead */
argc = (argc < NEW_ARGV_SIZE - 1) ? argc : NEW_ARGV_SIZE - 1; argc = (argc < NEW_ARGV_SIZE - 1) ? argc : NEW_ARGV_SIZE - 1;

View File

@ -1,5 +1,7 @@
:orphan: :orphan:
.. _command-powerline-lint:
powerline-lint manual page powerline-lint manual page
========================== ==========================

View File

@ -16,7 +16,7 @@ Powerline provides default configurations in the following locations:
:ref:`Main configuration <config-main>` :ref:`Main configuration <config-main>`
:file:`powerline/config.json` :file:`powerline/config.json`
:ref:`Colorschemes <config-colors>` :ref:`Colorschemes <config-colorschemes>`
:file:`powerline/colorschemes/{name}.json`, :file:`powerline/colorschemes/{name}.json`,
:file:`powerline/colorscheme/{extension}/__main__.json`, :file:`powerline/colorscheme/{extension}/__main__.json`,
:file:`powerline/colorschemes/{extension}/{name}.json` :file:`powerline/colorschemes/{extension}/{name}.json`
@ -33,6 +33,8 @@ corresponds to :file:`~/.config/powerline` on both platforms.
If per-instance configuration is needed please refer to :ref:`Local If per-instance configuration is needed please refer to :ref:`Local
configuration overrides <local-configuration-overrides>`. configuration overrides <local-configuration-overrides>`.
.. _configuration-merging:
.. note:: .. note::
Existing multiple configuration files that have the same name, but are placed Existing multiple configuration files that have the same name, but are placed
in different directories, will be merged. Merging happens in the following in different directories, will be merged. Merging happens in the following
@ -63,20 +65,21 @@ Quick setup guide
This guide will help you with the initial configuration of Powerline. This guide will help you with the initial configuration of Powerline.
Start by copying the entire set of default configuration files to the Look at configuration in :file:`{powerline_root}/powerline/config_files`. If you
corresponding path in your user config directory: want to modify some file you can create :file:`~/.config/powerline` directory
and put modifications there: all configuration files are :ref:`merged
.. code-block:: sh <configuration-merging>` with each other.
mkdir ~/.config/powerline
cp -R /path/to/powerline/config_files/* ~/.config/powerline
Each extension (vim, tmux, etc.) has its own theme, and they are located in Each extension (vim, tmux, etc.) has its own theme, and they are located in
:file:`{config directory}/themes/{extension}/default.json`. :file:`{config directory}/themes/{extension}/default.json`. Best way to modify
it is to copy this theme as a whole, remove ``segment_data`` key with
corresponding value if present (unless you need to modify it, in which case only
modifications must be left) and do necessary modifications in the list of
segments (lists are not subject to merging: this is why you need a copy).
If you want to move, remove or customize any of the provided segments, you If you want to move, remove or customize any of the provided segments in the
can do that by updating the segment dictionary in the theme you want to copy, you can do that by updating the segment dictionary in the theme you want
customize. A segment dictionary looks like this: to customize. A segment dictionary looks like this:
.. code-block:: javascript .. code-block:: javascript
@ -93,6 +96,11 @@ prompt or statusline.
is valid JSON! Its strongly recommended that you run your configuration is valid JSON! Its strongly recommended that you run your configuration
files through ``jsonlint`` after changing them. files through ``jsonlint`` after changing them.
.. note::
If your modifications appear not to work, run :ref:`powerline-lint script
<command-powerline-lint>`. This script should show you the location of the
error.
Some segments need a user configuration to work properly. Heres a couple of Some segments need a user configuration to work properly. Heres a couple of
segments that you may want to customize right away: segments that you may want to customize right away:

View File

@ -23,3 +23,9 @@ Vim listers
.. automodule:: powerline.listers.vim .. automodule:: powerline.listers.vim
:members: :members:
Pdb listers
-----------
.. automodule:: powerline.listers.pdb
:members:

View File

@ -239,3 +239,9 @@ In order to keep shell prompt, but avoid launching Python twice to get unused
In order to remove additional space from the end of the right prompt in fish In order to remove additional space from the end of the right prompt in fish
that was added in order to support multiline prompt ``$POWERLINE_NO_FISH_ABOVE`` that was added in order to support multiline prompt ``$POWERLINE_NO_FISH_ABOVE``
or ``$POWERLINE_NO_SHELL_ABOVE`` variable should be set. or ``$POWERLINE_NO_SHELL_ABOVE`` variable should be set.
PDB overrides
=============
Like shell bindings :ref:`PDB bindings <pdb-prompt>` take overrides from
:ref:`environment variables <local-configuration-overrides-env>`.

View File

@ -0,0 +1,7 @@
************
PDB segments
************
.. automodule:: powerline.segments.pdb
:members:

View File

@ -469,6 +469,21 @@ Ipython
Attribute ``prompt_count`` contains the so-called “history count” Attribute ``prompt_count`` contains the so-called “history count”
(equivalent to ``\N`` in ``in_template``). (equivalent to ``\N`` in ``in_template``).
Pdb
---
``pdb``
Currently active :py:class:`pdb.Pdb` instance.
``curframe``
Frame which will be run next. Note: due to the existence of
:py:func:`powerline.listers.pdb.frame_lister` one must not use
``segment_info['pdb'].curframe``.
``initial_stack_length``
Equal to the length of :py:attr:`pdb.Pdb.stack` at the first invocation of
the prompt decremented by one.
Segment class Segment class
============= =============

View File

@ -124,3 +124,41 @@ the used profile:
IPython=0.11* is not supported and does not work. IPython<0.10 was not IPython=0.11* is not supported and does not work. IPython<0.10 was not
tested (not installable by pip). tested (not installable by pip).
.. _pdb-prompt:
PDB prompt
==========
To use Powerline with PDB prompt you need to use custom class. Inherit your
class from :py:class:`pdb.Pdb` and decorate it with
:py:func:`powerline.bindings.pdb.use_powerline_prompt`:
.. code-block:: Python
import pdb
from powerline.bindings.pdb import use_powerline_prompt
@use_powerline_prompt
class MyPdb(pdb.Pdb):
pass
MyPdb.run('some.code.to.debug()')
. Alternatively you may use
.. code-block:: bash
python -mpowerline.bindings.pdb path/to/script.py
just like you used ``python -m pdb``.
.. note:
If you are using Python-2.6 you need to use ``python
-mpowerline.bindings.pdb.__main__``, not what is shown above.
.. warning:
Using PyPy (not PyPy3) forces ASCII-only prompts. In other cases unicode
characters are allowed, even if you use `pdbpp
<https://pypi.python.org/pypi/pdbpp>`_.

View File

@ -44,12 +44,30 @@ Add the following to :file:`~/.config/qtile/config.py`:
), ),
] ]
.. _bar-usage:
LemonBoys bar
==============
To run the bar simply pipe the output of the binding script into ``bar`` and
specify appropriate options, for example like this::
python /path/to/powerline/bindings/bar/powerline-bar.py | bar
to run with i3, simply ``exec`` this in i3 config file::
exec python /path/to/powerline/bindings/bar/powerline-bar.py --i3 | bar
See the `bar documentation <https://github.com/LemonBoy/bar>`_ for more
information and options.
I3 bar I3 bar
====== ======
.. note:: .. note::
Until the patch is done in i3 a custom ``i3bar`` build called ``i3bgbar`` is As the patch to include background-colors in i3bar is likely not to be
needed. The source is available `in S0lll0s/i3bgbar github repository merged, it is recommended to instead run ``bar`` (see above). The source for
i3bgbar is however still available `here
<https://github.com/S0lll0s/i3bgbar>`_. <https://github.com/S0lll0s/i3bgbar>`_.
Add the following to :file:`~/.i3/config`:: Add the following to :file:`~/.i3/config`::

View File

@ -0,0 +1,52 @@
#!/usr/bin/env python
# vim:fileencoding=utf-8:noet
from __future__ import (unicode_literals, division, absolute_import, print_function)
import sys
import time
from threading import Lock
from argparse import ArgumentParser
from powerline import Powerline
from powerline.lib.monotonic import monotonic
from powerline.lib.encoding import get_unicode_writer
class BarPowerline(Powerline):
get_encoding = staticmethod(lambda: 'utf-8')
def init(self):
super(BarPowerline, self).init(ext='wm', renderer_module='bar')
def render(event=None, data=None, sub=None):
global lock
with lock:
write(powerline.render())
write('\n')
sys.stdout.flush()
if __name__ == '__main__':
parser = ArgumentParser(description='Powerline BAR bindings.')
parser.add_argument(
'--i3', action='store_true',
help='Subscribe for i3 events.'
)
args = parser.parse_args()
powerline = BarPowerline()
interval = 0.5
lock = Lock()
write = get_unicode_writer(encoding='utf-8')
if args.i3:
import i3
sub = i3.Subscription(render, 'workspace')
while True:
start_time = monotonic()
render()
time.sleep(max(interval - (monotonic() - start_time), 0.1))

View File

@ -76,7 +76,6 @@ function powerline-setup
" "
_powerline_set_columns _powerline_set_columns
end end
_powerline_bind_mode
_powerline_set_default_mode _powerline_set_default_mode
_powerline_update _powerline_update
end end

View File

@ -0,0 +1,183 @@
# vim:fileencoding=utf-8:noet
from __future__ import (unicode_literals, division, absolute_import, print_function)
import sys
import pdb
from powerline.pdb import PDBPowerline
from powerline.lib.encoding import get_preferred_output_encoding
from powerline.lib.unicode import unicode
if sys.version_info < (3,):
# XXX The below classes make code compatible with PDBpp which uses pyrepl
# which does not expect unicode or something above ASCII. They are
# completely not needed if pdbpp is not used, but thats not always the
# case.
class PowerlineRenderBytesResult(bytes):
def __new__(cls, s, encoding=None):
encoding = encoding or s.encoding
if isinstance(s, PowerlineRenderResult):
return s.encode(encoding)
self = bytes.__new__(cls, s.encode(encoding) if isinstance(s, unicode) else s)
self.encoding = encoding
return self
for meth in (
'__contains__',
'partition', 'rpartition',
'split', 'rsplit',
'count', 'join',
):
exec((
'def {0}(self, *args):\n'
' if any((isinstance(arg, unicode) for arg in args)):\n'
' return self.__unicode__().{0}(*args)\n'
' else:\n'
' return bytes.{0}(self, *args)'
).format(meth))
for meth in (
'find', 'rfind',
'index', 'rindex',
):
exec((
'def {0}(self, *args):\n'
' if any((isinstance(arg, unicode) for arg in args)):\n'
' args = [arg.encode(self.encoding) if isinstance(arg, unicode) else arg for arg in args]\n'
' return bytes.{0}(self, *args)'
).format(meth))
def __len__(self):
return len(self.decode(self.encoding))
def __getitem__(self, *args):
return PowerlineRenderBytesResult(bytes.__getitem__(self, *args), encoding=self.encoding)
def __getslice__(self, *args):
return PowerlineRenderBytesResult(bytes.__getslice__(self, *args), encoding=self.encoding)
@staticmethod
def add(encoding, *args):
if any((isinstance(arg, unicode) for arg in args)):
return PowerlineRenderResult(''.join((
arg
if isinstance(arg, unicode)
else arg.decode(encoding)
for arg in args
)), encoding)
else:
return PowerlineRenderBytesResult(b''.join(args), encoding=encoding)
def __add__(self, other):
return self.add(self.encoding, self, other)
def __radd__(self, other):
return self.add(self.encoding, other, self)
def __unicode__(self):
return PowerlineRenderResult(self)
class PowerlineRenderResult(unicode):
def __new__(cls, s, encoding=None):
encoding = (
encoding
or getattr(s, 'encoding', None)
or get_preferred_output_encoding()
)
if isinstance(s, unicode):
self = unicode.__new__(cls, s)
else:
self = unicode.__new__(cls, s, encoding, 'replace')
self.encoding = encoding
return self
def __str__(self):
return PowerlineRenderBytesResult(self)
def __getitem__(self, *args):
return PowerlineRenderResult(unicode.__getitem__(self, *args))
def __getslice__(self, *args):
return PowerlineRenderResult(unicode.__getslice__(self, *args))
@staticmethod
def add(encoding, *args):
return PowerlineRenderResult(''.join((
arg
if isinstance(arg, unicode)
else arg.decode(encoding)
for arg in args
)), encoding)
def __add__(self, other):
return self.add(self.encoding, self, other)
def __radd__(self, other):
return self.add(self.encoding, other, self)
def encode(self, *args, **kwargs):
return PowerlineRenderBytesResult(unicode.encode(self, *args, **kwargs), args[0])
else:
PowerlineRenderResult = str
def use_powerline_prompt(cls):
'''Decorator that installs powerline prompt to the class
:param pdb.Pdb cls:
Class that should be decorated.
:return:
``cls`` argument or a class derived from it. Latter is used to turn
old-style classes into new-style classes.
'''
@property
def prompt(self):
try:
powerline = self.powerline
except AttributeError:
powerline = PDBPowerline()
powerline.setup(self)
self.powerline = powerline
return PowerlineRenderResult(powerline.render(side='left'))
@prompt.setter
def prompt(self, _):
pass
@prompt.deleter
def prompt(self):
pass
if not hasattr(cls, '__class__'):
# Old-style class: make it new-style or @property will not work.
old_cls = cls
class cls(cls, object):
__module__ = cls.__module__
__doc__ = cls.__doc__
cls.__name__ = old_cls.__name__
cls.prompt = prompt
return cls
def main():
'''Run module as a script
Uses :py:func:`pdb.main` function directly, but prior to that it mocks
:py:class:`pdb.Pdb` class with powerline-specific class instance.
'''
orig_pdb = pdb.Pdb
@use_powerline_prompt
class Pdb(pdb.Pdb, object):
def __init__(self):
orig_pdb.__init__(self)
pdb.Pdb = Pdb
return pdb.main()

View File

@ -0,0 +1,9 @@
#!/usr/bin/env python
# vim:fileencoding=utf-8:noet
from __future__ import (unicode_literals, division, absolute_import, print_function)
from powerline.bindings.pdb import main
if __name__ == '__main__':
main()

View File

@ -15,7 +15,7 @@ fn _powerline_continuation_prompt {
_powerline_prompt --renderer-arg 'local_theme=continuation' $* _powerline_prompt --renderer-arg 'local_theme=continuation' $*
} }
fn _powerline_prompt { fn _powerline_prompt {
$POWERLINE_COMMAND $POWERLINE_COMMAND_ARGS shell aboveleft -r.rcsh --last-pipe-status $^_POWERLINE_STATUS --last-exit-code $_POWERLINE_STATUS($#_POWERLINE_STATUS) --jobnum $_POWERLINE_JOBNUM --renderer-arg 'client_id='$pid $* $POWERLINE_COMMAND $POWERLINE_COMMAND_ARGS shell aboveleft -r.readline --last-pipe-status $^_POWERLINE_STATUS --last-exit-code $_POWERLINE_STATUS($#_POWERLINE_STATUS) --jobnum $_POWERLINE_JOBNUM --renderer-arg 'client_id='$pid $*
} }
fn _powerline_set_prompt { fn _powerline_set_prompt {
_POWERLINE_STATUS = ( $status ) _POWERLINE_STATUS = ( $status )

View File

@ -1,2 +1,2 @@
if-shell 'test -z "$POWERLINE_CONFIG_COMMAND"' 'set-environment -g POWERLINE_CONFIG_COMMAND powerline-config; run-shell "env \"\$POWERLINE_CONFIG_COMMAND\" tmux setup"' 'run-shell "env \"\$POWERLINE_CONFIG_COMMAND\" tmux setup"' if-shell 'env "$POWERLINE_CONFIG_COMMAND" tmux setup' '' 'run-shell "powerline-config tmux setup"'
# vim: ft=tmux # vim: ft=tmux

View File

@ -101,7 +101,20 @@ class Environment(object):
return False return False
environ = getattr(zsh, 'environ', Environment()) if hasattr(getattr(zsh, 'environ', None), '__contains__'):
environ = zsh.environ
else:
environ = Environment()
if hasattr(zsh, 'expand') and zsh.expand('${:-}') == '':
zsh_expand = zsh.expand
else:
def zsh_expand(s):
zsh.eval('_POWERLINE_REPLY="' + s + '"')
ret = zsh.getvalue('_POWERLINE_REPLY')
zsh.setvalue('_POWERLINE_REPLY', None)
return ret
class ZshPowerline(ShellPowerline): class ZshPowerline(ShellPowerline):
@ -135,8 +148,8 @@ class Prompt(object):
self.theme = theme self.theme = theme
def __str__(self): def __str__(self):
zsh.eval('_POWERLINE_PARSER_STATE="${(%):-%_}"') parser_state = u(zsh_expand('${(%):-%_}'))
zsh.eval('_POWERLINE_SHORTENED_PATH="${(%):-%~}"') shortened_path = u(zsh_expand('${(%):-%~}'))
try: try:
mode = u(zsh.getvalue('_POWERLINE_MODE')) mode = u(zsh.getvalue('_POWERLINE_MODE'))
except IndexError: except IndexError:
@ -150,13 +163,11 @@ class Prompt(object):
'environ': environ, 'environ': environ,
'client_id': 1, 'client_id': 1,
'local_theme': self.theme, 'local_theme': self.theme,
'parser_state': zsh.getvalue('_POWERLINE_PARSER_STATE'), 'parser_state': parser_state,
'shortened_path': zsh.getvalue('_POWERLINE_SHORTENED_PATH'), 'shortened_path': shortened_path,
'mode': mode, 'mode': mode,
'default_mode': default_mode, 'default_mode': default_mode,
} }
zsh.setvalue('_POWERLINE_PARSER_STATE', None)
zsh.setvalue('_POWERLINE_SHORTENED_PATH', None)
try: try:
zle_rprompt_indent = zsh.getvalue('ZLE_RPROMPT_INDENT') zle_rprompt_indent = zsh.getvalue('ZLE_RPROMPT_INDENT')
except IndexError: except IndexError:
@ -194,7 +205,7 @@ def set_prompt(powerline, psvar, side, theme, above=False):
savedps = None savedps = None
zpyvar = 'ZPYTHON_POWERLINE_' + psvar zpyvar = 'ZPYTHON_POWERLINE_' + psvar
prompt = Prompt(powerline, side, theme, psvar, savedps, above) prompt = Prompt(powerline, side, theme, psvar, savedps, above)
zsh.eval('unset ' + zpyvar) zsh.setvalue(zpyvar, None)
zsh.set_special_string(zpyvar, prompt) zsh.set_special_string(zpyvar, prompt)
zsh.setvalue(psvar, '${' + zpyvar + '}') zsh.setvalue(psvar, '${' + zpyvar + '}')
return ref(prompt) return ref(prompt)

View File

@ -150,7 +150,7 @@ def get_argparser(ArgumentParser=argparse.ArgumentParser):
return parser return parser
def write_output(args, powerline, segment_info, write, encoding): def write_output(args, powerline, segment_info, write):
if args.renderer_arg: if args.renderer_arg:
segment_info.update(args.renderer_arg) segment_info.update(args.renderer_arg)
if args.side.startswith('above'): if args.side.startswith('above'):
@ -159,8 +159,7 @@ def write_output(args, powerline, segment_info, write, encoding):
segment_info=segment_info, segment_info=segment_info,
mode=segment_info.get('mode', None), mode=segment_info.get('mode', None),
): ):
write(line.encode(encoding, 'replace')) write(line + '\n')
write(b'\n')
args.side = args.side[len('above'):] args.side = args.side[len('above'):]
if args.side: if args.side:
@ -170,4 +169,4 @@ def write_output(args, powerline, segment_info, write, encoding):
segment_info=segment_info, segment_info=segment_info,
mode=segment_info.get('mode', None), mode=segment_info.get('mode', None),
) )
write(rendered.encode(encoding, 'replace')) write(rendered)

View File

@ -1,13 +1,19 @@
{ {
"name": "Default", "name": "Default",
"groups": { "groups": {
"information:additional": { "fg": "gray9", "bg": "gray4", "attrs": [] },
"information:regular": { "fg": "gray10", "bg": "gray4", "attrs": ["bold"] },
"information:highlighted": { "fg": "white", "bg": "gray4", "attrs": [] },
"information:priority": { "fg": "brightyellow", "bg": "mediumorange", "attrs": [] },
"critical:failure": { "fg": "white", "bg": "darkestred", "attrs": [] },
"critical:success": { "fg": "white", "bg": "darkestgreen", "attrs": [] },
"background": { "fg": "white", "bg": "gray0", "attrs": [] }, "background": { "fg": "white", "bg": "gray0", "attrs": [] },
"background:divider": { "fg": "gray5", "bg": "gray0", "attrs": [] }, "background:divider": { "fg": "gray5", "bg": "gray0", "attrs": [] },
"session": { "fg": "black", "bg": "gray10", "attrs": ["bold"] }, "session": { "fg": "black", "bg": "gray10", "attrs": ["bold"] },
"date": { "fg": "gray8", "bg": "gray2", "attrs": [] }, "date": { "fg": "gray8", "bg": "gray2", "attrs": [] },
"time": { "fg": "gray10", "bg": "gray2", "attrs": ["bold"] }, "time": { "fg": "gray10", "bg": "gray2", "attrs": ["bold"] },
"time:divider": { "fg": "gray5", "bg": "gray2", "attrs": [] }, "time:divider": { "fg": "gray5", "bg": "gray2", "attrs": [] },
"email_alert": { "fg": "white", "bg": "brightred", "attrs": ["bold"] }, "email_alert": "warning:regular",
"email_alert_gradient": { "fg": "white", "bg": "yellow_orange_red", "attrs": ["bold"] }, "email_alert_gradient": { "fg": "white", "bg": "yellow_orange_red", "attrs": ["bold"] },
"hostname": { "fg": "black", "bg": "gray10", "attrs": ["bold"] }, "hostname": { "fg": "black", "bg": "gray10", "attrs": ["bold"] },
"weather": { "fg": "gray8", "bg": "gray0", "attrs": [] }, "weather": { "fg": "gray8", "bg": "gray0", "attrs": [] },
@ -31,13 +37,12 @@
"battery_empty": { "fg": "white", "bg": "gray0", "attrs": [] }, "battery_empty": { "fg": "white", "bg": "gray0", "attrs": [] },
"player": { "fg": "gray10", "bg": "black", "attrs": [] }, "player": { "fg": "gray10", "bg": "black", "attrs": [] },
"user": { "fg": "white", "bg": "darkblue", "attrs": ["bold"] }, "user": { "fg": "white", "bg": "darkblue", "attrs": ["bold"] },
"superuser": { "fg": "white", "bg": "brightred", "attrs": ["bold"] },
"branch": { "fg": "gray9", "bg": "gray2", "attrs": [] }, "branch": { "fg": "gray9", "bg": "gray2", "attrs": [] },
"branch_dirty": { "fg": "brightyellow", "bg": "gray2", "attrs": [] }, "branch_dirty": { "fg": "brightyellow", "bg": "gray2", "attrs": [] },
"branch_clean": { "fg": "gray9", "bg": "gray2", "attrs": [] }, "branch_clean": { "fg": "gray9", "bg": "gray2", "attrs": [] },
"branch:divider": { "fg": "gray7", "bg": "gray2", "attrs": [] }, "branch:divider": { "fg": "gray7", "bg": "gray2", "attrs": [] },
"cwd": { "fg": "gray9", "bg": "gray4", "attrs": [] }, "cwd": "information:additional",
"cwd:current_folder": { "fg": "gray10", "bg": "gray4", "attrs": ["bold"] }, "cwd:current_folder": "information:regular",
"cwd:divider": { "fg": "gray7", "bg": "gray4", "attrs": [] }, "cwd:divider": { "fg": "gray7", "bg": "gray4", "attrs": [] },
"virtualenv": { "fg": "white", "bg": "darkcyan", "attrs": [] }, "virtualenv": { "fg": "white", "bg": "darkcyan", "attrs": [] },
"attached_clients": { "fg": "gray8", "bg": "gray0", "attrs": [] } "attached_clients": { "fg": "gray8", "bg": "gray0", "attrs": [] }

View File

@ -0,0 +1,6 @@
{
"groups": {
"prompt": "information:additional",
"prompt_count": "information:highlighted"
}
}

View File

@ -1,7 +0,0 @@
{
"name": "Default color scheme for IPython prompt",
"groups": {
"prompt": { "fg": "gray9", "bg": "gray4", "attrs": [] },
"prompt_count": { "fg": "white", "bg": "gray4", "attrs": [] }
}
}

View File

@ -0,0 +1,8 @@
{
"groups": {
"current_code_name": "information:additional",
"current_context": "current_code_name",
"current_line": "information:regular",
"current_file": "information:regular"
}
}

View File

@ -0,0 +1,5 @@
{
"groups": {
"stack_depth": { "fg": "gray1", "bg": "gray10", "attrs": ["bold"] }
}
}

View File

@ -0,0 +1,5 @@
{
"groups": {
"stack_depth": { "fg": "solarized:base03", "bg": "solarized:base2", "attrs": ["bold"] }
}
}

View File

@ -1,6 +1,10 @@
{ {
"groups": { "groups": {
"continuation": "cwd", "continuation": "cwd",
"continuation:current": "cwd:current_folder" "continuation:current": "cwd:current_folder",
"exit_fail": "critical:failure",
"exit_success": "critical:success",
"jobnum": "information:priority",
"superuser": "warning:regular"
} }
} }

View File

@ -2,9 +2,6 @@
"name": "Default color scheme for shell prompts", "name": "Default color scheme for shell prompts",
"groups": { "groups": {
"hostname": { "fg": "brightyellow", "bg": "mediumorange", "attrs": [] }, "hostname": { "fg": "brightyellow", "bg": "mediumorange", "attrs": [] },
"jobnum": { "fg": "brightyellow", "bg": "mediumorange", "attrs": [] },
"exit_fail": { "fg": "white", "bg": "darkestred", "attrs": [] },
"exit_success": { "fg": "white", "bg": "darkestgreen", "attrs": [] },
"environment": { "fg": "white", "bg": "darkestgreen", "attrs": [] }, "environment": { "fg": "white", "bg": "darkestgreen", "attrs": [] },
"mode": { "fg": "darkestgreen", "bg": "brightgreen", "attrs": ["bold"] }, "mode": { "fg": "darkestgreen", "bg": "brightgreen", "attrs": ["bold"] },
"attached_clients": { "fg": "white", "bg": "darkestgreen", "attrs": [] } "attached_clients": { "fg": "white", "bg": "darkestgreen", "attrs": [] }

View File

@ -1,9 +1,6 @@
{ {
"name": "Solarized dark for shell", "name": "Solarized dark for shell",
"groups": { "groups": {
"jobnum": { "fg": "solarized:base3", "bg": "solarized:base01", "attrs": [] },
"exit_fail": { "fg": "solarized:base3", "bg": "solarized:red", "attrs": [] },
"exit_success": { "fg": "solarized:base3", "bg": "solarized:green", "attrs": [] },
"mode": { "fg": "solarized:base3", "bg": "solarized:green", "attrs": ["bold"] } "mode": { "fg": "solarized:base3", "bg": "solarized:green", "attrs": ["bold"] }
}, },
"mode_translations": { "mode_translations": {

View File

@ -1,18 +1,34 @@
{ {
"name": "Solarized dark", "name": "Solarized dark",
"groups": { "groups": {
"information:additional": { "fg": "solarized:base2", "bg": "solarized:base01", "attrs": [] },
"information:regular": { "fg": "solarized:base3", "bg": "solarized:base01", "attrs": ["bold"] },
"information:highlighted": { "fg": "solarized:base3", "bg": "solarized:base01", "attrs": ["bold"]},
"information:priority": { "fg": "solarized:base3", "bg": "solarized:yellow", "attrs": [] },
"warning:regular": { "fg": "solarized:base3", "bg": "solarized:red", "attrs": [] },
"critical:failure": { "fg": "solarized:base3", "bg": "solarized:red", "attrs": [] },
"critical:success": { "fg": "solarized:base3", "bg": "solarized:green", "attrs": [] },
"background": { "fg": "solarized:base3", "bg": "solarized:base02", "attrs": [] }, "background": { "fg": "solarized:base3", "bg": "solarized:base02", "attrs": [] },
"background:divider": { "fg": "solarized:base1", "bg": "solarized:base02", "attrs": [] },
"user": { "fg": "solarized:base3", "bg": "solarized:blue", "attrs": ["bold"] }, "user": { "fg": "solarized:base3", "bg": "solarized:blue", "attrs": ["bold"] },
"superuser": { "fg": "solarized:base3", "bg": "solarized:red", "attrs": ["bold"] },
"virtualenv": { "fg": "solarized:base3", "bg": "solarized:green", "attrs": [] }, "virtualenv": { "fg": "solarized:base3", "bg": "solarized:green", "attrs": [] },
"branch": { "fg": "solarized:base1", "bg": "solarized:base02", "attrs": [] }, "branch": { "fg": "solarized:base1", "bg": "solarized:base02", "attrs": [] },
"branch_dirty": { "fg": "solarized:yellow", "bg": "solarized:base02", "attrs": [] }, "branch_dirty": { "fg": "solarized:yellow", "bg": "solarized:base02", "attrs": [] },
"branch_clean": { "fg": "solarized:base1", "bg": "solarized:base02", "attrs": [] }, "branch_clean": { "fg": "solarized:base1", "bg": "solarized:base02", "attrs": [] },
"cwd": { "fg": "solarized:base2", "bg": "solarized:base01", "attrs": [] }, "email_alert_gradient": { "fg": "solarized:base3", "bg": "yellow_orange_red", "attrs": [] },
"cwd:current_folder": { "fg": "solarized:base3", "bg": "solarized:base01", "attrs": ["bold"] }, "email_alert": "warning:regular",
"cwd": "information:additional",
"cwd:current_folder": "information:regular",
"cwd:divider": { "fg": "solarized:base1", "bg": "solarized:base01", "attrs": [] }, "cwd:divider": { "fg": "solarized:base1", "bg": "solarized:base01", "attrs": [] },
"hostname": { "fg": "solarized:base3", "bg": "solarized:base01", "attrs": [] }, "hostname": { "fg": "solarized:base3", "bg": "solarized:base01", "attrs": [] },
"environment": { "fg": "solarized:base3", "bg": "solarized:green", "attrs": [] }, "environment": { "fg": "solarized:base3", "bg": "solarized:green", "attrs": [] },
"attached_clients": { "fg": "solarized:base3", "bg": "solarized:green", "attrs": [] } "attached_clients": { "fg": "solarized:base3", "bg": "solarized:green", "attrs": [] },
"date": { "fg": "solarized:base1", "bg": "solarized:base02", "attrs": [] },
"time": { "fg": "solarized:base1", "bg": "solarized:base02", "attrs": ["bold"] },
"time:divider": { "fg": "solarized:base1", "bg": "solarized:base02", "attrs": [] },
"system_load": { "fg": "solarized:base1", "bg": "solarized:base03", "attrs": [] },
"weather_temp_gradient": { "fg": "blue_red", "bg": "solarized:base03", "attrs": [] },
"weather": { "fg": "solarized:base1", "bg": "solarized:base03", "attrs": [] },
"uptime": { "fg": "solarized:base1", "bg": "solarized:base03", "attrs": [] }
} }
} }

View File

@ -12,6 +12,10 @@
"in2": "in2" "in2": "in2"
} }
}, },
"pdb": {
"colorscheme": "default",
"theme": "default"
},
"shell": { "shell": {
"colorscheme": "default", "colorscheme": "default",
"theme": "default", "theme": "default",

View File

@ -0,0 +1,27 @@
{
"default_module": "powerline.segments.pdb",
"segments": {
"left": [
{
"function": "stack_depth"
},
{
"type": "segment_list",
"function": "powerline.listers.pdb.frame_lister",
"segments": [
{
"function": "current_file",
"after": ":"
},
{
"function": "current_line",
"after": " "
},
{
"function": "current_code_name"
}
]
}
]
}
}

View File

@ -86,3 +86,28 @@ def get_preferred_environment_encoding():
locale.getpreferredencoding() locale.getpreferredencoding()
or 'utf-8' or 'utf-8'
) )
def get_unicode_writer(stream=sys.stdout, encoding=None, errors='replace'):
'''Get function which will write unicode string to the given stream
Writing is done using encoding returned by
:py:func:`get_preferred_output_encoding`.
:param file stream:
Stream to write to. Default value is :py:attr:`sys.stdout`.
:param str encoding:
Determines which encoding to use. If this argument is specified then
:py:func:`get_preferred_output_encoding` is not used.
:param str errors:
Determines what to do with characters which cannot be encoded. See
``errors`` argument of :py:func:`codecs.encode`.
:return: Callable which writes unicode string to the given stream using
the preferred output encoding.
'''
encoding = encoding or get_preferred_output_encoding()
if sys.version_info < (3,) or not hasattr(stream, 'buffer'):
return lambda s: stream.write(s.encode(encoding, errors))
else:
return lambda s: stream.buffer.write(s.encode(encoding, errors))

View File

@ -233,6 +233,7 @@ segment_spec = Spec(
segments=sub_segments_spec, segments=sub_segments_spec,
).func(check_full_segment_data) ).func(check_full_segment_data)
sub_segments_spec.optional().list(segment_spec) sub_segments_spec.optional().list(segment_spec)
del sub_segments_spec
segments_spec = Spec().optional().list(segment_spec).copy segments_spec = Spec().optional().list(segment_spec).copy
segdict_spec = Spec( segdict_spec = Spec(
left=segments_spec().context_message('Error while loading segments from left side (key {key})'), left=segments_spec().context_message('Error while loading segments from left side (key {key})'),
@ -546,6 +547,8 @@ def check(paths=None, debug=False, echoerr=echoerr, require_ext=None):
econfigs.get('__main__'), econfigs.get('__main__'),
ecconfigs, ecconfigs,
) )
if not (mconfigs[0] or mconfigs[2]):
continue
config = None config = None
for mconfig in mconfigs: for mconfig in mconfigs:
if not mconfig: if not mconfig:
@ -554,7 +557,7 @@ def check(paths=None, debug=False, echoerr=echoerr, require_ext=None):
config = mergedicts_copy(config, mconfig) config = mergedicts_copy(config, mconfig)
else: else:
config = mconfig config = mconfig
colorscheme_configs[colorscheme] = config colorscheme_configs[ext][colorscheme] = config
theme_configs = dict2(loaded_configs['themes']) theme_configs = dict2(loaded_configs['themes'])
top_theme_configs = dict(loaded_configs['top_themes']) top_theme_configs = dict(loaded_configs['top_themes'])

View File

@ -499,26 +499,27 @@ def check_segment_function(function_name, data, context, echoerr):
return True, False, False return True, False, False
def hl_exists(hl_group, data, context, echoerr, allow_gradients=False): def hl_group_in_colorscheme(hl_group, cconfig, allow_gradients, data, context, echoerr):
havemarks(hl_group) havemarks(hl_group, cconfig)
ext = data['ext']
if ext not in data['colorscheme_configs']:
# No colorschemes. Error was already reported, no need to report it
# twice
return []
r = []
for colorscheme, cconfig in data['colorscheme_configs'][ext].items():
if hl_group not in cconfig.get('groups', {}): if hl_group not in cconfig.get('groups', {}):
r.append(colorscheme) return False
elif not allow_gradients or allow_gradients == 'force': elif not allow_gradients or allow_gradients == 'force':
group_config = cconfig['groups'][hl_group] group_config = cconfig['groups'][hl_group]
while isinstance(group_config, unicode):
try:
group_config = cconfig['groups'][group_config]
except KeyError:
# No such group. Error was already reported when checking
# colorschemes.
return True
havemarks(group_config) havemarks(group_config)
hadgradient = False hadgradient = False
for ckey in ('fg', 'bg'): for ckey in ('fg', 'bg'):
color = group_config.get(ckey) color = group_config.get(ckey)
if not color: if not color:
# No color. Error was already reported. # No color. Error was already reported when checking
continue # colorschemes.
return True
havemarks(color) havemarks(color)
# Gradients are only allowed for function segments. Note that # Gradients are only allowed for function segments. Note that
# whether *either* color or gradient exists should have been # whether *either* color or gradient exists should have been
@ -535,8 +536,7 @@ def hl_exists(hl_group, data, context, echoerr, allow_gradients=False):
problem='group {0} is using gradient {1} instead of a color'.format(hl_group, color), problem='group {0} is using gradient {1} instead of a color'.format(hl_group, color),
problem_mark=color.mark problem_mark=color.mark
) )
r.append(colorscheme) return False
continue
if allow_gradients == 'force' and not hadgradient: if allow_gradients == 'force' and not hadgradient:
echoerr( echoerr(
context='Error while checking highlight group in theme (key {key})'.format( context='Error while checking highlight group in theme (key {key})'.format(
@ -545,7 +545,26 @@ def hl_exists(hl_group, data, context, echoerr, allow_gradients=False):
problem='group {0} should have at least one gradient color, but it has no'.format(hl_group), problem='group {0} should have at least one gradient color, but it has no'.format(hl_group),
problem_mark=group_config.mark problem_mark=group_config.mark
) )
return False
return True
def hl_exists(hl_group, data, context, echoerr, allow_gradients=False):
havemarks(hl_group)
ext = data['ext']
if ext not in data['colorscheme_configs']:
# No colorschemes. Error was already reported, no need to report it
# twice
return []
r = []
found = False
for colorscheme, cconfig in data['colorscheme_configs'][ext].items():
if hl_group_in_colorscheme(hl_group, cconfig, allow_gradients, data, context, echoerr):
found = True
else:
r.append(colorscheme) r.append(colorscheme)
if not found:
pass
return r return r

37
powerline/listers/pdb.py Normal file
View File

@ -0,0 +1,37 @@
# vim:fileencoding=utf-8:noet
from __future__ import (unicode_literals, division, absolute_import, print_function)
from powerline.theme import requires_segment_info
@requires_segment_info
def frame_lister(pl, segment_info, full_stack=False, maxframes=3):
'''List all frames in segment_info format
:param bool full_stack:
If true, then all frames in the stack are listed. Normally N first
frames are discarded where N is a number of frames present at the first
invocation of the prompt minus one.
:param int maxframes:
Maximum number of frames to display.
'''
if full_stack:
initial_stack_length = 0
frames = segment_info['pdb'].stack
else:
initial_stack_length = segment_info['initial_stack_length']
frames = segment_info['pdb'].stack[initial_stack_length:]
if len(frames) > maxframes:
frames = frames[-maxframes:]
return (
(
{
'curframe': frame[0],
'initial_stack_length': initial_stack_length,
},
{}
)
for frame in frames
)

48
powerline/pdb.py Normal file
View File

@ -0,0 +1,48 @@
# vim:fileencoding=utf-8:noet
from __future__ import (unicode_literals, division, absolute_import, print_function)
import sys
import platform
import os
from powerline import Powerline
from powerline.lib.overrides import parse_override_var
from powerline.lib.dict import mergeargs, mergedicts
class PDBPowerline(Powerline):
'''PDB-specific powerline bindings
'''
def init(self, **kwargs):
return super(PDBPowerline, self).init(
ext='pdb',
renderer_module='pdb',
**kwargs
)
def do_setup(self, pdb):
self.update_renderer()
self.renderer.set_pdb(pdb)
def load_main_config(self):
r = super(PDBPowerline, self).load_main_config()
config_overrides = os.environ.get('POWERLINE_CONFIG_OVERRIDES')
if config_overrides:
mergedicts(r, mergeargs(parse_override_var(config_overrides)))
return r
def load_theme_config(self, name):
r = super(PDBPowerline, self).load_theme_config(name)
theme_overrides = os.environ.get('POWERLINE_THEME_OVERRIDES')
if theme_overrides:
theme_overrides_dict = mergeargs(parse_override_var(theme_overrides))
if name in theme_overrides_dict:
mergedicts(r, theme_overrides_dict[name])
return r
def get_config_paths(self):
paths = [path for path in os.environ.get('POWERLINE_CONFIG_PATHS', '').split(':') if path]
return paths or super(PDBPowerline, self).get_config_paths()
if sys.version_info < (3,) and platform.python_implementation() == 'PyPy':
get_encoding = staticmethod(lambda: 'ascii')

View File

@ -124,8 +124,10 @@ class Renderer(object):
'getcwd': getattr(os, 'getcwdu', os.getcwd), 'getcwd': getattr(os, 'getcwdu', os.getcwd),
'home': os.environ.get('HOME'), 'home': os.environ.get('HOME'),
} }
'''Basic segment info. Is merged with local segment information by '''Basic segment info
``.get_segment_info()`` method. Keys:
Is merged with local segment information by :py:meth:`get_segment_info`
method. Keys:
``environ`` ``environ``
Object containing environment variables. Must define at least the Object containing environment variables. Must define at least the
@ -279,9 +281,10 @@ class Renderer(object):
string_width)``. Returns a three-tuple if ``output_raw`` is also string_width)``. Returns a three-tuple if ``output_raw`` is also
``True``: ``(colored_string, colorless_string, string_width)``. ``True``: ``(colored_string, colorless_string, string_width)``.
:param dict segment_info: :param dict segment_info:
Segment information. See also ``.get_segment_info()`` method. Segment information. See also :py:meth:`get_segment_info` method.
:param matcher_info: :param matcher_info:
Matcher information. Is processed in ``.get_theme()`` method. Matcher information. Is processed in :py:meth:`get_segment_info`
method.
''' '''
theme = self.get_theme(matcher_info) theme = self.get_theme(matcher_info)
return self.do_render( return self.do_render(
@ -504,7 +507,7 @@ class Renderer(object):
def hl(self, contents, fg=None, bg=None, attrs=None): def hl(self, contents, fg=None, bg=None, attrs=None):
'''Output highlighted chunk. '''Output highlighted chunk.
This implementation just outputs ``.hlstyle()`` joined with This implementation just outputs :py:meth:`hlstyle` joined with
``contents``. ``contents``.
''' '''
return self.hlstyle(fg, bg, attrs) + (contents or '') return self.hlstyle(fg, bg, attrs) + (contents or '')

View File

@ -0,0 +1,45 @@
# vim:fileencoding=utf-8:noet
from __future__ import (unicode_literals, division, absolute_import, print_function)
from powerline.renderer import Renderer
from powerline.colorscheme import ATTR_UNDERLINE
class BarRenderer(Renderer):
'''bar (bar ain't recursive) renderer
See documentation of `bar <https://github.com/LemonBoy/bar>`_ and :ref:`the usage instructions <bar-usage>`
'''
character_translations = Renderer.character_translations.copy()
character_translations[ord('%')] = '%%'
@staticmethod
def hlstyle(*args, **kwargs):
# We dont need to explicitly reset attributes, so skip those calls
return ''
def hl(self, contents, fg=None, bg=None, attrs=None):
text = ''
if fg is not None:
if fg is not False and fg[1] is not False:
text += '%{{F#ff{0:06x}}}'.format(fg[1])
if bg is not None:
if bg is not False and bg[1] is not False:
text += '%{{B#ff{0:06x}}}'.format(bg[1])
if attrs & ATTR_UNDERLINE:
text += '%{+u}'
return text + contents + '%{F-B--u}'
def render(self):
return '%{{l}}{0}%{{r}}{1}'.format(
super(BarRenderer, self).render(side='left'),
super(BarRenderer, self).render(side='right'),
)
renderer = BarRenderer

View File

@ -2,6 +2,7 @@
from __future__ import (unicode_literals, division, absolute_import, print_function) from __future__ import (unicode_literals, division, absolute_import, print_function)
from powerline.renderers.shell import ShellRenderer from powerline.renderers.shell import ShellRenderer
from powerline.renderers.shell.readline import ReadlineRenderer
from powerline.theme import Theme from powerline.theme import Theme
@ -45,10 +46,9 @@ class IPythonRenderer(ShellRenderer):
) )
class IPythonPromptRenderer(IPythonRenderer): class IPythonPromptRenderer(IPythonRenderer, ReadlineRenderer):
'''Powerline ipython prompt (in and in2) renderer''' '''Powerline ipython prompt (in and in2) renderer'''
escape_hl_start = '\x01' pass
escape_hl_end = '\x02'
class IPythonNonPromptRenderer(IPythonRenderer): class IPythonNonPromptRenderer(IPythonRenderer):

View File

@ -0,0 +1,50 @@
# vim:fileencoding=utf-8:noet
from __future__ import (unicode_literals, division, absolute_import, print_function)
import sys
import platform
from powerline.renderers.shell.readline import ReadlineRenderer
from powerline.renderer import Renderer
class PDBRenderer(ReadlineRenderer):
'''PDB-specific powerline renderer
'''
pdb = None
initial_stack_length = None
def get_segment_info(self, segment_info, mode):
r = self.segment_info.copy()
r['pdb'] = self.pdb
r['initial_stack_length'] = self.initial_stack_length
r['curframe'] = self.pdb.curframe
return r
def set_pdb(self, pdb):
'''Record currently used :py:class:`pdb.Pdb` instance
Must be called before first calling :py:meth:`render` method.
:param pdb.Pdb pdb:
Used :py:class:`pdb.Pdb` instance. This instance will later be used
by :py:meth:`get_segment_info` for patching :ref:`segment_info
<dev-segments-info>` dictionary.
'''
self.pdb = pdb
def render(self, **kwargs):
if self.initial_stack_length is None:
self.initial_stack_length = len(self.pdb.stack) - 1
return Renderer.render(self, **kwargs)
if sys.version_info < (3,) and platform.python_implementation() == 'PyPy':
def do_render(self, **kwargs):
# Make sure that only ASCII characters survive
ret = super(PDBRenderer, self).do_render(**kwargs)
ret = ret.encode('ascii', 'replace')
ret = ret.decode('ascii')
return ret
renderer = PDBRenderer

View File

@ -1,12 +1,7 @@
# vim:fileencoding=utf-8:noet # vim:fileencoding=utf-8:noet
from __future__ import (unicode_literals, division, absolute_import, print_function) from __future__ import (unicode_literals, division, absolute_import, print_function)
from powerline.renderers.shell import ShellRenderer from powerline.renderers.shell.readline import ReadlineRenderer
class RcshRenderer(ShellRenderer): renderer = ReadlineRenderer
'''Powerline rcsh prompt renderer'''
escape_hl_start = '\x01'
escape_hl_end = '\x02'
renderer = RcshRenderer

View File

@ -0,0 +1,14 @@
# vim:fileencoding=utf-8:noet
from __future__ import (unicode_literals, division, absolute_import, print_function)
from powerline.renderers.shell import ShellRenderer
class ReadlineRenderer(ShellRenderer):
'''Renderer useful for some applications that use readline
'''
escape_hl_start = '\x01'
escape_hl_end = '\x02'
renderer = ReadlineRenderer

61
powerline/segments/pdb.py Normal file
View File

@ -0,0 +1,61 @@
# vim:fileencoding=utf-8:noet
from __future__ import (unicode_literals, division, absolute_import, print_function)
import os
from powerline.theme import requires_segment_info
@requires_segment_info
def current_line(pl, segment_info):
'''Displays line number that is next to be run
'''
return str(segment_info['curframe'].f_lineno)
@requires_segment_info
def current_file(pl, segment_info, basename=True):
'''Displays current file name
:param bool basename:
If true only basename is displayed.
'''
filename = segment_info['curframe'].f_code.co_filename
if basename:
filename = os.path.basename(filename)
return filename
@requires_segment_info
def current_code_name(pl, segment_info):
'''Displays name of the code object of the current frame
'''
return segment_info['curframe'].f_code.co_name
@requires_segment_info
def current_context(pl, segment_info):
'''Displays currently executed context name
This is similar to :py:func:`current_code_name`, but gives more details.
Currently it only gives module file name if code_name happens to be
``<module>``.
'''
name = segment_info['curframe'].f_code.co_name
if name == '<module>':
name = os.path.basename(segment_info['curframe'].f_code.co_filename)
return name
@requires_segment_info
def stack_depth(pl, segment_info, full_stack=False):
'''Displays current stack depth
Result is relative to the stack depth at the time prompt was first run.
:param bool full_stack:
If true then absolute depth is used.
'''
return str(len(segment_info['pdb'].stack) - (
0 if full_stack else segment_info['initial_stack_length']))

View File

@ -50,6 +50,8 @@ def finder(pl):
$command_t to add them). All Command-T finders have ``CommandT::`` module $command_t to add them). All Command-T finders have ``CommandT::`` module
prefix, but it is stripped out (actually, any ``CommandT::`` substring will prefix, but it is stripped out (actually, any ``CommandT::`` substring will
be stripped out). be stripped out).
Highlight groups used: ``commandt:finder``.
''' '''
initialize() initialize()
vim.command('ruby $powerline.commandt_set_active_finder') vim.command('ruby $powerline.commandt_set_active_finder')
@ -80,6 +82,8 @@ def path(pl):
$command_t.active_finder is required in order to omit displaying path for $command_t.active_finder is required in order to omit displaying path for
finders ``MRUBufferFinder``, ``BufferFinder``, ``TagFinder`` and finders ``MRUBufferFinder``, ``BufferFinder``, ``TagFinder`` and
``JumpFinder`` (pretty much any finder, except ``FileFinder``). ``JumpFinder`` (pretty much any finder, except ``FileFinder``).
Highlight groups used: ``commandt:path``.
''' '''
initialize() initialize()
vim.command('ruby $powerline.commandt_set_active_finder') vim.command('ruby $powerline.commandt_set_active_finder')

View File

@ -217,10 +217,6 @@ class VimPowerline(Powerline):
for args in _local_themes: for args in _local_themes:
self.add_local_theme(*args) self.add_local_theme(*args)
@staticmethod
def get_segment_info():
return {}
def reset_highlight(self): def reset_highlight(self):
try: try:
self.renderer.reset_highlight() self.renderer.reset_highlight()

View File

@ -17,7 +17,7 @@ from io import BytesIO
from powerline.shell import ShellPowerline from powerline.shell import ShellPowerline
from powerline.commands.main import finish_args, write_output from powerline.commands.main import finish_args, write_output
from powerline.lib.monotonic import monotonic from powerline.lib.monotonic import monotonic
from powerline.lib.encoding import get_preferred_output_encoding from powerline.lib.encoding import get_preferred_output_encoding, get_preferred_arguments_encoding, get_unicode_writer
from powerline.commands.main import get_argparser as get_main_argparser from powerline.commands.main import get_argparser as get_main_argparser
from powerline.commands.daemon import get_argparser as get_daemon_argparser from powerline.commands.daemon import get_argparser as get_daemon_argparser
@ -107,7 +107,7 @@ def render(args, environ, cwd):
else: else:
return 'Failed to render {0}: {1}'.format(str(key), str(e)) return 'Failed to render {0}: {1}'.format(str(key), str(e))
s = BytesIO() s = BytesIO()
write_output(args, powerline, segment_info, s.write, encoding) write_output(args, powerline, segment_info, get_unicode_writer(stream=s))
s.seek(0) s.seek(0)
return s.read() return s.read()
@ -150,10 +150,7 @@ def do_write(conn, result):
pass pass
encoding = get_preferred_output_encoding() def safe_bytes(o, encoding=get_preferred_output_encoding()):
def safe_bytes(o, encoding=encoding):
'''Return bytes instance without ever throwing an exception.''' '''Return bytes instance without ever throwing an exception.'''
try: try:
try: try:
@ -171,7 +168,7 @@ def safe_bytes(o, encoding=encoding):
return safe_bytes(str(e), encoding) return safe_bytes(str(e), encoding)
def parse_args(req): def parse_args(req, encoding=get_preferred_arguments_encoding()):
args = [x.decode(encoding) for x in req.split(b'\0') if x] args = [x.decode(encoding) for x in req.split(b'\0') if x]
numargs = int(args[0], 16) numargs = int(args[0], 16)
shell_args = parser.parse_args(args[1:numargs + 1]) shell_args = parser.parse_args(args[1:numargs + 1])

View File

@ -48,24 +48,57 @@ def parse_version(s):
return tuple(map(int, s.split('.'))) return tuple(map(int, s.split('.')))
def setup_py_filter(filter_func):
with codecs.open('.setup.py.new', 'w', encoding='utf-8') as NS:
with codecs.open('setup.py', 'r', encoding='utf-8') as OS:
for line in OS:
line = filter_func(line)
NS.write(line)
os.unlink('setup.py')
os.rename('.setup.py.new', 'setup.py')
def setup_py_develop_filter(line, version_string):
if line.startswith('\tbase_version = '):
line = '\tbase_version = \'' + version_string + '\'\n'
return line
def setup_py_master_filter(line, version_string):
if line.startswith('\tversion='):
line = '\tversion=\'' + version_string + '\',\n'
elif 'Development Status' in line:
line = '\t\t\'Development Status :: 5 - Production/Stable\',\n'
return line
def merge(version_string, rev, **kwargs): def merge(version_string, rev, **kwargs):
check_call(['git', 'checkout', rev])
temp_branch_name = 'release-' + version_string
check_call(['git', 'checkout', '-b', temp_branch_name])
setup_py_filter(lambda line: setup_py_develop_filter(line, version_string))
check_call(['git', 'add', 'setup.py'])
check_call(['git', 'commit', '-m', 'Update base version'])
check_call(['git', 'checkout', rev])
check_call(['git', 'merge', '--no-ff',
'--strategy', 'recursive',
'--strategy-option', 'theirs',
'--commit',
'-m', 'Merge branch \'{0}\' into {1}'.format(temp_branch_name, rev),
temp_branch_name])
check_call(['git', 'branch', '-d', temp_branch_name])
rev = check_output(['git', 'rev-parse', 'HEAD']).strip()
check_call(['git', 'checkout', 'master']) check_call(['git', 'checkout', 'master'])
try: try:
check_call(['git', 'merge', '--no-ff', '--no-commit', '--log', rev]) check_call(['git', 'merge', '--no-ff', '--no-commit', '--log', rev])
except CalledProcessError: except CalledProcessError:
check_call(['git', 'mergetool', '--tool', 'vimdiff2']) check_call(['git', 'mergetool', '--tool', 'vimdiff2'])
with codecs.open('.setup.py.new', 'w', encoding='utf-8') as NS: setup_py_filter(lambda line: setup_py_master_filter(line, version_string))
with codecs.open('setup.py', 'r', encoding='utf-8') as OS:
for line in OS:
if line.startswith('\tversion='):
line = '\tversion=\'' + version_string + '\',\n'
elif 'Development Status' in line:
line = '\t\t\'Development Status :: 5 - Production/Stable\',\n'
NS.write(line)
os.unlink('setup.py')
os.rename('.setup.py.new', 'setup.py')
check_call(['git', 'add', 'setup.py']) check_call(['git', 'add', 'setup.py'])
check_call(['git', 'commit']) check_call(['git', 'commit'])

View File

@ -13,7 +13,7 @@ except ImportError:
from powerline.shell import ShellPowerline from powerline.shell import ShellPowerline
from powerline.commands.main import get_argparser, finish_args, write_output from powerline.commands.main import get_argparser, finish_args, write_output
from powerline.lib.unicode import get_preferred_output_encoding from powerline.lib.encoding import get_unicode_writer
if sys.version_info < (3,): if sys.version_info < (3,):
@ -27,4 +27,4 @@ if __name__ == '__main__':
finish_args(os.environ, args) finish_args(os.environ, args)
powerline = ShellPowerline(args, run_once=True) powerline = ShellPowerline(args, run_once=True)
segment_info = {'args': args, 'environ': os.environ} segment_info = {'args': args, 'environ': os.environ}
write_output(args, powerline, segment_info, write, get_preferred_output_encoding()) write_output(args, powerline, segment_info, get_unicode_writer())

View File

@ -8,6 +8,7 @@ import subprocess
import logging import logging
import shlex import shlex
from traceback import print_exc
from setuptools import setup, find_packages from setuptools import setup, find_packages
@ -28,7 +29,7 @@ def compile_client():
else: else:
from distutils.ccompiler import new_compiler from distutils.ccompiler import new_compiler
compiler = new_compiler().compiler compiler = new_compiler().compiler
cflags = os.environ.get('CFLAGS', '-O3') cflags = os.environ.get('CFLAGS', str('-O3'))
# A normal split would do a split on each space which might be incorrect. The # A normal split would do a split on each space which might be incorrect. The
# shlex will not split if a space occurs in an arguments value. # shlex will not split if a space occurs in an arguments value.
subprocess.check_call(compiler + shlex.split(cflags) + ['client/powerline.c', '-o', 'scripts/powerline']) subprocess.check_call(compiler + shlex.split(cflags) + ['client/powerline.c', '-o', 'scripts/powerline'])
@ -58,15 +59,18 @@ else:
def get_version(): def get_version():
base_version = '2.1'
base_version += '.dev9999'
try: try:
return 'dev-' + subprocess.check_output(['git', 'rev-parse', 'HEAD']).strip() return base_version + '+git.' + str(subprocess.check_output(['git', 'rev-parse', 'HEAD']).strip())
except Exception as e: except Exception:
return 'dev' print_exc()
return base_version
setup( setup(
name='powerline-status', name='powerline-status',
version='2.0', version='2.1',
description='The ultimate statusline/prompt utility.', description='The ultimate statusline/prompt utility.',
long_description=README, long_description=README,
classifiers=[ classifiers=[

View File

@ -182,10 +182,17 @@ def select_renderer(simpler_renderer=False):
renderer = EvenSimplerRenderer if simpler_renderer else SimpleRenderer renderer = EvenSimplerRenderer if simpler_renderer else SimpleRenderer
def get_powerline_raw(helpers, PowerlineClass, **kwargs): def get_powerline_raw(helpers, PowerlineClass, replace_gcp=False, **kwargs):
if not isinstance(helpers, TestHelpers): if not isinstance(helpers, TestHelpers):
helpers = TestHelpers(helpers) helpers = TestHelpers(helpers)
select_renderer(kwargs.pop('simpler_renderer', False)) select_renderer(kwargs.pop('simpler_renderer', False))
if replace_gcp:
class PowerlineClass(PowerlineClass):
@staticmethod
def get_config_paths():
return ['/']
pl = PowerlineClass( pl = PowerlineClass(
config_loader=TestConfigLoader( config_loader=TestConfigLoader(
_helpers=helpers, _helpers=helpers,

View File

@ -43,6 +43,10 @@ config = {
'theme': 'default', 'theme': 'default',
'colorscheme': 'default', 'colorscheme': 'default',
}, },
'wm': {
'theme': 'default',
'colorscheme': 'default',
},
}, },
}, },
'colors': { 'colors': {
@ -91,6 +95,14 @@ config = {
'environment': {'fg': 'col3', 'bg': 'col4', 'attrs': ['underline']}, 'environment': {'fg': 'col3', 'bg': 'col4', 'attrs': ['underline']},
}, },
}, },
'colorschemes/wm/default': {
'groups': {
'hl1': {'fg': 'col1', 'bg': 'col2', 'attrs': ['underline']},
'hl2': {'fg': 'col2', 'bg': 'col1', 'attrs': []},
'hl3': {'fg': 'col3', 'bg': 'col1', 'attrs': ['underline']},
'hl4': {'fg': 'col2', 'bg': 'col4', 'attrs': []},
},
},
'themes/test/default': { 'themes/test/default': {
'segments': { 'segments': {
'left': [ 'left': [
@ -142,6 +154,19 @@ config = {
], ],
}, },
}, },
'themes/wm/default': {
'default_module': 'powerline.segments.common',
'segments': {
'left': [
highlighted_string('A', 'hl1'),
highlighted_string('B', 'hl2'),
],
'right': [
highlighted_string('C', 'hl3'),
highlighted_string('D', 'hl4'),
],
},
},
} }
@ -750,10 +775,10 @@ class TestVim(TestCase):
def test_environ_update(self): def test_environ_update(self):
# Regression test: test that segment obtains environment from vim, not # Regression test: test that segment obtains environment from vim, not
# from os.environ. # from os.environ.
import tests.vim as vim_module
with vim_module._with('globals', powerline_config_paths=['/']):
from powerline.vim import VimPowerline from powerline.vim import VimPowerline
import powerline as powerline_module import powerline as powerline_module
import vim
vim.vars['powerline_config_paths'] = ['/']
with swap_attributes(config, powerline_module): with swap_attributes(config, powerline_module):
with vim_module._with('environ', TEST='abc'): with vim_module._with('environ', TEST='abc'):
with get_powerline_raw(config, VimPowerline) as powerline: with get_powerline_raw(config, VimPowerline) as powerline:
@ -769,7 +794,7 @@ class TestVim(TestCase):
from powerline.vim import VimPowerline from powerline.vim import VimPowerline
import powerline as powerline_module import powerline as powerline_module
with swap_attributes(config, powerline_module): with swap_attributes(config, powerline_module):
with get_powerline_raw(config, VimPowerline) as powerline: with get_powerline_raw(config, VimPowerline, replace_gcp=True) as powerline:
powerline.add_local_theme('tests.matchers.always_true', { powerline.add_local_theme('tests.matchers.always_true', {
'segment_data': { 'segment_data': {
'foo': { 'foo': {
@ -800,6 +825,31 @@ class TestVim(TestCase):
sys.path.pop(0) sys.path.pop(0)
class TestBar(TestRender):
def test_bar(self):
import powerline as powerline_module
with swap_attributes(config, powerline_module):
with get_powerline_raw(config, powerline_module.Powerline, replace_gcp=True, ext='wm', renderer_module='bar') as powerline:
self.assertRenderEqual(
powerline,
'%{l}%{F#ffc00000}%{B#ff008000}%{+u} A%{F-B--u}%{F#ff008000}%{B#ffc00000}>>%{F-B--u}%{F#ff008000}%{B#ffc00000}B%{F-B--u}%{F#ffc00000}>>%{F-B--u}%{r}%{F#ffc00000}<<%{F-B--u}%{F#ff804000}%{B#ffc00000}%{+u}C%{F-B--u}%{F#ff0000c0}%{B#ffc00000}<<%{F-B--u}%{F#ff008000}%{B#ff0000c0}D %{F-B--u}'
)
@with_new_config
def test_bar_escape(self, config):
import powerline as powerline_module
config['themes/wm/default']['segments']['left'] = (
highlighted_string('%{asd}', 'hl1'),
highlighted_string('10% %', 'hl2'),
)
with swap_attributes(config, powerline_module):
with get_powerline_raw(config, powerline_module.Powerline, replace_gcp=True, ext='wm', renderer_module='bar') as powerline:
self.assertRenderEqual(
powerline,
'%{l}%{F#ffc00000}%{B#ff008000}%{+u} %%{asd}%{F-B--u}%{F#ff008000}%{B#ffc00000}>>%{F-B--u}%{F#ff008000}%{B#ffc00000}10%% %%%{F-B--u}%{F#ffc00000}>>%{F-B--u}%{r}%{F#ffc00000}<<%{F-B--u}%{F#ff804000}%{B#ffc00000}%{+u}C%{F-B--u}%{F#ff0000c0}%{B#ffc00000}<<%{F-B--u}%{F#ff008000}%{B#ff0000c0}D %{F-B--u}'
)
if __name__ == '__main__': if __name__ == '__main__':
from tests import main from tests import main
main() main()

View File

@ -27,6 +27,60 @@ def cell_properties_key_to_shell_escape(cell_properties_key):
)) ))
def test_expected_result(p, expected_result, cols, rows):
last_line = []
for col in range(cols):
last_line.append(p[rows - 1, col])
attempts = 10
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('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]))))
return False
def main(): def main():
VTERM_TEST_DIR = os.path.abspath('tests/vterm') VTERM_TEST_DIR = os.path.abspath('tests/vterm')
vterm_path = os.path.join(VTERM_TEST_DIR, 'path') vterm_path = os.path.join(VTERM_TEST_DIR, 'path')
@ -103,14 +157,7 @@ def main():
}, },
) )
p.start() p.start()
sleep(10) sleep(2)
last_line = []
for col in range(cols):
last_line.append(p[rows - 1, col])
result = tuple((
(key, ''.join((i.text for i in subline)))
for key, subline in groupby(last_line, lambda i: i.cell_properties_key)
))
expected_result_new = ( expected_result_new = (
(((0, 0, 0), (243, 243, 243), 1, 0, 0), ' 0 '), (((0, 0, 0), (243, 243, 243), 1, 0, 0), ' 0 '),
(((243, 243, 243), (11, 11, 11), 0, 0, 0), ' '), (((243, 243, 243), (11, 11, 11), 0, 0, 0), ' '),
@ -151,50 +198,12 @@ def main():
(((88, 88, 88), (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 '), (((199, 199, 199), (88, 88, 88), 0, 0, 0), ' S1 string here '),
) )
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('Expected:')
tmux_version = get_tmux_version(get_fallback_logger()) tmux_version = get_tmux_version(get_fallback_logger())
if tmux_version < (1, 8): if tmux_version < (1, 8):
expected_result = expected_result_old expected_result = expected_result_old
else: else:
expected_result = expected_result_new expected_result = expected_result_new
shesc_expected_result = ''.join(( return test_expected_result(p, expected_result, cols, rows)
'{0}{1}\x1b[m'.format(cell_properties_key_to_shell_escape(key), text)
for key, text in expected_result
))
print(shesc_expected_result)
if result == expected_result:
return True
else:
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]))))
return False
finally: finally:
check_call([tmux_exe, '-S', socket_path, 'kill-server'], env={ check_call([tmux_exe, '-S', socket_path, 'kill-server'], env={
'PATH': vterm_path, 'PATH': vterm_path,

View File

@ -7,7 +7,7 @@ import os
from functools import partial from functools import partial
from collections import namedtuple from collections import namedtuple
from powerline.segments import shell, tmux from powerline.segments import shell, tmux, pdb
from powerline.lib.vcs import get_fallback_create_watcher from powerline.lib.vcs import get_fallback_create_watcher
from powerline.lib.unicode import out_u from powerline.lib.unicode import out_u
@ -1308,6 +1308,52 @@ class TestVim(TestCase):
sys.path.pop(0) sys.path.pop(0)
class TestPDB(TestCase):
def test_current_line(self):
pl = Pl()
self.assertEqual(pdb.current_line(pl=pl, segment_info={'curframe': Args(f_lineno=10)}), '10')
def test_current_file(self):
pl = Pl()
cf = lambda **kwargs: pdb.current_file(
pl=pl,
segment_info={'curframe': Args(f_code=Args(co_filename='/tmp/abc.py'))},
**kwargs
)
self.assertEqual(cf(), 'abc.py')
self.assertEqual(cf(basename=True), 'abc.py')
self.assertEqual(cf(basename=False), '/tmp/abc.py')
def test_current_code_name(self):
pl = Pl()
ccn = lambda **kwargs: pdb.current_code_name(
pl=pl,
segment_info={'curframe': Args(f_code=Args(co_name='<module>'))},
**kwargs
)
self.assertEqual(ccn(), '<module>')
def test_current_context(self):
pl = Pl()
cc = lambda **kwargs: pdb.current_context(
pl=pl,
segment_info={'curframe': Args(f_code=Args(co_name='<module>', co_filename='/tmp/abc.py'))},
**kwargs
)
self.assertEqual(cc(), 'abc.py')
def test_stack_depth(self):
pl = Pl()
sd = lambda **kwargs: pdb.stack_depth(
pl=pl,
segment_info={'pdb': Args(stack=[1, 2, 3]), 'initial_stack_length': 1},
**kwargs
)
self.assertEqual(sd(), '2')
self.assertEqual(sd(full_stack=False), '2')
self.assertEqual(sd(full_stack=True), '3')
old_cwd = None old_cwd = None

View File

@ -0,0 +1,89 @@
s


View File

@ -0,0 +1,24 @@
# vim:fileencoding=utf-8:noet
from __future__ import (unicode_literals, division, absolute_import, print_function)
import pdb
import os
import sys
from powerline.bindings.pdb import use_powerline_prompt
@use_powerline_prompt
class Pdb(pdb.Pdb):
pass
p = Pdb()
script = os.path.join(os.path.dirname(__file__), 'pdb-script.py')
with open(script, 'r') as fd:
code = compile(fd.read(), script, 'exec')
p.run('exec(code)', globals={'code': code})

View File

@ -0,0 +1,38 @@
# vim:fileencoding=utf-8:noet
def nop(_):
pass
class Foo(object):
def __init__(self):
nop('__init__')
self.bar()
self.baz()
self.bra()
@classmethod
def bar(cls):
nop(cls.__name__)
@staticmethod
def baz():
nop(1)
def bra(self):
nop(self.__class__.__name__)
def brah():
nop('brah')
f = Foo()
Foo.bar()
Foo.baz()
Foo.bra(f)
f.bar()
f.baz()
f.bra()
brah()

View File

@ -0,0 +1,222 @@
 1  pdb-script.py:6 <module>  
--Call--
-> class Foo(object):
 2  pdb-script.py:6 <module>  pdb-script.py:6 Foo  
-> class Foo(object):
 2  pdb-script.py:6 <module>  pdb-script.py:6 Foo  
-> def __init__(self):
 2  pdb-script.py:6 <module>  pdb-script.py:7 Foo  
-> @classmethod
 2  pdb-script.py:6 <module>  pdb-script.py:13 Foo  
-> @staticmethod
 2  pdb-script.py:6 <module>  pdb-script.py:17 Foo  
-> def bra(self):
 2  pdb-script.py:6 <module>  pdb-script.py:21 Foo  
--Return--
-> def bra(self):
 2  pdb-script.py:6 <module>  pdb-script.py:21 Foo  
-> def brah():
 1  pdb-script.py:25 <module>  
-> f = Foo()
 1  pdb-script.py:29 <module>  
--Call--
-> def __init__(self):
 2  pdb-script.py:29 <module>  pdb-script.py:7 __init__  
-> nop('__init__')
 2  pdb-script.py:29 <module>  pdb-script.py:8 __init__  
--Call--
-> def nop(_):
 3  pdb-script.py:29 <module>  pdb-script.py:8 __init__  pdb-script.py:2 nop  
-> pass
 3  pdb-script.py:29 <module>  pdb-script.py:8 __init__  pdb-script.py:3 nop  
--Return--
-> pass
 3  pdb-script.py:29 <module>  pdb-script.py:8 __init__  pdb-script.py:3 nop  
-> self.bar()
 2  pdb-script.py:29 <module>  pdb-script.py:9 __init__  
--Call--
-> @classmethod
 3  pdb-script.py:29 <module>  pdb-script.py:9 __init__  pdb-script.py:13 bar  
-> nop(cls.__name__)
 3  pdb-script.py:29 <module>  pdb-script.py:9 __init__  pdb-script.py:15 bar  
--Call--
-> def nop(_):
 4  pdb-script.py:9 __init__  pdb-script.py:15 bar  pdb-script.py:2 nop  
-> pass
 4  pdb-script.py:9 __init__  pdb-script.py:15 bar  pdb-script.py:3 nop  
--Return--
-> pass
 4  pdb-script.py:9 __init__  pdb-script.py:15 bar  pdb-script.py:3 nop  
--Return--
-> nop(cls.__name__)
 3  pdb-script.py:29 <module>  pdb-script.py:9 __init__  pdb-script.py:15 bar  
-> self.baz()
 2  pdb-script.py:29 <module>  pdb-script.py:10 __init__  
--Call--
-> @staticmethod
 3  pdb-script.py:29 <module>  pdb-script.py:10 __init__  pdb-script.py:17 baz  
-> nop(1)
 3  pdb-script.py:29 <module>  pdb-script.py:10 __init__  pdb-script.py:19 baz  
--Call--
-> def nop(_):
 4  pdb-script.py:10 __init__  pdb-script.py:19 baz  pdb-script.py:2 nop  
-> pass
 4  pdb-script.py:10 __init__  pdb-script.py:19 baz  pdb-script.py:3 nop  
--Return--
-> pass
 4  pdb-script.py:10 __init__  pdb-script.py:19 baz  pdb-script.py:3 nop  
--Return--
-> nop(1)
 3  pdb-script.py:29 <module>  pdb-script.py:10 __init__  pdb-script.py:19 baz  
-> self.bra()
 2  pdb-script.py:29 <module>  pdb-script.py:11 __init__  
--Call--
-> def bra(self):
 3  pdb-script.py:29 <module>  pdb-script.py:11 __init__  pdb-script.py:21 bra  
-> nop(self.__class__.__name__)
 3  pdb-script.py:29 <module>  pdb-script.py:11 __init__  pdb-script.py:22 bra  
--Call--
-> def nop(_):
 4  pdb-script.py:11 __init__  pdb-script.py:22 bra  pdb-script.py:2 nop  
-> pass
 4  pdb-script.py:11 __init__  pdb-script.py:22 bra  pdb-script.py:3 nop  
--Return--
-> pass
 4  pdb-script.py:11 __init__  pdb-script.py:22 bra  pdb-script.py:3 nop  
--Return--
-> nop(self.__class__.__name__)
 3  pdb-script.py:29 <module>  pdb-script.py:11 __init__  pdb-script.py:22 bra  
--Return--
-> self.bra()
 2  pdb-script.py:29 <module>  pdb-script.py:11 __init__  
-> Foo.bar()
 1  pdb-script.py:30 <module>  
--Call--
-> @classmethod
 2  pdb-script.py:30 <module>  pdb-script.py:13 bar  
-> nop(cls.__name__)
 2  pdb-script.py:30 <module>  pdb-script.py:15 bar  
--Call--
-> def nop(_):
 3  pdb-script.py:30 <module>  pdb-script.py:15 bar  pdb-script.py:2 nop  
-> pass
 3  pdb-script.py:30 <module>  pdb-script.py:15 bar  pdb-script.py:3 nop  
--Return--
-> pass
 3  pdb-script.py:30 <module>  pdb-script.py:15 bar  pdb-script.py:3 nop  
--Return--
-> nop(cls.__name__)
 2  pdb-script.py:30 <module>  pdb-script.py:15 bar  
-> Foo.baz()
 1  pdb-script.py:31 <module>  
--Call--
-> @staticmethod
 2  pdb-script.py:31 <module>  pdb-script.py:17 baz  
-> nop(1)
 2  pdb-script.py:31 <module>  pdb-script.py:19 baz  
--Call--
-> def nop(_):
 3  pdb-script.py:31 <module>  pdb-script.py:19 baz  pdb-script.py:2 nop  
-> pass
 3  pdb-script.py:31 <module>  pdb-script.py:19 baz  pdb-script.py:3 nop  
--Return--
-> pass
 3  pdb-script.py:31 <module>  pdb-script.py:19 baz  pdb-script.py:3 nop  
--Return--
-> nop(1)
 2  pdb-script.py:31 <module>  pdb-script.py:19 baz  
-> Foo.bra(f)
 1  pdb-script.py:32 <module>  
--Call--
-> def bra(self):
 2  pdb-script.py:32 <module>  pdb-script.py:21 bra  
-> nop(self.__class__.__name__)
 2  pdb-script.py:32 <module>  pdb-script.py:22 bra  
--Call--
-> def nop(_):
 3  pdb-script.py:32 <module>  pdb-script.py:22 bra  pdb-script.py:2 nop  
-> pass
 3  pdb-script.py:32 <module>  pdb-script.py:22 bra  pdb-script.py:3 nop  
--Return--
-> pass
 3  pdb-script.py:32 <module>  pdb-script.py:22 bra  pdb-script.py:3 nop  
--Return--
-> nop(self.__class__.__name__)
 2  pdb-script.py:32 <module>  pdb-script.py:22 bra  
-> f.bar()
 1  pdb-script.py:34 <module>  
--Call--
-> @classmethod
 2  pdb-script.py:34 <module>  pdb-script.py:13 bar  
-> nop(cls.__name__)
 2  pdb-script.py:34 <module>  pdb-script.py:15 bar  
--Call--
-> def nop(_):
 3  pdb-script.py:34 <module>  pdb-script.py:15 bar  pdb-script.py:2 nop  
-> pass
 3  pdb-script.py:34 <module>  pdb-script.py:15 bar  pdb-script.py:3 nop  
--Return--
-> pass
 3  pdb-script.py:34 <module>  pdb-script.py:15 bar  pdb-script.py:3 nop  
--Return--
-> nop(cls.__name__)
 2  pdb-script.py:34 <module>  pdb-script.py:15 bar  
-> f.baz()
 1  pdb-script.py:35 <module>  
--Call--
-> @staticmethod
 2  pdb-script.py:35 <module>  pdb-script.py:17 baz  
-> nop(1)
 2  pdb-script.py:35 <module>  pdb-script.py:19 baz  
--Call--
-> def nop(_):
 3  pdb-script.py:35 <module>  pdb-script.py:19 baz  pdb-script.py:2 nop  
-> pass
 3  pdb-script.py:35 <module>  pdb-script.py:19 baz  pdb-script.py:3 nop  
--Return--
-> pass
 3  pdb-script.py:35 <module>  pdb-script.py:19 baz  pdb-script.py:3 nop  
--Return--
-> nop(1)
 2  pdb-script.py:35 <module>  pdb-script.py:19 baz  
-> f.bra()
 1  pdb-script.py:36 <module>  
--Call--
-> def bra(self):
 2  pdb-script.py:36 <module>  pdb-script.py:21 bra  
-> nop(self.__class__.__name__)
 2  pdb-script.py:36 <module>  pdb-script.py:22 bra  
--Call--
-> def nop(_):
 3  pdb-script.py:36 <module>  pdb-script.py:22 bra  pdb-script.py:2 nop  
-> pass
 3  pdb-script.py:36 <module>  pdb-script.py:22 bra  pdb-script.py:3 nop  
--Return--
-> pass
 3  pdb-script.py:36 <module>  pdb-script.py:22 bra  pdb-script.py:3 nop  
--Return--
-> nop(self.__class__.__name__)
 2  pdb-script.py:36 <module>  pdb-script.py:22 bra  
-> brah()
 1  pdb-script.py:38 <module>  
--Call--
-> def brah():
 2  pdb-script.py:38 <module>  pdb-script.py:25 brah  
-> nop('brah')
 2  pdb-script.py:38 <module>  pdb-script.py:26 brah  
--Call--
-> def nop(_):
 3  pdb-script.py:38 <module>  pdb-script.py:26 brah  pdb-script.py:2 nop  
-> pass
 3  pdb-script.py:38 <module>  pdb-script.py:26 brah  pdb-script.py:3 nop  
--Return--
-> pass
 3  pdb-script.py:38 <module>  pdb-script.py:26 brah  pdb-script.py:3 nop  
--Return--
-> nop('brah')
 2  pdb-script.py:38 <module>  pdb-script.py:26 brah  
--Return--
-> brah()
 1  pdb-script.py:38 <module>  
--Return--
 0  

View File

@ -0,0 +1,217 @@
 2  <string>:1 <module>  pdb-script.py:6 <module>  
--Call--
-> class Foo(object):
 3  <string>:1 <module>  pdb-script.py:6 <module>  pdb-script.py:6 Foo  
-> class Foo(object):
 3  <string>:1 <module>  pdb-script.py:6 <module>  pdb-script.py:6 Foo  
-> def __init__(self):
 3  <string>:1 <module>  pdb-script.py:6 <module>  pdb-script.py:7 Foo  
-> @classmethod
 3  <string>:1 <module>  pdb-script.py:6 <module>  pdb-script.py:13 Foo  
-> @staticmethod
 3  <string>:1 <module>  pdb-script.py:6 <module>  pdb-script.py:17 Foo  
-> def bra(self):
 3  <string>:1 <module>  pdb-script.py:6 <module>  pdb-script.py:21 Foo  
--Return--
-> def bra(self):
 3  <string>:1 <module>  pdb-script.py:6 <module>  pdb-script.py:21 Foo  
-> def brah():
 2  <string>:1 <module>  pdb-script.py:25 <module>  
-> f = Foo()
 2  <string>:1 <module>  pdb-script.py:29 <module>  
--Call--
-> def __init__(self):
 3  <string>:1 <module>  pdb-script.py:29 <module>  pdb-script.py:7 __init__  
-> nop('__init__')
 3  <string>:1 <module>  pdb-script.py:29 <module>  pdb-script.py:8 __init__  
--Call--
-> def nop(_):
 4  pdb-script.py:29 <module>  pdb-script.py:8 __init__  pdb-script.py:2 nop  
-> pass
 4  pdb-script.py:29 <module>  pdb-script.py:8 __init__  pdb-script.py:3 nop  
--Return--
-> pass
 4  pdb-script.py:29 <module>  pdb-script.py:8 __init__  pdb-script.py:3 nop  
-> self.bar()
 3  <string>:1 <module>  pdb-script.py:29 <module>  pdb-script.py:9 __init__  
--Call--
-> @classmethod
 4  pdb-script.py:29 <module>  pdb-script.py:9 __init__  pdb-script.py:13 bar  
-> nop(cls.__name__)
 4  pdb-script.py:29 <module>  pdb-script.py:9 __init__  pdb-script.py:15 bar  
--Call--
-> def nop(_):
 5  pdb-script.py:9 __init__  pdb-script.py:15 bar  pdb-script.py:2 nop  
-> pass
 5  pdb-script.py:9 __init__  pdb-script.py:15 bar  pdb-script.py:3 nop  
--Return--
-> pass
 5  pdb-script.py:9 __init__  pdb-script.py:15 bar  pdb-script.py:3 nop  
--Return--
-> nop(cls.__name__)
 4  pdb-script.py:29 <module>  pdb-script.py:9 __init__  pdb-script.py:15 bar  
-> self.baz()
 3  <string>:1 <module>  pdb-script.py:29 <module>  pdb-script.py:10 __init__  
--Call--
-> @staticmethod
 4  pdb-script.py:29 <module>  pdb-script.py:10 __init__  pdb-script.py:17 baz  
-> nop(1)
 4  pdb-script.py:29 <module>  pdb-script.py:10 __init__  pdb-script.py:19 baz  
--Call--
-> def nop(_):
 5  pdb-script.py:10 __init__  pdb-script.py:19 baz  pdb-script.py:2 nop  
-> pass
 5  pdb-script.py:10 __init__  pdb-script.py:19 baz  pdb-script.py:3 nop  
--Return--
-> pass
 5  pdb-script.py:10 __init__  pdb-script.py:19 baz  pdb-script.py:3 nop  
--Return--
-> nop(1)
 4  pdb-script.py:29 <module>  pdb-script.py:10 __init__  pdb-script.py:19 baz  
-> self.bra()
 3  <string>:1 <module>  pdb-script.py:29 <module>  pdb-script.py:11 __init__  
--Call--
-> def bra(self):
 4  pdb-script.py:29 <module>  pdb-script.py:11 __init__  pdb-script.py:21 bra  
-> nop(self.__class__.__name__)
 4  pdb-script.py:29 <module>  pdb-script.py:11 __init__  pdb-script.py:22 bra  
--Call--
-> def nop(_):
 5  pdb-script.py:11 __init__  pdb-script.py:22 bra  pdb-script.py:2 nop  
-> pass
 5  pdb-script.py:11 __init__  pdb-script.py:22 bra  pdb-script.py:3 nop  
--Return--
-> pass
 5  pdb-script.py:11 __init__  pdb-script.py:22 bra  pdb-script.py:3 nop  
--Return--
-> nop(self.__class__.__name__)
 4  pdb-script.py:29 <module>  pdb-script.py:11 __init__  pdb-script.py:22 bra  
--Return--
-> self.bra()
 3  <string>:1 <module>  pdb-script.py:29 <module>  pdb-script.py:11 __init__  
-> Foo.bar()
 2  <string>:1 <module>  pdb-script.py:30 <module>  
--Call--
-> @classmethod
 3  <string>:1 <module>  pdb-script.py:30 <module>  pdb-script.py:13 bar  
-> nop(cls.__name__)
 3  <string>:1 <module>  pdb-script.py:30 <module>  pdb-script.py:15 bar  
--Call--
-> def nop(_):
 4  pdb-script.py:30 <module>  pdb-script.py:15 bar  pdb-script.py:2 nop  
-> pass
 4  pdb-script.py:30 <module>  pdb-script.py:15 bar  pdb-script.py:3 nop  
--Return--
-> pass
 4  pdb-script.py:30 <module>  pdb-script.py:15 bar  pdb-script.py:3 nop  
--Return--
-> nop(cls.__name__)
 3  <string>:1 <module>  pdb-script.py:30 <module>  pdb-script.py:15 bar  
-> Foo.baz()
 2  <string>:1 <module>  pdb-script.py:31 <module>  
--Call--
-> @staticmethod
 3  <string>:1 <module>  pdb-script.py:31 <module>  pdb-script.py:17 baz  
-> nop(1)
 3  <string>:1 <module>  pdb-script.py:31 <module>  pdb-script.py:19 baz  
--Call--
-> def nop(_):
 4  pdb-script.py:31 <module>  pdb-script.py:19 baz  pdb-script.py:2 nop  
-> pass
 4  pdb-script.py:31 <module>  pdb-script.py:19 baz  pdb-script.py:3 nop  
--Return--
-> pass
 4  pdb-script.py:31 <module>  pdb-script.py:19 baz  pdb-script.py:3 nop  
--Return--
-> nop(1)
 3  <string>:1 <module>  pdb-script.py:31 <module>  pdb-script.py:19 baz  
-> Foo.bra(f)
 2  <string>:1 <module>  pdb-script.py:32 <module>  
--Call--
-> def bra(self):
 3  <string>:1 <module>  pdb-script.py:32 <module>  pdb-script.py:21 bra  
-> nop(self.__class__.__name__)
 3  <string>:1 <module>  pdb-script.py:32 <module>  pdb-script.py:22 bra  
--Call--
-> def nop(_):
 4  pdb-script.py:32 <module>  pdb-script.py:22 bra  pdb-script.py:2 nop  
-> pass
 4  pdb-script.py:32 <module>  pdb-script.py:22 bra  pdb-script.py:3 nop  
--Return--
-> pass
 4  pdb-script.py:32 <module>  pdb-script.py:22 bra  pdb-script.py:3 nop  
--Return--
-> nop(self.__class__.__name__)
 3  <string>:1 <module>  pdb-script.py:32 <module>  pdb-script.py:22 bra  
-> f.bar()
 2  <string>:1 <module>  pdb-script.py:34 <module>  
--Call--
-> @classmethod
 3  <string>:1 <module>  pdb-script.py:34 <module>  pdb-script.py:13 bar  
-> nop(cls.__name__)
 3  <string>:1 <module>  pdb-script.py:34 <module>  pdb-script.py:15 bar  
--Call--
-> def nop(_):
 4  pdb-script.py:34 <module>  pdb-script.py:15 bar  pdb-script.py:2 nop  
-> pass
 4  pdb-script.py:34 <module>  pdb-script.py:15 bar  pdb-script.py:3 nop  
--Return--
-> pass
 4  pdb-script.py:34 <module>  pdb-script.py:15 bar  pdb-script.py:3 nop  
--Return--
-> nop(cls.__name__)
 3  <string>:1 <module>  pdb-script.py:34 <module>  pdb-script.py:15 bar  
-> f.baz()
 2  <string>:1 <module>  pdb-script.py:35 <module>  
--Call--
-> @staticmethod
 3  <string>:1 <module>  pdb-script.py:35 <module>  pdb-script.py:17 baz  
-> nop(1)
 3  <string>:1 <module>  pdb-script.py:35 <module>  pdb-script.py:19 baz  
--Call--
-> def nop(_):
 4  pdb-script.py:35 <module>  pdb-script.py:19 baz  pdb-script.py:2 nop  
-> pass
 4  pdb-script.py:35 <module>  pdb-script.py:19 baz  pdb-script.py:3 nop  
--Return--
-> pass
 4  pdb-script.py:35 <module>  pdb-script.py:19 baz  pdb-script.py:3 nop  
--Return--
-> nop(1)
 3  <string>:1 <module>  pdb-script.py:35 <module>  pdb-script.py:19 baz  
-> f.bra()
 2  <string>:1 <module>  pdb-script.py:36 <module>  
--Call--
-> def bra(self):
 3  <string>:1 <module>  pdb-script.py:36 <module>  pdb-script.py:21 bra  
-> nop(self.__class__.__name__)
 3  <string>:1 <module>  pdb-script.py:36 <module>  pdb-script.py:22 bra  
--Call--
-> def nop(_):
 4  pdb-script.py:36 <module>  pdb-script.py:22 bra  pdb-script.py:2 nop  
-> pass
 4  pdb-script.py:36 <module>  pdb-script.py:22 bra  pdb-script.py:3 nop  
--Return--
-> pass
 4  pdb-script.py:36 <module>  pdb-script.py:22 bra  pdb-script.py:3 nop  
--Return--
-> nop(self.__class__.__name__)
 3  <string>:1 <module>  pdb-script.py:36 <module>  pdb-script.py:22 bra  
-> brah()
 2  <string>:1 <module>  pdb-script.py:38 <module>  
--Call--
-> def brah():
 3  <string>:1 <module>  pdb-script.py:38 <module>  pdb-script.py:25 brah  
-> nop('brah')
 3  <string>:1 <module>  pdb-script.py:38 <module>  pdb-script.py:26 brah  
--Call--
-> def nop(_):
 4  pdb-script.py:38 <module>  pdb-script.py:26 brah  pdb-script.py:2 nop  
-> pass
 4  pdb-script.py:38 <module>  pdb-script.py:26 brah  pdb-script.py:3 nop  
--Return--
-> pass
 4  pdb-script.py:38 <module>  pdb-script.py:26 brah  pdb-script.py:3 nop  
--Return--
-> nop('brah')
 3  <string>:1 <module>  pdb-script.py:38 <module>  pdb-script.py:26 brah  

View File

@ -34,9 +34,15 @@ IPYPY_DEANSI_RE = re.compile(r'\033(?:\[(?:\?\d+[lh]|[^a-zA-Z]+[a-ln-zA-Z])|[=>]
with codecs.open(fname, 'r', encoding='utf-8') as R: with codecs.open(fname, 'r', encoding='utf-8') as R:
with codecs.open(new_fname, 'w', encoding='utf-8') as W: with codecs.open(new_fname, 'w', encoding='utf-8') as W:
found_cd = False found_cd = False
i = -1
for line in (R if shell != 'fish' else R.read().split('\n')): for line in (R if shell != 'fish' else R.read().split('\n')):
i += 1
if not found_cd: if not found_cd:
found_cd = ('cd tests/shell/3rd' in line) found_cd = (
'class Foo(object):' in line
if shell == 'pdb' else
'cd tests/shell/3rd' in line
)
continue continue
if 'true is the last line' in line: if 'true is the last line' in line:
break break
@ -101,4 +107,15 @@ with codecs.open(fname, 'r', encoding='utf-8') as R:
elif shell == 'rc': elif shell == 'rc':
if line == 'read() failed: Connection reset by peer\n': if line == 'read() failed: Connection reset by peer\n':
line = '' line = ''
elif shell == 'pdb':
if is_pypy:
if line == '\033[?1h\033=\033[?25l\033[1A\n':
line = ''
line = IPYPY_DEANSI_RE.subn('', line)[0]
if line == '\n':
line = ''
if line.startswith(('>',)):
line = ''
elif line == '-> self.quitting = 1\n':
line = '-> self.quitting = True\n'
W.write(line) W.write(line)

View File

@ -1,5 +1,7 @@
#!/bin/sh #!/bin/sh
set -e . tests/bot-ci/scripts/common/main.sh
set +x
: ${PYTHON:=python} : ${PYTHON:=python}
FAIL_SUMMARY="" FAIL_SUMMARY=""
FAILED=0 FAILED=0
@ -109,14 +111,41 @@ do_run_test() {
done done
# Wait for screen to initialize # Wait for screen to initialize
sleep 1 sleep 1
while ! screen -S "$SESNAME" -p 0 -X width 300 1 ; do local attempts=100
while ! screen -S "$SESNAME" -p 0 -X width 300 1 >/dev/null ; do
sleep 0.1s sleep 0.1s
attempts=$(( attempts - 1 ))
if test $attempts -eq 0 ; then
echo "Waiting for too long: assuming test failed"
echo "Failed ${SH}. Full output:"
echo '============================================================'
cat tests/shell/${SH}.${TEST_TYPE}.${TEST_CLIENT}.full.log
echo '____________________________________________________________'
if test "x$POWERLINE_TEST_NO_CAT_V" != "x1" ; then
echo "Full output (cat -v):"
echo '============================================================'
cat -v tests/shell/${SH}.${TEST_TYPE}.${TEST_CLIENT}.full.log
echo '____________________________________________________________'
fi
return 1
fi
done done
if ( \ if ( \
test "x${SH}" = "xdash" || test "x${SH}" = "xdash" \
( \ || ( \
test "x${SH}" = "xipython" \ test "x${SH}" = "xipython" \
&& ${PYTHON} -c 'import platform, sys; sys.exit(1 - (platform.python_implementation() == "PyPy"))' \ && test "$PYTHON_IMPLEMENTATION" = "PyPy" \
) \
|| ( \
test "x${SH}" = "xpdb" \
&& ( \
( \
test "$PYTHON_VERSION_MAJOR" -eq 3 \
&& test "$PYTHON_VERSION_MINOR" -eq 2 \
&& test "$PYTHON_IMPLEMENTATION" = "CPython" \
) \
|| test "$PYTHON_IMPLEMENTATION" = "PyPy" \
) \
) \ ) \
) ; then ) ; then
# If I do not use this hack for dash then output will look like # If I do not use this hack for dash then output will look like
@ -126,7 +155,9 @@ do_run_test() {
# … # …
# prompt1> prompt2> … # prompt1> prompt2> …
while read -r line ; do while read -r line ; do
screen -S "$SESNAME" -p 0 -X stuff "$line$NL" if test "$(screen -S "$SESNAME" -p 0 -X stuff "$line$NL")" = "No screen session found." ; then
break
fi
sleep 1 sleep 1
done < tests/test_shells/input.$SH done < tests/test_shells/input.$SH
else else
@ -185,6 +216,9 @@ run_test() {
TEST_CLIENT="$2" TEST_CLIENT="$2"
SH="$3" SH="$3"
local attempts=3 local attempts=3
if test -n "$ONLY_SHELL$ONLY_TEST_TYPE$ONLY_TEST_CLIENT" ; then
attempts=1
fi
while test $attempts -gt 0 ; do while test $attempts -gt 0 ; do
rm -f tests/shell/${SH}.${TEST_TYPE}.${TEST_CLIENT}.log rm -f tests/shell/${SH}.${TEST_TYPE}.${TEST_CLIENT}.log
rm -f tests/shell/${SH}.${TEST_TYPE}.${TEST_CLIENT}.full.log rm -f tests/shell/${SH}.${TEST_TYPE}.${TEST_CLIENT}.full.log
@ -245,9 +279,11 @@ ln -s ../../test_shells/waitpid.sh tests/shell/path
if which socat ; then if which socat ; then
ln -s "$(which socat)" tests/shell/path ln -s "$(which socat)" tests/shell/path
fi fi
for pexe in powerline powerline-config ; do for pexe in powerline powerline-config powerline-render powerline.sh powerline.py ; do
if test -e scripts/$pexe ; then if test -e scripts/$pexe ; then
ln -s "$PWD/scripts/$pexe" tests/shell/path ln -s "$PWD/scripts/$pexe" tests/shell/path
elif test -e client/$pexe ; then
ln -s "$PWD/client/$pexe" tests/shell/path
elif which $pexe ; then elif which $pexe ; then
ln -s "$(which $pexe)" tests/shell/path ln -s "$(which $pexe)" tests/shell/path
else else
@ -256,6 +292,9 @@ for pexe in powerline powerline-config ; do
fi fi
done done
ln -s python tests/shell/path/pdb
PDB_PYTHON=pdb
if test -z "$POWERLINE_RC_EXE" ; then if test -z "$POWERLINE_RC_EXE" ; then
if which rc-status >/dev/null ; then if which rc-status >/dev/null ; then
# On Gentoo `rc` executable is from OpenRC. Thus app-shells/rc instals # On Gentoo `rc` executable is from OpenRC. Thus app-shells/rc instals
@ -282,6 +321,25 @@ export ADDRESS="powerline-ipc-test-$$"
export PYTHON export PYTHON
echo "Powerline address: $ADDRESS" echo "Powerline address: $ADDRESS"
check_test_client() {
local executable="$1"
local client_type="$2"
local actual_mime_type="$(file --mime-type --brief --dereference "tests/shell/path/$executable" | cut -d/ -f1)"
local expected_mime_type
case "$client_type" in
C) expected_mime_type="application/x-executable" ;;
python) expected_mime_type="text/x-python" ;;
render) expected_mime_type="text/x-python" ;;
shell) expected_mime_type="text/x-shellscript" ;;
esac
expected_mime_type="${expected_mime_type%/*}"
if test "$expected_mime_type" != "$actual_mime_type" ; then
echo "Expected $executable to have MIME type $expected_mime_type, but got $actual_mime_type"
FAILED=1
FAIL_SUMMARY="${FAIL_SUMMARY}${NL}M ${executable}"
fi
}
if test -z "${ONLY_SHELL}" || test "x${ONLY_SHELL%sh}" != "x${ONLY_SHELL}" || test "x${ONLY_SHELL}" = xbusybox || test "x${ONLY_SHELL}" = xrc ; then if test -z "${ONLY_SHELL}" || test "x${ONLY_SHELL%sh}" != "x${ONLY_SHELL}" || test "x${ONLY_SHELL}" = xbusybox || test "x${ONLY_SHELL}" = xrc ; then
scripts/powerline-config shell command scripts/powerline-config shell command
@ -308,17 +366,18 @@ if test -z "${ONLY_SHELL}" || test "x${ONLY_SHELL%sh}" != "x${ONLY_SHELL}" || te
echo "> Testing $TEST_TYPE" echo "> Testing $TEST_TYPE"
I=-1 I=-1
for POWERLINE_COMMAND in \ for POWERLINE_COMMAND in \
$PWD/scripts/powerline \ powerline \
$PWD/scripts/powerline-render \ powerline-render \
$PWD/client/powerline.py \ powerline.py \
$PWD/client/powerline.sh powerline.sh
do do
case "$POWERLINE_COMMAND" in case "$POWERLINE_COMMAND" in
*powerline) TEST_CLIENT=C ;; powerline) TEST_CLIENT=C ;;
*powerline-render) TEST_CLIENT=render ;; powerline-render) TEST_CLIENT=render ;;
*powerline.py) TEST_CLIENT=python ;; powerline.py) TEST_CLIENT=python ;;
*powerline.sh) TEST_CLIENT=shell ;; powerline.sh) TEST_CLIENT=shell ;;
esac esac
check_test_client "$POWERLINE_COMMAND" $TEST_CLIENT
if test "$TEST_CLIENT" = render && test "$TEST_TYPE" = daemon ; then if test "$TEST_CLIENT" = render && test "$TEST_TYPE" = daemon ; then
continue continue
fi fi
@ -418,6 +477,29 @@ if ( test "x${ONLY_SHELL}" = "x" || test "x${ONLY_SHELL}" = "xzsh" ) \
fi fi
fi fi
if test "x${ONLY_SHELL}" = "x" || test "x${ONLY_SHELL}" = "xpdb" ; then
if ! ( test "$PYTHON_IMPLEMENTATION" = "PyPy" && test "$PYTHON_VERSION_MAJOR" = 2 ) ; then
if test "x${ONLY_TEST_TYPE}" = "x" || test "x${ONLY_TEST_TYPE}" = "xsubclass" ; then
echo "> pdb subclass"
if ! run_test subclass python $PDB_PYTHON "$PWD/tests/test_shells/pdb-main.py" ; then
FAILED=1
FAIL_SUMMARY="${FAIL_SUMMARY}${NL}T pdb $PDB_PYTHON $PWD/tests/test_shells/pdb-main.py"
fi
fi
if test "x${ONLY_TEST_TYPE}" = "x" || test "x${ONLY_TEST_TYPE}" = "xmodule" ; then
echo "> pdb module"
MODULE="powerline.bindings.pdb"
if test "$PYTHON_MM" = "2.6" ; then
MODULE="powerline.bindings.pdb.__main__"
fi
if ! run_test module python $PDB_PYTHON -m$MODULE "$PWD/tests/test_shells/pdb-script.py" ; then
FAILED=1
FAIL_SUMMARY="${FAIL_SUMMARY}${NL}T pdb $PDB_PYTHON -m$MODULE $PWD/tests/test_shells/pdb-script"
fi
fi
fi
fi
if test "x${ONLY_SHELL}" = "x" || test "x${ONLY_SHELL}" = "xipython" ; then if test "x${ONLY_SHELL}" = "x" || test "x${ONLY_SHELL}" = "xipython" ; then
if which ipython >/dev/null ; then if which ipython >/dev/null ; then
# Define some overrides which should be ignored by IPython. # Define some overrides which should be ignored by IPython.