diff --git a/Doc/c-api/exceptions.rst b/Doc/c-api/exceptions.rst index 535513229b5..f650cfdaada 100644 --- a/Doc/c-api/exceptions.rst +++ b/Doc/c-api/exceptions.rst @@ -280,9 +280,10 @@ in various ways. There is a separate error indicator for each thread. .. cfunction:: void PyErr_BadInternalCall() - This is a shorthand for ``PyErr_SetString(PyExc_TypeError, message)``, where - *message* indicates that an internal operation (e.g. a Python/C API function) - was invoked with an illegal argument. It is mostly for internal use. + This is a shorthand for ``PyErr_SetString(PyExc_SystemError, message)``, + where *message* indicates that an internal operation (e.g. a Python/C API + function) was invoked with an illegal argument. It is mostly for internal + use. .. cfunction:: int PyErr_WarnEx(PyObject *category, char *message, int stacklevel) diff --git a/Doc/c-api/init.rst b/Doc/c-api/init.rst index e2b2267a11a..b63ab9f7f74 100644 --- a/Doc/c-api/init.rst +++ b/Doc/c-api/init.rst @@ -350,18 +350,36 @@ Initialization, Finalization, and Threads single: Py_FatalError() single: argv (in module sys) - Set ``sys.argv`` based on *argc* and *argv*. These parameters are similar to - those passed to the program's :cfunc:`main` function with the difference that - the first entry should refer to the script file to be executed rather than the - executable hosting the Python interpreter. If there isn't a script that will be - run, the first entry in *argv* can be an empty string. If this function fails - to initialize ``sys.argv``, a fatal condition is signalled using - :cfunc:`Py_FatalError`. + Set :data:`sys.argv` based on *argc* and *argv*. These parameters are + similar to those passed to the program's :cfunc:`main` function with the + difference that the first entry should refer to the script file to be + executed rather than the executable hosting the Python interpreter. If there + isn't a script that will be run, the first entry in *argv* can be an empty + string. If this function fails to initialize :data:`sys.argv`, a fatal + condition is signalled using :cfunc:`Py_FatalError`. + + This function also prepends the executed script's path to :data:`sys.path`. + If no script is executed (in the case of calling ``python -c`` or just the + interactive interpreter), the empty string is used instead. .. XXX impl. doesn't seem consistent in allowing 0/NULL for the params; check w/ Guido. +.. cfunction:: void Py_SetPythonHome(char *home) + + Set the default "home" directory, that is, the location of the standard + Python libraries. The libraries are searched in + :file:`{home}/lib/python{version}` and :file:`{home}/lib/python{version}`. + + +.. cfunction:: char* Py_GetPythonHome() + + Return the default "home", that is, the value set by a previous call to + :cfunc:`Py_SetPythonHome`, or the value of the :envvar:`PYTHONHOME` + environment variable if it is set. + + .. _threads: Thread State and the Global Interpreter Lock diff --git a/Doc/library/ctypes.rst b/Doc/library/ctypes.rst index 47f9819b4fc..e389a633315 100644 --- a/Doc/library/ctypes.rst +++ b/Doc/library/ctypes.rst @@ -1272,6 +1272,7 @@ library to load. .. data:: find_library(name) + :module: ctypes.util :noindex: Try to find a library and return a pathname. *name* is the library name without diff --git a/Doc/library/optparse.rst b/Doc/library/optparse.rst index 4e9bb2384a4..2cf804226e1 100644 --- a/Doc/library/optparse.rst +++ b/Doc/library/optparse.rst @@ -1506,7 +1506,7 @@ Here's an example of a callback option that takes no arguments, and simply records that the option was seen:: def record_foo_seen(option, opt_str, value, parser): - parser.saw_foo = True + parser.values.saw_foo = True parser.add_option("--foo", action="callback", callback=record_foo_seen) @@ -1646,7 +1646,7 @@ arguments:: value.append(arg) del parser.rargs[:len(value)] - setattr(parser.values, option.dest, value)) + setattr(parser.values, option.dest, value) [...] parser.add_option("-c", "--callback", dest="vararg_attr", diff --git a/Doc/library/threading.rst b/Doc/library/threading.rst index 769afd4ffec..609056869bd 100644 --- a/Doc/library/threading.rst +++ b/Doc/library/threading.rst @@ -198,7 +198,7 @@ changed through the :attr:`name` attribute. A thread can be flagged as a "daemon thread". The significance of this flag is that the entire Python program exits when only daemon threads are left. The initial value is inherited from the creating thread. The flag can be set -through the :attr:`daemon` attribute. +through the :attr:`daemon` property. There is a "main thread" object; this corresponds to the initial thread of control in the Python program. It is not a daemon thread. @@ -312,10 +312,11 @@ impossible to detect the termination of alien threads. .. attribute:: Thread.daemon - The thread's daemon flag. This must be set before :meth:`start` is called, - otherwise :exc:`RuntimeError` is raised. - - The initial value is inherited from the creating thread. + A boolean value indicating whether this thread is a daemon thread (True) or + not (False). This must be set before :meth:`start` is called, otherwise + :exc:`RuntimeError` is raised. Its initial value is inherited from the + creating thread; the main thread is not a daemon thread and therefore all + threads created in the main thread default to :attr:`daemon` = ``False``. The entire Python program exits when no alive non-daemon threads are left. diff --git a/Doc/tools/sphinxext/download.html b/Doc/tools/sphinxext/download.html index 0de9c2a0627..22a03a0d2fb 100644 --- a/Doc/tools/sphinxext/download.html +++ b/Doc/tools/sphinxext/download.html @@ -31,7 +31,7 @@

