Author: Ronan Lamy <ronan.l...@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'] _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit