summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2016-01-28 17:56:40 (GMT)
committerSerhiy Storchaka <storchaka@gmail.com>2016-01-28 17:56:40 (GMT)
commitb49a1edc1556d99a9231f0e7da54e01096f4d912 (patch)
tree24067c21aace36e35cbcc5297ea82f0cf3d60459
parentc8241fdde7bce66f74363f8240e1b29d75fab3f8 (diff)
parent8f475effbc860e84e266923f9c19915914cc780f (diff)
downloadcpython-b49a1edc1556d99a9231f0e7da54e01096f4d912.zip
cpython-b49a1edc1556d99a9231f0e7da54e01096f4d912.tar.gz
cpython-b49a1edc1556d99a9231f0e7da54e01096f4d912.tar.bz2
Merge heads
-rw-r--r--Doc/c-api/stable.rst2
-rw-r--r--Doc/library/ctypes.rst58
-rw-r--r--Lib/ctypes/test/test_arrays.py12
-rw-r--r--Lib/ctypes/test/test_pointers.py9
-rw-r--r--Lib/test/eintrdata/eintr_tester.py22
-rw-r--r--Lib/test/test_sysconfig.py3
-rw-r--r--Misc/ACKS1
-rw-r--r--Misc/NEWS4
-rw-r--r--Modules/socketmodule.c26
9 files changed, 119 insertions, 18 deletions
diff --git a/Doc/c-api/stable.rst b/Doc/c-api/stable.rst
index 063f856..5b771dd 100644
--- a/Doc/c-api/stable.rst
+++ b/Doc/c-api/stable.rst
@@ -34,5 +34,5 @@ will work on all subsequent Python releases, but fail to load (because of
missing symbols) on the older releases.
As of Python 3.2, the set of functions available to the limited API is
-documented in PEP 384. In the C API documentation, API elements that are not
+documented in :pep:`384`. In the C API documentation, API elements that are not
part of the limited API are marked as "Not part of the limited API."
diff --git a/Doc/library/ctypes.rst b/Doc/library/ctypes.rst
index b72bdb4..9abd469 100644
--- a/Doc/library/ctypes.rst
+++ b/Doc/library/ctypes.rst
@@ -716,8 +716,8 @@ Pointer instances are created by calling the :func:`pointer` function on a
>>> pi = pointer(i)
>>>
-Pointer instances have a :attr:`contents` attribute which returns the object to
-which the pointer points, the ``i`` object above::
+Pointer instances have a :attr:`~_Pointer.contents` attribute which
+returns the object to which the pointer points, the ``i`` object above::
>>> pi.contents
c_long(42)
@@ -2401,6 +2401,56 @@ other data types containing pointer type fields.
Arrays and pointers
^^^^^^^^^^^^^^^^^^^
-Not yet written - please see the sections :ref:`ctypes-pointers` and section
-:ref:`ctypes-arrays` in the tutorial.
+.. class:: Array(\*args)
+
+ Abstract base class for arrays.
+
+ The recommended way to create concrete array types is by multiplying any
+ :mod:`ctypes` data type with a positive integer. Alternatively, you can subclass
+ this type and define :attr:`_length_` and :attr:`_type_` class variables.
+ Array elements can be read and written using standard
+ subscript and slice accesses; for slice reads, the resulting object is
+ *not* itself an :class:`Array`.
+
+
+ .. attribute:: _length_
+
+ A positive integer specifying the number of elements in the array.
+ Out-of-range subscripts result in an :exc:`IndexError`. Will be
+ returned by :func:`len`.
+
+
+ .. attribute:: _type_
+
+ Specifies the type of each element in the array.
+
+
+ Array subclass constructors accept positional arguments, used to
+ initialize the elements in order.
+
+
+.. class:: _Pointer
+
+ Private, abstract base class for pointers.
+
+ Concrete pointer types are created by calling :func:`POINTER` with the
+ type that will be pointed to; this is done automatically by
+ :func:`pointer`.
+
+ If a pointer points to an array, its elements can be read and
+ written using standard subscript and slice accesses. Pointer objects
+ have no size, so :func:`len` will raise :exc:`TypeError`. Negative
+ subscripts will read from the memory *before* the pointer (as in C), and
+ out-of-range subscripts will probably crash with an access violation (if
+ you're lucky).
+
+
+ .. attribute:: _type_
+
+ Specifies the type pointed to.
+
+ .. attribute:: contents
+
+ Returns the object to which to pointer points. Assigning to this
+ attribute changes the pointer to point to the assigned object.
diff --git a/Lib/ctypes/test/test_arrays.py b/Lib/ctypes/test/test_arrays.py
index 8ca77e0..4ed566b 100644
--- a/Lib/ctypes/test/test_arrays.py
+++ b/Lib/ctypes/test/test_arrays.py
@@ -24,20 +24,24 @@ class ArrayTestCase(unittest.TestCase):
self.assertEqual(len(ia), alen)
# slot values ok?
- values = [ia[i] for i in range(len(init))]
+ values = [ia[i] for i in range(alen)]
self.assertEqual(values, init)
+ # out-of-bounds accesses should be caught
+ with self.assertRaises(IndexError): ia[alen]
+ with self.assertRaises(IndexError): ia[-alen-1]
+
# change the items
from operator import setitem
new_values = list(range(42, 42+alen))
[setitem(ia, n, new_values[n]) for n in range(alen)]
- values = [ia[i] for i in range(len(init))]
+ values = [ia[i] for i in range(alen)]
self.assertEqual(values, new_values)
# are the items initialized to 0?
ia = int_array()
- values = [ia[i] for i in range(len(init))]
- self.assertEqual(values, [0] * len(init))
+ values = [ia[i] for i in range(alen)]
+ self.assertEqual(values, [0] * alen)
# Too many initializers should be caught
self.assertRaises(IndexError, int_array, *range(alen*2))
diff --git a/Lib/ctypes/test/test_pointers.py b/Lib/ctypes/test/test_pointers.py
index 225b9d1..751f85f 100644
--- a/Lib/ctypes/test/test_pointers.py
+++ b/Lib/ctypes/test/test_pointers.py
@@ -56,9 +56,13 @@ class PointersTestCase(unittest.TestCase):
# C code:
# int x = 12321;
# res = &x
- res.contents = c_int(12321)
+ x = c_int(12321)
+ res.contents = x
self.assertEqual(i.value, 54345)
+ x.value = -99
+ self.assertEqual(res.contents.value, -99)
+
def test_callbacks_with_pointers(self):
# a function type receiving a pointer
PROTOTYPE = CFUNCTYPE(c_int, POINTER(c_int))
@@ -131,9 +135,10 @@ class PointersTestCase(unittest.TestCase):
def test_basic(self):
p = pointer(c_int(42))
- # Although a pointer can be indexed, it ha no length
+ # Although a pointer can be indexed, it has no length
self.assertRaises(TypeError, len, p)
self.assertEqual(p[0], 42)
+ self.assertEqual(p[0:1], [42])
self.assertEqual(p.contents.value, 42)
def test_charpp(self):
diff --git a/Lib/test/eintrdata/eintr_tester.py b/Lib/test/eintrdata/eintr_tester.py
index e3c36f9..9931a55 100644
--- a/Lib/test/eintrdata/eintr_tester.py
+++ b/Lib/test/eintrdata/eintr_tester.py
@@ -334,10 +334,12 @@ class SocketEINTRTest(EINTRBaseTest):
self._test_open("fp = open(path, 'r')\nfp.close()",
self.python_open)
+ @unittest.skipIf(sys.platform == 'darwin', "hangs under OS X; see issue #25234")
def os_open(self, path):
fd = os.open(path, os.O_WRONLY)
os.close(fd)
+ @unittest.skipIf(sys.platform == "darwin", "hangs under OS X; see issue #25234")
def test_os_open(self):
self._test_open("fd = os.open(path, os.O_RDONLY)\nos.close(fd)",
self.os_open)
@@ -370,10 +372,10 @@ class SignalEINTRTest(EINTRBaseTest):
@unittest.skipUnless(hasattr(signal, 'sigwaitinfo'),
'need signal.sigwaitinfo()')
def test_sigwaitinfo(self):
- # Issue #25277: The sleep is a weak synchronization between the parent
- # and the child process. If the sleep is too low, the test hangs on
- # slow or highly loaded systems.
- self.sleep_time = 2.0
+ # Issue #25277, #25868: give a few miliseconds to the parent process
+ # between os.write() and signal.sigwaitinfo() to works around a race
+ # condition
+ self.sleep_time = 0.100
signum = signal.SIGUSR1
pid = os.getpid()
@@ -381,18 +383,28 @@ class SignalEINTRTest(EINTRBaseTest):
old_handler = signal.signal(signum, lambda *args: None)
self.addCleanup(signal.signal, signum, old_handler)
+ rpipe, wpipe = os.pipe()
+
code = '\n'.join((
'import os, time',
'pid = %s' % os.getpid(),
'signum = %s' % int(signum),
'sleep_time = %r' % self.sleep_time,
+ 'rpipe = %r' % rpipe,
+ 'os.read(rpipe, 1)',
+ 'os.close(rpipe)',
'time.sleep(sleep_time)',
'os.kill(pid, signum)',
))
t0 = time.monotonic()
- proc = self.subprocess(code)
+ proc = self.subprocess(code, pass_fds=(rpipe,))
+ os.close(rpipe)
with kill_on_error(proc):
+ # sync child-parent
+ os.write(wpipe, b'x')
+ os.close(wpipe)
+
# parent
signal.sigwaitinfo([signum])
dt = time.monotonic() - t0
diff --git a/Lib/test/test_sysconfig.py b/Lib/test/test_sysconfig.py
index 0917c3e..a23bf06a 100644
--- a/Lib/test/test_sysconfig.py
+++ b/Lib/test/test_sysconfig.py
@@ -421,6 +421,8 @@ class MakefileTests(unittest.TestCase):
print("var3=42", file=makefile)
print("var4=$/invalid", file=makefile)
print("var5=dollar$$5", file=makefile)
+ print("var6=${var3}/lib/python3.5/config-$(VAR2)$(var5)"
+ "-x86_64-linux-gnu", file=makefile)
vars = sysconfig._parse_makefile(TESTFN)
self.assertEqual(vars, {
'var1': 'ab42',
@@ -428,6 +430,7 @@ class MakefileTests(unittest.TestCase):
'var3': 42,
'var4': '$/invalid',
'var5': 'dollar$5',
+ 'var6': '42/lib/python3.5/config-b42dollar$5-x86_64-linux-gnu',
})
diff --git a/Misc/ACKS b/Misc/ACKS
index 93a31de..28e45d3 100644
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -1497,6 +1497,7 @@ Dmitry Vasiliev
Sebastian Ortiz Vasquez
Alexandre Vassalotti
Nadeem Vawda
+Sye van der Veen
Frank Vercruesse
Mike Verdone
Jaap Vermeulen
diff --git a/Misc/NEWS b/Misc/NEWS
index 5e461f9..d6f81db 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -66,6 +66,10 @@ Core and Builtins
Library
-------
+- Issue #26227: On Windows, getnameinfo(), gethostbyaddr() and
+ gethostbyname_ex() functions of the socket module now decode the hostname
+ from the ANSI code page rather than UTF-8.
+
- Issue #26147: xmlrpc now works with strings not encodable with used
non-UTF-8 encoding.
diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c
index bae9634..90aa3af 100644
--- a/Modules/socketmodule.c
+++ b/Modules/socketmodule.c
@@ -4519,6 +4519,19 @@ PyDoc_STRVAR(gethostbyname_doc,
Return the IP address (a string of the form '255.255.255.255') for a host.");
+static PyObject*
+sock_decode_hostname(const char *name)
+{
+#ifdef MS_WINDOWS
+ /* Issue #26227: gethostbyaddr() returns a string encoded
+ * to the ANSI code page */
+ return PyUnicode_DecodeFSDefault(name);
+#else
+ /* Decode from UTF-8 */
+ return PyUnicode_FromString(name);
+#endif
+}
+
/* Convenience function common to gethostbyname_ex and gethostbyaddr */
static PyObject *
@@ -4529,6 +4542,7 @@ gethost_common(struct hostent *h, struct sockaddr *addr, size_t alen, int af)
PyObject *name_list = (PyObject *)NULL;
PyObject *addr_list = (PyObject *)NULL;
PyObject *tmp;
+ PyObject *name;
if (h == NULL) {
/* Let's get real error message to return */
@@ -4637,7 +4651,10 @@ gethost_common(struct hostent *h, struct sockaddr *addr, size_t alen, int af)
goto err;
}
- rtn_tuple = Py_BuildValue("sOO", h->h_name, name_list, addr_list);
+ name = sock_decode_hostname(h->h_name);
+ if (name == NULL)
+ goto err;
+ rtn_tuple = Py_BuildValue("NOO", name, name_list, addr_list);
err:
Py_XDECREF(name_list);
@@ -5623,6 +5640,7 @@ socket_getnameinfo(PyObject *self, PyObject *args)
struct addrinfo hints, *res = NULL;
int error;
PyObject *ret = (PyObject *)NULL;
+ PyObject *name;
flags = flowinfo = scope_id = 0;
if (!PyArg_ParseTuple(args, "Oi:getnameinfo", &sa, &flags))
@@ -5686,7 +5704,11 @@ socket_getnameinfo(PyObject *self, PyObject *args)
set_gaierror(error);
goto fail;
}
- ret = Py_BuildValue("ss", hbuf, pbuf);
+
+ name = sock_decode_hostname(hbuf);
+ if (name == NULL)
+ goto fail;
+ ret = Py_BuildValue("Ns", name, pbuf);
fail:
if (res)