Author: Matti Picus <[email protected]>
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
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit