Fixes in struct and socket from merge reviews.

- Following Guido's comments, renamed

  * pack_to -> pack_into
  * recv_buf -> recv_into
  * recvfrom_buf -> recvfrom_into

- Made fixes to _struct.c according to Neal Norwitz comments on the checkins
  list.

- Converted some ints into the appropriate -- I hope -- ssize_t and size_t.
This commit is contained in:
Martin Blais 2006-06-04 13:49:49 +00:00
parent 63f0db682e
commit af2ae72cb2
6 changed files with 75 additions and 74 deletions

View File

@ -141,7 +141,7 @@ class _socketobject(object):
__doc__ = _realsocket.__doc__ __doc__ = _realsocket.__doc__
__slots__ = ["_sock", __slots__ = ["_sock",
"recv", "recv_buf", "recvfrom_buf", "recv", "recv_into", "recvfrom_into",
"send", "sendto", "recvfrom", "send", "sendto", "recvfrom",
"__weakref__"] "__weakref__"]
@ -151,10 +151,10 @@ class _socketobject(object):
self._sock = _sock self._sock = _sock
self.send = self._sock.send self.send = self._sock.send
self.recv = self._sock.recv self.recv = self._sock.recv
self.recv_buf = self._sock.recv_buf self.recv_into = self._sock.recv_into
self.sendto = self._sock.sendto self.sendto = self._sock.sendto
self.recvfrom = self._sock.recvfrom self.recvfrom = self._sock.recvfrom
self.recvfrom_buf = self._sock.recvfrom_buf self.recvfrom_into = self._sock.recvfrom_into
def close(self): def close(self):
self._sock = _closedsocket() self._sock = _closedsocket()

View File

@ -62,7 +62,7 @@ def pack(fmt, *args):
o = _compile(fmt) o = _compile(fmt)
return o.pack(*args) return o.pack(*args)
def pack_to(fmt, buf, offset, *args): def pack_into(fmt, buf, offset, *args):
""" """
Pack the values v2, v2, ... according to fmt, write Pack the values v2, v2, ... according to fmt, write
the packed bytes into the writable buffer buf starting at offset. the packed bytes into the writable buffer buf starting at offset.
@ -72,7 +72,7 @@ def pack_to(fmt, buf, offset, *args):
o = _cache[fmt] o = _cache[fmt]
except KeyError: except KeyError:
o = _compile(fmt) o = _compile(fmt)
return o.pack_to(buf, offset, *args) return o.pack_into(buf, offset, *args)
def unpack(fmt, s): def unpack(fmt, s):
""" """

View File

@ -860,25 +860,25 @@ class BufferIOTest(SocketConnectedTest):
def __init__(self, methodName='runTest'): def __init__(self, methodName='runTest'):
SocketConnectedTest.__init__(self, methodName=methodName) SocketConnectedTest.__init__(self, methodName=methodName)
def testRecvBuf(self): def testRecvInto(self):
buf = array.array('c', ' '*1024) buf = array.array('c', ' '*1024)
nbytes = self.cli_conn.recv_buf(buf) nbytes = self.cli_conn.recv_into(buf)
self.assertEqual(nbytes, len(MSG)) self.assertEqual(nbytes, len(MSG))
msg = buf.tostring()[:len(MSG)] msg = buf.tostring()[:len(MSG)]
self.assertEqual(msg, MSG) self.assertEqual(msg, MSG)
def _testRecvBuf(self): def _testRecvInto(self):
buf = buffer(MSG) buf = buffer(MSG)
self.serv_conn.send(buf) self.serv_conn.send(buf)
def testRecvFromBuf(self): def testRecvFromInto(self):
buf = array.array('c', ' '*1024) buf = array.array('c', ' '*1024)
nbytes, addr = self.cli_conn.recvfrom_buf(buf) nbytes, addr = self.cli_conn.recvfrom_into(buf)
self.assertEqual(nbytes, len(MSG)) self.assertEqual(nbytes, len(MSG))
msg = buf.tostring()[:len(MSG)] msg = buf.tostring()[:len(MSG)]
self.assertEqual(msg, MSG) self.assertEqual(msg, MSG)
def _testRecvFromBuf(self): def _testRecvFromInto(self):
buf = buffer(MSG) buf = buffer(MSG)
self.serv_conn.send(buf) self.serv_conn.send(buf)

