Merge heads

This commit is contained in:
Serhiy Storchaka 2016-01-28 19:56:40 +02:00
commit b49a1edc15
9 changed files with 119 additions and 18 deletions

View File

@ -34,5 +34,5 @@ will work on all subsequent Python releases, but fail to load (because of
missing symbols) on the older releases. missing symbols) on the older releases.
As of Python 3.2, the set of functions available to the limited API is 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." part of the limited API are marked as "Not part of the limited API."

View File

@ -716,8 +716,8 @@ Pointer instances are created by calling the :func:`pointer` function on a
>>> pi = pointer(i) >>> pi = pointer(i)
>>> >>>
Pointer instances have a :attr:`contents` attribute which returns the object to Pointer instances have a :attr:`~_Pointer.contents` attribute which
which the pointer points, the ``i`` object above:: returns the object to which the pointer points, the ``i`` object above::
>>> pi.contents >>> pi.contents
c_long(42) c_long(42)
@ -2401,6 +2401,56 @@ other data types containing pointer type fields.
Arrays and pointers Arrays and pointers
^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^
Not yet written - please see the sections :ref:`ctypes-pointers` and section .. class:: Array(\*args)
:ref:`ctypes-arrays` in the tutorial.
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.

View File

@ -24,20 +24,24 @@ class ArrayTestCase(unittest.TestCase):
self.assertEqual(len(ia), alen) self.assertEqual(len(ia), alen)
# slot values ok? # slot values ok?
values = [ia[i] for i in range(len(init))] values = [ia[i] for i in range(alen)]
self.assertEqual(values, init) 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 # change the items
from operator import setitem from operator import setitem
new_values = list(range(42, 42+alen)) new_values = list(range(42, 42+alen))
[setitem(ia, n, new_values[n]) for n in range(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) self.assertEqual(values, new_values)
# are the items initialized to 0? # are the items initialized to 0?
ia = int_array() ia = int_array()
values = [ia[i] for i in range(len(init))] values = [ia[i] for i in range(alen)]
self.assertEqual(values, [0] * len(init)) self.assertEqual(values, [0] * alen)
# Too many initializers should be caught # Too many initializers should be caught
self.assertRaises(IndexError, int_array, *range(alen*2)) self.assertRaises(IndexError, int_array, *range(alen*2))

View File

@ -56,9 +56,13 @@ class PointersTestCase(unittest.TestCase):
# C code: # C code:
# int x = 12321; # int x = 12321;
# res = &x # res = &x
res.contents = c_int(12321) x = c_int(12321)
res.contents = x
self.assertEqual(i.value, 54345) self.assertEqual(i.value, 54345)
x.value = -99
self.assertEqual(res.contents.value, -99)
def test_callbacks_with_pointers(self): def test_callbacks_with_pointers(self):
# a function type receiving a pointer # a function type receiving a pointer
PROTOTYPE = CFUNCTYPE(c_int, POINTER(c_int)) PROTOTYPE = CFUNCTYPE(c_int, POINTER(c_int))
@ -131,9 +135,10 @@ class PointersTestCase(unittest.TestCase):
def test_basic(self): def test_basic(self):
p = pointer(c_int(42)) 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.assertRaises(TypeError, len, p)
self.assertEqual(p[0], 42) self.assertEqual(p[0], 42)
self.assertEqual(p[0:1], [42])
self.assertEqual(p.contents.value, 42) self.assertEqual(p.contents.value, 42)
def test_charpp(self): def test_charpp(self):

View File

@ -334,10 +334,12 @@ class SocketEINTRTest(EINTRBaseTest):
self._test_open("fp = open(path, 'r')\nfp.close()", self._test_open("fp = open(path, 'r')\nfp.close()",
self.python_open) self.python_open)
@unittest.skipIf(sys.platform == 'darwin', "hangs under OS X; see issue #25234")
def os_open(self, path): def os_open(self, path):
fd = os.open(path, os.O_WRONLY) fd = os.open(path, os.O_WRONLY)
os.close(fd) os.close(fd)
@unittest.skipIf(sys.platform == "darwin", "hangs under OS X; see issue #25234")
def test_os_open(self): def test_os_open(self):
self._test_open("fd = os.open(path, os.O_RDONLY)\nos.close(fd)", self._test_open("fd = os.open(path, os.O_RDONLY)\nos.close(fd)",
self.os_open) self.os_open)
@ -370,10 +372,10 @@ class SignalEINTRTest(EINTRBaseTest):
@unittest.skipUnless(hasattr(signal, 'sigwaitinfo'), @unittest.skipUnless(hasattr(signal, 'sigwaitinfo'),
'need signal.sigwaitinfo()') 'need signal.sigwaitinfo()')
def test_sigwaitinfo(self): def test_sigwaitinfo(self):
# Issue #25277: The sleep is a weak synchronization between the parent # Issue #25277, #25868: give a few miliseconds to the parent process
# and the child process. If the sleep is too low, the test hangs on # between os.write() and signal.sigwaitinfo() to works around a race
# slow or highly loaded systems. # condition
self.sleep_time = 2.0 self.sleep_time = 0.100
signum = signal.SIGUSR1 signum = signal.SIGUSR1
pid = os.getpid() pid = os.getpid()
@ -381,18 +383,28 @@ class SignalEINTRTest(EINTRBaseTest):
old_handler = signal.signal(signum, lambda *args: None) old_handler = signal.signal(signum, lambda *args: None)
self.addCleanup(signal.signal, signum, old_handler) self.addCleanup(signal.signal, signum, old_handler)
rpipe, wpipe = os.pipe()
code = '\n'.join(( code = '\n'.join((
'import os, time', 'import os, time',
'pid = %s' % os.getpid(), 'pid = %s' % os.getpid(),
'signum = %s' % int(signum), 'signum = %s' % int(signum),
'sleep_time = %r' % self.sleep_time, 'sleep_time = %r' % self.sleep_time,
'rpipe = %r' % rpipe,
'os.read(rpipe, 1)',
'os.close(rpipe)',
'time.sleep(sleep_time)', 'time.sleep(sleep_time)',
'os.kill(pid, signum)', 'os.kill(pid, signum)',
)) ))
t0 = time.monotonic() t0 = time.monotonic()
proc = self.subprocess(code) proc = self.subprocess(code, pass_fds=(rpipe,))
os.close(rpipe)
with kill_on_error(proc): with kill_on_error(proc):
# sync child-parent
os.write(wpipe, b'x')
os.close(wpipe)
# parent # parent
signal.sigwaitinfo([signum]) signal.sigwaitinfo([signum])
dt = time.monotonic() - t0 dt = time.monotonic() - t0

View File

@ -421,6 +421,8 @@ class MakefileTests(unittest.TestCase):
print("var3=42", file=makefile) print("var3=42", file=makefile)
print("var4=$/invalid", file=makefile) print("var4=$/invalid", file=makefile)
print("var5=dollar$$5", 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) vars = sysconfig._parse_makefile(TESTFN)
self.assertEqual(vars, { self.assertEqual(vars, {
'var1': 'ab42', 'var1': 'ab42',
@ -428,6 +430,7 @@ class MakefileTests(unittest.TestCase):
'var3': 42, 'var3': 42,
'var4': '$/invalid', 'var4': '$/invalid',
'var5': 'dollar$5', 'var5': 'dollar$5',
'var6': '42/lib/python3.5/config-b42dollar$5-x86_64-linux-gnu',
}) })

View File

@ -1497,6 +1497,7 @@ Dmitry Vasiliev
Sebastian Ortiz Vasquez Sebastian Ortiz Vasquez
Alexandre Vassalotti Alexandre Vassalotti
Nadeem Vawda Nadeem Vawda
Sye van der Veen
Frank Vercruesse Frank Vercruesse
Mike Verdone Mike Verdone
Jaap Vermeulen Jaap Vermeulen

View File

@ -66,6 +66,10 @@ Core and Builtins
Library 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 - Issue #26147: xmlrpc now works with strings not encodable with used
non-UTF-8 encoding. non-UTF-8 encoding.

View File

@ -4519,6 +4519,19 @@ PyDoc_STRVAR(gethostbyname_doc,
Return the IP address (a string of the form '255.255.255.255') for a host."); 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 */ /* Convenience function common to gethostbyname_ex and gethostbyaddr */
static PyObject * 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 *name_list = (PyObject *)NULL;
PyObject *addr_list = (PyObject *)NULL; PyObject *addr_list = (PyObject *)NULL;
PyObject *tmp; PyObject *tmp;
PyObject *name;
if (h == NULL) { if (h == NULL) {
/* Let's get real error message to return */ /* 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; 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: err:
Py_XDECREF(name_list); Py_XDECREF(name_list);
@ -5623,6 +5640,7 @@ socket_getnameinfo(PyObject *self, PyObject *args)
struct addrinfo hints, *res = NULL; struct addrinfo hints, *res = NULL;
int error; int error;
PyObject *ret = (PyObject *)NULL; PyObject *ret = (PyObject *)NULL;
PyObject *name;
flags = flowinfo = scope_id = 0; flags = flowinfo = scope_id = 0;
if (!PyArg_ParseTuple(args, "Oi:getnameinfo", &sa, &flags)) if (!PyArg_ParseTuple(args, "Oi:getnameinfo", &sa, &flags))
@ -5686,7 +5704,11 @@ socket_getnameinfo(PyObject *self, PyObject *args)
set_gaierror(error); set_gaierror(error);
goto fail; 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: fail:
if (res) if (res)