From ab4021a2730c3800e07d65738a643ce628bc7bce Mon Sep 17 00:00:00 2001 From: ZyX Date: Sun, 25 Jan 2015 01:24:05 +0300 Subject: [PATCH 01/43] Make sure that powerline.bindings.zsh is able to work with old zpython --- powerline/bindings/zsh/__init__.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/powerline/bindings/zsh/__init__.py b/powerline/bindings/zsh/__init__.py index 291a4c39..a7ab44fd 100644 --- a/powerline/bindings/zsh/__init__.py +++ b/powerline/bindings/zsh/__init__.py @@ -101,7 +101,10 @@ class Environment(object): return False -environ = getattr(zsh, 'environ', Environment()) +if hasattr(getattr(zsh, 'environ', None), '__contains__'): + environ = zsh.environ +else: + environ = Environment() class ZshPowerline(ShellPowerline): From 332a266d87602fcb6f0ebd96a094a19429d8c385 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sun, 25 Jan 2015 01:58:27 +0300 Subject: [PATCH 02/43] When testing Vim do not rely on test order and do not save state This commit refactors `TestVim` test class in test_configuration so that 1. `test_environ_update` does not leave state (value of `powerline_config_paths` global Vim variable) behind other tests can use. 2. `test_local_themes` does not rely on state left from `test_environ_update`, instead using new facility for providing needed value of `Powerline.get_config_paths` call. This facility will be used later in BAR tests. Ref #1256 --- tests/lib/config_mock.py | 9 ++++++++- tests/test_configuration.py | 28 ++++++++++++++-------------- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/tests/lib/config_mock.py b/tests/lib/config_mock.py index dd19ff11..9e0edf6d 100644 --- a/tests/lib/config_mock.py +++ b/tests/lib/config_mock.py @@ -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, diff --git a/tests/test_configuration.py b/tests/test_configuration.py index efc21476..9d6af211 100644 --- a/tests/test_configuration.py +++ b/tests/test_configuration.py @@ -750,26 +750,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': { From 96571cc47b197569cbaf4a72be0be27e221efbd4 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sun, 25 Jan 2015 02:06:35 +0300 Subject: [PATCH 03/43] Use new `zsh.expand` function in place of `zsh.eval` --- powerline/bindings/zsh/__init__.py | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/powerline/bindings/zsh/__init__.py b/powerline/bindings/zsh/__init__.py index a7ab44fd..5913842a 100644 --- a/powerline/bindings/zsh/__init__.py +++ b/powerline/bindings/zsh/__init__.py @@ -107,6 +107,16 @@ 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): def init(self, **kwargs): super(ZshPowerline, self).init(Args(), **kwargs) @@ -138,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: @@ -153,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: From 614c17d1158cf95bb0e1f5a4dd1293c9d32380b8 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sun, 25 Jan 2015 02:08:36 +0300 Subject: [PATCH 04/43] Do not use `zsh.eval` to unset special value --- powerline/bindings/zsh/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powerline/bindings/zsh/__init__.py b/powerline/bindings/zsh/__init__.py index 5913842a..cbe5f957 100644 --- a/powerline/bindings/zsh/__init__.py +++ b/powerline/bindings/zsh/__init__.py @@ -205,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) From dd77d420a3e697ec7ea62a23ba07ab6e86297654 Mon Sep 17 00:00:00 2001 From: S0lll0s Date: Thu, 8 Jan 2015 00:03:34 +0100 Subject: [PATCH 05/43] Add BAR (bar ain't recursive) renderer and fitting i3 bindings --- docs/source/usage/wm-widgets.rst | 23 ++++++++++++-- powerline/bindings/i3/powerline-bar.py | 42 +++++++++++++++++++++++++ powerline/renderers/bar.py | 39 +++++++++++++++++++++++ tests/test_configuration.py | 43 ++++++++++++++++++++++++++ 4 files changed, 144 insertions(+), 3 deletions(-) create mode 100644 powerline/bindings/i3/powerline-bar.py create mode 100644 powerline/renderers/bar.py diff --git a/docs/source/usage/wm-widgets.rst b/docs/source/usage/wm-widgets.rst index 0a734ea7..6a28246d 100644 --- a/docs/source/usage/wm-widgets.rst +++ b/docs/source/usage/wm-widgets.rst @@ -44,13 +44,30 @@ Add the following to :file:`~/.config/qtile/config.py`: ), ] +.. _bar-usage: + +LemonBoy’s bar +============= + +To run the bar simply pipe the output of the binding script into ``bar`` and specify appropriate +options, for example like this:: + + python powerline-bar.py | bar -f "-xos4-*" + +to run with i3, simply ``exec`` this in i3 config file:: + + exec python powerline-bar.py | bar -f "-xos4-*" + +See the `bar documentation `_ 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 - `_. + 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 + `_. Add the following to :file:`~/.i3/config`:: diff --git a/powerline/bindings/i3/powerline-bar.py b/powerline/bindings/i3/powerline-bar.py new file mode 100644 index 00000000..fe29a08b --- /dev/null +++ b/powerline/bindings/i3/powerline-bar.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python +# vim:fileencoding=utf-8:noet +from __future__ import (unicode_literals, division, absolute_import, print_function) + +import sys +import time +import i3 +from threading import Lock +from powerline import Powerline +from powerline.lib.monotonic import monotonic + +if __name__ == '__main__': + name = 'wm' + if len(sys.argv) > 1: + name = sys.argv[1] + + powerline = Powerline( name, renderer_module='bar' ) + powerline.update_renderer() + + interval = 0.5 + lock = Lock() + + def encode( str ): return str.encode('utf-8') + + if sys.version_info > (3,0): + def encode( str ): return str + + def render(event=None, data=None, sub=None): + global lock + with lock: + ln = '%{l}' + ln += powerline.render(side='left') + ln += '%{r}' + ln += powerline.render(side='right') + print( encode(ln) ) + sys.stdout.flush() + + sub = i3.Subscription(render, 'workspace') + while True: + start_time = monotonic() + render() + time.sleep(max(interval - (monotonic() - start_time), 0.1)) diff --git a/powerline/renderers/bar.py b/powerline/renderers/bar.py new file mode 100644 index 00000000..e61c3cc3 --- /dev/null +++ b/powerline/renderers/bar.py @@ -0,0 +1,39 @@ +# 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_BOLD, ATTR_ITALIC, ATTR_UNDERLINE + + +class BarRenderer(Renderer): + '''bar (bar ain't recursive) renderer + + + See documentation of `bar `_ and :ref:`the usage instructions ` + ''' + + character_translations = Renderer.character_translations.copy() + character_translations[ord('%')] = '%%' + + @staticmethod + def hlstyle(*args, **kwargs): + # We don’t 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}' + + +renderer = BarRenderer diff --git a/tests/test_configuration.py b/tests/test_configuration.py index 9d6af211..07d98b71 100644 --- a/tests/test_configuration.py +++ b/tests/test_configuration.py @@ -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'), + ], + }, + }, } @@ -799,6 +824,24 @@ class TestVim(TestCase): def tearDownClass(cls): sys.path.pop(0) +class TestBar(TestCase): + def test_bar(self): + import powerline as powerline_module + with swap_attributes(config, powerline_module): + with get_powerline_raw(config, powerline_module, ext='wm', renderer_module='bar') as powerline: + self.assertEqual("%{{l}}{}%{{r}}{}".format(powerline.render(side='left'), powerline.render(side='right')), "SOME_STRING_HERE") + + def test_bar_escape(self): + from powerline.shell import ShellPowerline + 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, ext='wm', renderer_module='bar') as powerline: + self.assertEqual(powerline.render(side='left'), "SOME_STRING_HERE") + if __name__ == '__main__': from tests import main From 1e7dc7900d5a44563bbcfd3679fee54b42bf3c45 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sun, 25 Jan 2015 12:51:19 +0300 Subject: [PATCH 06/43] Fix issues found in 1256 pull request Ref #1256 --- docs/source/usage/wm-widgets.rst | 13 ++++---- .../bindings/{i3 => bar}/powerline-bar.py | 33 +++++++++---------- powerline/renderers/bar.py | 12 +++++-- tests/test_configuration.py | 25 +++++++++----- 4 files changed, 48 insertions(+), 35 deletions(-) rename powerline/bindings/{i3 => bar}/powerline-bar.py (58%) mode change 100644 => 100755 diff --git a/docs/source/usage/wm-widgets.rst b/docs/source/usage/wm-widgets.rst index 6a28246d..bcbf206f 100644 --- a/docs/source/usage/wm-widgets.rst +++ b/docs/source/usage/wm-widgets.rst @@ -47,18 +47,19 @@ Add the following to :file:`~/.config/qtile/config.py`: .. _bar-usage: LemonBoy’s bar -============= +============== -To run the bar simply pipe the output of the binding script into ``bar`` and specify appropriate -options, for example like this:: +To run the bar simply pipe the output of the binding script into ``bar`` and +specify appropriate options, for example like this:: - python powerline-bar.py | bar -f "-xos4-*" + python /path/to/powerline/bindings/bar/powerline-bar.py | bar to run with i3, simply ``exec`` this in i3 config file:: - exec python powerline-bar.py | bar -f "-xos4-*" + exec python /path/to/powerline/bindings/bar/powerline-bar.py --i3 | bar -See the `bar documentation `_ for more information and options. +See the `bar documentation `_ for more +information and options. I3 bar ====== diff --git a/powerline/bindings/i3/powerline-bar.py b/powerline/bindings/bar/powerline-bar.py old mode 100644 new mode 100755 similarity index 58% rename from powerline/bindings/i3/powerline-bar.py rename to powerline/bindings/bar/powerline-bar.py index fe29a08b..51ea63d6 --- a/powerline/bindings/i3/powerline-bar.py +++ b/powerline/bindings/bar/powerline-bar.py @@ -4,38 +4,37 @@ from __future__ import (unicode_literals, division, absolute_import, print_funct import sys import time -import i3 + from threading import Lock +from argparse import ArgumentParser + from powerline import Powerline from powerline.lib.monotonic import monotonic -if __name__ == '__main__': - name = 'wm' - if len(sys.argv) > 1: - name = sys.argv[1] - powerline = Powerline( name, renderer_module='bar' ) +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 = Powerline('wm', renderer_module='bar') powerline.update_renderer() interval = 0.5 lock = Lock() - def encode( str ): return str.encode('utf-8') - - if sys.version_info > (3,0): - def encode( str ): return str - def render(event=None, data=None, sub=None): global lock with lock: - ln = '%{l}' - ln += powerline.render(side='left') - ln += '%{r}' - ln += powerline.render(side='right') - print( encode(ln) ) + print(powerline.render()) sys.stdout.flush() - sub = i3.Subscription(render, 'workspace') + if args.i3: + import i3 + sub = i3.Subscription(render, 'workspace') + while True: start_time = monotonic() render() diff --git a/powerline/renderers/bar.py b/powerline/renderers/bar.py index e61c3cc3..7e1e5d36 100644 --- a/powerline/renderers/bar.py +++ b/powerline/renderers/bar.py @@ -2,7 +2,7 @@ from __future__ import (unicode_literals, division, absolute_import, print_function) from powerline.renderer import Renderer -from powerline.colorscheme import ATTR_BOLD, ATTR_ITALIC, ATTR_UNDERLINE +from powerline.colorscheme import ATTR_UNDERLINE class BarRenderer(Renderer): @@ -25,15 +25,21 @@ class BarRenderer(Renderer): if fg is not None: if fg is not False and fg[1] is not False: - text += '%{{F#ff{0:06x}}}'.format(fg[1]) + 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]) + 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 diff --git a/tests/test_configuration.py b/tests/test_configuration.py index 07d98b71..c0708c3d 100644 --- a/tests/test_configuration.py +++ b/tests/test_configuration.py @@ -824,23 +824,30 @@ class TestVim(TestCase): def tearDownClass(cls): sys.path.pop(0) -class TestBar(TestCase): + +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, ext='wm', renderer_module='bar') as powerline: - self.assertEqual("%{{l}}{}%{{r}}{}".format(powerline.render(side='left'), powerline.render(side='right')), "SOME_STRING_HERE") + 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}' + ) - def test_bar_escape(self): - from powerline.shell import ShellPowerline + @with_new_config + def test_bar_escape(self, config): import powerline as powerline_module - config['themes/wm/default']['segments']['left'] = { + 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, ext='wm', renderer_module='bar') as powerline: - self.assertEqual(powerline.render(side='left'), "SOME_STRING_HERE") + 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 ea9eae676f8a2a44cd2fa96a87c3932f2e42db45 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sun, 25 Jan 2015 16:59:36 +0300 Subject: [PATCH 07/43] Always write UTF-8 string --- powerline/bindings/bar/powerline-bar.py | 6 +++++- powerline/commands/main.py | 7 +++---- powerline/lib/encoding.py | 25 +++++++++++++++++++++++++ scripts/powerline-daemon | 11 ++++------- scripts/powerline-render | 4 ++-- 5 files changed, 39 insertions(+), 14 deletions(-) diff --git a/powerline/bindings/bar/powerline-bar.py b/powerline/bindings/bar/powerline-bar.py index 51ea63d6..b93def02 100755 --- a/powerline/bindings/bar/powerline-bar.py +++ b/powerline/bindings/bar/powerline-bar.py @@ -10,6 +10,7 @@ from argparse import ArgumentParser from powerline import Powerline from powerline.lib.monotonic import monotonic +from powerline.lib.encoding import get_unicode_writer if __name__ == '__main__': @@ -25,10 +26,13 @@ if __name__ == '__main__': interval = 0.5 lock = Lock() + write = get_unicode_writer(encoding='utf-8') + def render(event=None, data=None, sub=None): global lock with lock: - print(powerline.render()) + write(powerline.render()) + write('\n') sys.stdout.flush() if args.i3: diff --git a/powerline/commands/main.py b/powerline/commands/main.py index 605098c6..8c41b476 100644 --- a/powerline/commands/main.py +++ b/powerline/commands/main.py @@ -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) diff --git a/powerline/lib/encoding.py b/powerline/lib/encoding.py index 1ca48ce6..798fc396 100644 --- a/powerline/lib/encoding.py +++ b/powerline/lib/encoding.py @@ -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)) diff --git a/scripts/powerline-daemon b/scripts/powerline-daemon index 82841878..10635c97 100755 --- a/scripts/powerline-daemon +++ b/scripts/powerline-daemon @@ -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]) diff --git a/scripts/powerline-render b/scripts/powerline-render index 07016705..4b8a3a0a 100755 --- a/scripts/powerline-render +++ b/scripts/powerline-render @@ -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()) From ff0631c625cda7c1aac3d86cbc7074a996ef0fc1 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sun, 25 Jan 2015 17:02:54 +0300 Subject: [PATCH 08/43] Make sure powerline class knows that it will use UTF-8 --- powerline/bindings/bar/powerline-bar.py | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/powerline/bindings/bar/powerline-bar.py b/powerline/bindings/bar/powerline-bar.py index b93def02..898c5cc6 100755 --- a/powerline/bindings/bar/powerline-bar.py +++ b/powerline/bindings/bar/powerline-bar.py @@ -13,6 +13,21 @@ 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( @@ -20,21 +35,13 @@ if __name__ == '__main__': help='Subscribe for i3 events.' ) args = parser.parse_args() - powerline = Powerline('wm', renderer_module='bar') - powerline.update_renderer() + powerline = BarPowerline() interval = 0.5 lock = Lock() write = get_unicode_writer(encoding='utf-8') - def render(event=None, data=None, sub=None): - global lock - with lock: - write(powerline.render()) - write('\n') - sys.stdout.flush() - if args.i3: import i3 sub = i3.Subscription(render, 'workspace') From c606db75a5780a4b5216631b904d03a3a84ea395 Mon Sep 17 00:00:00 2001 From: ZyX Date: Mon, 26 Jan 2015 20:38:56 +0300 Subject: [PATCH 09/43] Remove call to a removed function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Function was removed in a90b080 (“Remove all exports”), but call survived. Fixes #1286 --- powerline/bindings/fish/powerline-setup.fish | 1 - 1 file changed, 1 deletion(-) diff --git a/powerline/bindings/fish/powerline-setup.fish b/powerline/bindings/fish/powerline-setup.fish index dc631c5e..4c80cae7 100644 --- a/powerline/bindings/fish/powerline-setup.fish +++ b/powerline/bindings/fish/powerline-setup.fish @@ -76,7 +76,6 @@ function powerline-setup " _powerline_set_columns end - _powerline_bind_mode _powerline_set_default_mode _powerline_update end From 3b56cf748b7241a6fcfd47eafad79fabb08b134d Mon Sep 17 00:00:00 2001 From: ZyX Date: Sat, 31 Jan 2015 13:49:05 +0300 Subject: [PATCH 10/43] Fix linting of highlight groups Currently checks for highlight group existence do not work. With this commit tests will fail due to #1136. --- powerline/lint/__init__.py | 5 +- powerline/lint/checks.py | 93 +++++++++++++++++++++++--------------- 2 files changed, 60 insertions(+), 38 deletions(-) diff --git a/powerline/lint/__init__.py b/powerline/lint/__init__.py index d6ba0bfe..340e69a5 100644 --- a/powerline/lint/__init__.py +++ b/powerline/lint/__init__.py @@ -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']) diff --git a/powerline/lint/checks.py b/powerline/lint/checks.py index 24c91f43..4fcd71dd 100644 --- a/powerline/lint/checks.py +++ b/powerline/lint/checks.py @@ -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 From 72d9b8305a163ff64c1bcfdd5ab66912e6102c27 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sat, 31 Jan 2015 15:10:06 +0300 Subject: [PATCH 11/43] Fix linter errors: add necessary highlight groups or fix docstrings Fixes #1136 --- .../config_files/colorschemes/default.json | 13 ++++-- .../colorschemes/ipython/__main__.json | 6 +++ .../colorschemes/ipython/default.json | 7 ---- .../colorschemes/shell/__main__.json | 6 ++- .../colorschemes/shell/default.json | 3 -- .../colorschemes/shell/solarized.json | 5 +-- .../config_files/colorschemes/solarized.json | 42 +++++++++++++------ powerline/segments/vim/plugin/commandt.py | 4 ++ 8 files changed, 54 insertions(+), 32 deletions(-) create mode 100644 powerline/config_files/colorschemes/ipython/__main__.json delete mode 100644 powerline/config_files/colorschemes/ipython/default.json diff --git a/powerline/config_files/colorschemes/default.json b/powerline/config_files/colorschemes/default.json index fbea5532..b1d653c0 100644 --- a/powerline/config_files/colorschemes/default.json +++ b/powerline/config_files/colorschemes/default.json @@ -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": [] } diff --git a/powerline/config_files/colorschemes/ipython/__main__.json b/powerline/config_files/colorschemes/ipython/__main__.json new file mode 100644 index 00000000..982ea355 --- /dev/null +++ b/powerline/config_files/colorschemes/ipython/__main__.json @@ -0,0 +1,6 @@ +{ + "groups": { + "prompt": "information:additional", + "prompt_count": "information:highlighted" + } +} diff --git a/powerline/config_files/colorschemes/ipython/default.json b/powerline/config_files/colorschemes/ipython/default.json deleted file mode 100644 index a5da8ffc..00000000 --- a/powerline/config_files/colorschemes/ipython/default.json +++ /dev/null @@ -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": [] } - } -} diff --git a/powerline/config_files/colorschemes/shell/__main__.json b/powerline/config_files/colorschemes/shell/__main__.json index c8c2aaa2..6e3856f5 100644 --- a/powerline/config_files/colorschemes/shell/__main__.json +++ b/powerline/config_files/colorschemes/shell/__main__.json @@ -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" } } diff --git a/powerline/config_files/colorschemes/shell/default.json b/powerline/config_files/colorschemes/shell/default.json index 09f3d211..1126febf 100644 --- a/powerline/config_files/colorschemes/shell/default.json +++ b/powerline/config_files/colorschemes/shell/default.json @@ -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": [] } diff --git a/powerline/config_files/colorschemes/shell/solarized.json b/powerline/config_files/colorschemes/shell/solarized.json index 43b1666a..69dcab1d 100644 --- a/powerline/config_files/colorschemes/shell/solarized.json +++ b/powerline/config_files/colorschemes/shell/solarized.json @@ -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": { diff --git a/powerline/config_files/colorschemes/solarized.json b/powerline/config_files/colorschemes/solarized.json index 9730e825..6a573dcd 100644 --- a/powerline/config_files/colorschemes/solarized.json +++ b/powerline/config_files/colorschemes/solarized.json @@ -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": [] } } } diff --git a/powerline/segments/vim/plugin/commandt.py b/powerline/segments/vim/plugin/commandt.py index 7b8007f3..7e5262ef 100644 --- a/powerline/segments/vim/plugin/commandt.py +++ b/powerline/segments/vim/plugin/commandt.py @@ -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') From f5d96743fe1bdd0880e1222775107ebed3c2ac40 Mon Sep 17 00:00:00 2001 From: ZyX Date: Tue, 27 Jan 2015 20:13:19 +0300 Subject: [PATCH 12/43] Move IPython prompt and rcsh renderers into a separate module Some applications that use readline use same variants of telling it where highlighting starts and ends. This module will also be used for pdb. --- powerline/bindings/rc/powerline.rc | 2 +- powerline/renderers/ipython/__init__.py | 6 +++--- powerline/renderers/shell/rcsh.py | 9 ++------- powerline/renderers/shell/readline.py | 14 ++++++++++++++ 4 files changed, 20 insertions(+), 11 deletions(-) create mode 100644 powerline/renderers/shell/readline.py diff --git a/powerline/bindings/rc/powerline.rc b/powerline/bindings/rc/powerline.rc index 732d40c8..15b313a9 100644 --- a/powerline/bindings/rc/powerline.rc +++ b/powerline/bindings/rc/powerline.rc @@ -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 ) diff --git a/powerline/renderers/ipython/__init__.py b/powerline/renderers/ipython/__init__.py index 3547fd2e..a84418f1 100644 --- a/powerline/renderers/ipython/__init__.py +++ b/powerline/renderers/ipython/__init__.py @@ -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): diff --git a/powerline/renderers/shell/rcsh.py b/powerline/renderers/shell/rcsh.py index 4bc01412..75ccb223 100644 --- a/powerline/renderers/shell/rcsh.py +++ b/powerline/renderers/shell/rcsh.py @@ -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 diff --git a/powerline/renderers/shell/readline.py b/powerline/renderers/shell/readline.py new file mode 100644 index 00000000..a72dff05 --- /dev/null +++ b/powerline/renderers/shell/readline.py @@ -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 From 36d64bc3da41c12f08883debfc00a510998703f7 Mon Sep 17 00:00:00 2001 From: ZyX Date: Tue, 27 Jan 2015 20:22:38 +0300 Subject: [PATCH 13/43] Remove unused `get_segment_info` method --- powerline/vim.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/powerline/vim.py b/powerline/vim.py index b93788a8..d4f5c2d6 100644 --- a/powerline/vim.py +++ b/powerline/vim.py @@ -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() From 7250cd4bd85069aa802a5987fc39466444ca97db Mon Sep 17 00:00:00 2001 From: ZyX Date: Tue, 27 Jan 2015 20:24:45 +0300 Subject: [PATCH 14/43] Use `:py:meth` for referring to methods --- powerline/renderer.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/powerline/renderer.py b/powerline/renderer.py index 6d9b56a7..c03c42e8 100644 --- a/powerline/renderer.py +++ b/powerline/renderer.py @@ -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 '') From 9bbec772e063326466f6b175c338f5058e069213 Mon Sep 17 00:00:00 2001 From: ZyX Date: Tue, 27 Jan 2015 22:15:26 +0300 Subject: [PATCH 15/43] Add support for pdb prompt Note: pdbpp is not supported, it has lots of problems with unicode<-->str conversion (either explicit or implicit). --- docs/source/develop/segments.rst | 6 +++ docs/source/usage/other.rst | 27 ++++++++++ powerline/bindings/pdb/__init__.py | 54 +++++++++++++++++++ powerline/bindings/pdb/__main__.py | 29 ++++++++++ powerline/config_files/config.json | 4 ++ .../config_files/themes/pdb/default.json | 21 ++++++++ powerline/pdb.py | 19 +++++++ powerline/renderers/pdb.py | 34 ++++++++++++ 8 files changed, 194 insertions(+) create mode 100644 powerline/bindings/pdb/__init__.py create mode 100755 powerline/bindings/pdb/__main__.py create mode 100644 powerline/config_files/themes/pdb/default.json create mode 100644 powerline/pdb.py create mode 100644 powerline/renderers/pdb.py diff --git a/docs/source/develop/segments.rst b/docs/source/develop/segments.rst index 509eb7f7..a16f067d 100644 --- a/docs/source/develop/segments.rst +++ b/docs/source/develop/segments.rst @@ -469,6 +469,12 @@ 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. + Segment class ============= diff --git a/docs/source/usage/other.rst b/docs/source/usage/other.rst index cbdab712..69144777 100644 --- a/docs/source/usage/other.rst +++ b/docs/source/usage/other.rst @@ -124,3 +124,30 @@ 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 +========== + +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``. diff --git a/powerline/bindings/pdb/__init__.py b/powerline/bindings/pdb/__init__.py new file mode 100644 index 00000000..8df3886e --- /dev/null +++ b/powerline/bindings/pdb/__init__.py @@ -0,0 +1,54 @@ +# vim:fileencoding=utf-8:noet +from __future__ import (unicode_literals, division, absolute_import, print_function) + +from powerline.pdb import PDBPowerline +from powerline.lib.encoding import get_preferred_output_encoding + + +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. + ''' + encoding = get_preferred_output_encoding() + + @property + def prompt(self): + try: + powerline = self.powerline + except AttributeError: + powerline = PDBPowerline() + powerline.setup(self) + self.powerline = powerline + ret = powerline.render(side='left') + if not isinstance(ret, str): + # Python-2 + ret = ret.encode(encoding) + return ret + + @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 diff --git a/powerline/bindings/pdb/__main__.py b/powerline/bindings/pdb/__main__.py new file mode 100755 index 00000000..78527500 --- /dev/null +++ b/powerline/bindings/pdb/__main__.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python +# vim:fileencoding=utf-8:noet +from __future__ import (unicode_literals, division, absolute_import, print_function) + +import pdb + +from powerline.bindings.pdb import use_powerline_prompt + + +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() + + +if __name__ == '__main__': + main() diff --git a/powerline/config_files/config.json b/powerline/config_files/config.json index 9502129a..bd2cf2bb 100644 --- a/powerline/config_files/config.json +++ b/powerline/config_files/config.json @@ -12,6 +12,10 @@ "in2": "in2" } }, + "pdb": { + "colorscheme": "default", + "theme": "default" + }, "shell": { "colorscheme": "default", "theme": "default", diff --git a/powerline/config_files/themes/pdb/default.json b/powerline/config_files/themes/pdb/default.json new file mode 100644 index 00000000..55505f67 --- /dev/null +++ b/powerline/config_files/themes/pdb/default.json @@ -0,0 +1,21 @@ +{ + "segments": { + "left": [ + { + "function": "powerline.segments.common.env.virtualenv", + "priority": 10 + }, + { + "type": "string", + "contents": "In [", + "draw_soft_divider": false, + "highlight_groups": ["virtualenv"] + }, + { + "type": "string", + "contents": "]", + "highlight_groups": ["virtualenv"] + } + ] + } +} diff --git a/powerline/pdb.py b/powerline/pdb.py new file mode 100644 index 00000000..3a986dfb --- /dev/null +++ b/powerline/pdb.py @@ -0,0 +1,19 @@ +# vim:fileencoding=utf-8:noet +from __future__ import (unicode_literals, division, absolute_import, print_function) + +from powerline import Powerline + + +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) diff --git a/powerline/renderers/pdb.py b/powerline/renderers/pdb.py new file mode 100644 index 00000000..d514e490 --- /dev/null +++ b/powerline/renderers/pdb.py @@ -0,0 +1,34 @@ +# vim:fileencoding=utf-8:noet +from __future__ import (unicode_literals, division, absolute_import, print_function) + +from powerline.renderers.shell.readline import ReadlineRenderer +from powerline.renderer import Renderer + + +class PDBRenderer(ReadlineRenderer): + '''PDB-specific powerline renderer + ''' + pdb = None + + def get_segment_info(self, segment_info, mode): + r = self.segment_info.copy() + r['pdb'] = self.pdb + 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 + ` dictionary. + ''' + self.pdb = pdb + + def render(self, **kwargs): + return Renderer.render(self, **kwargs) + + +renderer = PDBRenderer From b0d295301b36eb1b39736c924919676b263b1510 Mon Sep 17 00:00:00 2001 From: ZyX Date: Tue, 27 Jan 2015 22:38:50 +0300 Subject: [PATCH 16/43] Add some hacks to make code compatible with pdbpp --- powerline/bindings/pdb/__init__.py | 98 +++++++++++++++++++++++++++--- 1 file changed, 91 insertions(+), 7 deletions(-) diff --git a/powerline/bindings/pdb/__init__.py b/powerline/bindings/pdb/__init__.py index 8df3886e..34040751 100644 --- a/powerline/bindings/pdb/__init__.py +++ b/powerline/bindings/pdb/__init__.py @@ -1,8 +1,98 @@ # vim:fileencoding=utf-8:noet from __future__ import (unicode_literals, division, absolute_import, print_function) +import sys + 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 that’s not always the + # case. + class PowerlineRenderBytesResult(bytes): + def __new__(cls, s, encoding=None): + encoding = encoding or s.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 ''.join(( + arg + if isinstance(arg, unicode) + else arg.decode(encoding) + for arg in args + )) + 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) +else: + PowerlineRenderResult = str def use_powerline_prompt(cls): @@ -15,8 +105,6 @@ def use_powerline_prompt(cls): ``cls`` argument or a class derived from it. Latter is used to turn old-style classes into new-style classes. ''' - encoding = get_preferred_output_encoding() - @property def prompt(self): try: @@ -25,11 +113,7 @@ def use_powerline_prompt(cls): powerline = PDBPowerline() powerline.setup(self) self.powerline = powerline - ret = powerline.render(side='left') - if not isinstance(ret, str): - # Python-2 - ret = ret.encode(encoding) - return ret + return PowerlineRenderResult(powerline.render(side='left')) @prompt.setter def prompt(self, _): From cac9754fcfeb5728354d260665c7f9205d61fa0c Mon Sep 17 00:00:00 2001 From: ZyX Date: Sat, 31 Jan 2015 13:43:24 +0300 Subject: [PATCH 17/43] Add pdb-specific segments and make default theme use them --- docs/source/configuration/listers.rst | 6 ++ docs/source/configuration/segments/pdb.rst | 7 +++ docs/source/develop/segments.rst | 9 +++ .../colorschemes/pdb/__main__.json | 5 ++ .../colorschemes/pdb/default.json | 8 +++ .../config_files/themes/pdb/default.json | 28 +++++---- powerline/listers/pdb.py | 37 +++++++++++ powerline/renderers/pdb.py | 5 ++ powerline/segments/pdb.py | 61 +++++++++++++++++++ 9 files changed, 155 insertions(+), 11 deletions(-) create mode 100644 docs/source/configuration/segments/pdb.rst create mode 100644 powerline/config_files/colorschemes/pdb/__main__.json create mode 100644 powerline/config_files/colorschemes/pdb/default.json create mode 100644 powerline/listers/pdb.py create mode 100644 powerline/segments/pdb.py diff --git a/docs/source/configuration/listers.rst b/docs/source/configuration/listers.rst index dc544b91..04e5371e 100644 --- a/docs/source/configuration/listers.rst +++ b/docs/source/configuration/listers.rst @@ -23,3 +23,9 @@ Vim listers .. automodule:: powerline.listers.vim :members: + +Pdb listers +----------- + +.. automodule:: powerline.listers.pdb + :members: diff --git a/docs/source/configuration/segments/pdb.rst b/docs/source/configuration/segments/pdb.rst new file mode 100644 index 00000000..b9a104b2 --- /dev/null +++ b/docs/source/configuration/segments/pdb.rst @@ -0,0 +1,7 @@ +************ +PDB segments +************ + +.. automodule:: powerline.segments.pdb + :members: + diff --git a/docs/source/develop/segments.rst b/docs/source/develop/segments.rst index a16f067d..3fea00a2 100644 --- a/docs/source/develop/segments.rst +++ b/docs/source/develop/segments.rst @@ -475,6 +475,15 @@ 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 ============= diff --git a/powerline/config_files/colorschemes/pdb/__main__.json b/powerline/config_files/colorschemes/pdb/__main__.json new file mode 100644 index 00000000..b7ce28f0 --- /dev/null +++ b/powerline/config_files/colorschemes/pdb/__main__.json @@ -0,0 +1,5 @@ +{ + "groups": { + "current_context": "current_code_name" + } +} diff --git a/powerline/config_files/colorschemes/pdb/default.json b/powerline/config_files/colorschemes/pdb/default.json new file mode 100644 index 00000000..56f9020f --- /dev/null +++ b/powerline/config_files/colorschemes/pdb/default.json @@ -0,0 +1,8 @@ +{ + "groups": { + "current_line": { "fg": "gray10", "bg": "gray4", "attrs": ["bold"] }, + "current_file": { "fg": "gray10", "bg": "gray4", "attrs": ["bold"] }, + "current_code_name": { "fg": "gray9", "bg": "gray4", "attrs": ["bold"] }, + "stack_depth": { "fg": "gray1", "bg": "gray10", "attrs": ["bold"] } + } +} diff --git a/powerline/config_files/themes/pdb/default.json b/powerline/config_files/themes/pdb/default.json index 55505f67..dcae1080 100644 --- a/powerline/config_files/themes/pdb/default.json +++ b/powerline/config_files/themes/pdb/default.json @@ -1,20 +1,26 @@ { + "default_module": "powerline.segments.pdb", "segments": { "left": [ { - "function": "powerline.segments.common.env.virtualenv", - "priority": 10 + "function": "stack_depth" }, { - "type": "string", - "contents": "In [", - "draw_soft_divider": false, - "highlight_groups": ["virtualenv"] - }, - { - "type": "string", - "contents": "]", - "highlight_groups": ["virtualenv"] + "type": "segment_list", + "function": "powerline.listers.pdb.frame_lister", + "segments": [ + { + "function": "current_file", + "after": ":" + }, + { + "function": "current_line", + "after": " " + }, + { + "function": "current_code_name" + } + ] } ] } diff --git a/powerline/listers/pdb.py b/powerline/listers/pdb.py new file mode 100644 index 00000000..24e11eaf --- /dev/null +++ b/powerline/listers/pdb.py @@ -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 + ) diff --git a/powerline/renderers/pdb.py b/powerline/renderers/pdb.py index d514e490..828223a5 100644 --- a/powerline/renderers/pdb.py +++ b/powerline/renderers/pdb.py @@ -9,10 +9,13 @@ 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): @@ -28,6 +31,8 @@ class PDBRenderer(ReadlineRenderer): 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) diff --git a/powerline/segments/pdb.py b/powerline/segments/pdb.py new file mode 100644 index 00000000..bd6a38b7 --- /dev/null +++ b/powerline/segments/pdb.py @@ -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 + ````. + ''' + name = segment_info['curframe'].f_code.co_name + if name == '': + 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'])) From 47dbdd571ddd18d38dc91b843a2b116010761e3a Mon Sep 17 00:00:00 2001 From: ZyX Date: Sat, 31 Jan 2015 17:58:14 +0300 Subject: [PATCH 18/43] Add pdb integration tests --- tests/test_shells/input.pdb | 94 +++++++++++++ tests/test_shells/pdb-main.py | 24 ++++ tests/test_shells/pdb-script.py | 38 ++++++ tests/test_shells/pdb.ok | 230 ++++++++++++++++++++++++++++++++ tests/test_shells/postproc.py | 16 ++- tests/test_shells/test.sh | 40 +++++- 6 files changed, 436 insertions(+), 6 deletions(-) create mode 100644 tests/test_shells/input.pdb create mode 100644 tests/test_shells/pdb-main.py create mode 100644 tests/test_shells/pdb-script.py create mode 100644 tests/test_shells/pdb.ok diff --git a/tests/test_shells/input.pdb b/tests/test_shells/input.pdb new file mode 100644 index 00000000..9b1aad49 --- /dev/null +++ b/tests/test_shells/input.pdb @@ -0,0 +1,94 @@ +s + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/test_shells/pdb-main.py b/tests/test_shells/pdb-main.py new file mode 100644 index 00000000..37af785f --- /dev/null +++ b/tests/test_shells/pdb-main.py @@ -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}) diff --git a/tests/test_shells/pdb-script.py b/tests/test_shells/pdb-script.py new file mode 100644 index 00000000..40db5e8d --- /dev/null +++ b/tests/test_shells/pdb-script.py @@ -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() diff --git a/tests/test_shells/pdb.ok b/tests/test_shells/pdb.ok new file mode 100644 index 00000000..181ef636 --- /dev/null +++ b/tests/test_shells/pdb.ok @@ -0,0 +1,230 @@ +--Call-- +-> def nop(_): + 2  :1   pdb-script.py:2    +-> def nop(_): + 2  :1   pdb-script.py:2    +-> class Foo(object): + 2  :1   pdb-script.py:6    +--Call-- +-> class Foo(object): + 3  :1   pdb-script.py:6   pdb-script.py:6 Foo   +-> class Foo(object): + 3  :1   pdb-script.py:6   pdb-script.py:6 Foo   +-> def __init__(self): + 3  :1   pdb-script.py:6   pdb-script.py:7 Foo   +-> @classmethod + 3  :1   pdb-script.py:6   pdb-script.py:13 Foo   +-> @staticmethod + 3  :1   pdb-script.py:6   pdb-script.py:17 Foo   +-> def bra(self): + 3  :1   pdb-script.py:6   pdb-script.py:21 Foo   +--Return-- +-> def bra(self): + 3  :1   pdb-script.py:6   pdb-script.py:21 Foo   +-> def brah(): + 2  :1   pdb-script.py:25    +-> f = Foo() + 2  :1   pdb-script.py:29    +--Call-- +-> def __init__(self): + 3  :1   pdb-script.py:29   pdb-script.py:7 __init__   +-> nop('__init__') + 3  :1   pdb-script.py:29   pdb-script.py:8 __init__   +--Call-- +-> def nop(_): + 4  pdb-script.py:29   pdb-script.py:8 __init__  pdb-script.py:2 nop   +-> pass + 4  pdb-script.py:29   pdb-script.py:8 __init__  pdb-script.py:3 nop   +--Return-- +-> pass + 4  pdb-script.py:29   pdb-script.py:8 __init__  pdb-script.py:3 nop   +-> self.bar() + 3  :1   pdb-script.py:29   pdb-script.py:9 __init__   +--Call-- +-> @classmethod + 4  pdb-script.py:29   pdb-script.py:9 __init__  pdb-script.py:13 bar   +-> nop(cls.__name__) + 4  pdb-script.py:29   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   pdb-script.py:9 __init__  pdb-script.py:15 bar   +-> self.baz() + 3  :1   pdb-script.py:29   pdb-script.py:10 __init__   +--Call-- +-> @staticmethod + 4  pdb-script.py:29   pdb-script.py:10 __init__  pdb-script.py:17 baz   +-> nop(1) + 4  pdb-script.py:29   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   pdb-script.py:10 __init__  pdb-script.py:19 baz   +-> self.bra() + 3  :1   pdb-script.py:29   pdb-script.py:11 __init__   +--Call-- +-> def bra(self): + 4  pdb-script.py:29   pdb-script.py:11 __init__  pdb-script.py:21 bra   +-> nop(self.__class__.__name__) + 4  pdb-script.py:29   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   pdb-script.py:11 __init__  pdb-script.py:22 bra   +--Return-- +-> self.bra() + 3  :1   pdb-script.py:29   pdb-script.py:11 __init__   +-> Foo.bar() + 2  :1   pdb-script.py:30    +--Call-- +-> @classmethod + 3  :1   pdb-script.py:30   pdb-script.py:13 bar   +-> nop(cls.__name__) + 3  :1   pdb-script.py:30   pdb-script.py:15 bar   +--Call-- +-> def nop(_): + 4  pdb-script.py:30   pdb-script.py:15 bar  pdb-script.py:2 nop   +-> pass + 4  pdb-script.py:30   pdb-script.py:15 bar  pdb-script.py:3 nop   +--Return-- +-> pass + 4  pdb-script.py:30   pdb-script.py:15 bar  pdb-script.py:3 nop   +--Return-- +-> nop(cls.__name__) + 3  :1   pdb-script.py:30   pdb-script.py:15 bar   +-> Foo.baz() + 2  :1   pdb-script.py:31    +--Call-- +-> @staticmethod + 3  :1   pdb-script.py:31   pdb-script.py:17 baz   +-> nop(1) + 3  :1   pdb-script.py:31   pdb-script.py:19 baz   +--Call-- +-> def nop(_): + 4  pdb-script.py:31   pdb-script.py:19 baz  pdb-script.py:2 nop   +-> pass + 4  pdb-script.py:31   pdb-script.py:19 baz  pdb-script.py:3 nop   +--Return-- +-> pass + 4  pdb-script.py:31   pdb-script.py:19 baz  pdb-script.py:3 nop   +--Return-- +-> nop(1) + 3  :1   pdb-script.py:31   pdb-script.py:19 baz   +-> Foo.bra(f) + 2  :1   pdb-script.py:32    +--Call-- +-> def bra(self): + 3  :1   pdb-script.py:32   pdb-script.py:21 bra   +-> nop(self.__class__.__name__) + 3  :1   pdb-script.py:32   pdb-script.py:22 bra   +--Call-- +-> def nop(_): + 4  pdb-script.py:32   pdb-script.py:22 bra  pdb-script.py:2 nop   +-> pass + 4  pdb-script.py:32   pdb-script.py:22 bra  pdb-script.py:3 nop   +--Return-- +-> pass + 4  pdb-script.py:32   pdb-script.py:22 bra  pdb-script.py:3 nop   +--Return-- +-> nop(self.__class__.__name__) + 3  :1   pdb-script.py:32   pdb-script.py:22 bra   +-> f.bar() + 2  :1   pdb-script.py:34    +--Call-- +-> @classmethod + 3  :1   pdb-script.py:34   pdb-script.py:13 bar   +-> nop(cls.__name__) + 3  :1   pdb-script.py:34   pdb-script.py:15 bar   +--Call-- +-> def nop(_): + 4  pdb-script.py:34   pdb-script.py:15 bar  pdb-script.py:2 nop   +-> pass + 4  pdb-script.py:34   pdb-script.py:15 bar  pdb-script.py:3 nop   +--Return-- +-> pass + 4  pdb-script.py:34   pdb-script.py:15 bar  pdb-script.py:3 nop   +--Return-- +-> nop(cls.__name__) + 3  :1   pdb-script.py:34   pdb-script.py:15 bar   +-> f.baz() + 2  :1   pdb-script.py:35    +--Call-- +-> @staticmethod + 3  :1   pdb-script.py:35   pdb-script.py:17 baz   +-> nop(1) + 3  :1   pdb-script.py:35   pdb-script.py:19 baz   +--Call-- +-> def nop(_): + 4  pdb-script.py:35   pdb-script.py:19 baz  pdb-script.py:2 nop   +-> pass + 4  pdb-script.py:35   pdb-script.py:19 baz  pdb-script.py:3 nop   +--Return-- +-> pass + 4  pdb-script.py:35   pdb-script.py:19 baz  pdb-script.py:3 nop   +--Return-- +-> nop(1) + 3  :1   pdb-script.py:35   pdb-script.py:19 baz   +-> f.bra() + 2  :1   pdb-script.py:36    +--Call-- +-> def bra(self): + 3  :1   pdb-script.py:36   pdb-script.py:21 bra   +-> nop(self.__class__.__name__) + 3  :1   pdb-script.py:36   pdb-script.py:22 bra   +--Call-- +-> def nop(_): + 4  pdb-script.py:36   pdb-script.py:22 bra  pdb-script.py:2 nop   +-> pass + 4  pdb-script.py:36   pdb-script.py:22 bra  pdb-script.py:3 nop   +--Return-- +-> pass + 4  pdb-script.py:36   pdb-script.py:22 bra  pdb-script.py:3 nop   +--Return-- +-> nop(self.__class__.__name__) + 3  :1   pdb-script.py:36   pdb-script.py:22 bra   +-> brah() + 2  :1   pdb-script.py:38    +--Call-- +-> def brah(): + 3  :1   pdb-script.py:38   pdb-script.py:25 brah   +-> nop('brah') + 3  :1   pdb-script.py:38   pdb-script.py:26 brah   +--Call-- +-> def nop(_): + 4  pdb-script.py:38   pdb-script.py:26 brah  pdb-script.py:2 nop   +-> pass + 4  pdb-script.py:38   pdb-script.py:26 brah  pdb-script.py:3 nop   +--Return-- +-> pass + 4  pdb-script.py:38   pdb-script.py:26 brah  pdb-script.py:3 nop   +--Return-- +-> nop('brah') + 3  :1   pdb-script.py:38   pdb-script.py:26 brah   +--Return-- +-> brah() + 2  :1   pdb-script.py:38    +--Return-- + 1  :1    +-> self.quitting = True + 0   diff --git a/tests/test_shells/postproc.py b/tests/test_shells/postproc.py index ff9c5748..7b9d330e 100755 --- a/tests/test_shells/postproc.py +++ b/tests/test_shells/postproc.py @@ -34,9 +34,14 @@ 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) + if shell == 'pdb': + found_cd = (i > 1) + else: + found_cd = ('cd tests/shell/3rd' in line) continue if 'true is the last line' in line: break @@ -101,4 +106,13 @@ 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.startswith(('>',)): + line = '' + elif line == '-> self.quitting = 1\n': + line = '-> self.quitting = True\n' W.write(line) diff --git a/tests/test_shells/test.sh b/tests/test_shells/test.sh index 81b5edb2..7f01e405 100755 --- a/tests/test_shells/test.sh +++ b/tests/test_shells/test.sh @@ -1,5 +1,7 @@ #!/bin/sh -set -e +. tests/bot-ci/scripts/common/main.sh +set +x + : ${PYTHON:=python} FAIL_SUMMARY="" FAILED=0 @@ -113,10 +115,18 @@ do_run_test() { sleep 0.1s 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 +136,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 +197,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 @@ -256,6 +271,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 @@ -418,6 +436,18 @@ if ( test "x${ONLY_SHELL}" = "x" || test "x${ONLY_SHELL}" = "xzsh" ) \ fi fi +if ( test "x${ONLY_SHELL}" = "x" || test "x${ONLY_SHELL}" = "xpdb" ) \ + && ( test "x${ONLY_TEST_TYPE}" = "x" || test "x${ONLY_TEST_TYPE}" = "xsubclass" ) +then + if ! ( test "$PYTHON_IMPLEMENTATION" = "PyPy" && test "$PYTHON_VERSION_MAJOR" = 2 ) ; then + echo "> pdb subclass" + if ! run_test pdb subclass $PDB_PYTHON "$PWD/tests/test_shells/pdb-main.py" ; then + FAILED=1 + FAIL_SUMMARY="${FAIL_SUMMARY}${NL}T pdb $PDB_PYTHON -m $PWD/tests/test_shells/pdb-main.py" + 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. From ef02ab70fb27d45ac495bfc4a140c9a9857c2957 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sat, 31 Jan 2015 18:10:19 +0300 Subject: [PATCH 19/43] Also test powerline.bindings.pdb module --- tests/test_shells/input.pdb | 7 +- tests/test_shells/pdb.module.ok | 224 ++++++++++++++++++ tests/test_shells/{pdb.ok => pdb.subclass.ok} | 7 - tests/test_shells/test.sh | 24 +- 4 files changed, 241 insertions(+), 21 deletions(-) create mode 100644 tests/test_shells/pdb.module.ok rename tests/test_shells/{pdb.ok => pdb.subclass.ok} (98%) diff --git a/tests/test_shells/input.pdb b/tests/test_shells/input.pdb index 9b1aad49..e9ac498c 100644 --- a/tests/test_shells/input.pdb +++ b/tests/test_shells/input.pdb @@ -86,9 +86,4 @@ s - - - - - - + diff --git a/tests/test_shells/pdb.module.ok b/tests/test_shells/pdb.module.ok new file mode 100644 index 00000000..629d2993 --- /dev/null +++ b/tests/test_shells/pdb.module.ok @@ -0,0 +1,224 @@ + 1  pdb-script.py:2   s +-> class Foo(object): + 1  pdb-script.py:6    +--Call-- +-> class Foo(object): + 2  pdb-script.py:6   pdb-script.py:6 Foo   +-> class Foo(object): + 2  pdb-script.py:6   pdb-script.py:6 Foo   +-> def __init__(self): + 2  pdb-script.py:6   pdb-script.py:7 Foo   +-> @classmethod + 2  pdb-script.py:6   pdb-script.py:13 Foo   +-> @staticmethod + 2  pdb-script.py:6   pdb-script.py:17 Foo   +-> def bra(self): + 2  pdb-script.py:6   pdb-script.py:21 Foo   +--Return-- +-> def bra(self): + 2  pdb-script.py:6   pdb-script.py:21 Foo   +-> def brah(): + 1  pdb-script.py:25    +-> f = Foo() + 1  pdb-script.py:29    +--Call-- +-> def __init__(self): + 2  pdb-script.py:29   pdb-script.py:7 __init__   +-> nop('__init__') + 2  pdb-script.py:29   pdb-script.py:8 __init__   +--Call-- +-> def nop(_): + 3  pdb-script.py:29   pdb-script.py:8 __init__  pdb-script.py:2 nop   +-> pass + 3  pdb-script.py:29   pdb-script.py:8 __init__  pdb-script.py:3 nop   +--Return-- +-> pass + 3  pdb-script.py:29   pdb-script.py:8 __init__  pdb-script.py:3 nop   +-> self.bar() + 2  pdb-script.py:29   pdb-script.py:9 __init__   +--Call-- +-> @classmethod + 3  pdb-script.py:29   pdb-script.py:9 __init__  pdb-script.py:13 bar   +-> nop(cls.__name__) + 3  pdb-script.py:29   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   pdb-script.py:9 __init__  pdb-script.py:15 bar   +-> self.baz() + 2  pdb-script.py:29   pdb-script.py:10 __init__   +--Call-- +-> @staticmethod + 3  pdb-script.py:29   pdb-script.py:10 __init__  pdb-script.py:17 baz   +-> nop(1) + 3  pdb-script.py:29   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   pdb-script.py:10 __init__  pdb-script.py:19 baz   +-> self.bra() + 2  pdb-script.py:29   pdb-script.py:11 __init__   +--Call-- +-> def bra(self): + 3  pdb-script.py:29   pdb-script.py:11 __init__  pdb-script.py:21 bra   +-> nop(self.__class__.__name__) + 3  pdb-script.py:29   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   pdb-script.py:11 __init__  pdb-script.py:22 bra   +--Return-- +-> self.bra() + 2  pdb-script.py:29   pdb-script.py:11 __init__   +-> Foo.bar() + 1  pdb-script.py:30    +--Call-- +-> @classmethod + 2  pdb-script.py:30   pdb-script.py:13 bar   +-> nop(cls.__name__) + 2  pdb-script.py:30   pdb-script.py:15 bar   +--Call-- +-> def nop(_): + 3  pdb-script.py:30   pdb-script.py:15 bar  pdb-script.py:2 nop   +-> pass + 3  pdb-script.py:30   pdb-script.py:15 bar  pdb-script.py:3 nop   +--Return-- +-> pass + 3  pdb-script.py:30   pdb-script.py:15 bar  pdb-script.py:3 nop   +--Return-- +-> nop(cls.__name__) + 2  pdb-script.py:30   pdb-script.py:15 bar   +-> Foo.baz() + 1  pdb-script.py:31    +--Call-- +-> @staticmethod + 2  pdb-script.py:31   pdb-script.py:17 baz   +-> nop(1) + 2  pdb-script.py:31   pdb-script.py:19 baz   +--Call-- +-> def nop(_): + 3  pdb-script.py:31   pdb-script.py:19 baz  pdb-script.py:2 nop   +-> pass + 3  pdb-script.py:31   pdb-script.py:19 baz  pdb-script.py:3 nop   +--Return-- +-> pass + 3  pdb-script.py:31   pdb-script.py:19 baz  pdb-script.py:3 nop   +--Return-- +-> nop(1) + 2  pdb-script.py:31   pdb-script.py:19 baz   +-> Foo.bra(f) + 1  pdb-script.py:32    +--Call-- +-> def bra(self): + 2  pdb-script.py:32   pdb-script.py:21 bra   +-> nop(self.__class__.__name__) + 2  pdb-script.py:32   pdb-script.py:22 bra   +--Call-- +-> def nop(_): + 3  pdb-script.py:32   pdb-script.py:22 bra  pdb-script.py:2 nop   +-> pass + 3  pdb-script.py:32   pdb-script.py:22 bra  pdb-script.py:3 nop   +--Return-- +-> pass + 3  pdb-script.py:32   pdb-script.py:22 bra  pdb-script.py:3 nop   +--Return-- +-> nop(self.__class__.__name__) + 2  pdb-script.py:32   pdb-script.py:22 bra   +-> f.bar() + 1  pdb-script.py:34    +--Call-- +-> @classmethod + 2  pdb-script.py:34   pdb-script.py:13 bar   +-> nop(cls.__name__) + 2  pdb-script.py:34   pdb-script.py:15 bar   +--Call-- +-> def nop(_): + 3  pdb-script.py:34   pdb-script.py:15 bar  pdb-script.py:2 nop   +-> pass + 3  pdb-script.py:34   pdb-script.py:15 bar  pdb-script.py:3 nop   +--Return-- +-> pass + 3  pdb-script.py:34   pdb-script.py:15 bar  pdb-script.py:3 nop   +--Return-- +-> nop(cls.__name__) + 2  pdb-script.py:34   pdb-script.py:15 bar   +-> f.baz() + 1  pdb-script.py:35    +--Call-- +-> @staticmethod + 2  pdb-script.py:35   pdb-script.py:17 baz   +-> nop(1) + 2  pdb-script.py:35   pdb-script.py:19 baz   +--Call-- +-> def nop(_): + 3  pdb-script.py:35   pdb-script.py:19 baz  pdb-script.py:2 nop   +-> pass + 3  pdb-script.py:35   pdb-script.py:19 baz  pdb-script.py:3 nop   +--Return-- +-> pass + 3  pdb-script.py:35   pdb-script.py:19 baz  pdb-script.py:3 nop   +--Return-- +-> nop(1) + 2  pdb-script.py:35   pdb-script.py:19 baz   +-> f.bra() + 1  pdb-script.py:36    +--Call-- +-> def bra(self): + 2  pdb-script.py:36   pdb-script.py:21 bra   +-> nop(self.__class__.__name__) + 2  pdb-script.py:36   pdb-script.py:22 bra   +--Call-- +-> def nop(_): + 3  pdb-script.py:36   pdb-script.py:22 bra  pdb-script.py:2 nop   +-> pass + 3  pdb-script.py:36   pdb-script.py:22 bra  pdb-script.py:3 nop   +--Return-- +-> pass + 3  pdb-script.py:36   pdb-script.py:22 bra  pdb-script.py:3 nop   +--Return-- +-> nop(self.__class__.__name__) + 2  pdb-script.py:36   pdb-script.py:22 bra   +-> brah() + 1  pdb-script.py:38    +--Call-- +-> def brah(): + 2  pdb-script.py:38   pdb-script.py:25 brah   +-> nop('brah') + 2  pdb-script.py:38   pdb-script.py:26 brah   +--Call-- +-> def nop(_): + 3  pdb-script.py:38   pdb-script.py:26 brah  pdb-script.py:2 nop   +-> pass + 3  pdb-script.py:38   pdb-script.py:26 brah  pdb-script.py:3 nop   +--Return-- +-> pass + 3  pdb-script.py:38   pdb-script.py:26 brah  pdb-script.py:3 nop   +--Return-- +-> nop('brah') + 2  pdb-script.py:38   pdb-script.py:26 brah   +--Return-- +-> brah() + 1  pdb-script.py:38    +--Return-- + 0   diff --git a/tests/test_shells/pdb.ok b/tests/test_shells/pdb.subclass.ok similarity index 98% rename from tests/test_shells/pdb.ok rename to tests/test_shells/pdb.subclass.ok index 181ef636..41bda2da 100644 --- a/tests/test_shells/pdb.ok +++ b/tests/test_shells/pdb.subclass.ok @@ -221,10 +221,3 @@ --Return-- -> nop('brah')  3  :1   pdb-script.py:38   pdb-script.py:26 brah   ---Return-- --> brah() - 2  :1   pdb-script.py:38    ---Return-- - 1  :1    --> self.quitting = True - 0   diff --git a/tests/test_shells/test.sh b/tests/test_shells/test.sh index 7f01e405..830dcb0a 100755 --- a/tests/test_shells/test.sh +++ b/tests/test_shells/test.sh @@ -122,7 +122,8 @@ do_run_test() { ) \ || ( \ test "x${SH}" = "xpdb" \ - && ( test "$PYTHON_VERSION_MAJOR" -eq 3 \ + && ( \ + test "$PYTHON_VERSION_MAJOR" -eq 3 \ && test "$PYTHON_VERSION_MINOR" -eq 2 \ && test "$PYTHON_IMPLEMENTATION" = "CPython" \ ) \ @@ -436,14 +437,21 @@ if ( test "x${ONLY_SHELL}" = "x" || test "x${ONLY_SHELL}" = "xzsh" ) \ fi fi -if ( test "x${ONLY_SHELL}" = "x" || test "x${ONLY_SHELL}" = "xpdb" ) \ - && ( test "x${ONLY_TEST_TYPE}" = "x" || test "x${ONLY_TEST_TYPE}" = "xsubclass" ) -then +if test "x${ONLY_SHELL}" = "x" || test "x${ONLY_SHELL}" = "xpdb" ; then if ! ( test "$PYTHON_IMPLEMENTATION" = "PyPy" && test "$PYTHON_VERSION_MAJOR" = 2 ) ; then - echo "> pdb subclass" - if ! run_test pdb subclass $PDB_PYTHON "$PWD/tests/test_shells/pdb-main.py" ; then - FAILED=1 - FAIL_SUMMARY="${FAIL_SUMMARY}${NL}T pdb $PDB_PYTHON -m $PWD/tests/test_shells/pdb-main.py" + 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" + if ! run_test module python $PDB_PYTHON -mpowerline.bindings.pdb "$PWD/tests/test_shells/pdb-script.py" ; then + FAILED=1 + FAIL_SUMMARY="${FAIL_SUMMARY}${NL}T pdb $PDB_PYTHON -mpowerline.bindings.pdb $PWD/tests/test_shells/pdb-script" + fi fi fi fi From deacb9ab0227abfd2cd32ae5da56ef42a1a9d05d Mon Sep 17 00:00:00 2001 From: ZyX Date: Sat, 31 Jan 2015 18:21:20 +0300 Subject: [PATCH 20/43] Add some methods to PowerlineRenderResult This is an attempt to fix PDB prompt on PyPy. Does not work. --- powerline/bindings/pdb/__init__.py | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/powerline/bindings/pdb/__init__.py b/powerline/bindings/pdb/__init__.py index 34040751..48b8a606 100644 --- a/powerline/bindings/pdb/__init__.py +++ b/powerline/bindings/pdb/__init__.py @@ -16,6 +16,8 @@ if sys.version_info < (3,): 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 @@ -57,12 +59,12 @@ if sys.version_info < (3,): @staticmethod def add(encoding, *args): if any((isinstance(arg, unicode) for arg in args)): - return ''.join(( + 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) @@ -91,6 +93,30 @@ if sys.version_info < (3,): 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 From 682a9ab5040e964c6a3aae72f7aac96901770872 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sat, 31 Jan 2015 18:21:33 +0300 Subject: [PATCH 21/43] Warn that PyPy is not supported --- docs/source/usage/other.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/source/usage/other.rst b/docs/source/usage/other.rst index 69144777..30f0ad02 100644 --- a/docs/source/usage/other.rst +++ b/docs/source/usage/other.rst @@ -151,3 +151,5 @@ class from :py:class:`pdb.Pdb` and decorate it with python -mpowerline.bindings.pdb path/to/script.py just like you used ``python -m pdb``. + +.. warning: PyPy is not supported, PyPy3 is. From 27291b5e0ea2aa7fb0f8c56f9e2e795b67f909e6 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sat, 31 Jan 2015 18:30:26 +0300 Subject: [PATCH 22/43] Force ASCII-only prompt when using PyPy --- docs/source/usage/other.rst | 5 ++++- powerline/pdb.py | 6 ++++++ powerline/renderers/pdb.py | 11 +++++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/docs/source/usage/other.rst b/docs/source/usage/other.rst index 30f0ad02..2e7d334d 100644 --- a/docs/source/usage/other.rst +++ b/docs/source/usage/other.rst @@ -152,4 +152,7 @@ class from :py:class:`pdb.Pdb` and decorate it with just like you used ``python -m pdb``. -.. warning: PyPy is not supported, PyPy3 is. +.. warning: + Using PyPy (not PyPy3) forces ASCII-only prompts. In other cases unicode + characters are allowed, even if you use `pdbpp + `_. diff --git a/powerline/pdb.py b/powerline/pdb.py index 3a986dfb..79915818 100644 --- a/powerline/pdb.py +++ b/powerline/pdb.py @@ -1,6 +1,9 @@ # vim:fileencoding=utf-8:noet from __future__ import (unicode_literals, division, absolute_import, print_function) +import sys +import platform + from powerline import Powerline @@ -17,3 +20,6 @@ class PDBPowerline(Powerline): def do_setup(self, pdb): self.update_renderer() self.renderer.set_pdb(pdb) + + if sys.version_info < (3,) and platform.python_implementation() == 'PyPy': + get_encoding = staticmethod(lambda: 'ascii') diff --git a/powerline/renderers/pdb.py b/powerline/renderers/pdb.py index 828223a5..040f0e1a 100644 --- a/powerline/renderers/pdb.py +++ b/powerline/renderers/pdb.py @@ -1,6 +1,9 @@ # 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 @@ -35,5 +38,13 @@ class PDBRenderer(ReadlineRenderer): 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 From f74320fba81d0388cf41a9781353b1ddd85f18eb Mon Sep 17 00:00:00 2001 From: ZyX Date: Sat, 31 Jan 2015 18:41:17 +0300 Subject: [PATCH 23/43] Add unit tests for pdb segments --- tests/test_segments.py | 48 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/tests/test_segments.py b/tests/test_segments.py index 73e4bb91..08fc520b 100644 --- a/tests/test_segments.py +++ b/tests/test_segments.py @@ -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=''))}, + **kwargs + ) + self.assertEqual(ccn(), '') + + def test_current_context(self): + pl = Pl() + cc = lambda **kwargs: pdb.current_context( + pl=pl, + segment_info={'curframe': Args(f_code=Args(co_name='', 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 From 5bc68b66fe8b830c0f775fbd15d81d1d1e4f6206 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sat, 31 Jan 2015 18:49:41 +0300 Subject: [PATCH 24/43] Define all groups in both default and solarized colorschemes --- powerline/config_files/colorschemes/pdb/__main__.json | 5 ++++- powerline/config_files/colorschemes/pdb/default.json | 5 +---- powerline/config_files/colorschemes/pdb/solarized.json | 5 +++++ 3 files changed, 10 insertions(+), 5 deletions(-) create mode 100644 powerline/config_files/colorschemes/pdb/solarized.json diff --git a/powerline/config_files/colorschemes/pdb/__main__.json b/powerline/config_files/colorschemes/pdb/__main__.json index b7ce28f0..01a51fe5 100644 --- a/powerline/config_files/colorschemes/pdb/__main__.json +++ b/powerline/config_files/colorschemes/pdb/__main__.json @@ -1,5 +1,8 @@ { "groups": { - "current_context": "current_code_name" + "current_code_name": "information:additional", + "current_context": "current_code_name", + "current_line": "information:regular", + "current_file": "information:regular" } } diff --git a/powerline/config_files/colorschemes/pdb/default.json b/powerline/config_files/colorschemes/pdb/default.json index 56f9020f..b97acf7f 100644 --- a/powerline/config_files/colorschemes/pdb/default.json +++ b/powerline/config_files/colorschemes/pdb/default.json @@ -1,8 +1,5 @@ { "groups": { - "current_line": { "fg": "gray10", "bg": "gray4", "attrs": ["bold"] }, - "current_file": { "fg": "gray10", "bg": "gray4", "attrs": ["bold"] }, - "current_code_name": { "fg": "gray9", "bg": "gray4", "attrs": ["bold"] }, - "stack_depth": { "fg": "gray1", "bg": "gray10", "attrs": ["bold"] } + "stack_depth": { "fg": "gray1", "bg": "gray10", "attrs": ["bold"] } } } diff --git a/powerline/config_files/colorschemes/pdb/solarized.json b/powerline/config_files/colorschemes/pdb/solarized.json new file mode 100644 index 00000000..2e1c787c --- /dev/null +++ b/powerline/config_files/colorschemes/pdb/solarized.json @@ -0,0 +1,5 @@ +{ + "groups": { + "stack_depth": { "fg": "solarized:base03", "bg": "solarized:base2", "attrs": ["bold"] } + } +} From 2ef5107628956b0433537e8fdb3534d88f91f0f4 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sat, 31 Jan 2015 20:23:10 +0300 Subject: [PATCH 25/43] Import overrides from environment in PDB prompts --- docs/source/configuration/local.rst | 6 + docs/source/usage/other.rst | 2 + powerline/pdb.py | 23 ++++ tests/test_shells/pdb.module.ok | 176 ++++++++++++++-------------- tests/test_shells/pdb.subclass.ok | 176 ++++++++++++++-------------- 5 files changed, 207 insertions(+), 176 deletions(-) diff --git a/docs/source/configuration/local.rst b/docs/source/configuration/local.rst index 3eec3ee0..5ea233f4 100644 --- a/docs/source/configuration/local.rst +++ b/docs/source/configuration/local.rst @@ -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 ` take overrides from +:ref:`environment variables `. diff --git a/docs/source/usage/other.rst b/docs/source/usage/other.rst index 2e7d334d..108ec3ed 100644 --- a/docs/source/usage/other.rst +++ b/docs/source/usage/other.rst @@ -125,6 +125,8 @@ 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 ========== diff --git a/powerline/pdb.py b/powerline/pdb.py index 79915818..b1e13cea 100644 --- a/powerline/pdb.py +++ b/powerline/pdb.py @@ -3,8 +3,11 @@ from __future__ import (unicode_literals, division, absolute_import, print_funct 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): @@ -21,5 +24,25 @@ class PDBPowerline(Powerline): 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') diff --git a/tests/test_shells/pdb.module.ok b/tests/test_shells/pdb.module.ok index 629d2993..1001dc42 100644 --- a/tests/test_shells/pdb.module.ok +++ b/tests/test_shells/pdb.module.ok @@ -1,224 +1,224 @@ - 1  pdb-script.py:2   s + 1  pdb-script.py:2   s -> class Foo(object): - 1  pdb-script.py:6    + 1  pdb-script.py:6    --Call-- -> class Foo(object): - 2  pdb-script.py:6   pdb-script.py:6 Foo   + 2  pdb-script.py:6   pdb-script.py:6 Foo   -> class Foo(object): - 2  pdb-script.py:6   pdb-script.py:6 Foo   + 2  pdb-script.py:6   pdb-script.py:6 Foo   -> def __init__(self): - 2  pdb-script.py:6   pdb-script.py:7 Foo   + 2  pdb-script.py:6   pdb-script.py:7 Foo   -> @classmethod - 2  pdb-script.py:6   pdb-script.py:13 Foo   + 2  pdb-script.py:6   pdb-script.py:13 Foo   -> @staticmethod - 2  pdb-script.py:6   pdb-script.py:17 Foo   + 2  pdb-script.py:6   pdb-script.py:17 Foo   -> def bra(self): - 2  pdb-script.py:6   pdb-script.py:21 Foo   + 2  pdb-script.py:6   pdb-script.py:21 Foo   --Return-- -> def bra(self): - 2  pdb-script.py:6   pdb-script.py:21 Foo   + 2  pdb-script.py:6   pdb-script.py:21 Foo   -> def brah(): - 1  pdb-script.py:25    + 1  pdb-script.py:25    -> f = Foo() - 1  pdb-script.py:29    + 1  pdb-script.py:29    --Call-- -> def __init__(self): - 2  pdb-script.py:29   pdb-script.py:7 __init__   + 2  pdb-script.py:29   pdb-script.py:7 __init__   -> nop('__init__') - 2  pdb-script.py:29   pdb-script.py:8 __init__   + 2  pdb-script.py:29   pdb-script.py:8 __init__   --Call-- -> def nop(_): - 3  pdb-script.py:29   pdb-script.py:8 __init__  pdb-script.py:2 nop   + 3  pdb-script.py:29   pdb-script.py:8 __init__  pdb-script.py:2 nop   -> pass - 3  pdb-script.py:29   pdb-script.py:8 __init__  pdb-script.py:3 nop   + 3  pdb-script.py:29   pdb-script.py:8 __init__  pdb-script.py:3 nop   --Return-- -> pass - 3  pdb-script.py:29   pdb-script.py:8 __init__  pdb-script.py:3 nop   + 3  pdb-script.py:29   pdb-script.py:8 __init__  pdb-script.py:3 nop   -> self.bar() - 2  pdb-script.py:29   pdb-script.py:9 __init__   + 2  pdb-script.py:29   pdb-script.py:9 __init__   --Call-- -> @classmethod - 3  pdb-script.py:29   pdb-script.py:9 __init__  pdb-script.py:13 bar   + 3  pdb-script.py:29   pdb-script.py:9 __init__  pdb-script.py:13 bar   -> nop(cls.__name__) - 3  pdb-script.py:29   pdb-script.py:9 __init__  pdb-script.py:15 bar   + 3  pdb-script.py:29   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   + 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   + 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   + 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   pdb-script.py:9 __init__  pdb-script.py:15 bar   + 3  pdb-script.py:29   pdb-script.py:9 __init__  pdb-script.py:15 bar   -> self.baz() - 2  pdb-script.py:29   pdb-script.py:10 __init__   + 2  pdb-script.py:29   pdb-script.py:10 __init__   --Call-- -> @staticmethod - 3  pdb-script.py:29   pdb-script.py:10 __init__  pdb-script.py:17 baz   + 3  pdb-script.py:29   pdb-script.py:10 __init__  pdb-script.py:17 baz   -> nop(1) - 3  pdb-script.py:29   pdb-script.py:10 __init__  pdb-script.py:19 baz   + 3  pdb-script.py:29   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   + 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   + 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   + 4  pdb-script.py:10 __init__  pdb-script.py:19 baz  pdb-script.py:3 nop   --Return-- -> nop(1) - 3  pdb-script.py:29   pdb-script.py:10 __init__  pdb-script.py:19 baz   + 3  pdb-script.py:29   pdb-script.py:10 __init__  pdb-script.py:19 baz   -> self.bra() - 2  pdb-script.py:29   pdb-script.py:11 __init__   + 2  pdb-script.py:29   pdb-script.py:11 __init__   --Call-- -> def bra(self): - 3  pdb-script.py:29   pdb-script.py:11 __init__  pdb-script.py:21 bra   + 3  pdb-script.py:29   pdb-script.py:11 __init__  pdb-script.py:21 bra   -> nop(self.__class__.__name__) - 3  pdb-script.py:29   pdb-script.py:11 __init__  pdb-script.py:22 bra   + 3  pdb-script.py:29   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   + 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   + 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   + 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   pdb-script.py:11 __init__  pdb-script.py:22 bra   + 3  pdb-script.py:29   pdb-script.py:11 __init__  pdb-script.py:22 bra   --Return-- -> self.bra() - 2  pdb-script.py:29   pdb-script.py:11 __init__   + 2  pdb-script.py:29   pdb-script.py:11 __init__   -> Foo.bar() - 1  pdb-script.py:30    + 1  pdb-script.py:30    --Call-- -> @classmethod - 2  pdb-script.py:30   pdb-script.py:13 bar   + 2  pdb-script.py:30   pdb-script.py:13 bar   -> nop(cls.__name__) - 2  pdb-script.py:30   pdb-script.py:15 bar   + 2  pdb-script.py:30   pdb-script.py:15 bar   --Call-- -> def nop(_): - 3  pdb-script.py:30   pdb-script.py:15 bar  pdb-script.py:2 nop   + 3  pdb-script.py:30   pdb-script.py:15 bar  pdb-script.py:2 nop   -> pass - 3  pdb-script.py:30   pdb-script.py:15 bar  pdb-script.py:3 nop   + 3  pdb-script.py:30   pdb-script.py:15 bar  pdb-script.py:3 nop   --Return-- -> pass - 3  pdb-script.py:30   pdb-script.py:15 bar  pdb-script.py:3 nop   + 3  pdb-script.py:30   pdb-script.py:15 bar  pdb-script.py:3 nop   --Return-- -> nop(cls.__name__) - 2  pdb-script.py:30   pdb-script.py:15 bar   + 2  pdb-script.py:30   pdb-script.py:15 bar   -> Foo.baz() - 1  pdb-script.py:31    + 1  pdb-script.py:31    --Call-- -> @staticmethod - 2  pdb-script.py:31   pdb-script.py:17 baz   + 2  pdb-script.py:31   pdb-script.py:17 baz   -> nop(1) - 2  pdb-script.py:31   pdb-script.py:19 baz   + 2  pdb-script.py:31   pdb-script.py:19 baz   --Call-- -> def nop(_): - 3  pdb-script.py:31   pdb-script.py:19 baz  pdb-script.py:2 nop   + 3  pdb-script.py:31   pdb-script.py:19 baz  pdb-script.py:2 nop   -> pass - 3  pdb-script.py:31   pdb-script.py:19 baz  pdb-script.py:3 nop   + 3  pdb-script.py:31   pdb-script.py:19 baz  pdb-script.py:3 nop   --Return-- -> pass - 3  pdb-script.py:31   pdb-script.py:19 baz  pdb-script.py:3 nop   + 3  pdb-script.py:31   pdb-script.py:19 baz  pdb-script.py:3 nop   --Return-- -> nop(1) - 2  pdb-script.py:31   pdb-script.py:19 baz   + 2  pdb-script.py:31   pdb-script.py:19 baz   -> Foo.bra(f) - 1  pdb-script.py:32    + 1  pdb-script.py:32    --Call-- -> def bra(self): - 2  pdb-script.py:32   pdb-script.py:21 bra   + 2  pdb-script.py:32   pdb-script.py:21 bra   -> nop(self.__class__.__name__) - 2  pdb-script.py:32   pdb-script.py:22 bra   + 2  pdb-script.py:32   pdb-script.py:22 bra   --Call-- -> def nop(_): - 3  pdb-script.py:32   pdb-script.py:22 bra  pdb-script.py:2 nop   + 3  pdb-script.py:32   pdb-script.py:22 bra  pdb-script.py:2 nop   -> pass - 3  pdb-script.py:32   pdb-script.py:22 bra  pdb-script.py:3 nop   + 3  pdb-script.py:32   pdb-script.py:22 bra  pdb-script.py:3 nop   --Return-- -> pass - 3  pdb-script.py:32   pdb-script.py:22 bra  pdb-script.py:3 nop   + 3  pdb-script.py:32   pdb-script.py:22 bra  pdb-script.py:3 nop   --Return-- -> nop(self.__class__.__name__) - 2  pdb-script.py:32   pdb-script.py:22 bra   + 2  pdb-script.py:32   pdb-script.py:22 bra   -> f.bar() - 1  pdb-script.py:34    + 1  pdb-script.py:34    --Call-- -> @classmethod - 2  pdb-script.py:34   pdb-script.py:13 bar   + 2  pdb-script.py:34   pdb-script.py:13 bar   -> nop(cls.__name__) - 2  pdb-script.py:34   pdb-script.py:15 bar   + 2  pdb-script.py:34   pdb-script.py:15 bar   --Call-- -> def nop(_): - 3  pdb-script.py:34   pdb-script.py:15 bar  pdb-script.py:2 nop   + 3  pdb-script.py:34   pdb-script.py:15 bar  pdb-script.py:2 nop   -> pass - 3  pdb-script.py:34   pdb-script.py:15 bar  pdb-script.py:3 nop   + 3  pdb-script.py:34   pdb-script.py:15 bar  pdb-script.py:3 nop   --Return-- -> pass - 3  pdb-script.py:34   pdb-script.py:15 bar  pdb-script.py:3 nop   + 3  pdb-script.py:34   pdb-script.py:15 bar  pdb-script.py:3 nop   --Return-- -> nop(cls.__name__) - 2  pdb-script.py:34   pdb-script.py:15 bar   + 2  pdb-script.py:34   pdb-script.py:15 bar   -> f.baz() - 1  pdb-script.py:35    + 1  pdb-script.py:35    --Call-- -> @staticmethod - 2  pdb-script.py:35   pdb-script.py:17 baz   + 2  pdb-script.py:35   pdb-script.py:17 baz   -> nop(1) - 2  pdb-script.py:35   pdb-script.py:19 baz   + 2  pdb-script.py:35   pdb-script.py:19 baz   --Call-- -> def nop(_): - 3  pdb-script.py:35   pdb-script.py:19 baz  pdb-script.py:2 nop   + 3  pdb-script.py:35   pdb-script.py:19 baz  pdb-script.py:2 nop   -> pass - 3  pdb-script.py:35   pdb-script.py:19 baz  pdb-script.py:3 nop   + 3  pdb-script.py:35   pdb-script.py:19 baz  pdb-script.py:3 nop   --Return-- -> pass - 3  pdb-script.py:35   pdb-script.py:19 baz  pdb-script.py:3 nop   + 3  pdb-script.py:35   pdb-script.py:19 baz  pdb-script.py:3 nop   --Return-- -> nop(1) - 2  pdb-script.py:35   pdb-script.py:19 baz   + 2  pdb-script.py:35   pdb-script.py:19 baz   -> f.bra() - 1  pdb-script.py:36    + 1  pdb-script.py:36    --Call-- -> def bra(self): - 2  pdb-script.py:36   pdb-script.py:21 bra   + 2  pdb-script.py:36   pdb-script.py:21 bra   -> nop(self.__class__.__name__) - 2  pdb-script.py:36   pdb-script.py:22 bra   + 2  pdb-script.py:36   pdb-script.py:22 bra   --Call-- -> def nop(_): - 3  pdb-script.py:36   pdb-script.py:22 bra  pdb-script.py:2 nop   + 3  pdb-script.py:36   pdb-script.py:22 bra  pdb-script.py:2 nop   -> pass - 3  pdb-script.py:36   pdb-script.py:22 bra  pdb-script.py:3 nop   + 3  pdb-script.py:36   pdb-script.py:22 bra  pdb-script.py:3 nop   --Return-- -> pass - 3  pdb-script.py:36   pdb-script.py:22 bra  pdb-script.py:3 nop   + 3  pdb-script.py:36   pdb-script.py:22 bra  pdb-script.py:3 nop   --Return-- -> nop(self.__class__.__name__) - 2  pdb-script.py:36   pdb-script.py:22 bra   + 2  pdb-script.py:36   pdb-script.py:22 bra   -> brah() - 1  pdb-script.py:38    + 1  pdb-script.py:38    --Call-- -> def brah(): - 2  pdb-script.py:38   pdb-script.py:25 brah   + 2  pdb-script.py:38   pdb-script.py:25 brah   -> nop('brah') - 2  pdb-script.py:38   pdb-script.py:26 brah   + 2  pdb-script.py:38   pdb-script.py:26 brah   --Call-- -> def nop(_): - 3  pdb-script.py:38   pdb-script.py:26 brah  pdb-script.py:2 nop   + 3  pdb-script.py:38   pdb-script.py:26 brah  pdb-script.py:2 nop   -> pass - 3  pdb-script.py:38   pdb-script.py:26 brah  pdb-script.py:3 nop   + 3  pdb-script.py:38   pdb-script.py:26 brah  pdb-script.py:3 nop   --Return-- -> pass - 3  pdb-script.py:38   pdb-script.py:26 brah  pdb-script.py:3 nop   + 3  pdb-script.py:38   pdb-script.py:26 brah  pdb-script.py:3 nop   --Return-- -> nop('brah') - 2  pdb-script.py:38   pdb-script.py:26 brah   + 2  pdb-script.py:38   pdb-script.py:26 brah   --Return-- -> brah() - 1  pdb-script.py:38    + 1  pdb-script.py:38    --Return--  0   diff --git a/tests/test_shells/pdb.subclass.ok b/tests/test_shells/pdb.subclass.ok index 41bda2da..b6f024fd 100644 --- a/tests/test_shells/pdb.subclass.ok +++ b/tests/test_shells/pdb.subclass.ok @@ -1,223 +1,223 @@ --Call-- -> def nop(_): - 2  :1   pdb-script.py:2    + 2  :1   pdb-script.py:2    -> def nop(_): - 2  :1   pdb-script.py:2    + 2  :1   pdb-script.py:2    -> class Foo(object): - 2  :1   pdb-script.py:6    + 2  :1   pdb-script.py:6    --Call-- -> class Foo(object): - 3  :1   pdb-script.py:6   pdb-script.py:6 Foo   + 3  :1   pdb-script.py:6   pdb-script.py:6 Foo   -> class Foo(object): - 3  :1   pdb-script.py:6   pdb-script.py:6 Foo   + 3  :1   pdb-script.py:6   pdb-script.py:6 Foo   -> def __init__(self): - 3  :1   pdb-script.py:6   pdb-script.py:7 Foo   + 3  :1   pdb-script.py:6   pdb-script.py:7 Foo   -> @classmethod - 3  :1   pdb-script.py:6   pdb-script.py:13 Foo   + 3  :1   pdb-script.py:6   pdb-script.py:13 Foo   -> @staticmethod - 3  :1   pdb-script.py:6   pdb-script.py:17 Foo   + 3  :1   pdb-script.py:6   pdb-script.py:17 Foo   -> def bra(self): - 3  :1   pdb-script.py:6   pdb-script.py:21 Foo   + 3  :1   pdb-script.py:6   pdb-script.py:21 Foo   --Return-- -> def bra(self): - 3  :1   pdb-script.py:6   pdb-script.py:21 Foo   + 3  :1   pdb-script.py:6   pdb-script.py:21 Foo   -> def brah(): - 2  :1   pdb-script.py:25    + 2  :1   pdb-script.py:25    -> f = Foo() - 2  :1   pdb-script.py:29    + 2  :1   pdb-script.py:29    --Call-- -> def __init__(self): - 3  :1   pdb-script.py:29   pdb-script.py:7 __init__   + 3  :1   pdb-script.py:29   pdb-script.py:7 __init__   -> nop('__init__') - 3  :1   pdb-script.py:29   pdb-script.py:8 __init__   + 3  :1   pdb-script.py:29   pdb-script.py:8 __init__   --Call-- -> def nop(_): - 4  pdb-script.py:29   pdb-script.py:8 __init__  pdb-script.py:2 nop   + 4  pdb-script.py:29   pdb-script.py:8 __init__  pdb-script.py:2 nop   -> pass - 4  pdb-script.py:29   pdb-script.py:8 __init__  pdb-script.py:3 nop   + 4  pdb-script.py:29   pdb-script.py:8 __init__  pdb-script.py:3 nop   --Return-- -> pass - 4  pdb-script.py:29   pdb-script.py:8 __init__  pdb-script.py:3 nop   + 4  pdb-script.py:29   pdb-script.py:8 __init__  pdb-script.py:3 nop   -> self.bar() - 3  :1   pdb-script.py:29   pdb-script.py:9 __init__   + 3  :1   pdb-script.py:29   pdb-script.py:9 __init__   --Call-- -> @classmethod - 4  pdb-script.py:29   pdb-script.py:9 __init__  pdb-script.py:13 bar   + 4  pdb-script.py:29   pdb-script.py:9 __init__  pdb-script.py:13 bar   -> nop(cls.__name__) - 4  pdb-script.py:29   pdb-script.py:9 __init__  pdb-script.py:15 bar   + 4  pdb-script.py:29   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   + 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   + 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   + 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   pdb-script.py:9 __init__  pdb-script.py:15 bar   + 4  pdb-script.py:29   pdb-script.py:9 __init__  pdb-script.py:15 bar   -> self.baz() - 3  :1   pdb-script.py:29   pdb-script.py:10 __init__   + 3  :1   pdb-script.py:29   pdb-script.py:10 __init__   --Call-- -> @staticmethod - 4  pdb-script.py:29   pdb-script.py:10 __init__  pdb-script.py:17 baz   + 4  pdb-script.py:29   pdb-script.py:10 __init__  pdb-script.py:17 baz   -> nop(1) - 4  pdb-script.py:29   pdb-script.py:10 __init__  pdb-script.py:19 baz   + 4  pdb-script.py:29   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   + 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   + 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   + 5  pdb-script.py:10 __init__  pdb-script.py:19 baz  pdb-script.py:3 nop   --Return-- -> nop(1) - 4  pdb-script.py:29   pdb-script.py:10 __init__  pdb-script.py:19 baz   + 4  pdb-script.py:29   pdb-script.py:10 __init__  pdb-script.py:19 baz   -> self.bra() - 3  :1   pdb-script.py:29   pdb-script.py:11 __init__   + 3  :1   pdb-script.py:29   pdb-script.py:11 __init__   --Call-- -> def bra(self): - 4  pdb-script.py:29   pdb-script.py:11 __init__  pdb-script.py:21 bra   + 4  pdb-script.py:29   pdb-script.py:11 __init__  pdb-script.py:21 bra   -> nop(self.__class__.__name__) - 4  pdb-script.py:29   pdb-script.py:11 __init__  pdb-script.py:22 bra   + 4  pdb-script.py:29   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   + 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   + 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   + 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   pdb-script.py:11 __init__  pdb-script.py:22 bra   + 4  pdb-script.py:29   pdb-script.py:11 __init__  pdb-script.py:22 bra   --Return-- -> self.bra() - 3  :1   pdb-script.py:29   pdb-script.py:11 __init__   + 3  :1   pdb-script.py:29   pdb-script.py:11 __init__   -> Foo.bar() - 2  :1   pdb-script.py:30    + 2  :1   pdb-script.py:30    --Call-- -> @classmethod - 3  :1   pdb-script.py:30   pdb-script.py:13 bar   + 3  :1   pdb-script.py:30   pdb-script.py:13 bar   -> nop(cls.__name__) - 3  :1   pdb-script.py:30   pdb-script.py:15 bar   + 3  :1   pdb-script.py:30   pdb-script.py:15 bar   --Call-- -> def nop(_): - 4  pdb-script.py:30   pdb-script.py:15 bar  pdb-script.py:2 nop   + 4  pdb-script.py:30   pdb-script.py:15 bar  pdb-script.py:2 nop   -> pass - 4  pdb-script.py:30   pdb-script.py:15 bar  pdb-script.py:3 nop   + 4  pdb-script.py:30   pdb-script.py:15 bar  pdb-script.py:3 nop   --Return-- -> pass - 4  pdb-script.py:30   pdb-script.py:15 bar  pdb-script.py:3 nop   + 4  pdb-script.py:30   pdb-script.py:15 bar  pdb-script.py:3 nop   --Return-- -> nop(cls.__name__) - 3  :1   pdb-script.py:30   pdb-script.py:15 bar   + 3  :1   pdb-script.py:30   pdb-script.py:15 bar   -> Foo.baz() - 2  :1   pdb-script.py:31    + 2  :1   pdb-script.py:31    --Call-- -> @staticmethod - 3  :1   pdb-script.py:31   pdb-script.py:17 baz   + 3  :1   pdb-script.py:31   pdb-script.py:17 baz   -> nop(1) - 3  :1   pdb-script.py:31   pdb-script.py:19 baz   + 3  :1   pdb-script.py:31   pdb-script.py:19 baz   --Call-- -> def nop(_): - 4  pdb-script.py:31   pdb-script.py:19 baz  pdb-script.py:2 nop   + 4  pdb-script.py:31   pdb-script.py:19 baz  pdb-script.py:2 nop   -> pass - 4  pdb-script.py:31   pdb-script.py:19 baz  pdb-script.py:3 nop   + 4  pdb-script.py:31   pdb-script.py:19 baz  pdb-script.py:3 nop   --Return-- -> pass - 4  pdb-script.py:31   pdb-script.py:19 baz  pdb-script.py:3 nop   + 4  pdb-script.py:31   pdb-script.py:19 baz  pdb-script.py:3 nop   --Return-- -> nop(1) - 3  :1   pdb-script.py:31   pdb-script.py:19 baz   + 3  :1   pdb-script.py:31   pdb-script.py:19 baz   -> Foo.bra(f) - 2  :1   pdb-script.py:32    + 2  :1   pdb-script.py:32    --Call-- -> def bra(self): - 3  :1   pdb-script.py:32   pdb-script.py:21 bra   + 3  :1   pdb-script.py:32   pdb-script.py:21 bra   -> nop(self.__class__.__name__) - 3  :1   pdb-script.py:32   pdb-script.py:22 bra   + 3  :1   pdb-script.py:32   pdb-script.py:22 bra   --Call-- -> def nop(_): - 4  pdb-script.py:32   pdb-script.py:22 bra  pdb-script.py:2 nop   + 4  pdb-script.py:32   pdb-script.py:22 bra  pdb-script.py:2 nop   -> pass - 4  pdb-script.py:32   pdb-script.py:22 bra  pdb-script.py:3 nop   + 4  pdb-script.py:32   pdb-script.py:22 bra  pdb-script.py:3 nop   --Return-- -> pass - 4  pdb-script.py:32   pdb-script.py:22 bra  pdb-script.py:3 nop   + 4  pdb-script.py:32   pdb-script.py:22 bra  pdb-script.py:3 nop   --Return-- -> nop(self.__class__.__name__) - 3  :1   pdb-script.py:32   pdb-script.py:22 bra   + 3  :1   pdb-script.py:32   pdb-script.py:22 bra   -> f.bar() - 2  :1   pdb-script.py:34    + 2  :1   pdb-script.py:34    --Call-- -> @classmethod - 3  :1   pdb-script.py:34   pdb-script.py:13 bar   + 3  :1   pdb-script.py:34   pdb-script.py:13 bar   -> nop(cls.__name__) - 3  :1   pdb-script.py:34   pdb-script.py:15 bar   + 3  :1   pdb-script.py:34   pdb-script.py:15 bar   --Call-- -> def nop(_): - 4  pdb-script.py:34   pdb-script.py:15 bar  pdb-script.py:2 nop   + 4  pdb-script.py:34   pdb-script.py:15 bar  pdb-script.py:2 nop   -> pass - 4  pdb-script.py:34   pdb-script.py:15 bar  pdb-script.py:3 nop   + 4  pdb-script.py:34   pdb-script.py:15 bar  pdb-script.py:3 nop   --Return-- -> pass - 4  pdb-script.py:34   pdb-script.py:15 bar  pdb-script.py:3 nop   + 4  pdb-script.py:34   pdb-script.py:15 bar  pdb-script.py:3 nop   --Return-- -> nop(cls.__name__) - 3  :1   pdb-script.py:34   pdb-script.py:15 bar   + 3  :1   pdb-script.py:34   pdb-script.py:15 bar   -> f.baz() - 2  :1   pdb-script.py:35    + 2  :1   pdb-script.py:35    --Call-- -> @staticmethod - 3  :1   pdb-script.py:35   pdb-script.py:17 baz   + 3  :1   pdb-script.py:35   pdb-script.py:17 baz   -> nop(1) - 3  :1   pdb-script.py:35   pdb-script.py:19 baz   + 3  :1   pdb-script.py:35   pdb-script.py:19 baz   --Call-- -> def nop(_): - 4  pdb-script.py:35   pdb-script.py:19 baz  pdb-script.py:2 nop   + 4  pdb-script.py:35   pdb-script.py:19 baz  pdb-script.py:2 nop   -> pass - 4  pdb-script.py:35   pdb-script.py:19 baz  pdb-script.py:3 nop   + 4  pdb-script.py:35   pdb-script.py:19 baz  pdb-script.py:3 nop   --Return-- -> pass - 4  pdb-script.py:35   pdb-script.py:19 baz  pdb-script.py:3 nop   + 4  pdb-script.py:35   pdb-script.py:19 baz  pdb-script.py:3 nop   --Return-- -> nop(1) - 3  :1   pdb-script.py:35   pdb-script.py:19 baz   + 3  :1   pdb-script.py:35   pdb-script.py:19 baz   -> f.bra() - 2  :1   pdb-script.py:36    + 2  :1   pdb-script.py:36    --Call-- -> def bra(self): - 3  :1   pdb-script.py:36   pdb-script.py:21 bra   + 3  :1   pdb-script.py:36   pdb-script.py:21 bra   -> nop(self.__class__.__name__) - 3  :1   pdb-script.py:36   pdb-script.py:22 bra   + 3  :1   pdb-script.py:36   pdb-script.py:22 bra   --Call-- -> def nop(_): - 4  pdb-script.py:36   pdb-script.py:22 bra  pdb-script.py:2 nop   + 4  pdb-script.py:36   pdb-script.py:22 bra  pdb-script.py:2 nop   -> pass - 4  pdb-script.py:36   pdb-script.py:22 bra  pdb-script.py:3 nop   + 4  pdb-script.py:36   pdb-script.py:22 bra  pdb-script.py:3 nop   --Return-- -> pass - 4  pdb-script.py:36   pdb-script.py:22 bra  pdb-script.py:3 nop   + 4  pdb-script.py:36   pdb-script.py:22 bra  pdb-script.py:3 nop   --Return-- -> nop(self.__class__.__name__) - 3  :1   pdb-script.py:36   pdb-script.py:22 bra   + 3  :1   pdb-script.py:36   pdb-script.py:22 bra   -> brah() - 2  :1   pdb-script.py:38    + 2  :1   pdb-script.py:38    --Call-- -> def brah(): - 3  :1   pdb-script.py:38   pdb-script.py:25 brah   + 3  :1   pdb-script.py:38   pdb-script.py:25 brah   -> nop('brah') - 3  :1   pdb-script.py:38   pdb-script.py:26 brah   + 3  :1   pdb-script.py:38   pdb-script.py:26 brah   --Call-- -> def nop(_): - 4  pdb-script.py:38   pdb-script.py:26 brah  pdb-script.py:2 nop   + 4  pdb-script.py:38   pdb-script.py:26 brah  pdb-script.py:2 nop   -> pass - 4  pdb-script.py:38   pdb-script.py:26 brah  pdb-script.py:3 nop   + 4  pdb-script.py:38   pdb-script.py:26 brah  pdb-script.py:3 nop   --Return-- -> pass - 4  pdb-script.py:38   pdb-script.py:26 brah  pdb-script.py:3 nop   + 4  pdb-script.py:38   pdb-script.py:26 brah  pdb-script.py:3 nop   --Return-- -> nop('brah') - 3  :1   pdb-script.py:38   pdb-script.py:26 brah   + 3  :1   pdb-script.py:38   pdb-script.py:26 brah   From f9d65fb34db1ea419941a101da02ebd975c31ce4 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sat, 31 Jan 2015 20:25:40 +0300 Subject: [PATCH 26/43] Do not wait for too long in do_run_test --- tests/test_shells/test.sh | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/test_shells/test.sh b/tests/test_shells/test.sh index 830dcb0a..a84854aa 100755 --- a/tests/test_shells/test.sh +++ b/tests/test_shells/test.sh @@ -111,8 +111,14 @@ 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" + return 1 + fi done if ( \ test "x${SH}" = "xdash" \ From d8252f66b7d99caa7f31d9522f8514e8f6fb704b Mon Sep 17 00:00:00 2001 From: ZyX Date: Sat, 31 Jan 2015 21:09:39 +0300 Subject: [PATCH 27/43] Move main() into powerline.bindings.pdb --- powerline/bindings/pdb/__init__.py | 19 +++++++++++++++++++ powerline/bindings/pdb/__main__.py | 22 +--------------------- 2 files changed, 20 insertions(+), 21 deletions(-) diff --git a/powerline/bindings/pdb/__init__.py b/powerline/bindings/pdb/__init__.py index 48b8a606..4033e611 100644 --- a/powerline/bindings/pdb/__init__.py +++ b/powerline/bindings/pdb/__init__.py @@ -2,6 +2,7 @@ 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 @@ -162,3 +163,21 @@ def use_powerline_prompt(cls): 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() diff --git a/powerline/bindings/pdb/__main__.py b/powerline/bindings/pdb/__main__.py index 78527500..768b2f29 100755 --- a/powerline/bindings/pdb/__main__.py +++ b/powerline/bindings/pdb/__main__.py @@ -2,27 +2,7 @@ # vim:fileencoding=utf-8:noet from __future__ import (unicode_literals, division, absolute_import, print_function) -import pdb - -from powerline.bindings.pdb import use_powerline_prompt - - -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() +from powerline.bindings.pdb import main if __name__ == '__main__': From e63a1c7cb50474cb31ec7cb334dd4d6d1046b0e4 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sat, 31 Jan 2015 21:18:06 +0300 Subject: [PATCH 28/43] Display the log after long wait --- tests/test_shells/test.sh | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/test_shells/test.sh b/tests/test_shells/test.sh index a84854aa..effd3c45 100755 --- a/tests/test_shells/test.sh +++ b/tests/test_shells/test.sh @@ -117,6 +117,16 @@ do_run_test() { 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 From 0db8154b9aab99880c416af51b54519c57385505 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sat, 31 Jan 2015 21:32:16 +0300 Subject: [PATCH 29/43] Document how to pdb bindings with Python-2.6 and update tests --- docs/source/usage/other.rst | 4 ++++ tests/test_shells/test.sh | 8 ++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/docs/source/usage/other.rst b/docs/source/usage/other.rst index 108ec3ed..c160339f 100644 --- a/docs/source/usage/other.rst +++ b/docs/source/usage/other.rst @@ -154,6 +154,10 @@ class from :py:class:`pdb.Pdb` and decorate it with 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 diff --git a/tests/test_shells/test.sh b/tests/test_shells/test.sh index effd3c45..d436080e 100755 --- a/tests/test_shells/test.sh +++ b/tests/test_shells/test.sh @@ -464,9 +464,13 @@ if test "x${ONLY_SHELL}" = "x" || test "x${ONLY_SHELL}" = "xpdb" ; then fi if test "x${ONLY_TEST_TYPE}" = "x" || test "x${ONLY_TEST_TYPE}" = "xmodule" ; then echo "> pdb module" - if ! run_test module python $PDB_PYTHON -mpowerline.bindings.pdb "$PWD/tests/test_shells/pdb-script.py" ; then + 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 -mpowerline.bindings.pdb $PWD/tests/test_shells/pdb-script" + FAIL_SUMMARY="${FAIL_SUMMARY}${NL}T pdb $PDB_PYTHON -m$MODULE $PWD/tests/test_shells/pdb-script" fi fi fi From c3e541d16a9af7be670a620023dd8934a2778090 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sun, 1 Feb 2015 12:08:09 +0300 Subject: [PATCH 30/43] Remove empty lines --- tests/test_shells/postproc.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/test_shells/postproc.py b/tests/test_shells/postproc.py index 7b9d330e..32f311d3 100755 --- a/tests/test_shells/postproc.py +++ b/tests/test_shells/postproc.py @@ -111,6 +111,8 @@ with codecs.open(fname, 'r', encoding='utf-8') as R: 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': From f4e3c3099fdab5401cfa64efdf81962c3dcb6cf2 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sun, 1 Feb 2015 12:13:56 +0300 Subject: [PATCH 31/43] Remove everything up until `class Foo(object):` in pdb tests PyPy3 displays prompt two times on the line where `s` is present. --- tests/test_shells/pdb.module.ok | 2 -- tests/test_shells/pdb.subclass.ok | 6 ------ tests/test_shells/postproc.py | 9 +++++---- 3 files changed, 5 insertions(+), 12 deletions(-) diff --git a/tests/test_shells/pdb.module.ok b/tests/test_shells/pdb.module.ok index 1001dc42..7554dd6c 100644 --- a/tests/test_shells/pdb.module.ok +++ b/tests/test_shells/pdb.module.ok @@ -1,5 +1,3 @@ - 1  pdb-script.py:2   s --> class Foo(object):  1  pdb-script.py:6    --Call-- -> class Foo(object): diff --git a/tests/test_shells/pdb.subclass.ok b/tests/test_shells/pdb.subclass.ok index b6f024fd..d8eba5ef 100644 --- a/tests/test_shells/pdb.subclass.ok +++ b/tests/test_shells/pdb.subclass.ok @@ -1,9 +1,3 @@ ---Call-- --> def nop(_): - 2  :1   pdb-script.py:2    --> def nop(_): - 2  :1   pdb-script.py:2    --> class Foo(object):  2  :1   pdb-script.py:6    --Call-- -> class Foo(object): diff --git a/tests/test_shells/postproc.py b/tests/test_shells/postproc.py index 32f311d3..d544bf83 100755 --- a/tests/test_shells/postproc.py +++ b/tests/test_shells/postproc.py @@ -38,10 +38,11 @@ with codecs.open(fname, 'r', encoding='utf-8') as R: for line in (R if shell != 'fish' else R.read().split('\n')): i += 1 if not found_cd: - if shell == 'pdb': - found_cd = (i > 1) - else: - 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 From d57be8324a224b0b7dbaea232595a338fe04c755 Mon Sep 17 00:00:00 2001 From: ZyX Date: Mon, 2 Feb 2015 00:12:06 +0300 Subject: [PATCH 32/43] Do not alter the way keys are fed with PyPy --- tests/test_shells/test.sh | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tests/test_shells/test.sh b/tests/test_shells/test.sh index d436080e..fdce0d3e 100755 --- a/tests/test_shells/test.sh +++ b/tests/test_shells/test.sh @@ -139,11 +139,13 @@ do_run_test() { || ( \ test "x${SH}" = "xpdb" \ && ( \ - test "$PYTHON_VERSION_MAJOR" -eq 3 \ - && test "$PYTHON_VERSION_MINOR" -eq 2 \ - && test "$PYTHON_IMPLEMENTATION" = "CPython" \ + ( \ + test "$PYTHON_VERSION_MAJOR" -eq 3 \ + && test "$PYTHON_VERSION_MINOR" -eq 2 \ + && test "$PYTHON_IMPLEMENTATION" = "CPython" \ + ) \ + || test "$PYTHON_IMPLEMENTATION" = "PyPy" \ ) \ - || test "$PYTHON_IMPLEMENTATION" = "PyPy" ) \ ) ; then # If I do not use this hack for dash then output will look like From 17e0f74eb0c44c54e14a9ccfef19c8634c0bf87a Mon Sep 17 00:00:00 2001 From: Sean Fisk Date: Wed, 4 Feb 2015 02:28:44 -0500 Subject: [PATCH 33/43] Fix socket address size on non-Linux platforms. --- client/powerline.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/client/powerline.c b/client/powerline.c index d6858770..cafd3d62 100644 --- a/client/powerline.c +++ b/client/powerline.c @@ -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; From 92d4beffa41b81aaa7cfa4feaf9eacc789af9072 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sat, 7 Feb 2015 05:00:37 +0300 Subject: [PATCH 34/43] Wait more before failing tmux vterm tests May fix random test failures. --- tests/test_in_vterm/test_tmux.py | 101 +++++++++++++++++-------------- 1 file changed, 55 insertions(+), 46 deletions(-) diff --git a/tests/test_in_vterm/test_tmux.py b/tests/test_in_vterm/test_tmux.py index eb8de65f..c8f79547 100755 --- a/tests/test_in_vterm/test_tmux.py +++ b/tests/test_in_vterm/test_tmux.py @@ -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(10) + 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') @@ -104,13 +158,6 @@ 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) - )) 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, From d5d138f83d5dea44fcd52c7ed8ebfcfde97e1efe Mon Sep 17 00:00:00 2001 From: ZyX Date: Sat, 7 Feb 2015 11:13:16 +0300 Subject: [PATCH 35/43] Do not bother with testing or setting POWERLINE_CONFIG_COMMAND MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead just test whether using $POWERLINE_CONFIG_COMMAND succeeds and if it does not run just `powerline-config tmux setup`. Problem is that tests in vterm fail *not* because sleeping time is too short, but because `powerline-config tmux setup` for some reason is not launched at all. I am not sure whether this construct is going to fix things. Also ref #875. I am very unsure this commit will fix the issue, but since I do not know what is the reason for this issue at all… who knows. --- powerline/bindings/tmux/powerline.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powerline/bindings/tmux/powerline.conf b/powerline/bindings/tmux/powerline.conf index 7ea407a5..29ec6a47 100644 --- a/powerline/bindings/tmux/powerline.conf +++ b/powerline/bindings/tmux/powerline.conf @@ -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 From 66c6128b664453a385aae248c54bac0c9ea6b653 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sat, 7 Feb 2015 11:14:09 +0300 Subject: [PATCH 36/43] Wait less in vterm tmux tests --- tests/test_in_vterm/test_tmux.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_in_vterm/test_tmux.py b/tests/test_in_vterm/test_tmux.py index c8f79547..2562939d 100755 --- a/tests/test_in_vterm/test_tmux.py +++ b/tests/test_in_vterm/test_tmux.py @@ -42,7 +42,7 @@ def test_expected_result(p, expected_result, cols, rows): return True attempts -= 1 print('Actual result does not match expected. Attempts left: {0}.'.format(attempts)) - sleep(10) + sleep(2) print('Result:') shesc_result = ''.join(( '{0}{1}\x1b[m'.format(cell_properties_key_to_shell_escape(key), text) @@ -157,7 +157,7 @@ def main(): }, ) p.start() - sleep(10) + sleep(2) expected_result_new = ( (((0, 0, 0), (243, 243, 243), 1, 0, 0), ' 0 '), (((243, 243, 243), (11, 11, 11), 0, 0, 0), ' '), From 9e5bd5c1af57053489377d84ea3e7f2cf5a39d0c Mon Sep 17 00:00:00 2001 From: ZyX Date: Sat, 7 Feb 2015 18:50:47 +0300 Subject: [PATCH 37/43] Replace obsolete advice to copy the entire configuration --- docs/source/commands/lint.rst | 2 ++ docs/source/configuration.rst | 30 +++++++++++++++++++----------- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/docs/source/commands/lint.rst b/docs/source/commands/lint.rst index 2ea5ee6b..92d676d6 100644 --- a/docs/source/commands/lint.rst +++ b/docs/source/commands/lint.rst @@ -1,5 +1,7 @@ :orphan: +.. _command-powerline-lint: + powerline-lint manual page ========================== diff --git a/docs/source/configuration.rst b/docs/source/configuration.rst index d3754905..a9ab17be 100644 --- a/docs/source/configuration.rst +++ b/docs/source/configuration.rst @@ -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 `. +.. _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 +` 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! It’s 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 + `. This script should show you the location of the + error. + Some segments need a user configuration to work properly. Here’s a couple of segments that you may want to customize right away: From e112eb4ec44d7ae6b986ec3556f89272919af087 Mon Sep 17 00:00:00 2001 From: Sergey Zolotarev Date: Sun, 8 Feb 2015 02:31:53 +0500 Subject: [PATCH 38/43] Fix link to colorschemes section --- docs/source/configuration.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/configuration.rst b/docs/source/configuration.rst index a9ab17be..7c20eb17 100644 --- a/docs/source/configuration.rst +++ b/docs/source/configuration.rst @@ -16,7 +16,7 @@ Powerline provides default configurations in the following locations: :ref:`Main configuration ` :file:`powerline/config.json` -:ref:`Colorschemes ` +:ref:`Colorschemes ` :file:`powerline/colorschemes/{name}.json`, :file:`powerline/colorscheme/{extension}/__main__.json`, :file:`powerline/colorschemes/{extension}/{name}.json` From 99830bad496d57bc600737f123f1df1a52b43788 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sun, 15 Feb 2015 01:04:58 +0300 Subject: [PATCH 39/43] Use PEP440-compatible versions Fixes #1310 --- scripts/powerline-release.py | 54 ++++++++++++++++++++++++++++-------- setup.py | 10 +++++-- 2 files changed, 50 insertions(+), 14 deletions(-) diff --git a/scripts/powerline-release.py b/scripts/powerline-release.py index 0c3eba10..2d3a7f10 100755 --- a/scripts/powerline-release.py +++ b/scripts/powerline-release.py @@ -48,24 +48,56 @@ 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)]) + 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']) diff --git a/setup.py b/setup.py index 7dbf0217..5160c19f 100755 --- a/setup.py +++ b/setup.py @@ -8,6 +8,7 @@ import subprocess import logging import shlex +from traceback import print_exc from setuptools import setup, find_packages @@ -58,10 +59,13 @@ else: def get_version(): + base_version = '2.0' + 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( From e233ca7a54875a46d287299d4d602231f77be138 Mon Sep 17 00:00:00 2001 From: ZyX Date: Sun, 15 Feb 2015 01:19:06 +0300 Subject: [PATCH 40/43] Fix compiling C client when using Python-2.6 `shlex.split` is inadequate when it receives Unicode strings: `u'-O3'` is split into a single argument that looks like `'-\x00O\x003\x00'`. --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 5160c19f..de22136f 100755 --- a/setup.py +++ b/setup.py @@ -29,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']) From 4c6a2e3e597b30fdd1c4ed1c75750cc44d65036c Mon Sep 17 00:00:00 2001 From: ZyX Date: Sun, 15 Feb 2015 01:25:25 +0300 Subject: [PATCH 41/43] Also check that MIME type matches during tests MIME type names are inconsistent across different systems, so only first component is used. For example, `file` in Travis Ubuntu detects Python scripts as `text/x-java`, in Gentoo these are `text/x-python`. Travis Ubuntu also uses magic file format different from the one sys-apps/file-5.22 from Gentoo has, making it impossible to fix the issue by just copying the files from my system. --- tests/test_shells/test.sh | 40 ++++++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/tests/test_shells/test.sh b/tests/test_shells/test.sh index fdce0d3e..14430361 100755 --- a/tests/test_shells/test.sh +++ b/tests/test_shells/test.sh @@ -279,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 @@ -319,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 @@ -345,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 From d5d4e956fe75eebb2814831e1258a899f4d20c80 Mon Sep 17 00:00:00 2001 From: ZyX Date: Thu, 19 Feb 2015 02:56:05 +0300 Subject: [PATCH 42/43] Fix typo in release script --- scripts/powerline-release.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/powerline-release.py b/scripts/powerline-release.py index 2d3a7f10..242beccd 100755 --- a/scripts/powerline-release.py +++ b/scripts/powerline-release.py @@ -86,7 +86,8 @@ def merge(version_string, rev, **kwargs): '--strategy', 'recursive', '--strategy-option', 'theirs', '--commit', - '-m', 'Merge branch \'{0}\' into {1}'.format(temp_branch_name, rev)]) + '-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() From ceb0487fe0f7590f6543e79ce3b0bf398326abc5 Mon Sep 17 00:00:00 2001 From: ZyX Date: Thu, 19 Feb 2015 02:56:44 +0300 Subject: [PATCH 43/43] Update base version --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) mode change 100755 => 100644 setup.py diff --git a/setup.py b/setup.py old mode 100755 new mode 100644 index de22136f..2220b4d0 --- a/setup.py +++ b/setup.py @@ -59,7 +59,7 @@ else: def get_version(): - base_version = '2.0' + base_version = '2.1' base_version += '.dev9999' try: return base_version + '+git.' + str(subprocess.check_output(['git', 'rev-parse', 'HEAD']).strip())