Skip to content

Commit 8ae5da8

Browse files
merge py3k support branch
2 parents 8e5d9ef + 6e7766e commit 8ae5da8

28 files changed

+432
-348
lines changed

pyrepl/_minimal_curses.py

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
"""Minimal '_curses' module, the low-level interface for curses module
2+
which is not meant to be used directly.
3+
4+
Based on ctypes. It's too incomplete to be really called '_curses', so
5+
to use it, you have to import it and stick it in sys.modules['_curses']
6+
manually.
7+
8+
Note that there is also a built-in module _minimal_curses which will
9+
hide this one if compiled in.
10+
"""
11+
12+
import ctypes, ctypes.util
13+
14+
class error(Exception):
15+
pass
16+
17+
18+
def _find_clib():
19+
trylibs = ['ncurses', 'curses']
20+
21+
for lib in trylibs:
22+
path = ctypes.util.find_library(lib)
23+
if path:
24+
return path
25+
raise ImportError("curses library not found")
26+
27+
_clibpath = _find_clib()
28+
clib = ctypes.cdll.LoadLibrary(_clibpath)
29+
30+
clib.setupterm.argtypes = [ctypes.c_char_p, ctypes.c_int,
31+
ctypes.POINTER(ctypes.c_int)]
32+
clib.setupterm.restype = ctypes.c_int
33+
34+
clib.tigetstr.argtypes = [ctypes.c_char_p]
35+
clib.tigetstr.restype = ctypes.POINTER(ctypes.c_char)
36+
37+
clib.tparm.argtypes = [ctypes.c_char_p] + 9 * [ctypes.c_int]
38+
clib.tparm.restype = ctypes.c_char_p
39+
40+
OK = 0
41+
ERR = -1
42+
43+
# ____________________________________________________________
44+
45+
try: from __pypy__ import builtinify
46+
except ImportError: builtinify = lambda f: f
47+
48+
@builtinify
49+
def setupterm(termstr, fd):
50+
err = ctypes.c_int(0)
51+
result = clib.setupterm(termstr, fd, ctypes.byref(err))
52+
if result == ERR:
53+
raise error("setupterm() failed (err=%d)" % err.value)
54+
55+
@builtinify
56+
def tigetstr(cap):
57+
if not isinstance(cap, bytes):
58+
cap = cap.encode('ascii')
59+
result = clib.tigetstr(cap)
60+
if ctypes.cast(result, ctypes.c_void_p).value == ERR:
61+
return None
62+
return ctypes.cast(result, ctypes.c_char_p).value
63+
64+
@builtinify
65+
def tparm(str, i1=0, i2=0, i3=0, i4=0, i5=0, i6=0, i7=0, i8=0, i9=0):
66+
result = clib.tparm(str, i1, i2, i3, i4, i5, i6, i7, i8, i9)
67+
if result is None:
68+
raise error("tparm() returned NULL")
69+
return result

pyrepl/cmdrepl.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
which is in fact done by the `pythoni' script that comes with
3434
pyrepl."""
3535

36-
from __future__ import nested_scopes
36+
from __future__ import print_function
3737

3838
from pyrepl import completing_reader as cr, reader, completer
3939
from pyrepl.completing_reader import CompletingReader as CR
@@ -96,7 +96,7 @@ def cmdloop(self, intro=None):
9696
if intro is not None:
9797
self.intro = intro
9898
if self.intro:
99-
print self.intro
99+
print(self.intro)
100100
stop = None
101101
while not stop:
102102
if self.cmdqueue:

pyrepl/commands.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,12 @@
3333
class Command(object):
3434
finish = 0
3535
kills_digit_arg = 1
36-
def __init__(self, reader, (event_name, event)):
36+
37+
def __init__(self, reader, event_name, event):
3738
self.reader = reader
3839
self.event = event
3940
self.event_name = event_name
41+
4042
def do(self):
4143
pass
4244

pyrepl/completer.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,10 @@
1717
# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
1818
# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1919

20-
import __builtin__
20+
try:
21+
import __builtin__ as builtins
22+
except ImportError:
23+
import builtins
2124

2225
class Completer:
2326
def __init__(self, ns):
@@ -38,12 +41,11 @@ def global_matches(self, text):
3841
"""
3942
import keyword
4043
matches = []
41-
n = len(text)
4244
for list in [keyword.kwlist,
43-
__builtin__.__dict__.keys(),
45+
builtins.__dict__.keys(),
4446
self.ns.keys()]:
4547
for word in list:
46-
if word[:n] == text and word != "__builtins__":
48+
if word.startswith(text) and word != "__builtins__":
4749
matches.append(word)
4850
return matches
4951

pyrepl/completing_reader.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ def do(self):
168168
r.insert(completions[0][len(stem):])
169169
else:
170170
p = prefix(completions, len(stem))
171-
if p <> '':
171+
if p:
172172
r.insert(p)
173173
if r.last_command_is(self.__class__):
174174
if not r.cmpltn_menu_vis:
@@ -259,7 +259,7 @@ def get_stem(self):
259259
p = self.pos - 1
260260
while p >= 0 and st.get(b[p], SW) == SW:
261261
p -= 1
262-
return u''.join(b[p+1:self.pos])
262+
return ''.join(b[p+1:self.pos])
263263

264264
def get_completions(self, stem):
265265
return []

pyrepl/console.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,9 @@
1717
# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
1818
# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1919

20-
class Event:
20+
class Event(object):
2121
"""An Event. `evt' is 'key' or somesuch."""
22+
__slots__ = 'evt', 'data', 'raw'
2223