Download Python {{ release }} Documentation

Download (ca. 4 MB) Plain Text - Download (ca. 2 MB) + Download (ca. 2 MB) Download (ca. 1.5 MB) diff --git a/Doc/tools/sphinxext/pyspecific.py b/Doc/tools/sphinxext/pyspecific.py index 66a0afc2949..be0da34683a 100644 --- a/Doc/tools/sphinxext/pyspecific.py +++ b/Doc/tools/sphinxext/pyspecific.py @@ -13,6 +13,14 @@ from docutils import nodes, utils +# monkey-patch reST parser to disable alphabetic and roman enumerated lists +from docutils.parsers.rst.states import Body +Body.enum.converters['loweralpha'] = \ + Body.enum.converters['upperalpha'] = \ + Body.enum.converters['lowerroman'] = \ + Body.enum.converters['upperroman'] = lambda x: None + + def issue_role(typ, rawtext, text, lineno, inliner, options={}, content=[]): issue = utils.unescape(text) text = 'issue ' + issue diff --git a/Doc/tutorial/floatingpoint.rst b/Doc/tutorial/floatingpoint.rst index a38a53ef5ad..f41be3a038e 100644 --- a/Doc/tutorial/floatingpoint.rst +++ b/Doc/tutorial/floatingpoint.rst @@ -200,7 +200,7 @@ Why is that? 1/10 is not exactly representable as a binary fraction. Almost all machines today (November 2000) use IEEE-754 floating point arithmetic, and almost all platforms map Python floats to IEEE-754 "double precision". 754 doubles contain 53 bits of precision, so on input the computer strives to -convert 0.1 to the closest fraction it can of the form *J*/2\*\**N* where *J* is +convert 0.1 to the closest fraction it can of the form *J*/2**\ *N* where *J* is an integer containing exactly 53 bits. Rewriting :: 1 / 10 ~= J / (2**N) diff --git a/Doc/whatsnew/2.7.rst b/Doc/whatsnew/2.7.rst index 6c65d0b5d26..77fe3a2d542 100644 --- a/Doc/whatsnew/2.7.rst +++ b/Doc/whatsnew/2.7.rst @@ -197,6 +197,23 @@ changes, or look through the Subversion logs for all the details. .. ====================================================================== .. whole new modules get described in subsections here +ttk: Themed Widgets for Tk +-------------------------- + +Tcl/Tk 8.5 includes a set of themed widgets that re-implement basic Tk +widgets but have a more customizable appearance and can therefore more +closely resemble the native platform's widgets. This widget +set was originally called Tile, but was renamed to Ttk (for "themed Tk") +on being added to Tcl/Tck release 8.5. + +XXX write a brief discussion and an example here. + +The :mod:`ttk` module was written by Guilherme Polo and added in +:issue:`2983`. An alternate version called ``Tile.py``, written by +Martin Franklin and maintained by Kevin Walzer, was proposed for +inclusion in :issue:`2618`, but the authors argued that Guilherme +Polo's work was more comprehensive. + .. ====================================================================== diff --git a/Lib/heapq.py b/Lib/heapq.py index ff4fc03bf62..529fc2b5e71 100644 --- a/Lib/heapq.py +++ b/Lib/heapq.py @@ -195,7 +195,7 @@ def nlargest(n, iterable): heapify(result) _heappushpop = heappushpop for elem in it: - heappushpop(result, elem) + _heappushpop(result, elem) result.sort(reverse=True) return result diff --git a/Lib/test/test_hash.py b/Lib/test/test_hash.py index 5881d03c514..4cbbe78424e 100644 --- a/Lib/test/test_hash.py +++ b/Lib/test/test_hash.py @@ -33,6 +33,7 @@ def test_coerced_integers(self): # for 64-bit platforms self.same_hash(int(2**31), float(2**31)) self.same_hash(int(-2**63), float(-2**63)) + self.same_hash(long(2**63), float(2**63)) def test_coerced_floats(self): self.same_hash(int(1.23e300), float(1.23e300)) diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py index baaf33ad2cc..51663e16fa8 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -3,6 +3,7 @@ # portable than they had been thought to be. import os +import errno import unittest import warnings import sys @@ -277,7 +278,6 @@ def test_statvfs_attributes(self): result = os.statvfs(self.fname) except OSError as e: # On AtheOS, glibc always returns ENOSYS - import errno if e.errno == errno.ENOSYS: return @@ -601,7 +601,13 @@ def helper(self): locals()["test_"+f] = get_single(f) def check(self, f, *args): - self.assertRaises(OSError, f, support.make_bad_fd(), *args) + try: + f(support.make_bad_fd(), *args) + except OSError as e: + self.assertEqual(e.errno, errno.EBADF) + else: + self.fail("%r didn't raise a OSError with a bad file descriptor" + % f) def test_isatty(self): if hasattr(os, "isatty"): diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py index 731827c84b9..429ec6f978d 100644 --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -366,6 +366,9 @@ def testGetServBy(self): eq(socket.getservbyport(port, 'tcp'), service) if udpport is not None: eq(socket.getservbyport(udpport, 'udp'), service) + # Make sure getservbyport does not accept out of range ports. + self.assertRaises(OverflowError, socket.getservbyport, -1) + self.assertRaises(OverflowError, socket.getservbyport, 65536) def testDefaultTimeout(self): # Testing default timeout @@ -466,15 +469,23 @@ def testStringToIPv6(self): # XXX The following don't test module-level functionality... - def testSockName(self): - # Testing getsockname(). Use a temporary socket to elicit an unused - # ephemeral port that we can use later in the test. - tempsock = socket.socket() - tempsock.bind(("0.0.0.0", 0)) - (host, port) = tempsock.getsockname() - tempsock.close() - del tempsock + def _get_unused_port(self, bind_address='0.0.0.0'): + """Use a temporary socket to elicit an unused ephemeral port. + Args: + bind_address: Hostname or IP address to search for a port on. + + Returns: A most likely to be unused port. + """ + tempsock = socket.socket() + tempsock.bind((bind_address, 0)) + host, port = tempsock.getsockname() + tempsock.close() + return port + + def testSockName(self): + # Testing getsockname() + port = self._get_unused_port() sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.bind(("0.0.0.0", port)) name = sock.getsockname() @@ -514,6 +525,19 @@ def testNewAttributes(self): self.assertEqual(sock.proto, 0) sock.close() + def test_getsockaddrarg(self): + host = '0.0.0.0' + port = self._get_unused_port(bind_address=host) + big_port = port + 65536 + neg_port = port - 65536 + sock = socket.socket() + try: + self.assertRaises(OverflowError, sock.bind, (host, big_port)) + self.assertRaises(OverflowError, sock.bind, (host, neg_port)) + sock.bind((host, port)) + finally: + sock.close() + def test_sock_ioctl(self): if os.name != "nt": return diff --git a/Lib/test/test_tcl.py b/Lib/test/test_tcl.py index fa1727c81f2..4d92b268b8e 100644 --- a/Lib/test/test_tcl.py +++ b/Lib/test/test_tcl.py @@ -4,9 +4,15 @@ import os import _tkinter from test import support -from tkinter import Tcl +from tkinter import Tk, Tcl from _tkinter import TclError +# Restore Tkinter.Tk._loadtk that may have been overridden by ttk. +# If this is not done then this test may fail for reasons related +# to ttk only (like failing to load the tile package). +from ttk import __loadtk__ +Tk._loadtk = __loadtk__ + class TkinterTest(unittest.TestCase): diff --git a/Misc/NEWS b/Misc/NEWS index b6e06d79b07..cd60fa39d98 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -382,6 +382,10 @@ Library - Issue #4861: ctypes.util.find_library(): Robustify. Fix library detection on biarch systems. Try to rely on ldconfig only, without using objdump and gcc. +- Issue #5104: The socket module now raises OverflowError when 16-bit port and + protocol numbers are supplied outside the allowed 0-65536 range on bind() + and getservbyport(). + Tools/Demos ----------- diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index a302dc5fa3a..f9f486e6315 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -1223,6 +1223,12 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args, PyMem_Free(host); if (result < 0) return 0; + if (port < 0 || port > 0xffff) { + PyErr_SetString( + PyExc_OverflowError, + "getsockaddrarg: port must be 0-65535."); + return 0; + } addr->sin_family = AF_INET; addr->sin_port = htons((short)port); *len_ret = sizeof *addr; @@ -1255,6 +1261,12 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args, PyMem_Free(host); if (result < 0) return 0; + if (port < 0 || port > 0xffff) { + PyErr_SetString( + PyExc_OverflowError, + "getsockaddrarg: port must be 0-65535."); + return 0; + } addr->sin6_family = s->sock_family; addr->sin6_port = htons((short)port); addr->sin6_flowinfo = flowinfo; @@ -1381,6 +1393,12 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args, "Hardware address must be 8 bytes or less"); return 0; } + if (protoNumber < 0 || protoNumber > 0xffff) { + PyErr_SetString( + PyExc_OverflowError, + "getsockaddrarg: protoNumber must be 0-65535."); + return 0; + } addr = (struct sockaddr_ll*)addr_ret; addr->sll_family = AF_PACKET; addr->sll_protocol = htons((short)protoNumber); @@ -3271,13 +3289,19 @@ otherwise any protocol will match."); static PyObject * socket_getservbyport(PyObject *self, PyObject *args) { - unsigned short port; + int port; char *proto=NULL; struct servent *sp; - if (!PyArg_ParseTuple(args, "H|s:getservbyport", &port, &proto)) + if (!PyArg_ParseTuple(args, "i|s:getservbyport", &port, &proto)) return NULL; + if (port < 0 || port > 0xffff) { + PyErr_SetString( + PyExc_OverflowError, + "getservbyport: port must be 0-65535."); + return NULL; + } Py_BEGIN_ALLOW_THREADS - sp = getservbyport(htons(port), proto); + sp = getservbyport(htons((short)port), proto); Py_END_ALLOW_THREADS if (sp == NULL) { PyErr_SetString(socket_error, "port/proto not found"); diff --git a/Python/compile.c b/Python/compile.c index 7c44f091cef..38b4aa4ecaf 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -4006,6 +4006,8 @@ dict_keys_inorder(PyObject *dict, int offset) return NULL; while (PyDict_Next(dict, &pos, &k, &v)) { i = PyLong_AS_LONG(v); + /* The keys of the dictionary are tuples. (see compiler_add_o) + The object we want is always first, though. */ k = PyTuple_GET_ITEM(k, 0); Py_INCREF(k); assert((i - offset) < size); @@ -4029,13 +4031,11 @@ compute_code_flags(struct compiler *c) flags |= CO_NESTED; if (ste->ste_generator) flags |= CO_GENERATOR; + if (ste->ste_varargs) + flags |= CO_VARARGS; + if (ste->ste_varkeywords) + flags |= CO_VARKEYWORDS; } - if (ste->ste_varargs) - flags |= CO_VARARGS; - if (ste->ste_varkeywords) - flags |= CO_VARKEYWORDS; - if (ste->ste_generator) - flags |= CO_GENERATOR; /* (Only) inherit compilerflags in PyCF_MASK */ flags |= (c->c_flags->cf_flags & PyCF_MASK);