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