Author: Matti Picus <matti.pi...@gmail.com> Branch: release-pypy3.5-5.x Changeset: r92481:24686d8f9ef3 Date: 2017-09-27 21:18 +0300 http://bitbucket.org/pypy/pypy/changeset/24686d8f9ef3/
Log: merge py3.5 into branch diff --git a/pypy/interpreter/pycode.py b/pypy/interpreter/pycode.py --- a/pypy/interpreter/pycode.py +++ b/pypy/interpreter/pycode.py @@ -12,7 +12,8 @@ from pypy.interpreter.gateway import unwrap_spec from pypy.interpreter.astcompiler.consts import ( CO_OPTIMIZED, CO_NEWLOCALS, CO_VARARGS, CO_VARKEYWORDS, CO_NESTED, - CO_GENERATOR, CO_COROUTINE, CO_KILL_DOCSTRING, CO_YIELD_INSIDE_TRY) + CO_GENERATOR, CO_COROUTINE, CO_KILL_DOCSTRING, CO_YIELD_INSIDE_TRY, + CO_ITERABLE_COROUTINE) from pypy.tool import dis3 from pypy.tool.stdlib_opcode import opcodedesc, HAVE_ARGUMENT from rpython.rlib.rarithmetic import intmask diff --git a/pypy/module/_socket/__init__.py b/pypy/module/_socket/__init__.py --- a/pypy/module/_socket/__init__.py +++ b/pypy/module/_socket/__init__.py @@ -37,7 +37,8 @@ CMSG_SPACE CMSG_LEN """.split(): - if (name in ('inet_pton', 'inet_ntop', 'socketpair') and + if (name in ('inet_pton', 'inet_ntop', 'socketpair', + 'CMSG_SPACE', 'CMSG_LEN') and not hasattr(rsocket, name)): continue diff --git a/pypy/module/_socket/interp_func.py b/pypy/module/_socket/interp_func.py --- a/pypy/module/_socket/interp_func.py +++ b/pypy/module/_socket/interp_func.py @@ -1,3 +1,4 @@ +import sys from rpython.rlib import rsocket from rpython.rlib.rsocket import SocketError, INVALID_SOCKET from rpython.rlib.rarithmetic import intmask, r_longlong, r_uint32 @@ -327,41 +328,42 @@ for (family, socktype, protocol, canonname, addr) in lst] return space.newlist(lst1) -@unwrap_spec(size=int) -def CMSG_SPACE(space, size): - """ - Socket method to determine the optimal byte size of the ancillary. - Recommended to be used when computing the ancillary size for recvmsg. - :param space: - :param size: an integer with the minimum size required. - :return: an integer with the minimum memory needed for the required size. The value is memory alligned - """ - if size < 0: - raise oefmt(space.w_OverflowError, - "CMSG_SPACE() argument out of range") - retval = rsocket.CMSG_SPACE(size) - if retval == 0: - raise oefmt(space.w_OverflowError, - "CMSG_SPACE() argument out of range") - return space.newint(retval) +if sys.platform != 'win32': + @unwrap_spec(size=int) + def CMSG_SPACE(space, size): + """ + Socket method to determine the optimal byte size of the ancillary. + Recommended to be used when computing the ancillary size for recvmsg. + :param space: + :param size: an integer with the minimum size required. + :return: an integer with the minimum memory needed for the required size. The value is memory alligned + """ + if size < 0: + raise oefmt(space.w_OverflowError, + "CMSG_SPACE() argument out of range") + retval = rsocket.CMSG_SPACE(size) + if retval == 0: + raise oefmt(space.w_OverflowError, + "CMSG_SPACE() argument out of range") + return space.newint(retval) -@unwrap_spec(len=int) -def CMSG_LEN(space, len): - """ - Socket method to determine the optimal byte size of the ancillary. - Recommended to be used when computing the ancillary size for recvmsg. - :param space: - :param len: an integer with the minimum size required. - :return: an integer with the minimum memory needed for the required size. The value is not mem alligned. - """ - if len < 0: - raise oefmt(space.w_OverflowError, - "CMSG_LEN() argument out of range") - retval = rsocket.CMSG_LEN(len) - if retval == 0: - raise oefmt(space.w_OverflowError, - "CMSG_LEN() argument out of range") - return space.newint(retval) + @unwrap_spec(len=int) + def CMSG_LEN(space, len): + """ + Socket method to determine the optimal byte size of the ancillary. + Recommended to be used when computing the ancillary size for recvmsg. + :param space: + :param len: an integer with the minimum size required. + :return: an integer with the minimum memory needed for the required size. The value is not mem alligned. + """ + if len < 0: + raise oefmt(space.w_OverflowError, + "CMSG_LEN() argument out of range") + retval = rsocket.CMSG_LEN(len) + if retval == 0: + raise oefmt(space.w_OverflowError, + "CMSG_LEN() argument out of range") + return space.newint(retval) def getdefaulttimeout(space): """getdefaulttimeout() -> timeout diff --git a/pypy/module/_socket/interp_socket.py b/pypy/module/_socket/interp_socket.py --- a/pypy/module/_socket/interp_socket.py +++ b/pypy/module/_socket/interp_socket.py @@ -879,11 +879,14 @@ socketmethodnames = """ _accept bind close connect connect_ex fileno detach getpeername getsockname getsockopt gettimeout listen -recv recvfrom recvmsg send sendall sendto sendmsg setblocking +recv recvfrom send sendall sendto setblocking setsockopt settimeout shutdown _reuse _drop recv_into recvfrom_into """.split() if hasattr(rsocket._c, 'WSAIoctl'): socketmethodnames.append('ioctl') +if rsocket._c.HAVE_SENDMSG: + socketmethodnames.append('sendmsg') + socketmethodnames.append('recvmsg') socketmethods = {} for methodname in socketmethodnames: diff --git a/pypy/module/cpyext/funcobject.py b/pypy/module/cpyext/funcobject.py --- a/pypy/module/cpyext/funcobject.py +++ b/pypy/module/cpyext/funcobject.py @@ -18,6 +18,8 @@ CO_VARKEYWORDS = 0x0008, CO_NESTED = 0x0010, CO_GENERATOR = 0x0020, + CO_COROUTINE=0x0080, + CO_ITERABLE_COROUTINE=0x0100, ) ALL_CODE_FLAGS = unrolling_iterable(CODE_FLAGS.items()) diff --git a/pypy/module/cpyext/genobject.py b/pypy/module/cpyext/genobject.py --- a/pypy/module/cpyext/genobject.py +++ b/pypy/module/cpyext/genobject.py @@ -1,7 +1,32 @@ +from rpython.rtyper.lltypesystem import lltype from pypy.interpreter.generator import GeneratorIterator, Coroutine -from pypy.module.cpyext.api import build_type_checkers +from pypy.module.cpyext.api import ( + build_type_checkers, cts, parse_dir, bootstrap_function, slot_function) +from pypy.module.cpyext.pyobject import PyObject, make_typedescr, as_pyobj +from pypy.module.cpyext.object import _dealloc + +cts.parse_header(parse_dir / 'cpyext_genobject.h') + +@bootstrap_function +def init_genobject(space): + make_typedescr(GeneratorIterator.typedef, + basestruct=cts.gettype('PyGenObject'), + attach=gi_attach, + dealloc=gi_dealloc) PyGen_Check, PyGen_CheckExact = build_type_checkers("Gen", GeneratorIterator) _, PyCoro_CheckExact = build_type_checkers("Coro", Coroutine) + +def gi_attach(space, py_obj, w_obj, w_userdata=None): + assert isinstance(w_obj, GeneratorIterator) + cts.cast('PyGenObject*', py_obj).c_gi_code = as_pyobj(space, w_obj.pycode) + +def gi_realize(space, py_obj): + raise NotImplementedError( + "PyPy doesn't support creation of generators from the C-API.") + +@slot_function([PyObject], lltype.Void) +def gi_dealloc(space, py_obj): + _dealloc(space, py_obj) 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 @@ -127,6 +127,7 @@ #include "pycapsule.h" #include "bytesobject.h" #include "sliceobject.h" +#include "genobject.h" #include "datetime.h" #include "pystate.h" #include "fileobject.h" diff --git a/pypy/module/cpyext/include/code.h b/pypy/module/cpyext/include/code.h --- a/pypy/module/cpyext/include/code.h +++ b/pypy/module/cpyext/include/code.h @@ -20,6 +20,11 @@ #define CO_VARKEYWORDS 0x0008 #define CO_NESTED 0x0010 #define CO_GENERATOR 0x0020 + +/* The CO_COROUTINE flag is set for coroutine functions (defined with + ``async def`` keywords) */ +#define CO_COROUTINE 0x0080 +#define CO_ITERABLE_COROUTINE 0x0100 #define CO_FUTURE_DIVISION 0x02000 #define CO_FUTURE_ABSOLUTE_IMPORT 0x04000 diff --git a/pypy/module/cpyext/include/genobject.h b/pypy/module/cpyext/include/genobject.h new file mode 100644 --- /dev/null +++ b/pypy/module/cpyext/include/genobject.h @@ -0,0 +1,12 @@ +#ifndef Py_GENOBJECT_H +#define Py_GENOBJECT_H +#ifdef __cplusplus +extern "C" { +#endif + +#include "cpyext_genobject.h" + +#ifdef __cplusplus +} +#endif +#endif /* !Py_GENOBJECT_H */ diff --git a/pypy/module/cpyext/longobject.py b/pypy/module/cpyext/longobject.py --- a/pypy/module/cpyext/longobject.py +++ b/pypy/module/cpyext/longobject.py @@ -201,6 +201,10 @@ for the conversion. The radix must be in the range [2, 36]; if it is out of range, ValueError will be raised.""" w_value = space.newunicode(rffi.wcharpsize2unicode(u, length)) + return PyLong_FromUnicodeObject(space, w_value, base) + +@cpython_api([PyObject, rffi.INT_real], PyObject) +def PyLong_FromUnicodeObject(space, w_value, base): w_base = space.newint(rffi.cast(lltype.Signed, base)) return space.call_function(space.w_long, w_value, w_base) diff --git a/pypy/module/cpyext/parse/cpyext_genobject.h b/pypy/module/cpyext/parse/cpyext_genobject.h new file mode 100644 --- /dev/null +++ b/pypy/module/cpyext/parse/cpyext_genobject.h @@ -0,0 +1,4 @@ +typedef struct { + PyObject_HEAD + PyObject* gi_code; +} PyGenObject; diff --git a/pypy/module/cpyext/test/test_genobject.py b/pypy/module/cpyext/test/test_genobject.py --- a/pypy/module/cpyext/test/test_genobject.py +++ b/pypy/module/cpyext/test/test_genobject.py @@ -28,7 +28,29 @@ assert PyCoro_CheckExact(space, w_coroutine) class AppTestCoroutine(AppTestCpythonExtensionBase): - def test_simple(self): + def test_generator_coroutine(self): + module = self.import_extension('test_gen', [ + ('is_coroutine', 'METH_O', + ''' + if (!PyGen_CheckExact(args)) + Py_RETURN_NONE; + PyObject* co = ((PyGenObject*)args)->gi_code; + if (((PyCodeObject*)co)->co_flags & CO_ITERABLE_COROUTINE) + Py_RETURN_TRUE; + else + Py_RETURN_FALSE; + ''')]) + + def it(): + yield 42 + + print(module.is_coroutine(it())) + assert module.is_coroutine(it()) is False + self.debug_collect() # don't crash while deallocating + from types import coroutine + assert module.is_coroutine(coroutine(it)()) is True + + def test_await(self): """ module = self.import_extension('test_coroutine', [ ('await_', 'METH_O', diff --git a/pypy/module/cpyext/test/test_longobject.py b/pypy/module/cpyext/test/test_longobject.py --- a/pypy/module/cpyext/test/test_longobject.py +++ b/pypy/module/cpyext/test/test_longobject.py @@ -272,6 +272,19 @@ # A string with arabic digits. 'BAD' is after the 6th character. assert module.from_unicode(u' 1\u0662\u0663\u0664BAD') == (1234, 4660) + def test_fromunicodeobject(self): + module = self.import_extension('foo', [ + ("from_unicodeobject", "METH_O", + """ + return Py_BuildValue("NN", + PyLong_FromUnicodeObject(args, 10), + PyLong_FromUnicodeObject(args, 16)); + """), + ]) + # A string with arabic digits. + assert (module.from_unicodeobject(u' 1\u0662\u0663\u0664') + == (1234, 4660)) + def test_aslong(self): module = self.import_extension('foo', [ ("as_long", "METH_O", diff --git a/pypy/module/cpyext/test/test_unicodeobject.py b/pypy/module/cpyext/test/test_unicodeobject.py --- a/pypy/module/cpyext/test/test_unicodeobject.py +++ b/pypy/module/cpyext/test/test_unicodeobject.py @@ -851,6 +851,17 @@ assert r"['a\n', 'b\n', 'c\n', 'd']" == space.unwrap(space.repr( PyUnicode_Splitlines(space, w_str, 1))) + def test_substring_api(self, space): + w_str = space.wrap(u"abcd") + assert space.unwrap(PyUnicode_Substring(space, w_str, 1, 3)) == u"bc" + assert space.unwrap(PyUnicode_Substring(space, w_str, 0, 4)) == u"abcd" + assert space.unwrap(PyUnicode_Substring(space, w_str, 0, 9)) == u"abcd" + assert space.unwrap(PyUnicode_Substring(space, w_str, 1, 4)) == u"bcd" + assert space.unwrap(PyUnicode_Substring(space, w_str, 2, 2)) == u"" + assert space.unwrap(PyUnicode_Substring(space, w_str, 5, 4)) == u"" + assert space.unwrap(PyUnicode_Substring(space, w_str, 5, 3)) == u"" + assert space.unwrap(PyUnicode_Substring(space, w_str, 4, 3)) == u"" + def test_Ready(self, space): w_str = space.wrap(u'abc') # ASCII py_str = as_pyobj(space, w_str) diff --git a/pypy/module/cpyext/unicodeobject.py b/pypy/module/cpyext/unicodeobject.py --- a/pypy/module/cpyext/unicodeobject.py +++ b/pypy/module/cpyext/unicodeobject.py @@ -1043,3 +1043,17 @@ resulting strings.""" w_keepend = space.newbool(bool(rffi.cast(lltype.Signed, keepend))) return space.call_method(w_str, "splitlines", w_keepend) + +@cpython_api([PyObject, Py_ssize_t, Py_ssize_t], PyObject) +def PyUnicode_Substring(space, w_str, start, end): + usrc = space.unicode_w(w_str) + length = len(usrc) + if start < 0 or end < 0: + raise oefmt(space.w_IndexError, "string index out of range") + if start >= length or end < start: + result = u'' + else: + if end > length: + end = length + result = usrc[start:end] + return space.newunicode(result) diff --git a/rpython/rlib/_rsocket_rffi.py b/rpython/rlib/_rsocket_rffi.py --- a/rpython/rlib/_rsocket_rffi.py +++ b/rpython/rlib/_rsocket_rffi.py @@ -348,7 +348,8 @@ ('ifr_name', rffi.CFixedArray(rffi.CHAR, 8))]) # insert handler for sendmsg / recvmsg here -if _POSIX: +HAVE_SENDMSG = bool(_POSIX) +if HAVE_SENDMSG: includes = ['stddef.h', 'sys/socket.h', 'unistd.h', diff --git a/rpython/rlib/rsocket.py b/rpython/rlib/rsocket.py --- a/rpython/rlib/rsocket.py +++ b/rpython/rlib/rsocket.py @@ -1393,7 +1393,7 @@ return (make_socket(fd0, family, type, proto, SocketClass), make_socket(fd1, family, type, proto, SocketClass)) -if _c._POSIX: +if _c.HAVE_SENDMSG: def CMSG_LEN( demanded_len): """ Socket method to determine the optimal byte size of the ancillary. _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit