[pypy-commit] pypy py3.6: hg merge py3.5
rlamy
pypy.commits at gmail.com
Sat Sep 1 09:58:43 EDT 2018
Author: Ronan Lamy <ronan.lamy at gmail.com>
Branch: py3.6
Changeset: r95059:3101fec75c3f
Date: 2018-09-01 15:57 +0200
http://bitbucket.org/pypy/pypy/changeset/3101fec75c3f/
Log: hg merge py3.5
diff --git a/lib_pypy/_ctypes/array.py b/lib_pypy/_ctypes/array.py
--- a/lib_pypy/_ctypes/array.py
+++ b/lib_pypy/_ctypes/array.py
@@ -189,6 +189,7 @@
self._buffer = self._ffiarray(self._length_, autofree=True)
for i, arg in enumerate(args):
self[i] = arg
+ _init_no_arg_ = __init__
def _fix_index(self, index):
if index < 0:
diff --git a/lib_pypy/_ctypes/basics.py b/lib_pypy/_ctypes/basics.py
--- a/lib_pypy/_ctypes/basics.py
+++ b/lib_pypy/_ctypes/basics.py
@@ -110,7 +110,7 @@
raise ValueError(
"Buffer size too small (%d instead of at least %d bytes)"
% (buf.nbytes, offset + size))
- result = self()
+ result = self._newowninstance_()
dest = result._buffer.buffer
try:
raw_addr = buf._pypy_raw_address() + offset
@@ -121,6 +121,11 @@
memmove(dest, raw_addr, size)
return result
+ def _newowninstance_(self):
+ result = self.__new__(self)
+ result._init_no_arg_()
+ return result
+
class CArgObject(object):
""" simple wrapper around buffer, just for the case of freeing
@@ -151,6 +156,7 @@
def __init__(self, *args, **kwds):
raise TypeError("%s has no type" % (type(self),))
+ _init_no_arg_ = __init__
def _ensure_objects(self):
if '_objects' not in self.__dict__:
diff --git a/lib_pypy/_ctypes/function.py b/lib_pypy/_ctypes/function.py
--- a/lib_pypy/_ctypes/function.py
+++ b/lib_pypy/_ctypes/function.py
@@ -267,6 +267,7 @@
return
raise TypeError("Unknown constructor %s" % (args,))
+ _init_no_arg_ = __init__
def _wrap_callable(self, to_call, argtypes):
def f(*args):
@@ -557,7 +558,7 @@
keepalive, newarg, newargtype = self._conv_param(argtype, defval)
else:
import ctypes
- val = argtype._type_()
+ val = argtype._type_._newowninstance_()
keepalive = None
newarg = ctypes.byref(val)
newargtype = type(newarg)
diff --git a/lib_pypy/_ctypes/pointer.py b/lib_pypy/_ctypes/pointer.py
--- a/lib_pypy/_ctypes/pointer.py
+++ b/lib_pypy/_ctypes/pointer.py
@@ -67,8 +67,11 @@
self._buffer = ffiarray(1, autofree=True)
if value is not None:
self.contents = value
+ def _init_no_arg_(self):
+ self._buffer = ffiarray(1, autofree=True)
self._ffiarray = ffiarray
self.__init__ = __init__
+ self._init_no_arg_ = _init_no_arg_
self._type_ = TP
def _build_ffiargtype(self):
@@ -136,27 +139,21 @@
if not (isinstance(tp, _CDataMeta) and tp._is_pointer_like()):
raise TypeError("cast() argument 2 must be a pointer type, not %s"
% (tp,))
+ result = tp._newowninstance_()
if isinstance(obj, int):
- result = tp()
result._buffer[0] = obj
return result
elif obj is None:
- result = tp()
return result
elif isinstance(obj, Array):
- ptr = tp.__new__(tp)
- ptr._buffer = tp._ffiarray(1, autofree=True)
- ptr._buffer[0] = obj._buffer
- result = ptr
+ result._buffer[0] = obj._buffer
elif isinstance(obj, bytes):
- result = tp()
result._buffer[0] = memoryview(obj)._pypy_raw_address()
return result
elif not (isinstance(obj, _CData) and type(obj)._is_pointer_like()):
raise TypeError("cast() argument 1 must be a pointer, not %s"
% (type(obj),))
else:
- result = tp()
result._buffer[0] = obj._buffer[0]
# The casted objects '_objects' member:
diff --git a/lib_pypy/_ctypes/primitive.py b/lib_pypy/_ctypes/primitive.py
--- a/lib_pypy/_ctypes/primitive.py
+++ b/lib_pypy/_ctypes/primitive.py
@@ -378,11 +378,14 @@
self._buffer = self._ffiarray(1, autofree=True)
if value is not DEFAULT_VALUE:
self.value = value
+ _init_no_arg_ = __init__
def _ensure_objects(self):
- if self._type_ not in 'zZP':
- assert self._objects is None
- return self._objects
+ # No '_objects' is the common case for primitives. Examples
+ # where there is an _objects is if _type in 'zZP', or if
+ # self comes from 'from_buffer(buf)'. See module/test_lib_pypy/
+ # ctypes_test/test_buffers.py: test_from_buffer_keepalive.
+ return getattr(self, '_objects', None)
def _getvalue(self):
return self._buffer[0]
diff --git a/lib_pypy/_ctypes/structure.py b/lib_pypy/_ctypes/structure.py
--- a/lib_pypy/_ctypes/structure.py
+++ b/lib_pypy/_ctypes/structure.py
@@ -280,6 +280,7 @@
self.__setattr__(name, arg)
for name, arg in kwds.items():
self.__setattr__(name, arg)
+ _init_no_arg_ = __init__
def _subarray(self, fieldtype, name):
"""Return a _rawffi array of length 1 whose address is the same as
diff --git a/pypy/module/test_lib_pypy/ctypes_tests/test_buffers.py b/pypy/module/test_lib_pypy/ctypes_tests/test_buffers.py
--- a/pypy/module/test_lib_pypy/ctypes_tests/test_buffers.py
+++ b/pypy/module/test_lib_pypy/ctypes_tests/test_buffers.py
@@ -34,6 +34,15 @@
assert b.value in (1684234849, # little endian
1633837924) # big endian
+ def test_from_buffer_keepalive(self):
+ # Issue #2878
+ b1 = bytearray("ab")
+ array = (c_uint16 * 32)()
+ array[6] = c_uint16.from_buffer(b1)
+ # this is also what we get on CPython. I don't think it makes
+ # sense because the array contains just a copy of the number.
+ assert array._objects == {'6': b1}
+
try:
c_wchar
except NameError:
diff --git a/pypy/module/test_lib_pypy/ctypes_tests/test_structures.py b/pypy/module/test_lib_pypy/ctypes_tests/test_structures.py
--- a/pypy/module/test_lib_pypy/ctypes_tests/test_structures.py
+++ b/pypy/module/test_lib_pypy/ctypes_tests/test_structures.py
@@ -498,6 +498,22 @@
assert dostruct(Native) == dostruct(Big)
assert dostruct(Native) != dostruct(Little)
+ def test_from_buffer_copy(self):
+ from array import array
+
+ class S(Structure):
+ _fields_ = [('i', c_int)]
+ def __init__(self, some, unused, arguments):
+ pass
+ a = array('i', [1234567])
+ s1 = S.from_buffer(a)
+ s2 = S.from_buffer_copy(a)
+ assert s1.i == 1234567
+ assert s2.i == 1234567
+ a[0] = -7654321
+ assert s1.i == -7654321
+ assert s2.i == 1234567
+
class TestPointerMember(BaseCTypesTestChecker):
def test_1(self):
diff --git a/rpython/rlib/rstring.py b/rpython/rlib/rstring.py
--- a/rpython/rlib/rstring.py
+++ b/rpython/rlib/rstring.py
@@ -464,6 +464,10 @@
raise InvalidBaseError("%s() base must be >= 2 and <= 36" % fname)
self.base = base
+ # Leading underscores are not allowed
+ if s.startswith('_'):
+ self.error()
+
if base == 16 and (s.startswith('0x') or s.startswith('0X')):
s = s[2:]
if base == 8 and (s.startswith('0o') or s.startswith('0O')):
diff --git a/rpython/rlib/test/test_rarithmetic.py b/rpython/rlib/test/test_rarithmetic.py
--- a/rpython/rlib/test/test_rarithmetic.py
+++ b/rpython/rlib/test/test_rarithmetic.py
@@ -554,50 +554,52 @@
py.test.raises(ParseStringError, string_to_int, '+'+s, base)
py.test.raises(ParseStringError, string_to_int, '-'+s, base)
- def test_number_underscores(self):
- VALID_UNDERSCORE_LITERALS = [
- '0_0_0',
- '4_2',
- '1_0000_0000',
- '0b1001_0100',
- '0xfff_ffff',
- '0o5_7_7',
- '0b_0',
- '0x_f',
- '0o_5',
- ]
- INVALID_UNDERSCORE_LITERALS = [
- # Trailing underscores:
- '0_',
- '42_',
- '1.4j_',
- '0x_',
- '0b1_',
- '0xf_',
- '0o5_',
- # Underscores in the base selector:
- '0_b0',
- '0_xf',
- '0_o5',
- # Old-style octal, still disallowed:
- '09_99',
- # Multiple consecutive underscores:
- '4_______2',
- '0b1001__0100',
- '0xfff__ffff',
- '0x___',
- '0o5__77',
- '1e1__0',
- ]
- for x in VALID_UNDERSCORE_LITERALS:
- print x
- y = string_to_int(x, base=0, allow_underscores=True,
- no_implicit_octal=True)
- assert y == int(x.replace('_', ''), base=0)
- for x in INVALID_UNDERSCORE_LITERALS:
- print x
- py.test.raises(ParseStringError, string_to_int, x, base=0,
- allow_underscores=True)
+ @py.test.mark.parametrize('s', [
+ '0_0_0',
+ '4_2',
+ '1_0000_0000',
+ '0b1001_0100',
+ '0xfff_ffff',
+ '0o5_7_7',
+ '0b_0',
+ '0x_f',
+ '0o_5',
+ ])
+ def test_valid_underscores(self, s):
+ result = string_to_int(
+ s, base=0, allow_underscores=True, no_implicit_octal=True)
+ assert result == int(s.replace('_', ''), base=0)
+
+ @py.test.mark.parametrize('s', [
+ # Leading underscores
+ '_100',
+ '_',
+ '_0b1001_0100',
+ # Trailing underscores:
+ '0_',
+ '42_',
+ '1.4j_',
+ '0x_',
+ '0b1_',
+ '0xf_',
+ '0o5_',
+ # Underscores in the base selector:
+ '0_b0',
+ '0_xf',
+ '0_o5',
+ # Old-style octal, still disallowed:
+ '09_99',
+ # Multiple consecutive underscores:
+ '4_______2',
+ '0b1001__0100',
+ '0xfff__ffff',
+ '0x___',
+ '0o5__77',
+ '1e1__0',
+ ])
+ def test_invalid_underscores(self, s):
+ with py.test.raises(ParseStringError):
+ string_to_int(s, base=0, allow_underscores=True)
def test_no_implicit_octal(self):
TESTS = ['00', '000', '00_00', '02', '0377', '02_34']
More information about the pypy-commit
mailing list