137 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
		
		
			
		
	
	
			137 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
|   | """Global yap_ipython app to support test running.
 | ||
|  | 
 | ||
|  | We must start our own ipython object and heavily muck with it so that all the | ||
|  | modifications yap_ipython makes to system behavior don't send the doctest machinery | ||
|  | into a fit.  This code should be considered a gross hack, but it gets the job | ||
|  | done. | ||
|  | """
 | ||
|  | 
 | ||
|  | # Copyright (c) yap_ipython Development Team. | ||
|  | # Distributed under the terms of the Modified BSD License. | ||
|  | 
 | ||
|  | import builtins as builtin_mod | ||
|  | import sys | ||
|  | import types | ||
|  | import warnings | ||
|  | 
 | ||
|  | from . import tools | ||
|  | 
 | ||
|  | from yap_ipython.core import page | ||
|  | from yap_ipython.utils import io | ||
|  | from yap_ipython.terminal.interactiveshell import TerminalInteractiveShell | ||
|  | 
 | ||
|  | 
 | ||
|  | class StreamProxy(io.IOStream): | ||
|  |     """Proxy for sys.stdout/err.  This will request the stream *at call time*
 | ||
|  |     allowing for nose's Capture plugin's redirection of sys.stdout/err. | ||
|  | 
 | ||
|  |     Parameters | ||
|  |     ---------- | ||
|  |     name : str | ||
|  |         The name of the stream. This will be requested anew at every call | ||
|  |     """
 | ||
|  | 
 | ||
|  |     def __init__(self, name): | ||
|  |         warnings.warn("StreamProxy is deprecated and unused as of yap_ipython 5", DeprecationWarning, | ||
|  |             stacklevel=2, | ||
|  |         ) | ||
|  |         self.name=name | ||
|  | 
 | ||
|  |     @property | ||
|  |     def stream(self): | ||
|  |         return getattr(sys, self.name) | ||
|  | 
 | ||
|  |     def flush(self): | ||
|  |         self.stream.flush() | ||
|  | 
 | ||
|  | 
 | ||
|  | def get_ipython(): | ||
|  |     # This will get replaced by the real thing once we start yap_ipython below | ||
|  |     return start_ipython() | ||
|  | 
 | ||
|  | 
 | ||
|  | # A couple of methods to override those in the running yap_ipython to interact | ||
|  | # better with doctest (doctest captures on raw stdout, so we need to direct | ||
|  | # various types of output there otherwise it will miss them). | ||
|  | 
 | ||
|  | def xsys(self, cmd): | ||
|  |     """Replace the default system call with a capturing one for doctest.
 | ||
|  |     """
 | ||
|  |     # We use getoutput, but we need to strip it because pexpect captures | ||
|  |     # the trailing newline differently from commands.getoutput | ||
|  |     print(self.getoutput(cmd, split=False, depth=1).rstrip(), end='', file=sys.stdout) | ||
|  |     sys.stdout.flush() | ||
|  | 
 | ||
|  | 
 | ||
|  | def _showtraceback(self, etype, evalue, stb): | ||
|  |     """Print the traceback purely on stdout for doctest to capture it.
 | ||
|  |     """
 | ||
|  |     print(self.InteractiveTB.stb2text(stb), file=sys.stdout) | ||
|  | 
 | ||
|  | 
 | ||
|  | def start_ipython(): | ||
|  |     """Start a global yap_ipython shell, which we need for yap_ipython-specific syntax.
 | ||
|  |     """
 | ||
|  |     global get_ipython | ||
|  | 
 | ||
|  |     # This function should only ever run once! | ||
|  |     if hasattr(start_ipython, 'already_called'): | ||
|  |         return | ||
|  |     start_ipython.already_called = True | ||
|  | 
 | ||
|  |     # Store certain global objects that yap_ipython modifies | ||
|  |     _displayhook = sys.displayhook | ||
|  |     _excepthook = sys.excepthook | ||
|  |     _main = sys.modules.get('__main__') | ||
|  | 
 | ||
|  |     # Create custom argv and namespaces for our yap_ipython to be test-friendly | ||
|  |     config = tools.default_config() | ||
|  |     config.TerminalInteractiveShell.simple_prompt = True | ||
|  | 
 | ||
|  |     # Create and initialize our test-friendly yap_ipython instance. | ||
|  |     shell = TerminalInteractiveShell.instance(config=config, | ||
|  |                                               ) | ||
|  | 
 | ||
|  |     # A few more tweaks needed for playing nicely with doctests... | ||
|  | 
 | ||
|  |     # remove history file | ||
|  |     shell.tempfiles.append(config.HistoryManager.hist_file) | ||
|  | 
 | ||
|  |     # These traps are normally only active for interactive use, set them | ||
|  |     # permanently since we'll be mocking interactive sessions. | ||
|  |     shell.builtin_trap.activate() | ||
|  | 
 | ||
|  |     # Modify the yap_ipython system call with one that uses getoutput, so that we | ||
|  |     # can capture subcommands and print them to Python's stdout, otherwise the | ||
|  |     # doctest machinery would miss them. | ||
|  |     shell.system = types.MethodType(xsys, shell) | ||
|  | 
 | ||
|  |     shell._showtraceback = types.MethodType(_showtraceback, shell) | ||
|  | 
 | ||
|  |     # yap_ipython is ready, now clean up some global state... | ||
|  | 
 | ||
|  |     # Deactivate the various python system hooks added by ipython for | ||
|  |     # interactive convenience so we don't confuse the doctest system | ||
|  |     sys.modules['__main__'] = _main | ||
|  |     sys.displayhook = _displayhook | ||
|  |     sys.excepthook = _excepthook | ||
|  | 
 | ||
|  |     # So that ipython magics and aliases can be doctested (they work by making | ||
|  |     # a call into a global _ip object).  Also make the top-level get_ipython | ||
|  |     # now return this without recursively calling here again. | ||
|  |     _ip = shell | ||
|  |     get_ipython = _ip.get_ipython | ||
|  |     builtin_mod._ip = _ip | ||
|  |     builtin_mod.get_ipython = get_ipython | ||
|  | 
 | ||
|  |     # Override paging, so we don't require user interaction during the tests. | ||
|  |     def nopage(strng, start=0, screen_lines=0, pager_cmd=None): | ||
|  |         if isinstance(strng, dict): | ||
|  |            strng = strng.get('text/plain', '') | ||
|  |         print(strng) | ||
|  |      | ||
|  |     page.orig_page = page.pager_page | ||
|  |     page.pager_page = nopage | ||
|  | 
 | ||
|  |     return _ip |