View File

@ -529,50 +529,50 @@ def test_unpack_from():
for i in xrange(6, len(test_string) + 1): for i in xrange(6, len(test_string) + 1):
simple_err(struct.unpack_from, fmt, data, i) simple_err(struct.unpack_from, fmt, data, i)
def test_pack_to(): def test_pack_into():
test_string = 'Reykjavik rocks, eow!' test_string = 'Reykjavik rocks, eow!'
writable_buf = array.array('c', ' '*100) writable_buf = array.array('c', ' '*100)
fmt = '21s' fmt = '21s'
s = struct.Struct(fmt) s = struct.Struct(fmt)
# Test without offset # Test without offset
s.pack_to(writable_buf, 0, test_string) s.pack_into(writable_buf, 0, test_string)
from_buf = writable_buf.tostring()[:len(test_string)] from_buf = writable_buf.tostring()[:len(test_string)]
assert from_buf == test_string assert from_buf == test_string
# Test with offset. # Test with offset.
s.pack_to(writable_buf, 10, test_string) s.pack_into(writable_buf, 10, test_string)
from_buf = writable_buf.tostring()[:len(test_string)+10] from_buf = writable_buf.tostring()[:len(test_string)+10]
assert from_buf == (test_string[:10] + test_string) assert from_buf == (test_string[:10] + test_string)
# Go beyond boundaries. # Go beyond boundaries.
small_buf = array.array('c', ' '*10) small_buf = array.array('c', ' '*10)
assertRaises(struct.error, s.pack_to, small_buf, 0, test_string) assertRaises(struct.error, s.pack_into, small_buf, 0, test_string)
assertRaises(struct.error, s.pack_to, small_buf, 2, test_string) assertRaises(struct.error, s.pack_into, small_buf, 2, test_string)
def test_pack_to_fn(): def test_pack_into_fn():
test_string = 'Reykjavik rocks, eow!' test_string = 'Reykjavik rocks, eow!'
writable_buf = array.array('c', ' '*100) writable_buf = array.array('c', ' '*100)
fmt = '21s' fmt = '21s'
pack_to = lambda *args: struct.pack_to(fmt, *args) pack_into = lambda *args: struct.pack_into(fmt, *args)
# Test without offset # Test without offset
pack_to(writable_buf, 0, test_string) pack_into(writable_buf, 0, test_string)
from_buf = writable_buf.tostring()[:len(test_string)] from_buf = writable_buf.tostring()[:len(test_string)]
assert from_buf == test_string assert from_buf == test_string
# Test with offset. # Test with offset.
pack_to(writable_buf, 10, test_string) pack_into(writable_buf, 10, test_string)
from_buf = writable_buf.tostring()[:len(test_string)+10] from_buf = writable_buf.tostring()[:len(test_string)+10]
assert from_buf == (test_string[:10] + test_string) assert from_buf == (test_string[:10] + test_string)
# Go beyond boundaries. # Go beyond boundaries.
small_buf = array.array('c', ' '*10) small_buf = array.array('c', ' '*10)
assertRaises(struct.error, pack_to, small_buf, 0, test_string) assertRaises(struct.error, pack_into, small_buf, 0, test_string)
assertRaises(struct.error, pack_to, small_buf, 2, test_string) assertRaises(struct.error, pack_into, small_buf, 2, test_string)
# Test methods to pack and unpack from buffers rather than strings. # Test methods to pack and unpack from buffers rather than strings.
test_unpack_from() test_unpack_from()
test_pack_to() test_pack_into()
test_pack_to_fn() test_pack_into_fn()

View File

