Branch merge
diff --git a/Doc/library/cmd.rst b/Doc/library/cmd.rst
index c1cda5b..0c43bb8 100644
--- a/Doc/library/cmd.rst
+++ b/Doc/library/cmd.rst
@@ -247,7 +247,7 @@
right(*parse(arg))
def do_left(self, arg):
'Turn turtle left by given number of degrees: LEFT 90'
- right(*parse(arg))
+ left(*parse(arg))
def do_goto(self, arg):
'Move turtle to an absolute position with changing orientation. GOTO 100 200'
goto(*parse(arg))
diff --git a/Doc/library/zlib.rst b/Doc/library/zlib.rst
index 54835e7..9f8eb26 100644
--- a/Doc/library/zlib.rst
+++ b/Doc/library/zlib.rst
@@ -19,7 +19,7 @@
information.
For reading and writing ``.gz`` files see the :mod:`gzip` module. For
-other archive formats, see the :mod:`bz2`, :mod:`zipfile`, and
+other related file formats, see the :mod:`bz2`, :mod:`zipfile`, and
:mod:`tarfile` modules.
The available exception and functions in this module are:
@@ -122,6 +122,7 @@
won't fit into memory at once. The *wbits* parameter controls the size of the
window buffer.
+
Compression objects support the following methods:
@@ -217,6 +218,24 @@
seeks into the stream at a future point.
+Information about the version of the zlib library in use is available through
+the following constants:
+
+
+.. data:: ZLIB_VERSION
+
+ The version string of the zlib library that was used for building the module.
+ This may be different from the zlib library actually used at runtime, which
+ is available as :const:`ZLIB_RUNTIME_VERSION`.
+
+
+.. data:: ZLIB_RUNTIME_VERSION
+
+ The version string of the zlib library actually loaded by the interpreter.
+
+ .. versionadded:: 3.3
+
+
.. seealso::
Module :mod:`gzip`
diff --git a/Lib/bz2.py b/Lib/bz2.py
index cc71ae0..cbf5233 100644
--- a/Lib/bz2.py
+++ b/Lib/bz2.py
@@ -75,11 +75,11 @@
elif mode in ("w", "wb"):
mode = "wb"
mode_code = _MODE_WRITE
- self._compressor = BZ2Compressor()
+ self._compressor = BZ2Compressor(compresslevel)
elif mode in ("a", "ab"):
mode = "ab"
mode_code = _MODE_WRITE
- self._compressor = BZ2Compressor()
+ self._compressor = BZ2Compressor(compresslevel)
else:
raise ValueError("Invalid mode: {!r}".format(mode))
diff --git a/Lib/collections/__init__.py b/Lib/collections/__init__.py
index 2007e68..e5e0277 100644
--- a/Lib/collections/__init__.py
+++ b/Lib/collections/__init__.py
@@ -1,5 +1,5 @@
__all__ = ['deque', 'defaultdict', 'namedtuple', 'UserDict', 'UserList',
- 'UserString', 'Counter', 'OrderedDict']
+ 'UserString', 'Counter', 'OrderedDict', 'ChainMap']
# For backwards compatibility, continue to make the collections ABCs
# available through the collections module.
diff --git a/Lib/test/test_bz2.py b/Lib/test/test_bz2.py
index 5a7d342..d003238 100644
--- a/Lib/test/test_bz2.py
+++ b/Lib/test/test_bz2.py
@@ -224,6 +224,13 @@
with open(self.filename, 'rb') as f:
self.assertEqual(self.decompress(f.read()), self.TEXT)
+ def testWriteNonDefaultCompressLevel(self):
+ expected = bz2.compress(self.TEXT, compresslevel=5)
+ with BZ2File(self.filename, "w", compresslevel=5) as bz2f:
+ bz2f.write(self.TEXT)
+ with open(self.filename, "rb") as f:
+ self.assertEqual(f.read(), expected)
+
def testWriteLines(self):
with BZ2File(self.filename, "w") as bz2f:
self.assertRaises(TypeError, bz2f.writelines)
diff --git a/Lib/test/test_multiprocessing.py b/Lib/test/test_multiprocessing.py
index 7a7805d..3f8a9a2 100644
--- a/Lib/test/test_multiprocessing.py
+++ b/Lib/test/test_multiprocessing.py
@@ -296,6 +296,7 @@
p = self.Process(target=time.sleep, args=(DELTA,))
self.assertNotIn(p, self.active_children())
+ p.daemon = True
p.start()
self.assertIn(p, self.active_children())
@@ -386,6 +387,7 @@
def test_subclassing(self):
uppercaser = _UpperCaser()
+ uppercaser.daemon = True
uppercaser.start()
self.assertEqual(uppercaser.submit('hello'), 'HELLO')
self.assertEqual(uppercaser.submit('world'), 'WORLD')
@@ -564,6 +566,7 @@
# fork process
p = self.Process(target=self._test_fork, args=(queue,))
+ p.daemon = True
p.start()
# check that all expected items are in the queue
@@ -604,6 +607,7 @@
for i in range(4)]
for p in workers:
+ p.daemon = True
p.start()
for i in range(10):
@@ -874,7 +878,9 @@
#self.assertEqual(event.is_set(), False)
- self.Process(target=self._test_event, args=(event,)).start()
+ p = self.Process(target=self._test_event, args=(event,))
+ p.daemon = True
+ p.start()
self.assertEqual(wait(), True)
#
@@ -914,6 +920,7 @@
self.assertEqual(sv.value, cv[1])
proc = self.Process(target=self._test, args=(values,))
+ proc.daemon = True
proc.start()
proc.join()
@@ -977,6 +984,7 @@
self.f(seq)
p = self.Process(target=self.f, args=(arr,))
+ p.daemon = True
p.start()
p.join()
@@ -1381,6 +1389,7 @@
manager.start()
p = self.Process(target=self._putter, args=(manager.address, authkey))
+ p.daemon = True
p.start()
manager2 = QueueManager2(
@@ -1422,6 +1431,7 @@
manager.start()
p = self.Process(target=self._putter, args=(manager.address, authkey))
+ p.daemon = True
p.start()
queue = manager.get_queue()
self.assertEqual(queue.get(), 'hello world')
@@ -1554,6 +1564,7 @@
conn, child_conn = self.Pipe()
p = self.Process(target=self._echo, args=(child_conn,))
+ p.daemon = True
p.start()
child_conn.close() # this might complete before child initializes
@@ -1626,6 +1637,7 @@
conn, child_conn = self.Pipe(duplex=True)
p = self.Process(target=self._writefd, args=(child_conn, b"foo"))
+ p.daemon = True
p.start()
with open(test.support.TESTFN, "wb") as f:
fd = f.fileno()
@@ -1649,6 +1661,7 @@
conn, child_conn = self.Pipe(duplex=True)
p = self.Process(target=self._writefd, args=(child_conn, b"bar", True))
+ p.daemon = True
p.start()
with open(test.support.TESTFN, "wb") as f:
fd = f.fileno()
@@ -1737,11 +1750,13 @@
lconn, lconn0 = self.Pipe()
lp = self.Process(target=self._listener, args=(lconn0, families))
+ lp.daemon = True
lp.start()
lconn0.close()
rconn, rconn0 = self.Pipe()
rp = self.Process(target=self._remote, args=(rconn0,))
+ rp.daemon = True
rp.start()
rconn0.close()
@@ -1879,6 +1894,7 @@
string.value = latin('hello')
p = self.Process(target=self._double, args=(x, y, foo, arr, string))
+ p.daemon = True
p.start()
p.join()
@@ -1951,6 +1967,7 @@
conn, child_conn = self.Pipe()
p = self.Process(target=self._test_finalize, args=(child_conn,))
+ p.daemon = True
p.start()
p.join()
@@ -2020,12 +2037,16 @@
reader, writer = multiprocessing.Pipe(duplex=False)
logger.setLevel(LEVEL1)
- self.Process(target=self._test_level, args=(writer,)).start()
+ p = self.Process(target=self._test_level, args=(writer,))
+ p.daemon = True
+ p.start()
self.assertEqual(LEVEL1, reader.recv())
logger.setLevel(logging.NOTSET)
root_logger.setLevel(LEVEL2)
- self.Process(target=self._test_level, args=(writer,)).start()
+ p = self.Process(target=self._test_level, args=(writer,))
+ p.daemon = True
+ p.start()
self.assertEqual(LEVEL2, reader.recv())
root_logger.setLevel(root_level)
@@ -2217,6 +2238,7 @@
def _TestProcess(q):
queue = multiprocessing.Queue()
subProc = multiprocessing.Process(target=_ThisSubProcess, args=(queue,))
+ subProc.daemon = True
subProc.start()
subProc.join()
diff --git a/Lib/test/test_posix.py b/Lib/test/test_posix.py
index 1af6cf4..f70688d 100644
--- a/Lib/test/test_posix.py
+++ b/Lib/test/test_posix.py
@@ -862,12 +862,12 @@
mine = posix.sched_getscheduler(0)
self.assertIn(mine, possible_schedulers)
try:
- init = posix.sched_getscheduler(1)
+ parent = posix.sched_getscheduler(os.getppid())
except OSError as e:
- if e.errno != errno.EPERM and e.errno != errno.ESRCH:
+ if e.errno != errno.EPERM:
raise
else:
- self.assertIn(init, possible_schedulers)
+ self.assertIn(parent, possible_schedulers)
self.assertRaises(OSError, posix.sched_getscheduler, -1)
self.assertRaises(OSError, posix.sched_getparam, -1)
param = posix.sched_getparam(0)
diff --git a/Lib/test/test_zlib.py b/Lib/test/test_zlib.py
index dddde47..8d137ac 100644
--- a/Lib/test/test_zlib.py
+++ b/Lib/test/test_zlib.py
@@ -13,6 +13,17 @@
mmap = None
+class VersionTestCase(unittest.TestCase):
+
+ def test_library_version(self):
+ # On the build system, ZLIB_RUNTIME_VERSION should match ZLIB_VERSION.
+ # ZLIB_RUNTIME_VERSION is the actual library version while ZLIB_VERSION
+ # is the version from the header file. On the build system, the headers
+ # should match with the library exactly. At runtime, only the first
+ # digit is required to match.
+ self.assertEqual(zlib.ZLIB_RUNTIME_VERSION, zlib.ZLIB_VERSION)
+
+
class ChecksumTestCase(unittest.TestCase):
# checksum test cases
def test_crc32start(self):
@@ -647,6 +658,7 @@
def test_main():
support.run_unittest(
+ VersionTestCase,
ChecksumTestCase,
ChecksumBigBufferTestCase,
ExceptionTestCase,
diff --git a/Misc/NEWS b/Misc/NEWS
index 3d35823..7218bfd 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -274,6 +274,11 @@
Library
-------
+- Issue #12306: Expose the runtime version of the zlib C library as a constant,
+ ZLIB_RUNTIME_VERSION, in the zlib module. Patch by Torsten Landschoff.
+
+- Issue #12959: Add collections.ChainMap to collections.__all__.
+
- Issue #8933: distutils' PKG-INFO files and packaging's METADATA files will
now correctly report Metadata-Version: 1.1 instead of 1.0 if a Classifier or
Download-URL field is present.
@@ -1269,6 +1274,9 @@
Extension Modules
-----------------
+- Issue #12950: Fix passing file descriptors in multiprocessing, under
+ OpenIndiana/Illumos.
+
- Issue #12764: Fix a crash in ctypes when the name of a Structure field is not
a string.
diff --git a/Modules/_multiprocessing/multiprocessing.c b/Modules/_multiprocessing/multiprocessing.c
index 1987b95..f6c2259 100644
--- a/Modules/_multiprocessing/multiprocessing.c
+++ b/Modules/_multiprocessing/multiprocessing.c
@@ -86,31 +86,37 @@
/* Functions for transferring file descriptors between processes.
Reimplements some of the functionality of the fdcred
module at http://www.mca-ltd.com/resources/fdcred_1.tgz. */
+/* Based in http://resin.csoft.net/cgi-bin/man.cgi?section=3&topic=CMSG_DATA */
static PyObject *
multiprocessing_sendfd(PyObject *self, PyObject *args)
{
int conn, fd, res;
- char dummy_char;
- char buf[CMSG_SPACE(sizeof(int))];
- struct msghdr msg = {0};
struct iovec dummy_iov;
+ char dummy_char;
+ struct msghdr msg;
struct cmsghdr *cmsg;
+ union {
+ struct cmsghdr hdr;
+ unsigned char buf[CMSG_SPACE(sizeof(int))];
+ } cmsgbuf;
if (!PyArg_ParseTuple(args, "ii", &conn, &fd))
return NULL;
dummy_iov.iov_base = &dummy_char;
dummy_iov.iov_len = 1;
- msg.msg_control = buf;
- msg.msg_controllen = sizeof(buf);
+
+ memset(&msg, 0, sizeof(msg));
+ msg.msg_control = &cmsgbuf.buf;
+ msg.msg_controllen = sizeof(cmsgbuf.buf);
msg.msg_iov = &dummy_iov;
msg.msg_iovlen = 1;
+
cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_len = CMSG_LEN(sizeof(int));
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
- cmsg->cmsg_len = CMSG_LEN(sizeof(int));
- msg.msg_controllen = cmsg->cmsg_len;
* (int *) CMSG_DATA(cmsg) = fd;
Py_BEGIN_ALLOW_THREADS
@@ -127,20 +133,26 @@
{
int conn, fd, res;
char dummy_char;
- char buf[CMSG_SPACE(sizeof(int))];
- struct msghdr msg = {0};
struct iovec dummy_iov;
+ struct msghdr msg = {0};
struct cmsghdr *cmsg;
+ union {
+ struct cmsghdr hdr;
+ unsigned char buf[CMSG_SPACE(sizeof(int))];
+ } cmsgbuf;
if (!PyArg_ParseTuple(args, "i", &conn))
return NULL;
dummy_iov.iov_base = &dummy_char;
dummy_iov.iov_len = 1;
- msg.msg_control = buf;
- msg.msg_controllen = sizeof(buf);
+
+ memset(&msg, 0, sizeof(msg));
+ msg.msg_control = &cmsgbuf.buf;
+ msg.msg_controllen = sizeof(cmsgbuf.buf);
msg.msg_iov = &dummy_iov;
msg.msg_iovlen = 1;
+
cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
index d67cada..153ddcd 100644
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -4741,7 +4741,13 @@
if (!PyArg_ParseTuple(args, _Py_PARSE_PID "iO&:sched_setscheduler",
&pid, &policy, &convert_sched_param, ¶m))
return NULL;
- if (sched_setscheduler(pid, policy, ¶m))
+
+ /*
+ ** sched_setscheduler() returns 0 in Linux, but the previous
+ ** scheduling policy under Solaris/Illumos, and others.
+ ** On error, -1 is returned in all Operating Systems.
+ */
+ if (sched_setscheduler(pid, policy, ¶m) == -1)
return posix_error();
Py_RETURN_NONE;
}
@@ -11301,12 +11307,12 @@
#endif
#ifdef HAVE_SCHED_H
+ if (ins(d, "SCHED_OTHER", (long)SCHED_OTHER)) return -1;
if (ins(d, "SCHED_FIFO", (long)SCHED_FIFO)) return -1;
if (ins(d, "SCHED_RR", (long)SCHED_RR)) return -1;
#ifdef SCHED_SPORADIC
if (ins(d, "SCHED_SPORADIC", (long)SCHED_SPORADIC) return -1;
#endif
- if (ins(d, "SCHED_OTHER", (long)SCHED_OTHER)) return -1;
#ifdef SCHED_BATCH
if (ins(d, "SCHED_BATCH", (long)SCHED_BATCH)) return -1;
#endif
@@ -11316,6 +11322,18 @@
#ifdef SCHED_RESET_ON_FORK
if (ins(d, "SCHED_RESET_ON_FORK", (long)SCHED_RESET_ON_FORK)) return -1;
#endif
+#ifdef SCHED_SYS
+ if (ins(d, "SCHED_SYS", (long)SCHED_SYS)) return -1;
+#endif
+#ifdef SCHED_IA
+ if (ins(d, "SCHED_IA", (long)SCHED_IA)) return -1;
+#endif
+#ifdef SCHED_FSS
+ if (ins(d, "SCHED_FSS", (long)SCHED_FSS)) return -1;
+#endif
+#ifdef SCHED_FX
+ if (ins(d, "SCHED_FX", (long)SCHED_FSS)) return -1;
+#endif
#endif
#ifdef HAVE_ATTR_XATTR_H
diff --git a/Modules/zlibmodule.c b/Modules/zlibmodule.c
index f1f84e3..a6da056 100644
--- a/Modules/zlibmodule.c
+++ b/Modules/zlibmodule.c
@@ -1169,6 +1169,10 @@
if (ver != NULL)
PyModule_AddObject(m, "ZLIB_VERSION", ver);
+ ver = PyUnicode_FromString(zlibVersion());
+ if (ver != NULL)
+ PyModule_AddObject(m, "ZLIB_RUNTIME_VERSION", ver);
+
PyModule_AddStringConstant(m, "__version__", "1.0");
return m;
diff --git a/Objects/longobject.c b/Objects/longobject.c
index 8f6f18f..5a4259d 100644
--- a/Objects/longobject.c
+++ b/Objects/longobject.c
@@ -525,8 +525,8 @@
return x;
}
-/* Get a C unsigned long int from a long int object.
- Returns -1 and sets an error condition if overflow occurs. */
+/* Get a C size_t from a long int object. Returns (size_t)-1 and sets
+ an error condition if overflow occurs. */
size_t
PyLong_AsSize_t(PyObject *vv)
@@ -562,7 +562,7 @@
if ((x >> PyLong_SHIFT) != prev) {
PyErr_SetString(PyExc_OverflowError,
"Python int too large to convert to C size_t");
- return (unsigned long) -1;
+ return (size_t) -1;
}
}
return x;