Author: Matti Picus <[email protected]>
Branch: py3.7
Changeset: r98594:55e4d78197be
Date: 2020-01-29 22:05 +0200
http://bitbucket.org/pypy/pypy/changeset/55e4d78197be/
Log: merge py3.6 into branch
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-python/3/venv/__init__.py b/lib-python/3/venv/__init__.py
--- a/lib-python/3/venv/__init__.py
+++ b/lib-python/3/venv/__init__.py
@@ -187,6 +187,9 @@
logger.warning('Unable to symlink %r to %r', src, dst)
force_copy = True
if force_copy:
+ if os.path.isdir(src):
+ shutil.copytree(src, dst)
+ else:
shutil.copyfile(src, dst)
else:
def symlink_or_copy(self, src, dst, relative_symlinks_ok=False):
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
@@ -57,7 +58,7 @@
if key_n == b"UNKNOWN KEY":
continue
if not isinstance(key_n, str): # python 3
- key_n = key_n.decode()
+ key_n = key_n.decode('utf-8')
key_n = key_n.replace('(', '').replace(')', '')
globals()[key_n] = key
@@ -83,7 +84,9 @@
def _ensure_initialised_color():
- if not _initialised and _initialised_color:
+ if not _initialised:
+ raise error("must call initscr() first")
+ if not _initialised_color:
raise error("must call start_color() first")
@@ -173,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:
@@ -216,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:
@@ -286,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)
@@ -300,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)
@@ -333,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
@@ -434,11 +488,16 @@
val = lib.keyname(val)
if val == ffi.NULL:
return ""
- return ffi.string(val)
+ key_n = ffi.string(val)
+ if not isinstance(key_n, str):
+ key_n = key_n.decode('utf-8')
+ return key_n
@_argspec(0, 1, 2)
def getstr(self, y, x, n=1023):
n = min(n, 1023)
+ if n < 0:
+ raise ValueError("'n' must be nonnegative")
buf = ffi.new("char[1024]") # /* This should be big enough.. I hope */
if y is None:
@@ -481,6 +540,8 @@
@_argspec(0, 1, 2)
def instr(self, y, x, n=1023):
n = min(n, 1023)
+ if n < 0:
+ raise ValueError("'n' must be nonnegative")
buf = ffi.new("char[1024]") # /* This should be big enough.. I hope */
if y is None:
code = lib.winnstr(self._win, buf, n)
@@ -493,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)
@@ -507,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)
@@ -601,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:
@@ -625,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")
@@ -812,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):
@@ -1021,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):
diff --git a/lib_pypy/_sysconfigdata.py b/lib_pypy/_sysconfigdata.py
--- a/lib_pypy/_sysconfigdata.py
+++ b/lib_pypy/_sysconfigdata.py
@@ -47,4 +47,5 @@
build_time_vars['CC'] += ' -arch %s' % (arch,)
if "CXX" in build_time_vars:
build_time_vars['CXX'] += ' -arch %s' % (arch,)
+ build_time_vars['MACOSX_DEPLOYMENT_TARGET'] = '10.7'
diff --git a/pypy/conftest.py b/pypy/conftest.py
--- a/pypy/conftest.py
+++ b/pypy/conftest.py
@@ -68,6 +68,11 @@
if not mode_A and not mode_D: # 'own' tests
from rpython.conftest import LeakFinder
config.pluginmanager.register(LeakFinder())
+ if mode_A:
+ from pypy.tool.pytest.apptest import PythonInterpreter
+ config.applevel = PythonInterpreter(config.option.python)
+ else:
+ config.applevel = None
def pytest_addoption(parser):
group = parser.getgroup("pypy options")
@@ -201,13 +206,17 @@
@pytest.hookimpl(tryfirst=True)
def pytest_runtest_setup(item):
if isinstance(item, py.test.collect.Function):
+ config = item.config
+ if item.get_marker(name='pypy_only'):
+ if config.applevel is not None and not config.applevel.is_pypy:
+ pytest.skip('PyPy-specific test')
appclass = item.getparent(py.test.Class)
if appclass is not None:
from pypy.tool.pytest.objspace import gettestobjspace
# Make cls.space and cls.runappdirect available in tests.
spaceconfig = getattr(appclass.obj, 'spaceconfig', {})
appclass.obj.space = gettestobjspace(**spaceconfig)
- appclass.obj.runappdirect = option.runappdirect
+ appclass.obj.runappdirect = config.option.runappdirect
def pytest_ignore_collect(path, config):
if (config.getoption('direct_apptest') and not path.isdir()
diff --git a/pypy/interpreter/test/test_argument.py
b/pypy/interpreter/test/test_argument.py
--- a/pypy/interpreter/test/test_argument.py
+++ b/pypy/interpreter/test/test_argument.py
@@ -806,7 +806,7 @@
exc = raises(TypeError, '(lambda *, kw: 0)(1, kw=3)')
assert str(exc.value) == "<lambda>() takes 0 positional arguments but
1 positional argument (and 1 keyword-only argument) were given"
- @py.test.mark.skipif("config.option.runappdirect")
+ @pytest.mark.pypy_only
def test_error_message_method(self):
class A(object):
def f0():
@@ -823,14 +823,14 @@
# does not contain the warning about missing self
assert exc.value.args[0] == "f0() takes 0 positional arguments but 1
was given"
- @py.test.mark.skipif("config.option.runappdirect")
def test_error_message_module_function(self):
import operator # use countOf because it's defined at applevel
exc = raises(TypeError, lambda : operator.countOf(1, 2, 3))
- # does not contain the warning about missing self
- assert exc.value.args[0] == "countOf() takes 2 positional arguments
but 3 were given"
+ # does not contain the warning
+ # 'Did you forget 'self' in the function definition?'
+ assert 'self' not in str(exc.value)
- @py.test.mark.skipif("config.option.runappdirect")
+ @pytest.mark.pypy_only
def test_error_message_bound_method(self):
class A(object):
def f0():
diff --git a/pypy/module/__builtin__/test/test_abstractinst.py
b/pypy/module/__builtin__/test/test_abstractinst.py
--- a/pypy/module/__builtin__/test/test_abstractinst.py
+++ b/pypy/module/__builtin__/test/test_abstractinst.py
@@ -215,7 +215,7 @@
def test_dont_call_instancecheck_fast_path(self):
called = []
-
+
class M(type):
def __instancecheck__(self, obj):
called.append("called")
@@ -272,9 +272,30 @@
except Special:
pass
+ def test_exception_bad_subclasscheck(self):
+ """
+ import sys
+ class Meta(type):
+ def __subclasscheck__(cls, subclass):
+ raise ValueError()
+
+ class MyException(Exception, metaclass=Meta):
+ pass
+
+ try:
+ raise KeyError()
+ except MyException as e:
+ assert False, "exception should not be a MyException"
+ except KeyError:
+ pass
+ except:
+ assert False, "Should have raised KeyError"
+ else:
+ assert False, "Should have raised KeyError"
+ """
+
def test_exception_contains_type_name(self):
with raises(TypeError) as e:
issubclass(type, None)
print(e.value)
assert "NoneType" in str(e.value)
-
diff --git a/pypy/module/_multibytecodec/c_codecs.py
b/pypy/module/_multibytecodec/c_codecs.py
--- a/pypy/module/_multibytecodec/c_codecs.py
+++ b/pypy/module/_multibytecodec/c_codecs.py
@@ -194,17 +194,23 @@
rffi.SSIZE_T)
pypy_cjk_enc_getcodec = llexternal('pypy_cjk_enc_getcodec',
[ENCODEBUF_P], MULTIBYTECODEC_P)
+pypy_cjk_enc_copystate = llexternal('pypy_cjk_enc_copystate',
+ [ENCODEBUF_P, ENCODEBUF_P], lltype.Void)
MBENC_FLUSH = 1
MBENC_RESET = 2
def encode(codec, unicodedata, length, errors="strict", errorcb=None,
- namecb=None):
+ namecb=None, copystate=lltype.nullptr(ENCODEBUF_P.TO)):
encodebuf = pypy_cjk_enc_new(codec)
if not encodebuf:
raise MemoryError
+ if copystate:
+ pypy_cjk_enc_copystate(encodebuf, copystate)
try:
return encodeex(encodebuf, unicodedata, length, errors, errorcb,
namecb)
finally:
+ if copystate:
+ pypy_cjk_enc_copystate(copystate, encodebuf)
pypy_cjk_enc_free(encodebuf)
def encodeex(encodebuf, utf8data, length, errors="strict", errorcb=None,
@@ -257,22 +263,21 @@
raise EncodeDecodeError(start, end, reason)
elif errors == "ignore":
replace = ""
+ rettype = 'b' # != 'u'
elif errors == "replace":
- codec = pypy_cjk_enc_getcodec(encodebuf)
- try:
- replace = encode(codec, "?", 1)
- except EncodeDecodeError:
- replace = "?"
+ replace = "?" # utf-8 unicode
+ rettype = 'u'
else:
assert errorcb
replace, end, rettype = errorcb(errors, namecb, reason,
unicodedata, start, end)
- if rettype == 'u':
- codec = pypy_cjk_enc_getcodec(encodebuf)
- lgt = rutf8.check_utf8(replace, False)
- replace = encode(codec, replace, lgt)
- lgt = len(replace)
+ if rettype == 'u':
+ codec = pypy_cjk_enc_getcodec(encodebuf)
+ lgt = rutf8.check_utf8(replace, False)
+ replace = encode(codec, replace, lgt, copystate=encodebuf)
+ #else:
+ # replace is meant to be a byte string already
with rffi.scoped_nonmovingbuffer(replace) as inbuf:
- r = pypy_cjk_enc_replace_on_error(encodebuf, inbuf, lgt, end)
+ r = pypy_cjk_enc_replace_on_error(encodebuf, inbuf, len(replace), end)
if r == MBERR_NOMEMORY:
raise MemoryError
diff --git a/pypy/module/_multibytecodec/src/cjkcodecs/multibytecodec.c
b/pypy/module/_multibytecodec/src/cjkcodecs/multibytecodec.c
--- a/pypy/module/_multibytecodec/src/cjkcodecs/multibytecodec.c
+++ b/pypy/module/_multibytecodec/src/cjkcodecs/multibytecodec.c
@@ -135,6 +135,11 @@
return d;
}
+void pypy_cjk_enc_copystate(struct pypy_cjk_enc_s *dst, struct pypy_cjk_enc_s
*src)
+{
+ dst->state = src->state;
+}
+
Py_ssize_t pypy_cjk_enc_init(struct pypy_cjk_enc_s *d,
Py_UNICODE *inbuf, Py_ssize_t inlen)
{
diff --git a/pypy/module/_multibytecodec/src/cjkcodecs/multibytecodec.h
b/pypy/module/_multibytecodec/src/cjkcodecs/multibytecodec.h
--- a/pypy/module/_multibytecodec/src/cjkcodecs/multibytecodec.h
+++ b/pypy/module/_multibytecodec/src/cjkcodecs/multibytecodec.h
@@ -146,6 +146,8 @@
char *, pypymbc_ssize_t,
pypymbc_ssize_t);
RPY_EXTERN
const MultibyteCodec *pypy_cjk_enc_getcodec(struct pypy_cjk_enc_s *);
+RPY_EXTERN
+void pypy_cjk_enc_copystate(struct pypy_cjk_enc_s *dst, struct pypy_cjk_enc_s
*src);
/* list of codecs defined in the .c files */
diff --git a/pypy/module/_multibytecodec/test/test_app_codecs.py
b/pypy/module/_multibytecodec/test/test_app_codecs.py
--- a/pypy/module/_multibytecodec/test/test_app_codecs.py
+++ b/pypy/module/_multibytecodec/test/test_app_codecs.py
@@ -126,3 +126,33 @@
lambda e: (b'\xc3', e.end))
result = "\uDDA1".encode("gbk",
"test.test_encode_custom_error_handler_type")
assert b'\xc3' in result
+
+ def test_encode_replacement_with_state(self):
+ import codecs
+ s = u'\u4ee4\u477c\u4ee4'.encode("iso-2022-jp", errors="replace")
+ assert s == b'\x1b$BNa\x1b(B?\x1b$BNa\x1b(B'
+
+ def test_streaming_codec(self):
+ test_0 = u'\uc5fc\u76d0\u5869\u9e7d\u477c\u4e3d/\u3012'
+ test_1 =
u'\u4ee4\u477c\u3080\u304b\u3057\u3080\u304b\u3057\u3042\u308b\u3068\u3053\u308d\u306b'
+ test_2 = u' foo = "Quoted string ****\u4ee4\u477c" '
+
+ ereplace = {'errors': 'replace'}
+ exml = {'errors': 'xmlcharrefreplace'}
+ for codec in ("iso-2022-jp", "iso-2022-jp-ext", "iso-2022-jp-1",
+ "iso-2022-jp-2", "iso-2022-jp-3", "iso-2022-jp-2004",
+ "iso-2022-kr",
+ ):
+
+ out_1 = test_1.encode(codec, **ereplace).decode(codec, **ereplace)
+ assert
out_1.endswith(u'\u3080\u304b\u3057\u3080\u304b\u3057\u3042\u308b\u3068\u3053\u308d\u306b')
+
+ out_0a = test_0.encode(codec, **ereplace).decode(codec, **ereplace)
+ for n, char in enumerate(out_0a):
+ assert char in (test_0[n], "?")
+
+ out_0b = test_0.encode(codec, **exml).decode(codec, **ereplace)
+ assert "䝼" in out_0b
+
+ out_2 = test_2.encode(codec, **ereplace).decode(codec, **ereplace)
+ assert out_2.count('"') == 2
diff --git a/pypy/module/cpyext/codecs.py b/pypy/module/cpyext/codecs.py
--- a/pypy/module/cpyext/codecs.py
+++ b/pypy/module/cpyext/codecs.py
@@ -20,3 +20,12 @@
else:
return space.call_method(w_codec, "incrementaldecoder")
+@cpython_api([CONST_STRING], PyObject)
+def PyCodec_Encoder(space, encoding):
+ w_codec = interp_codecs.lookup_codec(space, rffi.charp2str(encoding))
+ return space.getitem(w_codec, space.newint(0))
+
+@cpython_api([CONST_STRING], PyObject)
+def PyCodec_Decoder(space, encoding):
+ w_codec = interp_codecs.lookup_codec(space, rffi.charp2str(encoding))
+ return space.getitem(w_codec, space.newint(1))
diff --git a/pypy/module/cpyext/include/Python.h
b/pypy/module/cpyext/include/Python.h
--- a/pypy/module/cpyext/include/Python.h
+++ b/pypy/module/cpyext/include/Python.h
@@ -123,6 +123,7 @@
#include "sliceobject.h"
#include "genobject.h"
#include "datetime.h"
+#include "structseq.h"
#include "pystate.h"
#include "fileobject.h"
#include "pysignals.h"
diff --git a/pypy/module/cpyext/test/test_codecs.py
b/pypy/module/cpyext/test/test_codecs.py
--- a/pypy/module/cpyext/test/test_codecs.py
+++ b/pypy/module/cpyext/test/test_codecs.py
@@ -2,7 +2,8 @@
from pypy.module.cpyext.test.test_api import BaseApiTest
from rpython.rtyper.lltypesystem import rffi
from pypy.module.cpyext.codecs import (
- PyCodec_IncrementalEncoder, PyCodec_IncrementalDecoder)
+ PyCodec_IncrementalEncoder, PyCodec_IncrementalDecoder,
+ PyCodec_Encoder, PyCodec_Decoder)
class TestCodecs(BaseApiTest):
def test_incremental(self, space):
@@ -13,3 +14,13 @@
w_decoded = space.call_method(w_decoder, 'decode', w_encoded)
assert space.utf8_w(w_decoded) == u'späm'.encode("utf-8")
rffi.free_charp(utf8)
+
+ def test_encoder_decoder(self, space):
+ utf8 = rffi.str2charp('utf-8')
+ w_encoder = PyCodec_Encoder(space, utf8)
+ w_decoder = PyCodec_Decoder(space, utf8)
+ rffi.free_charp(utf8)
+ space.appexec([w_encoder, w_decoder], r"""(encoder, decoder):
+ assert encoder(u"\u1234") == (b"\xe1\x88\xb4", 1)
+ assert decoder(b"\xe1\x88\xb4") == (u"\u1234", 3)
+ """)
diff --git a/pypy/tool/pytest/apptest.py b/pypy/tool/pytest/apptest.py
--- a/pypy/tool/pytest/apptest.py
+++ b/pypy/tool/pytest/apptest.py
@@ -35,6 +35,24 @@
def __init__(self, excinfo):
self.excinfo = excinfo
+class PythonInterpreter(object):
+ def __init__(self, path):
+ self.path = path
+ self._is_pypy = None
+
+ @property
+ def is_pypy(self):
+ if self._is_pypy is not None:
+ return self._is_pypy
+ CODE = "import sys; print('__pypy__' in sys.builtin_module_names)"
+ res, stdout, stderr = run_subprocess( self.path, ["-c", CODE])
+ if res != 0:
+ raise ValueError("Invalid Python interpreter")
+ print stdout
+ is_pypy = stdout.strip() == 'True'
+ self._is_pypy = is_pypy
+ return is_pypy
+
def py3k_repr(value):
"return the repr() that py3k would give for an object."""
@@ -120,7 +138,7 @@
pytest.fail("DID NOT RAISE")
self.value = tp[1]
return issubclass(tp[0], self.expected_exception)
-
+
__builtins__.raises = raises
class Test:
pass
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit