[pypy-svn] r43966 - in pypy/branch/kill-ctypes/pypy/module/_curses: . test
fijal at codespeak.net
fijal at codespeak.net
Fri Jun 1 07:49:46 CEST 2007
Author: fijal
Date: Fri Jun 1 07:49:45 2007
New Revision: 43966
Added:
pypy/branch/kill-ctypes/pypy/module/_curses/ (props changed)
pypy/branch/kill-ctypes/pypy/module/_curses/__init__.py
pypy/branch/kill-ctypes/pypy/module/_curses/app_curses.py
pypy/branch/kill-ctypes/pypy/module/_curses/fficurses.py
pypy/branch/kill-ctypes/pypy/module/_curses/interp_curses.py
pypy/branch/kill-ctypes/pypy/module/_curses/test/ (props changed)
pypy/branch/kill-ctypes/pypy/module/_curses/test/__init__.py
pypy/branch/kill-ctypes/pypy/module/_curses/test/test_curses.py
Log:
Add a dummy _curses module, just enough to run pyrepl. Still, there
are major concerns about merging this branch:
* storing annotations on __class__ of ExtFunc
* termios exception hacks (annotation)
* seems that lltype.free has some problems with exception_is_here()
(fficurses.py/tigetstr_llimpl)
* we_are_translated in interp_termios, which is ugly.
Added: pypy/branch/kill-ctypes/pypy/module/_curses/__init__.py
==============================================================================
--- (empty file)
+++ pypy/branch/kill-ctypes/pypy/module/_curses/__init__.py Fri Jun 1 07:49:45 2007
@@ -0,0 +1,35 @@
+
+from pypy.interpreter.mixedmodule import MixedModule
+from pypy.module._curses import fficurses
+from pypy.module._curses import interp_curses
+from pypy.rlib.nonconst import NonConstant
+import _curses
+
+class Module(MixedModule):
+ """ Low-level interface for curses module,
+ not meant to be used directly
+ """
+ applevel_name = "_curses"
+
+ appleveldefs = {
+ 'error' : 'app_curses.error',
+ }
+
+ interpleveldefs = {
+ 'setupterm' : 'interp_curses.setupterm',
+ 'tigetstr' : 'interp_curses.tigetstr',
+ 'tparm' : 'interp_curses.tparm',
+ }
+
+ def startup(self, space):
+ # XXX nasty annotation trick
+ try:
+ raise interp_curses.curses_error(NonConstant("xxx"))
+ except _curses.error, e:
+ pass
+
+import _curses
+for i in dir(_curses):
+ val = getattr(_curses, i)
+ if i.isupper() and type(val) is int:
+ Module.interpleveldefs[i] = "space.wrap(%s)" % val
Added: pypy/branch/kill-ctypes/pypy/module/_curses/app_curses.py
==============================================================================
--- (empty file)
+++ pypy/branch/kill-ctypes/pypy/module/_curses/app_curses.py Fri Jun 1 07:49:45 2007
@@ -0,0 +1,3 @@
+
+class error(Exception):
+ pass
Added: pypy/branch/kill-ctypes/pypy/module/_curses/fficurses.py
==============================================================================
--- (empty file)
+++ pypy/branch/kill-ctypes/pypy/module/_curses/fficurses.py Fri Jun 1 07:49:45 2007
@@ -0,0 +1,101 @@
+
+""" The ffi for rpython, need to be imported for side effects
+"""
+
+import sys
+from pypy.rpython.lltypesystem import rffi
+from pypy.rpython.lltypesystem import lltype
+from pypy.rpython.extfunc import register_external
+from pypy.rpython.extregistry import ExtRegistryEntry
+from pypy.module._curses import interp_curses
+from pypy.rpython.lltypesystem import llmemory
+
+# waaa...
+includes = ['curses.h', 'term.h']
+libs = ['curses']
+
+INT = rffi.INT
+INTP = lltype.Ptr(lltype.Array(INT, hints={'nolength':True}))
+c_setupterm = rffi.llexternal('setupterm', [rffi.CCHARP, INT, INTP], INT,
+ includes=includes, libraries=libs)
+c_tigetstr = rffi.llexternal('tigetstr', [rffi.CCHARP], rffi.CCHARP,
+ includes=includes, libraries=libs)
+c_tparm = rffi.llexternal('tparm', [rffi.CCHARP, INT, INT, INT, INT, INT,
+ INT, INT, INT, INT, INT], rffi.CCHARP,
+ includes=includes, libraries=libs)
+
+ERR = rffi.CConstant('ERR', INT)
+OK = rffi.CConstant('OK', INT)
+
+def curses_setupterm(term, fd):
+ intp = lltype.malloc(INTP.TO, 1, flavor='raw')
+ err = c_setupterm(term, fd, intp)
+ try:
+ if err == ERR:
+ if intp[0] == 0:
+ msg = "setupterm: could not find terminal"
+ elif intp[0] == -1:
+ msg = "setupterm: could not find terminfo database"
+ else:
+ msg = "setupterm: unknown error"
+ raise interp_curses.curses_error(msg)
+ interp_curses.module_info.setupterm_called = True
+ finally:
+ lltype.free(intp, flavor='raw')
+
+def curses_setupterm_null_llimpl(fd):
+ curses_setupterm(lltype.nullptr(rffi.CCHARP.TO), fd)
+
+def curses_setupterm_llimpl(term, fd):
+ ll_s = rffi.str2charp(term)
+ try:
+ curses_setupterm(ll_s, fd)
+ finally:
+ lltype.free(ll_s, flavor='raw')
+
+register_external(interp_curses._curses_setupterm_null,
+ [int], llimpl=curses_setupterm_null_llimpl,
+ export_name='_curses.setupterm_null')
+register_external(interp_curses._curses_setupterm,
+ [str, int], llimpl=curses_setupterm_llimpl,
+ export_name='_curses.setupterm')
+
+def check_setup_invoked():
+ if not interp_curses.module_info.setupterm_called:
+ raise interp_curses.curses_error("must call (at least) setupterm() first")
+
+def tigetstr_llimpl(cap):
+ check_setup_invoked()
+ ll_cap = rffi.str2charp(cap)
+ try:
+ ll_res = c_tigetstr(ll_cap)
+ num = lltype.cast_ptr_to_int(ll_res)
+ if num == 0 or num == -1:
+ raise interp_curses.TermError()
+ res = rffi.charp2str(ll_res)
+ # XXX - how to avoid a problem with leaking stuff here???
+ #lltype.free(ll_res, flavor='raw')
+ return res
+ finally:
+ lltype.free(ll_cap, flavor='raw')
+
+register_external(interp_curses._curses_tigetstr, [str], str,
+ export_name='_curses.tigetstr', llimpl=tigetstr_llimpl)
+
+def tparm_llimpl(s, args):
+ check_setup_invoked()
+ l = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+ for i in range(min(len(args), 10)):
+ l[i] = args[i]
+ ll_s = rffi.str2charp(s)
+ # XXX nasty trick stolen from CPython
+ ll_res = c_tparm(ll_s, l[0], l[1], l[2], l[3], l[4], l[5], l[6],
+ l[7], l[8], l[9])
+ lltype.free(ll_s, flavor='raw')
+ # XXX - how to make this happy?
+ # lltype.free(ll_res, flavor.raw)
+ return rffi.charp2str(ll_res)
+
+register_external(interp_curses._curses_tparm, [str, [int]], str,
+ export_name='_curses.tparm', llimpl=tparm_llimpl)
+
Added: pypy/branch/kill-ctypes/pypy/module/_curses/interp_curses.py
==============================================================================
--- (empty file)
+++ pypy/branch/kill-ctypes/pypy/module/_curses/interp_curses.py Fri Jun 1 07:49:45 2007
@@ -0,0 +1,77 @@
+
+from pypy.interpreter.baseobjspace import ObjSpace, W_Root
+from pypy.interpreter.error import OperationError
+
+import _curses
+
+class ModuleInfo:
+ def __init__(self):
+ self.setupterm_called = False
+
+module_info = ModuleInfo()
+
+class curses_error(_curses.error):
+ def __init__(self, msg):
+ self.args = [msg]
+
+def convert_error(space, error):
+ msg = error.args[0]
+ w_module = space.getbuiltinmodule('_curses')
+ w_exception_class = space.getattr(w_module, space.wrap('error'))
+ w_exception = space.call_function(w_exception_class, space.wrap(msg))
+ return OperationError(w_exception_class, w_exception)
+
+def _curses_setupterm_null(fd):
+ # NOT_RPYTHON
+ _curses.setupterm(None, fd)
+
+def _curses_setupterm(termname, fd):
+ # NOT_RPYTHON
+ _curses.setupterm(termname, fd)
+
+def setupterm(space, w_termname=None, fd=-1):
+ if fd == -1:
+ w_stdout = space.getattr(space.getbuiltinmodule('sys'),
+ space.wrap('stdout'))
+ fd = space.int_w(space.call_function(space.getattr(w_stdout,
+ space.wrap('fileno'))))
+ try:
+ if space.is_w(w_termname, space.w_None) or w_termname is None:
+ _curses_setupterm_null(fd)
+ else:
+ _curses_setupterm(space.str_w(w_termname), fd)
+ except _curses.error, e:
+ raise convert_error(space, e)
+setupterm.unwrap_spec = [ObjSpace, W_Root, int]
+
+class TermError(Exception):
+ pass
+
+def _curses_tigetstr(capname):
+ # NOT_RPYTHON
+ res = _curses.tigetstr(capname)
+ if res is None:
+ raise TermError
+ return res
+
+def _curses_tparm(s, args):
+ # NOT_RPYTHON
+ return _curses.tparm(s, *args)
+
+def tigetstr(space, capname):
+ try:
+ result = _curses_tigetstr(capname)
+ except TermError:
+ return space.w_None
+ except _curses.error, e:
+ raise convert_error(space, e)
+ return space.wrap(result)
+tigetstr.unwrap_spec = [ObjSpace, str]
+
+def tparm(space, s, args_w):
+ args = [space.int_w(a) for a in args_w]
+ try:
+ return space.wrap(_curses_tparm(s, args))
+ except _curses.error, e:
+ raise convert_error(space, e)
+tparm.unwrap_spec = [ObjSpace, str, 'args_w']
Added: pypy/branch/kill-ctypes/pypy/module/_curses/test/__init__.py
==============================================================================
Added: pypy/branch/kill-ctypes/pypy/module/_curses/test/test_curses.py
==============================================================================
--- (empty file)
+++ pypy/branch/kill-ctypes/pypy/module/_curses/test/test_curses.py Fri Jun 1 07:49:45 2007
@@ -0,0 +1,89 @@
+
+from pypy.translator.c.test.test_genc import compile
+from pypy.module._curses import interp_curses
+from pypy.module._curses import fficurses
+from pypy.conftest import gettestobjspace
+from pypy.tool.autopath import pypydir
+from pypy.tool.udir import udir
+import py
+import sys
+
+class AppTestCurses(object):
+ def setup_class(cls):
+ cls.space = gettestobjspace(usemodules=['_curses'])
+
+ def test_tigetstr(self):
+ import _curses
+ _curses.setupterm()
+ assert _curses.tigetstr('cup') == '\x1b[%i%p1%d;%p2%dH'
+
+ def test_tparm(self):
+ import _curses
+ _curses.setupterm()
+ assert _curses.tparm(_curses.tigetstr('cup'), 5, 3) == '\033[6;4H'
+
+class TestCurses(object):
+ """ We need to fork here, to prevent
+ the setup to be done
+ """
+ def _spawn(self, *args, **kwds):
+ import pexpect
+ print 'SPAWN:', args, kwds
+ child = pexpect.spawn(*args, **kwds)
+ child.logfile = sys.stdout
+ return child
+
+ def spawn(self, argv):
+ py_py = py.path.local(pypydir).join('bin', 'py.py')
+ return self._spawn(sys.executable, [str(py_py)] + argv)
+
+ def setup_class(self):
+ try:
+ import pexpect
+ except ImportError:
+ py.test.skip('pexpect not found')
+
+ def test_setupterm(self):
+ source = py.code.Source("""
+ import _curses
+ try:
+ _curses.tigetstr('cup')
+ except _curses.error:
+ print 'ok!'
+ """)
+ f = udir.join("test_setupterm.py")
+ f.write(source)
+ child = self.spawn(['--withmod-_curses', str(f)])
+ child.expect('ok!')
+
+# XXX probably we need to run all the stuff here in pexpect anyway...
+
+class TestCCurses(object):
+ """ Test compiled version
+ """
+ def test_csetupterm(self):
+ def runs_setupterm():
+ interp_curses._curses_setupterm_null(1)
+
+ fn = compile(runs_setupterm, [])
+ fn()
+
+ def test_ctgetstr(self):
+ def runs_ctgetstr():
+ interp_curses._curses_setupterm("xterm", 1)
+ res = interp_curses._curses_tigetstr('cup')
+ assert res == '\x1b[%i%p1%d;%p2%dH'
+
+ fn = compile(runs_ctgetstr, [])
+ fn()
+
+ def test_ctparm(self):
+ def runs_tparm():
+ interp_curses._curses_setupterm("xterm", 1)
+ cup = interp_curses._curses_tigetstr('cup')
+ res = interp_curses._curses_tparm(cup, [5, 3])
+ assert res == '\033[6;4H'
+
+ fn = compile(runs_tparm, [])
+ fn()
+
More information about the pypy-svn
mailing list