diff options
-rw-r--r-- | Doc/howto/descriptor.rst | 2 | ||||
-rw-r--r-- | Doc/library/logging.handlers.rst | 8 | ||||
-rw-r--r-- | Doc/library/smtplib.rst | 18 | ||||
-rw-r--r-- | Doc/library/stdtypes.rst | 16 | ||||
-rw-r--r-- | Doc/reference/expressions.rst | 2 | ||||
-rw-r--r-- | Lib/smtplib.py | 32 | ||||
-rw-r--r-- | Lib/test/test_smtplib.py | 17 | ||||
-rw-r--r-- | Lib/test/test_smtpnet.py | 8 | ||||
-rw-r--r-- | Lib/test/test_urllib2net.py | 24 | ||||
-rw-r--r-- | Makefile.pre.in | 54 | ||||
-rw-r--r-- | Modules/_cursesmodule.c | 4 | ||||
-rw-r--r-- | setup.py | 6 |
12 files changed, 115 insertions, 76 deletions
diff --git a/Doc/howto/descriptor.rst b/Doc/howto/descriptor.rst index 81bb8ca..1616f67 100644 --- a/Doc/howto/descriptor.rst +++ b/Doc/howto/descriptor.rst @@ -42,7 +42,7 @@ classes (a class is new style if it inherits from :class:`object` or Descriptors are a powerful, general purpose protocol. They are the mechanism behind properties, methods, static methods, class methods, and :func:`super()`. -They are used used throughout Python itself to implement the new style classes +They are used throughout Python itself to implement the new style classes introduced in version 2.2. Descriptors simplify the underlying C-code and offer a flexible set of new tools for everyday Python programs. diff --git a/Doc/library/logging.handlers.rst b/Doc/library/logging.handlers.rst index 82e3969..27d2efd 100644 --- a/Doc/library/logging.handlers.rst +++ b/Doc/library/logging.handlers.rst @@ -623,7 +623,7 @@ The :class:`SMTPHandler` class, located in the :mod:`logging.handlers` module, supports sending logging messages to an email address via SMTP. -.. class:: SMTPHandler(mailhost, fromaddr, toaddrs, subject, credentials=None) +.. class:: SMTPHandler(mailhost, fromaddr, toaddrs, subject, credentials=None, secure=None) Returns a new instance of the :class:`SMTPHandler` class. The instance is initialized with the from and to addresses and subject line of the email. The @@ -632,6 +632,12 @@ supports sending logging messages to an email address via SMTP. the standard SMTP port is used. If your SMTP server requires authentication, you can specify a (username, password) tuple for the *credentials* argument. + To specify the use of a secure protocol (TLS), pass in a tuple to the + *secure* argument. This will only be used when authentication credentials are + supplied. The tuple should be either an empty tuple, or a single-value tuple + with the name of a keyfile, or a 2-value tuple with the names of the keyfile + and certificate file. (This tuple is passed to the + :meth:`smtplib.SMTP.starttls` method.) .. method:: emit(record) diff --git a/Doc/library/smtplib.rst b/Doc/library/smtplib.rst index 4a0f756..7dd038d 100644 --- a/Doc/library/smtplib.rst +++ b/Doc/library/smtplib.rst @@ -31,9 +31,9 @@ Protocol) and :rfc:`1869` (SMTP Service Extensions). like the connection attempt (if not specified, the global default timeout setting will be used). The optional source_address parameter allows to bind to some specific source address in a machine with multiple network interfaces, - and/or to some specific source tcp port. It takes a 2-tuple (host, port), + and/or to some specific source TCP port. It takes a 2-tuple (host, port), for the socket to bind to as its source address before connecting. If - ommited (or if host or port are '' and/or 0 respectively) the OS default + omitted (or if host or port are ``''`` and/or 0 respectively) the OS default behavior will be used. For normal use, you should only require the initialization/connect, @@ -53,8 +53,8 @@ Protocol) and :rfc:`1869` (SMTP Service Extensions). .. versionchanged:: 3.3 Support for the :keyword:`with` statement was added. - .. versionadded:: 3.3 - source_address parameter. + .. versionchanged:: 3.3 + source_address argument was added. .. class:: SMTP_SSL(host='', port=0, local_hostname=None, keyfile=None, certfile=None[, timeout], context=None, source_address=None) @@ -73,14 +73,14 @@ Protocol) and :rfc:`1869` (SMTP Service Extensions). specific source address in a machine with multiple network interfaces, and/or to some specific source tcp port. It takes a 2-tuple (host, port), for the socket to bind to as its source address before connecting. If - ommited (or if host or port are '' and/or 0 respectively) the OS default + omitted (or if host or port are ``''`` and/or 0 respectively) the OS default behavior will be used. .. versionchanged:: 3.3 *context* was added. - .. versionadded:: 3.3 - source_address parameter. + .. versionchanged:: 3.3 + source_address argument was added. .. class:: LMTP(host='', port=LMTP_PORT, local_hostname=None, source_address=None) @@ -88,8 +88,8 @@ Protocol) and :rfc:`1869` (SMTP Service Extensions). The LMTP protocol, which is very similar to ESMTP, is heavily based on the standard SMTP client. It's common to use Unix sockets for LMTP, so our :meth:`connect` method must support that as well as a regular host:port - server. The optional parameters local_hostname and source_address has the - same meaning as that of SMTP client.To specify a Unix socket, you must use + server. The optional arguments local_hostname and source_address have the + same meaning as that of SMTP client. To specify a Unix socket, you must use an absolute path for *host*, starting with a '/'. Authentication is supported, using the regular SMTP mechanism. When using a Unix diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index 5660224..8a117ba 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -2706,7 +2706,7 @@ The Null Object This object is returned by functions that don't explicitly return a value. It supports no special operations. There is exactly one null object, named -``None`` (a built-in name). +``None`` (a built-in name). ``type(None)()`` produces the same singleton. It is written as ``None``. @@ -2718,11 +2718,23 @@ The Ellipsis Object This object is commonly used by slicing (see :ref:`slicings`). It supports no special operations. There is exactly one ellipsis object, named -:const:`Ellipsis` (a built-in name). +:const:`Ellipsis` (a built-in name). ``type(Ellipsis)()`` produces the +:const:`Ellipsis` singleton. It is written as ``Ellipsis`` or ``...``. +The NotImplemented Object +------------------------- + +This object is returned from comparisons and binary operations when they are +asked to operate on types they don't support. See :ref:`comparisons` for more +information. There is exactly one ``NotImplemented`` object. +``type(NotImplemented)()`` produces the singleton instance. + +It is written as ``NotImplemented``. + + Boolean Values -------------- diff --git a/Doc/reference/expressions.rst b/Doc/reference/expressions.rst index d85a9c6..655ebde 100644 --- a/Doc/reference/expressions.rst +++ b/Doc/reference/expressions.rst @@ -673,7 +673,7 @@ there were no excess keyword arguments. If the syntax ``*expression`` appears in the function call, ``expression`` must evaluate to an iterable. Elements from this iterable are treated as if they were additional positional arguments; if there are positional arguments -*x1*, ... ,*xN*, and ``expression`` evaluates to a sequence *y1*, ..., *yM*, +*x1*, ..., *xN*, and ``expression`` evaluates to a sequence *y1*, ..., *yM*, this is equivalent to a call with M+N positional arguments *x1*, ..., *xN*, *y1*, ..., *yM*. diff --git a/Lib/smtplib.py b/Lib/smtplib.py index 2039592..a4c0d89 100644 --- a/Lib/smtplib.py +++ b/Lib/smtplib.py @@ -282,7 +282,8 @@ class SMTP: # This makes it simpler for SMTP_SSL to use the SMTP connect code # and just alter the socket connection bit. if self.debuglevel > 0: - print('connect: to', (host, port), self.source_address, file=stderr) + print('connect: to', (host, port), self.source_address, + file=stderr) return socket.create_connection((host, port), timeout, self.source_address) @@ -297,7 +298,10 @@ class SMTP: specified during instantiation. """ - if source_address: self.source_address = source_address + + if source_address: + self.source_address = source_address + if not port and (host.find(':') == host.rfind(':')): i = host.rfind(':') if i >= 0: @@ -381,7 +385,8 @@ class SMTP: errmsg = b"\n".join(resp) if self.debuglevel > 0: - print('reply: retcode (%s); Msg: %s' % (errcode, errmsg), file=stderr) + print('reply: retcode (%s); Msg: %s' % (errcode, errmsg), + file=stderr) return errcode, errmsg def docmd(self, cmd, args=""): @@ -788,7 +793,8 @@ class SMTP: # TODO implement heuristics to guess the correct Resent-* block with an # option allowing the user to enable the heuristics. (It should be # possible to guess correctly almost all of the time.) - resent =msg.get_all('Resent-Date') + + resent = msg.get_all('Resent-Date') if resent is None: header_prefix = '' elif len(resent) == 1: @@ -797,13 +803,13 @@ class SMTP: raise ValueError("message has more than one 'Resent-' header block") if from_addr is None: # Prefer the sender field per RFC 2822:3.6.2. - from_addr = (msg[header_prefix+'Sender'] - if (header_prefix+'Sender') in msg - else msg[header_prefix+'From']) + from_addr = (msg[header_prefix + 'Sender'] + if (header_prefix + 'Sender') in msg + else msg[header_prefix + 'From']) if to_addrs is None: - addr_fields = [f for f in (msg[header_prefix+'To'], - msg[header_prefix+'Bcc'], - msg[header_prefix+'Cc']) if f is not None] + addr_fields = [f for f in (msg[header_prefix + 'To'], + msg[header_prefix + 'Bcc'], + msg[header_prefix + 'Cc']) if f is not None] to_addrs = [a[1] for a in email.utils.getaddresses(addr_fields)] # Make a local copy so we can delete the bcc headers. msg_copy = copy.copy(msg) @@ -899,13 +905,13 @@ class LMTP(SMTP): def __init__(self, host='', port=LMTP_PORT, local_hostname=None, source_address=None): """Initialize a new instance.""" - SMTP.__init__(self, host, port, local_hostname = local_hostname, - source_address = source_address) + SMTP.__init__(self, host, port, local_hostname=local_hostname, + source_address=source_address) def connect(self, host='localhost', port=0, source_address=None): """Connect to the LMTP daemon, on either a Unix or a TCP socket.""" if host[0] != '/': - return SMTP.connect(self, host, port, source_address = source_address) + return SMTP.connect(self, host, port, source_address=source_address) # Handle Unix-domain sockets. try: diff --git a/Lib/test/test_smtplib.py b/Lib/test/test_smtplib.py index 70654c5..969ff15 100644 --- a/Lib/test/test_smtplib.py +++ b/Lib/test/test_smtplib.py @@ -216,12 +216,17 @@ class DebuggingServerTests(unittest.TestCase): def testSourceAddress(self): # connect - smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', timeout=3, - source_address=('127.0.0.1', 19876)) - self.assertEqual(smtp.source_address, ('127.0.0.1', 19876)) - self.assertEqual(smtp.local_hostname, 'localhost') - print(dir(smtp)) - smtp.quit() + port = support.find_unused_port() + try: + smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', + timeout=3, source_address=('127.0.0.1', port)) + self.assertEqual(smtp.source_address, ('127.0.0.1', port)) + self.assertEqual(smtp.local_hostname, 'localhost') + smtp.quit() + except IOError as e: + if e.errno == errno.EADDRINUSE: + self.skipTest("couldn't bind to port %d" % port) + raise def testNOOP(self): smtp = smtplib.SMTP(HOST, self.port, local_hostname='localhost', timeout=3) diff --git a/Lib/test/test_smtpnet.py b/Lib/test/test_smtpnet.py index 7d0fa98..86224ef 100644 --- a/Lib/test/test_smtpnet.py +++ b/Lib/test/test_smtpnet.py @@ -18,7 +18,13 @@ class SmtpTest(unittest.TestCase): support.get_attribute(smtplib, 'SMTP_SSL') with support.transient_internet(self.testServer): server = smtplib.SMTP(self.testServer, self.remotePort) - server.starttls(context=self.context) + try: + server.starttls(context=self.context) + except smtplib.SMTPException as e: + if e.args[0] == 'STARTTLS extension not supported by server.': + unittest.skip(e.args[0]) + else: + raise server.ehlo() server.quit() diff --git a/Lib/test/test_urllib2net.py b/Lib/test/test_urllib2net.py index cd225c9..54f4e0c 100644 --- a/Lib/test/test_urllib2net.py +++ b/Lib/test/test_urllib2net.py @@ -178,17 +178,21 @@ class OtherNetworkTests(unittest.TestCase): # Some sites do not send Connection: close header. # Verify that those work properly. (#issue12576) - try: - with urllib.request.urlopen('http://www.imdb.com') as res: - pass - except ValueError as e: - self.fail("urlopen failed for sites not sending Connection:close") - else: - self.assertTrue(res) + URL = 'http://www.imdb.com' # mangles Connection:close + + with support.transient_internet(URL): + try: + with urllib.request.urlopen(URL) as res: + pass + except ValueError as e: + self.fail("urlopen failed for site not sending \ + Connection:close") + else: + self.assertTrue(res) - req = urllib.request.urlopen('http://www.imdb.com') - res = req.read() - self.assertTrue(res) + req = urllib.request.urlopen(URL) + res = req.read() + self.assertTrue(res) def _test_urls(self, urls, handlers, retry=True): import time diff --git a/Makefile.pre.in b/Makefile.pre.in index c2b1a11..0c7b180 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -747,45 +747,41 @@ $(LIBRARY_OBJS) $(MODOBJS) Modules/python.o: $(PYTHON_HEADERS) ###################################################################### -# Test the interpreter (twice, once without .pyc files, once with) -# In the past, we've had problems where bugs in the marshalling or -# elsewhere caused bytecode read from .pyc files to behave differently -# than bytecode generated directly from a .py source file. Sometimes -# the bytecode read from a .pyc file had the bug, somtimes the directly -# generated bytecode. This is sometimes a very shy bug needing a lot of -# sample data. - -TESTOPTS= -l $(EXTRATESTOPTS) +# Run a basic set of regression tests. +# This excludes some tests that are particularly resource-intensive. +TESTOPTS= $(EXTRATESTOPTS) TESTPROG= $(srcdir)/Lib/test/regrtest.py TESTPYTHON= $(RUNSHARED) ./$(BUILDPYTHON) -Wd -E -bb $(TESTPYTHONOPTS) TESTTIMEOUT= 3600 test: all platform - -find $(srcdir)/Lib -name '*.py[co]' -print | xargs rm -f - -$(TESTPYTHON) $(TESTPROG) $(TESTOPTS) - $(TESTPYTHON) $(TESTPROG) $(TESTOPTS) + $(TESTPYTHON) $(TESTPROG) -j0 $(TESTOPTS) +# Run the full test suite twice - once without .pyc files, and once with. +# In the past, we've had problems where bugs in the marshalling or +# elsewhere caused bytecode read from .pyc files to behave differently +# than bytecode generated directly from a .py source file. Sometimes +# the bytecode read from a .pyc file had the bug, sometimes the directly +# generated bytecode. This is sometimes a very shy bug needing a lot of +# sample data. testall: all platform -find $(srcdir)/Lib -name '*.py[co]' -print | xargs rm -f $(TESTPYTHON) $(srcdir)/Lib/compileall.py -find $(srcdir)/Lib -name '*.py[co]' -print | xargs rm -f - -$(TESTPYTHON) $(TESTPROG) -uall $(TESTOPTS) - $(TESTPYTHON) $(TESTPROG) -uall $(TESTOPTS) + -$(TESTPYTHON) $(TESTPROG) -j0 -uall $(TESTOPTS) + $(TESTPYTHON) $(TESTPROG) -j0 -uall $(TESTOPTS) -# Run the unitests for both architectures in a Universal build on OSX -# Must be run on an Intel box. +# Run the test suite for both architectures in a Universal build on OSX. +# Must be run on an Intel box. testuniversal: all platform if [ `arch` != 'i386' ];then \ echo "This can only be used on OSX/i386" ;\ exit 1 ;\ fi - -find $(srcdir)/Lib -name '*.py[co]' -print | xargs rm -f - -$(TESTPYTHON) $(TESTPROG) -uall $(TESTOPTS) - $(TESTPYTHON) $(TESTPROG) -uall $(TESTOPTS) - $(RUNSHARED) /usr/libexec/oah/translate ./$(BUILDPYTHON) -E $(TESTPROG) -uall $(TESTOPTS) - + $(TESTPYTHON) $(TESTPROG) -j0 -uall $(TESTOPTS) + $(RUNSHARED) /usr/libexec/oah/translate ./$(BUILDPYTHON) -E $(TESTPROG) -j0 -uall $(TESTOPTS) -# Like testall, but with a single pass only -# run an optional script to include some information about the build environment +# Like testall, but with only one pass. +# Run an optional script to include information about the build environment. buildbottest: all platform -@if which pybuildbot.identify >/dev/null 2>&1; then \ pybuildbot.identify "CC='$(CC)'" "CXX='$(CXX)'"; \ @@ -798,15 +794,9 @@ QUICKTESTOPTS= $(TESTOPTS) -x test_subprocess test_io test_lib2to3 \ test_select test_zipfile quicktest: all platform -find $(srcdir)/Lib -name '*.py[co]' -print | xargs rm -f - -$(TESTPYTHON) $(TESTPROG) $(QUICKTESTOPTS) - $(TESTPYTHON) $(TESTPROG) $(QUICKTESTOPTS) + -$(TESTPYTHON) $(TESTPROG) -j0 $(QUICKTESTOPTS) + $(TESTPYTHON) $(TESTPROG) -j0 $(QUICKTESTOPTS) -MEMTESTOPTS= $(QUICKTESTOPTS) -x test_dl test___all__ test_fork1 \ - test_longexp -memtest: all platform - -rm -f $(srcdir)/Lib/test/*.py[co] - -$(TESTPYTHON) $(TESTPROG) $(MEMTESTOPTS) - $(TESTPYTHON) $(TESTPROG) $(MEMTESTOPTS) install: altinstall bininstall @@ -1381,7 +1371,7 @@ patchcheck: Python/thread.o: @THREADHEADERS@ # Declare targets that aren't real files -.PHONY: all build_all sharedmods oldsharedmods test quicktest memtest +.PHONY: all build_all sharedmods oldsharedmods test quicktest .PHONY: install altinstall oldsharedinstall bininstall altbininstall .PHONY: maninstall libinstall inclinstall libainstall sharedinstall .PHONY: frameworkinstall frameworkinstallframework frameworkinstallstructure diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index 9e57cd9..6d72024 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -906,6 +906,7 @@ PyCursesWindow_GetKey(PyCursesWindowObject *self, PyObject *args) } } +#ifdef HAVE_NCURSESW static PyObject * PyCursesWindow_Get_WCh(PyCursesWindowObject *self, PyObject *args) { @@ -937,6 +938,7 @@ PyCursesWindow_Get_WCh(PyCursesWindowObject *self, PyObject *args) } return PyLong_FromLong(rtn); } +#endif static PyObject * PyCursesWindow_GetStr(PyCursesWindowObject *self, PyObject *args) @@ -1636,7 +1638,9 @@ static PyMethodDef PyCursesWindow_Methods[] = { {"getbkgd", (PyCFunction)PyCursesWindow_GetBkgd, METH_NOARGS}, {"getch", (PyCFunction)PyCursesWindow_GetCh, METH_VARARGS}, {"getkey", (PyCFunction)PyCursesWindow_GetKey, METH_VARARGS}, +#ifdef HAVE_NCURSESW {"get_wch", (PyCFunction)PyCursesWindow_Get_WCh, METH_VARARGS}, +#endif {"getmaxyx", (PyCFunction)PyCursesWindow_getmaxyx, METH_NOARGS}, {"getparyx", (PyCFunction)PyCursesWindow_getparyx, METH_NOARGS}, {"getstr", (PyCFunction)PyCursesWindow_GetStr, METH_VARARGS}, @@ -1161,6 +1161,10 @@ class PyBuildExt(build_ext): else: missing.extend(['nis', 'resource', 'termios']) + curses_defines = [] + if curses_library == 'ncursesw': + curses_defines.append(('HAVE_NCURSESW', '1')) + # Curses support, requiring the System V version of curses, often # provided by the ncurses library. panel_library = 'panel' @@ -1171,6 +1175,7 @@ class PyBuildExt(build_ext): panel_library = 'panelw' curses_libs = [curses_library] exts.append( Extension('_curses', ['_cursesmodule.c'], + define_macros=curses_defines, libraries = curses_libs) ) elif curses_library == 'curses' and platform != 'darwin': # OSX has an old Berkeley curses, not good enough for @@ -1183,6 +1188,7 @@ class PyBuildExt(build_ext): curses_libs = ['curses'] exts.append( Extension('_curses', ['_cursesmodule.c'], + define_macros=curses_defines, libraries = curses_libs) ) else: missing.append('_curses') |