[pypy-commit] pypy release-2.5.x: merge default into branch
mattip
noreply at buildbot.pypy.org
Tue Mar 10 22:52:17 CET 2015
Author: mattip <matti.picus at gmail.com>
Branch: release-2.5.x
Changeset: r76312:eae427987fb2
Date: 2015-03-10 21:28 +0200
http://bitbucket.org/pypy/pypy/changeset/eae427987fb2/
Log: merge default into branch
diff too long, truncating to 2000 out of 40273 lines
diff --git a/.gitignore b/.gitignore
--- a/.gitignore
+++ b/.gitignore
@@ -7,7 +7,10 @@
bin/pypy-c
include/*.h
+include/numpy/
lib_pypy/ctypes_config_cache/_[^_]*_*.py
+libpypy-c.*
+pypy-c
pypy/_cache
pypy/doc/*.html
pypy/doc/config/*.html
@@ -18,4 +21,5 @@
pypy/translator/c/src/dtoa.o
pypy/translator/goal/pypy-c
pypy/translator/goal/target*-c
-release/
\ No newline at end of file
+release/
+rpython/_cache/
diff --git a/.hgtags b/.hgtags
--- a/.hgtags
+++ b/.hgtags
@@ -7,10 +7,7 @@
9b623bc48b5950cf07184462a0e48f2c4df0d720 pypy-2.1-beta1-arm
ab0dd631c22015ed88e583d9fdd4c43eebf0be21 pypy-2.1-beta1-arm
20e51c4389ed4469b66bb9d6289ce0ecfc82c4b9 release-2.3.0
-20e51c4389ed4469b66bb9d6289ce0ecfc82c4b9 release-2.3.0
-0000000000000000000000000000000000000000 release-2.3.0
394146e9bb673514c61f0150ab2013ccf78e8de7 release-2.3
32f35069a16d819b58c1b6efb17c44e3e53397b2 release-2.2=3.1
32f35069a16d819b58c1b6efb17c44e3e53397b2 release-2.3.1
-32f35069a16d819b58c1b6efb17c44e3e53397b2 release-2.2=3.1
-0000000000000000000000000000000000000000 release-2.2=3.1
+10f1b29a2bd21f837090286174a9ca030b8680b2 release-2.5.0
diff --git a/lib-python/2.7/CGIHTTPServer.py b/lib-python/2.7/CGIHTTPServer.py
--- a/lib-python/2.7/CGIHTTPServer.py
+++ b/lib-python/2.7/CGIHTTPServer.py
@@ -106,16 +106,16 @@
def run_cgi(self):
"""Execute a CGI script."""
dir, rest = self.cgi_info
-
- i = rest.find('/')
+ path = dir + '/' + rest
+ i = path.find('/', len(dir)+1)
while i >= 0:
- nextdir = rest[:i]
- nextrest = rest[i+1:]
+ nextdir = path[:i]
+ nextrest = path[i+1:]
scriptdir = self.translate_path(nextdir)
if os.path.isdir(scriptdir):
dir, rest = nextdir, nextrest
- i = rest.find('/')
+ i = path.find('/', len(dir)+1)
else:
break
diff --git a/lib-python/2.7/Cookie.py b/lib-python/2.7/Cookie.py
--- a/lib-python/2.7/Cookie.py
+++ b/lib-python/2.7/Cookie.py
@@ -56,7 +56,7 @@
>>> C = Cookie.SmartCookie()
[Note: Long-time users of Cookie.py will remember using
-Cookie.Cookie() to create an Cookie object. Although deprecated, it
+Cookie.Cookie() to create a Cookie object. Although deprecated, it
is still supported by the code. See the Backward Compatibility notes
for more information.]
@@ -426,6 +426,8 @@
"version" : "Version",
}
+ _flags = {'secure', 'httponly'}
+
def __init__(self):
# Set defaults
self.key = self.value = self.coded_value = None
@@ -529,9 +531,11 @@
_LegalCharsPatt = r"[\w\d!#%&'~_`><@,:/\$\*\+\-\.\^\|\)\(\?\}\{\=]"
_CookiePattern = re.compile(
r"(?x)" # This is a Verbose pattern
+ r"\s*" # Optional whitespace at start of cookie
r"(?P<key>" # Start of group 'key'
""+ _LegalCharsPatt +"+?" # Any word of at least one letter, nongreedy
r")" # End of group 'key'
+ r"(" # Optional group: there may not be a value.
r"\s*=\s*" # Equal Sign
r"(?P<val>" # Start of group 'val'
r'"(?:[^\\"]|\\.)*"' # Any doublequoted string
@@ -540,7 +544,9 @@
r"|" # or
""+ _LegalCharsPatt +"*" # Any word or empty string
r")" # End of group 'val'
- r"\s*;?" # Probably ending in a semi-colon
+ r")?" # End of optional value group
+ r"\s*" # Any number of spaces.
+ r"(\s+|;|$)" # Ending either at space, semicolon, or EOS.
)
@@ -585,8 +591,12 @@
def __setitem__(self, key, value):
"""Dictionary style assignment."""
- rval, cval = self.value_encode(value)
- self.__set(key, rval, cval)
+ if isinstance(value, Morsel):
+ # allow assignment of constructed Morsels (e.g. for pickling)
+ dict.__setitem__(self, key, value)
+ else:
+ rval, cval = self.value_encode(value)
+ self.__set(key, rval, cval)
# end __setitem__
def output(self, attrs=None, header="Set-Cookie:", sep="\015\012"):
@@ -641,7 +651,7 @@
while 0 <= i < n:
# Start looking for a cookie
- match = patt.search(str, i)
+ match = patt.match(str, i)
if not match: break # No more cookies
K,V = match.group("key"), match.group("val")
@@ -656,8 +666,12 @@
M[ K[1:] ] = V
elif K.lower() in Morsel._reserved:
if M:
- M[ K ] = _unquote(V)
- else:
+ if V is None:
+ if K.lower() in Morsel._flags:
+ M[K] = True
+ else:
+ M[K] = _unquote(V)
+ elif V is not None:
rval, cval = self.value_decode(V)
self.__set(K, rval, cval)
M = self[K]
diff --git a/lib-python/2.7/SocketServer.py b/lib-python/2.7/SocketServer.py
--- a/lib-python/2.7/SocketServer.py
+++ b/lib-python/2.7/SocketServer.py
@@ -416,8 +416,12 @@
self.socket = socket.socket(self.address_family,
self.socket_type)
if bind_and_activate:
- self.server_bind()
- self.server_activate()
+ try:
+ self.server_bind()
+ self.server_activate()
+ except:
+ self.server_close()
+ raise
def server_bind(self):
"""Called by constructor to bind the socket.
diff --git a/lib-python/2.7/_abcoll.py b/lib-python/2.7/_abcoll.py
--- a/lib-python/2.7/_abcoll.py
+++ b/lib-python/2.7/_abcoll.py
@@ -143,7 +143,7 @@
methods except for __contains__, __iter__ and __len__.
To override the comparisons (presumably for speed, as the
- semantics are fixed), all you have to do is redefine __le__ and
+ semantics are fixed), redefine __le__ and __ge__,
then the other operations will automatically follow suit.
"""
diff --git a/lib-python/2.7/argparse.py b/lib-python/2.7/argparse.py
--- a/lib-python/2.7/argparse.py
+++ b/lib-python/2.7/argparse.py
@@ -1089,7 +1089,14 @@
# parse all the remaining options into the namespace
# store any unrecognized options on the object, so that the top
# level parser can decide what to do with them
- namespace, arg_strings = parser.parse_known_args(arg_strings, namespace)
+
+ # In case this subparser defines new defaults, we parse them
+ # in a new namespace object and then update the original
+ # namespace for the relevant parts.
+ subnamespace, arg_strings = parser.parse_known_args(arg_strings, None)
+ for key, value in vars(subnamespace).items():
+ setattr(namespace, key, value)
+
if arg_strings:
vars(namespace).setdefault(_UNRECOGNIZED_ARGS_ATTR, [])
getattr(namespace, _UNRECOGNIZED_ARGS_ATTR).extend(arg_strings)
diff --git a/lib-python/2.7/asynchat.py b/lib-python/2.7/asynchat.py
--- a/lib-python/2.7/asynchat.py
+++ b/lib-python/2.7/asynchat.py
@@ -46,12 +46,17 @@
you - by calling your self.found_terminator() method.
"""
+import asyncore
+import errno
import socket
-import asyncore
from collections import deque
from sys import py3kwarning
from warnings import filterwarnings, catch_warnings
+_BLOCKING_IO_ERRORS = (errno.EAGAIN, errno.EALREADY, errno.EINPROGRESS,
+ errno.EWOULDBLOCK)
+
+
class async_chat (asyncore.dispatcher):
"""This is an abstract class. You must derive from this class, and add
the two methods collect_incoming_data() and found_terminator()"""
@@ -109,6 +114,8 @@
try:
data = self.recv (self.ac_in_buffer_size)
except socket.error, why:
+ if why.args[0] in _BLOCKING_IO_ERRORS:
+ return
self.handle_error()
return
diff --git a/lib-python/2.7/bsddb/test/test_queue.py b/lib-python/2.7/bsddb/test/test_queue.py
--- a/lib-python/2.7/bsddb/test/test_queue.py
+++ b/lib-python/2.7/bsddb/test/test_queue.py
@@ -10,6 +10,7 @@
#----------------------------------------------------------------------
+ at unittest.skip("fails on Windows; see issue 22943")
class SimpleQueueTestCase(unittest.TestCase):
def setUp(self):
self.filename = get_new_database_path()
diff --git a/lib-python/2.7/cookielib.py b/lib-python/2.7/cookielib.py
--- a/lib-python/2.7/cookielib.py
+++ b/lib-python/2.7/cookielib.py
@@ -1719,12 +1719,12 @@
def __repr__(self):
r = []
for cookie in self: r.append(repr(cookie))
- return "<%s[%s]>" % (self.__class__, ", ".join(r))
+ return "<%s[%s]>" % (self.__class__.__name__, ", ".join(r))
def __str__(self):
r = []
for cookie in self: r.append(str(cookie))
- return "<%s[%s]>" % (self.__class__, ", ".join(r))
+ return "<%s[%s]>" % (self.__class__.__name__, ", ".join(r))
# derives from IOError for backwards-compatibility with Python 2.4.0
diff --git a/lib-python/2.7/ctypes/test/test_pointers.py b/lib-python/2.7/ctypes/test/test_pointers.py
--- a/lib-python/2.7/ctypes/test/test_pointers.py
+++ b/lib-python/2.7/ctypes/test/test_pointers.py
@@ -7,6 +7,8 @@
c_long, c_ulong, c_longlong, c_ulonglong, c_double, c_float]
python_types = [int, int, int, int, int, long,
int, long, long, long, float, float]
+LargeNamedType = type('T' * 2 ** 25, (Structure,), {})
+large_string = 'T' * 2 ** 25
class PointersTestCase(unittest.TestCase):
@@ -188,5 +190,11 @@
mth = WINFUNCTYPE(None)(42, "name", (), None)
self.assertEqual(bool(mth), True)
+ def test_pointer_type_name(self):
+ self.assertTrue(POINTER(LargeNamedType))
+
+ def test_pointer_type_str_name(self):
+ self.assertTrue(POINTER(large_string))
+
if __name__ == '__main__':
unittest.main()
diff --git a/lib-python/2.7/ctypes/test/test_python_api.py b/lib-python/2.7/ctypes/test/test_python_api.py
--- a/lib-python/2.7/ctypes/test/test_python_api.py
+++ b/lib-python/2.7/ctypes/test/test_python_api.py
@@ -46,8 +46,8 @@
# This test is unreliable, because it is possible that code in
# unittest changes the refcount of the '42' integer. So, it
# is disabled by default.
- @requires("refcount")
def test_PyInt_Long(self):
+ requires("refcount")
ref42 = grc(42)
pythonapi.PyInt_FromLong.restype = py_object
self.assertEqual(pythonapi.PyInt_FromLong(42), 42)
diff --git a/lib-python/2.7/ctypes/test/test_win32.py b/lib-python/2.7/ctypes/test/test_win32.py
--- a/lib-python/2.7/ctypes/test/test_win32.py
+++ b/lib-python/2.7/ctypes/test/test_win32.py
@@ -38,8 +38,11 @@
@unittest.skipUnless(sys.platform == "win32", 'Windows-specific test')
class FunctionCallTestCase(unittest.TestCase):
- @requires("SEH")
+ @unittest.skipUnless('MSC' in sys.version, "SEH only supported by MSC")
+ @unittest.skipIf(sys.executable.endswith('_d.exe'),
+ "SEH not enabled in debug builds")
def test_SEH(self):
+ requires("SEH")
# Call functions with invalid arguments, and make sure
# that access violations are trapped and raise an
# exception.
@@ -87,9 +90,29 @@
dll = CDLL(_ctypes_test.__file__)
- pt = POINT(10, 10)
- rect = RECT(0, 0, 20, 20)
- self.assertEqual(1, dll.PointInRect(byref(rect), pt))
+ pt = POINT(15, 25)
+ left = c_long.in_dll(dll, 'left')
+ top = c_long.in_dll(dll, 'top')
+ right = c_long.in_dll(dll, 'right')
+ bottom = c_long.in_dll(dll, 'bottom')
+ rect = RECT(left, top, right, bottom)
+ PointInRect = dll.PointInRect
+ PointInRect.argtypes = [POINTER(RECT), POINT]
+ self.assertEqual(1, PointInRect(byref(rect), pt))
+
+ ReturnRect = dll.ReturnRect
+ ReturnRect.argtypes = [c_int, RECT, POINTER(RECT), POINT, RECT,
+ POINTER(RECT), POINT, RECT]
+ ReturnRect.restype = RECT
+ for i in range(4):
+ ret = ReturnRect(i, rect, pointer(rect), pt, rect,
+ byref(rect), pt, rect)
+ # the c function will check and modify ret if something is
+ # passed in improperly
+ self.assertEqual(ret.left, left.value)
+ self.assertEqual(ret.right, right.value)
+ self.assertEqual(ret.top, top.value)
+ self.assertEqual(ret.bottom, bottom.value)
if __name__ == '__main__':
unittest.main()
diff --git a/lib-python/2.7/decimal.py b/lib-python/2.7/decimal.py
--- a/lib-python/2.7/decimal.py
+++ b/lib-python/2.7/decimal.py
@@ -136,7 +136,6 @@
__version__ = '1.70' # Highest version of the spec this complies with
-import copy as _copy
import math as _math
import numbers as _numbers
@@ -3665,6 +3664,8 @@
if self._is_special:
sign = _format_sign(self._sign, spec)
body = str(self.copy_abs())
+ if spec['type'] == '%':
+ body += '%'
return _format_align(sign, body, spec)
# a type of None defaults to 'g' or 'G', depending on context
@@ -6033,7 +6034,10 @@
format_dict['decimal_point'] = '.'
# record whether return type should be str or unicode
- format_dict['unicode'] = isinstance(format_spec, unicode)
+ try:
+ format_dict['unicode'] = isinstance(format_spec, unicode)
+ except NameError:
+ format_dict['unicode'] = False
return format_dict
diff --git a/lib-python/2.7/distutils/__init__.py b/lib-python/2.7/distutils/__init__.py
--- a/lib-python/2.7/distutils/__init__.py
+++ b/lib-python/2.7/distutils/__init__.py
@@ -15,5 +15,5 @@
# Updated automatically by the Python release process.
#
#--start constants--
-__version__ = "2.7.8"
+__version__ = "2.7.9"
#--end constants--
diff --git a/lib-python/2.7/distutils/command/build_ext.py b/lib-python/2.7/distutils/command/build_ext.py
--- a/lib-python/2.7/distutils/command/build_ext.py
+++ b/lib-python/2.7/distutils/command/build_ext.py
@@ -245,7 +245,7 @@
# Python's library directory must be appended to library_dirs
# See Issues: #1600860, #4366
if (sysconfig.get_config_var('Py_ENABLE_SHARED')):
- if sys.executable.startswith(os.path.join(sys.exec_prefix, "bin")):
+ if not sysconfig.python_build:
# building third party extensions
self.library_dirs.append(sysconfig.get_config_var('LIBDIR'))
else:
diff --git a/lib-python/2.7/distutils/command/upload.py b/lib-python/2.7/distutils/command/upload.py
--- a/lib-python/2.7/distutils/command/upload.py
+++ b/lib-python/2.7/distutils/command/upload.py
@@ -136,8 +136,8 @@
# Build up the MIME payload for the POST data
boundary = '--------------GHSKFJDLGDS7543FJKLFHRE75642756743254'
- sep_boundary = '\n--' + boundary
- end_boundary = sep_boundary + '--'
+ sep_boundary = '\r\n--' + boundary
+ end_boundary = sep_boundary + '--\r\n'
body = StringIO.StringIO()
for key, value in data.items():
# handle multiple entries for the same name
@@ -151,14 +151,13 @@
fn = ""
body.write(sep_boundary)
- body.write('\nContent-Disposition: form-data; name="%s"'%key)
+ body.write('\r\nContent-Disposition: form-data; name="%s"' % key)
body.write(fn)
- body.write("\n\n")
+ body.write("\r\n\r\n")
body.write(value)
if value and value[-1] == '\r':
body.write('\n') # write an extra newline (lurve Macs)
body.write(end_boundary)
- body.write("\n")
body = body.getvalue()
self.announce("Submitting %s to %s" % (filename, self.repository), log.INFO)
diff --git a/lib-python/2.7/distutils/file_util.py b/lib-python/2.7/distutils/file_util.py
--- a/lib-python/2.7/distutils/file_util.py
+++ b/lib-python/2.7/distutils/file_util.py
@@ -85,7 +85,8 @@
(os.symlink) instead of copying: set it to "hard" or "sym"; if it is
None (the default), files are copied. Don't set 'link' on systems that
don't support it: 'copy_file()' doesn't check if hard or symbolic
- linking is available.
+ linking is available. If hardlink fails, falls back to
+ _copy_file_contents().
Under Mac OS, uses the native file copy function in macostools; on
other systems, uses '_copy_file_contents()' to copy file contents.
@@ -137,24 +138,31 @@
# (Unix only, of course, but that's the caller's responsibility)
if link == 'hard':
if not (os.path.exists(dst) and os.path.samefile(src, dst)):
- os.link(src, dst)
+ try:
+ os.link(src, dst)
+ return (dst, 1)
+ except OSError:
+ # If hard linking fails, fall back on copying file
+ # (some special filesystems don't support hard linking
+ # even under Unix, see issue #8876).
+ pass
elif link == 'sym':
if not (os.path.exists(dst) and os.path.samefile(src, dst)):
os.symlink(src, dst)
+ return (dst, 1)
# Otherwise (non-Mac, not linking), copy the file contents and
# (optionally) copy the times and mode.
- else:
- _copy_file_contents(src, dst)
- if preserve_mode or preserve_times:
- st = os.stat(src)
+ _copy_file_contents(src, dst)
+ if preserve_mode or preserve_times:
+ st = os.stat(src)
- # According to David Ascher <da at ski.org>, utime() should be done
- # before chmod() (at least under NT).
- if preserve_times:
- os.utime(dst, (st[ST_ATIME], st[ST_MTIME]))
- if preserve_mode:
- os.chmod(dst, S_IMODE(st[ST_MODE]))
+ # According to David Ascher <da at ski.org>, utime() should be done
+ # before chmod() (at least under NT).
+ if preserve_times:
+ os.utime(dst, (st[ST_ATIME], st[ST_MTIME]))
+ if preserve_mode:
+ os.chmod(dst, S_IMODE(st[ST_MODE]))
return (dst, 1)
diff --git a/lib-python/2.7/distutils/sysconfig_cpython.py b/lib-python/2.7/distutils/sysconfig_cpython.py
--- a/lib-python/2.7/distutils/sysconfig_cpython.py
+++ b/lib-python/2.7/distutils/sysconfig_cpython.py
@@ -165,7 +165,8 @@
# version and build tools may not support the same set
# of CPU architectures for universal builds.
global _config_vars
- if not _config_vars.get('CUSTOMIZED_OSX_COMPILER', ''):
+ # Use get_config_var() to ensure _config_vars is initialized.
+ if not get_config_var('CUSTOMIZED_OSX_COMPILER'):
import _osx_support
_osx_support.customize_compiler(_config_vars)
_config_vars['CUSTOMIZED_OSX_COMPILER'] = 'True'
diff --git a/lib-python/2.7/distutils/tests/test_bdist_rpm.py b/lib-python/2.7/distutils/tests/test_bdist_rpm.py
--- a/lib-python/2.7/distutils/tests/test_bdist_rpm.py
+++ b/lib-python/2.7/distutils/tests/test_bdist_rpm.py
@@ -25,6 +25,7 @@
"""
class BuildRpmTestCase(support.TempdirManager,
+ support.EnvironGuard,
support.LoggingSilencer,
unittest.TestCase):
@@ -50,6 +51,7 @@
def test_quiet(self):
# let's create a package
tmp_dir = self.mkdtemp()
+ os.environ['HOME'] = tmp_dir # to confine dir '.rpmdb' creation
pkg_dir = os.path.join(tmp_dir, 'foo')
os.mkdir(pkg_dir)
self.write_file((pkg_dir, 'setup.py'), SETUP_PY)
@@ -92,6 +94,7 @@
def test_no_optimize_flag(self):
# let's create a package that brakes bdist_rpm
tmp_dir = self.mkdtemp()
+ os.environ['HOME'] = tmp_dir # to confine dir '.rpmdb' creation
pkg_dir = os.path.join(tmp_dir, 'foo')
os.mkdir(pkg_dir)
self.write_file((pkg_dir, 'setup.py'), SETUP_PY)
diff --git a/lib-python/2.7/distutils/tests/test_dist.py b/lib-python/2.7/distutils/tests/test_dist.py
--- a/lib-python/2.7/distutils/tests/test_dist.py
+++ b/lib-python/2.7/distutils/tests/test_dist.py
@@ -11,7 +11,7 @@
from distutils.dist import Distribution, fix_help_options
from distutils.cmd import Command
import distutils.dist
-from test.test_support import TESTFN, captured_stdout, run_unittest
+from test.test_support import TESTFN, captured_stdout, run_unittest, unlink
from distutils.tests import support
@@ -64,6 +64,7 @@
with open(TESTFN, "w") as f:
f.write("[global]\n")
f.write("command_packages = foo.bar, splat")
+ self.addCleanup(unlink, TESTFN)
files = [TESTFN]
sys.argv.append("build")
diff --git a/lib-python/2.7/distutils/tests/test_file_util.py b/lib-python/2.7/distutils/tests/test_file_util.py
--- a/lib-python/2.7/distutils/tests/test_file_util.py
+++ b/lib-python/2.7/distutils/tests/test_file_util.py
@@ -8,6 +8,11 @@
from distutils.tests import support
from test.test_support import run_unittest
+
+requires_os_link = unittest.skipUnless(hasattr(os, "link"),
+ "test requires os.link()")
+
+
class FileUtilTestCase(support.TempdirManager, unittest.TestCase):
def _log(self, msg, *args):
@@ -74,6 +79,44 @@
copy_file(foo, dst_dir)
self.assertTrue(os.path.exists(os.path.join(dst_dir, 'foo')))
+ @requires_os_link
+ def test_copy_file_hard_link(self):
+ with open(self.source, 'w') as f:
+ f.write('some content')
+ st = os.stat(self.source)
+ copy_file(self.source, self.target, link='hard')
+ st2 = os.stat(self.source)
+ st3 = os.stat(self.target)
+ self.assertTrue(os.path.samestat(st, st2), (st, st2))
+ self.assertTrue(os.path.samestat(st2, st3), (st2, st3))
+ with open(self.source, 'r') as f:
+ self.assertEqual(f.read(), 'some content')
+
+ @requires_os_link
+ def test_copy_file_hard_link_failure(self):
+ # If hard linking fails, copy_file() falls back on copying file
+ # (some special filesystems don't support hard linking even under
+ # Unix, see issue #8876).
+ with open(self.source, 'w') as f:
+ f.write('some content')
+ st = os.stat(self.source)
+ def _os_link(*args):
+ raise OSError(0, "linking unsupported")
+ old_link = os.link
+ os.link = _os_link
+ try:
+ copy_file(self.source, self.target, link='hard')
+ finally:
+ os.link = old_link
+ st2 = os.stat(self.source)
+ st3 = os.stat(self.target)
+ self.assertTrue(os.path.samestat(st, st2), (st, st2))
+ self.assertFalse(os.path.samestat(st2, st3), (st2, st3))
+ for fn in (self.source, self.target):
+ with open(fn, 'r') as f:
+ self.assertEqual(f.read(), 'some content')
+
+
def test_suite():
return unittest.makeSuite(FileUtilTestCase)
diff --git a/lib-python/2.7/distutils/tests/test_sysconfig.py b/lib-python/2.7/distutils/tests/test_sysconfig.py
--- a/lib-python/2.7/distutils/tests/test_sysconfig.py
+++ b/lib-python/2.7/distutils/tests/test_sysconfig.py
@@ -3,6 +3,9 @@
import test
import unittest
import shutil
+import subprocess
+import sys
+import textwrap
from distutils import sysconfig
from distutils.tests import support
@@ -99,6 +102,24 @@
self.assertEqual(global_sysconfig.get_config_var('LDSHARED'), sysconfig.get_config_var('LDSHARED'))
self.assertEqual(global_sysconfig.get_config_var('CC'), sysconfig.get_config_var('CC'))
+ def test_customize_compiler_before_get_config_vars(self):
+ # Issue #21923: test that a Distribution compiler
+ # instance can be called without an explicit call to
+ # get_config_vars().
+ with open(TESTFN, 'w') as f:
+ f.writelines(textwrap.dedent('''\
+ from distutils.core import Distribution
+ config = Distribution().get_command_obj('config')
+ # try_compile may pass or it may fail if no compiler
+ # is found but it should not raise an exception.
+ rc = config.try_compile('int x;')
+ '''))
+ p = subprocess.Popen([str(sys.executable), TESTFN],
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT,
+ universal_newlines=True)
+ outs, errs = p.communicate()
+ self.assertEqual(0, p.returncode, "Subprocess failed: " + outs)
def test_suite():
diff --git a/lib-python/2.7/distutils/tests/test_upload.py b/lib-python/2.7/distutils/tests/test_upload.py
--- a/lib-python/2.7/distutils/tests/test_upload.py
+++ b/lib-python/2.7/distutils/tests/test_upload.py
@@ -119,7 +119,7 @@
# what did we send ?
self.assertIn('dédé', self.last_open.req.data)
headers = dict(self.last_open.req.headers)
- self.assertEqual(headers['Content-length'], '2085')
+ self.assertEqual(headers['Content-length'], '2159')
self.assertTrue(headers['Content-type'].startswith('multipart/form-data'))
self.assertEqual(self.last_open.req.get_method(), 'POST')
self.assertEqual(self.last_open.req.get_full_url(),
diff --git a/lib-python/2.7/doctest.py b/lib-python/2.7/doctest.py
--- a/lib-python/2.7/doctest.py
+++ b/lib-python/2.7/doctest.py
@@ -216,7 +216,7 @@
# get_data() opens files as 'rb', so one must do the equivalent
# conversion as universal newlines would do.
return file_contents.replace(os.linesep, '\n'), filename
- with open(filename) as f:
+ with open(filename, 'U') as f:
return f.read(), filename
# Use sys.stdout encoding for ouput.
diff --git a/lib-python/2.7/email/feedparser.py b/lib-python/2.7/email/feedparser.py
--- a/lib-python/2.7/email/feedparser.py
+++ b/lib-python/2.7/email/feedparser.py
@@ -49,8 +49,8 @@
simple abstraction -- it parses until EOF closes the current message.
"""
def __init__(self):
- # The last partial line pushed into this object.
- self._partial = ''
+ # Chunks of the last partial line pushed into this object.
+ self._partial = []
# The list of full, pushed lines, in reverse order
self._lines = []
# The stack of false-EOF checking predicates.
@@ -66,8 +66,8 @@
def close(self):
# Don't forget any trailing partial line.
- self._lines.append(self._partial)
- self._partial = ''
+ self.pushlines(''.join(self._partial).splitlines(True))
+ self._partial = []
self._closed = True
def readline(self):
@@ -95,8 +95,29 @@
def push(self, data):
"""Push some new data into this object."""
- # Handle any previous leftovers
- data, self._partial = self._partial + data, ''
+ # Crack into lines, but preserve the linesep characters on the end of each
+ parts = data.splitlines(True)
+
+ if not parts or not parts[0].endswith(('\n', '\r')):
+ # No new complete lines, so just accumulate partials
+ self._partial += parts
+ return
+
+ if self._partial:
+ # If there are previous leftovers, complete them now
+ self._partial.append(parts[0])
+ parts[0:1] = ''.join(self._partial).splitlines(True)
+ del self._partial[:]
+
+ # If the last element of the list does not end in a newline, then treat
+ # it as a partial line. We only check for '\n' here because a line
+ # ending with '\r' might be a line that was split in the middle of a
+ # '\r\n' sequence (see bugs 1555570 and 1721862).
+ if not parts[-1].endswith('\n'):
+ self._partial = [parts.pop()]
+ self.pushlines(parts)
+
+ def pushlines(self, lines):
# Crack into lines, but preserve the newlines on the end of each
parts = NLCRE_crack.split(data)
# The *ahem* interesting behaviour of re.split when supplied grouping
diff --git a/lib-python/2.7/email/mime/nonmultipart.py b/lib-python/2.7/email/mime/nonmultipart.py
--- a/lib-python/2.7/email/mime/nonmultipart.py
+++ b/lib-python/2.7/email/mime/nonmultipart.py
@@ -12,7 +12,7 @@
class MIMENonMultipart(MIMEBase):
- """Base class for MIME multipart/* type messages."""
+ """Base class for MIME non-multipart type messages."""
def attach(self, payload):
# The public API prohibits attaching multiple subparts to MIMEBase
diff --git a/lib-python/2.7/email/test/test_email.py b/lib-python/2.7/email/test/test_email.py
--- a/lib-python/2.7/email/test/test_email.py
+++ b/lib-python/2.7/email/test/test_email.py
@@ -11,6 +11,7 @@
import warnings
import textwrap
from cStringIO import StringIO
+from random import choice
import email
@@ -2578,16 +2579,64 @@
bsf.push(il)
nt += n
n1 = 0
- while True:
- ol = bsf.readline()
- if ol == NeedMoreData:
- break
+ for ol in iter(bsf.readline, NeedMoreData):
om.append(ol)
n1 += 1
self.assertEqual(n, n1)
self.assertEqual(len(om), nt)
self.assertEqual(''.join([il for il, n in imt]), ''.join(om))
+ def test_push_random(self):
+ from email.feedparser import BufferedSubFile, NeedMoreData
+
+ n = 10000
+ chunksize = 5
+ chars = 'abcd \t\r\n'
+
+ s = ''.join(choice(chars) for i in range(n)) + '\n'
+ target = s.splitlines(True)
+
+ bsf = BufferedSubFile()
+ lines = []
+ for i in range(0, len(s), chunksize):
+ chunk = s[i:i+chunksize]
+ bsf.push(chunk)
+ lines.extend(iter(bsf.readline, NeedMoreData))
+ self.assertEqual(lines, target)
+
+
+class TestFeedParsers(TestEmailBase):
+
+ def parse(self, chunks):
+ from email.feedparser import FeedParser
+ feedparser = FeedParser()
+ for chunk in chunks:
+ feedparser.feed(chunk)
+ return feedparser.close()
+
+ def test_newlines(self):
+ m = self.parse(['a:\nb:\rc:\r\nd:\n'])
+ self.assertEqual(m.keys(), ['a', 'b', 'c', 'd'])
+ m = self.parse(['a:\nb:\rc:\r\nd:'])
+ self.assertEqual(m.keys(), ['a', 'b', 'c', 'd'])
+ m = self.parse(['a:\rb', 'c:\n'])
+ self.assertEqual(m.keys(), ['a', 'bc'])
+ m = self.parse(['a:\r', 'b:\n'])
+ self.assertEqual(m.keys(), ['a', 'b'])
+ m = self.parse(['a:\r', '\nb:\n'])
+ self.assertEqual(m.keys(), ['a', 'b'])
+
+ def test_long_lines(self):
+ # Expected peak memory use on 32-bit platform: 4*N*M bytes.
+ M, N = 1000, 20000
+ m = self.parse(['a:b\n\n'] + ['x'*M] * N)
+ self.assertEqual(m.items(), [('a', 'b')])
+ self.assertEqual(m.get_payload(), 'x'*M*N)
+ m = self.parse(['a:b\r\r'] + ['x'*M] * N)
+ self.assertEqual(m.items(), [('a', 'b')])
+ self.assertEqual(m.get_payload(), 'x'*M*N)
+ m = self.parse(['a:\r', 'b: '] + ['x'*M] * N)
+ self.assertEqual(m.items(), [('a', ''), ('b', 'x'*M*N)])
class TestParsers(TestEmailBase):
@@ -3180,7 +3229,6 @@
self.assertEqual(res, '=?iso-8859-2?q?abc?=')
self.assertIsInstance(res, str)
-
# Test RFC 2231 header parameters (en/de)coding
class TestRFC2231(TestEmailBase):
def test_get_param(self):
diff --git a/lib-python/2.7/ensurepip/__init__.py b/lib-python/2.7/ensurepip/__init__.py
new file mode 100644
--- /dev/null
+++ b/lib-python/2.7/ensurepip/__init__.py
@@ -0,0 +1,227 @@
+#!/usr/bin/env python2
+from __future__ import print_function
+
+import os
+import os.path
+import pkgutil
+import shutil
+import sys
+import tempfile
+
+
+__all__ = ["version", "bootstrap"]
+
+
+_SETUPTOOLS_VERSION = "7.0"
+
+_PIP_VERSION = "1.5.6"
+
+# pip currently requires ssl support, so we try to provide a nicer
+# error message when that is missing (http://bugs.python.org/issue19744)
+_MISSING_SSL_MESSAGE = ("pip {} requires SSL/TLS".format(_PIP_VERSION))
+try:
+ import ssl
+except ImportError:
+ ssl = None
+
+ def _require_ssl_for_pip():
+ raise RuntimeError(_MISSING_SSL_MESSAGE)
+else:
+ def _require_ssl_for_pip():
+ pass
+
+_PROJECTS = [
+ ("setuptools", _SETUPTOOLS_VERSION),
+ ("pip", _PIP_VERSION),
+]
+
+
+def _run_pip(args, additional_paths=None):
+ # Add our bundled software to the sys.path so we can import it
+ if additional_paths is not None:
+ sys.path = additional_paths + sys.path
+
+ # Install the bundled software
+ import pip
+ pip.main(args)
+
+
+def version():
+ """
+ Returns a string specifying the bundled version of pip.
+ """
+ return _PIP_VERSION
+
+
+def _disable_pip_configuration_settings():
+ # We deliberately ignore all pip environment variables
+ # when invoking pip
+ # See http://bugs.python.org/issue19734 for details
+ keys_to_remove = [k for k in os.environ if k.startswith("PIP_")]
+ for k in keys_to_remove:
+ del os.environ[k]
+ # We also ignore the settings in the default pip configuration file
+ # See http://bugs.python.org/issue20053 for details
+ os.environ['PIP_CONFIG_FILE'] = os.devnull
+
+
+def bootstrap(root=None, upgrade=False, user=False,
+ altinstall=False, default_pip=True,
+ verbosity=0):
+ """
+ Bootstrap pip into the current Python installation (or the given root
+ directory).
+
+ Note that calling this function will alter both sys.path and os.environ.
+ """
+ if altinstall and default_pip:
+ raise ValueError("Cannot use altinstall and default_pip together")
+
+ _require_ssl_for_pip()
+ _disable_pip_configuration_settings()
+
+ # By default, installing pip and setuptools installs all of the
+ # following scripts (X.Y == running Python version):
+ #
+ # pip, pipX, pipX.Y, easy_install, easy_install-X.Y
+ #
+ # pip 1.5+ allows ensurepip to request that some of those be left out
+ if altinstall:
+ # omit pip, pipX and easy_install
+ os.environ["ENSUREPIP_OPTIONS"] = "altinstall"
+ elif not default_pip:
+ # omit pip and easy_install
+ os.environ["ENSUREPIP_OPTIONS"] = "install"
+
+ tmpdir = tempfile.mkdtemp()
+ try:
+ # Put our bundled wheels into a temporary directory and construct the
+ # additional paths that need added to sys.path
+ additional_paths = []
+ for project, version in _PROJECTS:
+ wheel_name = "{}-{}-py2.py3-none-any.whl".format(project, version)
+ whl = pkgutil.get_data(
+ "ensurepip",
+ "_bundled/{}".format(wheel_name),
+ )
+ with open(os.path.join(tmpdir, wheel_name), "wb") as fp:
+ fp.write(whl)
+
+ additional_paths.append(os.path.join(tmpdir, wheel_name))
+
+ # Construct the arguments to be passed to the pip command
+ args = ["install", "--no-index", "--find-links", tmpdir]
+ if root:
+ args += ["--root", root]
+ if upgrade:
+ args += ["--upgrade"]
+ if user:
+ args += ["--user"]
+ if verbosity:
+ args += ["-" + "v" * verbosity]
+
+ _run_pip(args + [p[0] for p in _PROJECTS], additional_paths)
+ finally:
+ shutil.rmtree(tmpdir, ignore_errors=True)
+
+
+def _uninstall_helper(verbosity=0):
+ """Helper to support a clean default uninstall process on Windows
+
+ Note that calling this function may alter os.environ.
+ """
+ # Nothing to do if pip was never installed, or has been removed
+ try:
+ import pip
+ except ImportError:
+ return
+
+ # If the pip version doesn't match the bundled one, leave it alone
+ if pip.__version__ != _PIP_VERSION:
+ msg = ("ensurepip will only uninstall a matching version "
+ "({!r} installed, {!r} bundled)")
+ print(msg.format(pip.__version__, _PIP_VERSION), file=sys.stderr)
+ return
+
+ _require_ssl_for_pip()
+ _disable_pip_configuration_settings()
+
+ # Construct the arguments to be passed to the pip command
+ args = ["uninstall", "-y"]
+ if verbosity:
+ args += ["-" + "v" * verbosity]
+
+ _run_pip(args + [p[0] for p in reversed(_PROJECTS)])
+
+
+def _main(argv=None):
+ if ssl is None:
+ print("Ignoring ensurepip failure: {}".format(_MISSING_SSL_MESSAGE),
+ file=sys.stderr)
+ return
+
+ import argparse
+ parser = argparse.ArgumentParser(prog="python -m ensurepip")
+ parser.add_argument(
+ "--version",
+ action="version",
+ version="pip {}".format(version()),
+ help="Show the version of pip that is bundled with this Python.",
+ )
+ parser.add_argument(
+ "-v", "--verbose",
+ action="count",
+ default=0,
+ dest="verbosity",
+ help=("Give more output. Option is additive, and can be used up to 3 "
+ "times."),
+ )
+ parser.add_argument(
+ "-U", "--upgrade",
+ action="store_true",
+ default=False,
+ help="Upgrade pip and dependencies, even if already installed.",
+ )
+ parser.add_argument(
+ "--user",
+ action="store_true",
+ default=False,
+ help="Install using the user scheme.",
+ )
+ parser.add_argument(
+ "--root",
+ default=None,
+ help="Install everything relative to this alternate root directory.",
+ )
+ parser.add_argument(
+ "--altinstall",
+ action="store_true",
+ default=False,
+ help=("Make an alternate install, installing only the X.Y versioned"
+ "scripts (Default: pipX, pipX.Y, easy_install-X.Y)"),
+ )
+ parser.add_argument(
+ "--default-pip",
+ action="store_true",
+ default=True,
+ dest="default_pip",
+ help=argparse.SUPPRESS,
+ )
+ parser.add_argument(
+ "--no-default-pip",
+ action="store_false",
+ dest="default_pip",
+ help=("Make a non default install, installing only the X and X.Y "
+ "versioned scripts."),
+ )
+
+ args = parser.parse_args(argv)
+
+ bootstrap(
+ root=args.root,
+ upgrade=args.upgrade,
+ user=args.user,
+ verbosity=args.verbosity,
+ altinstall=args.altinstall,
+ default_pip=args.default_pip,
+ )
diff --git a/lib-python/2.7/ensurepip/__main__.py b/lib-python/2.7/ensurepip/__main__.py
new file mode 100644
--- /dev/null
+++ b/lib-python/2.7/ensurepip/__main__.py
@@ -0,0 +1,4 @@
+import ensurepip
+
+if __name__ == "__main__":
+ ensurepip._main()
diff --git a/lib-python/2.7/ensurepip/_bundled/pip-1.5.6-py2.py3-none-any.whl b/lib-python/2.7/ensurepip/_bundled/pip-1.5.6-py2.py3-none-any.whl
new file mode 100644
index 0000000000000000000000000000000000000000..097ab43430d4c1302b0be353a8c16407c370693b
GIT binary patch
[cut]
diff --git a/lib-python/2.7/ensurepip/_bundled/setuptools-7.0-py2.py3-none-any.whl b/lib-python/2.7/ensurepip/_bundled/setuptools-7.0-py2.py3-none-any.whl
new file mode 100644
index 0000000000000000000000000000000000000000..fa1d1054da1dab98f8906555d31a9fda271b3a85
GIT binary patch
[cut]
diff --git a/lib-python/2.7/ensurepip/_uninstall.py b/lib-python/2.7/ensurepip/_uninstall.py
new file mode 100644
--- /dev/null
+++ b/lib-python/2.7/ensurepip/_uninstall.py
@@ -0,0 +1,30 @@
+"""Basic pip uninstallation support, helper for the Windows uninstaller"""
+
+import argparse
+import ensurepip
+
+
+def _main(argv=None):
+ parser = argparse.ArgumentParser(prog="python -m ensurepip._uninstall")
+ parser.add_argument(
+ "--version",
+ action="version",
+ version="pip {}".format(ensurepip.version()),
+ help="Show the version of pip this will attempt to uninstall.",
+ )
+ parser.add_argument(
+ "-v", "--verbose",
+ action="count",
+ default=0,
+ dest="verbosity",
+ help=("Give more output. Option is additive, and can be used up to 3 "
+ "times."),
+ )
+
+ args = parser.parse_args(argv)
+
+ ensurepip._uninstall_helper(verbosity=args.verbosity)
+
+
+if __name__ == "__main__":
+ _main()
diff --git a/lib-python/2.7/glob.py b/lib-python/2.7/glob.py
--- a/lib-python/2.7/glob.py
+++ b/lib-python/2.7/glob.py
@@ -35,11 +35,16 @@
patterns.
"""
+ dirname, basename = os.path.split(pathname)
if not has_magic(pathname):
- if os.path.lexists(pathname):
- yield pathname
+ if basename:
+ if os.path.lexists(pathname):
+ yield pathname
+ else:
+ # Patterns ending with a slash should match only directories
+ if os.path.isdir(dirname):
+ yield pathname
return
- dirname, basename = os.path.split(pathname)
if not dirname:
for name in glob1(os.curdir, basename):
yield name
diff --git a/lib-python/2.7/gzip.py b/lib-python/2.7/gzip.py
--- a/lib-python/2.7/gzip.py
+++ b/lib-python/2.7/gzip.py
@@ -164,9 +164,16 @@
def _write_gzip_header(self):
self.fileobj.write('\037\213') # magic header
self.fileobj.write('\010') # compression method
- fname = os.path.basename(self.name)
- if fname.endswith(".gz"):
- fname = fname[:-3]
+ try:
+ # RFC 1952 requires the FNAME field to be Latin-1. Do not
+ # include filenames that cannot be represented that way.
+ fname = os.path.basename(self.name)
+ if not isinstance(fname, str):
+ fname = fname.encode('latin-1')
+ if fname.endswith('.gz'):
+ fname = fname[:-3]
+ except UnicodeEncodeError:
+ fname = ''
flags = 0
if fname:
flags = FNAME
diff --git a/lib-python/2.7/hashlib.py b/lib-python/2.7/hashlib.py
--- a/lib-python/2.7/hashlib.py
+++ b/lib-python/2.7/hashlib.py
@@ -15,8 +15,9 @@
md5(), sha1(), sha224(), sha256(), sha384(), and sha512()
-More algorithms may be available on your platform but the above are
-guaranteed to exist.
+More algorithms may be available on your platform but the above are guaranteed
+to exist. See the algorithms_guaranteed and algorithms_available attributes
+to find out what algorithm names can be passed to new().
NOTE: If you want the adler32 or crc32 hash functions they are available in
the zlib module.
@@ -58,9 +59,14 @@
# always available algorithm is added.
__always_supported = ('md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512')
+algorithms_guaranteed = set(__always_supported)
+algorithms_available = set(__always_supported)
+
algorithms = __always_supported
-__all__ = __always_supported + ('new', 'algorithms', 'pbkdf2_hmac')
+__all__ = __always_supported + ('new', 'algorithms_guaranteed',
+ 'algorithms_available', 'algorithms',
+ 'pbkdf2_hmac')
def __get_builtin_constructor(name):
@@ -128,6 +134,8 @@
import _hashlib
new = __hash_new
__get_hash = __get_openssl_constructor
+ algorithms_available = algorithms_available.union(
+ _hashlib.openssl_md_meth_names)
except ImportError:
new = __py_new
__get_hash = __get_builtin_constructor
diff --git a/lib-python/2.7/httplib.py b/lib-python/2.7/httplib.py
--- a/lib-python/2.7/httplib.py
+++ b/lib-python/2.7/httplib.py
@@ -215,6 +215,10 @@
# maximal line length when calling readline().
_MAXLINE = 65536
+# maximum amount of headers accepted
+_MAXHEADERS = 100
+
+
class HTTPMessage(mimetools.Message):
def addheader(self, key, value):
@@ -271,6 +275,8 @@
elif self.seekable:
tell = self.fp.tell
while True:
+ if len(hlist) > _MAXHEADERS:
+ raise HTTPException("got more than %d headers" % _MAXHEADERS)
if tell:
try:
startofline = tell()
@@ -1185,21 +1191,29 @@
def __init__(self, host, port=None, key_file=None, cert_file=None,
strict=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT,
- source_address=None):
+ source_address=None, context=None):
HTTPConnection.__init__(self, host, port, strict, timeout,
source_address)
self.key_file = key_file
self.cert_file = cert_file
+ if context is None:
+ context = ssl._create_default_https_context()
+ if key_file or cert_file:
+ context.load_cert_chain(cert_file, key_file)
+ self._context = context
def connect(self):
"Connect to a host on a given (SSL) port."
- sock = self._create_connection((self.host, self.port),
- self.timeout, self.source_address)
+ HTTPConnection.connect(self)
+
if self._tunnel_host:
- self.sock = sock
- self._tunnel()
- self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file)
+ server_hostname = self._tunnel_host
+ else:
+ server_hostname = self.host
+
+ self.sock = self._context.wrap_socket(self.sock,
+ server_hostname=server_hostname)
__all__.append("HTTPSConnection")
@@ -1214,14 +1228,15 @@
_connection_class = HTTPSConnection
def __init__(self, host='', port=None, key_file=None, cert_file=None,
- strict=None):
+ strict=None, context=None):
# provide a default host, pass the X509 cert info
# urf. compensate for bad input.
if port == 0:
port = None
self._setup(self._connection_class(host, port, key_file,
- cert_file, strict))
+ cert_file, strict,
+ context=context))
# we never actually use these for anything, but we keep them
# here for compatibility with post-1.5.2 CVS.
diff --git a/lib-python/2.7/idlelib/Bindings.py b/lib-python/2.7/idlelib/Bindings.py
--- a/lib-python/2.7/idlelib/Bindings.py
+++ b/lib-python/2.7/idlelib/Bindings.py
@@ -75,7 +75,8 @@
('!_Auto-open Stack Viewer', '<<toggle-jit-stack-viewer>>'),
]),
('options', [
- ('_Configure IDLE...', '<<open-config-dialog>>'),
+ ('Configure _IDLE', '<<open-config-dialog>>'),
+ ('Configure _Extensions', '<<open-config-extensions-dialog>>'),
None,
]),
('help', [
diff --git a/lib-python/2.7/idlelib/CallTipWindow.py b/lib-python/2.7/idlelib/CallTipWindow.py
--- a/lib-python/2.7/idlelib/CallTipWindow.py
+++ b/lib-python/2.7/idlelib/CallTipWindow.py
@@ -2,9 +2,8 @@
After ToolTip.py, which uses ideas gleaned from PySol
Used by the CallTips IDLE extension.
-
"""
-from Tkinter import *
+from Tkinter import Toplevel, Label, LEFT, SOLID, TclError
HIDE_VIRTUAL_EVENT_NAME = "<<calltipwindow-hide>>"
HIDE_SEQUENCES = ("<Key-Escape>", "<FocusOut>")
@@ -133,35 +132,28 @@
return bool(self.tipwindow)
-def _calltip_window(parent):
- root = Tk()
- root.title("Test calltips")
- width, height, x, y = list(map(int, re.split('[x+]', parent.geometry())))
- root.geometry("+%d+%d"%(x, y + 150))
+def _calltip_window(parent): # htest #
+ from Tkinter import Toplevel, Text, LEFT, BOTH
- class MyEditWin: # comparenceptually an editor_window
- def __init__(self):
- text = self.text = Text(root)
- text.pack(side=LEFT, fill=BOTH, expand=1)
- text.insert("insert", "string.split")
- root.update()
- self.calltip = CallTip(text)
+ top = Toplevel(parent)
+ top.title("Test calltips")
+ top.geometry("200x100+%d+%d" % (parent.winfo_rootx() + 200,
+ parent.winfo_rooty() + 150))
+ text = Text(top)
+ text.pack(side=LEFT, fill=BOTH, expand=1)
+ text.insert("insert", "string.split")
+ top.update()
+ calltip = CallTip(text)
- text.event_add("<<calltip-show>>", "(")
- text.event_add("<<calltip-hide>>", ")")
- text.bind("<<calltip-show>>", self.calltip_show)
- text.bind("<<calltip-hide>>", self.calltip_hide)
-
- text.focus_set()
- root.mainloop()
-
- def calltip_show(self, event):
- self.calltip.showtip("Hello world", "insert", "end")
-
- def calltip_hide(self, event):
- self.calltip.hidetip()
-
- editwin = MyEditWin()
+ def calltip_show(event):
+ calltip.showtip("(s=Hello world)", "insert", "end")
+ def calltip_hide(event):
+ calltip.hidetip()
+ text.event_add("<<calltip-show>>", "(")
+ text.event_add("<<calltip-hide>>", ")")
+ text.bind("<<calltip-show>>", calltip_show)
+ text.bind("<<calltip-hide>>", calltip_hide)
+ text.focus_set()
if __name__=='__main__':
from idlelib.idle_test.htest import run
diff --git a/lib-python/2.7/idlelib/ClassBrowser.py b/lib-python/2.7/idlelib/ClassBrowser.py
--- a/lib-python/2.7/idlelib/ClassBrowser.py
+++ b/lib-python/2.7/idlelib/ClassBrowser.py
@@ -19,6 +19,9 @@
from idlelib.TreeWidget import TreeNode, TreeItem, ScrolledCanvas
from idlelib.configHandler import idleConf
+file_open = None # Method...Item and Class...Item use this.
+# Normally PyShell.flist.open, but there is no PyShell.flist for htest.
+
class ClassBrowser:
def __init__(self, flist, name, path, _htest=False):
@@ -27,6 +30,9 @@
"""
_htest - bool, change box when location running htest.
"""
+ global file_open
+ if not _htest:
+ file_open = PyShell.flist.open
self.name = name
self.file = os.path.join(path[0], self.name + ".py")
self._htest = _htest
@@ -101,7 +107,7 @@
return []
try:
dict = pyclbr.readmodule_ex(name, [dir] + sys.path)
- except ImportError, msg:
+ except ImportError:
return []
items = []
self.classes = {}
@@ -170,7 +176,7 @@
def OnDoubleClick(self):
if not os.path.exists(self.file):
return
- edit = PyShell.flist.open(self.file)
+ edit = file_open(self.file)
if hasattr(self.cl, 'lineno'):
lineno = self.cl.lineno
edit.gotoline(lineno)
@@ -206,7 +212,7 @@
def OnDoubleClick(self):
if not os.path.exists(self.file):
return
- edit = PyShell.flist.open(self.file)
+ edit = file_open(self.file)
edit.gotoline(self.cl.methods[self.name])
def _class_browser(parent): #Wrapper for htest
@@ -221,8 +227,9 @@
dir, file = os.path.split(file)
name = os.path.splitext(file)[0]
flist = PyShell.PyShellFileList(parent)
+ global file_open
+ file_open = flist.open
ClassBrowser(flist, name, [dir], _htest=True)
- parent.mainloop()
if __name__ == "__main__":
from idlelib.idle_test.htest import run
diff --git a/lib-python/2.7/idlelib/ColorDelegator.py b/lib-python/2.7/idlelib/ColorDelegator.py
--- a/lib-python/2.7/idlelib/ColorDelegator.py
+++ b/lib-python/2.7/idlelib/ColorDelegator.py
@@ -2,7 +2,6 @@
import re
import keyword
import __builtin__
-from Tkinter import *
from idlelib.Delegator import Delegator
from idlelib.configHandler import idleConf
@@ -34,7 +33,6 @@
prog = re.compile(make_pat(), re.S)
idprog = re.compile(r"\s+(\w+)", re.S)
-asprog = re.compile(r".*?\b(as)\b")
class ColorDelegator(Delegator):
@@ -42,7 +40,6 @@
Delegator.__init__(self)
self.prog = prog
self.idprog = idprog
- self.asprog = asprog
self.LoadTagDefs()
def setdelegate(self, delegate):
@@ -74,7 +71,6 @@
"DEFINITION": idleConf.GetHighlight(theme, "definition"),
"SYNC": {'background':None,'foreground':None},
"TODO": {'background':None,'foreground':None},
- "BREAK": idleConf.GetHighlight(theme, "break"),
"ERROR": idleConf.GetHighlight(theme, "error"),
# The following is used by ReplaceDialog:
"hit": idleConf.GetHighlight(theme, "hit"),
@@ -216,22 +212,6 @@
self.tag_add("DEFINITION",
head + "+%dc" % a,
head + "+%dc" % b)
- elif value == "import":
- # color all the "as" words on same line, except
- # if in a comment; cheap approximation to the
- # truth
- if '#' in chars:
- endpos = chars.index('#')
- else:
- endpos = len(chars)
- while True:
- m1 = self.asprog.match(chars, b, endpos)
- if not m1:
- break
- a, b = m1.span(1)
- self.tag_add("KEYWORD",
- head + "+%dc" % a,
- head + "+%dc" % b)
m = self.prog.search(chars, m.end())
if "SYNC" in self.tag_names(next + "-1c"):
head = next
@@ -255,20 +235,23 @@
for tag in self.tagdefs.keys():
self.tag_remove(tag, "1.0", "end")
-def _color_delegator(parent):
+def _color_delegator(parent): # htest #
+ from Tkinter import Toplevel, Text
from idlelib.Percolator import Percolator
- root = Tk()
- root.title("Test ColorDelegator")
- width, height, x, y = list(map(int, re.split('[x+]', parent.geometry())))
- root.geometry("+%d+%d"%(x, y + 150))
- source = "if somename: x = 'abc' # comment\nprint"
- text = Text(root, background="white")
+
+ top = Toplevel(parent)
+ top.title("Test ColorDelegator")
+ top.geometry("200x100+%d+%d" % (parent.winfo_rootx() + 200,
+ parent.winfo_rooty() + 150))
+ source = "if somename: x = 'abc' # comment\nprint\n"
+ text = Text(top, background="white")
+ text.pack(expand=1, fill="both")
text.insert("insert", source)
- text.pack(expand=1, fill="both")
+ text.focus_set()
+
p = Percolator(text)
d = ColorDelegator()
p.insertfilter(d)
- root.mainloop()
if __name__ == "__main__":
from idlelib.idle_test.htest import run
diff --git a/lib-python/2.7/idlelib/Debugger.py b/lib-python/2.7/idlelib/Debugger.py
--- a/lib-python/2.7/idlelib/Debugger.py
+++ b/lib-python/2.7/idlelib/Debugger.py
@@ -1,6 +1,5 @@
import os
import bdb
-import types
from Tkinter import *
from idlelib.WindowList import ListedToplevel
from idlelib.ScrolledList import ScrolledList
diff --git a/lib-python/2.7/idlelib/EditorWindow.py b/lib-python/2.7/idlelib/EditorWindow.py
--- a/lib-python/2.7/idlelib/EditorWindow.py
+++ b/lib-python/2.7/idlelib/EditorWindow.py
@@ -1,6 +1,6 @@
import sys
import os
-from platform import python_version
+import platform
import re
import imp
from Tkinter import *
@@ -22,6 +22,8 @@
# The default tab setting for a Text widget, in average-width characters.
TK_TABWIDTH_DEFAULT = 8
+_py_version = ' (%s)' % platform.python_version()
+
def _sphinx_version():
"Format sys.version_info to produce the Sphinx version string used to install the chm docs"
major, minor, micro, level, serial = sys.version_info
@@ -151,7 +153,7 @@
# Safari requires real file:-URLs
EditorWindow.help_url = 'file://' + EditorWindow.help_url
else:
- EditorWindow.help_url = "http://docs.python.org/%d.%d" % sys.version_info[:2]
+ EditorWindow.help_url = "https://docs.python.org/%d.%d/" % sys.version_info[:2]
currentTheme=idleConf.CurrentTheme()
self.flist = flist
root = root or flist.root
@@ -214,6 +216,8 @@
text.bind("<<python-docs>>", self.python_docs)
text.bind("<<about-idle>>", self.about_dialog)
text.bind("<<open-config-dialog>>", self.config_dialog)
+ text.bind("<<open-config-extensions-dialog>>",
+ self.config_extensions_dialog)
text.bind("<<open-module>>", self.open_module)
text.bind("<<do-nothing>>", lambda event: "break")
text.bind("<<select-all>>", self.select_all)
@@ -568,6 +572,8 @@
def config_dialog(self, event=None):
configDialog.ConfigDialog(self.top,'Settings')
+ def config_extensions_dialog(self, event=None):
+ configDialog.ConfigExtensionsDialog(self.top)
def help_dialog(self, event=None):
if self.root:
@@ -691,30 +697,29 @@
return
# XXX Ought to insert current file's directory in front of path
try:
- (f, file, (suffix, mode, type)) = _find_module(name)
+ (f, file_path, (suffix, mode, mtype)) = _find_module(name)
except (NameError, ImportError) as msg:
tkMessageBox.showerror("Import error", str(msg), parent=self.text)
return
- if type != imp.PY_SOURCE:
+ if mtype != imp.PY_SOURCE:
tkMessageBox.showerror("Unsupported type",
"%s is not a source module" % name, parent=self.text)
return
if f:
f.close()
if self.flist:
- self.flist.open(file)
+ self.flist.open(file_path)
else:
- self.io.loadfile(file)
+ self.io.loadfile(file_path)
+ return file_path
def open_class_browser(self, event=None):
filename = self.io.filename
- if not filename:
- tkMessageBox.showerror(
- "No filename",
- "This buffer has no associated filename",
- master=self.text)
- self.text.focus_set()
- return None
+ if not (self.__class__.__name__ == 'PyShellEditorWindow'
+ and filename):
+ filename = self.open_module()
+ if filename is None:
+ return
head, tail = os.path.split(filename)
base, ext = os.path.splitext(tail)
from idlelib import ClassBrowser
@@ -779,7 +784,7 @@
self.color = None
def ResetColorizer(self):
- "Update the colour theme"
+ "Update the color theme"
# Called from self.filename_change_hook and from configDialog.py
self._rmcolorizer()
self._addcolorizer()
@@ -944,7 +949,7 @@
short = self.short_title()
long = self.long_title()
if short and long:
- title = short + " - " + long
+ title = short + " - " + long + _py_version
elif short:
title = short
elif long:
@@ -968,14 +973,13 @@
self.undo.reset_undo()
def short_title(self):
- pyversion = "Python " + python_version() + ": "
filename = self.io.filename
if filename:
filename = os.path.basename(filename)
else:
filename = "Untitled"
# return unicode string to display non-ASCII chars correctly
- return pyversion + self._filename_to_unicode(filename)
+ return self._filename_to_unicode(filename)
def long_title(self):
# return unicode string to display non-ASCII chars correctly
@@ -1711,7 +1715,8 @@
tk.call('set', 'tcl_nonwordchars', '[^a-zA-Z0-9_]')
-def _editor_window(parent):
+def _editor_window(parent): # htest #
+ # error if close master window first - timer event, after script
root = parent
fixwordbreaks(root)
if sys.argv[1:]:
@@ -1721,7 +1726,8 @@
macosxSupport.setupApp(root, None)
edit = EditorWindow(root=root, filename=filename)
edit.text.bind("<<close-all-windows>>", edit.close_event)
- parent.mainloop()
+ # Does not stop error, neither does following
+ # edit.text.bind("<<close-window>>", edit.close_event)
if __name__ == '__main__':
diff --git a/lib-python/2.7/idlelib/GrepDialog.py b/lib-python/2.7/idlelib/GrepDialog.py
--- a/lib-python/2.7/idlelib/GrepDialog.py
+++ b/lib-python/2.7/idlelib/GrepDialog.py
@@ -45,10 +45,10 @@
def create_entries(self):
SearchDialogBase.create_entries(self)
- self.globent = self.make_entry("In files:", self.globvar)
+ self.globent = self.make_entry("In files:", self.globvar)[0]
def create_other_buttons(self):
- f = self.make_frame()
+ f = self.make_frame()[0]
btn = Checkbutton(f, anchor="w",
variable=self.recvar,
@@ -131,7 +131,7 @@
self.top.withdraw()
-def _grep_dialog(parent): # for htest
+def _grep_dialog(parent): # htest #
from idlelib.PyShell import PyShellFileList
root = Tk()
root.title("Test GrepDialog")
diff --git a/lib-python/2.7/idlelib/IOBinding.py b/lib-python/2.7/idlelib/IOBinding.py
--- a/lib-python/2.7/idlelib/IOBinding.py
+++ b/lib-python/2.7/idlelib/IOBinding.py
@@ -19,11 +19,7 @@
from idlelib.configHandler import idleConf
-try:
- from codecs import BOM_UTF8
-except ImportError:
- # only available since Python 2.3
- BOM_UTF8 = '\xef\xbb\xbf'
+from codecs import BOM_UTF8
# Try setting the locale, so that we can find out
# what encoding to use
@@ -72,6 +68,7 @@
encoding = encoding.lower()
coding_re = re.compile(r'^[ \t\f]*#.*coding[:=][ \t]*([-\w.]+)')
+blank_re = re.compile(r'^[ \t\f]*(?:[#\r\n]|$)')
class EncodingMessage(SimpleDialog):
"Inform user that an encoding declaration is needed."
@@ -130,6 +127,8 @@
match = coding_re.match(line)
if match is not None:
break
+ if not blank_re.match(line):
+ return None
else:
return None
name = match.group(1)
@@ -529,6 +528,8 @@
("All files", "*"),
]
+ defaultextension = '.py' if sys.platform == 'darwin' else ''
+
def askopenfile(self):
dir, base = self.defaultfilename("open")
if not self.opendialog:
@@ -554,8 +555,10 @@
def asksavefile(self):
dir, base = self.defaultfilename("save")
if not self.savedialog:
- self.savedialog = tkFileDialog.SaveAs(master=self.text,
- filetypes=self.filetypes)
+ self.savedialog = tkFileDialog.SaveAs(
+ master=self.text,
+ filetypes=self.filetypes,
+ defaultextension=self.defaultextension)
filename = self.savedialog.show(initialdir=dir, initialfile=base)
if isinstance(filename, unicode):
filename = filename.encode(filesystemencoding)
diff --git a/lib-python/2.7/idlelib/NEWS.txt b/lib-python/2.7/idlelib/NEWS.txt
--- a/lib-python/2.7/idlelib/NEWS.txt
+++ b/lib-python/2.7/idlelib/NEWS.txt
@@ -1,6 +1,183 @@
+What's New in IDLE 2.7.9?
+=========================
+
+*Release data: 2014-12-07* (projected)
+
+- Issue #16893: Update Idle doc chapter to match current Idle and add new
+ information.
+
+- Issue #3068: Add Idle extension configuration dialog to Options menu.
+ Changes are written to HOME/.idlerc/config-extensions.cfg.
+ Original patch by Tal Einat.
+
+- Issue #16233: A module browser (File : Class Browser, Alt+C) requires a
+ editor window with a filename. When Class Browser is requested otherwise,
+ from a shell, output window, or 'Untitled' editor, Idle no longer displays
+ an error box. It now pops up an Open Module box (Alt+M). If a valid name
+ is entered and a module is opened, a corresponding browser is also opened.
+
+- Issue #4832: Save As to type Python files automatically adds .py to the
+ name you enter (even if your system does not display it). Some systems
+ automatically add .txt when type is Text files.
+
+- Issue #21986: Code objects are not normally pickled by the pickle module.
+ To match this, they are no longer pickled when running under Idle.
+
+- Issue #22221: IDLE now ignores the source encoding declaration on the second
+ line if the first line contains anything except a comment.
+
+- Issue #17390: Adjust Editor window title; remove 'Python',
+ move version to end.
+
+- Issue #14105: Idle debugger breakpoints no longer disappear
+ when inseting or deleting lines.
+
+
+What's New in IDLE 2.7.8?
+=========================
+
+*Release date: 2014-06-29*
+
+- Issue #21940: Add unittest for WidgetRedirector. Initial patch by Saimadhav
+ Heblikar.
+
+- Issue #18592: Add unittest for SearchDialogBase. Patch by Phil Webster.
+
+- Issue #21694: Add unittest for ParenMatch. Patch by Saimadhav Heblikar.
+
+- Issue #21686: add unittest for HyperParser. Original patch by Saimadhav
+ Heblikar.
+
+- Issue #12387: Add missing upper(lower)case versions of default Windows key
+ bindings for Idle so Caps Lock does not disable them. Patch by Roger Serwy.
+
+- Issue #21695: Closing a Find-in-files output window while the search is
+ still in progress no longer closes Idle.
+
+- Issue #18910: Add unittest for textView. Patch by Phil Webster.
+
+- Issue #18292: Add unittest for AutoExpand. Patch by Saihadhav Heblikar.
+
+- Issue #18409: Add unittest for AutoComplete. Patch by Phil Webster.
+
+
+What's New in IDLE 2.7.7?
+=========================
+
+*Release date: 2014-05-31*
+
+- Issue #18104: Add idlelib/idle_test/htest.py with a few sample tests to begin
+ consolidating and improving human-validated tests of Idle. Change other files
+ as needed to work with htest. Running the module as __main__ runs all tests.
+
+- Issue #21139: Change default paragraph width to 72, the PEP 8 recommendation.
+
+- Issue #21284: Paragraph reformat test passes after user changes reformat width.
+
+- Issue #20406: Use Python application icons for Idle window title bars.
+ Patch mostly by Serhiy Storchaka.
+
+- Issue #21029: Occurrences of "print" are now consistently colored as
+ being a keyword (the colorizer doesn't know if print functions are
+ enabled in the source).
+
+- Issue #17721: Remove non-functional configuration dialog help button until we
+ make it actually gives some help when clicked. Patch by Guilherme Sim�es.
+
+- Issue #17390: Add Python version to Idle editor window title bar.
+ Original patches by Edmond Burnett and Kent Johnson.
+
+- Issue #20058: sys.stdin.readline() in IDLE now always returns only one line.
+
+- Issue #19481: print() of unicode, str or bytearray subclass instance in IDLE
+ no more hangs.
+
+- Issue #18270: Prevent possible IDLE AttributeError on OS X when no initial
+ shell window is present.
+
+- Issue #17654: Ensure IDLE menus are customized properly on OS X for
+ non-framework builds and for all variants of Tk.
+
+
+What's New in IDLE 2.7.6?
+=========================
+
+*Release date: 2013-11-10*
+
+- Issue #19426: Fixed the opening of Python source file with specified encoding.
+
+- Issue #18873: IDLE now detects Python source code encoding only in comment
+ lines.
+
+- Issue #18988: The "Tab" key now works when a word is already autocompleted.
+
+- Issue #18489: Add tests for SearchEngine. Original patch by Phil Webster.
+
+- Issue #18429: Format / Format Paragraph, now works when comment blocks
+ are selected. As with text blocks, this works best when the selection
+ only includes complete lines.
+
+- Issue #18226: Add docstrings and unittests for FormatParagraph.py.
+ Original patches by Todd Rovito and Phil Webster.
+
+- Issue #18279: Format - Strip trailing whitespace no longer marks a file as
+ changed when it has not been changed. This fix followed the addition of a
+ test file originally written by Phil Webster (the issue's main goal).
+
+- Issue #18539: Calltips now work for float default arguments.
+
+- Issue #7136: In the Idle File menu, "New Window" is renamed "New File".
+ Patch by Tal Einat, Roget Serwy, and Todd Rovito.
+
+- Issue #8515: Set __file__ when run file in IDLE.
+ Initial patch by Bruce Frederiksen.
+
+- Issue #5492: Avoid traceback when exiting IDLE caused by a race condition.
+
+- Issue #17511: Keep IDLE find dialog open after clicking "Find Next".
+ Original patch by Sarah K.
+
+- Issue #15392: Create a unittest framework for IDLE.
+ Preliminary patch by Rajagopalasarma Jayakrishnan
+ See Lib/idlelib/idle_test/README.txt for how to run Idle tests.
+
+- Issue #14146: Highlight source line while debugging on Windows.
+
+- Issue #17532: Always include Options menu for IDLE on OS X.
+ Patch by Guilherme Sim�es.
+
+
What's New in IDLE 2.7.5?
=========================
+*Release date: 2013-05-12*
+
+- Issue #17838: Allow sys.stdin to be reassigned.
+
+- Issue #14735: Update IDLE docs to omit "Control-z on Windows".
+
+- Issue #17585: Fixed IDLE regression. Now closes when using exit() or quit().
+
+- Issue #17657: Show full Tk version in IDLE's about dialog.
+ Patch by Todd Rovito.
+
+- Issue #17613: Prevent traceback when removing syntax colorizer in IDLE.
+
+- Issue #1207589: Backwards-compatibility patch for right-click menu in IDLE.
+
+- Issue #16887: IDLE now accepts Cancel in tabify/untabify dialog box.
+
+- Issue #14254: IDLE now handles readline correctly across shell restarts.
+
+- Issue #17614: IDLE no longer raises exception when quickly closing a file.
+
+- Issue #6698: IDLE now opens just an editor window when configured to do so.
+
+- Issue #8900: Using keyboard shortcuts in IDLE to open a file no longer
+ raises an exception.
+
+- Issue #6649: Fixed missing exit status in IDLE. Patch by Guilherme Polo.
+
- Issue #17390: Display Python version on Idle title bar.
Initial patch by Edmond Burnett.
@@ -8,17 +185,67 @@
What's New in IDLE 2.7.4?
=========================
+*Release date: 2013-04-06*
+
+- Issue #17625: In IDLE, close the replace dialog after it is used.
+
+- IDLE was displaying spurious SystemExit tracebacks when running scripts
+ that terminated by raising SystemExit (i.e. unittest and turtledemo).
+
+- Issue #9290: In IDLE the sys.std* streams now implement io.TextIOBase
+ interface and support all mandatory methods and properties.
+
+- Issue #16829: IDLE printing no longer fails if there are spaces or other
+ special characters in the file path.
+
+- Issue #16819: IDLE method completion now correctly works for unicode literals.
+
+- Issue #16504: IDLE now catches SyntaxErrors raised by tokenizer. Patch by
+ Roger Serwy.
+
+- Issue #1207589: Add Cut/Copy/Paste items to IDLE right click Context Menu
+ Patch by Todd Rovito.
+
+- Issue #13052: Fix IDLE crashing when replace string in Search/Replace dialog
+ ended with '\'. Patch by Roger Serwy.
+
+- Issue #9803: Don't close IDLE on saving if breakpoint is open.
+ Patch by Roger Serwy.
+
+- 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.
+
+- Issue #10997: Prevent a duplicate entry in IDLE's "Recent Files" menu.
+
+- Issue #12510: Attempting to get invalid tooltip no longer closes IDLE.
+ Original patch by Roger Serwy.
+
+- Issue #10365: File open dialog now works instead of crashing
+ even when parent window is closed. Patch by Roger Serwy.
+
+- Issue #14876: Use user-selected font for highlight configuration.
+ Patch by Roger Serwy.
+
+- Issue #14409: IDLE now properly executes commands in the Shell window
+ when it cannot read the normal config files on startup and
+ has to use the built-in default key bindings.
+ There was previously a bug in one of the defaults.
+
+- Issue #3573: IDLE hangs when passing invalid command line args
+ (directory(ies) instead of file(s)) (Patch by Guilherme Polo)
+
+- Issue #5219: Prevent event handler cascade in IDLE.
+
- Issue #15318: Prevent writing to sys.stdin.
- Issue #13532, #15319: Check that arguments to sys.stdout.write are strings.
-- Issue # 12510: Attempt to get certain tool tips no longer crashes IDLE.
-
-- Issue10365: File open dialog now works instead of crashing even when
+- Issue #10365: File open dialog now works instead of crashing even when
parent window is closed while dialog is open.
-- Issue 14876: use user-selected font for highlight configuration.
-
- Issue #14018: Update checks for unstable system Tcl/Tk versions on OS X
to include versions shipped with OS X 10.7 and 10.8 in addition to 10.6.
@@ -29,6 +256,27 @@
More information about the pypy-commit
mailing list