summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Doc/faq/general.rst14
-rw-r--r--Doc/whatsnew/3.3.rst2
-rw-r--r--Lib/codecs.py13
-rw-r--r--Lib/contextlib.py4
-rw-r--r--Lib/http/server.py24
-rw-r--r--Lib/imghdr.py20
-rw-r--r--Lib/mailcap.py4
-rw-r--r--Lib/mimetypes.py7
-rw-r--r--Lib/test/imghdrdata/python.bmpbin0 -> 1162 bytes
-rw-r--r--Lib/test/imghdrdata/python.gifbin0 -> 610 bytes
-rw-r--r--Lib/test/imghdrdata/python.jpgbin0 -> 543 bytes
-rw-r--r--Lib/test/imghdrdata/python.pbm3
-rw-r--r--Lib/test/imghdrdata/python.pgmbin0 -> 269 bytes
-rw-r--r--Lib/test/imghdrdata/python.pngbin0 -> 1020 bytes
-rw-r--r--Lib/test/imghdrdata/python.ppmbin0 -> 781 bytes
-rw-r--r--Lib/test/imghdrdata/python.rasbin0 -> 1056 bytes
-rw-r--r--Lib/test/imghdrdata/python.sgibin0 -> 1967 bytes
-rw-r--r--Lib/test/imghdrdata/python.tiffbin0 -> 1326 bytes
-rw-r--r--Lib/test/imghdrdata/python.xbm6
-rw-r--r--Lib/test/test_codecs.py36
-rw-r--r--Lib/test/test_contextlib.py58
-rw-r--r--Lib/test/test_epoll.py11
-rw-r--r--Lib/test/test_imghdr.py131
-rw-r--r--Lib/test/test_sundry.py1
-rw-r--r--Lib/test/test_tarfile.py7
-rw-r--r--Lib/test/test_tcl.py39
-rw-r--r--Lib/xml/etree/ElementInclude.py9
-rw-r--r--Misc/NEWS13
-rwxr-xr-x[-rw-r--r--]Modules/_ctypes/libffi/build-ios.sh0
-rwxr-xr-x[-rw-r--r--]Modules/_ctypes/libffi/libtool-ldflags0
-rwxr-xr-x[-rw-r--r--]Modules/_ctypes/libffi/msvcc.sh0
-rwxr-xr-x[-rw-r--r--]Modules/_ctypes/libffi/src/arm/gentramp.sh0
-rw-r--r--Modules/readline.c8
-rw-r--r--Modules/selectmodule.c4
34 files changed, 332 insertions, 82 deletions
diff --git a/Doc/faq/general.rst b/Doc/faq/general.rst
index 9a893ec..da2c933 100644
--- a/Doc/faq/general.rst
+++ b/Doc/faq/general.rst
@@ -181,8 +181,8 @@ at http://docs.python.org/. PDF, plain text, and downloadable HTML versions are
also available at http://docs.python.org/download.html.
The documentation is written in reStructuredText and processed by `the Sphinx
-documentation tool <http://sphinx.pocoo.org/>`__. The reStructuredText source
-for the documentation is part of the Python source distribution.
+documentation tool <http://sphinx-doc.org/>`__. The reStructuredText source for
+the documentation is part of the Python source distribution.
I've never programmed before. Is there a Python tutorial?
@@ -268,9 +268,13 @@ Python references; or perhaps search for "Python" and "language".
Where in the world is www.python.org located?
---------------------------------------------
-It's currently in Amsterdam, graciously hosted by `XS4ALL
-<http://www.xs4all.nl>`_. Thanks to Thomas Wouters for his work in arranging
-python.org's hosting.
+The Python project's infrastructure is located all over the world.
+`www.python.org <http://www.python.org>`_ is currently in Amsterdam, graciously
+hosted by `XS4ALL <http://www.xs4all.nl>`_. `Upfront Systems
+<http://www.upfrontsystems.co.za>`_ hosts `bugs.python.org
+<http://bugs.python.org>`_. Most other Python services like `PyPI
+<https://pypi.python.org>`_ and hg.python.org are hosted by `Oregon State
+University Open Source Lab <https://osuosl.org>`_.
Why is it called Python?
diff --git a/Doc/whatsnew/3.3.rst b/Doc/whatsnew/3.3.rst
index b44a2fe..cda63e4 100644
--- a/Doc/whatsnew/3.3.rst
+++ b/Doc/whatsnew/3.3.rst
@@ -1767,7 +1767,7 @@ sched
select
------
-Solaris and derivatives platforms have a new class :class:`select.devpoll`
+Solaris and derivative platforms have a new class :class:`select.devpoll`
for high performance asynchronous sockets via :file:`/dev/poll`.
(Contributed by Jesús Cea Avión in :issue:`6397`.)
diff --git a/Lib/codecs.py b/Lib/codecs.py
index 6a6eb90..01ae0f3 100644
--- a/Lib/codecs.py
+++ b/Lib/codecs.py
@@ -463,15 +463,12 @@ class StreamReader(Codec):
# read until we get the required number of characters (if available)
while True:
# can the request be satisfied from the character buffer?
- if chars < 0:
- if size < 0:
- if self.charbuffer:
- break
- elif len(self.charbuffer) >= size:
- break
- else:
+ if chars >= 0:
if len(self.charbuffer) >= chars:
break
+ elif size >= 0:
+ if len(self.charbuffer) >= size:
+ break
# we need more data
if size < 0:
newdata = self.stream.read()
@@ -479,6 +476,8 @@ class StreamReader(Codec):
newdata = self.stream.read(size)
# decode bytes (those remaining from the last call included)
data = self.bytebuffer + newdata
+ if not data:
+ break
try:
newchars, decodedbytes = self.decode(data, self.errors)
except UnicodeDecodeError as exc:
diff --git a/Lib/contextlib.py b/Lib/contextlib.py
index f878285..b03f828 100644
--- a/Lib/contextlib.py
+++ b/Lib/contextlib.py
@@ -231,7 +231,7 @@ class ExitStack(object):
# we were actually nesting multiple with statements
frame_exc = sys.exc_info()[1]
def _fix_exception_context(new_exc, old_exc):
- # Context isn't what we want, so find the end of the chain
+ # Context may not be correct, so find the end of the chain
while 1:
exc_context = new_exc.__context__
if exc_context is old_exc:
@@ -239,8 +239,6 @@ class ExitStack(object):
return
if exc_context is None or exc_context is frame_exc:
break
- details = id(new_exc), id(old_exc), id(exc_context)
- raise Exception(str(details))
new_exc = exc_context
# Change the end of the chain to point to the exception
# we expect it to reference
diff --git a/Lib/http/server.py b/Lib/http/server.py
index 7050b95..dab1eb6 100644
--- a/Lib/http/server.py
+++ b/Lib/http/server.py
@@ -670,8 +670,10 @@ class SimpleHTTPRequestHandler(BaseHTTPRequestHandler):
"""Serve a GET request."""
f = self.send_head()
if f:
- self.copyfile(f, self.wfile)
- f.close()
+ try:
+ self.copyfile(f, self.wfile)
+ finally:
+ f.close()
def do_HEAD(self):
"""Serve a HEAD request."""
@@ -712,13 +714,17 @@ class SimpleHTTPRequestHandler(BaseHTTPRequestHandler):
except IOError:
self.send_error(404, "File not found")
return None
- self.send_response(200)
- self.send_header("Content-type", ctype)
- fs = os.fstat(f.fileno())
- self.send_header("Content-Length", str(fs[6]))
- self.send_header("Last-Modified", self.date_time_string(fs.st_mtime))
- self.end_headers()
- return f
+ try:
+ self.send_response(200)
+ self.send_header("Content-type", ctype)
+ fs = os.fstat(f.fileno())
+ self.send_header("Content-Length", str(fs[6]))
+ self.send_header("Last-Modified", self.date_time_string(fs.st_mtime))
+ self.end_headers()
+ return f
+ except:
+ f.close()
+ raise
def list_directory(self, path):
"""Helper to produce a directory listing (absent index.html).
diff --git a/Lib/imghdr.py b/Lib/imghdr.py
index 6ee45da..bdd47ee 100644
--- a/Lib/imghdr.py
+++ b/Lib/imghdr.py
@@ -7,18 +7,16 @@ __all__ = ["what"]
#-------------------------#
def what(file, h=None):
- if h is None:
- if isinstance(file, str):
- f = open(file, 'rb')
- h = f.read(32)
- else:
- location = file.tell()
- h = file.read(32)
- file.seek(location)
- f = None
- else:
- f = None
+ f = None
try:
+ if h is None:
+ if isinstance(file, str):
+ f = open(file, 'rb')
+ h = f.read(32)
+ else:
+ location = file.tell()
+ h = file.read(32)
+ file.seek(location)
for tf in tests:
res = tf(h, f)
if res:
diff --git a/Lib/mailcap.py b/Lib/mailcap.py
index 99f4958..0c0b19c 100644
--- a/Lib/mailcap.py
+++ b/Lib/mailcap.py
@@ -22,8 +22,8 @@ def getcaps():
fp = open(mailcap, 'r')
except IOError:
continue
- morecaps = readmailcapfile(fp)
- fp.close()
+ with fp:
+ morecaps = readmailcapfile(fp)
for key, value in morecaps.items():
if not key in caps:
caps[key] = value
diff --git a/Lib/mimetypes.py b/Lib/mimetypes.py
index 3e742a7..cdebf7a 100644
--- a/Lib/mimetypes.py
+++ b/Lib/mimetypes.py
@@ -363,9 +363,10 @@ def read_mime_types(file):
f = open(file)
except IOError:
return None
- db = MimeTypes()
- db.readfp(f, True)
- return db.types_map[True]
+ with f:
+ db = MimeTypes()
+ db.readfp(f, True)
+ return db.types_map[True]
def _default_mime_types():
diff --git a/Lib/test/imghdrdata/python.bmp b/Lib/test/imghdrdata/python.bmp
new file mode 100644
index 0000000..675f951
--- /dev/null
+++ b/Lib/test/imghdrdata/python.bmp
Binary files differ
diff --git a/Lib/test/imghdrdata/python.gif b/Lib/test/imghdrdata/python.gif
new file mode 100644
index 0000000..96fd9fe
--- /dev/null
+++ b/Lib/test/imghdrdata/python.gif
Binary files differ
diff --git a/Lib/test/imghdrdata/python.jpg b/Lib/test/imghdrdata/python.jpg
new file mode 100644
index 0000000..21222c0
--- /dev/null
+++ b/Lib/test/imghdrdata/python.jpg
Binary files differ
diff --git a/Lib/test/imghdrdata/python.pbm b/Lib/test/imghdrdata/python.pbm
new file mode 100644
index 0000000..1848ba7
--- /dev/null
+++ b/Lib/test/imghdrdata/python.pbm
@@ -0,0 +1,3 @@
+P4
+16 16
+ûñ¿úßÕ­±[ñ¥a_ÁX°°ðððð?ÿÿ \ No newline at end of file
diff --git a/Lib/test/imghdrdata/python.pgm b/Lib/test/imghdrdata/python.pgm
new file mode 100644
index 0000000..8349f2a
--- /dev/null
+++ b/Lib/test/imghdrdata/python.pgm
Binary files differ
diff --git a/Lib/test/imghdrdata/python.png b/Lib/test/imghdrdata/python.png
new file mode 100644
index 0000000..1a987f7
--- /dev/null
+++ b/Lib/test/imghdrdata/python.png
Binary files differ
diff --git a/Lib/test/imghdrdata/python.ppm b/Lib/test/imghdrdata/python.ppm
new file mode 100644
index 0000000..7d9cdb3
--- /dev/null
+++ b/Lib/test/imghdrdata/python.ppm
Binary files differ
diff --git a/Lib/test/imghdrdata/python.ras b/Lib/test/imghdrdata/python.ras
new file mode 100644
index 0000000..130e96f
--- /dev/null
+++ b/Lib/test/imghdrdata/python.ras
Binary files differ
diff --git a/Lib/test/imghdrdata/python.sgi b/Lib/test/imghdrdata/python.sgi
new file mode 100644
index 0000000..ffe9081
--- /dev/null
+++ b/Lib/test/imghdrdata/python.sgi
Binary files differ
diff --git a/Lib/test/imghdrdata/python.tiff b/Lib/test/imghdrdata/python.tiff
new file mode 100644
index 0000000..39d0bfc
--- /dev/null
+++ b/Lib/test/imghdrdata/python.tiff
Binary files differ
diff --git a/Lib/test/imghdrdata/python.xbm b/Lib/test/imghdrdata/python.xbm
new file mode 100644
index 0000000..cfbee2e
--- /dev/null
+++ b/Lib/test/imghdrdata/python.xbm
@@ -0,0 +1,6 @@
+#define python_width 16
+#define python_height 16
+static char python_bits[] = {
+ 0xDF, 0xFE, 0x8F, 0xFD, 0x5F, 0xFB, 0xAB, 0xFE, 0xB5, 0x8D, 0xDA, 0x8F,
+ 0xA5, 0x86, 0xFA, 0x83, 0x1A, 0x80, 0x0D, 0x80, 0x0D, 0x80, 0x0F, 0xE0,
+ 0x0F, 0xF8, 0x0F, 0xF8, 0x0F, 0xFC, 0xFF, 0xFF, };
diff --git a/Lib/test/test_codecs.py b/Lib/test/test_codecs.py
index 3517057..5c51ef5 100644
--- a/Lib/test/test_codecs.py
+++ b/Lib/test/test_codecs.py
@@ -173,6 +173,40 @@ class ReadTest(MixInCheckStateHandling):
size*"a",
)
+ def test_mixed_readline_and_read(self):
+ lines = ["Humpty Dumpty sat on a wall,\n",
+ "Humpty Dumpty had a great fall.\r\n",
+ "All the king's horses and all the king's men\r",
+ "Couldn't put Humpty together again."]
+ data = ''.join(lines)
+ def getreader():
+ stream = io.BytesIO(data.encode(self.encoding))
+ return codecs.getreader(self.encoding)(stream)
+
+ # Issue #8260: Test readline() followed by read()
+ f = getreader()
+ self.assertEqual(f.readline(), lines[0])
+ self.assertEqual(f.read(), ''.join(lines[1:]))
+ self.assertEqual(f.read(), '')
+
+ # Issue #16636: Test readline() followed by readlines()
+ f = getreader()
+ self.assertEqual(f.readline(), lines[0])
+ self.assertEqual(f.readlines(), lines[1:])
+ self.assertEqual(f.read(), '')
+
+ # Test read() followed by read()
+ f = getreader()
+ self.assertEqual(f.read(size=40, chars=5), data[:5])
+ self.assertEqual(f.read(), data[5:])
+ self.assertEqual(f.read(), '')
+
+ # Issue #12446: Test read() followed by readlines()
+ f = getreader()
+ self.assertEqual(f.read(size=40, chars=5), data[:5])
+ self.assertEqual(f.readlines(), [lines[0][5:]] + lines[1:])
+ self.assertEqual(f.read(), '')
+
def test_bug1175396(self):
s = [
'<%!--===================================================\r\n',
@@ -2307,8 +2341,6 @@ class TransformCodecTest(unittest.TestCase):
def test_readline(self):
for encoding in bytes_transform_encodings:
- if encoding in ['uu_codec', 'zlib_codec']:
- continue
sin = codecs.encode(b"\x80", encoding)
reader = codecs.getreader(encoding)(io.BytesIO(sin))
sout = reader.readline()
diff --git a/Lib/test/test_contextlib.py b/Lib/test/test_contextlib.py
index e5365f7..e38d043 100644
--- a/Lib/test/test_contextlib.py
+++ b/Lib/test/test_contextlib.py
@@ -603,24 +603,62 @@ class TestExitStack(unittest.TestCase):
def test_exit_exception_with_correct_context(self):
# http://bugs.python.org/issue20317
@contextmanager
- def gets_the_context_right():
+ def gets_the_context_right(exc):
try:
- yield 6
+ yield
finally:
- 1 / 0
+ raise exc
+
+ exc1 = Exception(1)
+ exc2 = Exception(2)
+ exc3 = Exception(3)
+ exc4 = Exception(4)
# The contextmanager already fixes the context, so prior to the
# fix, ExitStack would try to fix it *again* and get into an
# infinite self-referential loop
try:
with ExitStack() as stack:
- stack.enter_context(gets_the_context_right())
- stack.enter_context(gets_the_context_right())
- stack.enter_context(gets_the_context_right())
- except ZeroDivisionError as exc:
- self.assertIsInstance(exc.__context__, ZeroDivisionError)
- self.assertIsInstance(exc.__context__.__context__, ZeroDivisionError)
- self.assertIsNone(exc.__context__.__context__.__context__)
+ stack.enter_context(gets_the_context_right(exc4))
+ stack.enter_context(gets_the_context_right(exc3))
+ stack.enter_context(gets_the_context_right(exc2))
+ raise exc1
+ except Exception as exc:
+ self.assertIs(exc, exc4)
+ self.assertIs(exc.__context__, exc3)
+ self.assertIs(exc.__context__.__context__, exc2)
+ self.assertIs(exc.__context__.__context__.__context__, exc1)
+ self.assertIsNone(
+ exc.__context__.__context__.__context__.__context__)
+
+ def test_exit_exception_with_existing_context(self):
+ # Addresses a lack of test coverage discovered after checking in a
+ # fix for issue 20317 that still contained debugging code.
+ def raise_nested(inner_exc, outer_exc):
+ try:
+ raise inner_exc
+ finally:
+ raise outer_exc
+ exc1 = Exception(1)
+ exc2 = Exception(2)
+ exc3 = Exception(3)
+ exc4 = Exception(4)
+ exc5 = Exception(5)
+ try:
+ with ExitStack() as stack:
+ stack.callback(raise_nested, exc4, exc5)
+ stack.callback(raise_nested, exc2, exc3)
+ raise exc1
+ except Exception as exc:
+ self.assertIs(exc, exc5)
+ self.assertIs(exc.__context__, exc4)
+ self.assertIs(exc.__context__.__context__, exc3)
+ self.assertIs(exc.__context__.__context__.__context__, exc2)
+ self.assertIs(
+ exc.__context__.__context__.__context__.__context__, exc1)
+ self.assertIsNone(
+ exc.__context__.__context__.__context__.__context__.__context__)
+
def test_body_exception_suppress(self):
diff --git a/Lib/test/test_epoll.py b/Lib/test/test_epoll.py
index 46d2968..871efb2 100644
--- a/Lib/test/test_epoll.py
+++ b/Lib/test/test_epoll.py
@@ -217,17 +217,6 @@ class TestEPoll(unittest.TestCase):
server.close()
ep.unregister(fd)
- def test_timeout_rounding(self):
- # epoll_wait() has a resolution of 1 millisecond, check if the timeout
- # is correctly rounded to the upper bound
- epoll = select.epoll()
- self.addCleanup(epoll.close)
- for timeout in (1e-2, 1e-3, 1e-4):
- t0 = time.monotonic()
- epoll.poll(timeout)
- dt = time.monotonic() - t0
- self.assertGreaterEqual(dt, timeout)
-
def test_main():
support.run_unittest(TestEPoll)
diff --git a/Lib/test/test_imghdr.py b/Lib/test/test_imghdr.py
new file mode 100644
index 0000000..0ad4343
--- /dev/null
+++ b/Lib/test/test_imghdr.py
@@ -0,0 +1,131 @@
+import imghdr
+import io
+import os
+import unittest
+import warnings
+from test.support import findfile, TESTFN, unlink
+
+TEST_FILES = (
+ ('python.png', 'png'),
+ ('python.gif', 'gif'),
+ ('python.bmp', 'bmp'),
+ ('python.ppm', 'ppm'),
+ ('python.pgm', 'pgm'),
+ ('python.pbm', 'pbm'),
+ ('python.jpg', 'jpeg'),
+ ('python.ras', 'rast'),
+ ('python.sgi', 'rgb'),
+ ('python.tiff', 'tiff'),
+ ('python.xbm', 'xbm')
+)
+
+class UnseekableIO(io.FileIO):
+ def tell(self):
+ raise io.UnsupportedOperation
+
+ def seek(self, *args, **kwargs):
+ raise io.UnsupportedOperation
+
+class TestImghdr(unittest.TestCase):
+ @classmethod
+ def setUpClass(cls):
+ cls.testfile = findfile('python.png', subdir='imghdrdata')
+ with open(cls.testfile, 'rb') as stream:
+ cls.testdata = stream.read()
+
+ def tearDown(self):
+ unlink(TESTFN)
+
+ def test_data(self):
+ for filename, expected in TEST_FILES:
+ filename = findfile(filename, subdir='imghdrdata')
+ self.assertEqual(imghdr.what(filename), expected)
+ with open(filename, 'rb') as stream:
+ self.assertEqual(imghdr.what(stream), expected)
+ with open(filename, 'rb') as stream:
+ data = stream.read()
+ self.assertEqual(imghdr.what(None, data), expected)
+ self.assertEqual(imghdr.what(None, bytearray(data)), expected)
+
+ def test_register_test(self):
+ def test_jumbo(h, file):
+ if h.startswith(b'eggs'):
+ return 'ham'
+ imghdr.tests.append(test_jumbo)
+ self.addCleanup(imghdr.tests.pop)
+ self.assertEqual(imghdr.what(None, b'eggs'), 'ham')
+
+ def test_file_pos(self):
+ with open(TESTFN, 'wb') as stream:
+ stream.write(b'ababagalamaga')
+ pos = stream.tell()
+ stream.write(self.testdata)
+ with open(TESTFN, 'rb') as stream:
+ stream.seek(pos)
+ self.assertEqual(imghdr.what(stream), 'png')
+ self.assertEqual(stream.tell(), pos)
+
+ def test_bad_args(self):
+ with self.assertRaises(TypeError):
+ imghdr.what()
+ with self.assertRaises(AttributeError):
+ imghdr.what(None)
+ with self.assertRaises(TypeError):
+ imghdr.what(self.testfile, 1)
+ with self.assertRaises(AttributeError):
+ imghdr.what(os.fsencode(self.testfile))
+ with open(self.testfile, 'rb') as f:
+ with self.assertRaises(AttributeError):
+ imghdr.what(f.fileno())
+
+ def test_invalid_headers(self):
+ for header in (b'\211PN\r\n',
+ b'\001\331',
+ b'\x59\xA6',
+ b'cutecat',
+ b'000000JFI',
+ b'GIF80'):
+ self.assertIsNone(imghdr.what(None, header))
+
+ def test_string_data(self):
+ with warnings.catch_warnings():
+ warnings.simplefilter("ignore", BytesWarning)
+ for filename, _ in TEST_FILES:
+ filename = findfile(filename, subdir='imghdrdata')
+ with open(filename, 'rb') as stream:
+ data = stream.read().decode('latin1')
+ with self.assertRaises(TypeError):
+ imghdr.what(io.StringIO(data))
+ with self.assertRaises(TypeError):
+ imghdr.what(None, data)
+
+ def test_missing_file(self):
+ with self.assertRaises(FileNotFoundError):
+ imghdr.what('missing')
+
+ def test_closed_file(self):
+ stream = open(self.testfile, 'rb')
+ stream.close()
+ with self.assertRaises(ValueError) as cm:
+ imghdr.what(stream)
+ stream = io.BytesIO(self.testdata)
+ stream.close()
+ with self.assertRaises(ValueError) as cm:
+ imghdr.what(stream)
+
+ def test_unseekable(self):
+ with open(TESTFN, 'wb') as stream:
+ stream.write(self.testdata)
+ with UnseekableIO(TESTFN, 'rb') as stream:
+ with self.assertRaises(io.UnsupportedOperation):
+ imghdr.what(stream)
+
+ def test_output_stream(self):
+ with open(TESTFN, 'wb') as stream:
+ stream.write(self.testdata)
+ stream.seek(0)
+ with self.assertRaises(OSError) as cm:
+ imghdr.what(stream)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/Lib/test/test_sundry.py b/Lib/test/test_sundry.py
index c6cca26..8808c47 100644
--- a/Lib/test/test_sundry.py
+++ b/Lib/test/test_sundry.py
@@ -42,7 +42,6 @@ class TestUntestedModules(unittest.TestCase):
import encodings
import formatter
import html.entities
- import imghdr
import keyword
import mailcap
import nturl2path
diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py
index f22b908..f64964d 100644
--- a/Lib/test/test_tarfile.py
+++ b/Lib/test/test_tarfile.py
@@ -239,7 +239,12 @@ class CommonReadTest(ReadTest):
def test_non_existent_tarfile(self):
# Test for issue11513: prevent non-existent gzipped tarfiles raising
# multiple exceptions.
- with self.assertRaisesRegex(FileNotFoundError, "xxx"):
+ test = 'xxx'
+ if sys.platform == 'win32' and '|' in self.mode:
+ # Issue #20384: On Windows os.open() error message doesn't
+ # contain file name.
+ test = ''
+ with self.assertRaisesRegex(FileNotFoundError, test):
tarfile.open("xxx", self.mode)
def test_null_tarfile(self):
diff --git a/Lib/test/test_tcl.py b/Lib/test/test_tcl.py
index ad17ee9..0520c09 100644
--- a/Lib/test/test_tcl.py
+++ b/Lib/test/test_tcl.py
@@ -192,6 +192,45 @@ class TclTest(unittest.TestCase):
self.assertEqual(passValue((1, '2', (3.4,))),
(1, '2', (3.4,)) if self.wantobjects else '1 2 3.4')
+ def test_user_command(self):
+ result = None
+ def testfunc(arg):
+ nonlocal result
+ result = arg
+ return arg
+ self.interp.createcommand('testfunc', testfunc)
+ def check(value, expected, eq=self.assertEqual):
+ r = self.interp.call('testfunc', value)
+ self.assertIsInstance(result, str)
+ eq(result, expected)
+ self.assertIsInstance(r, str)
+ eq(r, expected)
+ def float_eq(actual, expected):
+ expected = float(expected)
+ self.assertAlmostEqual(float(actual), expected,
+ delta=abs(expected) * 1e-10)
+ def nan_eq(actual, expected):
+ actual = float(actual)
+ self.assertNotEqual(actual, actual)
+
+ check(True, '1')
+ check(False, '0')
+ check('string', 'string')
+ check('string\xbd', 'string\xbd')
+ check('string\u20ac', 'string\u20ac')
+ for i in (0, 1, -1, 2**31-1, -2**31):
+ check(i, str(i))
+ for f in (0.0, 1.0, -1.0):
+ check(f, repr(f))
+ for f in (1/3.0, sys.float_info.min, sys.float_info.max,
+ -sys.float_info.min, -sys.float_info.max):
+ check(f, f, eq=float_eq)
+ check(float('inf'), 'Inf', eq=float_eq)
+ check(-float('inf'), '-Inf', eq=float_eq)
+ check(float('nan'), 'NaN', eq=nan_eq)
+ check((), '')
+ check((1, (2,), (3, 4), '5 6', ()), '1 2 {3 4} {5 6} {}')
+
def test_splitlist(self):
splitlist = self.interp.tk.splitlist
call = self.interp.tk.call
diff --git a/Lib/xml/etree/ElementInclude.py b/Lib/xml/etree/ElementInclude.py
index 6cc1b44..71eeb05 100644
--- a/Lib/xml/etree/ElementInclude.py
+++ b/Lib/xml/etree/ElementInclude.py
@@ -76,14 +76,13 @@ class FatalIncludeError(SyntaxError):
def default_loader(href, parse, encoding=None):
if parse == "xml":
- file = open(href, 'rb')
- data = ElementTree.parse(file).getroot()
+ with open(href, 'rb') as file:
+ data = ElementTree.parse(file).getroot()
else:
if not encoding:
encoding = 'UTF-8'
- file = open(href, 'r', encoding=encoding)
- data = file.read()
- file.close()
+ with open(href, 'r', encoding=encoding) as file:
+ data = file.read()
return data
##
diff --git a/Misc/NEWS b/Misc/NEWS
index 4372701..10cb08e 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -50,15 +50,17 @@ Core and Builtins
Library
-------
+- Issue #8260: The read(), readline() and readlines() methods of
+ codecs.StreamReader returned incomplete data when were called after
+ readline() or read(size). Based on patch by Amaury Forgeot d'Arc.
+
- Issue #20317: ExitStack.__exit__ could create a self-referential loop if an
exception raised by a cleanup operation already had its context set
correctly (for example, by the @contextmanager decorator). The infinite
loop this caused is now avoided by checking if the expected context is
already set before trying to fix it.
-- Issue #20311: select.epoll.poll() now rounds the timeout away from zero,
- instead of rounding towards zero. For example, a timeout of one microsecond
- is now rounded to one millisecond, instead of being rounded to zero.
+- Issue #20374: Fix build with GNU readline >= 6.3.
- Issue #20262: Warnings are raised now when duplicate names are added in the
ZIP file or too long ZIP file comment is truncated.
@@ -276,7 +278,7 @@ IDLE
--Issue #17390: Add Python version to Idle editor window title bar.
Original patches by Edmond Burnett and Kent Johnson.
-
+
- Issue #18960: IDLE now ignores the source encoding declaration on the second
line if the first line contains anything except a comment.
@@ -290,6 +292,9 @@ IDLE
Tests
-----
+- Issue #19990: Added tests for the imghdr module. Based on patch by
+ Claudiu Popa.
+
- Issue #19804: The test_find_mac test in test_uuid is now skipped if the
ifconfig executable is not available.
diff --git a/Modules/_ctypes/libffi/build-ios.sh b/Modules/_ctypes/libffi/build-ios.sh
index 3dea242..3dea242 100644..100755
--- a/Modules/_ctypes/libffi/build-ios.sh
+++ b/Modules/_ctypes/libffi/build-ios.sh
diff --git a/Modules/_ctypes/libffi/libtool-ldflags b/Modules/_ctypes/libffi/libtool-ldflags
index e32e37b..e32e37b 100644..100755
--- a/Modules/_ctypes/libffi/libtool-ldflags
+++ b/Modules/_ctypes/libffi/libtool-ldflags
diff --git a/Modules/_ctypes/libffi/msvcc.sh b/Modules/_ctypes/libffi/msvcc.sh
index dcdbeab..dcdbeab 100644..100755
--- a/Modules/_ctypes/libffi/msvcc.sh
+++ b/Modules/_ctypes/libffi/msvcc.sh
diff --git a/Modules/_ctypes/libffi/src/arm/gentramp.sh b/Modules/_ctypes/libffi/src/arm/gentramp.sh
index 74f0b86..74f0b86 100644..100755
--- a/Modules/_ctypes/libffi/src/arm/gentramp.sh
+++ b/Modules/_ctypes/libffi/src/arm/gentramp.sh
diff --git a/Modules/readline.c b/Modules/readline.c
index 096c6d1..4ee17a9 100644
--- a/Modules/readline.c
+++ b/Modules/readline.c
@@ -877,7 +877,7 @@ on_completion(const char *text, int state)
* before calling the normal completer */
static char **
-flex_complete(char *text, int start, int end)
+flex_complete(const char *text, int start, int end)
{
#ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
rl_completion_append_character ='\0';
@@ -936,12 +936,12 @@ setup_readline(void)
rl_bind_key_in_map ('\t', rl_complete, emacs_meta_keymap);
rl_bind_key_in_map ('\033', rl_complete, emacs_meta_keymap);
/* Set our hook functions */
- rl_startup_hook = (Function *)on_startup_hook;
+ rl_startup_hook = on_startup_hook;
#ifdef HAVE_RL_PRE_INPUT_HOOK
- rl_pre_input_hook = (Function *)on_pre_input_hook;
+ rl_pre_input_hook = on_pre_input_hook;
#endif
/* Set our completion function */
- rl_attempted_completion_function = (CPPFunction *)flex_complete;
+ rl_attempted_completion_function = flex_complete;
/* Set Python word break characters */
completer_word_break_characters =
rl_completer_word_break_characters =
diff --git a/Modules/selectmodule.c b/Modules/selectmodule.c
index ab2016a..c492224 100644
--- a/Modules/selectmodule.c
+++ b/Modules/selectmodule.c
@@ -1379,9 +1379,7 @@ pyepoll_poll(pyEpoll_Object *self, PyObject *args, PyObject *kwds)
return NULL;
}
else {
- /* epoll_wait() has a resolution of 1 millisecond, round away from zero
- to wait *at least* dtimeout seconds. */
- timeout = (int)ceil(dtimeout * 1000.0);
+ timeout = (int)(dtimeout * 1000.0);
}
if (maxevents == -1) {