@ -1572,8 +1572,7 @@ s_pack(PyObject *self, PyObject *args)
soself = (PyStructObject *)self; soself = (PyStructObject *)self;
assert(PyStruct_Check(self)); assert(PyStruct_Check(self));
assert(soself->s_codes != NULL); assert(soself->s_codes != NULL);
if (args == NULL || !PyTuple_Check(args) || if (PyTuple_GET_SIZE(args) != soself->s_len)
PyTuple_GET_SIZE(args) != soself->s_len)
{ {
PyErr_Format(StructError, PyErr_Format(StructError,
"pack requires exactly %zd arguments", soself->s_len); "pack requires exactly %zd arguments", soself->s_len);
@ -1594,16 +1593,16 @@ s_pack(PyObject *self, PyObject *args)
return result; return result;
} }
PyDoc_STRVAR(s_pack_to__doc__, PyDoc_STRVAR(s_pack_into__doc__,
"S.pack_to(buffer, offset, v1, v2, ...)\n\ "S.pack_into(buffer, offset, v1, v2, ...)\n\
\n\ \n\
Pack the values v2, v2, ... according to this Struct's format, write \n\ Pack the values v1, v2, ... according to this Struct's format, write \n\
the packed bytes into the writable buffer buf starting at offset. Note\n\ the packed bytes into the writable buffer buf starting at offset. Note\n\
that the offset is not an optional argument. See struct.__doc__ for \n\ that the offset is not an optional argument. See struct.__doc__ for \n\
more on format strings."); more on format strings.");
static PyObject * static PyObject *
s_pack_to(PyObject *self, PyObject *args) s_pack_into(PyObject *self, PyObject *args)
{ {
PyStructObject *soself; PyStructObject *soself;
char *buffer; char *buffer;
@ -1613,11 +1612,10 @@ s_pack_to(PyObject *self, PyObject *args)
soself = (PyStructObject *)self; soself = (PyStructObject *)self;
assert(PyStruct_Check(self)); assert(PyStruct_Check(self));
assert(soself->s_codes != NULL); assert(soself->s_codes != NULL);
if (args == NULL || !PyTuple_Check(args) || if (PyTuple_GET_SIZE(args) != (soself->s_len + 2))
PyTuple_GET_SIZE(args) != (soself->s_len + 2))
{ {
PyErr_Format(StructError, PyErr_Format(StructError,
"pack_to requires exactly %zd arguments", "pack_into requires exactly %zd arguments",
(soself->s_len + 2)); (soself->s_len + 2));
return NULL; return NULL;
} }
@ -1630,7 +1628,7 @@ s_pack_to(PyObject *self, PyObject *args)
assert( buffer_len >= 0 ); assert( buffer_len >= 0 );
/* Extract the offset from the first argument */ /* Extract the offset from the first argument */
offset = PyInt_AsLong(PyTuple_GET_ITEM(args, 1)); offset = PyInt_AsSsize_t(PyTuple_GET_ITEM(args, 1));
/* Support negative offsets. */ /* Support negative offsets. */
if (offset < 0) if (offset < 0)
@ -1639,7 +1637,7 @@ s_pack_to(PyObject *self, PyObject *args)
/* Check boundaries */ /* Check boundaries */
if (offset < 0 || (buffer_len - offset) < soself->s_size) { if (offset < 0 || (buffer_len - offset) < soself->s_size) {
PyErr_Format(StructError, PyErr_Format(StructError,
"pack_to requires a buffer of at least %zd bytes", "pack_into requires a buffer of at least %zd bytes",
soself->s_size); soself->s_size);
return NULL; return NULL;
} }
@ -1668,10 +1666,10 @@ s_get_size(PyStructObject *self, void *unused)
/* List of functions */ /* List of functions */
static struct PyMethodDef s_methods[] = { static struct PyMethodDef s_methods[] = {
{"pack", (PyCFunction)s_pack, METH_VARARGS, s_pack__doc__}, {"pack", s_pack, METH_VARARGS, s_pack__doc__},
{"pack_to", (PyCFunction)s_pack_to, METH_VARARGS, s_pack_to__doc__}, {"pack_into", s_pack_into, METH_VARARGS, s_pack_into__doc__},
{"unpack", (PyCFunction)s_unpack, METH_O, s_unpack__doc__}, {"unpack", s_unpack, METH_O, s_unpack__doc__},
{"unpack_from", (PyCFunction)s_unpack_from, METH_KEYWORDS, s_unpack_from__doc__}, {"unpack_from", s_unpack_from, METH_KEYWORDS, s_unpack_from__doc__},
{NULL, NULL} /* sentinel */ {NULL, NULL} /* sentinel */
}; };

View File

@ -104,9 +104,9 @@ gettimeout() -- return timeout or None\n\
listen(n) -- start listening for incoming connections\n\ listen(n) -- start listening for incoming connections\n\
makefile([mode, [bufsize]]) -- return a file object for the socket [*]\n\ makefile([mode, [bufsize]]) -- return a file object for the socket [*]\n\
recv(buflen[, flags]) -- receive data\n\ recv(buflen[, flags]) -- receive data\n\
recv_buf(buffer[, nbytes[, flags]]) -- receive data (into a buffer)\n\ recv_into(buffer[, nbytes[, flags]]) -- receive data (into a buffer)\n\
recvfrom(buflen[, flags]) -- receive data and sender\'s address\n\ recvfrom(buflen[, flags]) -- receive data and sender\'s address\n\
recvfrom_buf(buffer[, nbytes, [, flags])\n\ recvfrom_into(buffer[, nbytes, [, flags])\n\
-- receive data and sender\'s address (into a buffer)\n\ -- receive data and sender\'s address (into a buffer)\n\
sendall(data[, flags]) -- send all data\n\ sendall(data[, flags]) -- send all data\n\
send(data[, flags]) -- send data, may not send all of it\n\ send(data[, flags]) -- send data, may not send all of it\n\
@ -2139,17 +2139,18 @@ The mode and buffersize arguments are as for the built-in open() function.");
#endif /* NO_DUP */ #endif /* NO_DUP */
/* /*
* This is the guts of the recv() and recv_buf() methods, which reads into a * This is the guts of the recv() and recv_into() methods, which reads into a
* char buffer. If you have any inc/def ref to do to the objects that contain * char buffer. If you have any inc/def ref to do to the objects that contain
* the buffer, do it in the caller. This function returns the number of bytes * the buffer, do it in the caller. This function returns the number of bytes
* succesfully read. If there was an error, it returns -1. Note that it is * succesfully read. If there was an error, it returns -1. Note that it is
* also possible that we return a number of bytes smaller than the request * also possible that we return a number of bytes smaller than the request
* bytes. * bytes.
*/ */
static int static ssize_t
sock_recv_guts(PySocketSockObject *s, char* cbuf, int len, int flags) sock_recv_guts(PySocketSockObject *s, char* cbuf, int len, int flags)
{ {
int timeout, outlen = 0; ssize_t outlen = 0;
int timeout;
#ifdef __VMS #ifdef __VMS
int remaining, nread; int remaining, nread;
char *read_buf; char *read_buf;
@ -2225,7 +2226,8 @@ sock_recv_guts(PySocketSockObject *s, char* cbuf, int len, int flags)
static PyObject * static PyObject *
sock_recv(PySocketSockObject *s, PyObject *args) sock_recv(PySocketSockObject *s, PyObject *args)
{ {
int recvlen, flags = 0, outlen; int recvlen, flags = 0;
ssize_t outlen;
PyObject *buf; PyObject *buf;
if (!PyArg_ParseTuple(args, "i|i:recv", &recvlen, &flags)) if (!PyArg_ParseTuple(args, "i|i:recv", &recvlen, &flags))
@ -2243,7 +2245,7 @@ sock_recv(PySocketSockObject *s, PyObject *args)
return NULL; return NULL;
/* Call the guts */ /* Call the guts */
outlen = sock_recv_guts(s, PyString_AsString(buf), recvlen, flags); outlen = sock_recv_guts(s, PyString_AS_STRING(buf), recvlen, flags);
if (outlen < 0) { if (outlen < 0) {
/* An error occured, release the string and return an /* An error occured, release the string and return an
error. */ error. */
@ -2270,19 +2272,20 @@ at least one byte is available or until the remote end is closed. When\n\
the remote end is closed and all data is read, return the empty string."); the remote end is closed and all data is read, return the empty string.");
/* s.recv_buf(buffer, [nbytes [,flags]]) method */ /* s.recv_into(buffer, [nbytes [,flags]]) method */
static PyObject* static PyObject*
sock_recv_buf(PySocketSockObject *s, PyObject *args, PyObject *kwds) sock_recv_into(PySocketSockObject *s, PyObject *args, PyObject *kwds)
{ {
static char *kwlist[] = {"buffer", "nbytes", "flags", 0}; static char *kwlist[] = {"buffer", "nbytes", "flags", 0};
int recvlen = 0, flags = 0, readlen; int recvlen = 0, flags = 0;
ssize_t readlen;
char *buf; char *buf;
int buflen; int buflen;
/* Get the buffer's memory */ /* Get the buffer's memory */
if (!PyArg_ParseTupleAndKeywords(args, kwds, "s#|ii:recv", kwlist, if (!PyArg_ParseTupleAndKeywords(args, kwds, "w#|ii:recv", kwlist,
&buf, &buflen, &recvlen, &flags)) &buf, &buflen, &recvlen, &flags))
return NULL; return NULL;
assert(buf != 0 && buflen > 0); assert(buf != 0 && buflen > 0);
@ -2313,11 +2316,11 @@ sock_recv_buf(PySocketSockObject *s, PyObject *args, PyObject *kwds)
/* Return the number of bytes read. Note that we do not do anything /* Return the number of bytes read. Note that we do not do anything
special here in the case that readlen < recvlen. */ special here in the case that readlen < recvlen. */
return PyInt_FromLong(readlen); return PyInt_FromSsize_t(readlen);
} }
PyDoc_STRVAR(recv_buf_doc, PyDoc_STRVAR(recv_into_doc,
"recv_buf(buffer, [nbytes[, flags]]) -> nbytes_read\n\ "recv_into(buffer, [nbytes[, flags]]) -> nbytes_read\n\
\n\ \n\
A version of recv() that stores its data into a buffer rather than creating \n\ A version of recv() that stores its data into a buffer rather than creating \n\
a new string. Receive up to buffersize bytes from the socket. If buffersize \n\ a new string. Receive up to buffersize bytes from the socket. If buffersize \n\
@ -2327,7 +2330,7 @@ See recv() for documentation about the flags.");
/* /*
* This is the guts of the recv() and recv_buf() methods, which reads into a * This is the guts of the recv() and recv_into() methods, which reads into a
* char buffer. If you have any inc/def ref to do to the objects that contain * char buffer. If you have any inc/def ref to do to the objects that contain
* the buffer, do it in the caller. This function returns the number of bytes * the buffer, do it in the caller. This function returns the number of bytes
* succesfully read. If there was an error, it returns -1. Note that it is * succesfully read. If there was an error, it returns -1. Note that it is
@ -2337,12 +2340,13 @@ See recv() for documentation about the flags.");
* 'addr' is a return value for the address object. Note that you must decref * 'addr' is a return value for the address object. Note that you must decref
* it yourself. * it yourself.
*/ */
static int static ssize_t
sock_recvfrom_guts(PySocketSockObject *s, char* cbuf, int len, int flags, sock_recvfrom_guts(PySocketSockObject *s, char* cbuf, int len, int flags,
PyObject** addr) PyObject** addr)
{ {
sock_addr_t addrbuf; sock_addr_t addrbuf;
int n = 0, timeout; int timeout;
ssize_t n = 0;
socklen_t addrlen; socklen_t addrlen;
*addr = NULL; *addr = NULL;
@ -2398,7 +2402,8 @@ sock_recvfrom(PySocketSockObject *s, PyObject *args)
PyObject *buf = NULL; PyObject *buf = NULL;
PyObject *addr = NULL; PyObject *addr = NULL;
PyObject *ret = NULL; PyObject *ret = NULL;
int recvlen, outlen, flags = 0; int recvlen, flags = 0;
ssize_t outlen;
if (!PyArg_ParseTuple(args, "i|i:recvfrom", &recvlen, &flags)) if (!PyArg_ParseTuple(args, "i|i:recvfrom", &recvlen, &flags))
return NULL; return NULL;
@ -2435,21 +2440,22 @@ PyDoc_STRVAR(recvfrom_doc,
Like recv(buffersize, flags) but also return the sender's address info."); Like recv(buffersize, flags) but also return the sender's address info.");
/* s.recvfrom_buf(buffer[, nbytes [,flags]]) method */ /* s.recvfrom_into(buffer[, nbytes [,flags]]) method */
static PyObject * static PyObject *
sock_recvfrom_buf(PySocketSockObject *s, PyObject *args, PyObject* kwds) sock_recvfrom_into(PySocketSockObject *s, PyObject *args, PyObject* kwds)
{ {
static char *kwlist[] = {"buffer", "nbytes", "flags", 0}; static char *kwlist[] = {"buffer", "nbytes", "flags", 0};
int recvlen = 0, flags = 0, readlen; int recvlen = 0, flags = 0;
ssize_t readlen;
char *buf; char *buf;
int buflen; int buflen;
PyObject *addr = NULL; PyObject *addr = NULL;
PyObject *ret = NULL; PyObject *ret = NULL;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "s#|ii:recvfrom", kwlist, if (!PyArg_ParseTupleAndKeywords(args, kwds, "w#|ii:recvfrom", kwlist,
&buf, &buflen, &recvlen, &flags)) &buf, &buflen, &recvlen, &flags))
return NULL; return NULL;
assert(buf != 0 && buflen > 0); assert(buf != 0 && buflen > 0);
@ -2467,22 +2473,19 @@ sock_recvfrom_buf(PySocketSockObject *s, PyObject *args, PyObject* kwds)
readlen = sock_recvfrom_guts(s, buf, recvlen, flags, &addr); readlen = sock_recvfrom_guts(s, buf, recvlen, flags, &addr);
if (readlen < 0) { if (readlen < 0) {
/* Return an error */ /* Return an error */
goto finally; Py_XDECREF(addr);
return NULL;
} }
/* Return the number of bytes read and the address. Note that we do /* Return the number of bytes read and the address. Note that we do
not do anything special here in the case that readlen < recvlen. */ not do anything special here in the case that readlen < recvlen. */
ret = Py_BuildValue("lO", readlen, addr); return Py_BuildValue("lO", readlen, addr);
finally:
Py_XDECREF(addr);
return ret;
} }
PyDoc_STRVAR(recvfrom_buf_doc, PyDoc_STRVAR(recvfrom_into_doc,
"recvfrom_buf(buffer[, nbytes[, flags]]) -> (nbytes, address info)\n\ "recvfrom_into(buffer[, nbytes[, flags]]) -> (nbytes, address info)\n\
\n\ \n\
Like recv_buf(buffer[, nbytes[, flags]]) but also return the sender's address info."); Like recv_into(buffer[, nbytes[, flags]]) but also return the sender's address info.");
/* s.send(data [,flags]) method */ /* s.send(data [,flags]) method */
@ -2711,12 +2714,12 @@ static PyMethodDef sock_methods[] = {
#endif #endif
{"recv", (PyCFunction)sock_recv, METH_VARARGS, {"recv", (PyCFunction)sock_recv, METH_VARARGS,
recv_doc}, recv_doc},
{"recv_buf", (PyCFunction)sock_recv_buf, METH_VARARGS | METH_KEYWORDS, {"recv_into", (PyCFunction)sock_recv_into, METH_VARARGS | METH_KEYWORDS,
recv_buf_doc}, recv_into_doc},
{"recvfrom", (PyCFunction)sock_recvfrom, METH_VARARGS, {"recvfrom", (PyCFunction)sock_recvfrom, METH_VARARGS,
recvfrom_doc}, recvfrom_doc},
{"recvfrom_buf", (PyCFunction)sock_recvfrom_buf, METH_VARARGS | METH_KEYWORDS, {"recvfrom_into", (PyCFunction)sock_recvfrom_into, METH_VARARGS | METH_KEYWORDS,
recvfrom_buf_doc}, recvfrom_into_doc},
{"send", (PyCFunction)sock_send, METH_VARARGS, {"send", (PyCFunction)sock_send, METH_VARARGS,
send_doc}, send_doc},
{"sendall", (PyCFunction)sock_sendall, METH_VARARGS, {"sendall", (PyCFunction)sock_sendall, METH_VARARGS,