1 import builtins 2 import inspect 3 import os 4 import pathlib 5 import shutil 6 import sys 7 import types 8 9 import pytest 10 11 # Must register before it gets imported 12 pytest.register_assert_rewrite("IPython.testing.tools") 13 14 from .testing import tools 15 16 17 def pytest_collection_modifyitems(items): 18 """This function is automatically run by pytest passing all collected test 19 functions. 20 21 We use it to add asyncio marker to all async tests and assert we don't use 22 test functions that are async generators which wouldn't make sense. 23 """ 24 for item in items: 25 if inspect.iscoroutinefunction(item.obj): 26 item.add_marker("asyncio") 27 assert not inspect.isasyncgenfunction(item.obj) 28 29 30 def get_ipython(): 31 from .terminal.interactiveshell import TerminalInteractiveShell 32 if TerminalInteractiveShell._instance: 33 return TerminalInteractiveShell.instance() 34 35 config = tools.default_config() 36 config.TerminalInteractiveShell.simple_prompt = True 37 38 # Create and initialize our test-friendly IPython instance. 39 shell = TerminalInteractiveShell.instance(config=config) 40 return shell 41 42 43 @pytest.fixture(scope='session', autouse=True) 44 def work_path(): 45 path = pathlib.Path("./tmp-ipython-pytest-profiledir") 46 os.environ["IPYTHONDIR"] = str(path.absolute()) 47 if path.exists(): 48 raise ValueError('IPython dir temporary path already exists ! Did previous test run exit successfully ?') 49 path.mkdir() 50 yield 51 shutil.rmtree(str(path.resolve())) 52 53 54 def nopage(strng, start=0, screen_lines=0, pager_cmd=None): 55 if isinstance(strng, dict): 56 strng = strng.get("text/plain", "") 57 print(strng) 58 59 60 def xsys(self, cmd): 61 """Replace the default system call with a capturing one for doctest. 62 """ 63 # We use getoutput, but we need to strip it because pexpect captures 64 # the trailing newline differently from commands.getoutput 65 print(self.getoutput(cmd, split=False, depth=1).rstrip(), end="", file=sys.stdout) 66 sys.stdout.flush() 67 68 69 # for things to work correctly we would need this as a session fixture; 70 # unfortunately this will fail on some test that get executed as _collection_ 71 # time (before the fixture run), in particular parametrized test that contain 72 # yields. so for now execute at import time. 73 #@pytest.fixture(autouse=True, scope='session') 74 def inject(): 75 76 builtins.get_ipython = get_ipython 77 builtins._ip = get_ipython() 78 builtins.ip = get_ipython() 79 builtins.ip.system = types.MethodType(xsys, ip) 80 builtins.ip.builtin_trap.activate() 81 from .core import page 82 83 page.pager_page = nopage 84 # yield 85 86 87 inject() 88