Author: Joannah Nanjekye <nanjekyejoan...@gmail.com> Branch: os_lockf Changeset: r92918:f3f07f772e02 Date: 2017-10-30 12:57 +0300 http://bitbucket.org/pypy/pypy/changeset/f3f07f772e02/
Log: merge conflict diff --git a/.hgignore b/.hgignore --- a/.hgignore +++ b/.hgignore @@ -75,6 +75,8 @@ ^lib_pypy/.+.c$ ^lib_pypy/.+.o$ ^lib_pypy/.+.so$ +^lib_pypy/.+.pyd$ +^lib_pypy/Release/ ^pypy/doc/discussion/.+\.html$ ^include/.+\.h$ ^include/.+\.inl$ diff --git a/lib-python/3/ctypes/test/test_bitfields.py b/lib-python/3/ctypes/test/test_bitfields.py --- a/lib-python/3/ctypes/test/test_bitfields.py +++ b/lib-python/3/ctypes/test/test_bitfields.py @@ -1,5 +1,5 @@ from ctypes import * -from ctypes.test import need_symbol +from ctypes.test import need_symbol, xfail import unittest import os @@ -279,6 +279,7 @@ self.assertEqual(b, b'\xef\xcd\xab\x21') @need_symbol('c_uint32') + @xfail def test_uint32_swap_big_endian(self): # Issue #23319 class Big(BigEndianStructure): diff --git a/lib-python/3/ctypes/test/test_byteswap.py b/lib-python/3/ctypes/test/test_byteswap.py --- a/lib-python/3/ctypes/test/test_byteswap.py +++ b/lib-python/3/ctypes/test/test_byteswap.py @@ -2,6 +2,7 @@ from binascii import hexlify from ctypes import * +from test.support import impl_detail def bin(s): return hexlify(memoryview(s)).decode().upper() @@ -22,6 +23,7 @@ setattr(bits, "i%s" % i, 1) dump(bits) + @impl_detail("slots are irrelevant on PyPy", pypy=False) def test_slots(self): class BigPoint(BigEndianStructure): __slots__ = () diff --git a/lib-python/3/ctypes/test/test_frombuffer.py b/lib-python/3/ctypes/test/test_frombuffer.py --- a/lib-python/3/ctypes/test/test_frombuffer.py +++ b/lib-python/3/ctypes/test/test_frombuffer.py @@ -85,7 +85,6 @@ del a gc.collect() # Should not crash - @xfail def test_from_buffer_copy(self): a = array.array("i", range(16)) x = (c_int * 16).from_buffer_copy(a) diff --git a/lib-python/3/test/test_bytes.py b/lib-python/3/test/test_bytes.py --- a/lib-python/3/test/test_bytes.py +++ b/lib-python/3/test/test_bytes.py @@ -721,9 +721,12 @@ self.assertIs(type(BytesSubclass(A())), BytesSubclass) # Test PyBytes_FromFormat() - @test.support.impl_detail("don't test cpyext here") def test_from_format(self): test.support.import_module('ctypes') + try: + from ctypes import pythonapi + except ImportError: + self.skipTest( "no pythonapi in ctypes") from ctypes import pythonapi, py_object, c_int, c_char_p PyBytes_FromFormat = pythonapi.PyBytes_FromFormat PyBytes_FromFormat.restype = py_object diff --git a/lib-python/3/test/test_unicode.py b/lib-python/3/test/test_unicode.py --- a/lib-python/3/test/test_unicode.py +++ b/lib-python/3/test/test_unicode.py @@ -2396,6 +2396,10 @@ # Test PyUnicode_FromFormat() def test_from_format(self): support.import_module('ctypes') + try: + from ctypes import pythonapi + except ImportError: + self.skipTest( "no pythonapi in ctypes") from ctypes import ( pythonapi, py_object, sizeof, c_int, c_long, c_longlong, c_ssize_t, 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 @@ -8,9 +8,14 @@ class ArrayMeta(_CDataMeta): def __new__(self, name, cls, typedict): res = type.__new__(self, name, cls, typedict) + if cls == (_CData,): # this is the Array class defined below + res._ffiarray = None return res - + if not hasattr(res, '_length_') or not isinstance(res._length_, int): + raise AttributeError( + "class must define a '_length_' attribute, " + "which must be a positive integer") ffiarray = res._ffiarray = _rawffi.Array(res._type_._ffishape_) subletter = getattr(res._type_, '_type_', None) if subletter == 'c': @@ -55,7 +60,7 @@ for i in range(len(val)): target[i] = val[i] if len(val) < self._length_: - target[len(val)] = '\x00' + target[len(val)] = u'\x00' res.value = property(getvalue, setvalue) res._ffishape_ = (ffiarray, res._length_) @@ -164,7 +169,7 @@ if letter == 'c': return b"".join(l) if letter == 'u': - return "".join(l) + return u"".join(l) return l class Array(_CData, metaclass=ArrayMeta): 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 @@ -165,6 +165,10 @@ def _get_buffer_value(self): return self._buffer[0] + def _copy_to(self, addr): + target = type(self).from_address(addr)._buffer + target[0] = self._get_buffer_value() + def _to_ffi_param(self): if self.__class__._is_pointer_like(): return self._get_buffer_value() 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 @@ -113,7 +113,9 @@ cobj = self._type_.from_param(value) if ensure_objects(cobj) is not None: store_reference(self, index, cobj._objects) - self._subarray(index)[0] = cobj._get_buffer_value() + address = self._buffer[0] + address += index * sizeof(self._type_) + cobj._copy_to(address) def __bool__(self): return self._buffer[0] != 0 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 @@ -232,9 +232,6 @@ elif tp == 'u': def _setvalue(self, val): - if isinstance(val, bytes): - val = val.decode(ConvMode.encoding, ConvMode.errors) - # possible if we use 'ignore' if val: self._buffer[0] = val def _getvalue(self): @@ -243,8 +240,6 @@ elif tp == 'c': def _setvalue(self, val): - if isinstance(val, str): - val = val.encode(ConvMode.encoding, ConvMode.errors) if val: self._buffer[0] = val def _getvalue(self): 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 @@ -290,6 +290,11 @@ def _get_buffer_value(self): return self._buffer.buffer + def _copy_to(self, addr): + from ctypes import memmove + origin = self._get_buffer_value() + memmove(addr, origin, self._fficompositesize_) + def _to_ffi_param(self): return self._buffer diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py --- a/lib_pypy/_sqlite3.py +++ b/lib_pypy/_sqlite3.py @@ -1080,21 +1080,25 @@ if '\0' in sql: raise ValueError("the query contains a null character") - first_word = sql.lstrip().split(" ")[0].upper() - if first_word == "": + + if sql: + first_word = sql.lstrip().split()[0].upper() + if first_word == '': + self._type = _STMT_TYPE_INVALID + if first_word == "SELECT": + self._type = _STMT_TYPE_SELECT + elif first_word == "INSERT": + self._type = _STMT_TYPE_INSERT + elif first_word == "UPDATE": + self._type = _STMT_TYPE_UPDATE + elif first_word == "DELETE": + self._type = _STMT_TYPE_DELETE + elif first_word == "REPLACE": + self._type = _STMT_TYPE_REPLACE + else: + self._type = _STMT_TYPE_OTHER + else: self._type = _STMT_TYPE_INVALID - elif first_word == "SELECT": - self._type = _STMT_TYPE_SELECT - elif first_word == "INSERT": - self._type = _STMT_TYPE_INSERT - elif first_word == "UPDATE": - self._type = _STMT_TYPE_UPDATE - elif first_word == "DELETE": - self._type = _STMT_TYPE_DELETE - elif first_word == "REPLACE": - self._type = _STMT_TYPE_REPLACE - else: - self._type = _STMT_TYPE_OTHER if isinstance(sql, unicode): sql = sql.encode('utf-8') diff --git a/lib_pypy/cffi.egg-info/PKG-INFO b/lib_pypy/cffi.egg-info/PKG-INFO --- a/lib_pypy/cffi.egg-info/PKG-INFO +++ b/lib_pypy/cffi.egg-info/PKG-INFO @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: cffi -Version: 1.11.1 +Version: 1.11.2 Summary: Foreign Function Interface for Python calling C code. Home-page: http://cffi.readthedocs.org Author: Armin Rigo, Maciej Fijalkowski diff --git a/lib_pypy/cffi/__init__.py b/lib_pypy/cffi/__init__.py --- a/lib_pypy/cffi/__init__.py +++ b/lib_pypy/cffi/__init__.py @@ -4,8 +4,8 @@ from .api import FFI from .error import CDefError, FFIError, VerificationError, VerificationMissing -__version__ = "1.11.1" -__version_info__ = (1, 11, 1) +__version__ = "1.11.2" +__version_info__ = (1, 11, 2) # The verifier module file names are based on the CRC32 of a string that # contains the following version number. It may be older than __version__ diff --git a/lib_pypy/cffi/_cffi_include.h b/lib_pypy/cffi/_cffi_include.h --- a/lib_pypy/cffi/_cffi_include.h +++ b/lib_pypy/cffi/_cffi_include.h @@ -238,9 +238,9 @@ _CFFI_UNUSED_FN static PyObject *_cffi_from_c_char16_t(uint16_t x) { if (sizeof(_cffi_wchar_t) == 2) - return _cffi_from_c_wchar_t(x); + return _cffi_from_c_wchar_t((_cffi_wchar_t)x); else - return _cffi_from_c_wchar3216_t(x); + return _cffi_from_c_wchar3216_t((int)x); } _CFFI_UNUSED_FN static int _cffi_to_c_char32_t(PyObject *o) @@ -254,7 +254,7 @@ _CFFI_UNUSED_FN static PyObject *_cffi_from_c_char32_t(int x) { if (sizeof(_cffi_wchar_t) == 4) - return _cffi_from_c_wchar_t(x); + return _cffi_from_c_wchar_t((_cffi_wchar_t)x); else return _cffi_from_c_wchar3216_t(x); } diff --git a/lib_pypy/cffi/_embedding.h b/lib_pypy/cffi/_embedding.h --- a/lib_pypy/cffi/_embedding.h +++ b/lib_pypy/cffi/_embedding.h @@ -247,7 +247,7 @@ if (f != NULL && f != Py_None) { PyFile_WriteString("\nFrom: " _CFFI_MODULE_NAME - "\ncompiled with cffi version: 1.11.1" + "\ncompiled with cffi version: 1.11.2" "\n_cffi_backend module: ", f); modules = PyImport_GetModuleDict(); mod = PyDict_GetItemString(modules, "_cffi_backend"); diff --git a/pypy/TODO b/pypy/TODO --- a/pypy/TODO +++ b/pypy/TODO @@ -1,18 +1,4 @@ -TODO for the python3 test suite: - -* test_memoryview - Needs bytes/str changes. Probably easy. Work for this has begun on - py3k-memoryview (by mjacob) https://bugs.pypy.org/issue1542 - -own-tests: - -* module/test_lib_pypy - These crash the buildbots (via SyntaxErrors): others were really - made to run under Python 2.x and so simply fail - -* module.cpyext.test.test_structseq test_StructSeq - structseq now subclasses tuple on py3, which breaks how - BaseCpyTypeDescr.realize allocates it +... antocuni's older TODO: @@ -20,14 +6,6 @@ * run coverage against the parser/astbuilder/astcompiler: it's probably full of dead code because the grammar changed -* re-enable strategies https://bugs.pypy.org/issue1540 : - - re-enable IntDictStrategy - - re-enable StdObjSpace.listview_str - - re-enable the kwargs dict strategy in dictmultiobject.py - - re-enable view_as_kwargs - -* unskip numpypy tests in module/test_lib_pypy/numpypy/ - * optimize W_UnicodeObject, right now it stores both an unicode and an utf8 version of the same string diff --git a/pypy/doc/build.rst b/pypy/doc/build.rst --- a/pypy/doc/build.rst +++ b/pypy/doc/build.rst @@ -119,7 +119,7 @@ To run untranslated tests, you need the Boehm garbage collector libgc. -On recent Debian and Ubuntu (like 17.04), this is the command to install +On recent Debian and Ubuntu (16.04 onwards), this is the command to install all build-time dependencies:: apt-get install gcc make libffi-dev pkg-config zlib1g-dev libbz2-dev \ @@ -127,7 +127,7 @@ tk-dev libgc-dev python-cffi \ liblzma-dev libncursesw5-dev # these two only needed on PyPy3 -On older Debian and Ubuntu (12.04 to 16.04):: +On older Debian and Ubuntu (12.04-14.04):: apt-get install gcc make libffi-dev pkg-config libz-dev libbz2-dev \ libsqlite3-dev libncurses-dev libexpat1-dev libssl-dev libgdbm-dev \ @@ -149,12 +149,23 @@ xz-devel # For lzma on PyPy3. (XXX plus the SLES11 version of libgdbm-dev and tk-dev) -On Mac OS X, most of these build-time dependencies are installed alongside +On Mac OS X:: + +Most of these build-time dependencies are installed alongside the Developer Tools. However, note that in order for the installation to find them you may need to run:: xcode-select --install +An exception is OpenSSL, which is no longer provided with the operating +system. It can be obtained via Homebrew (with ``$ brew install openssl``), +but it will not be available on the system path by default. The easiest +way to enable it for building pypy is to set an environment variable:: + + export PKG_CONFIG_PATH=$(brew --prefix)/opt/openssl/lib/pkgconfig + +After setting this, translation (described next) will find the OpenSSL libs +as expected. Run the translation ------------------- @@ -187,18 +198,18 @@ entire pypy interpreter. This step is currently singe threaded, and RAM hungry. As part of this step, the chain creates a large number of C code files and a Makefile to compile them in a - directory controlled by the ``PYPY_USESSION_DIR`` environment variable. + directory controlled by the ``PYPY_USESSION_DIR`` environment variable. 2. Create an executable ``pypy-c`` by running the Makefile. This step can - utilize all possible cores on the machine. -3. Copy the needed binaries to the current directory. -4. Generate c-extension modules for any cffi-based stdlib modules. + utilize all possible cores on the machine. +3. Copy the needed binaries to the current directory. +4. Generate c-extension modules for any cffi-based stdlib modules. The resulting executable behaves mostly like a normal Python interpreter (see :doc:`cpython_differences`), and is ready for testing, for use as a base interpreter for a new virtualenv, or for packaging into a binary suitable for installation on another machine running the same OS as the build -machine. +machine. Note that step 4 is merely done as a convenience, any of the steps may be rerun without rerunning the previous steps. @@ -255,7 +266,7 @@ * PyPy 2.5.1 or earlier: normal users would see permission errors. Installers need to run ``pypy -c "import gdbm"`` and other similar - commands at install time; the exact list is in + commands at install time; the exact list is in :source:`pypy/tool/release/package.py <package.py>`. Users seeing a broken installation of PyPy can fix it after-the-fact if they have sudo rights, by running once e.g. ``sudo pypy -c "import gdbm``. diff --git a/pypy/doc/project-ideas.rst b/pypy/doc/project-ideas.rst --- a/pypy/doc/project-ideas.rst +++ b/pypy/doc/project-ideas.rst @@ -240,9 +240,12 @@ **matplotlib** https://github.com/matplotlib/matplotlib - TODO: the tkagg backend does not work, which makes tests fail on downstream - projects like Pandas, SciPy. It uses id(obj) as a c-pointer to obj in - tkagg.py, which requires refactoring + Status: using the matplotlib branch of PyPy and the tkagg-cffi branch of + matplotlib from https://github.com/mattip/matplotlib/tree/tkagg-cffi, the + tkagg backend can function. + + TODO: the matplotlib branch passes numpy arrays by value (copying all the + data), this proof-of-concept needs help to become completely compliant **wxPython** https://bitbucket.org/amauryfa/wxpython-cffi diff --git a/pypy/doc/test/test_whatsnew.py b/pypy/doc/test/test_whatsnew.py --- a/pypy/doc/test/test_whatsnew.py +++ b/pypy/doc/test/test_whatsnew.py @@ -89,7 +89,7 @@ startrev, documented = parse_doc(last_whatsnew) merged, branch = get_merged_branches(ROOT, startrev, '') merged.discard('default') - merged.discard('py3k') + merged.discard('py3.5') merged.discard('') not_documented = merged.difference(documented) not_merged = documented.difference(merged) @@ -100,7 +100,7 @@ print '\n'.join(not_merged) print assert not not_documented - if branch == 'py3k': + if branch == 'py3.5': assert not not_merged else: assert branch in documented, 'Please document this branch before merging: %s' % branch diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst --- a/pypy/doc/whatsnew-head.rst +++ b/pypy/doc/whatsnew-head.rst @@ -5,4 +5,8 @@ .. this is a revision shortly after release-pypy2.7-v5.9.0 .. startrev:d56dadcef996 +.. branch: cppyy-packaging +Cleanup and improve cppyy packaging +.. branch: docs-osx-brew-openssl + diff --git a/pypy/doc/whatsnew-pypy3-head.rst b/pypy/doc/whatsnew-pypy3-head.rst --- a/pypy/doc/whatsnew-pypy3-head.rst +++ b/pypy/doc/whatsnew-pypy3-head.rst @@ -4,8 +4,3 @@ .. this is the revision after release-pypy3.5-5.9 .. startrev: be41e3ac0a29 - -.. branch: multiphase - -Implement PyType_FromSpec (PEP 384) and fix issues with PEP 489 support. - diff --git a/pypy/interpreter/test/test_interpreter.py b/pypy/interpreter/test/test_interpreter.py --- a/pypy/interpreter/test/test_interpreter.py +++ b/pypy/interpreter/test/test_interpreter.py @@ -1,7 +1,6 @@ import py import sys from pypy.interpreter import gateway, module, error -from hypothesis import given, strategies class TestInterpreter: @@ -300,30 +299,6 @@ assert "TypeError:" in res assert "'tuple' object is not a mapping" in res - @given(strategies.lists(strategies.one_of(strategies.none(), - strategies.lists(strategies.none())))) - def test_build_map_order(self, shape): - value = [10] - def build_expr(shape): - if shape is None: - value[0] += 1 - return '0: %d' % value[0] - else: - return '**{%s}' % (', '.join( - [build_expr(shape1) for shape1 in shape]),) - - expr = build_expr(shape)[2:] - code = """ - def f(): - return %s - """ % (expr, ) - res = self.codetest(code, 'f', []) - if value[0] == 10: - expected = {} - else: - expected = {0: value[0]} - assert res == expected, "got %r for %r" % (res, expr) - def test_build_map_unpack_with_call(self): code = """ def f(a,b,c,d): @@ -348,6 +323,36 @@ assert "TypeError:" in resg4 assert "got multiple values for keyword argument 'a'" in resg4 +try: + from hypothesis import given, strategies +except ImportError: + pass +else: + class TestHypothesisInterpreter(TestInterpreter): + @given(strategies.lists(strategies.one_of(strategies.none(), + strategies.lists(strategies.none())))) + def test_build_map_order(self, shape): + value = [10] + def build_expr(shape): + if shape is None: + value[0] += 1 + return '0: %d' % value[0] + else: + return '**{%s}' % (', '.join( + [build_expr(shape1) for shape1 in shape]),) + + expr = build_expr(shape)[2:] + code = """ + def f(): + return %s + """ % (expr, ) + res = self.codetest(code, 'f', []) + if value[0] == 10: + expected = {} + else: + expected = {0: value[0]} + assert res == expected, "got %r for %r" % (res, expr) + class AppTestInterpreter: def test_trivial(self): diff --git a/pypy/module/_cffi_backend/__init__.py b/pypy/module/_cffi_backend/__init__.py --- a/pypy/module/_cffi_backend/__init__.py +++ b/pypy/module/_cffi_backend/__init__.py @@ -3,7 +3,7 @@ from rpython.rlib import rdynload, clibffi from rpython.rtyper.lltypesystem import rffi -VERSION = "1.11.1" +VERSION = "1.11.2" FFI_DEFAULT_ABI = clibffi.FFI_DEFAULT_ABI try: diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py b/pypy/module/_cffi_backend/test/_backend_test_c.py --- a/pypy/module/_cffi_backend/test/_backend_test_c.py +++ b/pypy/module/_cffi_backend/test/_backend_test_c.py @@ -1,7 +1,7 @@ # ____________________________________________________________ import sys -assert __version__ == "1.11.1", ("This test_c.py file is for testing a version" +assert __version__ == "1.11.2", ("This test_c.py file is for testing a version" " of cffi that differs from the one that we" " get from 'import _cffi_backend'") if sys.version_info < (3,): diff --git a/pypy/module/_codecs/test/test_codecs.py b/pypy/module/_codecs/test/test_codecs.py --- a/pypy/module/_codecs/test/test_codecs.py +++ b/pypy/module/_codecs/test/test_codecs.py @@ -762,9 +762,16 @@ assert s == b'\xe9' def test_lone_surrogates(self): - for encoding in ('utf-8', 'utf-16', 'utf-16-le', 'utf-16-be', - 'utf-32', 'utf-32-le', 'utf-32-be'): + encodings = ('utf-8', 'utf-16', 'utf-16-le', 'utf-16-be', + 'utf-32', 'utf-32-le', 'utf-32-be') + for encoding in encodings: raises(UnicodeEncodeError, u'\ud800'.encode, encoding) + assert (u'[\udc80]'.encode(encoding, "backslashreplace") == + '[\\udc80]'.encode(encoding)) + assert (u'[\udc80]'.encode(encoding, "ignore") == + '[]'.encode(encoding)) + assert (u'[\udc80]'.encode(encoding, "replace") == + '[?]'.encode(encoding)) def test_charmap_encode(self): assert 'xxx'.encode('charmap') == b'xxx' diff --git a/pypy/module/_continuation/test/test_stacklet.py b/pypy/module/_continuation/test/test_stacklet.py --- a/pypy/module/_continuation/test/test_stacklet.py +++ b/pypy/module/_continuation/test/test_stacklet.py @@ -290,66 +290,87 @@ def test_random_switching(self): from _continuation import continulet # + seen = [] + # def t1(c1): - return c1.switch() + seen.append(3) + res = c1.switch() + seen.append(6) + return res + # def s1(c1, n): + seen.append(2) assert n == 123 c2 = t1(c1) - return c1.switch('a') + 1 + seen.append(7) + res = c1.switch('a') + 1 + seen.append(10) + return res # def s2(c2, c1): + seen.append(5) res = c1.switch(c2) + seen.append(8) assert res == 'a' - return c2.switch('b') + 2 + res = c2.switch('b') + 2 + seen.append(12) + return res # def f(): + seen.append(1) c1 = continulet(s1, 123) c2 = continulet(s2, c1) c1.switch() + seen.append(4) res = c2.switch() + seen.append(9) assert res == 'b' res = c1.switch(1000) + seen.append(11) assert res == 1001 - return c2.switch(2000) + res = c2.switch(2000) + seen.append(13) + return res # res = f() assert res == 2002 + assert seen == [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13] def test_f_back(self): import sys from _continuation import continulet # - def g(c): + def bar(c): c.switch(sys._getframe(0)) c.switch(sys._getframe(0).f_back) c.switch(sys._getframe(1)) c.switch(sys._getframe(1).f_back) - assert sys._getframe(2) is f3.f_back + assert sys._getframe(2) is f3_foo.f_back c.switch(sys._getframe(2)) - def f(c): - g(c) + def foo(c): + bar(c) # - c = continulet(f) - f1 = c.switch() - assert f1.f_code.co_name == 'g' - f2 = c.switch() - assert f2.f_code.co_name == 'f' - f3 = c.switch() - assert f3 is f2 - assert f1.f_back is f3 + c = continulet(foo) + f1_bar = c.switch() + assert f1_bar.f_code.co_name == 'bar' + f2_foo = c.switch() + assert f2_foo.f_code.co_name == 'foo' + f3_foo = c.switch() + assert f3_foo is f2_foo + assert f1_bar.f_back is f3_foo def main(): - f4 = c.switch() - assert f4.f_code.co_name == 'main', repr(f4.f_code.co_name) - assert f3.f_back is f1 # not running, so a loop + f4_main = c.switch() + assert f4_main.f_code.co_name == 'main' + assert f3_foo.f_back is f1_bar # not running, so a loop def main2(): - f5 = c.switch() - assert f5.f_code.co_name == 'main2', repr(f5.f_code.co_name) - assert f3.f_back is f1 # not running, so a loop + f5_main2 = c.switch() + assert f5_main2.f_code.co_name == 'main2' + assert f3_foo.f_back is f1_bar # not running, so a loop main() main2() res = c.switch() assert res is None - assert f3.f_back is None + assert f3_foo.f_back is None def test_traceback_is_complete(self): import sys diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py --- a/pypy/module/cpyext/api.py +++ b/pypy/module/cpyext/api.py @@ -582,6 +582,7 @@ 'PyComplex_AsCComplex', 'PyComplex_FromCComplex', 'PyObject_AsReadBuffer', 'PyObject_AsWriteBuffer', 'PyObject_CheckReadBuffer', + 'PyBuffer_GetPointer', 'PyBuffer_ToContiguous', 'PyBuffer_FromContiguous', 'PyImport_ImportModuleLevel', diff --git a/pypy/module/cpyext/dictobject.py b/pypy/module/cpyext/dictobject.py --- a/pypy/module/cpyext/dictobject.py +++ b/pypy/module/cpyext/dictobject.py @@ -274,7 +274,10 @@ if pos == 0: # Store the current keys in the PyDictObject. decref(space, py_dict.c__tmpkeys) - w_keys = space.call_method(space.w_dict, "keys", w_dict) + w_keyview = space.call_method(space.w_dict, "keys", w_dict) + # w_keys must use the object strategy in order to keep the keys alive + w_keys = space.newlist(space.listview(w_keyview)) + w_keys.switch_to_object_strategy() py_dict.c__tmpkeys = create_ref(space, w_keys) Py_IncRef(space, py_dict.c__tmpkeys) else: @@ -287,10 +290,10 @@ decref(space, py_dict.c__tmpkeys) py_dict.c__tmpkeys = lltype.nullptr(PyObject.TO) return 0 - w_key = space.listview(w_keys)[pos] + w_key = space.listview(w_keys)[pos] # fast iff w_keys uses object strat w_value = space.getitem(w_dict, w_key) if pkey: - pkey[0] = as_pyobj(space, w_key) + pkey[0] = as_pyobj(space, w_key) if pvalue: pvalue[0] = as_pyobj(space, w_value) return 1 diff --git a/pypy/module/cpyext/include/object.h b/pypy/module/cpyext/include/object.h --- a/pypy/module/cpyext/include/object.h +++ b/pypy/module/cpyext/include/object.h @@ -308,6 +308,31 @@ PyAPI_FUNC(int) PyObject_AsReadBuffer(PyObject *, const void **, Py_ssize_t *); PyAPI_FUNC(int) PyObject_AsWriteBuffer(PyObject *, void **, Py_ssize_t *); PyAPI_FUNC(int) PyObject_CheckReadBuffer(PyObject *); +PyAPI_FUNC(void *) PyBuffer_GetPointer(Py_buffer *view, Py_ssize_t *indices); +/* Get the memory area pointed to by the indices for the buffer given. + Note that view->ndim is the assumed size of indices +*/ + +PyAPI_FUNC(int) PyBuffer_ToContiguous(void *buf, Py_buffer *view, + Py_ssize_t len, char fort); +PyAPI_FUNC(int) PyBuffer_FromContiguous(Py_buffer *view, void *buf, + Py_ssize_t len, char fort); +/* Copy len bytes of data from the contiguous chunk of memory + pointed to by buf into the buffer exported by obj. Return + 0 on success and return -1 and raise a PyBuffer_Error on + error (i.e. the object does not have a buffer interface or + it is not working). + + If fort is 'F' and the object is multi-dimensional, + then the data will be copied into the array in + Fortran-style (first dimension varies the fastest). If + fort is 'C', then the data will be copied into the array + in C-style (last dimension varies the fastest). If fort + is 'A', then it does not matter and the copy will be made + in whatever way is more efficient. + +*/ + #define PyObject_MALLOC PyObject_Malloc #define PyObject_REALLOC PyObject_Realloc diff --git a/pypy/module/cpyext/pyobject.py b/pypy/module/cpyext/pyobject.py --- a/pypy/module/cpyext/pyobject.py +++ b/pypy/module/cpyext/pyobject.py @@ -15,7 +15,7 @@ from rpython.rlib.objectmodel import keepalive_until_here from rpython.rtyper.annlowlevel import llhelper from rpython.rlib import rawrefcount, jit -from rpython.rlib.debug import fatalerror +from rpython.rlib.debug import ll_assert, fatalerror #________________________________________________________ @@ -243,6 +243,11 @@ py_obj = rawrefcount.from_obj(PyObject, w_obj) if not py_obj: py_obj = create_ref(space, w_obj, w_userdata, immortal=immortal) + # + # Try to crash here, instead of randomly, if we don't keep w_obj alive + ll_assert(py_obj.c_ob_refcnt >= rawrefcount.REFCNT_FROM_PYPY, + "Bug in cpyext: The W_Root object was garbage-collected " + "while being converted to PyObject.") return py_obj else: return lltype.nullptr(PyObject.TO) diff --git a/pypy/module/cpyext/slotdefs.py b/pypy/module/cpyext/slotdefs.py --- a/pypy/module/cpyext/slotdefs.py +++ b/pypy/module/cpyext/slotdefs.py @@ -13,7 +13,7 @@ ssizessizeargfunc, ssizeobjargproc, iternextfunc, initproc, richcmpfunc, cmpfunc, hashfunc, descrgetfunc, descrsetfunc, objobjproc, objobjargproc, getbufferproc, ssizessizeobjargproc) -from pypy.module.cpyext.pyobject import make_ref, decref, from_ref +from pypy.module.cpyext.pyobject import make_ref, from_ref, as_pyobj from pypy.module.cpyext.pyerrors import PyErr_Occurred from pypy.module.cpyext.memoryobject import fill_Py_buffer from pypy.module.cpyext.state import State @@ -90,20 +90,21 @@ args_w = space.fixedview(w_args) return generic_cpy_call(space, func_binary, w_self, args_w[0]) +def _get_ob_type(space, w_obj): + # please ensure that w_obj stays alive + ob_type = as_pyobj(space, space.type(w_obj)) + return rffi.cast(PyTypeObjectPtr, ob_type) + def wrap_binaryfunc_l(space, w_self, w_args, func): func_binary = rffi.cast(binaryfunc, func) check_num_args(space, w_args, 1) args_w = space.fixedview(w_args) - ref = make_ref(space, w_self) - decref(space, ref) return generic_cpy_call(space, func_binary, w_self, args_w[0]) def wrap_binaryfunc_r(space, w_self, w_args, func): func_binary = rffi.cast(binaryfunc, func) check_num_args(space, w_args, 1) args_w = space.fixedview(w_args) - ref = make_ref(space, w_self) - decref(space, ref) return generic_cpy_call(space, func_binary, args_w[0], w_self) def wrap_ternaryfunc(space, w_self, w_args, func): @@ -121,8 +122,6 @@ func_ternary = rffi.cast(ternaryfunc, func) check_num_argsv(space, w_args, 1, 2) args_w = space.fixedview(w_args) - ref = make_ref(space, w_self) - decref(space, ref) arg3 = space.w_None if len(args_w) > 1: arg3 = args_w[1] @@ -314,12 +313,10 @@ def wrap_getreadbuffer(space, w_self, w_args, func): func_target = rffi.cast(readbufferproc, func) - py_obj = make_ref(space, w_self) - py_type = py_obj.c_ob_type + py_type = _get_ob_type(space, w_self) rbp = rffi.cast(rffi.VOIDP, 0) if py_type.c_tp_as_buffer: rbp = rffi.cast(rffi.VOIDP, py_type.c_tp_as_buffer.c_bf_releasebuffer) - decref(space, py_obj) with lltype.scoped_alloc(rffi.VOIDPP.TO, 1) as ptr: index = rffi.cast(Py_ssize_t, 0) size = generic_cpy_call(space, func_target, w_self, index, ptr) @@ -332,9 +329,7 @@ def wrap_getwritebuffer(space, w_self, w_args, func): func_target = rffi.cast(readbufferproc, func) - py_obj = make_ref(space, w_self) - py_type = py_obj.c_ob_type - decref(space, py_obj) + py_type = _get_ob_type(space, w_self) rbp = rffi.cast(rffi.VOIDP, 0) if py_type.c_tp_as_buffer: rbp = rffi.cast(rffi.VOIDP, py_type.c_tp_as_buffer.c_bf_releasebuffer) @@ -350,12 +345,10 @@ def wrap_getbuffer(space, w_self, w_args, func): func_target = rffi.cast(getbufferproc, func) - py_obj = make_ref(space, w_self) - py_type = py_obj.c_ob_type + py_type = _get_ob_type(space, w_self) rbp = rffi.cast(rffi.VOIDP, 0) if py_type.c_tp_as_buffer: rbp = rffi.cast(rffi.VOIDP, py_type.c_tp_as_buffer.c_bf_releasebuffer) - decref(space, py_obj) with lltype.scoped_alloc(Py_buffer) as pybuf: _flags = 0 if space.len_w(w_args) > 0: diff --git a/pypy/module/cpyext/src/abstract.c b/pypy/module/cpyext/src/abstract.c --- a/pypy/module/cpyext/src/abstract.c +++ b/pypy/module/cpyext/src/abstract.c @@ -96,6 +96,163 @@ return 0; } +void* +PyBuffer_GetPointer(Py_buffer *view, Py_ssize_t *indices) +{ + char* pointer; + int i; + pointer = (char *)view->buf; + for (i = 0; i < view->ndim; i++) { + pointer += view->strides[i]*indices[i]; + if ((view->suboffsets != NULL) && (view->suboffsets[i] >= 0)) { + pointer = *((char**)pointer) + view->suboffsets[i]; + } + } + return (void*)pointer; +} + +void +_Py_add_one_to_index_F(int nd, Py_ssize_t *index, const Py_ssize_t *shape) +{ + int k; + + for (k=0; k<nd; k++) { + if (index[k] < shape[k]-1) { + index[k]++; + break; + } + else { + index[k] = 0; + } + } +} + +void +_Py_add_one_to_index_C(int nd, Py_ssize_t *index, const Py_ssize_t *shape) +{ + int k; + + for (k=nd-1; k>=0; k--) { + if (index[k] < shape[k]-1) { + index[k]++; + break; + } + else { + index[k] = 0; + } + } +} + + /* view is not checked for consistency in either of these. It is + assumed that the size of the buffer is view->len in + view->len / view->itemsize elements. + */ + +int +PyBuffer_ToContiguous(void *buf, Py_buffer *view, Py_ssize_t len, char fort) +{ + int k; + void (*addone)(int, Py_ssize_t *, const Py_ssize_t *); + Py_ssize_t *indices, elements; + char *dest, *ptr; + + if (len > view->len) { + len = view->len; + } + + if (PyBuffer_IsContiguous(view, fort)) { + /* simplest copy is all that is needed */ + memcpy(buf, view->buf, len); + return 0; + } + + /* Otherwise a more elaborate scheme is needed */ + + /* view->ndim <= 64 */ + indices = (Py_ssize_t *)PyMem_Malloc(sizeof(Py_ssize_t)*(view->ndim)); + if (indices == NULL) { + PyErr_NoMemory(); + return -1; + } + for (k=0; k<view->ndim;k++) { + indices[k] = 0; + } + + if (fort == 'F') { + addone = _Py_add_one_to_index_F; + } + else { + addone = _Py_add_one_to_index_C; + } + dest = buf; + /* XXX : This is not going to be the fastest code in the world + several optimizations are possible. + */ + elements = len / view->itemsize; + while (elements--) { + ptr = PyBuffer_GetPointer(view, indices); + memcpy(dest, ptr, view->itemsize); + dest += view->itemsize; + addone(view->ndim, indices, view->shape); + } + PyMem_Free(indices); + return 0; +} + +int +PyBuffer_FromContiguous(Py_buffer *view, void *buf, Py_ssize_t len, char fort) +{ + int k; + void (*addone)(int, Py_ssize_t *, const Py_ssize_t *); + Py_ssize_t *indices, elements; + char *src, *ptr; + + if (len > view->len) { + len = view->len; + } + + if (PyBuffer_IsContiguous(view, fort)) { + /* simplest copy is all that is needed */ + memcpy(view->buf, buf, len); + return 0; + } + + /* Otherwise a more elaborate scheme is needed */ + + /* view->ndim <= 64 */ + indices = (Py_ssize_t *)PyMem_Malloc(sizeof(Py_ssize_t)*(view->ndim)); + if (indices == NULL) { + PyErr_NoMemory(); + return -1; + } + for (k=0; k<view->ndim;k++) { + indices[k] = 0; + } + + if (fort == 'F') { + addone = _Py_add_one_to_index_F; + } + else { + addone = _Py_add_one_to_index_C; + } + src = buf; + /* XXX : This is not going to be the fastest code in the world + several optimizations are possible. + */ + elements = len / view->itemsize; + while (elements--) { + ptr = PyBuffer_GetPointer(view, indices); + memcpy(ptr, src, view->itemsize); + src += view->itemsize; + addone(view->ndim, indices, view->shape); + } + + PyMem_Free(indices); + return 0; +} + + + /* Buffer C-API for Python 3.0 */ int diff --git a/pypy/module/cpyext/test/test_memoryobject.py b/pypy/module/cpyext/test/test_memoryobject.py --- a/pypy/module/cpyext/test/test_memoryobject.py +++ b/pypy/module/cpyext/test/test_memoryobject.py @@ -137,7 +137,36 @@ view = PyMemoryView_GET_BUFFER(memoryview); Py_DECREF(memoryview); return PyLong_FromLong(view->len / view->itemsize); - """)]) + """), + ("test_contiguous", "METH_O", + """ + Py_buffer* view; + PyObject * memoryview; + void * buf = NULL; + int ret; + Py_ssize_t len; + memoryview = PyMemoryView_FromObject(args); + if (memoryview == NULL) + return NULL; + view = PyMemoryView_GET_BUFFER(memoryview); + Py_DECREF(memoryview); + len = view->len; + if (len == 0) + return NULL; + buf = malloc(len); + ret = PyBuffer_ToContiguous(buf, view, view->len, 'A'); + if (ret != 0) + { + free(buf); + return NULL; + } + ret = PyBuffer_FromContiguous(view, buf, view->len, 'A'); + free(buf); + if (ret != 0) + return NULL; + Py_RETURN_NONE; + """), + ]) module = self.import_module(name='buffer_test') arr = module.PyMyArray(10) ten = foo.get_len(arr) @@ -146,6 +175,7 @@ assert ten == 10 ten = foo.test_buffer(arr) assert ten == 10 + foo.test_contiguous(arr) def test_releasebuffer(self): module = self.import_extension('foo', [ diff --git a/pypy/module/cpyext/test/test_typeobject.py b/pypy/module/cpyext/test/test_typeobject.py --- a/pypy/module/cpyext/test/test_typeobject.py +++ b/pypy/module/cpyext/test/test_typeobject.py @@ -337,12 +337,8 @@ PyObject* name = PyBytes_FromString("mymodule"); PyObject *obj = PyType_Type.tp_alloc(&PyType_Type, 0); PyHeapTypeObject *type = (PyHeapTypeObject*)obj; - if ((type->ht_type.tp_flags & Py_TPFLAGS_HEAPTYPE) == 0) - { - PyErr_SetString(PyExc_ValueError, - "Py_TPFLAGS_HEAPTYPE not set"); - return NULL; - } + /* this is issue #2434: logic from pybind11 */ + type->ht_type.tp_flags |= Py_TPFLAGS_HEAPTYPE; type->ht_type.tp_name = ((PyTypeObject*)args)->tp_name; PyType_Ready(&type->ht_type); ret = PyObject_SetAttrString((PyObject*)&type->ht_type, diff --git a/pypy/module/imp/test/test_import.py b/pypy/module/imp/test/test_import.py --- a/pypy/module/imp/test/test_import.py +++ b/pypy/module/imp/test/test_import.py @@ -601,25 +601,15 @@ import pkg.a, imp imp.reload(pkg.a) - def test_reload_builtin(self): - import sys, imp - oldpath = sys.path - try: - del sys.settrace - except AttributeError: - pass - - imp.reload(sys) - - assert sys.path is oldpath - assert 'settrace' not in dir(sys) # at least on CPython 3.5.2 - def test_reload_builtin_doesnt_clear(self): import imp import sys sys.foobar = "baz" - imp.reload(sys) - assert sys.foobar == "baz" + try: + imp.reload(sys) + assert sys.foobar == "baz" + finally: + del sys.foobar def test_reimport_builtin_simple_case_1(self): import sys, time @@ -637,18 +627,18 @@ def test_reimport_builtin(self): import imp, sys, time - oldpath = sys.path - time.tzname = "<test_reimport_builtin removed this>" + old_sleep = time.sleep + time.sleep = "<test_reimport_builtin removed this>" del sys.modules['time'] import time as time1 assert sys.modules['time'] is time1 - assert time.tzname == "<test_reimport_builtin removed this>" + assert time.sleep == "<test_reimport_builtin removed this>" - imp.reload(time1) # don't leave a broken time.tzname behind + imp.reload(time1) # don't leave a broken time.sleep behind import time - assert time.tzname != "<test_reimport_builtin removed this>" + assert time.sleep is old_sleep def test_reload_infinite(self): import infinite_reload diff --git a/pypy/module/posix/__init__.py b/pypy/module/posix/__init__.py --- a/pypy/module/posix/__init__.py +++ b/pypy/module/posix/__init__.py @@ -243,6 +243,9 @@ if getattr(rposix, _name) is not None: interpleveldefs[_name] = 'space.wrap(%d)' % getattr(rposix, _name) + if hasattr(rposix, 'sched_yield'): + interpleveldefs['sched_yield'] = 'interp_posix.sched_yield' + for _name in ["O_CLOEXEC"]: if getattr(rposix, _name) is not None: interpleveldefs[_name] = 'space.wrap(%d)' % getattr(rposix, _name) diff --git a/pypy/module/posix/interp_posix.py b/pypy/module/posix/interp_posix.py --- a/pypy/module/posix/interp_posix.py +++ b/pypy/module/posix/interp_posix.py @@ -2481,3 +2481,14 @@ wrap_oserror(space, e, eintr_retry=True) else: return space.newint(s) + +def sched_yield(space): + """ Voluntarily relinquish the CPU""" + while True: + try: + res = rposix.sched_yield() + except OSError as e: + wrap_oserror(space, e, eintr_retry=True) + else: + return space.newint(res) +>>>>>>> other diff --git a/pypy/module/posix/test/test_posix2.py b/pypy/module/posix/test/test_posix2.py --- a/pypy/module/posix/test/test_posix2.py +++ b/pypy/module/posix/test/test_posix2.py @@ -975,6 +975,12 @@ assert isinstance(high, int) == True assert high > low + if hasattr(rposix, 'sched_yield'): + def test_sched_yield(self): + os = self.posix + #Always suceeds on Linux + os.sched_yield() + def test_write_buffer(self): os = self.posix fd = os.open(self.path2 + 'test_write_buffer', diff --git a/pypy/module/pyexpat/interp_pyexpat.py b/pypy/module/pyexpat/interp_pyexpat.py --- a/pypy/module/pyexpat/interp_pyexpat.py +++ b/pypy/module/pyexpat/interp_pyexpat.py @@ -811,7 +811,7 @@ w_encoding) if space.is_none(w_namespace_separator): - namespace_separator = 0 + namespace_separator = -1 elif space.isinstance_w(w_namespace_separator, space.w_text): separator = space.text_w(w_namespace_separator) if len(separator) == 0: @@ -834,7 +834,7 @@ elif space.is_w(w_intern, space.w_None): w_intern = None - if namespace_separator: + if namespace_separator >= 0: xmlparser = XML_ParserCreateNS( encoding, rffi.cast(rffi.CHAR, namespace_separator)) diff --git a/pypy/module/pyexpat/test/test_parser.py b/pypy/module/pyexpat/test/test_parser.py --- a/pypy/module/pyexpat/test/test_parser.py +++ b/pypy/module/pyexpat/test/test_parser.py @@ -58,9 +58,9 @@ p.CharacterDataHandler = lambda s: data.append(s) encoding = encoding_arg is None and 'utf-8' or encoding_arg - res = p.Parse("<xml>\u00f6</xml>".encode(encoding), True) + res = p.Parse(u"<xml>\u00f6</xml>".encode(encoding), True) assert res == 1 - assert data == ["\u00f6"] + assert data == [u"\u00f6"] def test_get_handler(self): import pyexpat @@ -210,6 +210,34 @@ p.ParseFile(fake_reader) assert fake_reader.read_count == 4 + def test_entities(self): + import pyexpat + parser = pyexpat.ParserCreate(None, "") + + def startElement(tag, attrs): + assert tag == 'http://www.w3.org/1999/02/22-rdf-syntax-ns#RDF' + assert attrs == { + 'http://www.w3.org/XML/1998/namespacebase': + 'http://www.semanticweb.org/jiba/ontologies/2017/0/test'} + parser.StartElementHandler = startElement + parser.Parse("""<?xml version="1.0"?> + + <!DOCTYPE rdf:RDF [ + <!ENTITY owl "http://www.w3.org/2002/07/owl#" > + <!ENTITY xsd "http://www.w3.org/2001/XMLSchema#" > + <!ENTITY rdfs "http://www.w3.org/2000/01/rdf-schema#" > + <!ENTITY rdf "http://www.w3.org/1999/02/22-rdf-syntax-ns#" > + ]> + + <rdf:RDF xmlns="http://www.semanticweb.org/jiba/ontologies/2017/0/test#" + xml:base="http://www.semanticweb.org/jiba/ontologies/2017/0/test" + xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#" + xmlns:owl="http://www.w3.org/2002/07/owl#" + xmlns:xsd="http://www.w3.org/2001/XMLSchema#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> + </rdf:RDF> + """, True) + def test_exception(self): """ diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_version.py b/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_version.py --- a/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_version.py +++ b/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_version.py @@ -37,7 +37,7 @@ v = cffi.__version__.replace('+', '') p = os.path.join(parent, 'doc', 'source', 'installation.rst') content = open(p).read() - assert ("/cffi-%s.tar.gz" % v) in content + assert (" package version %s:" % v) in content def test_setup_version(): parent = os.path.dirname(os.path.dirname(cffi.__file__)) diff --git a/pypy/module/test_lib_pypy/test_sqlite3.py b/pypy/module/test_lib_pypy/test_sqlite3.py --- a/pypy/module/test_lib_pypy/test_sqlite3.py +++ b/pypy/module/test_lib_pypy/test_sqlite3.py @@ -228,6 +228,14 @@ cur.execute("create table test(a)") cur.executemany("insert into test values (?)", [[1], [2], [3]]) assert cur.lastrowid is None + # issue 2682 + cur.execute('''insert + into test + values (?) + ''', (1, )) + assert cur.lastrowid is not None + cur.execute('''insert\t into test values (?) ''', (1, )) + assert cur.lastrowid is not None def test_authorizer_bad_value(self, con): def authorizer_cb(action, arg1, arg2, dbname, source): diff --git a/pypy/module/unicodedata/test/test_hyp.py b/pypy/module/unicodedata/test/test_hyp.py --- a/pypy/module/unicodedata/test/test_hyp.py +++ b/pypy/module/unicodedata/test/test_hyp.py @@ -40,6 +40,7 @@ @pytest.mark.parametrize('NF1, NF2, NF3', compositions) @example(s=u'---\uafb8\u11a7---') # issue 2289 +@example(s=u'\ufacf') @settings(max_examples=1000) @given(s=st.text()) def test_composition(s, space, NF1, NF2, NF3): diff --git a/pypy/objspace/std/test/test_bytesobject.py b/pypy/objspace/std/test/test_bytesobject.py --- a/pypy/objspace/std/test/test_bytesobject.py +++ b/pypy/objspace/std/test/test_bytesobject.py @@ -1,4 +1,7 @@ # coding: utf-8 + +from pypy.interpreter.error import OperationError + class TestW_BytesObject: def teardown_method(self, method): @@ -96,6 +99,78 @@ w_res = space.call_function(space.w_bytes, space.wrap([42])) assert space.str_w(w_res) == '*' + +try: + from hypothesis import given, strategies +except ImportError: + pass +else: + @given(u=strategies.binary(), + start=strategies.integers(min_value=0, max_value=10), + len1=strategies.integers(min_value=-1, max_value=10)) + def test_hypo_index_find(u, start, len1, space): + if start + len1 < 0: + return # skip this case + v = u[start : start + len1] + w_u = space.wrap(u) + w_v = space.wrap(v) + expected = u.find(v, start, start + len1) + try: + w_index = space.call_method(w_u, 'index', w_v, + space.newint(start), + space.newint(start + len1)) + except OperationError as e: + if not e.match(space, space.w_ValueError): + raise + assert expected == -1 + else: + assert space.int_w(w_index) == expected >= 0 + + w_index = space.call_method(w_u, 'find', w_v, + space.newint(start), + space.newint(start + len1)) + assert space.int_w(w_index) == expected + + rexpected = u.rfind(v, start, start + len1) + try: + w_index = space.call_method(w_u, 'rindex', w_v, + space.newint(start), + space.newint(start + len1)) + except OperationError as e: + if not e.match(space, space.w_ValueError): + raise + assert rexpected == -1 + else: + assert space.int_w(w_index) == rexpected >= 0 + + w_index = space.call_method(w_u, 'rfind', w_v, + space.newint(start), + space.newint(start + len1)) + assert space.int_w(w_index) == rexpected + + expected = u.startswith(v, start) + w_res = space.call_method(w_u, 'startswith', w_v, + space.newint(start)) + assert w_res is space.newbool(expected) + + expected = u.startswith(v, start, start + len1) + w_res = space.call_method(w_u, 'startswith', w_v, + space.newint(start), + space.newint(start + len1)) + assert w_res is space.newbool(expected) + + expected = u.endswith(v, start) + w_res = space.call_method(w_u, 'endswith', w_v, + space.newint(start)) + assert w_res is space.newbool(expected) + + expected = u.endswith(v, start, start + len1) + w_res = space.call_method(w_u, 'endswith', w_v, + space.newint(start), + space.newint(start + len1)) + assert w_res is space.newbool(expected) + + class AppTestBytesObject: def setup_class(cls): diff --git a/pypy/objspace/std/test/test_unicodeobject.py b/pypy/objspace/std/test/test_unicodeobject.py --- a/pypy/objspace/std/test/test_unicodeobject.py +++ b/pypy/objspace/std/test/test_unicodeobject.py @@ -1,6 +1,7 @@ # -*- encoding: utf-8 -*- import py import sys +from pypy.interpreter.error import OperationError class TestUnicodeObject: @@ -38,6 +39,55 @@ space.raises_w(space.w_UnicodeEncodeError, space.text_w, w_uni) +try: + from hypothesis import given, strategies +except ImportError: + pass +else: + @given(u=strategies.text(), + start=strategies.integers(min_value=0, max_value=10), + len1=strategies.integers(min_value=-1, max_value=10)) + def test_hypo_index_find(u, start, len1, space): + if start + len1 < 0: + return # skip this case + v = u[start : start + len1] + w_u = space.wrap(u) + w_v = space.wrap(v) + expected = u.find(v, start, start + len1) + try: + w_index = space.call_method(w_u, 'index', w_v, + space.newint(start), + space.newint(start + len1)) + except OperationError as e: + if not e.match(space, space.w_ValueError): + raise + assert expected == -1 + else: + assert space.int_w(w_index) == expected >= 0 + + w_index = space.call_method(w_u, 'find', w_v, + space.newint(start), + space.newint(start + len1)) + assert space.int_w(w_index) == expected + + rexpected = u.rfind(v, start, start + len1) + try: + w_index = space.call_method(w_u, 'rindex', w_v, + space.newint(start), + space.newint(start + len1)) + except OperationError as e: + if not e.match(space, space.w_ValueError): + raise + assert rexpected == -1 + else: + assert space.int_w(w_index) == rexpected >= 0 + + w_index = space.call_method(w_u, 'rfind', w_v, + space.newint(start), + space.newint(start + len1)) + assert space.int_w(w_index) == rexpected + + class AppTestUnicodeStringStdOnly: def test_compares(self): assert type('a') != type(b'a') diff --git a/pypy/objspace/std/unicodeobject.py b/pypy/objspace/std/unicodeobject.py --- a/pypy/objspace/std/unicodeobject.py +++ b/pypy/objspace/std/unicodeobject.py @@ -748,17 +748,6 @@ interpreted as in slice notation. """ - def decode(): - """S.decode(encoding=None, errors='strict') -> string or unicode - - Decode S using the codec registered for encoding. encoding defaults - to the default encoding. errors may be given to set a different error - handling scheme. Default is 'strict' meaning that encoding errors raise - a UnicodeDecodeError. Other possible values are 'ignore' and 'replace' - as well as any other name registered with codecs.register_error that is - able to handle UnicodeDecodeErrors. - """ - def encode(): """S.encode(encoding=None, errors='strict') -> string or unicode 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 @@ -12,7 +12,7 @@ from pypy.interpreter.gateway import app2interp_temp from pypy.interpreter.error import OperationError from pypy.interpreter.function import Method -from rpython.tool import runsubprocess +from rpython.tool.runsubprocess import run_subprocess from pypy.tool.pytest import appsupport from pypy.tool.pytest.objspace import gettestobjspace from rpython.tool.udir import udir @@ -67,14 +67,10 @@ def _rename_module(name): return str(RENAMED_USEMODULES.get(name, name)) - -def run_with_python(python_, target_, usemodules, **definitions): - if python_ is None: - py.test.skip("Cannot find the default python3 interpreter to run with -A") - # we assume that the source of target_ is in utf-8. Unfortunately, we don't - # have any easy/standard way to determine from here the original encoding - # of the source file - helpers = r"""# -*- encoding: utf-8 -*- +# we assume that the source of target_ is in utf-8. Unfortunately, we don't +# have any easy/standard way to determine from here the original encoding +# of the source file +helpers = r"""# -*- encoding: utf-8 -*- if 1: import sys sys.path.append(%r) @@ -90,7 +86,7 @@ import os try: if isinstance(func, str): - if func.startswith((' ', os.linesep)): + if func.startswith((' ', os.linesep, '\n')): # it's probably an indented block, so we prefix if True: # to avoid SyntaxError func = "if True:\n" + func @@ -109,6 +105,10 @@ pass self = Test() """ + +def run_with_python(python_, target_, usemodules, **definitions): + if python_ is None: + py.test.skip("Cannot find the default python3 interpreter to run with -A") defs = [] for symbol, value in sorted(definitions.items()): if isinstance(value, tuple) and isinstance(value[0], py.code.Source): @@ -181,7 +181,7 @@ helper_dir = os.path.join(pypydir, 'tool', 'cpyext') env = os.environ.copy() env['PYTHONPATH'] = helper_dir - res, stdout, stderr = runsubprocess.run_subprocess( + res, stdout, stderr = run_subprocess( python_, [str(pyfile)], env=env) print pyfile.read() print >> sys.stdout, stdout diff --git a/pypy/tool/pytest/objspace.py b/pypy/tool/pytest/objspace.py --- a/pypy/tool/pytest/objspace.py +++ b/pypy/tool/pytest/objspace.py @@ -57,9 +57,6 @@ if not ok: py.test.skip("cannot runappdirect test: " "module %r required" % (modname,)) - else: - if '__pypy__' in value: - py.test.skip("no module __pypy__ on top of CPython") continue if info is None: py.test.skip("cannot runappdirect this test on top of CPython") diff --git a/rpython/doc/jit/optimizer.rst b/rpython/doc/jit/optimizer.rst --- a/rpython/doc/jit/optimizer.rst +++ b/rpython/doc/jit/optimizer.rst @@ -42,10 +42,9 @@ There are better ways to compute the sum from ``[0..100]``, but it gives a better intuition on how traces are constructed than ``sum(range(101))``. Note that the trace syntax is the one used in the test suite. It is also very -similar to traces printed at runtime by PYPYLOG_. The first line gives the input variables, the -second line is a ``label`` operation, the last one is the backwards ``jump`` operation. - -.. _PYPYLOG: logging.html +similar to traces printed at runtime by :doc:`PYPYLOG <../logging>`. The first +line gives the input variables, the second line is a ``label`` operation, the +last one is the backwards ``jump`` operation. These instructions mentioned earlier are special: diff --git a/rpython/jit/metainterp/optimizeopt/intbounds.py b/rpython/jit/metainterp/optimizeopt/intbounds.py --- a/rpython/jit/metainterp/optimizeopt/intbounds.py +++ b/rpython/jit/metainterp/optimizeopt/intbounds.py @@ -305,6 +305,10 @@ # Transform into INT_ADD. The following guard will be killed # by optimize_GUARD_NO_OVERFLOW; if we see instead an # optimize_GUARD_OVERFLOW, then InvalidLoop. + + # NB: this case also takes care of int_add_ovf with 0 as on of the + # arguments: the result will be bounded, and then the optimization + # for int_add with 0 as argument will remove the op. op = self.replace_op_with(op, rop.INT_ADD) return self.emit(op) @@ -325,6 +329,7 @@ return None resbound = b0.sub_bound(b1) if resbound.bounded(): + # this case takes care of int_sub_ovf(x, 0) as well op = self.replace_op_with(op, rop.INT_SUB) return self.emit(op) @@ -342,6 +347,7 @@ b2 = self.getintbound(op.getarg(1)) resbound = b1.mul_bound(b2) if resbound.bounded(): + # this case also takes care of multiplication with 0 and 1 op = self.replace_op_with(op, rop.INT_MUL) return self.emit(op) diff --git a/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py b/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py --- a/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py +++ b/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py @@ -1962,6 +1962,55 @@ """ self.optimize_loop(ops, expected) + ops = """ + [i0] + i1 = int_mul_ovf(0, i0) + guard_no_overflow() [] + jump(i1) + """ + expected = """ + [i0] + jump(0) + """ + self.optimize_loop(ops, expected) + + ops = """ + [i0] + i1 = int_mul_ovf(i0, 0) + guard_no_overflow() [] + jump(i1) + """ + expected = """ + [i0] + jump(0) + """ + self.optimize_loop(ops, expected) + + ops = """ + [i0] + i1 = int_mul_ovf(1, i0) + guard_no_overflow() [] + jump(i1) + """ + expected = """ + [i0] + jump(i0) + """ + self.optimize_loop(ops, expected) + + ops = """ + [i0] + i1 = int_mul_ovf(i0, 1) + guard_no_overflow() [] + jump(i1) + """ + expected = """ + [i0] + jump(i0) + """ + self.optimize_loop(ops, expected) + + def test_fold_constant_partial_ops_float(self): ops = """ [f0] diff --git a/rpython/rlib/rposix.py b/rpython/rlib/rposix.py --- a/rpython/rlib/rposix.py +++ b/rpython/rlib/rposix.py @@ -1863,6 +1863,8 @@ rffi.INT, save_err=rffi.RFFI_FULL_ERRNO_ZERO) c_sched_get_priority_min = external('sched_get_priority_min', [rffi.INT], rffi.INT, save_err=rffi.RFFI_SAVE_ERRNO) + if not _WIN32: + c_sched_yield = external('sched_yield', [], rffi.INT) @enforceargs(int) def sched_get_priority_max(policy): @@ -1872,9 +1874,9 @@ def sched_get_priority_min(policy): return handle_posix_error('sched_get_priority_min', c_sched_get_priority_min(policy)) - - - + def sched_yield(): + return handle_posix_error('sched_yield', c_sched_yield()) + #___________________________________________________________________ c_chroot = external('chroot', [rffi.CCHARP], rffi.INT, diff --git a/rpython/rlib/runicode.py b/rpython/rlib/runicode.py --- a/rpython/rlib/runicode.py +++ b/rpython/rlib/runicode.py @@ -877,32 +877,31 @@ ch = ord(s[pos]) pos += 1 ch2 = 0 - if 0xD800 <= ch < 0xDC00: - if not allow_surrogates: - ru, rs, pos = errorhandler(errors, public_encoding_name, - 'surrogates not allowed', - s, pos-1, pos) - if rs is not None: - # py3k only - if len(rs) % 4 != 0: - errorhandler('strict', public_encoding_name, - 'surrogates not allowed', - s, pos-1, pos) - result.append(rs) - continue - for ch in ru: - if ord(ch) < 0xD800: - _STORECHAR32(result, ord(ch), byteorder) - else: - errorhandler('strict', public_encoding_name, - 'surrogates not allowed', - s, pos-1, pos) + if not allow_surrogates and 0xD800 <= ch < 0xE000: + ru, rs, pos = errorhandler(errors, public_encoding_name, + 'surrogates not allowed', + s, pos-1, pos) + if rs is not None: + # py3k only + if len(rs) % 4 != 0: + errorhandler('strict', public_encoding_name, + 'surrogates not allowed', + s, pos-1, pos) + result.append(rs) continue - elif MAXUNICODE < 65536 and pos < size: - ch2 = ord(s[pos]) - if 0xDC00 <= ch2 < 0xE000: - ch = (((ch & 0x3FF)<<10) | (ch2 & 0x3FF)) + 0x10000; - pos += 1 + for ch in ru: + if ord(ch) < 0xD800: + _STORECHAR32(result, ord(ch), byteorder) + else: + errorhandler('strict', public_encoding_name, + 'surrogates not allowed', + s, pos-1, pos) + continue + if 0xD800 <= ch < 0xDC00 and MAXUNICODE < 65536 and pos < size: + ch2 = ord(s[pos]) + if 0xDC00 <= ch2 < 0xE000: + ch = (((ch & 0x3FF)<<10) | (ch2 & 0x3FF)) + 0x10000; + pos += 1 _STORECHAR32(result, ch, byteorder) return result.build() diff --git a/rpython/rlib/test/test_rposix.py b/rpython/rlib/test/test_rposix.py --- a/rpython/rlib/test/test_rposix.py +++ b/rpython/rlib/test/test_rposix.py @@ -810,6 +810,11 @@ assert isinstance(low, int) == True assert isinstance(high, int) == True assert high > low + +@rposix_requires('sched_yield') +def test_sched_yield(): + if sys.platform != 'win32': + rposix.sched_yield() @rposix_requires('lockf') def test_os_lockf(): diff --git a/rpython/rlib/test/test_runicode.py b/rpython/rlib/test/test_runicode.py --- a/rpython/rlib/test/test_runicode.py +++ b/rpython/rlib/test/test_runicode.py @@ -2,6 +2,7 @@ import py import sys, random +import struct from rpython.rlib import runicode from hypothesis import given, settings, strategies @@ -266,11 +267,12 @@ assert replace_with(u'rep', None) == '\x00<\x00r\x00e\x00p\x00>' assert replace_with(None, '\xca\xfe') == '\x00<\xca\xfe\x00>' - def test_utf32_surrogates(self): + @py.test.mark.parametrize('unich',[u"\ud800", u"\udc80"]) + def test_utf32_surrogates(self, unich): assert runicode.unicode_encode_utf_32_be( - u"\ud800", 1, None) == '\x00\x00\xd8\x00' + unich, 1, None) == struct.pack('>i', ord(unich)) py.test.raises(UnicodeEncodeError, runicode.unicode_encode_utf_32_be, - u"\ud800", 1, None, allow_surrogates=False) + unich, 1, None, allow_surrogates=False) def replace_with(ru, rs): def errorhandler(errors, enc, msg, u, startingpos, endingpos): if errors == 'strict': @@ -278,7 +280,7 @@ endingpos, msg) return ru, rs, endingpos return runicode.unicode_encode_utf_32_be( - u"<\ud800>", 3, None, + u"<%s>" % unich, 3, None, errorhandler, allow_surrogates=False) assert replace_with(u'rep', None) == u'<rep>'.encode('utf-32-be') assert replace_with(None, '\xca\xfe\xca\xfe') == '\x00\x00\x00<\xca\xfe\xca\xfe\x00\x00\x00>' @@ -432,7 +434,7 @@ assert (self.decoder('aaaa' + seq + 'bbbb', len(seq) + 8, 'ignore', final=True) == (u'aaaabbbb', len(seq) + 8)) assert (self.decoder(seq, len(seq), 'custom', final=True, - errorhandler=self.custom_replace) == + errorhandler=self.custom_replace) == (FOO * len(seq), len(seq))) assert (self.decoder('aaaa' + seq + 'bbbb', len(seq) + 8, 'custom', final=True, errorhandler=self.custom_replace) == @@ -628,7 +630,7 @@ msg='invalid continuation byte') assert self.decoder(seq, len(seq), 'replace', final=True ) == (res, len(seq)) - assert (self.decoder('aaaa' + seq + 'bbbb', len(seq) + 8, + assert (self.decoder('aaaa' + seq + 'bbbb', len(seq) + 8, 'replace', final=True) == (u'aaaa' + res + u'bbbb', len(seq) + 8)) res = res.replace(FFFD, u'') _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit