mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 05:31:20 +00:00 
			
		
		
		
	merge heads
This commit is contained in:
		
						commit
						12f2bffce1
					
				
					 11 changed files with 118 additions and 96 deletions
				
			
		|  | @ -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 @@ | |||
| __revision__ = "$Id$" | ||||
| 
 | ||||
| from _curses import * | ||||
| from curses.wrapper import wrapper | ||||
| import os as _os | ||||
| import sys as _sys | ||||
| 
 | ||||
|  | @ -57,3 +56,48 @@ def start_color(): | |||
|     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 @@ def append(self, s, charset=None, errors='strict'): | |||
|             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 @@ def seek(self, offset, whence=0): | |||
| 
 | ||||
|     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 @@ def flush(self): | |||
| 
 | ||||
|     @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 @@ def _read(self, size, read_method): | |||
|     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 @@ def test_bad_8bit_header(self): | |||
| 
 | ||||
|     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 @@ def test_get_file(self): | |||
|         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 @@ def _test_seek_and_tell(self, proxy): | |||
| 
 | ||||
|     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…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Benjamin Peterson
						Benjamin Peterson