Author: Ronny Pfannschmidt <[email protected]>
Branch:
Changeset: r220:7a5bb323410c
Date: 2013-01-15 22:58 +0100
http://bitbucket.org/pypy/pyrepl/changeset/7a5bb323410c/
Log: merge codecheck clean
diff --git a/.hgignore b/.hgignore
--- a/.hgignore
+++ b/.hgignore
@@ -1,4 +1,5 @@
dist/
build/
+.cache/
\.tox/
.*\.egg-info
diff --git a/pyrepl/_minimal_curses.py b/pyrepl/_minimal_curses.py
--- a/pyrepl/_minimal_curses.py
+++ b/pyrepl/_minimal_curses.py
@@ -9,7 +9,8 @@
hide this one if compiled in.
"""
-import ctypes, ctypes.util
+import ctypes.util
+
class error(Exception):
pass
@@ -42,8 +43,12 @@
# ____________________________________________________________
-try: from __pypy__ import builtinify
-except ImportError: builtinify = lambda f: f
+try:
+ from __pypy__ import builtinify
+ builtinify # silence broken pyflakes
+except ImportError:
+ builtinify = lambda f: f
+
@builtinify
def setupterm(termstr, fd):
@@ -52,6 +57,7 @@
if result == ERR:
raise error("setupterm() failed (err=%d)" % err.value)
+
@builtinify
def tigetstr(cap):
if not isinstance(cap, bytes):
@@ -61,6 +67,7 @@
return None
return ctypes.cast(result, ctypes.c_char_p).value
+
@builtinify
def tparm(str, i1=0, i2=0, i3=0, i4=0, i5=0, i6=0, i7=0, i8=0, i9=0):
result = clib.tparm(str, i1, i2, i3, i4, i5, i6, i7, i8, i9)
diff --git a/pyrepl/cmdrepl.py b/pyrepl/cmdrepl.py
--- a/pyrepl/cmdrepl.py
+++ b/pyrepl/cmdrepl.py
@@ -35,26 +35,28 @@
from __future__ import print_function
-from pyrepl import completing_reader as cr, reader, completer
+from pyrepl import completer
from pyrepl.completing_reader import CompletingReader as CR
import cmd
+
class CmdReader(CR):
def collect_keymap(self):
return super(CmdReader, self).collect_keymap() + (
("\\M-\\n", "invalid-key"),
("\\n", "accept"))
-
- CR_init = CR.__init__
+
def __init__(self, completions):
- self.CR_init(self)
+ super(CmdReader, self).__init__()
self.completions = completions
def get_completions(self, stem):
if len(stem) != self.pos:
return []
- return sorted(set(s for s in self.completions
- if s.startswith(stem)))
+ return sorted(set(s
+ for s in self.completions
+ if s.startswith(stem)))
+
def replize(klass, history_across_invocations=1):
@@ -71,26 +73,25 @@
for s in completer.get_class_members(klass)
if s.startswith("do_")]
- if not issubclass(klass, cmd.Cmd):
- raise Exception
+ assert issubclass(klass, cmd.Cmd)
# if klass.cmdloop.im_class is not cmd.Cmd:
# print "this may not work"
- class CmdRepl(klass):
- k_init = klass.__init__
+ class MultiHist(object):
+ __history = []
- if history_across_invocations:
- _CmdRepl__history = []
- def __init__(self, *args, **kw):
- self.k_init(*args, **kw)
- self.__reader = CmdReader(completions)
- self.__reader.history = CmdRepl._CmdRepl__history
- self.__reader.historyi = len(CmdRepl._CmdRepl__history)
- else:
- def __init__(self, *args, **kw):
- self.k_init(*args, **kw)
- self.__reader = CmdReader(completions)
-
+ def __init__(self, *args, **kw):
+ super(MultiHist, self).__init__(*args, **kw)
+ self.__reader = CmdReader(completions)
+ self.__reader.history = self.__history
+ self.__reader.historyi = len(self.__history)
+
+ class SimpleHist(object):
+ def __init__(self, *args, **kw):
+ super(SimpleHist, self).__init__(*args, **kw)
+ self.__reader = CmdReader(completions)
+
+ class CmdLoopMixin(object):
def cmdloop(self, intro=None):
self.preloop()
if intro is not None:
@@ -113,6 +114,8 @@
stop = self.postcmd(stop, line)
self.postloop()
- CmdRepl.__name__ = "replize(%s.%s)"%(klass.__module__, klass.__name__)
+ hist = MultiHist if history_across_invocations else SimpleHist
+
+ class CmdRepl(hist, CmdLoopMixin, klass):
+ __name__ = "replize(%s.%s)" % (klass.__module__, klass.__name__)
return CmdRepl
-
diff --git a/pyrepl/completer.py b/pyrepl/completer.py
--- a/pyrepl/completer.py
+++ b/pyrepl/completer.py
@@ -19,10 +19,12 @@
try:
import __builtin__ as builtins
+ builtins # silence broken pyflakes
except ImportError:
import builtins
-class Completer:
+
+class Completer(object):
def __init__(self, ns):
self.ns = ns
@@ -79,11 +81,10 @@
matches.append("%s.%s" % (expr, word))
return matches
+
def get_class_members(klass):
ret = dir(klass)
if hasattr(klass, '__bases__'):
for base in klass.__bases__:
ret = ret + get_class_members(base)
return ret
-
-
diff --git a/pyrepl/completing_reader.py b/pyrepl/completing_reader.py
--- a/pyrepl/completing_reader.py
+++ b/pyrepl/completing_reader.py
@@ -18,11 +18,12 @@
# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+import re
from pyrepl import commands, reader
from pyrepl.reader import Reader
-def prefix(wordlist, j = 0):
+def prefix(wordlist, j=0):
d = {}
i = j
try:
@@ -36,14 +37,18 @@
except IndexError:
return wordlist[0][j:i]
-import re
+
+STRIPCOLOR_REGEX = re.compile(r"\x1B\[([0-9]{1,3}(;[0-9]{1,2})?)?[m|K]")
+
+
def stripcolor(s):
- return stripcolor.regexp.sub('', s)
-stripcolor.regexp = re.compile(r"\x1B\[([0-9]{1,3}(;[0-9]{1,2})?)?[m|K]")
+ return STRIPCOLOR_REGEX.regexp.sub('', s)
+
def real_len(s):
return len(stripcolor(s))
+
def left_align(s, maxlen):
stripped = stripcolor(s)
if len(stripped) > maxlen:
@@ -52,6 +57,7 @@
padding = maxlen - len(stripped)
return s + ' '*padding
+
def build_menu(cons, wordlist, start, use_brackets, sort_in_column):
if use_brackets:
item = "[ %s ]"
@@ -66,14 +72,14 @@
if sort_in_column:
# sort_in_column=False (default) sort_in_column=True
# A B C A D G
- # D E F B E
+ # D E F B E
# G C F
#
# "fill" the table with empty words, so we always have the same amout
# of rows for each column
missing = cols*rows - len(wordlist)
wordlist = wordlist + ['']*missing
- indexes = [(i%cols)*rows + i//cols for i in range(len(wordlist))]
+ indexes = [(i % cols) * rows + i // cols for i in range(len(wordlist))]
wordlist = [wordlist[i] for i in indexes]
menu = []
i = start
@@ -84,14 +90,14 @@
i += 1
if i >= len(wordlist):
break
- menu.append( ''.join(row) )
+ menu.append(''.join(row))
if i >= len(wordlist):
i = 0
break
if r + 5 > cons.height:
- menu.append(" %d more... "%(len(wordlist) - i))
+ menu.append(" %d more... " % (len(wordlist) - i))
break
- return menu, i
+ return menu, i
# this gets somewhat user interface-y, and as a result the logic gets
# very convoluted.
@@ -118,7 +124,7 @@
# only if the ``assume_immutable_completions`` is True.
#
# now it gets complicated.
-#
+#
# for the first press of a completion key:
# if there's a common prefix, stick it in.
@@ -140,22 +146,22 @@
# for subsequent bangs, rotate the menu around (if there are sufficient
# choices).
+
class complete(commands.Command):
def do(self):
r = self.reader
+ last_is_completer = r.last_command_is(self.__class__)
+ immutable_completions = r.assume_immutable_completions
+ completions_unchangable = last_is_completer and immutable_completions
stem = r.get_stem()
- if r.assume_immutable_completions and \
- r.last_command_is(self.__class__):
- completions = r.cmpltn_menu_choices
- else:
- r.cmpltn_menu_choices = completions = \
- r.get_completions(stem)
- if len(completions) == 0:
+ if not completions_unchangable:
+ r.cmpltn_menu_choices = r.get_completions(stem)
+
+ completions = r.cmpltn_menu_choices
+ if not completions:
r.error("no matches")
elif len(completions) == 1:
- if r.assume_immutable_completions and \
- len(completions[0]) == len(stem) and \
- r.last_command_is(self.__class__):
+ if completions_unchangable and len(completions[0]) == len(stem):
r.msg = "[ sole completion ]"
r.dirty = 1
r.insert(completions[0][len(stem):])
@@ -163,7 +169,7 @@
p = prefix(completions, len(stem))
if p:
r.insert(p)
- if r.last_command_is(self.__class__):
+ if last_is_completer:
if not r.cmpltn_menu_vis:
r.cmpltn_menu_vis = 1
r.cmpltn_menu, r.cmpltn_menu_end = build_menu(
@@ -177,6 +183,7 @@
r.msg = "[ not unique ]"
r.dirty = 1
+
class self_insert(commands.self_insert):
def do(self):
commands.self_insert.do(self)
@@ -195,6 +202,7 @@
else:
r.cmpltn_reset()
+
class CompletingReader(Reader):
"""Adds completion support
@@ -204,26 +212,25 @@
"""
# see the comment for the complete command
assume_immutable_completions = True
- use_brackets = True # display completions inside []
+ use_brackets = True # display completions inside []
sort_in_column = False
-
+
def collect_keymap(self):
return super(CompletingReader, self).collect_keymap() + (
(r'\t', 'complete'),)
-
+
def __init__(self, console):
super(CompletingReader, self).__init__(console)
self.cmpltn_menu = ["[ menu 1 ]", "[ menu 2 ]"]
self.cmpltn_menu_vis = 0
self.cmpltn_menu_end = 0
- for c in [complete, self_insert]:
+ for c in (complete, self_insert):
self.commands[c.__name__] = c
- self.commands[c.__name__.replace('_', '-')] = c
+ self.commands[c.__name__.replace('_', '-')] = c
def after_command(self, cmd):
super(CompletingReader, self).after_command(cmd)
- if not isinstance(cmd, self.commands['complete']) \
- and not isinstance(cmd, self.commands['self_insert']):
+ if not isinstance(cmd, (complete, self_insert)):
self.cmpltn_reset()
def calc_screen(self):
@@ -243,7 +250,7 @@
self.cmpltn_menu = []
self.cmpltn_menu_vis = 0
self.cmpltn_menu_end = 0
- self.cmpltn_menu_choices = []
+ self.cmpltn_menu_choices = []
def get_stem(self):
st = self.syntax_table
@@ -257,11 +264,14 @@
def get_completions(self, stem):
return []
+
def test():
class TestReader(CompletingReader):
def get_completions(self, stem):
- return [s for l in map(lambda x:x.split(),self.history)
- for s in l if s and s.startswith(stem)]
+ return [s for l in self.history
+ for s in l.split()
+ if s and s.startswith(stem)]
+
reader = TestReader()
reader.ps1 = "c**> "
reader.ps2 = "c/*> "
@@ -270,5 +280,6 @@
while reader.readline():
pass
-if __name__=='__main__':
+
+if __name__ == '__main__':
test()
diff --git a/pyrepl/console.py b/pyrepl/console.py
--- a/pyrepl/console.py
+++ b/pyrepl/console.py
@@ -17,6 +17,7 @@
# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
class Event(object):
"""An Event. `evt' is 'key' or somesuch."""
__slots__ = 'evt', 'data', 'raw'
@@ -27,7 +28,8 @@
self.raw = raw
def __repr__(self):
- return 'Event(%r, %r)'%(self.evt, self.data)
+ return 'Event(%r, %r)' % (self.evt, self.data)
+
class Console(object):
"""Attributes:
@@ -36,7 +38,7 @@
height,
width,
"""
-
+
def refresh(self, screen, xy):
pass
diff --git a/pyrepl/unix_eventqueue.py b/pyrepl/unix_eventqueue.py
--- a/pyrepl/unix_eventqueue.py
+++ b/pyrepl/unix_eventqueue.py
@@ -21,6 +21,8 @@
# Bah, this would be easier to test if curses/terminfo didn't have so
# much non-introspectable global state.
+from collections import deque
+
from pyrepl import keymap
from pyrepl.console import Event
from pyrepl import curses
@@ -34,23 +36,23 @@
_keynames = {
- "delete" : "kdch1",
- "down" : "kcud1",
- "end" : "kend",
- "enter" : "kent",
- "f1" : "kf1", "f2" : "kf2", "f3" : "kf3", "f4" : "kf4",
- "f5" : "kf5", "f6" : "kf6", "f7" : "kf7", "f8" : "kf8",
- "f9" : "kf9", "f10" : "kf10", "f11" : "kf11", "f12" : "kf12",
- "f13" : "kf13", "f14" : "kf14", "f15" : "kf15", "f16" : "kf16",
- "f17" : "kf17", "f18" : "kf18", "f19" : "kf19", "f20" : "kf20",
- "home" : "khome",
- "insert" : "kich1",
- "left" : "kcub1",
- "page down" : "knp",
- "page up" : "kpp",
- "right" : "kcuf1",
- "up" : "kcuu1",
- }
+ "delete": "kdch1",
+ "down": "kcud1",
+ "end": "kend",
+ "enter": "kent",
+ "home": "khome",
+ "insert": "kich1",
+ "left": "kcub1",
+ "page down": "knp",
+ "page up": "kpp",
+ "right": "kcuf1",
+ "up": "kcuu1",
+}
+
+
+#function keys x in 1-20 -> fX: kfX
+_keynames.update(('f%d' % i, 'kf%d' % i) for i in range(1, 21))
+
def general_keycodes():
keycodes = {}
@@ -62,7 +64,6 @@
return keycodes
-
def EventQueue(fd, encoding):
keycodes = general_keycodes()
if os.isatty(fd):
@@ -72,16 +73,17 @@
trace('keymap {k!r}', k=k)
return EncodedQueue(k, encoding)
+
class EncodedQueue(object):
def __init__(self, keymap, encoding):
self.k = self.ck = keymap
- self.events = []
+ self.events = deque()
self.buf = bytearray()
- self.encoding=encoding
+ self.encoding = encoding
def get(self):
if self.events:
- return self.events.pop(0)
+ return self.events.popleft()
else:
return None
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -17,7 +17,7 @@
# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-from setuptools import setup, Extension
+from setuptools import setup
long_desc = """\
pyrepl is a Python library, inspired by readline, for building flexible
@@ -31,17 +31,17 @@
setup(
- name = "pyrepl",
- version = "0.8.4",
- author = "Michael Hudson-Doyle",
- author_email = "[email protected]",
+ name="pyrepl",
+ version="0.8.4",
+ author="Michael Hudson-Doyle",
+ author_email="[email protected]",
maintainer="Ronny Pfannschmidt",
maintainer_email="[email protected]",
- url = "http://bitbucket.org/pypy/pyrepl/",
- license = "MIT X11 style",
- description = "A library for building flexible command line interfaces",
- platforms = ["unix", "linux"],
- packages = ["pyrepl" ],
- scripts = ["pythoni", "pythoni1"],
- long_description = long_desc,
- )
+ url="http://bitbucket.org/pypy/pyrepl/",
+ license="MIT X11 style",
+ description="A library for building flexible command line interfaces",
+ platforms=["unix", "linux"],
+ packages=["pyrepl"],
+ scripts=["pythoni", "pythoni1"],
+ long_description=long_desc,
+)
diff --git a/testing/test_unix_reader.py b/testing/test_unix_reader.py
--- a/testing/test_unix_reader.py
+++ b/testing/test_unix_reader.py
@@ -1,9 +1,6 @@
from __future__ import unicode_literals
from pyrepl.unix_eventqueue import EncodedQueue
-from pyrepl import curses
-
-
def test_simple():
q = EncodedQueue({}, 'utf-8')
diff --git a/testing/test_wishes.py b/testing/test_wishes.py
--- a/testing/test_wishes.py
+++ b/testing/test_wishes.py
@@ -24,8 +24,8 @@
def test_quoted_insert_repeat():
- read_spec([(('digit-arg', '3'), ['']),
- (('quoted-insert', None), ['']),
- (('self-insert', '\033'), ['^[^[^[']),
- (('accept', None), None)])
-
+ read_spec([
+ (('digit-arg', '3'), ['']),
+ (('quoted-insert', None), ['']),
+ (('self-insert', '\033'), ['^[^[^[']),
+ (('accept', None), None)])
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit