merge heads
This commit is contained in:
commit
12f2bffce1
@ -41,10 +41,6 @@ Linux and the BSD variants of Unix.
|
||||
Module :mod:`curses.textpad`
|
||||
Editable text widget for curses supporting :program:`Emacs`\ -like bindings.
|
||||
|
||||
Module :mod:`curses.wrapper`
|
||||
Convenience function to ensure proper terminal setup and resetting on
|
||||
application entry and exit.
|
||||
|
||||
:ref:`curses-howto`
|
||||
Tutorial material on using curses with Python, by Andrew Kuchling and Eric
|
||||
Raymond.
|
||||
@ -592,6 +588,19 @@ The module :mod:`curses` defines the following functions:
|
||||
foreground color on the default background.
|
||||
|
||||
|
||||
.. function:: wrapper(func, ...)
|
||||
|
||||
Initialize curses and call another callable object, *func*, which should be the
|
||||
rest of your curses-using application. If the application raises an exception,
|
||||
this function will restore the terminal to a sane state before re-raising the
|
||||
exception and generating a traceback. The callable object *func* is then passed
|
||||
the main window 'stdscr' as its first argument, followed by any other arguments
|
||||
passed to :func:`wrapper`. Before calling *func*, :func:`wrapper` turns on
|
||||
cbreak mode, turns off echo, enables the terminal keypad, and initializes colors
|
||||
if the terminal has color support. On exit (whether normally or by exception)
|
||||
it restores cooked mode, turns on echo, and disables the terminal keypad.
|
||||
|
||||
|
||||
.. _curses-window-objects:
|
||||
|
||||
Window Objects
|
||||
@ -1659,32 +1668,3 @@ You can instantiate a :class:`Textbox` object as follows:
|
||||
cursor motion that would land the cursor on a trailing blank goes to the
|
||||
end of that line instead, and trailing blanks are stripped when the window
|
||||
contents are gathered.
|
||||
|
||||
|
||||
:mod:`curses.wrapper` --- Terminal handler for curses programs
|
||||
==============================================================
|
||||
|
||||
.. module:: curses.wrapper
|
||||
:synopsis: Terminal configuration wrapper for curses programs.
|
||||
.. moduleauthor:: Eric Raymond <esr@thyrsus.com>
|
||||
.. sectionauthor:: Eric Raymond <esr@thyrsus.com>
|
||||
|
||||
|
||||
This module supplies one function, :func:`wrapper`, which runs another function
|
||||
which should be the rest of your curses-using application. If the application
|
||||
raises an exception, :func:`wrapper` will restore the terminal to a sane state
|
||||
before re-raising the exception and generating a traceback.
|
||||
|
||||
|
||||
.. function:: wrapper(func, ...)
|
||||
|
||||
Wrapper function that initializes curses and calls another function, *func*,
|
||||
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 :func:`wrapper`.
|
||||
|
||||
Before calling the hook function, :func:`wrapper` turns on cbreak mode, turns
|
||||
off echo, enables the terminal keypad, and initializes colors if the terminal
|
||||
has color support. On exit (whether normally or by exception) it restores
|
||||
cooked mode, turns on echo, and disables the terminal keypad.
|
||||
|
||||
|
@ -24,7 +24,7 @@ tracebacks:
|
||||
* Only ASCII is supported. The ``backslashreplace`` error handler is used on
|
||||
encoding.
|
||||
* Each string is limited to 100 characters.
|
||||
* Only the the filename, the function name and the line number are
|
||||
* Only the filename, the function name and the line number are
|
||||
displayed. (no source code)
|
||||
* It is limited to 100 frames and 100 threads.
|
||||
|
||||
|
@ -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()
|
||||
|
@ -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()
|
@ -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'
|
||||
|
@ -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):
|
||||
|
@ -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)
|
||||
|
@ -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.assertRaises(AttributeError, lambda: proxy.close())
|
||||
self.assertTrue(proxy.closed)
|
||||
# Issue 11700 subsequent closes should be a no-op.
|
||||
proxy.close()
|
||||
self.assertTrue(proxy.closed)
|
||||
|
||||
|
||||
class TestProxyFile(TestProxyFileBase):
|
||||
|
@ -1013,6 +1013,7 @@ David Wolever
|
||||
Klaus-Juergen Wolf
|
||||
Dan Wolfe
|
||||
Richard Wolff
|
||||
Adam Woodbeck
|
||||
Darren Worrall
|
||||
Gordon Worley
|
||||
Thomas Wouters
|
||||
|
11
Misc/NEWS
11
Misc/NEWS
@ -193,6 +193,17 @@ Core and Builtins
|
||||
Library
|
||||
-------
|
||||
|
||||
- Issue #6771: moved the curses.wrapper function from the single-function
|
||||
wrapper module into __init__, eliminating the module. Since __init__ was
|
||||
already importing the function to curses.wrapper, there is no API change.
|
||||
|
||||
- Issue #11584: email.header.decode_header no longer fails if the header
|
||||
passed to it is a Header object, and Header/make_header no longer fail
|
||||
if given binary unknown-8bit input.
|
||||
|
||||
- Issue #11700: mailbox proxy object close methods can now be called multiple
|
||||
times without error.
|
||||
|
||||
- Issue #11767: Correct file descriptor leak in mailbox's __getitem__ method.
|
||||
|
||||
- Issue #12133: AbstractHTTPHandler.do_open() of urllib.request closes the HTTP
|
||||
|
@ -1057,14 +1057,14 @@ def add_files(db):
|
||||
lib.add_file("turtle.cfg")
|
||||
if dir=="pydoc_data":
|
||||
lib.add_file("_pydoc.css")
|
||||
if dir=="data" and parent.physical=="test" and parent.basedir.physical=="email":
|
||||
if dir=="data" and parent.physical=="test_email":
|
||||
# This should contain all non-.svn files listed in subversion
|
||||
for f in os.listdir(lib.absolute):
|
||||
if f.endswith(".txt") or f==".svn":continue
|
||||
if f.endswith(".au") or f.endswith(".gif"):
|
||||
lib.add_file(f)
|
||||
else:
|
||||
print("WARNING: New file %s in email/test/data" % f)
|
||||
print("WARNING: New file %s in test/test_email/data" % f)
|
||||
for f in os.listdir(lib.absolute):
|
||||
if os.path.isdir(os.path.join(lib.absolute, f)):
|
||||
pydirs.append((lib, f))
|
||||
|
Loading…
x
Reference in New Issue
Block a user