summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Doc/faq/programming.rst4
-rw-r--r--Doc/glossary.rst5
-rw-r--r--Doc/howto/regex.rst49
-rw-r--r--Doc/library/argparse.rst2
-rw-r--r--Doc/library/ftplib.rst8
-rw-r--r--Doc/library/imp.rst16
-rw-r--r--Doc/library/itertools.rst3
-rw-r--r--Doc/library/poplib.rst2
-rw-r--r--Doc/library/smtplib.rst3
-rw-r--r--Doc/library/socket.rst12
-rw-r--r--Doc/library/socketserver.rst4
-rw-r--r--Doc/reference/compound_stmts.rst18
-rw-r--r--Doc/reference/expressions.rst28
-rw-r--r--Doc/using/windows.rst2
-rw-r--r--Lib/SocketServer.py7
-rw-r--r--Lib/aifc.py38
-rwxr-xr-xLib/cgi.py1
-rw-r--r--Lib/ctypes/test/test_bitfields.py8
-rw-r--r--Lib/curses/__init__.py2
-rw-r--r--Lib/idlelib/ColorDelegator.py9
-rw-r--r--Lib/idlelib/EditorWindow.py12
-rw-r--r--Lib/idlelib/FormatParagraph.py3
-rw-r--r--Lib/idlelib/configDialog.py11
-rw-r--r--Lib/idlelib/configHandler.py51
-rw-r--r--Lib/multiprocessing/connection.py21
-rw-r--r--Lib/socket.py4
-rw-r--r--Lib/ssl.py20
-rw-r--r--Lib/subprocess.py4
-rwxr-xr-xLib/test/regrtest.py4
-rw-r--r--Lib/test/test_aifc.py7
-rw-r--r--Lib/test/test_builtin.py2
-rw-r--r--Lib/test/test_calendar.py2
-rw-r--r--Lib/test/test_glob.py101
-rw-r--r--Lib/test/test_import.py41
-rw-r--r--Lib/test/test_int.py63
-rw-r--r--Lib/test/test_long.py6
-rw-r--r--Lib/test/test_multiprocessing.py1
-rw-r--r--Lib/test/test_mutex.py2
-rw-r--r--Lib/test/test_socket.py60
-rw-r--r--Lib/test/test_ssl.py28
-rw-r--r--Lib/test/test_tarfile.py29
-rw-r--r--Lib/test/test_urllib2.py36
-rw-r--r--Lib/test/test_urllib2_localnet.py8
-rw-r--r--Lib/test/test_urlparse.py33
-rw-r--r--Lib/test/test_winreg.py29
-rw-r--r--Lib/urllib2.py3
-rw-r--r--Lib/urlparse.py2
-rw-r--r--Misc/ACKS1
-rw-r--r--Misc/NEWS44
-rw-r--r--Modules/_ctypes/callproc.c2
-rw-r--r--Modules/_sre.c60
-rw-r--r--Objects/intobject.c8
-rw-r--r--Objects/longobject.c8
-rw-r--r--PC/_winreg.c15
-rw-r--r--Python/import.c52
55 files changed, 771 insertions, 223 deletions
diff --git a/Doc/faq/programming.rst b/Doc/faq/programming.rst
index 8e218c0029..edee68af14 100644
--- a/Doc/faq/programming.rst
+++ b/Doc/faq/programming.rst
@@ -469,6 +469,10 @@ In the unlikely case that you care about Python versions older than 2.0, use
apply(g, (x,)+args, kwargs)
+.. index::
+ single: argument; difference from parameter
+ single: parameter; difference from argument
+
.. _faq-argument-vs-parameter:
What is the difference between arguments and parameters?
diff --git a/Doc/glossary.rst b/Doc/glossary.rst
index e742336d29..392a60cd94 100644
--- a/Doc/glossary.rst
+++ b/Doc/glossary.rst
@@ -245,8 +245,9 @@ Glossary
function
A series of statements which returns some value to a caller. It can also
- be passed zero or more arguments which may be used in the execution of
- the body. See also :term:`argument` and :term:`method`.
+ be passed zero or more :term:`arguments <argument>` which may be used in
+ the execution of the body. See also :term:`parameter`, :term:`method`,
+ and the :ref:`function` section.
__future__
A pseudo-module which programmers can use to enable new language features
diff --git a/Doc/howto/regex.rst b/Doc/howto/regex.rst
index 95b0d04364..2f552e39a1 100644
--- a/Doc/howto/regex.rst
+++ b/Doc/howto/regex.rst
@@ -359,9 +359,9 @@ for a complete listing.
+------------------+-----------------------------------------------+
:meth:`match` and :meth:`search` return ``None`` if no match can be found. If
-they're successful, a ``MatchObject`` instance is returned, containing
-information about the match: where it starts and ends, the substring it matched,
-and more.
+they're successful, a :ref:`match object <match-objects>` instance is returned,
+containing information about the match: where it starts and ends, the substring
+it matched, and more.
You can learn about this by interactively experimenting with the :mod:`re`
module. If you have Tkinter available, you may also want to look at
@@ -392,16 +392,16 @@ interpreter to print no output. You can explicitly print the result of
None
Now, let's try it on a string that it should match, such as ``tempo``. In this
-case, :meth:`match` will return a :class:`MatchObject`, so you should store the
-result in a variable for later use. ::
+case, :meth:`match` will return a :ref:`match object <match-objects>`, so you
+should store the result in a variable for later use. ::
>>> m = p.match('tempo')
>>> m #doctest: +ELLIPSIS
<_sre.SRE_Match object at 0x...>
-Now you can query the :class:`MatchObject` for information about the matching
-string. :class:`MatchObject` instances also have several methods and
-attributes; the most important ones are:
+Now you can query the :ref:`match object <match-objects>` for information
+about the matching string. :ref:`match object <match-objects>` instances
+also have several methods and attributes; the most important ones are:
+------------------+--------------------------------------------+
| Method/Attribute | Purpose |
@@ -442,8 +442,9 @@ case. ::
>>> m.span()
(4, 11)
-In actual programs, the most common style is to store the :class:`MatchObject`
-in a variable, and then check if it was ``None``. This usually looks like::
+In actual programs, the most common style is to store the
+:ref:`match object <match-objects>` in a variable, and then check if it was
+``None``. This usually looks like::
p = re.compile( ... )
m = p.match( 'string goes here' )
@@ -460,8 +461,8 @@ Two pattern methods return all of the matches for a pattern.
['12', '11', '10']
:meth:`findall` has to create the entire list before it can be returned as the
-result. The :meth:`finditer` method returns a sequence of :class:`MatchObject`
-instances as an :term:`iterator`. [#]_ ::
+result. The :meth:`finditer` method returns a sequence of
+:ref:`match object <match-objects>` instances as an :term:`iterator`. [#]_ ::
>>> iterator = p.finditer('12 drummers drumming, 11 ... 10 ...')
>>> iterator #doctest: +ELLIPSIS
@@ -482,7 +483,7 @@ You don't have to create a pattern object and call its methods; the
:func:`search`, :func:`findall`, :func:`sub`, and so forth. These functions
take the same arguments as the corresponding pattern method, with
the RE string added as the first argument, and still return either ``None`` or a
-:class:`MatchObject` instance. ::
+:ref:`match object <match-objects>` instance. ::
>>> print re.match(r'From\s+', 'Fromage amk')
None
@@ -791,9 +792,9 @@ Groups indicated with ``'('``, ``')'`` also capture the starting and ending
index of the text that they match; this can be retrieved by passing an argument
to :meth:`group`, :meth:`start`, :meth:`end`, and :meth:`span`. Groups are
numbered starting with 0. Group 0 is always present; it's the whole RE, so
-:class:`MatchObject` methods all have group 0 as their default argument. Later
-we'll see how to express groups that don't capture the span of text that they
-match. ::
+:ref:`match object <match-objects>` methods all have group 0 as their default
+argument. Later we'll see how to express groups that don't capture the span
+of text that they match. ::
>>> p = re.compile('(a)b')
>>> m = p.match('ab')
@@ -913,10 +914,10 @@ numbers, groups can be referenced by a name.
The syntax for a named group is one of the Python-specific extensions:
``(?P<name>...)``. *name* is, obviously, the name of the group. Named groups
also behave exactly like capturing groups, and additionally associate a name
-with a group. The :class:`MatchObject` methods that deal with capturing groups
-all accept either integers that refer to the group by number or strings that
-contain the desired group's name. Named groups are still given numbers, so you
-can retrieve information about a group in two ways::
+with a group. The :ref:`match object <match-objects>` methods that deal with
+capturing groups all accept either integers that refer to the group by number
+or strings that contain the desired group's name. Named groups are still
+given numbers, so you can retrieve information about a group in two ways::
>>> p = re.compile(r'(?P<word>\b\w+\b)')
>>> m = p.search( '(((( Lots of punctuation )))' )
@@ -1180,11 +1181,11 @@ three variations of the replacement string. ::
*replacement* can also be a function, which gives you even more control. If
*replacement* is a function, the function is called for every non-overlapping
-occurrence of *pattern*. On each call, the function is passed a
-:class:`MatchObject` argument for the match and can use this information to
-compute the desired replacement string and return it.
+occurrence of *pattern*. On each call, the function is passed a
+:ref:`match object <match-objects>` argument for the match and can use this
+information to compute the desired replacement string and return it.
-In the following example, the replacement function translates decimals into
+In the following example, the replacement function translates decimals into
hexadecimal::
>>> def hexrepl(match):
diff --git a/Doc/library/argparse.rst b/Doc/library/argparse.rst
index 2380a509e9..73d454e8ed 100644
--- a/Doc/library/argparse.rst
+++ b/Doc/library/argparse.rst
@@ -1439,7 +1439,7 @@ Sub-commands
different functions which require different kinds of command-line arguments.
:class:`ArgumentParser` supports the creation of such sub-commands with the
:meth:`add_subparsers` method. The :meth:`add_subparsers` method is normally
- called with no arguments and returns an special action object. This object
+ called with no arguments and returns a special action object. This object
has a single method, :meth:`~ArgumentParser.add_parser`, which takes a
command name and any :class:`ArgumentParser` constructor arguments, and
returns an :class:`ArgumentParser` object that can be modified as usual.
diff --git a/Doc/library/ftplib.rst b/Doc/library/ftplib.rst
index b8f5b4e695..988278952b 100644
--- a/Doc/library/ftplib.rst
+++ b/Doc/library/ftplib.rst
@@ -370,10 +370,10 @@ followed by ``lines`` for the text version or ``binary`` for the binary version.
.. method:: FTP.close()
Close the connection unilaterally. This should not be applied to an already
- closed connection such as after a successful call to :meth:`quit`. After this
- call the :class:`FTP` instance should not be used any more (after a call to
- :meth:`close` or :meth:`quit` you cannot reopen the connection by issuing
- another :meth:`login` method).
+ closed connection such as after a successful call to :meth:`~FTP.quit`.
+ After this call the :class:`FTP` instance should not be used any more (after
+ a call to :meth:`close` or :meth:`~FTP.quit` you cannot reopen the
+ connection by issuing another :meth:`login` method).
FTP_TLS Objects
diff --git a/Doc/library/imp.rst b/Doc/library/imp.rst
index 04bc6f5877..8f98d652d8 100644
--- a/Doc/library/imp.rst
+++ b/Doc/library/imp.rst
@@ -239,14 +239,14 @@ around for backward compatibility:
.. impl-detail::
- The import internals identify extension modules by filename, so doing
- ``foo = load_dynamic("foo", "mod.so")`` and
- ``bar = load_dynamic("bar", "mod.so")`` will result in both foo and bar
- referring to the same module, regardless of whether or not
- ``mod.so`` exports an ``initbar`` function. On systems which
- support them, symlinks can be used to import multiple modules from
- the same shared library, as each reference to the module will use
- a different file name.
+ The import internals identify extension modules by filename, so doing
+ ``foo = load_dynamic("foo", "mod.so")`` and
+ ``bar = load_dynamic("bar", "mod.so")`` will result in both foo and bar
+ referring to the same module, regardless of whether or not
+ ``mod.so`` exports an ``initbar`` function. On systems which
+ support them, symlinks can be used to import multiple modules from
+ the same shared library, as each reference to the module will use
+ a different file name.
.. function:: load_source(name, pathname[, file])
diff --git a/Doc/library/itertools.rst b/Doc/library/itertools.rst
index 8bb9e3672a..a7f0058b4c 100644
--- a/Doc/library/itertools.rst
+++ b/Doc/library/itertools.rst
@@ -106,9 +106,8 @@ loops that truncate the stream.
.. classmethod:: chain.from_iterable(iterable)
Alternate constructor for :func:`chain`. Gets chained inputs from a
- single iterable argument that is evaluated lazily. Equivalent to::
+ single iterable argument that is evaluated lazily. Roughly equivalent to::
- @classmethod
def from_iterable(iterables):
# chain.from_iterable(['ABC', 'DEF']) --> A B C D E F
for it in iterables:
diff --git a/Doc/library/poplib.rst b/Doc/library/poplib.rst
index ca77e6e865..07c243fde9 100644
--- a/Doc/library/poplib.rst
+++ b/Doc/library/poplib.rst
@@ -102,7 +102,7 @@ An :class:`POP3` instance has the following methods:
.. method:: POP3.pass_(password)
Send password, response includes message count and mailbox size. Note: the
- mailbox on the server is locked until :meth:`quit` is called.
+ mailbox on the server is locked until :meth:`~poplib.quit` is called.
.. method:: POP3.apop(user, secret)
diff --git a/Doc/library/smtplib.rst b/Doc/library/smtplib.rst
index b0b58e8e8a..044bbde28b 100644
--- a/Doc/library/smtplib.rst
+++ b/Doc/library/smtplib.rst
@@ -32,7 +32,8 @@ Protocol) and :rfc:`1869` (SMTP Service Extensions).
setting will be used).
For normal use, you should only require the initialization/connect,
- :meth:`sendmail`, and :meth:`quit` methods. An example is included below.
+ :meth:`sendmail`, and :meth:`~smtplib.quit` methods.
+ An example is included below.
.. versionchanged:: 2.6
*timeout* was added.
diff --git a/Doc/library/socket.rst b/Doc/library/socket.rst
index 0e5dac0b77..7e8fb26a27 100644
--- a/Doc/library/socket.rst
+++ b/Doc/library/socket.rst
@@ -230,7 +230,7 @@ The module :mod:`socket` exports the following constants and functions:
*source_address* was added.
-.. function:: getaddrinfo(host, port, family=0, socktype=0, proto=0, flags=0)
+.. function:: getaddrinfo(host, port[, family[, socktype[, proto[, flags]]]])
Translate the *host*/*port* argument into a sequence of 5-tuples that contain
all the necessary arguments for creating a socket connected to that service.
@@ -240,12 +240,12 @@ The module :mod:`socket` exports the following constants and functions:
and *port*, you can pass ``NULL`` to the underlying C API.
The *family*, *socktype* and *proto* arguments can be optionally specified
- in order to narrow the list of addresses returned. Passing zero as a
- value for each of these arguments selects the full range of results.
+ in order to narrow the list of addresses returned. By default, their value
+ is ``0``, meaning that the full range of results is selected.
The *flags* argument can be one or several of the ``AI_*`` constants,
- and will influence how results are computed and returned.
- For example, :const:`AI_NUMERICHOST` will disable domain name resolution
- and will raise an error if *host* is a domain name.
+ and will influence how results are computed and returned. Its default value
+ is ``0``. For example, :const:`AI_NUMERICHOST` will disable domain name
+ resolution and will raise an error if *host* is a domain name.
The function returns a list of 5-tuples with the following structure:
diff --git a/Doc/library/socketserver.rst b/Doc/library/socketserver.rst
index c34b486806..d225392ba3 100644
--- a/Doc/library/socketserver.rst
+++ b/Doc/library/socketserver.rst
@@ -306,8 +306,8 @@ request.
.. method:: RequestHandler.finish()
Called after the :meth:`handle` method to perform any clean-up actions
- required. The default implementation does nothing. If :meth:`setup` or
- :meth:`handle` raise an exception, this function will not be called.
+ required. The default implementation does nothing. If :meth:`setup`
+ raises an exception, this function will not be called.
.. method:: RequestHandler.handle()
diff --git a/Doc/reference/compound_stmts.rst b/Doc/reference/compound_stmts.rst
index a86eb11f88..4a616eb7a9 100644
--- a/Doc/reference/compound_stmts.rst
+++ b/Doc/reference/compound_stmts.rst
@@ -407,6 +407,9 @@ is equivalent to ::
statement.
+.. index::
+ single: parameter; function definition
+
.. _function:
.. _def:
@@ -467,12 +470,15 @@ is equivalent to::
def func(): pass
func = f1(arg)(f2(func))
-.. index:: triple: default; parameter; value
-
-When one or more top-level parameters have the form *parameter* ``=``
-*expression*, the function is said to have "default parameter values." For a
-parameter with a default value, the corresponding argument may be omitted from a
-call, in which case the parameter's default value is substituted. If a
+.. index::
+ triple: default; parameter; value
+ single: argument; function definition
+
+When one or more top-level :term:`parameters <parameter>` have the form
+*parameter* ``=`` *expression*, the function is said to have "default parameter
+values." For a parameter with a default value, the corresponding
+:term:`argument` may be omitted from a call, in which
+case the parameter's default value is substituted. If a
parameter has a default value, all following parameters must also have a default
value --- this is a syntactic restriction that is not expressed by the grammar.
diff --git a/Doc/reference/expressions.rst b/Doc/reference/expressions.rst
index bc9f1b4b3a..812fb70ed2 100644
--- a/Doc/reference/expressions.rst
+++ b/Doc/reference/expressions.rst
@@ -667,17 +667,18 @@ upper bound and stride, respectively, substituting ``None`` for missing
expressions.
+.. index::
+ object: callable
+ single: call
+ single: argument; call semantics
+
.. _calls:
Calls
-----
-.. index:: single: call
-
-.. index:: object: callable
-
-A call calls a callable object (e.g., a function) with a possibly empty series
-of arguments:
+A call calls a callable object (e.g., a :term:`function`) with a possibly empty
+series of :term:`arguments <argument>`:
.. productionlist::
call: `primary` "(" [`argument_list` [","]
@@ -696,12 +697,15 @@ of arguments:
A trailing comma may be present after the positional and keyword arguments but
does not affect the semantics.
+.. index::
+ single: parameter; call semantics
+
The primary must evaluate to a callable object (user-defined functions, built-in
functions, methods of built-in objects, class objects, methods of class
instances, and certain class instances themselves are callable; extensions may
define additional callable object types). All argument expressions are
evaluated before the call is attempted. Please refer to section :ref:`function`
-for the syntax of formal parameter lists.
+for the syntax of formal :term:`parameter` lists.
If keyword arguments are present, they are first converted to positional
arguments, as follows. First, a list of unfilled slots is created for the
@@ -1339,8 +1343,8 @@ their suffixes::
.. _operator-summary:
-Summary
-=======
+Operator precedence
+===================
.. index:: pair: operator; precedence
@@ -1363,9 +1367,9 @@ groups from right to left).
+-----------------------------------------------+-------------------------------------+
| :keyword:`and` | Boolean AND |
+-----------------------------------------------+-------------------------------------+
-| :keyword:`not` *x* | Boolean NOT |
+| :keyword:`not` ``x`` | Boolean NOT |
+-----------------------------------------------+-------------------------------------+
-| :keyword:`in`, :keyword:`not` :keyword:`in`, | Comparisons, including membership |
+| :keyword:`in`, :keyword:`not in`, | Comparisons, including membership |
| :keyword:`is`, :keyword:`is not`, ``<``, | tests and identity tests, |
| ``<=``, ``>``, ``>=``, ``<>``, ``!=``, ``==`` | |
+-----------------------------------------------+-------------------------------------+
@@ -1391,7 +1395,7 @@ groups from right to left).
+-----------------------------------------------+-------------------------------------+
| ``(expressions...)``, | Binding or tuple display, |
| ``[expressions...]``, | list display, |
-| ``{key:datum...}``, | dictionary display, |
+| ``{key: value...}``, | dictionary display, |
| ```expressions...``` | string conversion |
+-----------------------------------------------+-------------------------------------+
diff --git a/Doc/using/windows.rst b/Doc/using/windows.rst
index 978440c20b..b49ba7ba92 100644
--- a/Doc/using/windows.rst
+++ b/Doc/using/windows.rst
@@ -84,6 +84,8 @@ In order to run Python flawlessly, you might have to change certain environment
settings in Windows.
+.. _setting-envvars:
+
Excursus: Setting environment variables
---------------------------------------
diff --git a/Lib/SocketServer.py b/Lib/SocketServer.py
index 1594321909..26611b74d1 100644
--- a/Lib/SocketServer.py
+++ b/Lib/SocketServer.py
@@ -701,7 +701,12 @@ class StreamRequestHandler(BaseRequestHandler):
def finish(self):
if not self.wfile.closed:
- self.wfile.flush()
+ try:
+ self.wfile.flush()
+ except socket.error:
+ # An final socket error may have occurred here, such as
+ # the local error ECONNABORTED.
+ pass
self.wfile.close()
self.rfile.close()
diff --git a/Lib/aifc.py b/Lib/aifc.py
index b8adc852ed..a0cfe5fc57 100644
--- a/Lib/aifc.py
+++ b/Lib/aifc.py
@@ -732,22 +732,28 @@ class Aifc_write:
self._patchheader()
def close(self):
- self._ensure_header_written(0)
- if self._datawritten & 1:
- # quick pad to even size
- self._file.write(chr(0))
- self._datawritten = self._datawritten + 1
- self._writemarkers()
- if self._nframeswritten != self._nframes or \
- self._datalength != self._datawritten or \
- self._marklength:
- self._patchheader()
- if self._comp:
- self._comp.CloseCompressor()
- self._comp = None
- # Prevent ref cycles
- self._convert = None
- self._file.close()
+ if self._file is None:
+ return
+ try:
+ self._ensure_header_written(0)
+ if self._datawritten & 1:
+ # quick pad to even size
+ self._file.write(chr(0))
+ self._datawritten = self._datawritten + 1
+ self._writemarkers()
+ if self._nframeswritten != self._nframes or \
+ self._datalength != self._datawritten or \
+ self._marklength:
+ self._patchheader()
+ if self._comp:
+ self._comp.CloseCompressor()
+ self._comp = None
+ finally:
+ # Prevent ref cycles
+ self._convert = None
+ f = self._file
+ self._file = None
+ f.close()
#
# Internal methods.
diff --git a/Lib/cgi.py b/Lib/cgi.py
index e7cd778316..67079db0d8 100755
--- a/Lib/cgi.py
+++ b/Lib/cgi.py
@@ -37,7 +37,6 @@ __version__ = "2.6"
from operator import attrgetter
import sys
import os
-import urllib
import UserDict
import urlparse
diff --git a/Lib/ctypes/test/test_bitfields.py b/Lib/ctypes/test/test_bitfields.py
index 090fb4dfc5..3bcc67fb75 100644
--- a/Lib/ctypes/test/test_bitfields.py
+++ b/Lib/ctypes/test/test_bitfields.py
@@ -246,9 +246,9 @@ class BitFieldTest(unittest.TestCase):
_fields_ = [("a", c_uint32, 32)]
x = X()
x.a = 10
- self.assertEquals(x.a, 10)
+ self.assertEqual(x.a, 10)
x.a = 0xFDCBA987
- self.assertEquals(x.a, 0xFDCBA987)
+ self.assertEqual(x.a, 0xFDCBA987)
@unittest.skipUnless(hasattr(ctypes, "c_uint64"), "c_int64 is required")
def test_uint64(self):
@@ -256,9 +256,9 @@ class BitFieldTest(unittest.TestCase):
_fields_ = [("a", c_uint64, 64)]
x = X()
x.a = 10
- self.assertEquals(x.a, 10)
+ self.assertEqual(x.a, 10)
x.a = 0xFEDCBA9876543211
- self.assertEquals(x.a, 0xFEDCBA9876543211)
+ self.assertEqual(x.a, 0xFEDCBA9876543211)
if __name__ == "__main__":
unittest.main()
diff --git a/Lib/curses/__init__.py b/Lib/curses/__init__.py
index bd7d5f61cf..ecf59de37d 100644
--- a/Lib/curses/__init__.py
+++ b/Lib/curses/__init__.py
@@ -5,7 +5,7 @@ the package, and perhaps a particular module inside it.
import curses
from curses import textpad
- curses.initwin()
+ curses.initscr()
...
"""
diff --git a/Lib/idlelib/ColorDelegator.py b/Lib/idlelib/ColorDelegator.py
index 7f4d740ffa..0610c4b6aa 100644
--- a/Lib/idlelib/ColorDelegator.py
+++ b/Lib/idlelib/ColorDelegator.py
@@ -20,10 +20,11 @@ def make_pat():
# 1st 'file' colorized normal, 2nd as builtin, 3rd as string
builtin = r"([^.'\"\\#]\b|^)" + any("BUILTIN", builtinlist) + r"\b"
comment = any("COMMENT", [r"#[^\n]*"])
- sqstring = r"(\b[rRuU])?'[^'\\\n]*(\\.[^'\\\n]*)*'?"
- dqstring = r'(\b[rRuU])?"[^"\\\n]*(\\.[^"\\\n]*)*"?'
- sq3string = r"(\b[rRuU])?'''[^'\\]*((\\.|'(?!''))[^'\\]*)*(''')?"
- dq3string = r'(\b[rRuU])?"""[^"\\]*((\\.|"(?!""))[^"\\]*)*(""")?'
+ stringprefix = r"(\br|u|ur|R|U|UR|Ur|uR|b|B|br|Br|bR|BR)?"
+ sqstring = stringprefix + r"'[^'\\\n]*(\\.[^'\\\n]*)*'?"
+ dqstring = stringprefix + r'"[^"\\\n]*(\\.[^"\\\n]*)*"?'
+ sq3string = stringprefix + r"'''[^'\\]*((\\.|'(?!''))[^'\\]*)*(''')?"
+ dq3string = stringprefix + r'"""[^"\\]*((\\.|"(?!""))[^"\\]*)*(""")?'
string = any("STRING", [sq3string, dq3string, sqstring, dqstring])
return kw + "|" + builtin + "|" + comment + "|" + string +\
"|" + any("SYNC", [r"\n"])
diff --git a/Lib/idlelib/EditorWindow.py b/Lib/idlelib/EditorWindow.py
index 241bd38ff9..0a01c9ec30 100644
--- a/Lib/idlelib/EditorWindow.py
+++ b/Lib/idlelib/EditorWindow.py
@@ -172,13 +172,13 @@ class EditorWindow(object):
'recent-files.lst')
self.text_frame = text_frame = Frame(top)
self.vbar = vbar = Scrollbar(text_frame, name='vbar')
- self.width = idleConf.GetOption('main','EditorWindow','width')
+ self.width = idleConf.GetOption('main','EditorWindow','width', type='int')
text_options = {
'name': 'text',
'padx': 5,
'wrap': 'none',
'width': self.width,
- 'height': idleConf.GetOption('main', 'EditorWindow', 'height')}
+ 'height': idleConf.GetOption('main', 'EditorWindow', 'height', type='int')}
if TkVersion >= 8.5:
# Starting with tk 8.5 we have to set the new tabstyle option
# to 'wordprocessor' to achieve the same display of tabs as in
@@ -255,7 +255,8 @@ class EditorWindow(object):
if idleConf.GetOption('main', 'EditorWindow', 'font-bold', type='bool'):
fontWeight='bold'
text.config(font=(idleConf.GetOption('main', 'EditorWindow', 'font'),
- idleConf.GetOption('main', 'EditorWindow', 'font-size'),
+ idleConf.GetOption('main', 'EditorWindow',
+ 'font-size', type='int'),
fontWeight))
text_frame.pack(side=LEFT, fill=BOTH, expand=1)
text.pack(side=TOP, fill=BOTH, expand=1)
@@ -763,7 +764,8 @@ class EditorWindow(object):
if idleConf.GetOption('main','EditorWindow','font-bold',type='bool'):
fontWeight='bold'
self.text.config(font=(idleConf.GetOption('main','EditorWindow','font'),
- idleConf.GetOption('main','EditorWindow','font-size'),
+ idleConf.GetOption('main','EditorWindow','font-size',
+ type='int'),
fontWeight))
def RemoveKeybindings(self):
@@ -1609,7 +1611,7 @@ class IndentSearcher(object):
try:
try:
_tokenize.tokenize(self.readline, self.tokeneater)
- except _tokenize.TokenError:
+ except (_tokenize.TokenError, SyntaxError):
# since we cut off the tokenizer early, we can trigger
# spurious errors
pass
diff --git a/Lib/idlelib/FormatParagraph.py b/Lib/idlelib/FormatParagraph.py
index 6a5f9b5dd5..557d8a9e0d 100644
--- a/Lib/idlelib/FormatParagraph.py
+++ b/Lib/idlelib/FormatParagraph.py
@@ -32,7 +32,8 @@ class FormatParagraph:
self.editwin = None
def format_paragraph_event(self, event):
- maxformatwidth = int(idleConf.GetOption('main','FormatParagraph','paragraph'))
+ maxformatwidth = int(idleConf.GetOption('main','FormatParagraph',
+ 'paragraph', type='int'))
text = self.editwin.text
first, last = self.editwin.get_selection_indices()
if first and last:
diff --git a/Lib/idlelib/configDialog.py b/Lib/idlelib/configDialog.py
index 9884d5e5a2..b707fc3ddb 100644
--- a/Lib/idlelib/configDialog.py
+++ b/Lib/idlelib/configDialog.py
@@ -947,7 +947,7 @@ class ConfigDialog(Toplevel):
self.listFontName.select_anchor(currentFontIndex)
##font size dropdown
fontSize=idleConf.GetOption('main','EditorWindow','font-size',
- default='10')
+ type='int', default='10')
self.optMenuFontSize.SetMenu(('7','8','9','10','11','12','13','14',
'16','18','20','22'),fontSize )
##fontWeight
@@ -1033,10 +1033,13 @@ class ConfigDialog(Toplevel):
self.autoSave.set(idleConf.GetOption('main', 'General', 'autosave',
default=0, type='bool'))
#initial window size
- self.winWidth.set(idleConf.GetOption('main','EditorWindow','width'))
- self.winHeight.set(idleConf.GetOption('main','EditorWindow','height'))
+ self.winWidth.set(idleConf.GetOption('main','EditorWindow','width',
+ type='int'))
+ self.winHeight.set(idleConf.GetOption('main','EditorWindow','height',
+ type='int'))
#initial paragraph reformat size
- self.paraWidth.set(idleConf.GetOption('main','FormatParagraph','paragraph'))
+ self.paraWidth.set(idleConf.GetOption('main','FormatParagraph','paragraph',
+ type='int'))
# default source encoding
self.encoding.set(idleConf.GetOption('main', 'EditorWindow',
'encoding', default='none'))
diff --git a/Lib/idlelib/configHandler.py b/Lib/idlelib/configHandler.py
index dd13a0e733..ce28d0836d 100644
--- a/Lib/idlelib/configHandler.py
+++ b/Lib/idlelib/configHandler.py
@@ -237,24 +237,39 @@ class IdleConf:
printed to stderr.
"""
- if self.userCfg[configType].has_option(section,option):
- return self.userCfg[configType].Get(section, option,
- type=type, raw=raw)
- elif self.defaultCfg[configType].has_option(section,option):
- return self.defaultCfg[configType].Get(section, option,
- type=type, raw=raw)
- else: #returning default, print warning
- if warn_on_default:
- warning = ('\n Warning: configHandler.py - IdleConf.GetOption -\n'
- ' problem retrieving configuration option %r\n'
- ' from section %r.\n'
- ' returning default value: %r\n' %
- (option, section, default))
- try:
- sys.stderr.write(warning)
- except IOError:
- pass
- return default
+ try:
+ if self.userCfg[configType].has_option(section,option):
+ return self.userCfg[configType].Get(section, option,
+ type=type, raw=raw)
+ except ValueError:
+ warning = ('\n Warning: configHandler.py - IdleConf.GetOption -\n'
+ ' invalid %r value for configuration option %r\n'
+ ' from section %r: %r\n' %
+ (type, option, section,
+ self.userCfg[configType].Get(section, option,
+ raw=raw)))
+ try:
+ sys.stderr.write(warning)
+ except IOError:
+ pass
+ try:
+ if self.defaultCfg[configType].has_option(section,option):
+ return self.defaultCfg[configType].Get(section, option,
+ type=type, raw=raw)
+ except ValueError:
+ pass
+ #returning default, print warning
+ if warn_on_default:
+ warning = ('\n Warning: configHandler.py - IdleConf.GetOption -\n'
+ ' problem retrieving configuration option %r\n'
+ ' from section %r.\n'
+ ' returning default value: %r\n' %
+ (option, section, default))
+ try:
+ sys.stderr.write(warning)
+ except IOError:
+ pass
+ return default
def SetOption(self, configType, section, option, value):
"""In user's config file, set section's option to value.
diff --git a/Lib/multiprocessing/connection.py b/Lib/multiprocessing/connection.py
index 4421ac5cfd..6c398fdc91 100644
--- a/Lib/multiprocessing/connection.py
+++ b/Lib/multiprocessing/connection.py
@@ -200,6 +200,27 @@ if sys.platform != 'win32':
return c1, c2
else:
+ if hasattr(select, 'poll'):
+ def _poll(fds, timeout):
+ if timeout is not None:
+ timeout = int(timeout) * 1000 # timeout is in milliseconds
+ fd_map = {}
+ pollster = select.poll()
+ for fd in fds:
+ pollster.register(fd, select.POLLIN)
+ if hasattr(fd, 'fileno'):
+ fd_map[fd.fileno()] = fd
+ else:
+ fd_map[fd] = fd
+ ls = []
+ for fd, event in pollster.poll(timeout):
+ if event & select.POLLNVAL:
+ raise ValueError('invalid file descriptor %i' % fd)
+ ls.append(fd_map[fd])
+ return ls
+ else:
+ def _poll(fds, timeout):
+ return select.select(fds, [], [], timeout)[0]
from _multiprocessing import win32
diff --git a/Lib/socket.py b/Lib/socket.py
index bd364e70db..aac04f6ca7 100644
--- a/Lib/socket.py
+++ b/Lib/socket.py
@@ -319,8 +319,8 @@ class _fileobject(object):
self._wbuf.append(data)
self._wbuf_len += len(data)
if (self._wbufsize == 0 or
- self._wbufsize == 1 and '\n' in data or
- self._wbuf_len >= self._wbufsize):
+ (self._wbufsize == 1 and '\n' in data) or
+ (self._wbufsize > 1 and self._wbuf_len >= self._wbufsize)):
self.flush()
def writelines(self, list):
diff --git a/Lib/ssl.py b/Lib/ssl.py
index 1951a620d9..88296358a0 100644
--- a/Lib/ssl.py
+++ b/Lib/ssl.py
@@ -313,17 +313,19 @@ class SSLSocket(socket):
self.cert_reqs, self.ssl_version,
self.ca_certs, self.ciphers)
try:
- socket.connect(self, addr)
- if self.do_handshake_on_connect:
- self.do_handshake()
- except socket_error as e:
if return_errno:
- return e.errno
+ rc = socket.connect_ex(self, addr)
else:
- self._sslobj = None
- raise e
- self._connected = True
- return 0
+ rc = None
+ socket.connect(self, addr)
+ if not rc:
+ if self.do_handshake_on_connect:
+ self.do_handshake()
+ self._connected = True
+ return rc
+ except socket_error:
+ self._sslobj = None
+ raise
def connect(self, addr):
"""Connects to remote ADDR, and then wraps the connection in
diff --git a/Lib/subprocess.py b/Lib/subprocess.py
index 104d6ec4d5..19a51889ea 100644
--- a/Lib/subprocess.py
+++ b/Lib/subprocess.py
@@ -1292,7 +1292,7 @@ class Popen(object):
def _internal_poll(self, _deadstate=None, _waitpid=os.waitpid,
- _WNOHANG=os.WNOHANG, _os_error=os.error):
+ _WNOHANG=os.WNOHANG, _os_error=os.error, _ECHILD=errno.ECHILD):
"""Check if child process has terminated. Returns returncode
attribute.
@@ -1308,7 +1308,7 @@ class Popen(object):
except _os_error as e:
if _deadstate is not None:
self.returncode = _deadstate
- if e.errno == errno.ECHILD:
+ if e.errno == _ECHILD:
# This happens if SIGCLD is set to be ignored or
# waiting for child processes has otherwise been
# disabled for our process. This child is dead, we
diff --git a/Lib/test/regrtest.py b/Lib/test/regrtest.py
index f01dcef308..dd47cc36e0 100755
--- a/Lib/test/regrtest.py
+++ b/Lib/test/regrtest.py
@@ -32,7 +32,7 @@ Verbosity
Selecting tests
--r/--random -- randomize test execution order (see below)
+-r/--randomize -- randomize test execution order (see below)
--randseed -- pass a random seed to reproduce a previous random run
-f/--fromfile -- read names of tests to run from a file (see below)
-x/--exclude -- arguments are tests to *exclude*
@@ -258,7 +258,7 @@ def main(tests=None, testdir=None, verbose=0, quiet=False,
try:
opts, args = getopt.getopt(sys.argv[1:], 'hvqxsSrf:lu:t:TD:NLR:FwWM:j:',
['help', 'verbose', 'verbose2', 'verbose3', 'quiet',
- 'exclude', 'single', 'slow', 'random', 'fromfile', 'findleaks',
+ 'exclude', 'single', 'slow', 'randomize', 'fromfile=', 'findleaks',
'use=', 'threshold=', 'trace', 'coverdir=', 'nocoverdir',
'runleaks', 'huntrleaks=', 'memlimit=', 'randseed=',
'multiprocess=', 'slaveargs=', 'forever', 'header'])
diff --git a/Lib/test/test_aifc.py b/Lib/test/test_aifc.py
index e492838258..62b3d18018 100644
--- a/Lib/test/test_aifc.py
+++ b/Lib/test/test_aifc.py
@@ -106,6 +106,13 @@ class AIFCTest(unittest.TestCase):
self.assertEqual(testfile.closed, False)
f.close()
self.assertEqual(testfile.closed, True)
+ testfile = open(TESTFN, 'wb')
+ fout = aifc.open(testfile, 'wb')
+ self.assertFalse(testfile.closed)
+ with self.assertRaises(aifc.Error):
+ fout.close()
+ self.assertTrue(testfile.closed)
+ fout.close() # do nothing
class AIFCLowLevelTest(unittest.TestCase):
diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py
index 1d35a6afe5..d75c44afbb 100644
--- a/Lib/test/test_builtin.py
+++ b/Lib/test/test_builtin.py
@@ -680,6 +680,8 @@ class BuiltinTest(unittest.TestCase):
# Test input() later, together with raw_input
+ # test_int(): see test_int.py for int() tests.
+
def test_intern(self):
self.assertRaises(TypeError, intern)
# This fails if the test is run twice with a constant string,
diff --git a/Lib/test/test_calendar.py b/Lib/test/test_calendar.py
index 5d6549c6cd..0f91d29590 100644
--- a/Lib/test/test_calendar.py
+++ b/Lib/test/test_calendar.py
@@ -261,7 +261,7 @@ class CalendarTestCase(unittest.TestCase):
return
calendar.LocaleHTMLCalendar(locale='').formatmonthname(2010, 10)
new_october = calendar.TextCalendar().formatmonthname(2010, 10, 10)
- self.assertEquals(old_october, new_october)
+ self.assertEqual(old_october, new_october)
def test_itermonthdates(self):
# ensure itermonthdates doesn't overflow after datetime.MAXYEAR
diff --git a/Lib/test/test_glob.py b/Lib/test/test_glob.py
index fee3a60a7e..b360d09dfa 100644
--- a/Lib/test/test_glob.py
+++ b/Lib/test/test_glob.py
@@ -1,9 +1,14 @@
-import unittest
-from test.test_support import run_unittest, TESTFN
import glob
import os
import shutil
import sys
+import unittest
+
+from test.test_support import run_unittest, TESTFN
+
+
+def fsdecode(s):
+ return unicode(s, sys.getfilesystemencoding())
class GlobTests(unittest.TestCase):
@@ -31,7 +36,8 @@ class GlobTests(unittest.TestCase):
self.mktemp('a', 'bcd', 'efg', 'ha')
if hasattr(os, 'symlink'):
os.symlink(self.norm('broken'), self.norm('sym1'))
- os.symlink(self.norm('broken'), self.norm('sym2'))
+ os.symlink('broken', self.norm('sym2'))
+ os.symlink(os.path.join('a', 'bcd'), self.norm('sym3'))
def tearDown(self):
shutil.rmtree(self.tempdir)
@@ -44,10 +50,16 @@ class GlobTests(unittest.TestCase):
p = os.path.join(self.tempdir, pattern)
res = glob.glob(p)
self.assertEqual(list(glob.iglob(p)), res)
+ ures = [fsdecode(x) for x in res]
+ self.assertEqual(glob.glob(fsdecode(p)), ures)
+ self.assertEqual(list(glob.iglob(fsdecode(p))), ures)
return res
def assertSequencesEqual_noorder(self, l1, l2):
+ l1 = list(l1)
+ l2 = list(l2)
self.assertEqual(set(l1), set(l2))
+ self.assertEqual(sorted(l1), sorted(l2))
def test_glob_literal(self):
eq = self.assertSequencesEqual_noorder
@@ -56,15 +68,19 @@ class GlobTests(unittest.TestCase):
eq(self.glob('aab'), [self.norm('aab')])
eq(self.glob('zymurgy'), [])
+ res = glob.glob('*')
+ self.assertEqual({type(r) for r in res}, {str})
+ res = glob.glob(os.path.join(os.curdir, '*'))
+ self.assertEqual({type(r) for r in res}, {str})
+
# test return types are unicode, but only if os.listdir
# returns unicode filenames
- uniset = set([unicode])
- tmp = os.listdir(u'.')
- if set(type(x) for x in tmp) == uniset:
- u1 = glob.glob(u'*')
- u2 = glob.glob(u'./*')
- self.assertEqual(set(type(r) for r in u1), uniset)
- self.assertEqual(set(type(r) for r in u2), uniset)
+ tmp = os.listdir(fsdecode(os.curdir))
+ if {type(x) for x in tmp} == {unicode}:
+ res = glob.glob(u'*')
+ self.assertEqual({type(r) for r in res}, {unicode})
+ res = glob.glob(os.path.join(fsdecode(os.curdir), u'*'))
+ self.assertEqual({type(r) for r in res}, {unicode})
def test_glob_one_directory(self):
eq = self.assertSequencesEqual_noorder
@@ -93,23 +109,60 @@ class GlobTests(unittest.TestCase):
eq(self.glob('*', '*a'), [])
eq(self.glob('a', '*', '*', '*a'),
[self.norm('a', 'bcd', 'efg', 'ha')])
- eq(self.glob('?a?', '*F'), map(self.norm, [os.path.join('aaa', 'zzzF'),
- os.path.join('aab', 'F')]))
+ eq(self.glob('?a?', '*F'), [self.norm('aaa', 'zzzF'),
+ self.norm('aab', 'F')])
def test_glob_directory_with_trailing_slash(self):
- # We are verifying that when there is wildcard pattern which
- # ends with os.sep doesn't blow up.
- res = glob.glob(self.tempdir + '*' + os.sep)
- self.assertEqual(len(res), 1)
- # either of these results are reasonable
- self.assertIn(res[0], [self.tempdir, self.tempdir + os.sep])
-
+ # Patterns ending with a slash shouldn't match non-dirs
+ res = glob.glob(self.norm('Z*Z') + os.sep)
+ self.assertEqual(res, [])
+ res = glob.glob(self.norm('ZZZ') + os.sep)
+ self.assertEqual(res, [])
+ # When there is a wildcard pattern which ends with os.sep, glob()
+ # doesn't blow up.
+ res = glob.glob(self.norm('aa*') + os.sep)
+ self.assertEqual(len(res), 2)
+ # either of these results is reasonable
+ self.assertIn(set(res), [
+ {self.norm('aaa'), self.norm('aab')},
+ {self.norm('aaa') + os.sep, self.norm('aab') + os.sep},
+ ])
+
+ def test_glob_unicode_directory_with_trailing_slash(self):
+ # Same as test_glob_directory_with_trailing_slash, but with an
+ # unicode argument.
+ res = glob.glob(fsdecode(self.norm('Z*Z') + os.sep))
+ self.assertEqual(res, [])
+ res = glob.glob(fsdecode(self.norm('ZZZ') + os.sep))
+ self.assertEqual(res, [])
+ res = glob.glob(fsdecode(self.norm('aa*') + os.sep))
+ self.assertEqual(len(res), 2)
+ # either of these results is reasonable
+ self.assertIn(set(res), [
+ {fsdecode(self.norm('aaa')), fsdecode(self.norm('aab'))},
+ {fsdecode(self.norm('aaa') + os.sep),
+ fsdecode(self.norm('aab') + os.sep)},
+ ])
+
+ @unittest.skipUnless(hasattr(os, 'symlink'), "Requires symlink support")
+ def test_glob_symlinks(self):
+ eq = self.assertSequencesEqual_noorder
+ eq(self.glob('sym3'), [self.norm('sym3')])
+ eq(self.glob('sym3', '*'), [self.norm('sym3', 'EF'),
+ self.norm('sym3', 'efg')])
+ self.assertIn(self.glob('sym3' + os.sep),
+ [[self.norm('sym3')], [self.norm('sym3') + os.sep]])
+ eq(self.glob('*', '*F'),
+ [self.norm('aaa', 'zzzF'), self.norm('aab', 'F'),
+ self.norm('sym3', 'EF')])
+
+ @unittest.skipUnless(hasattr(os, 'symlink'), "Requires symlink support")
def test_glob_broken_symlinks(self):
- if hasattr(os, 'symlink'):
- eq = self.assertSequencesEqual_noorder
- eq(self.glob('sym*'), [self.norm('sym1'), self.norm('sym2')])
- eq(self.glob('sym1'), [self.norm('sym1')])
- eq(self.glob('sym2'), [self.norm('sym2')])
+ eq = self.assertSequencesEqual_noorder
+ eq(self.glob('sym*'), [self.norm('sym1'), self.norm('sym2'),
+ self.norm('sym3')])
+ eq(self.glob('sym1'), [self.norm('sym1')])
+ eq(self.glob('sym2'), [self.norm('sym2')])
@unittest.skipUnless(sys.platform == "win32", "Win32 specific test")
def test_glob_magic_in_drive(self):
diff --git a/Lib/test/test_import.py b/Lib/test/test_import.py
index edd18694b9..ea50d34626 100644
--- a/Lib/test/test_import.py
+++ b/Lib/test/test_import.py
@@ -5,6 +5,7 @@ import os
import py_compile
import random
import stat
+import struct
import sys
import unittest
import textwrap
@@ -350,6 +351,46 @@ class ImportTests(unittest.TestCase):
del sys.path[0]
remove_files(TESTFN)
+ def test_pyc_mtime(self):
+ # Test for issue #13863: .pyc timestamp sometimes incorrect on Windows.
+ sys.path.insert(0, os.curdir)
+ try:
+ # Jan 1, 2012; Jul 1, 2012.
+ mtimes = 1325376000, 1341100800
+
+ # Different names to avoid running into import caching.
+ tails = "spam", "eggs"
+ for mtime, tail in zip(mtimes, tails):
+ module = TESTFN + tail
+ source = module + ".py"
+ compiled = source + ('c' if __debug__ else 'o')
+
+ # Create a new Python file with the given mtime.
+ with open(source, 'w') as f:
+ f.write("# Just testing\nx=1, 2, 3\n")
+ os.utime(source, (mtime, mtime))
+
+ # Generate the .pyc/o file; if it couldn't be created
+ # for some reason, skip the test.
+ m = __import__(module)
+ if not os.path.exists(compiled):
+ unlink(source)
+ self.skipTest("Couldn't create .pyc/.pyo file.")
+
+ # Actual modification time of .py file.
+ mtime1 = int(os.stat(source).st_mtime) & 0xffffffff
+
+ # mtime that was encoded in the .pyc file.
+ with open(compiled, 'rb') as f:
+ mtime2 = struct.unpack('<L', f.read(8)[4:])[0]
+
+ unlink(compiled)
+ unlink(source)
+
+ self.assertEqual(mtime1, mtime2)
+ finally:
+ sys.path.pop(0)
+
class PycRewritingTests(unittest.TestCase):
# Test that the `co_filename` attribute on code objects always points
diff --git a/Lib/test/test_int.py b/Lib/test/test_int.py
index fa46212d9b..365f9a247c 100644
--- a/Lib/test/test_int.py
+++ b/Lib/test/test_int.py
@@ -1,6 +1,7 @@
import sys
import unittest
+from test import test_support
from test.test_support import run_unittest, have_unicode
import math
@@ -44,7 +45,27 @@ if have_unicode:
(unichr(0x200), ValueError),
]
-class IntTestCases(unittest.TestCase):
+class IntLongCommonTests(object):
+
+ """Mixin of test cases to share between both test_int and test_long."""
+
+ # Change to int or long in the TestCase subclass.
+ ntype = None
+
+ def test_no_args(self):
+ self.assertEqual(self.ntype(), 0)
+
+ def test_keyword_args(self):
+ # Test invoking constructor using keyword arguments.
+ self.assertEqual(self.ntype(x=1.2), 1)
+ self.assertEqual(self.ntype('100', base=2), 4)
+ self.assertEqual(self.ntype(x='100', base=2), 4)
+ self.assertRaises(TypeError, self.ntype, base=10)
+ self.assertRaises(TypeError, self.ntype, base=0)
+
+class IntTestCases(IntLongCommonTests, unittest.TestCase):
+
+ ntype = int
def test_basic(self):
self.assertEqual(int(314), 314)
@@ -315,6 +336,46 @@ class IntTestCases(unittest.TestCase):
self.assertEqual(int(float(2**54+10)), 2**54+8)
self.assertEqual(int(float(2**54+11)), 2**54+12)
+ def test_valid_non_numeric_input_types_for_x(self):
+ # Test possible valid non-numeric types for x, including subclasses
+ # of the allowed built-in types.
+ class CustomStr(str): pass
+ values = ['100', CustomStr('100')]
+
+ if have_unicode:
+ class CustomUnicode(unicode): pass
+ values += [unicode('100'), CustomUnicode(unicode('100'))]
+
+ for x in values:
+ msg = 'x has value %s and type %s' % (x, type(x).__name__)
+ try:
+ self.assertEqual(int(x), 100, msg=msg)
+ self.assertEqual(int(x, 2), 4, msg=msg)
+ except TypeError, err:
+ raise AssertionError('For %s got TypeError: %s' %
+ (type(x).__name__, err))
+
+ def test_error_on_string_float_for_x(self):
+ self.assertRaises(ValueError, int, '1.2')
+
+ def test_error_on_bytearray_for_x(self):
+ self.assertRaises(TypeError, int, bytearray('100'), 2)
+
+ def test_error_on_invalid_int_bases(self):
+ for base in [-1, 1, 1000]:
+ self.assertRaises(ValueError, int, '100', base)
+
+ def test_error_on_string_base(self):
+ self.assertRaises(TypeError, int, 100, base='foo')
+
+ @test_support.cpython_only
+ def test_small_ints(self):
+ self.assertIs(int('10'), 10)
+ self.assertIs(int('-1'), -1)
+ if have_unicode:
+ self.assertIs(int(u'10'), 10)
+ self.assertIs(int(u'-1'), -1)
+
def test_intconversion(self):
# Test __int__()
class ClassicMissingMethods:
diff --git a/Lib/test/test_long.py b/Lib/test/test_long.py
index 58cfc3a2a3..f0847e7ab4 100644
--- a/Lib/test/test_long.py
+++ b/Lib/test/test_long.py
@@ -1,10 +1,11 @@
import unittest
-from test import test_support
import sys
import random
import math
+from test import test_int, test_support
+
# Used for lazy formatting of failure messages
class Frm(object):
def __init__(self, format, *args):
@@ -78,8 +79,9 @@ if test_support.have_unicode:
(unichr(0x200), ValueError),
]
+class LongTest(test_int.IntLongCommonTests, unittest.TestCase):
-class LongTest(unittest.TestCase):
+ ntype = long
# Get quasi-random long consisting of ndigits digits (in base BASE).
# quasi == the most-significant digit will not be 0, and the number
diff --git a/Lib/test/test_multiprocessing.py b/Lib/test/test_multiprocessing.py
index 15870570db..f140aca63f 100644
--- a/Lib/test/test_multiprocessing.py
+++ b/Lib/test/test_multiprocessing.py
@@ -1513,6 +1513,7 @@ class _TestConnection(BaseTestCase):
self.assertTimingAlmostEqual(poll.elapsed, TIMEOUT1)
conn.send(None)
+ time.sleep(.1)
self.assertEqual(poll(TIMEOUT1), True)
self.assertTimingAlmostEqual(poll.elapsed, 0)
diff --git a/Lib/test/test_mutex.py b/Lib/test/test_mutex.py
index 2882213394..030080e3a4 100644
--- a/Lib/test/test_mutex.py
+++ b/Lib/test/test_mutex.py
@@ -14,7 +14,7 @@ class MutexTest(unittest.TestCase):
m.lock(called_by_mutex2, "eggs")
def called_by_mutex2(some_data):
- self.assertEquals(some_data, "eggs")
+ self.assertEqual(some_data, "eggs")
self.assertTrue(m.test(), "mutex not held")
self.assertTrue(ready_for_2,
"called_by_mutex2 called too soon")
diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py
index 053c6fe7be..fec62efe03 100644
--- a/Lib/test/test_socket.py
+++ b/Lib/test/test_socket.py
@@ -962,8 +962,8 @@ class FileObjectClassTestCase(SocketConnectedTest):
def tearDown(self):
self.serv_file.close()
self.assertTrue(self.serv_file.closed)
- self.serv_file = None
SocketConnectedTest.tearDown(self)
+ self.serv_file = None
def clientSetUp(self):
SocketConnectedTest.clientSetUp(self)
@@ -1151,6 +1151,64 @@ class LineBufferedFileObjectClassTestCase(FileObjectClassTestCase):
bufsize = 1 # Default-buffered for reading; line-buffered for writing
+ class SocketMemo(object):
+ """A wrapper to keep track of sent data, needed to examine write behaviour"""
+ def __init__(self, sock):
+ self._sock = sock
+ self.sent = []
+
+ def send(self, data, flags=0):
+ n = self._sock.send(data, flags)
+ self.sent.append(data[:n])
+ return n
+
+ def sendall(self, data, flags=0):
+ self._sock.sendall(data, flags)
+ self.sent.append(data)
+
+ def __getattr__(self, attr):
+ return getattr(self._sock, attr)
+
+ def getsent(self):
+ return [e.tobytes() if isinstance(e, memoryview) else e for e in self.sent]
+
+ def setUp(self):
+ FileObjectClassTestCase.setUp(self)
+ self.serv_file._sock = self.SocketMemo(self.serv_file._sock)
+
+ def testLinebufferedWrite(self):
+ # Write two lines, in small chunks
+ msg = MSG.strip()
+ print >> self.serv_file, msg,
+ print >> self.serv_file, msg
+
+ # second line:
+ print >> self.serv_file, msg,
+ print >> self.serv_file, msg,
+ print >> self.serv_file, msg
+
+ # third line
+ print >> self.serv_file, ''
+
+ self.serv_file.flush()
+
+ msg1 = "%s %s\n"%(msg, msg)
+ msg2 = "%s %s %s\n"%(msg, msg, msg)
+ msg3 = "\n"
+ self.assertEqual(self.serv_file._sock.getsent(), [msg1, msg2, msg3])
+
+ def _testLinebufferedWrite(self):
+ msg = MSG.strip()
+ msg1 = "%s %s\n"%(msg, msg)
+ msg2 = "%s %s %s\n"%(msg, msg, msg)
+ msg3 = "\n"
+ l1 = self.cli_file.readline()
+ self.assertEqual(l1, msg1)
+ l2 = self.cli_file.readline()
+ self.assertEqual(l2, msg2)
+ l3 = self.cli_file.readline()
+ self.assertEqual(l3, msg3)
+
class SmallBufferedFileObjectClassTestCase(FileObjectClassTestCase):
diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py
index 58da942f49..9f5138719e 100644
--- a/Lib/test/test_ssl.py
+++ b/Lib/test/test_ssl.py
@@ -280,6 +280,34 @@ class NetworkedTests(unittest.TestCase):
finally:
s.close()
+ def test_timeout_connect_ex(self):
+ # Issue #12065: on a timeout, connect_ex() should return the original
+ # errno (mimicking the behaviour of non-SSL sockets).
+ with test_support.transient_internet("svn.python.org"):
+ s = ssl.wrap_socket(socket.socket(socket.AF_INET),
+ cert_reqs=ssl.CERT_REQUIRED,
+ ca_certs=SVN_PYTHON_ORG_ROOT_CERT,
+ do_handshake_on_connect=False)
+ try:
+ s.settimeout(0.0000001)
+ rc = s.connect_ex(('svn.python.org', 443))
+ if rc == 0:
+ self.skipTest("svn.python.org responded too quickly")
+ self.assertIn(rc, (errno.EAGAIN, errno.EWOULDBLOCK))
+ finally:
+ s.close()
+
+ def test_connect_ex_error(self):
+ with test_support.transient_internet("svn.python.org"):
+ s = ssl.wrap_socket(socket.socket(socket.AF_INET),
+ cert_reqs=ssl.CERT_REQUIRED,
+ ca_certs=SVN_PYTHON_ORG_ROOT_CERT)
+ try:
+ self.assertEqual(errno.ECONNREFUSED,
+ s.connect_ex(("svn.python.org", 444)))
+ finally:
+ s.close()
+
@unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows")
def test_makefile_close(self):
# Issue #5238: creating a file-like object with makefile() shouldn't
diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py
index a3685ea273..af59e277f3 100644
--- a/Lib/test/test_tarfile.py
+++ b/Lib/test/test_tarfile.py
@@ -297,26 +297,21 @@ class MiscReadTest(CommonReadTest):
def test_extract_hardlink(self):
# Test hardlink extraction (e.g. bug #857297).
- tar = tarfile.open(tarname, errorlevel=1, encoding="iso8859-1")
+ with tarfile.open(tarname, errorlevel=1, encoding="iso8859-1") as tar:
+ tar.extract("ustar/regtype", TEMPDIR)
+ self.addCleanup(os.remove, os.path.join(TEMPDIR, "ustar/regtype"))
- tar.extract("ustar/regtype", TEMPDIR)
- try:
tar.extract("ustar/lnktype", TEMPDIR)
- except EnvironmentError, e:
- if e.errno == errno.ENOENT:
- self.fail("hardlink not extracted properly")
-
- data = open(os.path.join(TEMPDIR, "ustar/lnktype"), "rb").read()
- self.assertEqual(md5sum(data), md5_regtype)
+ self.addCleanup(os.remove, os.path.join(TEMPDIR, "ustar/lnktype"))
+ with open(os.path.join(TEMPDIR, "ustar/lnktype"), "rb") as f:
+ data = f.read()
+ self.assertEqual(md5sum(data), md5_regtype)
- try:
tar.extract("ustar/symtype", TEMPDIR)
- except EnvironmentError, e:
- if e.errno == errno.ENOENT:
- self.fail("symlink not extracted properly")
-
- data = open(os.path.join(TEMPDIR, "ustar/symtype"), "rb").read()
- self.assertEqual(md5sum(data), md5_regtype)
+ self.addCleanup(os.remove, os.path.join(TEMPDIR, "ustar/symtype"))
+ with open(os.path.join(TEMPDIR, "ustar/symtype"), "rb") as f:
+ data = f.read()
+ self.assertEqual(md5sum(data), md5_regtype)
def test_extractall(self):
# Test if extractall() correctly restores directory permissions
@@ -858,7 +853,7 @@ class WriteTest(WriteTestBase):
tar = tarfile.open(tmpname, "r")
for t in tar:
- self.assert_(t.name == "." or t.name.startswith("./"))
+ self.assertTrue(t.name == "." or t.name.startswith("./"))
tar.close()
finally:
os.chdir(cwd)
diff --git a/Lib/test/test_urllib2.py b/Lib/test/test_urllib2.py
index 12263b381d..eac995001e 100644
--- a/Lib/test/test_urllib2.py
+++ b/Lib/test/test_urllib2.py
@@ -1336,16 +1336,32 @@ class RequestTests(unittest.TestCase):
req = Request(url)
self.assertEqual(req.get_full_url(), url)
-def test_HTTPError_interface():
- """
- Issue 13211 reveals that HTTPError didn't implement the URLError
- interface even though HTTPError is a subclass of URLError.
-
- >>> err = urllib2.HTTPError(msg='something bad happened', url=None, code=None, hdrs=None, fp=None)
- >>> assert hasattr(err, 'reason')
- >>> err.reason
- 'something bad happened'
- """
+ def test_HTTPError_interface(self):
+ """
+ Issue 13211 reveals that HTTPError didn't implement the URLError
+ interface even though HTTPError is a subclass of URLError.
+
+ >>> err = urllib2.HTTPError(msg='something bad happened', url=None, code=None, hdrs=None, fp=None)
+ >>> assert hasattr(err, 'reason')
+ >>> err.reason
+ 'something bad happened'
+ """
+
+ def test_HTTPError_interface_call(self):
+ """
+ Issue 15701= - HTTPError interface has info method available from URLError.
+ """
+ err = urllib2.HTTPError(msg='something bad happened', url=None,
+ code=None, hdrs='Content-Length:42', fp=None)
+ self.assertTrue(hasattr(err, 'reason'))
+ assert hasattr(err, 'reason')
+ assert hasattr(err, 'info')
+ assert callable(err.info)
+ try:
+ err.info()
+ except AttributeError:
+ self.fail("err.info() failed")
+ self.assertEqual(err.info(), "Content-Length:42")
def test_main(verbose=None):
from test import test_urllib2
diff --git a/Lib/test/test_urllib2_localnet.py b/Lib/test/test_urllib2_localnet.py
index 0fda770901..ec3437597d 100644
--- a/Lib/test/test_urllib2_localnet.py
+++ b/Lib/test/test_urllib2_localnet.py
@@ -5,7 +5,9 @@ import urllib2
import BaseHTTPServer
import unittest
import hashlib
+
from test import test_support
+
mimetools = test_support.import_module('mimetools', deprecated=True)
threading = test_support.import_module('threading')
@@ -346,6 +348,12 @@ class TestUrlopen(BaseTestCase):
for transparent redirection have been written.
"""
+ def setUp(self):
+ proxy_handler = urllib2.ProxyHandler({})
+ opener = urllib2.build_opener(proxy_handler)
+ urllib2.install_opener(opener)
+ super(TestUrlopen, self).setUp()
+
def start_server(self, responses):
handler = GetRequestHandler(responses)
diff --git a/Lib/test/test_urlparse.py b/Lib/test/test_urlparse.py
index 3f316d385c..72ebfaa089 100644
--- a/Lib/test/test_urlparse.py
+++ b/Lib/test/test_urlparse.py
@@ -446,10 +446,43 @@ class UrlParseTestCase(unittest.TestCase):
p1 = urlparse.urlsplit('tel:+31-641044153')
self.assertEqual(p1.scheme, 'tel')
self.assertEqual(p1.path, '+31-641044153')
+
p2 = urlparse.urlsplit('tel:+31641044153')
self.assertEqual(p2.scheme, 'tel')
self.assertEqual(p2.path, '+31641044153')
+ # Assert for urlparse
+ p1 = urlparse.urlparse('tel:+31-641044153')
+ self.assertEqual(p1.scheme, 'tel')
+ self.assertEqual(p1.path, '+31-641044153')
+
+ p2 = urlparse.urlparse('tel:+31641044153')
+ self.assertEqual(p2.scheme, 'tel')
+ self.assertEqual(p2.path, '+31641044153')
+
+
+ def test_telurl_params(self):
+ p1 = urlparse.urlparse('tel:123-4;phone-context=+1-650-516')
+ self.assertEqual(p1.scheme, 'tel')
+ self.assertEqual(p1.path, '123-4')
+ self.assertEqual(p1.params, 'phone-context=+1-650-516')
+
+ p1 = urlparse.urlparse('tel:+1-201-555-0123')
+ self.assertEqual(p1.scheme, 'tel')
+ self.assertEqual(p1.path, '+1-201-555-0123')
+ self.assertEqual(p1.params, '')
+
+ p1 = urlparse.urlparse('tel:7042;phone-context=example.com')
+ self.assertEqual(p1.scheme, 'tel')
+ self.assertEqual(p1.path, '7042')
+ self.assertEqual(p1.params, 'phone-context=example.com')
+
+ p1 = urlparse.urlparse('tel:863-1234;phone-context=+1-914-555')
+ self.assertEqual(p1.scheme, 'tel')
+ self.assertEqual(p1.path, '863-1234')
+ self.assertEqual(p1.params, 'phone-context=+1-914-555')
+
+
def test_attributes_bad_port(self):
"""Check handling of non-integer ports."""
p = urlparse.urlsplit("http://www.example.net:foo")
diff --git a/Lib/test/test_winreg.py b/Lib/test/test_winreg.py
index a741b65e07..2799e19480 100644
--- a/Lib/test/test_winreg.py
+++ b/Lib/test/test_winreg.py
@@ -314,6 +314,35 @@ class LocalWinregTests(BaseWinregTests):
finally:
DeleteKey(HKEY_CURRENT_USER, test_key_name)
+ def test_setvalueex_value_range(self):
+ # Test for Issue #14420, accept proper ranges for SetValueEx.
+ # Py2Reg, which gets called by SetValueEx, was using PyLong_AsLong,
+ # thus raising OverflowError. The implementation now uses
+ # PyLong_AsUnsignedLong to match DWORD's size.
+ try:
+ with CreateKey(HKEY_CURRENT_USER, test_key_name) as ck:
+ self.assertNotEqual(ck.handle, 0)
+ SetValueEx(ck, "test_name", None, REG_DWORD, 0x80000000)
+ finally:
+ DeleteKey(HKEY_CURRENT_USER, test_key_name)
+
+ def test_queryvalueex_return_value(self):
+ # Test for Issue #16759, return unsigned int from QueryValueEx.
+ # Reg2Py, which gets called by QueryValueEx, was returning a value
+ # generated by PyLong_FromLong. The implmentation now uses
+ # PyLong_FromUnsignedLong to match DWORD's size.
+ try:
+ with CreateKey(HKEY_CURRENT_USER, test_key_name) as ck:
+ self.assertNotEqual(ck.handle, 0)
+ test_val = 0x80000000
+ SetValueEx(ck, "test_name", None, REG_DWORD, test_val)
+ ret_val, ret_type = QueryValueEx(ck, "test_name")
+ self.assertEqual(ret_type, REG_DWORD)
+ self.assertEqual(ret_val, test_val)
+ finally:
+ DeleteKey(HKEY_CURRENT_USER, test_key_name)
+
+
@unittest.skipUnless(REMOTE_NAME, "Skipping remote registry tests")
class RemoteWinregTests(BaseWinregTests):
diff --git a/Lib/urllib2.py b/Lib/urllib2.py
index ebf58119d6..aadeb7371e 100644
--- a/Lib/urllib2.py
+++ b/Lib/urllib2.py
@@ -173,6 +173,9 @@ class HTTPError(URLError, addinfourl):
def reason(self):
return self.msg
+ def info(self):
+ return self.hdrs
+
# copied from cookielib.py
_cut_port_re = re.compile(r":\d+$")
def request_host(request):
diff --git a/Lib/urlparse.py b/Lib/urlparse.py
index abc53c616a..f370ce3bdc 100644
--- a/Lib/urlparse.py
+++ b/Lib/urlparse.py
@@ -42,7 +42,7 @@ uses_netloc = ['ftp', 'http', 'gopher', 'nntp', 'telnet',
'svn', 'svn+ssh', 'sftp','nfs','git', 'git+ssh']
uses_params = ['ftp', 'hdl', 'prospero', 'http', 'imap',
'https', 'shttp', 'rtsp', 'rtspu', 'sip', 'sips',
- 'mms', '', 'sftp']
+ 'mms', '', 'sftp', 'tel']
# These are not actually used anymore, but should stay for backwards
# compatibility. (They are undocumented, but have a public-looking name.)
diff --git a/Misc/ACKS b/Misc/ACKS
index ea7bea588a..cfe7462437 100644
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -499,6 +499,7 @@ Tamito Kajiyama
Peter van Kampen
Jacob Kaplan-Moss
Piotr Kasprzyk
+Anton Kasyanov
Lou Kates
Hiroaki Kawai
Sebastien Keim
diff --git a/Misc/NEWS b/Misc/NEWS
index babe8383a2..8bfa569017 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -9,6 +9,21 @@ What's New in Python 2.7.4
Core and Builtins
-----------------
+- Issue #16761: Calling ``int()`` and ``long()`` with *base* argument only
+ now raises TypeError.
+
+- Issue #16759: Support the full DWORD (unsigned long) range in Reg2Py
+ when retreiving a REG_DWORD value. This corrects functions like
+ winreg.QueryValueEx that may have been returning truncated values.
+
+- Issue #14420: Support the full DWORD (unsigned long) range in Py2Reg
+ when passed a REG_DWORD value. Fixes ValueError in winreg.SetValueEx when
+ given a long.
+
+- Issue #13863: Work around buggy 'fstat' implementation on Windows / NTFS that
+ lead to incorrect timestamps (off by one hour) being stored in .pyc files on
+ some systems.
+
- Issue #16602: When a weakref's target was part of a long deallocation
chain, the object could remain reachable through its weakref even though
its refcount had dropped to zero.
@@ -160,11 +175,32 @@ Core and Builtins
Library
-------
+- Issue 10527: make multiprocessing use poll() instead of select() if available.
+
+- Issue #16485: Fix file descriptor not being closed if file header patching
+ fails on closing of aifc file.
+
+- Issue #12065: connect_ex() on an SSL socket now returns the original errno
+ when the socket's timeout expires (it used to return None).
+
+- Issue #16504: IDLE now catches SyntaxErrors raised by tokenizer. Patch by
+ Roger Serwy.
+
+- Issue #16702: test_urllib2_localnet tests now correctly ignores proxies for
+ localhost tests.
+
+- Issue #16713: Fix the parsing of tel url with params using urlparse module.
+
+- Issue #16443: Add docstrings to regular expression match objects.
+ Patch by Anton Kasyanov.
+
- Issue #8853: Allow port to be of type long for socket.getaddrinfo().
- Issue #16597: In buffered and text IO, call close() on the underlying stream
if invoking flush() fails.
+- Issue #15701: Fix HTTPError info method call to return the headers information.
+
- Issue #16646: ftplib.FTP.makeport() might lose socket error details.
(patch by Serhiy Storchaka)
@@ -394,6 +430,9 @@ Library
- Issue #12157: Make pool.map() empty iterables correctly. Initial
patch by mouad.
+- Issue #14958: Change IDLE systax highlighting to recognize all string and byte
+ literals currently supported in Python 2.7.
+
- Issue #14962: Update text coloring in IDLE shell window after changing
options. Patch by Roger Serwy.
@@ -560,6 +599,11 @@ Extension Modules
Tests
-----
+- Issue #15324: Fix regrtest parsing of --fromfile and --randomize options.
+
+- Issue #16618: Add more regression tests for glob.
+ Patch by Serhiy Storchaka.
+
- Issue #16664: Add regression tests for glob's behaviour concerning entries
starting with a ".". Patch by Sebastian Kreft.
diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c
index ef3e97408c..23825a7110 100644
--- a/Modules/_ctypes/callproc.c
+++ b/Modules/_ctypes/callproc.c
@@ -844,11 +844,11 @@ static int _call_function_pointer(int flags,
space[0] = errno;
errno = temp;
}
- Py_XDECREF(error_object);
#ifdef WITH_THREAD
if ((flags & FUNCFLAG_PYTHONAPI) == 0)
Py_BLOCK_THREADS
#endif
+ Py_XDECREF(error_object);
#ifdef MS_WIN32
#ifndef DONT_USE_SEH
if (dwExceptionCode) {
diff --git a/Modules/_sre.c b/Modules/_sre.c
index a5a6b1e802..8f47688d41 100644
--- a/Modules/_sre.c
+++ b/Modules/_sre.c
@@ -2546,7 +2546,7 @@ PyDoc_STRVAR(pattern_match_doc,
PyDoc_STRVAR(pattern_search_doc,
"search(string[, pos[, endpos]]) --> match object or None.\n\
Scan through string looking for a match, and return a corresponding\n\
- MatchObject instance. Return None if no position in the string matches.");
+ match object instance. Return None if no position in the string matches.");
PyDoc_STRVAR(pattern_split_doc,
"split(string[, maxsplit = 0]) --> list.\n\
@@ -3545,14 +3545,54 @@ match_deepcopy(MatchObject* self, PyObject* memo)
#endif
}
-static struct PyMethodDef match_methods[] = {
- {"group", (PyCFunction) match_group, METH_VARARGS},
- {"start", (PyCFunction) match_start, METH_VARARGS},
- {"end", (PyCFunction) match_end, METH_VARARGS},
- {"span", (PyCFunction) match_span, METH_VARARGS},
- {"groups", (PyCFunction) match_groups, METH_VARARGS|METH_KEYWORDS},
- {"groupdict", (PyCFunction) match_groupdict, METH_VARARGS|METH_KEYWORDS},
- {"expand", (PyCFunction) match_expand, METH_O},
+PyDoc_STRVAR(match_doc,
+"The result of re.match() and re.search().\n\
+Match objects always have a boolean value of True.");
+
+PyDoc_STRVAR(match_group_doc,
+"group([group1, ...]) -> str or tuple.\n\
+ Return subgroup(s) of the match by indices or names.\n\
+ For 0 returns the entire match.");
+
+PyDoc_STRVAR(match_start_doc,
+"start([group=0]) -> int.\n\
+ Return index of the start of the substring matched by group.");
+
+PyDoc_STRVAR(match_end_doc,
+"end([group=0]) -> int.\n\
+ Return index of the end of the substring matched by group.");
+
+PyDoc_STRVAR(match_span_doc,
+"span([group]) -> tuple.\n\
+ For MatchObject m, return the 2-tuple (m.start(group), m.end(group)).");
+
+PyDoc_STRVAR(match_groups_doc,
+"groups([default=None]) -> tuple.\n\
+ Return a tuple containing all the subgroups of the match, from 1.\n\
+ The default argument is used for groups\n\
+ that did not participate in the match");
+
+PyDoc_STRVAR(match_groupdict_doc,
+"groupdict([default=None]) -> dict.\n\
+ Return a dictionary containing all the named subgroups of the match,\n\
+ keyed by the subgroup name. The default argument is used for groups\n\
+ that did not participate in the match");
+
+PyDoc_STRVAR(match_expand_doc,
+"expand(template) -> str.\n\
+ Return the string obtained by doing backslash substitution\n\
+ on the string template, as done by the sub() method.");
+
+static PyMethodDef match_methods[] = {
+ {"group", (PyCFunction) match_group, METH_VARARGS, match_group_doc},
+ {"start", (PyCFunction) match_start, METH_VARARGS, match_start_doc},
+ {"end", (PyCFunction) match_end, METH_VARARGS, match_end_doc},
+ {"span", (PyCFunction) match_span, METH_VARARGS, match_span_doc},
+ {"groups", (PyCFunction) match_groups, METH_VARARGS|METH_KEYWORDS,
+ match_groups_doc},
+ {"groupdict", (PyCFunction) match_groupdict, METH_VARARGS|METH_KEYWORDS,
+ match_groupdict_doc},
+ {"expand", (PyCFunction) match_expand, METH_O, match_expand_doc},
{"__copy__", (PyCFunction) match_copy, METH_NOARGS},
{"__deepcopy__", (PyCFunction) match_deepcopy, METH_O},
{NULL, NULL}
@@ -3632,7 +3672,7 @@ static PyTypeObject Match_Type = {
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT,
- 0, /* tp_doc */
+ match_doc, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
diff --git a/Objects/intobject.c b/Objects/intobject.c
index 74955adbef..1ae8006c28 100644
--- a/Objects/intobject.c
+++ b/Objects/intobject.c
@@ -1059,8 +1059,14 @@ int_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Oi:int", kwlist,
&x, &base))
return NULL;
- if (x == NULL)
+ if (x == NULL) {
+ if (base != -909) {
+ PyErr_SetString(PyExc_TypeError,
+ "int() missing string argument");
+ return NULL;
+ }
return PyInt_FromLong(0L);
+ }
if (base == -909)
return PyNumber_Int(x);
if (PyString_Check(x)) {
diff --git a/Objects/longobject.c b/Objects/longobject.c
index 9296ad49b1..5a6338f630 100644
--- a/Objects/longobject.c
+++ b/Objects/longobject.c
@@ -3987,8 +3987,14 @@ long_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Oi:long", kwlist,
&x, &base))
return NULL;
- if (x == NULL)
+ if (x == NULL) {
+ if (base != -909) {
+ PyErr_SetString(PyExc_TypeError,
+ "long() missing string argument");
+ return NULL;
+ }
return PyLong_FromLong(0L);
+ }
if (base == -909)
return PyNumber_Long(x);
else if (PyString_Check(x)) {
diff --git a/PC/_winreg.c b/PC/_winreg.c
index 445c3edd76..d60b151192 100644
--- a/PC/_winreg.c
+++ b/PC/_winreg.c
@@ -753,7 +753,8 @@ Py2Reg(PyObject *value, DWORD typ, BYTE **retDataBuf, DWORD *retDataSize)
Py_ssize_t i,j;
switch (typ) {
case REG_DWORD:
- if (value != Py_None && !PyInt_Check(value))
+ if (value != Py_None &&
+ !(PyInt_Check(value) || PyLong_Check(value)))
return FALSE;
*retDataBuf = (BYTE *)PyMem_NEW(DWORD, 1);
if (*retDataBuf==NULL){
@@ -765,10 +766,10 @@ Py2Reg(PyObject *value, DWORD typ, BYTE **retDataBuf, DWORD *retDataSize)
DWORD zero = 0;
memcpy(*retDataBuf, &zero, sizeof(DWORD));
}
- else
- memcpy(*retDataBuf,
- &PyInt_AS_LONG((PyIntObject *)value),
- sizeof(DWORD));
+ else {
+ DWORD d = PyLong_AsUnsignedLong(value);
+ memcpy(*retDataBuf, &d, sizeof(DWORD));
+ }
break;
case REG_SZ:
case REG_EXPAND_SZ:
@@ -917,9 +918,9 @@ Reg2Py(char *retDataBuf, DWORD retDataSize, DWORD typ)
switch (typ) {
case REG_DWORD:
if (retDataSize == 0)
- obData = Py_BuildValue("i", 0);
+ obData = Py_BuildValue("k", 0);
else
- obData = Py_BuildValue("i",
+ obData = Py_BuildValue("k",
*(int *)retDataBuf);
break;
case REG_SZ:
diff --git a/Python/import.c b/Python/import.c
index 7daba06ad2..92363b3937 100644
--- a/Python/import.c
+++ b/Python/import.c
@@ -904,10 +904,9 @@ open_exclusive(char *filename, mode_t mode)
remove the file. */
static void
-write_compiled_module(PyCodeObject *co, char *cpathname, struct stat *srcstat)
+write_compiled_module(PyCodeObject *co, char *cpathname, struct stat *srcstat, time_t mtime)
{
FILE *fp;
- time_t mtime = srcstat->st_mtime;
#ifdef MS_WINDOWS /* since Windows uses different permissions */
mode_t mode = srcstat->st_mode & ~S_IEXEC;
/* Issue #6074: We ensure user write access, so we can delete it later
@@ -993,6 +992,38 @@ update_compiled_module(PyCodeObject *co, char *pathname)
return 1;
}
+#ifdef MS_WINDOWS
+
+/* Seconds between 1.1.1601 and 1.1.1970 */
+static __int64 secs_between_epochs = 11644473600;
+
+/* Get mtime from file pointer. */
+
+static time_t
+win32_mtime(FILE *fp, char *pathname)
+{
+ __int64 filetime;
+ HANDLE fh;
+ BY_HANDLE_FILE_INFORMATION file_information;
+
+ fh = (HANDLE)_get_osfhandle(fileno(fp));
+ if (fh == INVALID_HANDLE_VALUE ||
+ !GetFileInformationByHandle(fh, &file_information)) {
+ PyErr_Format(PyExc_RuntimeError,
+ "unable to get file status from '%s'",
+ pathname);
+ return -1;
+ }
+ /* filetime represents the number of 100ns intervals since
+ 1.1.1601 (UTC). Convert to seconds since 1.1.1970 (UTC). */
+ filetime = (__int64)file_information.ftLastWriteTime.dwHighDateTime << 32 |
+ file_information.ftLastWriteTime.dwLowDateTime;
+ return filetime / 10000000 - secs_between_epochs;
+}
+
+#endif /* #ifdef MS_WINDOWS */
+
+
/* Load a source module from a given file and return its module
object WITH INCREMENTED REFERENCE COUNT. If there's a matching
byte-compiled file, use that instead. */
@@ -1006,6 +1037,7 @@ load_source_module(char *name, char *pathname, FILE *fp)
char *cpathname;
PyCodeObject *co = NULL;
PyObject *m;
+ time_t mtime;
if (fstat(fileno(fp), &st) != 0) {
PyErr_Format(PyExc_RuntimeError,
@@ -1013,13 +1045,21 @@ load_source_module(char *name, char *pathname, FILE *fp)
pathname);
return NULL;
}
- if (sizeof st.st_mtime > 4) {
+
+#ifdef MS_WINDOWS
+ mtime = win32_mtime(fp, pathname);
+ if (mtime == (time_t)-1 && PyErr_Occurred())
+ return NULL;
+#else
+ mtime = st.st_mtime;
+#endif
+ if (sizeof mtime > 4) {
/* Python's .pyc timestamp handling presumes that the timestamp fits
in 4 bytes. Since the code only does an equality comparison,
ordering is not important and we can safely ignore the higher bits
(collisions are extremely unlikely).
*/
- st.st_mtime &= 0xFFFFFFFF;
+ mtime &= 0xFFFFFFFF;
}
buf = PyMem_MALLOC(MAXPATHLEN+1);
if (buf == NULL) {
@@ -1028,7 +1068,7 @@ load_source_module(char *name, char *pathname, FILE *fp)
cpathname = make_compiled_pathname(pathname, buf,
(size_t)MAXPATHLEN + 1);
if (cpathname != NULL &&
- (fpc = check_compiled_module(pathname, st.st_mtime, cpathname))) {
+ (fpc = check_compiled_module(pathname, mtime, cpathname))) {
co = read_compiled_module(cpathname, fpc);
fclose(fpc);
if (co == NULL)
@@ -1053,7 +1093,7 @@ load_source_module(char *name, char *pathname, FILE *fp)
if (b < 0)
goto error_exit;
if (!b)
- write_compiled_module(co, cpathname, &st);
+ write_compiled_module(co, cpathname, &st, mtime);
}
}
m = PyImport_ExecCodeModuleEx(name, (PyObject *)co, pathname);