1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
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()
|