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__
# define ADDRESS_TEMPLATE "powerline-ipc-%d"
# define A +1
@ -91,7 +111,7 @@ int main(int argc, char *argv[]) {
server.sun_family = AF_UNIX;
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);
/* We failed to connect to the daemon, execute powerline instead */
argc = (argc < NEW_ARGV_SIZE - 1) ? argc : NEW_ARGV_SIZE - 1;

View File

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

View File

@ -16,7 +16,7 @@ Powerline provides default configurations in the following locations:
:ref:`Main configuration <config-main>`
:file:`powerline/config.json`
:ref:`Colorschemes <config-colors>`
:ref:`Colorschemes <config-colorschemes>`
:file:`powerline/colorschemes/{name}.json`,
:file:`powerline/colorscheme/{extension}/__main__.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
configuration overrides <local-configuration-overrides>`.
.. _configuration-merging:
.. note::
Existing multiple configuration files that have the same name, but are placed
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.
Start by copying the entire set of default configuration files to the
corresponding path in your user config directory:
.. code-block:: sh
mkdir ~/.config/powerline
cp -R /path/to/powerline/config_files/* ~/.config/powerline
Look at configuration in :file:`{powerline_root}/powerline/config_files`. If you
want to modify some file you can create :file:`~/.config/powerline` directory
and put modifications there: all configuration files are :ref:`merged
<configuration-merging>` with each other.
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
can do that by updating the segment dictionary in the theme you want to
customize. A segment dictionary looks like this:
If you want to move, remove or customize any of the provided segments in the
copy, you can do that by updating the segment dictionary in the theme you want
to customize. A segment dictionary looks like this:
.. code-block:: javascript
@ -93,6 +96,11 @@ prompt or statusline.
is valid JSON! Its strongly recommended that you run your configuration
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
segments that you may want to customize right away:

View File

@ -23,3 +23,9 @@ Vim listers
.. automodule:: powerline.listers.vim
: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
that was added in order to support multiline prompt ``$POWERLINE_NO_FISH_ABOVE``
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”
(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
=============

View File

@ -124,3 +124,41 @@ the used profile:
IPython=0.11* is not supported and does not work. IPython<0.10 was not
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,13 +44,31 @@ 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
======
.. note::
Until the patch is done in i3 a custom ``i3bar`` build called ``i3bgbar`` is
needed. The source is available `in S0lll0s/i3bgbar github repository
<https://github.com/S0lll0s/i3bgbar>`_.
As the patch to include background-colors in i3bar is likely not to be
merged, it is recommended to instead run ``bar`` (see above). The source for
i3bgbar is however still available `here
<https://github.com/S0lll0s/i3bgbar>`_.
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
end
_powerline_bind_mode
_powerline_set_default_mode
_powerline_update
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' $*
}
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 {
_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

View File

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

View File

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

View File

@ -1,13 +1,19 @@
{
"name": "Default",
"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:divider": { "fg": "gray5", "bg": "gray0", "attrs": [] },
"session": { "fg": "black", "bg": "gray10", "attrs": ["bold"] },
"date": { "fg": "gray8", "bg": "gray2", "attrs": [] },
"time": { "fg": "gray10", "bg": "gray2", "attrs": ["bold"] },
"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"] },
"hostname": { "fg": "black", "bg": "gray10", "attrs": ["bold"] },
"weather": { "fg": "gray8", "bg": "gray0", "attrs": [] },
@ -31,13 +37,12 @@
"battery_empty": { "fg": "white", "bg": "gray0", "attrs": [] },
"player": { "fg": "gray10", "bg": "black", "attrs": [] },
"user": { "fg": "white", "bg": "darkblue", "attrs": ["bold"] },
"superuser": { "fg": "white", "bg": "brightred", "attrs": ["bold"] },
"branch": { "fg": "gray9", "bg": "gray2", "attrs": [] },
"branch_dirty": { "fg": "brightyellow", "bg": "gray2", "attrs": [] },
"branch_clean": { "fg": "gray9", "bg": "gray2", "attrs": [] },
"branch:divider": { "fg": "gray7", "bg": "gray2", "attrs": [] },
"cwd": { "fg": "gray9", "bg": "gray4", "attrs": [] },
"cwd:current_folder": { "fg": "gray10", "bg": "gray4", "attrs": ["bold"] },
"cwd": "information:additional",
"cwd:current_folder": "information:regular",
"cwd:divider": { "fg": "gray7", "bg": "gray4", "attrs": [] },
"virtualenv": { "fg": "white", "bg": "darkcyan", "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": {
"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",
"groups": {
"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": [] },
"mode": { "fg": "darkestgreen", "bg": "brightgreen", "attrs": ["bold"] },
"attached_clients": { "fg": "white", "bg": "darkestgreen", "attrs": [] }

View File

@ -1,10 +1,7 @@
{
"name": "Solarized dark for shell",
"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": {
"vicmd": {

View File

@ -1,18 +1,34 @@
{
"name": "Solarized dark",
"groups": {
"background": { "fg": "solarized:base3", "bg": "solarized:base02", "attrs": [] },
"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": [] },
"branch": { "fg": "solarized:base1", "bg": "solarized:base02", "attrs": [] },
"branch_dirty": { "fg": "solarized:yellow", "bg": "solarized:base02", "attrs": [] },
"branch_clean": { "fg": "solarized:base1", "bg": "solarized:base02", "attrs": [] },
"cwd": { "fg": "solarized:base2", "bg": "solarized:base01", "attrs": [] },
"cwd:current_folder": { "fg": "solarized:base3", "bg": "solarized:base01", "attrs": ["bold"] },
"cwd:divider": { "fg": "solarized:base1", "bg": "solarized:base01", "attrs": [] },
"hostname": { "fg": "solarized:base3", "bg": "solarized:base01", "attrs": [] },
"environment": { "fg": "solarized:base3", "bg": "solarized:green", "attrs": [] },
"attached_clients": { "fg": "solarized:base3", "bg": "solarized:green", "attrs": [] }
"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:divider": { "fg": "solarized:base1", "bg": "solarized:base02", "attrs": [] },
"user": { "fg": "solarized:base3", "bg": "solarized:blue", "attrs": ["bold"] },
"virtualenv": { "fg": "solarized:base3", "bg": "solarized:green", "attrs": [] },
"branch": { "fg": "solarized:base1", "bg": "solarized:base02", "attrs": [] },
"branch_dirty": { "fg": "solarized:yellow", "bg": "solarized:base02", "attrs": [] },
"branch_clean": { "fg": "solarized:base1", "bg": "solarized:base02", "attrs": [] },
"email_alert_gradient": { "fg": "solarized:base3", "bg": "yellow_orange_red", "attrs": [] },
"email_alert": "warning:regular",
"cwd": "information:additional",
"cwd:current_folder": "information:regular",
"cwd:divider": { "fg": "solarized:base1", "bg": "solarized:base01", "attrs": [] },
"hostname": { "fg": "solarized:base3", "bg": "solarized:base01", "attrs": [] },
"environment": { "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"
}
},
"pdb": {
"colorscheme": "default",
"theme": "default"
},
"shell": {
"colorscheme": "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()
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,
).func(check_full_segment_data)
sub_segments_spec.optional().list(segment_spec)
del sub_segments_spec
segments_spec = Spec().optional().list(segment_spec).copy
segdict_spec = Spec(
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__'),
ecconfigs,
)
if not (mconfigs[0] or mconfigs[2]):
continue
config = None
for mconfig in mconfigs:
if not mconfig:
@ -554,7 +557,7 @@ def check(paths=None, debug=False, echoerr=echoerr, require_ext=None):
config = mergedicts_copy(config, mconfig)
else:
config = mconfig
colorscheme_configs[colorscheme] = config
colorscheme_configs[ext][colorscheme] = config
theme_configs = dict2(loaded_configs['themes'])
top_theme_configs = dict(loaded_configs['top_themes'])

View File

@ -499,6 +499,56 @@ def check_segment_function(function_name, data, context, echoerr):
return True, False, False
def hl_group_in_colorscheme(hl_group, cconfig, allow_gradients, data, context, echoerr):
havemarks(hl_group, cconfig)
if hl_group not in cconfig.get('groups', {}):
return False
elif not allow_gradients or allow_gradients == 'force':
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)
hadgradient = False
for ckey in ('fg', 'bg'):
color = group_config.get(ckey)
if not color:
# No color. Error was already reported when checking
# colorschemes.
return True
havemarks(color)
# Gradients are only allowed for function segments. Note that
# whether *either* color or gradient exists should have been
# already checked
hascolor = color in data['colors_config'].get('colors', {})
hasgradient = color in data['colors_config'].get('gradients', {})
if hasgradient:
hadgradient = True
if allow_gradients is False and not hascolor and hasgradient:
echoerr(
context='Error while checking highlight group in theme (key {key})'.format(
key=context.key),
context_mark=hl_group.mark,
problem='group {0} is using gradient {1} instead of a color'.format(hl_group, color),
problem_mark=color.mark
)
return False
if allow_gradients == 'force' and not hadgradient:
echoerr(
context='Error while checking highlight group in theme (key {key})'.format(
key=context.key),
context_mark=hl_group.mark,
problem='group {0} should have at least one gradient color, but it has no'.format(hl_group),
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']
@ -507,45 +557,14 @@ def hl_exists(hl_group, data, context, echoerr, allow_gradients=False):
# twice
return []
r = []
found = False
for colorscheme, cconfig in data['colorscheme_configs'][ext].items():
if hl_group not in cconfig.get('groups', {}):
if hl_group_in_colorscheme(hl_group, cconfig, allow_gradients, data, context, echoerr):
found = True
else:
r.append(colorscheme)
elif not allow_gradients or allow_gradients == 'force':
group_config = cconfig['groups'][hl_group]
havemarks(group_config)
hadgradient = False
for ckey in ('fg', 'bg'):
color = group_config.get(ckey)
if not color:
# No color. Error was already reported.
continue
havemarks(color)
# Gradients are only allowed for function segments. Note that
# whether *either* color or gradient exists should have been
# already checked
hascolor = color in data['colors_config'].get('colors', {})
hasgradient = color in data['colors_config'].get('gradients', {})
if hasgradient:
hadgradient = True
if allow_gradients is False and not hascolor and hasgradient:
echoerr(
context='Error while checking highlight group in theme (key {key})'.format(
key=context.key),
context_mark=hl_group.mark,
problem='group {0} is using gradient {1} instead of a color'.format(hl_group, color),
problem_mark=color.mark
)
r.append(colorscheme)
continue
if allow_gradients == 'force' and not hadgradient:
echoerr(
context='Error while checking highlight group in theme (key {key})'.format(
key=context.key),
context_mark=hl_group.mark,
problem='group {0} should have at least one gradient color, but it has no'.format(hl_group),
problem_mark=group_config.mark
)
r.append(colorscheme)
if not found:
pass
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),
'home': os.environ.get('HOME'),
}
'''Basic segment info. Is merged with local segment information by
``.get_segment_info()`` method. Keys:
'''Basic segment info
Is merged with local segment information by :py:meth:`get_segment_info`
method. Keys:
``environ``
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
``True``: ``(colored_string, colorless_string, string_width)``.
: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:
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)
return self.do_render(
@ -504,7 +507,7 @@ class Renderer(object):
def hl(self, contents, fg=None, bg=None, attrs=None):
'''Output highlighted chunk.
This implementation just outputs ``.hlstyle()`` joined with
This implementation just outputs :py:meth:`hlstyle` joined with
``contents``.
'''
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 powerline.renderers.shell import ShellRenderer
from powerline.renderers.shell.readline import ReadlineRenderer
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'''
escape_hl_start = '\x01'
escape_hl_end = '\x02'
pass
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
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):
'''Powerline rcsh prompt renderer'''
escape_hl_start = '\x01'
escape_hl_end = '\x02'
renderer = RcshRenderer
renderer = ReadlineRenderer

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
prefix, but it is stripped out (actually, any ``CommandT::`` substring will
be stripped out).
Highlight groups used: ``commandt:finder``.
'''
initialize()
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
finders ``MRUBufferFinder``, ``BufferFinder``, ``TagFinder`` and
``JumpFinder`` (pretty much any finder, except ``FileFinder``).
Highlight groups used: ``commandt:path``.
'''
initialize()
vim.command('ruby $powerline.commandt_set_active_finder')

View File

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

View File

@ -17,7 +17,7 @@ from io import BytesIO
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
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.daemon import get_argparser as get_daemon_argparser
@ -107,7 +107,7 @@ def render(args, environ, cwd):
else:
return 'Failed to render {0}: {1}'.format(str(key), str(e))
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)
return s.read()
@ -150,10 +150,7 @@ def do_write(conn, result):
pass
encoding = get_preferred_output_encoding()
def safe_bytes(o, encoding=encoding):
def safe_bytes(o, encoding=get_preferred_output_encoding()):
'''Return bytes instance without ever throwing an exception.'''
try:
try:
@ -171,7 +168,7 @@ def safe_bytes(o, encoding=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]
numargs = int(args[0], 16)
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('.')))
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):
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'])
try:
check_call(['git', 'merge', '--no-ff', '--no-commit', '--log', rev])
except CalledProcessError:
check_call(['git', 'mergetool', '--tool', 'vimdiff2'])
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:
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')
setup_py_filter(lambda line: setup_py_master_filter(line, version_string))
check_call(['git', 'add', 'setup.py'])
check_call(['git', 'commit'])

View File

@ -13,7 +13,7 @@ except ImportError:
from powerline.shell import ShellPowerline
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,):
@ -27,4 +27,4 @@ if __name__ == '__main__':
finish_args(os.environ, args)
powerline = ShellPowerline(args, run_once=True)
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 shlex
from traceback import print_exc
from setuptools import setup, find_packages
@ -28,7 +29,7 @@ def compile_client():
else:
from distutils.ccompiler import new_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
# 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'])
@ -58,15 +59,18 @@ else:
def get_version():
base_version = '2.1'
base_version += '.dev9999'
try:
return 'dev-' + subprocess.check_output(['git', 'rev-parse', 'HEAD']).strip()
except Exception as e:
return 'dev'
return base_version + '+git.' + str(subprocess.check_output(['git', 'rev-parse', 'HEAD']).strip())
except Exception:
print_exc()
return base_version
setup(
name='powerline-status',
version='2.0',
version='2.1',
description='The ultimate statusline/prompt utility.',
long_description=README,
classifiers=[

View File

@ -182,10 +182,17 @@ def select_renderer(simpler_renderer=False):
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):
helpers = TestHelpers(helpers)
select_renderer(kwargs.pop('simpler_renderer', False))
if replace_gcp:
class PowerlineClass(PowerlineClass):
@staticmethod
def get_config_paths():
return ['/']
pl = PowerlineClass(
config_loader=TestConfigLoader(
_helpers=helpers,

View File

@ -43,6 +43,10 @@ config = {
'theme': 'default',
'colorscheme': 'default',
},
'wm': {
'theme': 'default',
'colorscheme': 'default',
},
},
},
'colors': {
@ -91,6 +95,14 @@ config = {
'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': {
'segments': {
'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,26 +775,26 @@ class TestVim(TestCase):
def test_environ_update(self):
# Regression test: test that segment obtains environment from vim, not
# from os.environ.
from powerline.vim import VimPowerline
import powerline as powerline_module
import vim
vim.vars['powerline_config_paths'] = ['/']
with swap_attributes(config, powerline_module):
with vim_module._with('environ', TEST='abc'):
with get_powerline_raw(config, VimPowerline) as powerline:
window = vim_module.current.window
window_id = 1
winnr = window.number
self.assertEqual(powerline.render(window, window_id, winnr), b'%#Pl_3_8404992_4_192_underline#\xc2\xa0abc%#Pl_4_192_NONE_None_NONE#>>')
vim_module._environ['TEST'] = 'def'
self.assertEqual(powerline.render(window, window_id, winnr), b'%#Pl_3_8404992_4_192_underline#\xc2\xa0def%#Pl_4_192_NONE_None_NONE#>>')
import tests.vim as vim_module
with vim_module._with('globals', powerline_config_paths=['/']):
from powerline.vim import VimPowerline
import powerline as powerline_module
with swap_attributes(config, powerline_module):
with vim_module._with('environ', TEST='abc'):
with get_powerline_raw(config, VimPowerline) as powerline:
window = vim_module.current.window
window_id = 1
winnr = window.number
self.assertEqual(powerline.render(window, window_id, winnr), b'%#Pl_3_8404992_4_192_underline#\xc2\xa0abc%#Pl_4_192_NONE_None_NONE#>>')
vim_module._environ['TEST'] = 'def'
self.assertEqual(powerline.render(window, window_id, winnr), b'%#Pl_3_8404992_4_192_underline#\xc2\xa0def%#Pl_4_192_NONE_None_NONE#>>')
def test_local_themes(self):
# Regression test: VimPowerline.add_local_theme did not work properly.
from powerline.vim import VimPowerline
import powerline as 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', {
'segment_data': {
'foo': {
@ -800,6 +825,31 @@ class TestVim(TestCase):
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__':
from tests import 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():
VTERM_TEST_DIR = os.path.abspath('tests/vterm')
vterm_path = os.path.join(VTERM_TEST_DIR, 'path')
@ -103,14 +157,7 @@ def main():
},
)
p.start()
sleep(10)
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)
))
sleep(2)
expected_result_new = (
(((0, 0, 0), (243, 243, 243), 1, 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), ' '),
(((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())
if tmux_version < (1, 8):
expected_result = expected_result_old
else:
expected_result = expected_result_new
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)
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
return test_expected_result(p, expected_result, cols, rows)
finally:
check_call([tmux_exe, '-S', socket_path, 'kill-server'], env={
'PATH': vterm_path,

View File

@ -7,7 +7,7 @@ import os
from functools import partial
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.unicode import out_u
@ -1308,6 +1308,52 @@ class TestVim(TestCase):
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

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(new_fname, 'w', encoding='utf-8') as W:
found_cd = False
i = -1
for line in (R if shell != 'fish' else R.read().split('\n')):
i += 1
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
if 'true is the last line' in line:
break
@ -101,4 +107,15 @@ with codecs.open(fname, 'r', encoding='utf-8') as R:
elif shell == 'rc':
if line == 'read() failed: Connection reset by peer\n':
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)

View File

@ -1,5 +1,7 @@
#!/bin/sh
set -e
. tests/bot-ci/scripts/common/main.sh
set +x
: ${PYTHON:=python}
FAIL_SUMMARY=""
FAILED=0
@ -109,14 +111,41 @@ do_run_test() {
done
# Wait for screen to initialize
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
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
if ( \
test "x${SH}" = "xdash" ||
( \
test "x${SH}" = "xdash" \
|| ( \
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
# If I do not use this hack for dash then output will look like
@ -126,7 +155,9 @@ do_run_test() {
# …
# prompt1> prompt2> …
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
done < tests/test_shells/input.$SH
else
@ -185,6 +216,9 @@ run_test() {
TEST_CLIENT="$2"
SH="$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
rm -f tests/shell/${SH}.${TEST_TYPE}.${TEST_CLIENT}.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
ln -s "$(which socat)" tests/shell/path
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
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
ln -s "$(which $pexe)" tests/shell/path
else
@ -256,6 +292,9 @@ for pexe in powerline powerline-config ; do
fi
done
ln -s python tests/shell/path/pdb
PDB_PYTHON=pdb
if test -z "$POWERLINE_RC_EXE" ; then
if which rc-status >/dev/null ; then
# On Gentoo `rc` executable is from OpenRC. Thus app-shells/rc instals
@ -282,6 +321,25 @@ export ADDRESS="powerline-ipc-test-$$"
export PYTHON
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
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"
I=-1
for POWERLINE_COMMAND in \
$PWD/scripts/powerline \
$PWD/scripts/powerline-render \
$PWD/client/powerline.py \
$PWD/client/powerline.sh
powerline \
powerline-render \
powerline.py \
powerline.sh
do
case "$POWERLINE_COMMAND" in
*powerline) TEST_CLIENT=C ;;
*powerline-render) TEST_CLIENT=render ;;
*powerline.py) TEST_CLIENT=python ;;
*powerline.sh) TEST_CLIENT=shell ;;
powerline) TEST_CLIENT=C ;;
powerline-render) TEST_CLIENT=render ;;
powerline.py) TEST_CLIENT=python ;;
powerline.sh) TEST_CLIENT=shell ;;
esac
check_test_client "$POWERLINE_COMMAND" $TEST_CLIENT
if test "$TEST_CLIENT" = render && test "$TEST_TYPE" = daemon ; then
continue
fi
@ -418,6 +477,29 @@ if ( test "x${ONLY_SHELL}" = "x" || test "x${ONLY_SHELL}" = "xzsh" ) \
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 which ipython >/dev/null ; then
# Define some overrides which should be ignored by IPython.