summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorBenjamin Peterson <benjamin@python.org>2011-06-19 14:38:02 (GMT)
committerBenjamin Peterson <benjamin@python.org>2011-06-19 14:38:02 (GMT)
commit12f2bffce1be0e36e2cf11a8be80de7fcb76dd54 (patch)
tree1f37a3639480738daf90d359dbc239ac664860f3 /Lib
parentdefe6f61fe8595d0d2cc194c120ef0b3dc3a4286 (diff)
parent2510d9e8d9d3244c8d35efdd01bca265755655de (diff)
downloadcpython-12f2bffce1be0e36e2cf11a8be80de7fcb76dd54.zip
cpython-12f2bffce1be0e36e2cf11a8be80de7fcb76dd54.tar.gz
cpython-12f2bffce1be0e36e2cf11a8be80de7fcb76dd54.tar.bz2
merge heads
Diffstat (limited to 'Lib')
-rw-r--r--Lib/curses/__init__.py46
-rw-r--r--Lib/curses/wrapper.py50
-rw-r--r--Lib/email/header.py10
-rw-r--r--Lib/mailbox.py14
-rw-r--r--Lib/test/test_email/test_email.py17
-rw-r--r--Lib/test/test_mailbox.py13
6 files changed, 90 insertions, 60 deletions
diff --git a/Lib/curses/__init__.py b/Lib/curses/__init__.py
index bd7d5f6..5cd4eda 100644
--- a/Lib/curses/__init__.py
+++ b/Lib/curses/__init__.py
@@ -13,7 +13,6 @@ the package, and perhaps a particular module inside it.
__revision__ = "$Id$"
from _curses import *
-from curses.wrapper import wrapper
import os as _os
import sys as _sys
@@ -57,3 +56,48 @@ try:
has_key
except NameError:
from has_key import has_key
+
+# Wrapper for the entire curses-based application. Runs a function which
+# should be the rest of your curses-based application. If the application
+# raises an exception, wrapper() will restore the terminal to a sane state so
+# you can read the resulting traceback.
+
+def wrapper(func, *args, **kwds):
+ """Wrapper function that initializes curses and calls another function,
+ restoring normal keyboard/screen behavior on error.
+ The callable object 'func' is then passed the main window 'stdscr'
+ as its first argument, followed by any other arguments passed to
+ wrapper().
+ """
+
+ try:
+ # Initialize curses
+ stdscr = initscr()
+
+ # Turn off echoing of keys, and enter cbreak mode,
+ # where no buffering is performed on keyboard input
+ noecho()
+ cbreak()
+
+ # In keypad mode, escape sequences for special keys
+ # (like the cursor keys) will be interpreted and
+ # a special value like curses.KEY_LEFT will be returned
+ stdscr.keypad(1)
+
+ # Start color, too. Harmless if the terminal doesn't have
+ # color; user can test with has_color() later on. The try/catch
+ # works around a minor bit of over-conscientiousness in the curses
+ # module -- the error return from C start_color() is ignorable.
+ try:
+ start_color()
+ except:
+ pass
+
+ return func(stdscr, *args, **kwds)
+ finally:
+ # Set everything back to normal
+ if 'stdscr' in locals():
+ stdscr.keypad(0)
+ echo()
+ nocbreak()
+ endwin()
diff --git a/Lib/curses/wrapper.py b/Lib/curses/wrapper.py
deleted file mode 100644
index 5183ce7..0000000
--- a/Lib/curses/wrapper.py
+++ /dev/null
@@ -1,50 +0,0 @@
-"""curses.wrapper
-
-Contains one function, wrapper(), which runs another function which
-should be the rest of your curses-based application. If the
-application raises an exception, wrapper() will restore the terminal
-to a sane state so you can read the resulting traceback.
-
-"""
-
-import curses
-
-def wrapper(func, *args, **kwds):
- """Wrapper function that initializes curses and calls another function,
- restoring normal keyboard/screen behavior on error.
- The callable object 'func' is then passed the main window 'stdscr'
- as its first argument, followed by any other arguments passed to
- wrapper().
- """
-
- try:
- # Initialize curses
- stdscr = curses.initscr()
-
- # Turn off echoing of keys, and enter cbreak mode,
- # where no buffering is performed on keyboard input
- curses.noecho()
- curses.cbreak()
-
- # In keypad mode, escape sequences for special keys
- # (like the cursor keys) will be interpreted and
- # a special value like curses.KEY_LEFT will be returned
- stdscr.keypad(1)
-
- # Start color, too. Harmless if the terminal doesn't have
- # color; user can test with has_color() later on. The try/catch
- # works around a minor bit of over-conscientiousness in the curses
- # module -- the error return from C start_color() is ignorable.
- try:
- curses.start_color()
- except:
- pass
-
- return func(stdscr, *args, **kwds)
- finally:
- # Set everything back to normal
- if 'stdscr' in locals():
- stdscr.keypad(0)
- curses.echo()
- curses.nocbreak()
- curses.endwin()
diff --git a/Lib/email/header.py b/Lib/email/header.py
index 0a66df5..2e687b7 100644
--- a/Lib/email/header.py
+++ b/Lib/email/header.py
@@ -73,9 +73,10 @@ def decode_header(header):
An email.errors.HeaderParseError may be raised when certain decoding error
occurs (e.g. a base64 decoding exception).
"""
- # If it is a Header object, we can just return the chunks.
+ # If it is a Header object, we can just return the encoded chunks.
if hasattr(header, '_chunks'):
- return list(header._chunks)
+ return [(_charset._encode(string, str(charset)), str(charset))
+ for string, charset in header._chunks]
# If no encoding, just return the header with no charset.
if not ecre.search(header):
return [(header, None)]
@@ -274,7 +275,10 @@ class Header:
charset = Charset(charset)
if not isinstance(s, str):
input_charset = charset.input_codec or 'us-ascii'
- s = s.decode(input_charset, errors)
+ if input_charset == _charset.UNKNOWN8BIT:
+ s = s.decode('us-ascii', 'surrogateescape')
+ else:
+ s = s.decode(input_charset, errors)
# Ensure that the bytes we're storing can be decoded to the output
# character set, otherwise an early error is thrown.
output_charset = charset.output_codec or 'us-ascii'
diff --git a/Lib/mailbox.py b/Lib/mailbox.py
index b96b270..e23ea8c 100644
--- a/Lib/mailbox.py
+++ b/Lib/mailbox.py
@@ -1923,9 +1923,10 @@ class _ProxyFile:
def close(self):
"""Close the file."""
- if hasattr(self._file, 'close'):
- self._file.close()
- del self._file
+ if hasattr(self, '_file'):
+ if hasattr(self._file, 'close'):
+ self._file.close()
+ del self._file
def _read(self, size, read_method):
"""Read size bytes using read_method."""
@@ -1957,6 +1958,10 @@ class _ProxyFile:
@property
def closed(self):
+ if not hasattr(self, '_file'):
+ return True
+ if not hasattr(self._file, 'closed'):
+ return False
return self._file.closed
@@ -1995,7 +2000,8 @@ class _PartialFile(_ProxyFile):
def close(self):
# do *not* close the underlying file object for partial files,
# since it's global to the mailbox object
- del self._file
+ if hasattr(self, '_file'):
+ del self._file
def _lock_file(f, dotlock=True):
diff --git a/Lib/test/test_email/test_email.py b/Lib/test/test_email/test_email.py
index 1657afc..17451f3 100644
--- a/Lib/test/test_email/test_email.py
+++ b/Lib/test/test_email/test_email.py
@@ -4324,12 +4324,27 @@ A very long line that must get split to something other than at the
def test_escaped_8bit_header(self):
x = b'Ynwp4dUEbay Auction Semiar- No Charge \x96 Earn Big'
- x = x.decode('ascii', 'surrogateescape')
+ e = x.decode('ascii', 'surrogateescape')
+ h = Header(e, charset=email.charset.UNKNOWN8BIT)
+ self.assertEqual(str(h),
+ 'Ynwp4dUEbay Auction Semiar- No Charge \uFFFD Earn Big')
+ self.assertEqual(email.header.decode_header(h), [(x, 'unknown-8bit')])
+
+ def test_header_handles_binary_unknown8bit(self):
+ x = b'Ynwp4dUEbay Auction Semiar- No Charge \x96 Earn Big'
h = Header(x, charset=email.charset.UNKNOWN8BIT)
self.assertEqual(str(h),
'Ynwp4dUEbay Auction Semiar- No Charge \uFFFD Earn Big')
self.assertEqual(email.header.decode_header(h), [(x, 'unknown-8bit')])
+ def test_make_header_handles_binary_unknown8bit(self):
+ x = b'Ynwp4dUEbay Auction Semiar- No Charge \x96 Earn Big'
+ h = Header(x, charset=email.charset.UNKNOWN8BIT)
+ h2 = email.header.make_header(email.header.decode_header(h))
+ self.assertEqual(str(h2),
+ 'Ynwp4dUEbay Auction Semiar- No Charge \uFFFD Earn Big')
+ self.assertEqual(email.header.decode_header(h2), [(x, 'unknown-8bit')])
+
def test_modify_returned_list_does_not_change_header(self):
h = Header('test')
chunks = email.header.decode_header(h)
diff --git a/Lib/test/test_mailbox.py b/Lib/test/test_mailbox.py
index f5abb41..18aeec7 100644
--- a/Lib/test/test_mailbox.py
+++ b/Lib/test/test_mailbox.py
@@ -297,6 +297,13 @@ class TestMailbox(TestBase):
self.assertEqual(data1.decode('ascii').replace(os.linesep, '\n'),
_sample_message)
+ def test_get_file_can_be_closed_twice(self):
+ # Issue 11700
+ key = self._box.add(_sample_message)
+ f = self._box.get_file(key)
+ f.close()
+ f.close()
+
def test_iterkeys(self):
# Get keys using iterkeys()
self._check_iteration(self._box.keys, do_keys=True, do_values=False)
@@ -1862,8 +1869,12 @@ class TestProxyFileBase(TestBase):
def _test_close(self, proxy):
# Close a file
+ self.assertFalse(proxy.closed)
+ proxy.close()
+ self.assertTrue(proxy.closed)
+ # Issue 11700 subsequent closes should be a no-op.
proxy.close()
- self.assertRaises(AttributeError, lambda: proxy.close())
+ self.assertTrue(proxy.closed)
class TestProxyFile(TestProxyFileBase):