mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +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` |    Module :mod:`curses.textpad` | ||||||
|       Editable text widget for curses supporting  :program:`Emacs`\ -like bindings. |       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` |    :ref:`curses-howto` | ||||||
|       Tutorial material on using curses with Python, by Andrew Kuchling and Eric |       Tutorial material on using curses with Python, by Andrew Kuchling and Eric | ||||||
|       Raymond. |       Raymond. | ||||||
|  | @ -592,6 +588,19 @@ The module :mod:`curses` defines the following functions: | ||||||
|    foreground color on the default background. |    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: | .. _curses-window-objects: | ||||||
| 
 | 
 | ||||||
| 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 |       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 |       end of that line instead, and trailing blanks are stripped when the window | ||||||
|       contents are gathered. |       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 | * Only ASCII is supported. The ``backslashreplace`` error handler is used on | ||||||
|   encoding. |   encoding. | ||||||
| * Each string is limited to 100 characters. | * 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) |   displayed. (no source code) | ||||||
| * It is limited to 100 frames and 100 threads. | * It is limited to 100 frames and 100 threads. | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -13,7 +13,6 @@ | ||||||
| __revision__ = "$Id$" | __revision__ = "$Id$" | ||||||
| 
 | 
 | ||||||
| from _curses import * | from _curses import * | ||||||
| from curses.wrapper import wrapper |  | ||||||
| import os as _os | import os as _os | ||||||
| import sys as _sys | import sys as _sys | ||||||
| 
 | 
 | ||||||
|  | @ -57,3 +56,48 @@ def start_color(): | ||||||
|     has_key |     has_key | ||||||
| except NameError: | except NameError: | ||||||
|     from has_key import has_key |     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 |     An email.errors.HeaderParseError may be raised when certain decoding error | ||||||
|     occurs (e.g. a base64 decoding exception). |     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'): |     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 no encoding, just return the header with no charset. | ||||||
|     if not ecre.search(header): |     if not ecre.search(header): | ||||||
|         return [(header, None)] |         return [(header, None)] | ||||||
|  | @ -274,6 +275,9 @@ def append(self, s, charset=None, errors='strict'): | ||||||
|             charset = Charset(charset) |             charset = Charset(charset) | ||||||
|         if not isinstance(s, str): |         if not isinstance(s, str): | ||||||
|             input_charset = charset.input_codec or 'us-ascii' |             input_charset = charset.input_codec or 'us-ascii' | ||||||
|  |             if input_charset == _charset.UNKNOWN8BIT: | ||||||
|  |                 s = s.decode('us-ascii', 'surrogateescape') | ||||||
|  |             else: | ||||||
|                 s = s.decode(input_charset, errors) |                 s = s.decode(input_charset, errors) | ||||||
|         # Ensure that the bytes we're storing can be decoded to the output |         # Ensure that the bytes we're storing can be decoded to the output | ||||||
|         # character set, otherwise an early error is thrown. |         # character set, otherwise an early error is thrown. | ||||||
|  |  | ||||||
|  | @ -1923,6 +1923,7 @@ def seek(self, offset, whence=0): | ||||||
| 
 | 
 | ||||||
|     def close(self): |     def close(self): | ||||||
|         """Close the file.""" |         """Close the file.""" | ||||||
|  |         if hasattr(self, '_file'): | ||||||
|             if hasattr(self._file, 'close'): |             if hasattr(self._file, 'close'): | ||||||
|                 self._file.close() |                 self._file.close() | ||||||
|             del self._file |             del self._file | ||||||
|  | @ -1957,6 +1958,10 @@ def flush(self): | ||||||
| 
 | 
 | ||||||
|     @property |     @property | ||||||
|     def closed(self): |     def closed(self): | ||||||
|  |         if not hasattr(self, '_file'): | ||||||
|  |             return True | ||||||
|  |         if not hasattr(self._file, 'closed'): | ||||||
|  |             return False | ||||||
|         return self._file.closed |         return self._file.closed | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -1995,6 +2000,7 @@ def _read(self, size, read_method): | ||||||
|     def close(self): |     def close(self): | ||||||
|         # do *not* close the underlying file object for partial files, |         # do *not* close the underlying file object for partial files, | ||||||
|         # since it's global to the mailbox object |         # since it's global to the mailbox object | ||||||
|  |         if hasattr(self, '_file'): | ||||||
|             del self._file |             del self._file | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -4324,12 +4324,27 @@ def test_bad_8bit_header(self): | ||||||
| 
 | 
 | ||||||
|     def test_escaped_8bit_header(self): |     def test_escaped_8bit_header(self): | ||||||
|         x = b'Ynwp4dUEbay Auction Semiar- No Charge \x96 Earn Big' |         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) |         h = Header(x, charset=email.charset.UNKNOWN8BIT) | ||||||
|         self.assertEqual(str(h), |         self.assertEqual(str(h), | ||||||
|                         'Ynwp4dUEbay Auction Semiar- No Charge \uFFFD Earn Big') |                         'Ynwp4dUEbay Auction Semiar- No Charge \uFFFD Earn Big') | ||||||
|         self.assertEqual(email.header.decode_header(h), [(x, 'unknown-8bit')]) |         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): |     def test_modify_returned_list_does_not_change_header(self): | ||||||
|         h = Header('test') |         h = Header('test') | ||||||
|         chunks = email.header.decode_header(h) |         chunks = email.header.decode_header(h) | ||||||
|  |  | ||||||
|  | @ -297,6 +297,13 @@ def test_get_file(self): | ||||||
|         self.assertEqual(data1.decode('ascii').replace(os.linesep, '\n'), |         self.assertEqual(data1.decode('ascii').replace(os.linesep, '\n'), | ||||||
|                          _sample_message) |                          _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): |     def test_iterkeys(self): | ||||||
|         # Get keys using iterkeys() |         # Get keys using iterkeys() | ||||||
|         self._check_iteration(self._box.keys, do_keys=True, do_values=False) |         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): |     def _test_close(self, proxy): | ||||||
|         # Close a file |         # Close a file | ||||||
|  |         self.assertFalse(proxy.closed) | ||||||
|         proxy.close() |         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): | class TestProxyFile(TestProxyFileBase): | ||||||
|  |  | ||||||
|  | @ -1013,6 +1013,7 @@ David Wolever | ||||||
| Klaus-Juergen Wolf | Klaus-Juergen Wolf | ||||||
| Dan Wolfe | Dan Wolfe | ||||||
| Richard Wolff | Richard Wolff | ||||||
|  | Adam Woodbeck | ||||||
| Darren Worrall | Darren Worrall | ||||||
| Gordon Worley | Gordon Worley | ||||||
| Thomas Wouters | Thomas Wouters | ||||||
|  |  | ||||||
							
								
								
									
										11
									
								
								Misc/NEWS
									
										
									
									
									
								
							
							
						
						
									
										11
									
								
								Misc/NEWS
									
										
									
									
									
								
							|  | @ -193,6 +193,17 @@ Core and Builtins | ||||||
| Library | 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 #11767: Correct file descriptor leak in mailbox's __getitem__ method. | ||||||
| 
 | 
 | ||||||
| - Issue #12133: AbstractHTTPHandler.do_open() of urllib.request closes the HTTP | - Issue #12133: AbstractHTTPHandler.do_open() of urllib.request closes the HTTP | ||||||
|  |  | ||||||
|  | @ -1057,14 +1057,14 @@ def add_files(db): | ||||||
|             lib.add_file("turtle.cfg") |             lib.add_file("turtle.cfg") | ||||||
|         if dir=="pydoc_data": |         if dir=="pydoc_data": | ||||||
|             lib.add_file("_pydoc.css") |             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 |             # This should contain all non-.svn files listed in subversion | ||||||
|             for f in os.listdir(lib.absolute): |             for f in os.listdir(lib.absolute): | ||||||
|                 if f.endswith(".txt") or f==".svn":continue |                 if f.endswith(".txt") or f==".svn":continue | ||||||
|                 if f.endswith(".au") or f.endswith(".gif"): |                 if f.endswith(".au") or f.endswith(".gif"): | ||||||
|                     lib.add_file(f) |                     lib.add_file(f) | ||||||
|                 else: |                 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): |         for f in os.listdir(lib.absolute): | ||||||
|             if os.path.isdir(os.path.join(lib.absolute, f)): |             if os.path.isdir(os.path.join(lib.absolute, f)): | ||||||
|                 pydirs.append((lib, f)) |                 pydirs.append((lib, f)) | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Benjamin Peterson
						Benjamin Peterson