Thread View
j: Next unread message
k: Previous unread message
j a: Jump to all threads
j l: Jump to MailingList overview
https://hg.python.org/cpython/rev/7ed567ad8b4c
changeset: 95336:7ed567ad8b4c
user: Victor Stinner <victor.stinner(a)gmail.com>
date: Tue Mar 31 22:03:59 2015 +0200
summary:
Issue #23618: Enhance EINTR handling in socket.connect()
Call PyErr_CheckSignals() immediatly if connect() or select() fails with EINTR
in internal_connect().
Refactor also the code to limit indentaton and make it more readable.
files:
Modules/socketmodule.c | 78 +++++++++++++++--------------
1 files changed, 40 insertions(+), 38 deletions(-)
diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c
--- a/Modules/socketmodule.c
+++ b/Modules/socketmodule.c
@@ -2461,52 +2461,54 @@
# define TIMEOUT_ERR EWOULDBLOCK
#endif
- int res, err, in_progress, timeout;
-
- timeout = 0;
+ int res, err, wait_connect, timeout;
+ socklen_t res_size;
+
+ *timeoutp = 0;
Py_BEGIN_ALLOW_THREADS
res = connect(s->sock_fd, addr, addrlen);
Py_END_ALLOW_THREADS
- if (res < 0)
- err = GET_ERROR;
- else
- err = res;
- in_progress = (err == IN_PROGRESS_ERR);
-
- if (s->sock_timeout > 0 && in_progress && IS_SELECTABLE(s)) {
- timeout = internal_connect_select(s);
-
- if (timeout == 1) {
- /* timed out */
- err = TIMEOUT_ERR;
- }
- else if (timeout == 0) {
- socklen_t res_size = sizeof res;
- if (!getsockopt(s->sock_fd, SOL_SOCKET, SO_ERROR,
- (void *)&res, &res_size)) {
- if (res == EISCONN)
- res = 0;
- err = res;
- }
- else {
- /* getsockopt() failed */
- err = GET_ERROR;
- }
- }
- else {
- /* select() failed */
- err = GET_ERROR;
- }
- }
- *timeoutp = timeout;
-
+ if (!res) {
+ /* connect() succeeded, the socket is connected */
+ return 0;
+ }
+
+ err = GET_ERROR;
if (err == EINTR && PyErr_CheckSignals())
return -1;
- assert(err >= 0);
- return err;
+ wait_connect = (s->sock_timeout > 0 && err == IN_PROGRESS_ERR
+ && IS_SELECTABLE(s));
+ if (!wait_connect)
+ return err;
+
+ timeout = internal_connect_select(s);
+ if (timeout == -1) {
+ /* select() failed */
+ err = GET_ERROR;
+ if (err == EINTR && PyErr_CheckSignals())
+ return -1;
+ return err;
+ }
+
+ if (timeout == 1) {
+ /* select() timed out */
+ *timeoutp = 1;
+ return TIMEOUT_ERR;
+ }
+
+ res_size = sizeof res;
+ if (getsockopt(s->sock_fd, SOL_SOCKET, SO_ERROR,
+ (void *)&res, &res_size)) {
+ /* getsockopt() failed */
+ return GET_ERROR;
+ }
+
+ if (res == EISCONN)
+ return 0;
+ return res;
#undef GET_ERROR
#undef IN_PROGRESS_ERR
--
Repository URL: https://hg.python.org/cpython
https://hg.python.org/cpython/rev/4fad2b9fc4e6
changeset: 95335:4fad2b9fc4e6
user: Victor Stinner <victor.stinner(a)gmail.com>
date: Tue Mar 31 21:28:42 2015 +0200
summary:
Issue #23618: Fix EINTR handling in socket.connect()
Call PyErr_CheckSignals() if connect(), select() or getsockopt() failed with
EINTR.
files:
Modules/socketmodule.c | 18 ++++++++----------
1 files changed, 8 insertions(+), 10 deletions(-)
diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c
--- a/Modules/socketmodule.c
+++ b/Modules/socketmodule.c
@@ -2502,6 +2502,9 @@
}
*timeoutp = timeout;
+ if (err == EINTR && PyErr_CheckSignals())
+ return -1;
+
assert(err >= 0);
return err;
@@ -2524,13 +2527,14 @@
return NULL;
res = internal_connect(s, SAS2SA(&addrbuf), addrlen, &timeout);
+ if (res < 0)
+ return NULL;
if (timeout == 1) {
PyErr_SetString(socket_timeout, "timed out");
return NULL;
}
- if (res < 0)
- return NULL;
+
if (res != 0) {
#ifdef MS_WINDOWS
WSASetLastError(res);
@@ -2539,8 +2543,8 @@
#endif
return s->errorhandler();
}
- Py_INCREF(Py_None);
- return Py_None;
+
+ Py_RETURN_NONE;
}
PyDoc_STRVAR(connect_doc,
@@ -2564,15 +2568,9 @@
return NULL;
res = internal_connect(s, SAS2SA(&addrbuf), addrlen, &timeout);
-
if (res < 0)
return NULL;
- /* Signals are not errors (though they may raise exceptions). Adapted
- from PyErr_SetFromErrnoWithFilenameObject(). */
- if (res == EINTR && PyErr_CheckSignals())
- return NULL;
-
return PyLong_FromLong((long) res);
}
--
Repository URL: https://hg.python.org/cpython
https://hg.python.org/cpython/rev/d9374864d4a9
changeset: 95334:d9374864d4a9
user: Victor Stinner <victor.stinner(a)gmail.com>
date: Tue Mar 31 21:23:10 2015 +0200
summary:
Issue #23618: Cleanup internal_connect() in socketmodule.c
On Windows, it looks like using the C type socklen_t for getsockopt() (instead
of int) is fine, it was already used in socket.getsockopt().
files:
Modules/socketmodule.c | 4 +---
1 files changed, 1 insertions(+), 3 deletions(-)
diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c
--- a/Modules/socketmodule.c
+++ b/Modules/socketmodule.c
@@ -2485,7 +2485,7 @@
else if (timeout == 0) {
socklen_t res_size = sizeof res;
if (!getsockopt(s->sock_fd, SOL_SOCKET, SO_ERROR,
- (char*)&res, &res_size)) {
+ (void *)&res, &res_size)) {
if (res == EISCONN)
res = 0;
err = res;
@@ -2533,8 +2533,6 @@
return NULL;
if (res != 0) {
#ifdef MS_WINDOWS
- /* getsockopt also clears WSAGetLastError,
- so reset it back. */
WSASetLastError(res);
#else
errno = res;
--
Repository URL: https://hg.python.org/cpython
https://hg.python.org/cpython/rev/b75160d24b7b
changeset: 95333:b75160d24b7b
user: Raymond Hettinger <python(a)rcn.com>
date: Tue Mar 31 08:12:23 2015 -0700
summary:
Issue 23793: Add deque support for __add__(), __mul__(), and __imul__().
files:
Doc/library/collections.rst | 3 +
Lib/test/test_deque.py | 77 +++++++++++++
Misc/NEWS | 1 +
Modules/_collectionsmodule.c | 133 +++++++++++++++++++++-
4 files changed, 204 insertions(+), 10 deletions(-)
diff --git a/Doc/library/collections.rst b/Doc/library/collections.rst
--- a/Doc/library/collections.rst
+++ b/Doc/library/collections.rst
@@ -526,6 +526,9 @@
access is O(1) at both ends but slows to O(n) in the middle. For fast random
access, use lists instead.
+Starting in version 3.5, deques support ``__add__()``, ``__mul__()``,
+and ``__imul__()``.
+
Example:
.. doctest::
diff --git a/Lib/test/test_deque.py b/Lib/test/test_deque.py
--- a/Lib/test/test_deque.py
+++ b/Lib/test/test_deque.py
@@ -192,6 +192,26 @@
d.extend(d)
self.assertEqual(list(d), list('abcdabcd'))
+ def test_add(self):
+ d = deque()
+ e = deque('abc')
+ f = deque('def')
+ self.assertEqual(d + d, deque())
+ self.assertEqual(e + f, deque('abcdef'))
+ self.assertEqual(e + e, deque('abcabc'))
+ self.assertEqual(e + d, deque('abc'))
+ self.assertEqual(d + e, deque('abc'))
+ self.assertIsNot(d + d, deque())
+ self.assertIsNot(e + d, deque('abc'))
+ self.assertIsNot(d + e, deque('abc'))
+
+ g = deque('abcdef', maxlen=4)
+ h = deque('gh')
+ self.assertEqual(g + h, deque('efgh'))
+
+ with self.assertRaises(TypeError):
+ deque('abc') + 'def'
+
def test_iadd(self):
d = deque('a')
d += 'bcd'
@@ -279,6 +299,63 @@
s.insert(i, 'Z')
self.assertEqual(list(d), s)
+ def test_imul(self):
+ for n in (-10, -1, 0, 1, 2, 10, 1000):
+ d = deque()
+ d *= n
+ self.assertEqual(d, deque())
+ self.assertIsNone(d.maxlen)
+
+ for n in (-10, -1, 0, 1, 2, 10, 1000):
+ d = deque('a')
+ d *= n
+ self.assertEqual(d, deque('a' * n))
+ self.assertIsNone(d.maxlen)
+
+ for n in (-10, -1, 0, 1, 2, 10, 499, 500, 501, 1000):
+ d = deque('a', 500)
+ d *= n
+ self.assertEqual(d, deque('a' * min(n, 500)))
+ self.assertEqual(d.maxlen, 500)
+
+ for n in (-10, -1, 0, 1, 2, 10, 1000):
+ d = deque('abcdef')
+ d *= n
+ self.assertEqual(d, deque('abcdef' * n))
+ self.assertIsNone(d.maxlen)
+
+ for n in (-10, -1, 0, 1, 2, 10, 499, 500, 501, 1000):
+ d = deque('abcdef', 500)
+ d *= n
+ self.assertEqual(d, deque(('abcdef' * n)[-500:]))
+ self.assertEqual(d.maxlen, 500)
+
+ def test_mul(self):
+ d = deque('abc')
+ self.assertEqual(d * -5, deque())
+ self.assertEqual(d * 0, deque())
+ self.assertEqual(d * 1, deque('abc'))
+ self.assertEqual(d * 2, deque('abcabc'))
+ self.assertEqual(d * 3, deque('abcabcabc'))
+ self.assertIsNot(d * 1, d)
+
+ self.assertEqual(deque() * 0, deque())
+ self.assertEqual(deque() * 1, deque())
+ self.assertEqual(deque() * 5, deque())
+
+ self.assertEqual(-5 * d, deque())
+ self.assertEqual(0 * d, deque())
+ self.assertEqual(1 * d, deque('abc'))
+ self.assertEqual(2 * d, deque('abcabc'))
+ self.assertEqual(3 * d, deque('abcabcabc'))
+
+ d = deque('abc', maxlen=5)
+ self.assertEqual(d * -5, deque())
+ self.assertEqual(d * 0, deque())
+ self.assertEqual(d * 1, deque('abc'))
+ self.assertEqual(d * 2, deque('bcabc'))
+ self.assertEqual(d * 30, deque('bcabc'))
+
def test_setitem(self):
n = 200
d = deque(range(n))
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -152,6 +152,7 @@
- Issue #23704: collections.deque() objects now support methods for index(),
insert(), and copy(). This allows deques to be registered as a
MutableSequence and it improves their substitutablity for lists.
+ Deques now also support __add__, __mul__, and __imul__().
- Issue #23715: :func:`signal.sigwaitinfo` and :func:`signal.sigtimedwait` are
now retried when interrupted by a signal not in the *sigset* parameter, if
diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c
--- a/Modules/_collectionsmodule.c
+++ b/Modules/_collectionsmodule.c
@@ -110,6 +110,12 @@
#define CHECK_NOT_END(link)
#endif
+/* To prevent len from overflowing PY_SSIZE_T_MAX, we refuse to
+ allocate new blocks if the current len is nearing overflow.
+*/
+
+#define MAX_DEQUE_LEN (PY_SSIZE_T_MAX - 3*BLOCKLEN)
+
/* A simple freelisting scheme is used to minimize calls to the memory
allocator. It accommodates common use cases where new blocks are being
added at about the same rate as old blocks are being freed.
@@ -122,9 +128,7 @@
static block *
newblock(Py_ssize_t len) {
block *b;
- /* To prevent len from overflowing PY_SSIZE_T_MAX, we refuse to
- * allocate new blocks if the current len is nearing overflow. */
- if (len >= PY_SSIZE_T_MAX - 2*BLOCKLEN) {
+ if (len >= MAX_DEQUE_LEN) {
PyErr_SetString(PyExc_OverflowError,
"cannot add more blocks to the deque");
return NULL;
@@ -498,6 +502,115 @@
return (PyObject *)deque;
}
+static PyObject *deque_copy(PyObject *deque);
+
+static PyObject *
+deque_concat(dequeobject *deque, PyObject *other)
+{
+ PyObject *new_deque;
+ int rv;
+
+ rv = PyObject_IsInstance(other, (PyObject *)&deque_type);
+ if (rv <= 0) {
+ if (rv == 0) {
+ PyErr_Format(PyExc_TypeError,
+ "can only concatenate deque (not \"%.200s\") to deque",
+ other->ob_type->tp_name);
+ }
+ return NULL;
+ }
+
+ new_deque = deque_copy((PyObject *)deque);
+ if (new_deque == NULL)
+ return NULL;
+ return deque_inplace_concat((dequeobject *)new_deque, other);
+}
+
+static void deque_clear(dequeobject *deque);
+
+static PyObject *
+deque_repeat(dequeobject *deque, Py_ssize_t n)
+{
+ dequeobject *new_deque;
+ PyObject *result;
+
+ /* XXX add a special case for when maxlen is defined */
+ if (n < 0)
+ n = 0;
+ else if (n > 0 && Py_SIZE(deque) > MAX_DEQUE_LEN / n)
+ return PyErr_NoMemory();
+
+ new_deque = (dequeobject *)deque_new(&deque_type, (PyObject *)NULL, (PyObject *)NULL);
+ new_deque->maxlen = deque->maxlen;
+
+ for ( ; n ; n--) {
+ result = deque_extend(new_deque, (PyObject *)deque);
+ if (result == NULL) {
+ Py_DECREF(new_deque);
+ return NULL;
+ }
+ Py_DECREF(result);
+ }
+ return (PyObject *)new_deque;
+}
+
+static PyObject *
+deque_inplace_repeat(dequeobject *deque, Py_ssize_t n)
+{
+ Py_ssize_t i, size;
+ PyObject *seq;
+ PyObject *rv;
+
+ size = Py_SIZE(deque);
+ if (size == 0 || n == 1) {
+ Py_INCREF(deque);
+ return (PyObject *)deque;
+ }
+
+ if (n <= 0) {
+ deque_clear(deque);
+ Py_INCREF(deque);
+ return (PyObject *)deque;
+ }
+
+ if (size > MAX_DEQUE_LEN / n) {
+ return PyErr_NoMemory();
+ }
+
+ if (size == 1) {
+ /* common case, repeating a single element */
+ PyObject *item = deque->leftblock->data[deque->leftindex];
+
+ if (deque->maxlen != -1 && n > deque->maxlen)
+ n = deque->maxlen;
+
+ for (i = 0 ; i < n-1 ; i++) {
+ rv = deque_append(deque, item);
+ if (rv == NULL)
+ return NULL;
+ Py_DECREF(rv);
+ }
+ Py_INCREF(deque);
+ return (PyObject *)deque;
+ }
+
+ seq = PySequence_List((PyObject *)deque);
+ if (seq == NULL)
+ return seq;
+
+ for (i = 0 ; i < n-1 ; i++) {
+ rv = deque_extend(deque, seq);
+ if (rv == NULL) {
+ Py_DECREF(seq);
+ return NULL;
+ }
+ Py_DECREF(rv);
+ }
+ Py_INCREF(deque);
+ Py_DECREF(seq);
+ return (PyObject *)deque;
+}
+
/* The rotate() method is part of the public API and is used internally
as a primitive for other methods.
@@ -1283,6 +1396,9 @@
return PyLong_FromSsize_t(deque->maxlen);
}
+
+/* deque object ********************************************************/
+
static PyGetSetDef deque_getset[] = {
{"maxlen", (getter)deque_get_maxlen, (setter)NULL,
"maximum size of a deque or None if unbounded"},
@@ -1291,15 +1407,15 @@
static PySequenceMethods deque_as_sequence = {
(lenfunc)deque_len, /* sq_length */
- 0, /* sq_concat */
- 0, /* sq_repeat */
+ (binaryfunc)deque_concat, /* sq_concat */
+ (ssizeargfunc)deque_repeat, /* sq_repeat */
(ssizeargfunc)deque_item, /* sq_item */
0, /* sq_slice */
(ssizeobjargproc)deque_ass_item, /* sq_ass_item */
0, /* sq_ass_slice */
(objobjproc)deque_contains, /* sq_contains */
(binaryfunc)deque_inplace_concat, /* sq_inplace_concat */
- 0, /* sq_inplace_repeat */
+ (ssizeargfunc)deque_inplace_repeat, /* sq_inplace_repeat */
};
static PyNumberMethods deque_as_number = {
@@ -1316,9 +1432,6 @@
0, /* nb_invert */
};
-
-/* deque object ********************************************************/
-
static PyObject *deque_iter(dequeobject *deque);
static PyObject *deque_reviter(dequeobject *deque);
PyDoc_STRVAR(reversed_doc,
@@ -1367,7 +1480,7 @@
PyDoc_STRVAR(deque_doc,
"deque([iterable[, maxlen]]) --> deque object\n\
\n\
-Build an ordered collection with optimized access from its endpoints.");
+A list-like sequence optimized for data accesses near its endpoints.");
static PyTypeObject deque_type = {
PyVarObject_HEAD_INIT(NULL, 0)
--
Repository URL: https://hg.python.org/cpython
https://hg.python.org/cpython/rev/c59d81b802f8
changeset: 95332:c59d81b802f8
user: Victor Stinner <victor.stinner(a)gmail.com>
date: Tue Mar 31 16:35:35 2015 +0200
summary:
Issue #23618: Refactor internal_connect()
On Windows, internal_connect() now reuses internal_connect_select() and always
calls getsockopt().
files:
Modules/socketmodule.c | 117 ++++++++--------------------
1 files changed, 34 insertions(+), 83 deletions(-)
diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c
--- a/Modules/socketmodule.c
+++ b/Modules/socketmodule.c
@@ -2299,7 +2299,8 @@
if (PyArg_ParseTuple(args, "iii:setsockopt",
&level, &optname, &flag)) {
- res = setsockopt(s->sock_fd, level, optname, &flag, sizeof flag);
+ res = setsockopt(s->sock_fd, level, optname,
+ (char*)&flag, sizeof flag);
}
else {
PyErr_Clear();
@@ -2450,7 +2451,17 @@
internal_connect(PySocketSockObject *s, struct sockaddr *addr, int addrlen,
int *timeoutp)
{
- int err, res, timeout;
+#ifdef MS_WINDOWS
+# define GET_ERROR WSAGetLastError()
+# define IN_PROGRESS_ERR WSAEWOULDBLOCK
+# define TIMEOUT_ERR WSAEWOULDBLOCK
+#else
+# define GET_ERROR errno
+# define IN_PROGRESS_ERR EINPROGRESS
+# define TIMEOUT_ERR EWOULDBLOCK
+#endif
+
+ int res, err, in_progress, timeout;
timeout = 0;
@@ -2458,105 +2469,45 @@
res = connect(s->sock_fd, addr, addrlen);
Py_END_ALLOW_THREADS
-#ifdef MS_WINDOWS
-
if (res < 0)
- err = WSAGetLastError();
+ err = GET_ERROR;
else
err = res;
-
- if (s->sock_timeout > 0 && err == WSAEWOULDBLOCK && IS_SELECTABLE(s)) {
- /* This is a mess. Best solution: trust select */
- fd_set fds;
- fd_set fds_exc;
- struct timeval tv;
- int conv;
-
- _PyTime_AsTimeval_noraise(s->sock_timeout, &tv, _PyTime_ROUND_CEILING);
-
- Py_BEGIN_ALLOW_THREADS
- FD_ZERO(&fds);
- FD_SET(s->sock_fd, &fds);
- FD_ZERO(&fds_exc);
- FD_SET(s->sock_fd, &fds_exc);
- res = select(Py_SAFE_DOWNCAST(s->sock_fd+1, SOCKET_T, int),
- NULL, &fds, &fds_exc, &tv);
- Py_END_ALLOW_THREADS
-
- if (res == 0) {
- err = WSAEWOULDBLOCK;
- timeout = 1;
+ in_progress = (err == IN_PROGRESS_ERR);
+
+ if (s->sock_timeout > 0 && in_progress && IS_SELECTABLE(s)) {
+ timeout = internal_connect_select(s);
+
+ if (timeout == 1) {
+ /* timed out */
+ err = TIMEOUT_ERR;
}
- else if (res > 0) {
- if (FD_ISSET(s->sock_fd, &fds)) {
- /* The socket is in the writable set - this
- means connected */
- err = 0;
- }
- else {
- /* As per MS docs, we need to call getsockopt()
- to get the underlying error */
- int res_size;
-
- /* It must be in the exception set */
- assert(FD_ISSET(s->sock_fd, &fds_exc));
-
- res_size = sizeof res;
- if (!getsockopt(s->sock_fd, SOL_SOCKET, SO_ERROR,
- (char *)&res, &res_size)) {
- err = res;
- }
- else {
- err = WSAGetLastError();
- }
- }
- }
- else {
- /* select() failed */
- err = WSAGetLastError();
- }
- }
-
-#else
- if (res < 0)
- err = errno;
- else
- err = 0;
-
- if (s->sock_timeout > 0 && err == EINPROGRESS && IS_SELECTABLE(s)) {
-
- timeout = internal_connect_select(s);
-
- if (timeout == 0) {
- /* Bug #1019808: in case of an EINPROGRESS,
- use getsockopt(SO_ERROR) to get the real
- error. */
+ else if (timeout == 0) {
socklen_t res_size = sizeof res;
- if (!getsockopt(s->sock_fd, SOL_SOCKET,
- SO_ERROR, &res, &res_size)) {
+ if (!getsockopt(s->sock_fd, SOL_SOCKET, SO_ERROR,
+ (char*)&res, &res_size)) {
if (res == EISCONN)
res = 0;
err = res;
}
else {
/* getsockopt() failed */
- err = errno;
+ err = GET_ERROR;
}
}
- else if (timeout == -1) {
- /* select failed */
- err = errno;
+ else {
+ /* select() failed */
+ err = GET_ERROR;
}
- else {
- err = EWOULDBLOCK; /* timed out */
- }
- }
-
-#endif
+ }
*timeoutp = timeout;
assert(err >= 0);
return err;
+
+#undef GET_ERROR
+#undef IN_PROGRESS_ERR
+#undef TIMEOUT_ERR
}
/* s.connect(sockaddr) method */
--
Repository URL: https://hg.python.org/cpython
https://hg.python.org/cpython/rev/dbc92a254173
changeset: 95330:dbc92a254173
user: Victor Stinner <victor.stinner(a)gmail.com>
date: Tue Mar 31 16:31:19 2015 +0200
summary:
Issue #22117: Fix integer overflow check in socket_parse_timeout() on Windows
files:
Modules/socketmodule.c | 9 ++++++---
1 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c
--- a/Modules/socketmodule.c
+++ b/Modules/socketmodule.c
@@ -2197,6 +2197,9 @@
#ifdef MS_WINDOWS
struct timeval tv;
#endif
+#ifndef HAVE_POLL
+ _PyTime_t ms;
+#endif
int overflow = 0;
if (timeout_obj == Py_None) {
@@ -2214,11 +2217,11 @@
}
#ifdef MS_WINDOWS
- overflow = (_PyTime_AsTimeval(timeout, &tv, _PyTime_ROUND_CEILING) < 0);
+ overflow |= (_PyTime_AsTimeval(*timeout, &tv, _PyTime_ROUND_CEILING) < 0);
#endif
#ifndef HAVE_POLL
- timeout = _PyTime_AsMilliseconds(timeout, _PyTime_ROUND_CEILING);
- overflow = (timeout > INT_MAX);
+ ms = _PyTime_AsMilliseconds(*timeout, _PyTime_ROUND_CEILING);
+ overflow |= (ms > INT_MAX);
#endif
if (overflow) {
PyErr_SetString(PyExc_OverflowError,
--
Repository URL: https://hg.python.org/cpython
https://hg.python.org/cpython/rev/daf3d2a717e5
changeset: 95331:daf3d2a717e5
user: Victor Stinner <victor.stinner(a)gmail.com>
date: Tue Mar 31 16:08:22 2015 +0200
summary:
Issue #23618: Refactor internal_connect()
The function now returns the error code instead of using the global errno
(POSIX) or WSAGetLastError() (Windows).
internal_connect() now returns errno if getsockopt() fails.
files:
Modules/socketmodule.c | 100 +++++++++++++++++-----------
1 files changed, 61 insertions(+), 39 deletions(-)
diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c
--- a/Modules/socketmodule.c
+++ b/Modules/socketmodule.c
@@ -2450,7 +2450,7 @@
internal_connect(PySocketSockObject *s, struct sockaddr *addr, int addrlen,
int *timeoutp)
{
- int res, timeout;
+ int err, res, timeout;
timeout = 0;
@@ -2460,9 +2460,12 @@
#ifdef MS_WINDOWS
- if (s->sock_timeout > 0
- && res < 0 && WSAGetLastError() == WSAEWOULDBLOCK
- && IS_SELECTABLE(s)) {
+ if (res < 0)
+ err = WSAGetLastError();
+ else
+ err = res;
+
+ if (s->sock_timeout > 0 && err == WSAEWOULDBLOCK && IS_SELECTABLE(s)) {
/* This is a mess. Best solution: trust select */
fd_set fds;
fd_set fds_exc;
@@ -2481,38 +2484,46 @@
Py_END_ALLOW_THREADS
if (res == 0) {
- res = WSAEWOULDBLOCK;
+ err = WSAEWOULDBLOCK;
timeout = 1;
- } else if (res > 0) {
- if (FD_ISSET(s->sock_fd, &fds))
+ }
+ else if (res > 0) {
+ if (FD_ISSET(s->sock_fd, &fds)) {
/* The socket is in the writable set - this
means connected */
- res = 0;
+ err = 0;
+ }
else {
/* As per MS docs, we need to call getsockopt()
to get the underlying error */
- int res_size = sizeof res;
+ int res_size;
+
/* It must be in the exception set */
assert(FD_ISSET(s->sock_fd, &fds_exc));
- if (0 == getsockopt(s->sock_fd, SOL_SOCKET, SO_ERROR,
- (char *)&res, &res_size))
- /* getsockopt also clears WSAGetLastError,
- so reset it back. */
- WSASetLastError(res);
- else
- res = WSAGetLastError();
+
+ res_size = sizeof res;
+ if (!getsockopt(s->sock_fd, SOL_SOCKET, SO_ERROR,
+ (char *)&res, &res_size)) {
+ err = res;
+ }
+ else {
+ err = WSAGetLastError();
+ }
}
}
- /* else if (res < 0) an error occurred */
- }
-
+ else {
+ /* select() failed */
+ err = WSAGetLastError();
+ }
+ }
+
+#else
if (res < 0)
- res = WSAGetLastError();
-
-#else
-
- if (s->sock_timeout > 0
- && res < 0 && errno == EINPROGRESS && IS_SELECTABLE(s)) {
+ err = errno;
+ else
+ err = 0;
+
+ if (s->sock_timeout > 0 && err == EINPROGRESS && IS_SELECTABLE(s)) {
timeout = internal_connect_select(s);
@@ -2521,27 +2532,31 @@
use getsockopt(SO_ERROR) to get the real
error. */
socklen_t res_size = sizeof res;
- (void)getsockopt(s->sock_fd, SOL_SOCKET,
- SO_ERROR, &res, &res_size);
- if (res == EISCONN)
- res = 0;
- errno = res;
+ if (!getsockopt(s->sock_fd, SOL_SOCKET,
+ SO_ERROR, &res, &res_size)) {
+ if (res == EISCONN)
+ res = 0;
+ err = res;
+ }
+ else {
+ /* getsockopt() failed */
+ err = errno;
+ }
}
else if (timeout == -1) {
- res = errno; /* had error */
+ /* select failed */
+ err = errno;
}
- else
- res = EWOULDBLOCK; /* timed out */
- }
-
- if (res < 0)
- res = errno;
+ else {
+ err = EWOULDBLOCK; /* timed out */
+ }
+ }
#endif
*timeoutp = timeout;
- assert(res >= 0);
- return res;
+ assert(err >= 0);
+ return err;
}
/* s.connect(sockaddr) method */
@@ -2566,6 +2581,13 @@
if (res < 0)
return NULL;
if (res != 0) {
+#ifdef MS_WINDOWS
+ /* getsockopt also clears WSAGetLastError,
+ so reset it back. */
+ WSASetLastError(res);
+#else
+ errno = res;
+#endif
return s->errorhandler();
}
Py_INCREF(Py_None);
--
Repository URL: https://hg.python.org/cpython
https://hg.python.org/cpython/rev/f78b9f700d45
changeset: 95329:f78b9f700d45
user: Serhiy Storchaka <storchaka(a)gmail.com>
date: Tue Mar 31 16:56:49 2015 +0300
summary:
Issue #23611: Fixed enums pickling tests. Now all picklings work with all
protocols.
files:
Lib/test/test_enum.py | 22 +++++++---------------
1 files changed, 7 insertions(+), 15 deletions(-)
diff --git a/Lib/test/test_enum.py b/Lib/test/test_enum.py
--- a/Lib/test/test_enum.py
+++ b/Lib/test/test_enum.py
@@ -66,18 +66,14 @@
except Exception:
pass
-def test_pickle_dump_load(assertion, source, target=None,
- *, protocol=(0, HIGHEST_PROTOCOL)):
- start, stop = protocol
+def test_pickle_dump_load(assertion, source, target=None):
if target is None:
target = source
- for protocol in range(start, stop+1):
+ for protocol in range(HIGHEST_PROTOCOL + 1):
assertion(loads(dumps(source, protocol=protocol)), target)
-def test_pickle_exception(assertion, exception, obj,
- *, protocol=(0, HIGHEST_PROTOCOL)):
- start, stop = protocol
- for protocol in range(start, stop+1):
+def test_pickle_exception(assertion, exception, obj):
+ for protocol in range(HIGHEST_PROTOCOL + 1):
with assertion(exception):
dumps(obj, protocol=protocol)
@@ -575,11 +571,7 @@
self.__class__.NestedEnum = NestedEnum
self.NestedEnum.__qualname__ = '%s.NestedEnum' % self.__class__.__name__
- test_pickle_exception(
- self.assertRaises, PicklingError, self.NestedEnum.twigs,
- protocol=(0, 3))
- test_pickle_dump_load(self.assertIs, self.NestedEnum.twigs,
- protocol=(4, HIGHEST_PROTOCOL))
+ test_pickle_dump_load(self.assertIs, self.NestedEnum.twigs)
def test_pickle_by_name(self):
class ReplaceGlobalInt(IntEnum):
@@ -1096,9 +1088,9 @@
globals()['NEI'] = NEI
NI5 = NamedInt('test', 5)
self.assertEqual(NI5, 5)
- test_pickle_dump_load(self.assertEqual, NI5, 5, protocol=(4, 4))
+ test_pickle_dump_load(self.assertEqual, NI5, 5)
self.assertEqual(NEI.y.value, 2)
- test_pickle_dump_load(self.assertIs, NEI.y, protocol=(4, 4))
+ test_pickle_dump_load(self.assertIs, NEI.y)
test_pickle_dump_load(self.assertIs, NEI)
def test_subclasses_with_reduce(self):
--
Repository URL: https://hg.python.org/cpython
https://hg.python.org/cpython/rev/5c5eb374e296
changeset: 95327:5c5eb374e296
branch: 3.4
parent: 95316:8d86dfe53b97
user: Serhiy Storchaka <storchaka(a)gmail.com>
date: Tue Mar 31 16:49:26 2015 +0300
summary:
Issue #18473: Fixed pickle compatibility tests for optional modules.
Added WindowsError to compatibility mappings.
files:
Lib/_compat_pickle.py | 7 +++++
Lib/test/test_pickle.py | 35 ++++++++++++++++++++--------
2 files changed, 32 insertions(+), 10 deletions(-)
diff --git a/Lib/_compat_pickle.py b/Lib/_compat_pickle.py
--- a/Lib/_compat_pickle.py
+++ b/Lib/_compat_pickle.py
@@ -141,6 +141,13 @@
"ZeroDivisionError",
)
+try:
+ WindowsError
+except NameError:
+ pass
+else:
+ PYTHON2_EXCEPTIONS += ("WindowsError",)
+
for excname in PYTHON2_EXCEPTIONS:
NAME_MAPPING[("exceptions", excname)] = ("builtins", excname)
diff --git a/Lib/test/test_pickle.py b/Lib/test/test_pickle.py
--- a/Lib/test/test_pickle.py
+++ b/Lib/test/test_pickle.py
@@ -240,7 +240,16 @@
try:
return sys.modules[module]
except KeyError:
- __import__(module)
+ try:
+ __import__(module)
+ except AttributeError as exc:
+ if support.verbose:
+ print("Can't import module %r: %s" % (module, exc))
+ raise ImportError
+ except ImportError as exc:
+ if support.verbose:
+ print(exc)
+ raise
return sys.modules[module]
def getattribute(module, name):
@@ -264,18 +273,16 @@
for module in modules:
try:
getmodule(module)
- except ImportError as exc:
- if support.verbose:
- print(exc)
+ except ImportError:
+ pass
def test_import_mapping(self):
for module3, module2 in REVERSE_IMPORT_MAPPING.items():
with self.subTest((module3, module2)):
try:
getmodule(module3)
- except ImportError as exc:
- if support.verbose:
- print(exc)
+ except ImportError:
+ pass
if module3[:1] != '_':
self.assertIn(module2, IMPORT_MAPPING)
self.assertEqual(IMPORT_MAPPING[module2], module3)
@@ -283,14 +290,19 @@
def test_name_mapping(self):
for (module3, name3), (module2, name2) in REVERSE_NAME_MAPPING.items():
with self.subTest(((module3, name3), (module2, name2))):
- attr = getattribute(module3, name3)
if (module2, name2) == ('exceptions', 'OSError'):
+ attr = getattribute(module3, name3)
self.assertTrue(issubclass(attr, OSError))
else:
module, name = mapping(module2, name2)
if module3[:1] != '_':
self.assertEqual((module, name), (module3, name3))
- self.assertEqual(getattribute(module, name), attr)
+ try:
+ attr = getattribute(module3, name3)
+ except ImportError:
+ pass
+ else:
+ self.assertEqual(getattribute(module, name), attr)
def test_reverse_import_mapping(self):
for module2, module3 in IMPORT_MAPPING.items():
@@ -315,7 +327,10 @@
def test_reverse_name_mapping(self):
for (module2, name2), (module3, name3) in NAME_MAPPING.items():
with self.subTest(((module2, name2), (module3, name3))):
- attr = getattribute(module3, name3)
+ try:
+ attr = getattribute(module3, name3)
+ except ImportError:
+ pass
module, name = reverse_mapping(module3, name3)
if (module2, name2, module3, name3) not in ALT_NAME_MAPPING:
self.assertEqual((module, name), (module2, name2))
--
Repository URL: https://hg.python.org/cpython
https://hg.python.org/cpython/rev/29b2b2d8e36f
changeset: 95328:29b2b2d8e36f
parent: 95326:ec6c812fbc1f
parent: 95327:5c5eb374e296
user: Serhiy Storchaka <storchaka(a)gmail.com>
date: Tue Mar 31 16:49:48 2015 +0300
summary:
Issue #18473: Fixed pickle compatibility tests for optional modules.
Added WindowsError to compatibility mappings.
files:
Lib/_compat_pickle.py | 7 +++++
Lib/test/test_pickle.py | 35 ++++++++++++++++++++--------
2 files changed, 32 insertions(+), 10 deletions(-)
diff --git a/Lib/_compat_pickle.py b/Lib/_compat_pickle.py
--- a/Lib/_compat_pickle.py
+++ b/Lib/_compat_pickle.py
@@ -141,6 +141,13 @@
"ZeroDivisionError",
)
+try:
+ WindowsError
+except NameError:
+ pass
+else:
+ PYTHON2_EXCEPTIONS += ("WindowsError",)
+
for excname in PYTHON2_EXCEPTIONS:
NAME_MAPPING[("exceptions", excname)] = ("builtins", excname)
diff --git a/Lib/test/test_pickle.py b/Lib/test/test_pickle.py
--- a/Lib/test/test_pickle.py
+++ b/Lib/test/test_pickle.py
@@ -240,7 +240,16 @@
try:
return sys.modules[module]
except KeyError:
- __import__(module)
+ try:
+ __import__(module)
+ except AttributeError as exc:
+ if support.verbose:
+ print("Can't import module %r: %s" % (module, exc))
+ raise ImportError
+ except ImportError as exc:
+ if support.verbose:
+ print(exc)
+ raise
return sys.modules[module]
def getattribute(module, name):
@@ -264,18 +273,16 @@
for module in modules:
try:
getmodule(module)
- except ImportError as exc:
- if support.verbose:
- print(exc)
+ except ImportError:
+ pass
def test_import_mapping(self):
for module3, module2 in REVERSE_IMPORT_MAPPING.items():
with self.subTest((module3, module2)):
try:
getmodule(module3)
- except ImportError as exc:
- if support.verbose:
- print(exc)
+ except ImportError:
+ pass
if module3[:1] != '_':
self.assertIn(module2, IMPORT_MAPPING)
self.assertEqual(IMPORT_MAPPING[module2], module3)
@@ -283,14 +290,19 @@
def test_name_mapping(self):
for (module3, name3), (module2, name2) in REVERSE_NAME_MAPPING.items():
with self.subTest(((module3, name3), (module2, name2))):
- attr = getattribute(module3, name3)
if (module2, name2) == ('exceptions', 'OSError'):
+ attr = getattribute(module3, name3)
self.assertTrue(issubclass(attr, OSError))
else:
module, name = mapping(module2, name2)
if module3[:1] != '_':
self.assertEqual((module, name), (module3, name3))
- self.assertEqual(getattribute(module, name), attr)
+ try:
+ attr = getattribute(module3, name3)
+ except ImportError:
+ pass
+ else:
+ self.assertEqual(getattribute(module, name), attr)
def test_reverse_import_mapping(self):
for module2, module3 in IMPORT_MAPPING.items():
@@ -315,7 +327,10 @@
def test_reverse_name_mapping(self):
for (module2, name2), (module3, name3) in NAME_MAPPING.items():
with self.subTest(((module2, name2), (module3, name3))):
- attr = getattribute(module3, name3)
+ try:
+ attr = getattribute(module3, name3)
+ except ImportError:
+ pass
module, name = reverse_mapping(module3, name3)
if (module2, name2, module3, name3) not in ALT_NAME_MAPPING:
self.assertEqual((module, name), (module2, name2))
--
Repository URL: https://hg.python.org/cpython