[pypy-commit] pypy py3.6: fix _curses for py3.6
mattip
pypy.commits at gmail.com
Sun Jan 26 04:26:26 EST 2020
Author: Matti Picus <matti.picus at gmail.com>
Branch: py3.6
Changeset: r98587:9265d2b9cef6
Date: 2020-01-26 11:25 +0200
http://bitbucket.org/pypy/pypy/changeset/9265d2b9cef6/
Log: fix _curses for py3.6
diff --git a/lib-python/3/test/test_curses.py b/lib-python/3/test/test_curses.py
--- a/lib-python/3/test/test_curses.py
+++ b/lib-python/3/test/test_curses.py
@@ -15,7 +15,8 @@
import tempfile
import unittest
-from test.support import requires, import_module, verbose, SaveSignals
+from test.support import (requires, import_module, verbose, SaveSignals,
+ cpython_only)
# Optionally test curses module. This currently requires that the
# 'curses' resource be given on the regrtest command line using the -u
@@ -315,6 +316,7 @@
msg='userptr should fail since not set'):
p.userptr()
+ @cpython_only
@requires_curses_func('panel')
def test_userptr_memory_leak(self):
w = curses.newwin(10, 10)
@@ -328,6 +330,7 @@
self.assertEqual(sys.getrefcount(obj), nrefs,
"set_userptr leaked references")
+ @cpython_only
@requires_curses_func('panel')
def test_userptr_segfault(self):
w = curses.newwin(10, 10)
@@ -420,20 +423,20 @@
# we will need to rewrite this test.
try:
signature = inspect.signature(stdscr.addch)
- self.assertFalse(signature)
except ValueError:
- # not generating a signature is fine.
- pass
- # So. No signature for addch.
- # But Argument Clinic gave us a human-readable equivalent
- # as the first line of the docstring. So we parse that,
- # and ensure that the parameters appear in the correct order.
- # Since this is parsing output from Argument Clinic, we can
- # be reasonably certain the generated parsing code will be
- # correct too.
- human_readable_signature = stdscr.addch.__doc__.split("\n")[0]
- self.assertIn("[y, x,]", human_readable_signature)
+ # So. No signature for addch.
+ # But Argument Clinic gave us a human-readable equivalent
+ # as the first line of the docstring. So we parse that,
+ # and ensure that the parameters appear in the correct order.
+ # Since this is parsing output from Argument Clinic, we can
+ # be reasonably certain the generated parsing code will be
+ # correct too.
+ human_readable_signature = stdscr.addch.__doc__.split("\n")[0]
+ self.assertIn("[y, x,]", human_readable_signature)
+ else:
+ params = list(signature.parameters.keys())
+ self.assertTrue(params.index('y') < params.index('x'))
def test_issue13051(self):
stdscr = self.stdscr
diff --git a/lib_pypy/_curses.py b/lib_pypy/_curses.py
--- a/lib_pypy/_curses.py
+++ b/lib_pypy/_curses.py
@@ -4,6 +4,7 @@
if sys.platform == 'win32':
#This module does not exist in windows
raise ImportError('No module named _curses')
+import locale
from functools import wraps
from _curses_cffi import ffi, lib
@@ -175,6 +176,40 @@
raise TypeError("bytes or str expected, got a '%s' object"
% (type(text).__name__,))
+def _convert_to_chtype(win, obj):
+ if isinstance(obj, bytes) and len(obj) == 1:
+ value = ord(obj)
+ elif isinstance(obj, str):
+ if len(obj) != 1:
+ raise TypeError("expect bytes or str of length 1 or int, "
+ "got a str of length %d", len(obj))
+ value = ord(obj)
+ if (128 < value):
+ if win:
+ encoding = win.encoding
+ else:
+ encoding = screen_encoding
+ b = obj.encode(encoding)
+ if len(bytes) == 1:
+ value = ord(b)
+ else:
+ OverflowError("byte doesn't fit in chtype")
+ elif isinstance(obj, int):
+ value = obj
+ else:
+ raise TypeError('expect bytes or str of length 1, or int, got %s' % type(obj))
+ return value
+
+def _convert_to_string(win, obj):
+ if isinstance(obj, str):
+ value = obj.encode(win.encoding)
+ elif isinstance(obj, bytes):
+ value = obj
+ else:
+ raise TypeError('expect bytes or str, got %s' % type(obj))
+ if b'\0' in value:
+ raise ValueError('embedded null character')
+ return value
def _extract_yx(args):
if len(args) >= 2:
@@ -218,8 +253,17 @@
class Window(object):
- def __init__(self, window):
+ def __init__(self, window, encoding=None):
+ if encoding is None:
+ # CPython has a win32 branch here, but _curses is not supported
+ # on win32
+ codeset = locale.nl_langinfo(locale.CODESET)
+ if codeset:
+ encoding = codeset
+ else:
+ encoding = 'utf-8'
self._win = window
+ self._encoding = encoding
def __del__(self):
if self._win != lib.stdscr:
@@ -288,7 +332,7 @@
@_argspec(1, 1, 2)
def addstr(self, y, x, text, attr=None):
- text = _bytestype(text)
+ text = _convert_to_string(self, text)
if attr is not None:
attr_old = lib.getattrs(self._win)
lib.wattrset(self._win, attr)
@@ -302,7 +346,7 @@
@_argspec(2, 1, 2)
def addnstr(self, y, x, text, n, attr=None):
- text = _bytestype(text)
+ text = _convert_to_string(self, text)
if attr is not None:
attr_old = lib.getattrs(self._win)
lib.wattrset(self._win, attr)
@@ -335,7 +379,15 @@
_chtype(tl), _chtype(tr), _chtype(bl), _chtype(br))
return None
- def box(self, vertint=0, horint=0):
+ def box(self, *args):
+ if len(args) == 0:
+ vertint = 0
+ horint = 0
+ elif len(args) == 2:
+ vertint = _convert_to_chtype(self, args[0])
+ horint = _convert_to_chtype(self, args[1])
+ else:
+ raise TypeError('verch,horch required')
lib.box(self._win, vertint, horint)
return None
@@ -502,7 +554,7 @@
@_argspec(1, 1, 2)
def insstr(self, y, x, text, attr=None):
- text = _bytestype(text)
+ text = _convert_to_string(self, text)
if attr is not None:
attr_old = lib.getattrs(self._win)
lib.wattrset(self._win, attr)
@@ -516,7 +568,7 @@
@_argspec(2, 1, 2)
def insnstr(self, y, x, text, n, attr=None):
- text = _bytestype(text)
+ text = _convert_to_string(self, text)
if attr is not None:
attr_old = lib.getattrs(self._win)
lib.wattrset(self._win, attr)
@@ -610,7 +662,7 @@
win = lib.subpad(self._win, nlines, ncols, begin_y, begin_x)
else:
win = lib.subwin(self._win, nlines, ncols, begin_y, begin_x)
- return Window(_check_NULL(win))
+ return Window(_check_NULL(win), self.encoding)
def scroll(self, nlines=None):
if nlines is None:
@@ -634,6 +686,23 @@
_check_ERR(lib.wmove(self._win, y, x), "wmove")
return _check_ERR(lib.wvline(self._win, ch | attr, n), "vline")
+ @property
+ def encoding(self):
+ return self._encoding
+
+ @encoding.setter
+ def encoding(self, val):
+ if not val:
+ raise TypeError('encoding may not be deleted')
+ if not isinstance(val, str):
+ raise TypeError('setting encoding to a non-string')
+ encoding = val.encode('ascii')
+ self._encoding = val
+
+ @encoding.deleter
+ def encoding(self):
+ raise TypeError('encoding may not be deleted')
+
beep = _mk_no_return("beep")
def_prog_mode = _mk_no_return("def_prog_mode")
@@ -821,7 +890,9 @@
globals()["LINES"] = lib.LINES
globals()["COLS"] = lib.COLS
- return Window(win)
+ window = Window(win)
+ globals()['screen_encoding'] = window.encoding
+ return window
def setupterm(term=None, fd=-1):
@@ -1030,7 +1101,13 @@
def unget_wch(ch):
_ensure_initialised()
- return _check_ERR(lib.unget_wch(_chtype(ch)), "unget_wch")
+ if isinstance(ch, str):
+ if len(ch) != 1:
+ raise TypeError("expect bytes or str of length1, or int, "
+ "got a str of length %d" % len(ch))
+ elif isinstance(ch, int):
+ ch = chr(ch)
+ return _check_ERR(lib.unget_wch(ch), "unget_wch")
def use_env(flag):
More information about the pypy-commit
mailing list