2324
def __init__(self, evt, data, raw=''):
2425
self.evt = evt
@@ -28,7 +29,7 @@ def __init__(self, evt, data, raw=''):
2829
def __repr__(self):
2930
return 'Event(%r, %r)'%(self.evt, self.data)
3031

31-
class Console:
32+
class Console(object):
3233
"""Attributes:
3334
3435
screen,

pyrepl/copy_code.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
1818
# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1919

20-
import new
20+
from types import CodeType
2121

2222
def copy_code_with_changes(codeobject,
2323
argcount=None,
@@ -44,7 +44,7 @@ def copy_code_with_changes(codeobject,
4444
if name is None: name = codeobject.co_name
4545
if firstlineno is None: firstlineno = codeobject.co_firstlineno
4646
if lnotab is None: lnotab = codeobject.co_lnotab
47-
return new.code(argcount,
47+
return CodeType(argcount,
4848
nlocals,
4949
stacksize,
5050
flags,

pyrepl/curses.py

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -19,21 +19,5 @@
1919
# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
2020
# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
2121

22-
# Some try-import logic for two purposes: avoiding to bring in the whole
23-
# pure Python curses package if possible; and, in _curses is not actually
24-
# present, falling back to _minimal_curses (which is either a ctypes-based
25-
# pure Python module or a PyPy built-in module).
26-
try:
27-
import _curses
28-
except ImportError:
29-
try:
30-
import _minimal_curses as _curses
31-
except ImportError:
32-
# Who knows, maybe some environment has "curses" but not "_curses".
33-
# If not, at least the following import gives a clean ImportError.
34-
import _curses
3522

36-
setupterm = _curses.setupterm
37-
tigetstr = _curses.tigetstr
38-
tparm = _curses.tparm
39-
error = _curses.error
23+
from ._minimal_curses import setupterm, tigetstr, tparm, error

pyrepl/historical_reader.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@
3333
(r'\C-g', 'isearch-cancel'),
3434
(r'\<backspace>', 'isearch-backspace')])
3535

36-
del c
36+
if 'c' in globals():
37+
del c
3738

3839
ISEARCH_DIRECTION_NONE = ''
3940
ISEARCH_DIRECTION_BACKWARDS = 'r'
@@ -230,7 +231,7 @@ def select_item(self, i):
230231
self.dirty = 1
231232

232233
def get_item(self, i):
233-
if i <> len(self.history):
234+
if i != len(self.history):
234235
return self.transient_history.get(i, self.history[i])
235236
else:
236237
return self.transient_history.get(i, self.get_unicode())
@@ -253,7 +254,7 @@ def prepare(self):
253254
raise
254255

255256
def get_prompt(self, lineno, cursor_on_line):
256-
if cursor_on_line and self.isearch_direction <> ISEARCH_DIRECTION_NONE:
257+
if cursor_on_line and self.isearch_direction != ISEARCH_DIRECTION_NONE:
257258
d = 'rf'[self.isearch_direction == ISEARCH_DIRECTION_FORWARDS]
258259
return "(%s-search `%s') "%(d, self.isearch_term)
259260
else:

pyrepl/input.py

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,10 @@
3232
# executive, temporary decision: [tab] and [C-i] are distinct, but
3333
# [meta-key] is identified with [esc key]. We demand that any console
3434
# class does quite a lot towards emulating a unix terminal.
35-
35+
from __future__ import print_function
3636
from pyrepl import unicodedata_
37+
from collections import deque
38+
3739

3840
class InputTranslator(object):
3941
def push(self, evt):
@@ -43,7 +45,9 @@ def get(self):
4345
def empty(self):
4446
pass
4547

48+
4649
class KeymapTranslator(InputTranslator):
50+
4751
def __init__(self, keymap, verbose=0,
4852
invalid_cls=None, character_cls=None):
4953
self.verbose = verbose
@@ -56,24 +60,25 @@ def __init__(self, keymap, verbose=0,
5660
keyseq = tuple(parse_keys(keyspec))
5761
d[keyseq] = command
5862
if self.verbose:
59-
print d
63+
print(d)
6064
self.k = self.ck = compile_keymap(d, ())
61-
self.results = []
65+
self.results = deque()
6266
self.stack = []
67+
6368
def push(self, evt):
6469
if self.verbose:
65-
print "pushed", evt.data,
70+
print("pushed", evt.data, end='')
6671
key = evt.data
6772
d = self.k.get(key)
6873
if isinstance(d, dict):
6974
if self.verbose:
70-
print "transition"
75+
print("transition")
7176
self.stack.append(key)
7277
self.k = d
7378
else:
7479
if d is None:
7580
if self.verbose:
76-
print "invalid"
81+
print("invalid")
7782
if self.stack or len(key) > 1 or unicodedata_.category(key) == 'C':
7883
self.results.append(
7984
(self.invalid_cls, self.stack + [key]))
@@ -84,14 +89,16 @@ def push(self, evt):
8489
(self.character_cls, [key]))
8590
else:
8691
if self.verbose:
87-
print "matched", d
92+
print("matched", d)
8893
self.results.append((d, self.stack + [key]))
8994
self.stack = []
9095
self.k = self.ck
96+
9197
def get(self):
9298
if self.results:
93-
return self.results.pop(0)
99+
return self.results.popleft()
94100
else:
95101
return None
102+
96103
def empty(self):
97104
return not self.results

0 commit comments

Comments
 (0)