mirror of
https://github.com/aykhans/AzSuicideDataVisualization.git
synced 2025-07-02 14:27:31 +00:00
first commit
This commit is contained in:
BIN
.venv/Lib/site-packages/IPython/core/tests/2x2.jpg
Normal file
BIN
.venv/Lib/site-packages/IPython/core/tests/2x2.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 331 B |
BIN
.venv/Lib/site-packages/IPython/core/tests/2x2.png
Normal file
BIN
.venv/Lib/site-packages/IPython/core/tests/2x2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 71 B |
14
.venv/Lib/site-packages/IPython/core/tests/bad_all.py
Normal file
14
.venv/Lib/site-packages/IPython/core/tests/bad_all.py
Normal file
@ -0,0 +1,14 @@
|
||||
"""Module with bad __all__
|
||||
|
||||
To test https://github.com/ipython/ipython/issues/9678
|
||||
"""
|
||||
|
||||
def evil():
|
||||
pass
|
||||
|
||||
def puppies():
|
||||
pass
|
||||
|
||||
__all__ = [evil, # Bad
|
||||
'puppies', # Good
|
||||
]
|
@ -0,0 +1,12 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Useless IPython extension to test installing and loading extensions.
|
||||
"""
|
||||
some_vars = {'arq': 185}
|
||||
|
||||
def load_ipython_extension(ip):
|
||||
# set up simplified quantity input
|
||||
ip.push(some_vars)
|
||||
|
||||
def unload_ipython_extension(ip):
|
||||
ip.drop_by_id(some_vars)
|
4
.venv/Lib/site-packages/IPython/core/tests/nonascii.py
Normal file
4
.venv/Lib/site-packages/IPython/core/tests/nonascii.py
Normal file
@ -0,0 +1,4 @@
|
||||
# coding: iso-8859-5
|
||||
# (Unlikely to be the default encoding for most testers.)
|
||||
# <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <- Cyrillic characters
|
||||
u = '<EFBFBD><EFBFBD><EFBFBD><EFBFBD>'
|
4
.venv/Lib/site-packages/IPython/core/tests/nonascii2.py
Normal file
4
.venv/Lib/site-packages/IPython/core/tests/nonascii2.py
Normal file
@ -0,0 +1,4 @@
|
||||
# coding: iso-8859-5
|
||||
# (Unlikely to be the default encoding for most testers.)
|
||||
# БЖџрстуфхцчшщъыьэюя <- Cyrillic characters
|
||||
'Ўт№Ф'
|
2
.venv/Lib/site-packages/IPython/core/tests/print_argv.py
Normal file
2
.venv/Lib/site-packages/IPython/core/tests/print_argv.py
Normal file
@ -0,0 +1,2 @@
|
||||
import sys
|
||||
print(sys.argv[1:])
|
46
.venv/Lib/site-packages/IPython/core/tests/refbug.py
Normal file
46
.venv/Lib/site-packages/IPython/core/tests/refbug.py
Normal file
@ -0,0 +1,46 @@
|
||||
"""Minimal script to reproduce our nasty reference counting bug.
|
||||
|
||||
The problem is related to https://github.com/ipython/ipython/issues/141
|
||||
|
||||
The original fix for that appeared to work, but John D. Hunter found a
|
||||
matplotlib example which, when run twice in a row, would break. The problem
|
||||
were references held by open figures to internals of Tkinter.
|
||||
|
||||
This code reproduces the problem that John saw, without matplotlib.
|
||||
|
||||
This script is meant to be called by other parts of the test suite that call it
|
||||
via %run as if it were executed interactively by the user. As of 2011-05-29,
|
||||
test_run.py calls it.
|
||||
"""
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Module imports
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
from IPython import get_ipython
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Globals
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
# This needs to be here because nose and other test runners will import
|
||||
# this module. Importing this module has potential side effects that we
|
||||
# want to prevent.
|
||||
if __name__ == '__main__':
|
||||
|
||||
ip = get_ipython()
|
||||
|
||||
if not '_refbug_cache' in ip.user_ns:
|
||||
ip.user_ns['_refbug_cache'] = []
|
||||
|
||||
|
||||
aglobal = 'Hello'
|
||||
def f():
|
||||
return aglobal
|
||||
|
||||
cache = ip.user_ns['_refbug_cache']
|
||||
cache.append(f)
|
||||
|
||||
def call_f():
|
||||
for func in cache:
|
||||
print('lowercased:',func().lower())
|
33
.venv/Lib/site-packages/IPython/core/tests/simpleerr.py
Normal file
33
.venv/Lib/site-packages/IPython/core/tests/simpleerr.py
Normal file
@ -0,0 +1,33 @@
|
||||
"""Error script. DO NOT EDIT FURTHER! It will break exception doctests!!!"""
|
||||
import sys
|
||||
|
||||
def div0():
|
||||
"foo"
|
||||
x = 1
|
||||
y = 0
|
||||
x/y
|
||||
|
||||
def sysexit(stat, mode):
|
||||
raise SystemExit(stat, f"Mode = {mode}")
|
||||
|
||||
|
||||
def bar(mode):
|
||||
"bar"
|
||||
if mode=='div':
|
||||
div0()
|
||||
elif mode=='exit':
|
||||
try:
|
||||
stat = int(sys.argv[2])
|
||||
except:
|
||||
stat = 1
|
||||
sysexit(stat, mode)
|
||||
else:
|
||||
raise ValueError('Unknown mode')
|
||||
|
||||
if __name__ == '__main__':
|
||||
try:
|
||||
mode = sys.argv[1]
|
||||
except IndexError:
|
||||
mode = 'div'
|
||||
|
||||
bar(mode)
|
34
.venv/Lib/site-packages/IPython/core/tests/tclass.py
Normal file
34
.venv/Lib/site-packages/IPython/core/tests/tclass.py
Normal file
@ -0,0 +1,34 @@
|
||||
"""Simple script to be run *twice*, to check reference counting bugs.
|
||||
|
||||
See test_run for details."""
|
||||
|
||||
|
||||
import sys
|
||||
|
||||
# We want to ensure that while objects remain available for immediate access,
|
||||
# objects from *previous* runs of the same script get collected, to avoid
|
||||
# accumulating massive amounts of old references.
|
||||
class C(object):
|
||||
def __init__(self,name):
|
||||
self.name = name
|
||||
self.p = print
|
||||
self.flush_stdout = sys.stdout.flush
|
||||
|
||||
def __del__(self):
|
||||
self.p('tclass.py: deleting object:',self.name)
|
||||
self.flush_stdout()
|
||||
|
||||
try:
|
||||
name = sys.argv[1]
|
||||
except IndexError:
|
||||
pass
|
||||
else:
|
||||
if name.startswith('C'):
|
||||
c = C(name)
|
||||
|
||||
#print >> sys.stderr, "ARGV:", sys.argv # dbg
|
||||
|
||||
# This next print statement is NOT debugging, we're making the check on a
|
||||
# completely separate process so we verify by capturing stdout:
|
||||
print('ARGV 1-:', sys.argv[1:])
|
||||
sys.stdout.flush()
|
66
.venv/Lib/site-packages/IPython/core/tests/test_alias.py
Normal file
66
.venv/Lib/site-packages/IPython/core/tests/test_alias.py
Normal file
@ -0,0 +1,66 @@
|
||||
from IPython.utils.capture import capture_output
|
||||
|
||||
import pytest
|
||||
|
||||
def test_alias_lifecycle():
|
||||
name = 'test_alias1'
|
||||
cmd = 'echo "Hello"'
|
||||
am = _ip.alias_manager
|
||||
am.clear_aliases()
|
||||
am.define_alias(name, cmd)
|
||||
assert am.is_alias(name)
|
||||
assert am.retrieve_alias(name) == cmd
|
||||
assert (name, cmd) in am.aliases
|
||||
|
||||
# Test running the alias
|
||||
orig_system = _ip.system
|
||||
result = []
|
||||
_ip.system = result.append
|
||||
try:
|
||||
_ip.run_cell('%{}'.format(name))
|
||||
result = [c.strip() for c in result]
|
||||
assert result == [cmd]
|
||||
finally:
|
||||
_ip.system = orig_system
|
||||
|
||||
# Test removing the alias
|
||||
am.undefine_alias(name)
|
||||
assert not am.is_alias(name)
|
||||
with pytest.raises(ValueError):
|
||||
am.retrieve_alias(name)
|
||||
assert (name, cmd) not in am.aliases
|
||||
|
||||
|
||||
def test_alias_args_error():
|
||||
"""Error expanding with wrong number of arguments"""
|
||||
_ip.alias_manager.define_alias('parts', 'echo first %s second %s')
|
||||
# capture stderr:
|
||||
with capture_output() as cap:
|
||||
_ip.run_cell('parts 1')
|
||||
|
||||
assert cap.stderr.split(":")[0] == "UsageError"
|
||||
|
||||
|
||||
def test_alias_args_commented():
|
||||
"""Check that alias correctly ignores 'commented out' args"""
|
||||
_ip.run_line_magic("alias", "commentarg echo this is %%s a commented out arg")
|
||||
|
||||
with capture_output() as cap:
|
||||
_ip.run_cell("commentarg")
|
||||
|
||||
# strip() is for pytest compat; testing via iptest patch IPython shell
|
||||
# in testing.globalipapp and replace the system call which messed up the
|
||||
# \r\n
|
||||
assert cap.stdout.strip() == 'this is %s a commented out arg'
|
||||
|
||||
def test_alias_args_commented_nargs():
|
||||
"""Check that alias correctly counts args, excluding those commented out"""
|
||||
am = _ip.alias_manager
|
||||
alias_name = 'comargcount'
|
||||
cmd = 'echo this is %%s a commented out arg and this is not %s'
|
||||
|
||||
am.define_alias(alias_name, cmd)
|
||||
assert am.is_alias(alias_name)
|
||||
|
||||
thealias = am.get_alias(alias_name)
|
||||
assert thealias.nargs == 1
|
@ -0,0 +1,70 @@
|
||||
# coding: utf-8
|
||||
"""Tests for IPython.core.application"""
|
||||
|
||||
import os
|
||||
import tempfile
|
||||
|
||||
from tempfile import TemporaryDirectory
|
||||
from traitlets import Unicode
|
||||
|
||||
from IPython.core.application import BaseIPythonApplication
|
||||
from IPython.testing import decorators as dec
|
||||
|
||||
|
||||
@dec.onlyif_unicode_paths
|
||||
def test_unicode_cwd():
|
||||
"""Check that IPython starts with non-ascii characters in the path."""
|
||||
wd = tempfile.mkdtemp(suffix=u"€")
|
||||
|
||||
old_wd = os.getcwd()
|
||||
os.chdir(wd)
|
||||
#raise Exception(repr(os.getcwd()))
|
||||
try:
|
||||
app = BaseIPythonApplication()
|
||||
# The lines below are copied from Application.initialize()
|
||||
app.init_profile_dir()
|
||||
app.init_config_files()
|
||||
app.load_config_file(suppress_errors=False)
|
||||
finally:
|
||||
os.chdir(old_wd)
|
||||
|
||||
@dec.onlyif_unicode_paths
|
||||
def test_unicode_ipdir():
|
||||
"""Check that IPython starts with non-ascii characters in the IP dir."""
|
||||
ipdir = tempfile.mkdtemp(suffix=u"€")
|
||||
|
||||
# Create the config file, so it tries to load it.
|
||||
with open(os.path.join(ipdir, "ipython_config.py"), "w", encoding="utf-8") as f:
|
||||
pass
|
||||
|
||||
old_ipdir1 = os.environ.pop("IPYTHONDIR", None)
|
||||
old_ipdir2 = os.environ.pop("IPYTHON_DIR", None)
|
||||
os.environ["IPYTHONDIR"] = ipdir
|
||||
try:
|
||||
app = BaseIPythonApplication()
|
||||
# The lines below are copied from Application.initialize()
|
||||
app.init_profile_dir()
|
||||
app.init_config_files()
|
||||
app.load_config_file(suppress_errors=False)
|
||||
finally:
|
||||
if old_ipdir1:
|
||||
os.environ["IPYTHONDIR"] = old_ipdir1
|
||||
if old_ipdir2:
|
||||
os.environ["IPYTHONDIR"] = old_ipdir2
|
||||
|
||||
def test_cli_priority():
|
||||
with TemporaryDirectory() as td:
|
||||
|
||||
class TestApp(BaseIPythonApplication):
|
||||
test = Unicode().tag(config=True)
|
||||
|
||||
# Create the config file, so it tries to load it.
|
||||
with open(os.path.join(td, "ipython_config.py"), "w", encoding="utf-8") as f:
|
||||
f.write("c.TestApp.test = 'config file'")
|
||||
|
||||
app = TestApp()
|
||||
app.initialize(["--profile-dir", td])
|
||||
assert app.test == "config file"
|
||||
app = TestApp()
|
||||
app.initialize(["--profile-dir", td, "--TestApp.test=cli"])
|
||||
assert app.test == "cli"
|
316
.venv/Lib/site-packages/IPython/core/tests/test_async_helpers.py
Normal file
316
.venv/Lib/site-packages/IPython/core/tests/test_async_helpers.py
Normal file
@ -0,0 +1,316 @@
|
||||
"""
|
||||
Test for async helpers.
|
||||
|
||||
Should only trigger on python 3.5+ or will have syntax errors.
|
||||
"""
|
||||
import platform
|
||||
from itertools import chain, repeat
|
||||
from textwrap import dedent, indent
|
||||
from unittest import TestCase
|
||||
from IPython.testing.decorators import skip_without
|
||||
import sys
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from IPython import get_ipython
|
||||
|
||||
ip = get_ipython()
|
||||
|
||||
|
||||
iprc = lambda x: ip.run_cell(dedent(x)).raise_error()
|
||||
iprc_nr = lambda x: ip.run_cell(dedent(x))
|
||||
|
||||
from IPython.core.async_helpers import _should_be_async
|
||||
|
||||
class AsyncTest(TestCase):
|
||||
def test_should_be_async(self):
|
||||
self.assertFalse(_should_be_async("False"))
|
||||
self.assertTrue(_should_be_async("await bar()"))
|
||||
self.assertTrue(_should_be_async("x = await bar()"))
|
||||
self.assertFalse(
|
||||
_should_be_async(
|
||||
dedent(
|
||||
"""
|
||||
async def awaitable():
|
||||
pass
|
||||
"""
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
def _get_top_level_cases(self):
|
||||
# These are test cases that should be valid in a function
|
||||
# but invalid outside of a function.
|
||||
test_cases = []
|
||||
test_cases.append(('basic', "{val}"))
|
||||
|
||||
# Note, in all conditional cases, I use True instead of
|
||||
# False so that the peephole optimizer won't optimize away
|
||||
# the return, so CPython will see this as a syntax error:
|
||||
#
|
||||
# while True:
|
||||
# break
|
||||
# return
|
||||
#
|
||||
# But not this:
|
||||
#
|
||||
# while False:
|
||||
# return
|
||||
#
|
||||
# See https://bugs.python.org/issue1875
|
||||
|
||||
test_cases.append(('if', dedent("""
|
||||
if True:
|
||||
{val}
|
||||
""")))
|
||||
|
||||
test_cases.append(('while', dedent("""
|
||||
while True:
|
||||
{val}
|
||||
break
|
||||
""")))
|
||||
|
||||
test_cases.append(('try', dedent("""
|
||||
try:
|
||||
{val}
|
||||
except:
|
||||
pass
|
||||
""")))
|
||||
|
||||
test_cases.append(('except', dedent("""
|
||||
try:
|
||||
pass
|
||||
except:
|
||||
{val}
|
||||
""")))
|
||||
|
||||
test_cases.append(('finally', dedent("""
|
||||
try:
|
||||
pass
|
||||
except:
|
||||
pass
|
||||
finally:
|
||||
{val}
|
||||
""")))
|
||||
|
||||
test_cases.append(('for', dedent("""
|
||||
for _ in range(4):
|
||||
{val}
|
||||
""")))
|
||||
|
||||
|
||||
test_cases.append(('nested', dedent("""
|
||||
if True:
|
||||
while True:
|
||||
{val}
|
||||
break
|
||||
""")))
|
||||
|
||||
test_cases.append(('deep-nested', dedent("""
|
||||
if True:
|
||||
while True:
|
||||
break
|
||||
for x in range(3):
|
||||
if True:
|
||||
while True:
|
||||
for x in range(3):
|
||||
{val}
|
||||
""")))
|
||||
|
||||
return test_cases
|
||||
|
||||
def _get_ry_syntax_errors(self):
|
||||
# This is a mix of tests that should be a syntax error if
|
||||
# return or yield whether or not they are in a function
|
||||
|
||||
test_cases = []
|
||||
|
||||
test_cases.append(('class', dedent("""
|
||||
class V:
|
||||
{val}
|
||||
""")))
|
||||
|
||||
test_cases.append(('nested-class', dedent("""
|
||||
class V:
|
||||
class C:
|
||||
{val}
|
||||
""")))
|
||||
|
||||
return test_cases
|
||||
|
||||
|
||||
def test_top_level_return_error(self):
|
||||
tl_err_test_cases = self._get_top_level_cases()
|
||||
tl_err_test_cases.extend(self._get_ry_syntax_errors())
|
||||
|
||||
vals = ('return', 'yield', 'yield from (_ for _ in range(3))',
|
||||
dedent('''
|
||||
def f():
|
||||
pass
|
||||
return
|
||||
'''),
|
||||
)
|
||||
|
||||
for test_name, test_case in tl_err_test_cases:
|
||||
# This example should work if 'pass' is used as the value
|
||||
with self.subTest((test_name, 'pass')):
|
||||
iprc(test_case.format(val='pass'))
|
||||
|
||||
# It should fail with all the values
|
||||
for val in vals:
|
||||
with self.subTest((test_name, val)):
|
||||
msg = "Syntax error not raised for %s, %s" % (test_name, val)
|
||||
with self.assertRaises(SyntaxError, msg=msg):
|
||||
iprc(test_case.format(val=val))
|
||||
|
||||
def test_in_func_no_error(self):
|
||||
# Test that the implementation of top-level return/yield
|
||||
# detection isn't *too* aggressive, and works inside a function
|
||||
func_contexts = []
|
||||
|
||||
func_contexts.append(('func', False, dedent("""
|
||||
def f():""")))
|
||||
|
||||
func_contexts.append(('method', False, dedent("""
|
||||
class MyClass:
|
||||
def __init__(self):
|
||||
""")))
|
||||
|
||||
func_contexts.append(('async-func', True, dedent("""
|
||||
async def f():""")))
|
||||
|
||||
func_contexts.append(('async-method', True, dedent("""
|
||||
class MyClass:
|
||||
async def f(self):""")))
|
||||
|
||||
func_contexts.append(('closure', False, dedent("""
|
||||
def f():
|
||||
def g():
|
||||
""")))
|
||||
|
||||
def nest_case(context, case):
|
||||
# Detect indentation
|
||||
lines = context.strip().splitlines()
|
||||
prefix_len = 0
|
||||
for c in lines[-1]:
|
||||
if c != ' ':
|
||||
break
|
||||
prefix_len += 1
|
||||
|
||||
indented_case = indent(case, ' ' * (prefix_len + 4))
|
||||
return context + '\n' + indented_case
|
||||
|
||||
# Gather and run the tests
|
||||
|
||||
# yield is allowed in async functions, starting in Python 3.6,
|
||||
# and yield from is not allowed in any version
|
||||
vals = ('return', 'yield', 'yield from (_ for _ in range(3))')
|
||||
|
||||
success_tests = zip(self._get_top_level_cases(), repeat(False))
|
||||
failure_tests = zip(self._get_ry_syntax_errors(), repeat(True))
|
||||
|
||||
tests = chain(success_tests, failure_tests)
|
||||
|
||||
for context_name, async_func, context in func_contexts:
|
||||
for (test_name, test_case), should_fail in tests:
|
||||
nested_case = nest_case(context, test_case)
|
||||
|
||||
for val in vals:
|
||||
test_id = (context_name, test_name, val)
|
||||
cell = nested_case.format(val=val)
|
||||
|
||||
with self.subTest(test_id):
|
||||
if should_fail:
|
||||
msg = ("SyntaxError not raised for %s" %
|
||||
str(test_id))
|
||||
with self.assertRaises(SyntaxError, msg=msg):
|
||||
iprc(cell)
|
||||
|
||||
print(cell)
|
||||
else:
|
||||
iprc(cell)
|
||||
|
||||
def test_nonlocal(self):
|
||||
# fails if outer scope is not a function scope or if var not defined
|
||||
with self.assertRaises(SyntaxError):
|
||||
iprc("nonlocal x")
|
||||
iprc("""
|
||||
x = 1
|
||||
def f():
|
||||
nonlocal x
|
||||
x = 10000
|
||||
yield x
|
||||
""")
|
||||
iprc("""
|
||||
def f():
|
||||
def g():
|
||||
nonlocal x
|
||||
x = 10000
|
||||
yield x
|
||||
""")
|
||||
|
||||
# works if outer scope is a function scope and var exists
|
||||
iprc("""
|
||||
def f():
|
||||
x = 20
|
||||
def g():
|
||||
nonlocal x
|
||||
x = 10000
|
||||
yield x
|
||||
""")
|
||||
|
||||
|
||||
def test_execute(self):
|
||||
iprc("""
|
||||
import asyncio
|
||||
await asyncio.sleep(0.001)
|
||||
"""
|
||||
)
|
||||
|
||||
def test_autoawait(self):
|
||||
iprc("%autoawait False")
|
||||
iprc("%autoawait True")
|
||||
iprc("""
|
||||
from asyncio import sleep
|
||||
await sleep(0.1)
|
||||
"""
|
||||
)
|
||||
|
||||
if sys.version_info < (3, 9) and platform.python_implementation() != "PyPy":
|
||||
# new pgen parser in 3.9 does not raise MemoryError on too many nested
|
||||
# parens anymore
|
||||
def test_memory_error(self):
|
||||
with self.assertRaises(MemoryError):
|
||||
iprc("(" * 200 + ")" * 200)
|
||||
|
||||
@skip_without('curio')
|
||||
def test_autoawait_curio(self):
|
||||
iprc("%autoawait curio")
|
||||
|
||||
@skip_without('trio')
|
||||
def test_autoawait_trio(self):
|
||||
iprc("%autoawait trio")
|
||||
|
||||
@skip_without('trio')
|
||||
def test_autoawait_trio_wrong_sleep(self):
|
||||
iprc("%autoawait trio")
|
||||
res = iprc_nr("""
|
||||
import asyncio
|
||||
await asyncio.sleep(0)
|
||||
""")
|
||||
with self.assertRaises(TypeError):
|
||||
res.raise_error()
|
||||
|
||||
@skip_without('trio')
|
||||
def test_autoawait_asyncio_wrong_sleep(self):
|
||||
iprc("%autoawait asyncio")
|
||||
res = iprc_nr("""
|
||||
import trio
|
||||
await trio.sleep(0)
|
||||
""")
|
||||
with self.assertRaises(RuntimeError):
|
||||
res.raise_error()
|
||||
|
||||
|
||||
def tearDown(self):
|
||||
ip.loop_runner = "asyncio"
|
66
.venv/Lib/site-packages/IPython/core/tests/test_autocall.py
Normal file
66
.venv/Lib/site-packages/IPython/core/tests/test_autocall.py
Normal file
@ -0,0 +1,66 @@
|
||||
"""These kinds of tests are less than ideal, but at least they run.
|
||||
|
||||
This was an old test that was being run interactively in the top-level tests/
|
||||
directory, which we are removing. For now putting this here ensures at least
|
||||
we do run the test, though ultimately this functionality should all be tested
|
||||
with better-isolated tests that don't rely on the global instance in iptest.
|
||||
"""
|
||||
from IPython.core.splitinput import LineInfo
|
||||
from IPython.core.prefilter import AutocallChecker
|
||||
|
||||
def doctest_autocall():
|
||||
"""
|
||||
In [1]: def f1(a,b,c):
|
||||
...: return a+b+c
|
||||
...:
|
||||
|
||||
In [2]: def f2(a):
|
||||
...: return a + a
|
||||
...:
|
||||
|
||||
In [3]: def r(x):
|
||||
...: return True
|
||||
...:
|
||||
|
||||
In [4]: ;f2 a b c
|
||||
Out[4]: 'a b ca b c'
|
||||
|
||||
In [5]: assert _ == "a b ca b c"
|
||||
|
||||
In [6]: ,f1 a b c
|
||||
Out[6]: 'abc'
|
||||
|
||||
In [7]: assert _ == 'abc'
|
||||
|
||||
In [8]: print(_)
|
||||
abc
|
||||
|
||||
In [9]: /f1 1,2,3
|
||||
Out[9]: 6
|
||||
|
||||
In [10]: assert _ == 6
|
||||
|
||||
In [11]: /f2 4
|
||||
Out[11]: 8
|
||||
|
||||
In [12]: assert _ == 8
|
||||
|
||||
In [12]: del f1, f2
|
||||
|
||||
In [13]: ,r a
|
||||
Out[13]: True
|
||||
|
||||
In [14]: assert _ == True
|
||||
|
||||
In [15]: r'a'
|
||||
Out[15]: 'a'
|
||||
|
||||
In [16]: assert _ == 'a'
|
||||
"""
|
||||
|
||||
|
||||
def test_autocall_should_ignore_raw_strings():
|
||||
line_info = LineInfo("r'a'")
|
||||
pm = ip.prefilter_manager
|
||||
ac = AutocallChecker(shell=pm.shell, prefilter_manager=pm, config=pm.config)
|
||||
assert ac.check(line_info) is None
|
@ -0,0 +1,71 @@
|
||||
# coding: utf-8
|
||||
"""Tests for the compilerop module.
|
||||
"""
|
||||
#-----------------------------------------------------------------------------
|
||||
# Copyright (C) 2010-2011 The IPython Development Team.
|
||||
#
|
||||
# Distributed under the terms of the BSD License.
|
||||
#
|
||||
# The full license is in the file COPYING.txt, distributed with this software.
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Imports
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
# Stdlib imports
|
||||
import linecache
|
||||
import sys
|
||||
|
||||
# Third-party imports
|
||||
import pytest
|
||||
|
||||
# Our own imports
|
||||
from IPython.core import compilerop
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Test functions
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
def test_code_name():
|
||||
code = 'x=1'
|
||||
name = compilerop.code_name(code)
|
||||
assert name.startswith("<ipython-input-0")
|
||||
|
||||
|
||||
def test_code_name2():
|
||||
code = 'x=1'
|
||||
name = compilerop.code_name(code, 9)
|
||||
assert name.startswith("<ipython-input-9")
|
||||
|
||||
|
||||
def test_cache():
|
||||
"""Test the compiler correctly compiles and caches inputs
|
||||
"""
|
||||
cp = compilerop.CachingCompiler()
|
||||
ncache = len(linecache.cache)
|
||||
cp.cache('x=1')
|
||||
assert len(linecache.cache) > ncache
|
||||
|
||||
def test_proper_default_encoding():
|
||||
# Check we're in a proper Python 2 environment (some imports, such
|
||||
# as GTK, can change the default encoding, which can hide bugs.)
|
||||
assert sys.getdefaultencoding() == "utf-8"
|
||||
|
||||
def test_cache_unicode():
|
||||
cp = compilerop.CachingCompiler()
|
||||
ncache = len(linecache.cache)
|
||||
cp.cache(u"t = 'žćčšđ'")
|
||||
assert len(linecache.cache) > ncache
|
||||
|
||||
def test_compiler_check_cache():
|
||||
"""Test the compiler properly manages the cache.
|
||||
"""
|
||||
# Rather simple-minded tests that just exercise the API
|
||||
cp = compilerop.CachingCompiler()
|
||||
cp.cache('x=1', 99)
|
||||
# Ensure now that after clearing the cache, our entries survive
|
||||
linecache.checkcache()
|
||||
assert any(
|
||||
k.startswith("<ipython-input-99") for k in linecache.cache
|
||||
), "Entry for input-99 missing from linecache"
|
1275
.venv/Lib/site-packages/IPython/core/tests/test_completer.py
Normal file
1275
.venv/Lib/site-packages/IPython/core/tests/test_completer.py
Normal file
File diff suppressed because it is too large
Load Diff
193
.venv/Lib/site-packages/IPython/core/tests/test_completerlib.py
Normal file
193
.venv/Lib/site-packages/IPython/core/tests/test_completerlib.py
Normal file
@ -0,0 +1,193 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Tests for completerlib.
|
||||
|
||||
"""
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Imports
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import sys
|
||||
import tempfile
|
||||
import unittest
|
||||
from os.path import join
|
||||
|
||||
from tempfile import TemporaryDirectory
|
||||
|
||||
from IPython.core.completerlib import magic_run_completer, module_completion, try_import
|
||||
from IPython.testing.decorators import onlyif_unicode_paths
|
||||
|
||||
|
||||
class MockEvent(object):
|
||||
def __init__(self, line):
|
||||
self.line = line
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Test functions begin
|
||||
#-----------------------------------------------------------------------------
|
||||
class Test_magic_run_completer(unittest.TestCase):
|
||||
files = [u"aao.py", u"a.py", u"b.py", u"aao.txt"]
|
||||
dirs = [u"adir/", "bdir/"]
|
||||
|
||||
def setUp(self):
|
||||
self.BASETESTDIR = tempfile.mkdtemp()
|
||||
for fil in self.files:
|
||||
with open(join(self.BASETESTDIR, fil), "w", encoding="utf-8") as sfile:
|
||||
sfile.write("pass\n")
|
||||
for d in self.dirs:
|
||||
os.mkdir(join(self.BASETESTDIR, d))
|
||||
|
||||
self.oldpath = os.getcwd()
|
||||
os.chdir(self.BASETESTDIR)
|
||||
|
||||
def tearDown(self):
|
||||
os.chdir(self.oldpath)
|
||||
shutil.rmtree(self.BASETESTDIR)
|
||||
|
||||
def test_1(self):
|
||||
"""Test magic_run_completer, should match two alternatives
|
||||
"""
|
||||
event = MockEvent(u"%run a")
|
||||
mockself = None
|
||||
match = set(magic_run_completer(mockself, event))
|
||||
self.assertEqual(match, {u"a.py", u"aao.py", u"adir/"})
|
||||
|
||||
def test_2(self):
|
||||
"""Test magic_run_completer, should match one alternative
|
||||
"""
|
||||
event = MockEvent(u"%run aa")
|
||||
mockself = None
|
||||
match = set(magic_run_completer(mockself, event))
|
||||
self.assertEqual(match, {u"aao.py"})
|
||||
|
||||
def test_3(self):
|
||||
"""Test magic_run_completer with unterminated " """
|
||||
event = MockEvent(u'%run "a')
|
||||
mockself = None
|
||||
match = set(magic_run_completer(mockself, event))
|
||||
self.assertEqual(match, {u"a.py", u"aao.py", u"adir/"})
|
||||
|
||||
def test_completion_more_args(self):
|
||||
event = MockEvent(u'%run a.py ')
|
||||
match = set(magic_run_completer(None, event))
|
||||
self.assertEqual(match, set(self.files + self.dirs))
|
||||
|
||||
def test_completion_in_dir(self):
|
||||
# Github issue #3459
|
||||
event = MockEvent(u'%run a.py {}'.format(join(self.BASETESTDIR, 'a')))
|
||||
print(repr(event.line))
|
||||
match = set(magic_run_completer(None, event))
|
||||
# We specifically use replace here rather than normpath, because
|
||||
# at one point there were duplicates 'adir' and 'adir/', and normpath
|
||||
# would hide the failure for that.
|
||||
self.assertEqual(match, {join(self.BASETESTDIR, f).replace('\\','/')
|
||||
for f in (u'a.py', u'aao.py', u'aao.txt', u'adir/')})
|
||||
|
||||
class Test_magic_run_completer_nonascii(unittest.TestCase):
|
||||
@onlyif_unicode_paths
|
||||
def setUp(self):
|
||||
self.BASETESTDIR = tempfile.mkdtemp()
|
||||
for fil in [u"aaø.py", u"a.py", u"b.py"]:
|
||||
with open(join(self.BASETESTDIR, fil), "w", encoding="utf-8") as sfile:
|
||||
sfile.write("pass\n")
|
||||
self.oldpath = os.getcwd()
|
||||
os.chdir(self.BASETESTDIR)
|
||||
|
||||
def tearDown(self):
|
||||
os.chdir(self.oldpath)
|
||||
shutil.rmtree(self.BASETESTDIR)
|
||||
|
||||
@onlyif_unicode_paths
|
||||
def test_1(self):
|
||||
"""Test magic_run_completer, should match two alternatives
|
||||
"""
|
||||
event = MockEvent(u"%run a")
|
||||
mockself = None
|
||||
match = set(magic_run_completer(mockself, event))
|
||||
self.assertEqual(match, {u"a.py", u"aaø.py"})
|
||||
|
||||
@onlyif_unicode_paths
|
||||
def test_2(self):
|
||||
"""Test magic_run_completer, should match one alternative
|
||||
"""
|
||||
event = MockEvent(u"%run aa")
|
||||
mockself = None
|
||||
match = set(magic_run_completer(mockself, event))
|
||||
self.assertEqual(match, {u"aaø.py"})
|
||||
|
||||
@onlyif_unicode_paths
|
||||
def test_3(self):
|
||||
"""Test magic_run_completer with unterminated " """
|
||||
event = MockEvent(u'%run "a')
|
||||
mockself = None
|
||||
match = set(magic_run_completer(mockself, event))
|
||||
self.assertEqual(match, {u"a.py", u"aaø.py"})
|
||||
|
||||
# module_completer:
|
||||
|
||||
def test_import_invalid_module():
|
||||
"""Testing of issue https://github.com/ipython/ipython/issues/1107"""
|
||||
invalid_module_names = {'foo-bar', 'foo:bar', '10foo'}
|
||||
valid_module_names = {'foobar'}
|
||||
with TemporaryDirectory() as tmpdir:
|
||||
sys.path.insert( 0, tmpdir )
|
||||
for name in invalid_module_names | valid_module_names:
|
||||
filename = os.path.join(tmpdir, name + ".py")
|
||||
open(filename, "w", encoding="utf-8").close()
|
||||
|
||||
s = set( module_completion('import foo') )
|
||||
intersection = s.intersection(invalid_module_names)
|
||||
assert intersection == set()
|
||||
|
||||
assert valid_module_names.issubset(s), valid_module_names.intersection(s)
|
||||
|
||||
|
||||
def test_bad_module_all():
|
||||
"""Test module with invalid __all__
|
||||
|
||||
https://github.com/ipython/ipython/issues/9678
|
||||
"""
|
||||
testsdir = os.path.dirname(__file__)
|
||||
sys.path.insert(0, testsdir)
|
||||
try:
|
||||
results = module_completion("from bad_all import ")
|
||||
assert "puppies" in results
|
||||
for r in results:
|
||||
assert isinstance(r, str)
|
||||
|
||||
# bad_all doesn't contain submodules, but this completion
|
||||
# should finish without raising an exception:
|
||||
results = module_completion("import bad_all.")
|
||||
assert results == []
|
||||
finally:
|
||||
sys.path.remove(testsdir)
|
||||
|
||||
|
||||
def test_module_without_init():
|
||||
"""
|
||||
Test module without __init__.py.
|
||||
|
||||
https://github.com/ipython/ipython/issues/11226
|
||||
"""
|
||||
fake_module_name = "foo"
|
||||
with TemporaryDirectory() as tmpdir:
|
||||
sys.path.insert(0, tmpdir)
|
||||
try:
|
||||
os.makedirs(os.path.join(tmpdir, fake_module_name))
|
||||
s = try_import(mod=fake_module_name)
|
||||
assert s == []
|
||||
finally:
|
||||
sys.path.remove(tmpdir)
|
||||
|
||||
|
||||
def test_valid_exported_submodules():
|
||||
"""
|
||||
Test checking exported (__all__) objects are submodules
|
||||
"""
|
||||
results = module_completion("import os.pa")
|
||||
# ensure we get a valid submodule:
|
||||
assert "os.path" in results
|
||||
# ensure we don't get objects that aren't submodules:
|
||||
assert "os.pathconf" not in results
|
567
.venv/Lib/site-packages/IPython/core/tests/test_debugger.py
Normal file
567
.venv/Lib/site-packages/IPython/core/tests/test_debugger.py
Normal file
@ -0,0 +1,567 @@
|
||||
"""Tests for debugging machinery.
|
||||
"""
|
||||
|
||||
# Copyright (c) IPython Development Team.
|
||||
# Distributed under the terms of the Modified BSD License.
|
||||
|
||||
import bdb
|
||||
import builtins
|
||||
import os
|
||||
import sys
|
||||
import platform
|
||||
|
||||
from tempfile import NamedTemporaryFile
|
||||
from textwrap import dedent
|
||||
from unittest.mock import patch
|
||||
|
||||
from IPython.core import debugger
|
||||
from IPython.testing import IPYTHON_TESTING_TIMEOUT_SCALE
|
||||
from IPython.testing.decorators import skip_win32
|
||||
import pytest
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Helper classes, from CPython's Pdb test suite
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
class _FakeInput(object):
|
||||
"""
|
||||
A fake input stream for pdb's interactive debugger. Whenever a
|
||||
line is read, print it (to simulate the user typing it), and then
|
||||
return it. The set of lines to return is specified in the
|
||||
constructor; they should not have trailing newlines.
|
||||
"""
|
||||
def __init__(self, lines):
|
||||
self.lines = iter(lines)
|
||||
|
||||
def readline(self):
|
||||
line = next(self.lines)
|
||||
print(line)
|
||||
return line+'\n'
|
||||
|
||||
class PdbTestInput(object):
|
||||
"""Context manager that makes testing Pdb in doctests easier."""
|
||||
|
||||
def __init__(self, input):
|
||||
self.input = input
|
||||
|
||||
def __enter__(self):
|
||||
self.real_stdin = sys.stdin
|
||||
sys.stdin = _FakeInput(self.input)
|
||||
|
||||
def __exit__(self, *exc):
|
||||
sys.stdin = self.real_stdin
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Tests
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
def test_ipdb_magics():
|
||||
'''Test calling some IPython magics from ipdb.
|
||||
|
||||
First, set up some test functions and classes which we can inspect.
|
||||
|
||||
>>> class ExampleClass(object):
|
||||
... """Docstring for ExampleClass."""
|
||||
... def __init__(self):
|
||||
... """Docstring for ExampleClass.__init__"""
|
||||
... pass
|
||||
... def __str__(self):
|
||||
... return "ExampleClass()"
|
||||
|
||||
>>> def example_function(x, y, z="hello"):
|
||||
... """Docstring for example_function."""
|
||||
... pass
|
||||
|
||||
>>> old_trace = sys.gettrace()
|
||||
|
||||
Create a function which triggers ipdb.
|
||||
|
||||
>>> def trigger_ipdb():
|
||||
... a = ExampleClass()
|
||||
... debugger.Pdb().set_trace()
|
||||
|
||||
>>> with PdbTestInput([
|
||||
... 'pdef example_function',
|
||||
... 'pdoc ExampleClass',
|
||||
... 'up',
|
||||
... 'down',
|
||||
... 'list',
|
||||
... 'pinfo a',
|
||||
... 'll',
|
||||
... 'continue',
|
||||
... ]):
|
||||
... trigger_ipdb()
|
||||
--Return--
|
||||
None
|
||||
> <doctest ...>(3)trigger_ipdb()
|
||||
1 def trigger_ipdb():
|
||||
2 a = ExampleClass()
|
||||
----> 3 debugger.Pdb().set_trace()
|
||||
<BLANKLINE>
|
||||
ipdb> pdef example_function
|
||||
example_function(x, y, z='hello')
|
||||
ipdb> pdoc ExampleClass
|
||||
Class docstring:
|
||||
Docstring for ExampleClass.
|
||||
Init docstring:
|
||||
Docstring for ExampleClass.__init__
|
||||
ipdb> up
|
||||
> <doctest ...>(11)<module>()
|
||||
7 'pinfo a',
|
||||
8 'll',
|
||||
9 'continue',
|
||||
10 ]):
|
||||
---> 11 trigger_ipdb()
|
||||
<BLANKLINE>
|
||||
ipdb> down
|
||||
None
|
||||
> <doctest ...>(3)trigger_ipdb()
|
||||
1 def trigger_ipdb():
|
||||
2 a = ExampleClass()
|
||||
----> 3 debugger.Pdb().set_trace()
|
||||
<BLANKLINE>
|
||||
ipdb> list
|
||||
1 def trigger_ipdb():
|
||||
2 a = ExampleClass()
|
||||
----> 3 debugger.Pdb().set_trace()
|
||||
<BLANKLINE>
|
||||
ipdb> pinfo a
|
||||
Type: ExampleClass
|
||||
String form: ExampleClass()
|
||||
Namespace: Local...
|
||||
Docstring: Docstring for ExampleClass.
|
||||
Init docstring: Docstring for ExampleClass.__init__
|
||||
ipdb> ll
|
||||
1 def trigger_ipdb():
|
||||
2 a = ExampleClass()
|
||||
----> 3 debugger.Pdb().set_trace()
|
||||
<BLANKLINE>
|
||||
ipdb> continue
|
||||
|
||||
Restore previous trace function, e.g. for coverage.py
|
||||
|
||||
>>> sys.settrace(old_trace)
|
||||
'''
|
||||
|
||||
def test_ipdb_magics2():
|
||||
'''Test ipdb with a very short function.
|
||||
|
||||
>>> old_trace = sys.gettrace()
|
||||
|
||||
>>> def bar():
|
||||
... pass
|
||||
|
||||
Run ipdb.
|
||||
|
||||
>>> with PdbTestInput([
|
||||
... 'continue',
|
||||
... ]):
|
||||
... debugger.Pdb().runcall(bar)
|
||||
> <doctest ...>(2)bar()
|
||||
1 def bar():
|
||||
----> 2 pass
|
||||
<BLANKLINE>
|
||||
ipdb> continue
|
||||
|
||||
Restore previous trace function, e.g. for coverage.py
|
||||
|
||||
>>> sys.settrace(old_trace)
|
||||
'''
|
||||
|
||||
def can_quit():
|
||||
'''Test that quit work in ipydb
|
||||
|
||||
>>> old_trace = sys.gettrace()
|
||||
|
||||
>>> def bar():
|
||||
... pass
|
||||
|
||||
>>> with PdbTestInput([
|
||||
... 'quit',
|
||||
... ]):
|
||||
... debugger.Pdb().runcall(bar)
|
||||
> <doctest ...>(2)bar()
|
||||
1 def bar():
|
||||
----> 2 pass
|
||||
<BLANKLINE>
|
||||
ipdb> quit
|
||||
|
||||
Restore previous trace function, e.g. for coverage.py
|
||||
|
||||
>>> sys.settrace(old_trace)
|
||||
'''
|
||||
|
||||
|
||||
def can_exit():
|
||||
'''Test that quit work in ipydb
|
||||
|
||||
>>> old_trace = sys.gettrace()
|
||||
|
||||
>>> def bar():
|
||||
... pass
|
||||
|
||||
>>> with PdbTestInput([
|
||||
... 'exit',
|
||||
... ]):
|
||||
... debugger.Pdb().runcall(bar)
|
||||
> <doctest ...>(2)bar()
|
||||
1 def bar():
|
||||
----> 2 pass
|
||||
<BLANKLINE>
|
||||
ipdb> exit
|
||||
|
||||
Restore previous trace function, e.g. for coverage.py
|
||||
|
||||
>>> sys.settrace(old_trace)
|
||||
'''
|
||||
|
||||
|
||||
def test_interruptible_core_debugger():
|
||||
"""The debugger can be interrupted.
|
||||
|
||||
The presumption is there is some mechanism that causes a KeyboardInterrupt
|
||||
(this is implemented in ipykernel). We want to ensure the
|
||||
KeyboardInterrupt cause debugging to cease.
|
||||
"""
|
||||
def raising_input(msg="", called=[0]):
|
||||
called[0] += 1
|
||||
assert called[0] == 1, "input() should only be called once!"
|
||||
raise KeyboardInterrupt()
|
||||
|
||||
tracer_orig = sys.gettrace()
|
||||
try:
|
||||
with patch.object(builtins, "input", raising_input):
|
||||
debugger.InterruptiblePdb().set_trace()
|
||||
# The way this test will fail is by set_trace() never exiting,
|
||||
# resulting in a timeout by the test runner. The alternative
|
||||
# implementation would involve a subprocess, but that adds issues
|
||||
# with interrupting subprocesses that are rather complex, so it's
|
||||
# simpler just to do it this way.
|
||||
finally:
|
||||
# restore the original trace function
|
||||
sys.settrace(tracer_orig)
|
||||
|
||||
|
||||
@skip_win32
|
||||
def test_xmode_skip():
|
||||
"""that xmode skip frames
|
||||
|
||||
Not as a doctest as pytest does not run doctests.
|
||||
"""
|
||||
import pexpect
|
||||
env = os.environ.copy()
|
||||
env["IPY_TEST_SIMPLE_PROMPT"] = "1"
|
||||
|
||||
child = pexpect.spawn(
|
||||
sys.executable, ["-m", "IPython", "--colors=nocolor"], env=env
|
||||
)
|
||||
child.timeout = 15 * IPYTHON_TESTING_TIMEOUT_SCALE
|
||||
|
||||
child.expect("IPython")
|
||||
child.expect("\n")
|
||||
child.expect_exact("In [1]")
|
||||
|
||||
block = dedent(
|
||||
"""
|
||||
def f():
|
||||
__tracebackhide__ = True
|
||||
g()
|
||||
|
||||
def g():
|
||||
raise ValueError
|
||||
|
||||
f()
|
||||
"""
|
||||
)
|
||||
|
||||
for line in block.splitlines():
|
||||
child.sendline(line)
|
||||
child.expect_exact(line)
|
||||
child.expect_exact("skipping")
|
||||
|
||||
block = dedent(
|
||||
"""
|
||||
def f():
|
||||
__tracebackhide__ = True
|
||||
g()
|
||||
|
||||
def g():
|
||||
from IPython.core.debugger import set_trace
|
||||
set_trace()
|
||||
|
||||
f()
|
||||
"""
|
||||
)
|
||||
|
||||
for line in block.splitlines():
|
||||
child.sendline(line)
|
||||
child.expect_exact(line)
|
||||
|
||||
child.expect("ipdb>")
|
||||
child.sendline("w")
|
||||
child.expect("hidden")
|
||||
child.expect("ipdb>")
|
||||
child.sendline("skip_hidden false")
|
||||
child.sendline("w")
|
||||
child.expect("__traceba")
|
||||
child.expect("ipdb>")
|
||||
|
||||
child.close()
|
||||
|
||||
|
||||
skip_decorators_blocks = (
|
||||
"""
|
||||
def helpers_helper():
|
||||
pass # should not stop here except breakpoint
|
||||
""",
|
||||
"""
|
||||
def helper_1():
|
||||
helpers_helper() # should not stop here
|
||||
""",
|
||||
"""
|
||||
def helper_2():
|
||||
pass # should not stop here
|
||||
""",
|
||||
"""
|
||||
def pdb_skipped_decorator2(function):
|
||||
def wrapped_fn(*args, **kwargs):
|
||||
__debuggerskip__ = True
|
||||
helper_2()
|
||||
__debuggerskip__ = False
|
||||
result = function(*args, **kwargs)
|
||||
__debuggerskip__ = True
|
||||
helper_2()
|
||||
return result
|
||||
return wrapped_fn
|
||||
""",
|
||||
"""
|
||||
def pdb_skipped_decorator(function):
|
||||
def wrapped_fn(*args, **kwargs):
|
||||
__debuggerskip__ = True
|
||||
helper_1()
|
||||
__debuggerskip__ = False
|
||||
result = function(*args, **kwargs)
|
||||
__debuggerskip__ = True
|
||||
helper_2()
|
||||
return result
|
||||
return wrapped_fn
|
||||
""",
|
||||
"""
|
||||
@pdb_skipped_decorator
|
||||
@pdb_skipped_decorator2
|
||||
def bar(x, y):
|
||||
return x * y
|
||||
""",
|
||||
"""import IPython.terminal.debugger as ipdb""",
|
||||
"""
|
||||
def f():
|
||||
ipdb.set_trace()
|
||||
bar(3, 4)
|
||||
""",
|
||||
"""
|
||||
f()
|
||||
""",
|
||||
)
|
||||
|
||||
|
||||
def _decorator_skip_setup():
|
||||
import pexpect
|
||||
|
||||
env = os.environ.copy()
|
||||
env["IPY_TEST_SIMPLE_PROMPT"] = "1"
|
||||
|
||||
child = pexpect.spawn(
|
||||
sys.executable, ["-m", "IPython", "--colors=nocolor"], env=env
|
||||
)
|
||||
child.timeout = 15 * IPYTHON_TESTING_TIMEOUT_SCALE
|
||||
|
||||
child.expect("IPython")
|
||||
child.expect("\n")
|
||||
|
||||
child.timeout = 5 * IPYTHON_TESTING_TIMEOUT_SCALE
|
||||
|
||||
dedented_blocks = [dedent(b).strip() for b in skip_decorators_blocks]
|
||||
in_prompt_number = 1
|
||||
for cblock in dedented_blocks:
|
||||
child.expect_exact(f"In [{in_prompt_number}]:")
|
||||
in_prompt_number += 1
|
||||
for line in cblock.splitlines():
|
||||
child.sendline(line)
|
||||
child.expect_exact(line)
|
||||
child.sendline("")
|
||||
return child
|
||||
|
||||
|
||||
@skip_win32
|
||||
def test_decorator_skip():
|
||||
"""test that decorator frames can be skipped."""
|
||||
|
||||
child = _decorator_skip_setup()
|
||||
|
||||
child.expect_exact("3 bar(3, 4)")
|
||||
child.expect("ipdb>")
|
||||
|
||||
child.expect("ipdb>")
|
||||
child.sendline("step")
|
||||
child.expect_exact("step")
|
||||
|
||||
child.expect_exact("1 @pdb_skipped_decorator")
|
||||
|
||||
child.sendline("s")
|
||||
child.expect_exact("return x * y")
|
||||
|
||||
child.close()
|
||||
|
||||
|
||||
@pytest.mark.skipif(platform.python_implementation() == "PyPy", reason="issues on PyPy")
|
||||
@skip_win32
|
||||
def test_decorator_skip_disabled():
|
||||
"""test that decorator frame skipping can be disabled"""
|
||||
|
||||
child = _decorator_skip_setup()
|
||||
|
||||
child.expect_exact("3 bar(3, 4)")
|
||||
|
||||
for input_, expected in [
|
||||
("skip_predicates debuggerskip False", ""),
|
||||
("skip_predicates", "debuggerskip : False"),
|
||||
("step", "---> 2 def wrapped_fn"),
|
||||
("step", "----> 3 __debuggerskip__"),
|
||||
("step", "----> 4 helper_1()"),
|
||||
("step", "---> 1 def helper_1():"),
|
||||
("next", "----> 2 helpers_helper()"),
|
||||
("next", "--Return--"),
|
||||
("next", "----> 5 __debuggerskip__ = False"),
|
||||
]:
|
||||
child.expect("ipdb>")
|
||||
child.sendline(input_)
|
||||
child.expect_exact(input_)
|
||||
child.expect_exact(expected)
|
||||
|
||||
child.close()
|
||||
|
||||
|
||||
@pytest.mark.skipif(platform.python_implementation() == "PyPy", reason="issues on PyPy")
|
||||
@skip_win32
|
||||
def test_decorator_skip_with_breakpoint():
|
||||
"""test that decorator frame skipping can be disabled"""
|
||||
|
||||
import pexpect
|
||||
|
||||
env = os.environ.copy()
|
||||
env["IPY_TEST_SIMPLE_PROMPT"] = "1"
|
||||
|
||||
child = pexpect.spawn(
|
||||
sys.executable, ["-m", "IPython", "--colors=nocolor"], env=env
|
||||
)
|
||||
child.timeout = 15 * IPYTHON_TESTING_TIMEOUT_SCALE
|
||||
|
||||
child.expect("IPython")
|
||||
child.expect("\n")
|
||||
|
||||
child.timeout = 5 * IPYTHON_TESTING_TIMEOUT_SCALE
|
||||
|
||||
### we need a filename, so we need to exec the full block with a filename
|
||||
with NamedTemporaryFile(suffix=".py", dir=".", delete=True) as tf:
|
||||
|
||||
name = tf.name[:-3].split("/")[-1]
|
||||
tf.write("\n".join([dedent(x) for x in skip_decorators_blocks[:-1]]).encode())
|
||||
tf.flush()
|
||||
codeblock = f"from {name} import f"
|
||||
|
||||
dedented_blocks = [
|
||||
codeblock,
|
||||
"f()",
|
||||
]
|
||||
|
||||
in_prompt_number = 1
|
||||
for cblock in dedented_blocks:
|
||||
child.expect_exact(f"In [{in_prompt_number}]:")
|
||||
in_prompt_number += 1
|
||||
for line in cblock.splitlines():
|
||||
child.sendline(line)
|
||||
child.expect_exact(line)
|
||||
child.sendline("")
|
||||
|
||||
# as the filename does not exists, we'll rely on the filename prompt
|
||||
child.expect_exact("47 bar(3, 4)")
|
||||
|
||||
for input_, expected in [
|
||||
(f"b {name}.py:3", ""),
|
||||
("step", "1---> 3 pass # should not stop here except"),
|
||||
("step", "---> 38 @pdb_skipped_decorator"),
|
||||
("continue", ""),
|
||||
]:
|
||||
child.expect("ipdb>")
|
||||
child.sendline(input_)
|
||||
child.expect_exact(input_)
|
||||
child.expect_exact(expected)
|
||||
|
||||
child.close()
|
||||
|
||||
|
||||
@skip_win32
|
||||
def test_where_erase_value():
|
||||
"""Test that `where` does not access f_locals and erase values."""
|
||||
import pexpect
|
||||
|
||||
env = os.environ.copy()
|
||||
env["IPY_TEST_SIMPLE_PROMPT"] = "1"
|
||||
|
||||
child = pexpect.spawn(
|
||||
sys.executable, ["-m", "IPython", "--colors=nocolor"], env=env
|
||||
)
|
||||
child.timeout = 15 * IPYTHON_TESTING_TIMEOUT_SCALE
|
||||
|
||||
child.expect("IPython")
|
||||
child.expect("\n")
|
||||
child.expect_exact("In [1]")
|
||||
|
||||
block = dedent(
|
||||
"""
|
||||
def simple_f():
|
||||
myvar = 1
|
||||
print(myvar)
|
||||
1/0
|
||||
print(myvar)
|
||||
simple_f() """
|
||||
)
|
||||
|
||||
for line in block.splitlines():
|
||||
child.sendline(line)
|
||||
child.expect_exact(line)
|
||||
child.expect_exact("ZeroDivisionError")
|
||||
child.expect_exact("In [2]:")
|
||||
|
||||
child.sendline("%debug")
|
||||
|
||||
##
|
||||
child.expect("ipdb>")
|
||||
|
||||
child.sendline("myvar")
|
||||
child.expect("1")
|
||||
|
||||
##
|
||||
child.expect("ipdb>")
|
||||
|
||||
child.sendline("myvar = 2")
|
||||
|
||||
##
|
||||
child.expect_exact("ipdb>")
|
||||
|
||||
child.sendline("myvar")
|
||||
|
||||
child.expect_exact("2")
|
||||
|
||||
##
|
||||
child.expect("ipdb>")
|
||||
child.sendline("where")
|
||||
|
||||
##
|
||||
child.expect("ipdb>")
|
||||
child.sendline("myvar")
|
||||
|
||||
child.expect_exact("2")
|
||||
child.expect("ipdb>")
|
||||
|
||||
child.close()
|
513
.venv/Lib/site-packages/IPython/core/tests/test_display.py
Normal file
513
.venv/Lib/site-packages/IPython/core/tests/test_display.py
Normal file
@ -0,0 +1,513 @@
|
||||
# Copyright (c) IPython Development Team.
|
||||
# Distributed under the terms of the Modified BSD License.
|
||||
|
||||
import json
|
||||
import os
|
||||
import warnings
|
||||
|
||||
from unittest import mock
|
||||
|
||||
import pytest
|
||||
|
||||
from IPython import display
|
||||
from IPython.core.getipython import get_ipython
|
||||
from IPython.utils.io import capture_output
|
||||
from IPython.utils.tempdir import NamedFileInTemporaryDirectory
|
||||
from IPython import paths as ipath
|
||||
from IPython.testing.tools import AssertNotPrints
|
||||
|
||||
import IPython.testing.decorators as dec
|
||||
|
||||
def test_image_size():
|
||||
"""Simple test for display.Image(args, width=x,height=y)"""
|
||||
thisurl = 'http://www.google.fr/images/srpr/logo3w.png'
|
||||
img = display.Image(url=thisurl, width=200, height=200)
|
||||
assert '<img src="%s" width="200" height="200"/>' % (thisurl) == img._repr_html_()
|
||||
img = display.Image(url=thisurl, metadata={'width':200, 'height':200})
|
||||
assert '<img src="%s" width="200" height="200"/>' % (thisurl) == img._repr_html_()
|
||||
img = display.Image(url=thisurl, width=200)
|
||||
assert '<img src="%s" width="200"/>' % (thisurl) == img._repr_html_()
|
||||
img = display.Image(url=thisurl)
|
||||
assert '<img src="%s"/>' % (thisurl) == img._repr_html_()
|
||||
img = display.Image(url=thisurl, unconfined=True)
|
||||
assert '<img src="%s" class="unconfined"/>' % (thisurl) == img._repr_html_()
|
||||
|
||||
|
||||
def test_image_mimes():
|
||||
fmt = get_ipython().display_formatter.format
|
||||
for format in display.Image._ACCEPTABLE_EMBEDDINGS:
|
||||
mime = display.Image._MIMETYPES[format]
|
||||
img = display.Image(b'garbage', format=format)
|
||||
data, metadata = fmt(img)
|
||||
assert sorted(data) == sorted([mime, "text/plain"])
|
||||
|
||||
|
||||
def test_geojson():
|
||||
|
||||
gj = display.GeoJSON(data={
|
||||
"type": "Feature",
|
||||
"geometry": {
|
||||
"type": "Point",
|
||||
"coordinates": [-81.327, 296.038]
|
||||
},
|
||||
"properties": {
|
||||
"name": "Inca City"
|
||||
}
|
||||
},
|
||||
url_template="http://s3-eu-west-1.amazonaws.com/whereonmars.cartodb.net/{basemap_id}/{z}/{x}/{y}.png",
|
||||
layer_options={
|
||||
"basemap_id": "celestia_mars-shaded-16k_global",
|
||||
"attribution": "Celestia/praesepe",
|
||||
"minZoom": 0,
|
||||
"maxZoom": 18,
|
||||
},
|
||||
)
|
||||
assert "<IPython.core.display.GeoJSON object>" == str(gj)
|
||||
|
||||
|
||||
def test_retina_png():
|
||||
here = os.path.dirname(__file__)
|
||||
img = display.Image(os.path.join(here, "2x2.png"), retina=True)
|
||||
assert img.height == 1
|
||||
assert img.width == 1
|
||||
data, md = img._repr_png_()
|
||||
assert md["width"] == 1
|
||||
assert md["height"] == 1
|
||||
|
||||
|
||||
def test_embed_svg_url():
|
||||
import gzip
|
||||
from io import BytesIO
|
||||
svg_data = b'<svg><circle x="0" y="0" r="1"/></svg>'
|
||||
url = 'http://test.com/circle.svg'
|
||||
|
||||
gzip_svg = BytesIO()
|
||||
with gzip.open(gzip_svg, 'wb') as fp:
|
||||
fp.write(svg_data)
|
||||
gzip_svg = gzip_svg.getvalue()
|
||||
|
||||
def mocked_urlopen(*args, **kwargs):
|
||||
class MockResponse:
|
||||
def __init__(self, svg):
|
||||
self._svg_data = svg
|
||||
self.headers = {'content-type': 'image/svg+xml'}
|
||||
|
||||
def read(self):
|
||||
return self._svg_data
|
||||
|
||||
if args[0] == url:
|
||||
return MockResponse(svg_data)
|
||||
elif args[0] == url + "z":
|
||||
ret = MockResponse(gzip_svg)
|
||||
ret.headers["content-encoding"] = "gzip"
|
||||
return ret
|
||||
return MockResponse(None)
|
||||
|
||||
with mock.patch('urllib.request.urlopen', side_effect=mocked_urlopen):
|
||||
svg = display.SVG(url=url)
|
||||
assert svg._repr_svg_().startswith("<svg") is True
|
||||
svg = display.SVG(url=url + "z")
|
||||
assert svg._repr_svg_().startswith("<svg") is True
|
||||
|
||||
|
||||
def test_retina_jpeg():
|
||||
here = os.path.dirname(__file__)
|
||||
img = display.Image(os.path.join(here, "2x2.jpg"), retina=True)
|
||||
assert img.height == 1
|
||||
assert img.width == 1
|
||||
data, md = img._repr_jpeg_()
|
||||
assert md["width"] == 1
|
||||
assert md["height"] == 1
|
||||
|
||||
|
||||
def test_base64image():
|
||||
display.Image("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEUAAACnej3aAAAAAWJLR0QAiAUdSAAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB94BCRQnOqNu0b4AAAAKSURBVAjXY2AAAAACAAHiIbwzAAAAAElFTkSuQmCC")
|
||||
|
||||
def test_image_filename_defaults():
|
||||
'''test format constraint, and validity of jpeg and png'''
|
||||
tpath = ipath.get_ipython_package_dir()
|
||||
pytest.raises(
|
||||
ValueError,
|
||||
display.Image,
|
||||
filename=os.path.join(tpath, "testing/tests/badformat.zip"),
|
||||
embed=True,
|
||||
)
|
||||
pytest.raises(ValueError, display.Image)
|
||||
pytest.raises(
|
||||
ValueError,
|
||||
display.Image,
|
||||
data="this is not an image",
|
||||
format="badformat",
|
||||
embed=True,
|
||||
)
|
||||
# check boths paths to allow packages to test at build and install time
|
||||
imgfile = os.path.join(tpath, 'core/tests/2x2.png')
|
||||
img = display.Image(filename=imgfile)
|
||||
assert "png" == img.format
|
||||
assert img._repr_png_() is not None
|
||||
img = display.Image(
|
||||
filename=os.path.join(tpath, "testing/tests/logo.jpg"), embed=False
|
||||
)
|
||||
assert "jpeg" == img.format
|
||||
assert img._repr_jpeg_() is None
|
||||
|
||||
def _get_inline_config():
|
||||
from matplotlib_inline.config import InlineBackend
|
||||
return InlineBackend.instance()
|
||||
|
||||
|
||||
@dec.skip_without("matplotlib")
|
||||
def test_set_matplotlib_close():
|
||||
cfg = _get_inline_config()
|
||||
cfg.close_figures = False
|
||||
with pytest.deprecated_call():
|
||||
display.set_matplotlib_close()
|
||||
assert cfg.close_figures
|
||||
with pytest.deprecated_call():
|
||||
display.set_matplotlib_close(False)
|
||||
assert not cfg.close_figures
|
||||
|
||||
_fmt_mime_map = {
|
||||
'png': 'image/png',
|
||||
'jpeg': 'image/jpeg',
|
||||
'pdf': 'application/pdf',
|
||||
'retina': 'image/png',
|
||||
'svg': 'image/svg+xml',
|
||||
}
|
||||
|
||||
@dec.skip_without('matplotlib')
|
||||
def test_set_matplotlib_formats():
|
||||
from matplotlib.figure import Figure
|
||||
formatters = get_ipython().display_formatter.formatters
|
||||
for formats in [
|
||||
('png',),
|
||||
('pdf', 'svg'),
|
||||
('jpeg', 'retina', 'png'),
|
||||
(),
|
||||
]:
|
||||
active_mimes = {_fmt_mime_map[fmt] for fmt in formats}
|
||||
with pytest.deprecated_call():
|
||||
display.set_matplotlib_formats(*formats)
|
||||
for mime, f in formatters.items():
|
||||
if mime in active_mimes:
|
||||
assert Figure in f
|
||||
else:
|
||||
assert Figure not in f
|
||||
|
||||
|
||||
@dec.skip_without("matplotlib")
|
||||
def test_set_matplotlib_formats_kwargs():
|
||||
from matplotlib.figure import Figure
|
||||
ip = get_ipython()
|
||||
cfg = _get_inline_config()
|
||||
cfg.print_figure_kwargs.update(dict(foo='bar'))
|
||||
kwargs = dict(dpi=150)
|
||||
with pytest.deprecated_call():
|
||||
display.set_matplotlib_formats("png", **kwargs)
|
||||
formatter = ip.display_formatter.formatters["image/png"]
|
||||
f = formatter.lookup_by_type(Figure)
|
||||
formatter_kwargs = f.keywords
|
||||
expected = kwargs
|
||||
expected["base64"] = True
|
||||
expected["fmt"] = "png"
|
||||
expected.update(cfg.print_figure_kwargs)
|
||||
assert formatter_kwargs == expected
|
||||
|
||||
def test_display_available():
|
||||
"""
|
||||
Test that display is available without import
|
||||
|
||||
We don't really care if it's in builtin or anything else, but it should
|
||||
always be available.
|
||||
"""
|
||||
ip = get_ipython()
|
||||
with AssertNotPrints('NameError'):
|
||||
ip.run_cell('display')
|
||||
try:
|
||||
ip.run_cell('del display')
|
||||
except NameError:
|
||||
pass # it's ok, it might be in builtins
|
||||
# even if deleted it should be back
|
||||
with AssertNotPrints('NameError'):
|
||||
ip.run_cell('display')
|
||||
|
||||
def test_textdisplayobj_pretty_repr():
|
||||
p = display.Pretty("This is a simple test")
|
||||
assert repr(p) == "<IPython.core.display.Pretty object>"
|
||||
assert p.data == "This is a simple test"
|
||||
|
||||
p._show_mem_addr = True
|
||||
assert repr(p) == object.__repr__(p)
|
||||
|
||||
|
||||
def test_displayobject_repr():
|
||||
h = display.HTML("<br />")
|
||||
assert repr(h) == "<IPython.core.display.HTML object>"
|
||||
h._show_mem_addr = True
|
||||
assert repr(h) == object.__repr__(h)
|
||||
h._show_mem_addr = False
|
||||
assert repr(h) == "<IPython.core.display.HTML object>"
|
||||
|
||||
j = display.Javascript("")
|
||||
assert repr(j) == "<IPython.core.display.Javascript object>"
|
||||
j._show_mem_addr = True
|
||||
assert repr(j) == object.__repr__(j)
|
||||
j._show_mem_addr = False
|
||||
assert repr(j) == "<IPython.core.display.Javascript object>"
|
||||
|
||||
@mock.patch('warnings.warn')
|
||||
def test_encourage_iframe_over_html(m_warn):
|
||||
display.HTML()
|
||||
m_warn.assert_not_called()
|
||||
|
||||
display.HTML('<br />')
|
||||
m_warn.assert_not_called()
|
||||
|
||||
display.HTML('<html><p>Lots of content here</p><iframe src="http://a.com"></iframe>')
|
||||
m_warn.assert_not_called()
|
||||
|
||||
display.HTML('<iframe src="http://a.com"></iframe>')
|
||||
m_warn.assert_called_with('Consider using IPython.display.IFrame instead')
|
||||
|
||||
m_warn.reset_mock()
|
||||
display.HTML('<IFRAME SRC="http://a.com"></IFRAME>')
|
||||
m_warn.assert_called_with('Consider using IPython.display.IFrame instead')
|
||||
|
||||
def test_progress():
|
||||
p = display.ProgressBar(10)
|
||||
assert "0/10" in repr(p)
|
||||
p.html_width = "100%"
|
||||
p.progress = 5
|
||||
assert (
|
||||
p._repr_html_() == "<progress style='width:100%' max='10' value='5'></progress>"
|
||||
)
|
||||
|
||||
|
||||
def test_progress_iter():
|
||||
with capture_output(display=False) as captured:
|
||||
for i in display.ProgressBar(5):
|
||||
out = captured.stdout
|
||||
assert "{0}/5".format(i) in out
|
||||
out = captured.stdout
|
||||
assert "5/5" in out
|
||||
|
||||
|
||||
def test_json():
|
||||
d = {'a': 5}
|
||||
lis = [d]
|
||||
metadata = [
|
||||
{'expanded': False, 'root': 'root'},
|
||||
{'expanded': True, 'root': 'root'},
|
||||
{'expanded': False, 'root': 'custom'},
|
||||
{'expanded': True, 'root': 'custom'},
|
||||
]
|
||||
json_objs = [
|
||||
display.JSON(d),
|
||||
display.JSON(d, expanded=True),
|
||||
display.JSON(d, root='custom'),
|
||||
display.JSON(d, expanded=True, root='custom'),
|
||||
]
|
||||
for j, md in zip(json_objs, metadata):
|
||||
assert j._repr_json_() == (d, md)
|
||||
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter("always")
|
||||
j = display.JSON(json.dumps(d))
|
||||
assert len(w) == 1
|
||||
assert j._repr_json_() == (d, metadata[0])
|
||||
|
||||
json_objs = [
|
||||
display.JSON(lis),
|
||||
display.JSON(lis, expanded=True),
|
||||
display.JSON(lis, root='custom'),
|
||||
display.JSON(lis, expanded=True, root='custom'),
|
||||
]
|
||||
for j, md in zip(json_objs, metadata):
|
||||
assert j._repr_json_() == (lis, md)
|
||||
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter("always")
|
||||
j = display.JSON(json.dumps(lis))
|
||||
assert len(w) == 1
|
||||
assert j._repr_json_() == (lis, metadata[0])
|
||||
|
||||
|
||||
def test_video_embedding():
|
||||
"""use a tempfile, with dummy-data, to ensure that video embedding doesn't crash"""
|
||||
v = display.Video("http://ignored")
|
||||
assert not v.embed
|
||||
html = v._repr_html_()
|
||||
assert 'src="data:' not in html
|
||||
assert 'src="http://ignored"' in html
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
v = display.Video(b'abc')
|
||||
|
||||
with NamedFileInTemporaryDirectory('test.mp4') as f:
|
||||
f.write(b'abc')
|
||||
f.close()
|
||||
|
||||
v = display.Video(f.name)
|
||||
assert not v.embed
|
||||
html = v._repr_html_()
|
||||
assert 'src="data:' not in html
|
||||
|
||||
v = display.Video(f.name, embed=True)
|
||||
html = v._repr_html_()
|
||||
assert 'src="data:video/mp4;base64,YWJj"' in html
|
||||
|
||||
v = display.Video(f.name, embed=True, mimetype='video/other')
|
||||
html = v._repr_html_()
|
||||
assert 'src="data:video/other;base64,YWJj"' in html
|
||||
|
||||
v = display.Video(b'abc', embed=True, mimetype='video/mp4')
|
||||
html = v._repr_html_()
|
||||
assert 'src="data:video/mp4;base64,YWJj"' in html
|
||||
|
||||
v = display.Video(u'YWJj', embed=True, mimetype='video/xyz')
|
||||
html = v._repr_html_()
|
||||
assert 'src="data:video/xyz;base64,YWJj"' in html
|
||||
|
||||
def test_html_metadata():
|
||||
s = "<h1>Test</h1>"
|
||||
h = display.HTML(s, metadata={"isolated": True})
|
||||
assert h._repr_html_() == (s, {"isolated": True})
|
||||
|
||||
|
||||
def test_display_id():
|
||||
ip = get_ipython()
|
||||
with mock.patch.object(ip.display_pub, 'publish') as pub:
|
||||
handle = display.display('x')
|
||||
assert handle is None
|
||||
handle = display.display('y', display_id='secret')
|
||||
assert isinstance(handle, display.DisplayHandle)
|
||||
handle2 = display.display('z', display_id=True)
|
||||
assert isinstance(handle2, display.DisplayHandle)
|
||||
assert handle.display_id != handle2.display_id
|
||||
|
||||
assert pub.call_count == 3
|
||||
args, kwargs = pub.call_args_list[0]
|
||||
assert args == ()
|
||||
assert kwargs == {
|
||||
'data': {
|
||||
'text/plain': repr('x')
|
||||
},
|
||||
'metadata': {},
|
||||
}
|
||||
args, kwargs = pub.call_args_list[1]
|
||||
assert args == ()
|
||||
assert kwargs == {
|
||||
'data': {
|
||||
'text/plain': repr('y')
|
||||
},
|
||||
'metadata': {},
|
||||
'transient': {
|
||||
'display_id': handle.display_id,
|
||||
},
|
||||
}
|
||||
args, kwargs = pub.call_args_list[2]
|
||||
assert args == ()
|
||||
assert kwargs == {
|
||||
'data': {
|
||||
'text/plain': repr('z')
|
||||
},
|
||||
'metadata': {},
|
||||
'transient': {
|
||||
'display_id': handle2.display_id,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def test_update_display():
|
||||
ip = get_ipython()
|
||||
with mock.patch.object(ip.display_pub, 'publish') as pub:
|
||||
with pytest.raises(TypeError):
|
||||
display.update_display('x')
|
||||
display.update_display('x', display_id='1')
|
||||
display.update_display('y', display_id='2')
|
||||
args, kwargs = pub.call_args_list[0]
|
||||
assert args == ()
|
||||
assert kwargs == {
|
||||
'data': {
|
||||
'text/plain': repr('x')
|
||||
},
|
||||
'metadata': {},
|
||||
'transient': {
|
||||
'display_id': '1',
|
||||
},
|
||||
'update': True,
|
||||
}
|
||||
args, kwargs = pub.call_args_list[1]
|
||||
assert args == ()
|
||||
assert kwargs == {
|
||||
'data': {
|
||||
'text/plain': repr('y')
|
||||
},
|
||||
'metadata': {},
|
||||
'transient': {
|
||||
'display_id': '2',
|
||||
},
|
||||
'update': True,
|
||||
}
|
||||
|
||||
|
||||
def test_display_handle():
|
||||
ip = get_ipython()
|
||||
handle = display.DisplayHandle()
|
||||
assert isinstance(handle.display_id, str)
|
||||
handle = display.DisplayHandle("my-id")
|
||||
assert handle.display_id == "my-id"
|
||||
with mock.patch.object(ip.display_pub, "publish") as pub:
|
||||
handle.display("x")
|
||||
handle.update("y")
|
||||
|
||||
args, kwargs = pub.call_args_list[0]
|
||||
assert args == ()
|
||||
assert kwargs == {
|
||||
'data': {
|
||||
'text/plain': repr('x')
|
||||
},
|
||||
'metadata': {},
|
||||
'transient': {
|
||||
'display_id': handle.display_id,
|
||||
}
|
||||
}
|
||||
args, kwargs = pub.call_args_list[1]
|
||||
assert args == ()
|
||||
assert kwargs == {
|
||||
'data': {
|
||||
'text/plain': repr('y')
|
||||
},
|
||||
'metadata': {},
|
||||
'transient': {
|
||||
'display_id': handle.display_id,
|
||||
},
|
||||
'update': True,
|
||||
}
|
||||
|
||||
|
||||
def test_image_alt_tag():
|
||||
"""Simple test for display.Image(args, alt=x,)"""
|
||||
thisurl = "http://example.com/image.png"
|
||||
img = display.Image(url=thisurl, alt="an image")
|
||||
assert '<img src="%s" alt="an image"/>' % (thisurl) == img._repr_html_()
|
||||
img = display.Image(url=thisurl, unconfined=True, alt="an image")
|
||||
assert (
|
||||
'<img src="%s" class="unconfined" alt="an image"/>' % (thisurl)
|
||||
== img._repr_html_()
|
||||
)
|
||||
img = display.Image(url=thisurl, alt='>"& <')
|
||||
assert '<img src="%s" alt=">"& <"/>' % (thisurl) == img._repr_html_()
|
||||
|
||||
img = display.Image(url=thisurl, metadata={"alt": "an image"})
|
||||
assert img.alt == "an image"
|
||||
here = os.path.dirname(__file__)
|
||||
img = display.Image(os.path.join(here, "2x2.png"), alt="an image")
|
||||
assert img.alt == "an image"
|
||||
_, md = img._repr_png_()
|
||||
assert md["alt"] == "an image"
|
||||
|
||||
|
||||
def test_image_bad_filename_raises_proper_exception():
|
||||
with pytest.raises(FileNotFoundError):
|
||||
display.Image("/this/file/does/not/exist/")._repr_png_()
|
112
.venv/Lib/site-packages/IPython/core/tests/test_displayhook.py
Normal file
112
.venv/Lib/site-packages/IPython/core/tests/test_displayhook.py
Normal file
@ -0,0 +1,112 @@
|
||||
import sys
|
||||
from IPython.testing.tools import AssertPrints, AssertNotPrints
|
||||
from IPython.core.displayhook import CapturingDisplayHook
|
||||
from IPython.utils.capture import CapturedIO
|
||||
|
||||
def test_output_displayed():
|
||||
"""Checking to make sure that output is displayed"""
|
||||
|
||||
with AssertPrints('2'):
|
||||
ip.run_cell('1+1', store_history=True)
|
||||
|
||||
with AssertPrints('2'):
|
||||
ip.run_cell('1+1 # comment with a semicolon;', store_history=True)
|
||||
|
||||
with AssertPrints('2'):
|
||||
ip.run_cell('1+1\n#commented_out_function();', store_history=True)
|
||||
|
||||
|
||||
def test_output_quiet():
|
||||
"""Checking to make sure that output is quiet"""
|
||||
|
||||
with AssertNotPrints('2'):
|
||||
ip.run_cell('1+1;', store_history=True)
|
||||
|
||||
with AssertNotPrints('2'):
|
||||
ip.run_cell('1+1; # comment with a semicolon', store_history=True)
|
||||
|
||||
with AssertNotPrints('2'):
|
||||
ip.run_cell('1+1;\n#commented_out_function()', store_history=True)
|
||||
|
||||
def test_underscore_no_overrite_user():
|
||||
ip.run_cell('_ = 42', store_history=True)
|
||||
ip.run_cell('1+1', store_history=True)
|
||||
|
||||
with AssertPrints('42'):
|
||||
ip.run_cell('print(_)', store_history=True)
|
||||
|
||||
ip.run_cell('del _', store_history=True)
|
||||
ip.run_cell('6+6', store_history=True)
|
||||
with AssertPrints('12'):
|
||||
ip.run_cell('_', store_history=True)
|
||||
|
||||
|
||||
def test_underscore_no_overrite_builtins():
|
||||
ip.run_cell("import gettext ; gettext.install('foo')", store_history=True)
|
||||
ip.run_cell('3+3', store_history=True)
|
||||
|
||||
with AssertPrints('gettext'):
|
||||
ip.run_cell('print(_)', store_history=True)
|
||||
|
||||
ip.run_cell('_ = "userset"', store_history=True)
|
||||
|
||||
with AssertPrints('userset'):
|
||||
ip.run_cell('print(_)', store_history=True)
|
||||
ip.run_cell('import builtins; del builtins._')
|
||||
|
||||
|
||||
def test_interactivehooks_ast_modes():
|
||||
"""
|
||||
Test that ast nodes can be triggered with different modes
|
||||
"""
|
||||
saved_mode = ip.ast_node_interactivity
|
||||
ip.ast_node_interactivity = 'last_expr_or_assign'
|
||||
|
||||
try:
|
||||
with AssertPrints('2'):
|
||||
ip.run_cell('a = 1+1', store_history=True)
|
||||
|
||||
with AssertPrints('9'):
|
||||
ip.run_cell('b = 1+8 # comment with a semicolon;', store_history=False)
|
||||
|
||||
with AssertPrints('7'):
|
||||
ip.run_cell('c = 1+6\n#commented_out_function();', store_history=True)
|
||||
|
||||
ip.run_cell('d = 11', store_history=True)
|
||||
with AssertPrints('12'):
|
||||
ip.run_cell('d += 1', store_history=True)
|
||||
|
||||
with AssertNotPrints('42'):
|
||||
ip.run_cell('(u,v) = (41+1, 43-1)')
|
||||
|
||||
finally:
|
||||
ip.ast_node_interactivity = saved_mode
|
||||
|
||||
def test_interactivehooks_ast_modes_semi_suppress():
|
||||
"""
|
||||
Test that ast nodes can be triggered with different modes and suppressed
|
||||
by semicolon
|
||||
"""
|
||||
saved_mode = ip.ast_node_interactivity
|
||||
ip.ast_node_interactivity = 'last_expr_or_assign'
|
||||
|
||||
try:
|
||||
with AssertNotPrints('2'):
|
||||
ip.run_cell('x = 1+1;', store_history=True)
|
||||
|
||||
with AssertNotPrints('7'):
|
||||
ip.run_cell('y = 1+6; # comment with a semicolon', store_history=True)
|
||||
|
||||
with AssertNotPrints('9'):
|
||||
ip.run_cell('z = 1+8;\n#commented_out_function()', store_history=True)
|
||||
|
||||
finally:
|
||||
ip.ast_node_interactivity = saved_mode
|
||||
|
||||
def test_capture_display_hook_format():
|
||||
"""Tests that the capture display hook conforms to the CapturedIO output format"""
|
||||
hook = CapturingDisplayHook(ip)
|
||||
hook({"foo": "bar"})
|
||||
captured = CapturedIO(sys.stdout, sys.stderr, hook.outputs)
|
||||
# Should not raise with RichOutput transformation error
|
||||
captured.outputs
|
91
.venv/Lib/site-packages/IPython/core/tests/test_events.py
Normal file
91
.venv/Lib/site-packages/IPython/core/tests/test_events.py
Normal file
@ -0,0 +1,91 @@
|
||||
import unittest
|
||||
from unittest.mock import Mock
|
||||
|
||||
from IPython.core import events
|
||||
import IPython.testing.tools as tt
|
||||
|
||||
|
||||
@events._define_event
|
||||
def ping_received():
|
||||
pass
|
||||
|
||||
|
||||
@events._define_event
|
||||
def event_with_argument(argument):
|
||||
pass
|
||||
|
||||
|
||||
class CallbackTests(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.em = events.EventManager(get_ipython(),
|
||||
{'ping_received': ping_received,
|
||||
'event_with_argument': event_with_argument})
|
||||
|
||||
def test_register_unregister(self):
|
||||
cb = Mock()
|
||||
|
||||
self.em.register('ping_received', cb)
|
||||
self.em.trigger('ping_received')
|
||||
self.assertEqual(cb.call_count, 1)
|
||||
|
||||
self.em.unregister('ping_received', cb)
|
||||
self.em.trigger('ping_received')
|
||||
self.assertEqual(cb.call_count, 1)
|
||||
|
||||
def test_bare_function_missed_unregister(self):
|
||||
def cb1():
|
||||
...
|
||||
|
||||
def cb2():
|
||||
...
|
||||
|
||||
self.em.register("ping_received", cb1)
|
||||
self.assertRaises(ValueError, self.em.unregister, "ping_received", cb2)
|
||||
self.em.unregister("ping_received", cb1)
|
||||
|
||||
def test_cb_error(self):
|
||||
cb = Mock(side_effect=ValueError)
|
||||
self.em.register('ping_received', cb)
|
||||
with tt.AssertPrints("Error in callback"):
|
||||
self.em.trigger('ping_received')
|
||||
|
||||
def test_cb_keyboard_interrupt(self):
|
||||
cb = Mock(side_effect=KeyboardInterrupt)
|
||||
self.em.register('ping_received', cb)
|
||||
with tt.AssertPrints("Error in callback"):
|
||||
self.em.trigger('ping_received')
|
||||
|
||||
def test_unregister_during_callback(self):
|
||||
invoked = [False] * 3
|
||||
|
||||
def func1(*_):
|
||||
invoked[0] = True
|
||||
self.em.unregister('ping_received', func1)
|
||||
self.em.register('ping_received', func3)
|
||||
|
||||
def func2(*_):
|
||||
invoked[1] = True
|
||||
self.em.unregister('ping_received', func2)
|
||||
|
||||
def func3(*_):
|
||||
invoked[2] = True
|
||||
|
||||
self.em.register('ping_received', func1)
|
||||
self.em.register('ping_received', func2)
|
||||
|
||||
self.em.trigger('ping_received')
|
||||
self.assertEqual([True, True, False], invoked)
|
||||
self.assertEqual([func3], self.em.callbacks['ping_received'])
|
||||
|
||||
def test_ignore_event_arguments_if_no_argument_required(self):
|
||||
call_count = [0]
|
||||
def event_with_no_argument():
|
||||
call_count[0] += 1
|
||||
|
||||
self.em.register('event_with_argument', event_with_no_argument)
|
||||
self.em.trigger('event_with_argument', 'the argument')
|
||||
self.assertEqual(call_count[0], 1)
|
||||
|
||||
self.em.unregister('event_with_argument', event_with_no_argument)
|
||||
self.em.trigger('ping_received')
|
||||
self.assertEqual(call_count[0], 1)
|
95
.venv/Lib/site-packages/IPython/core/tests/test_extension.py
Normal file
95
.venv/Lib/site-packages/IPython/core/tests/test_extension.py
Normal file
@ -0,0 +1,95 @@
|
||||
import os.path
|
||||
|
||||
from tempfile import TemporaryDirectory
|
||||
|
||||
import IPython.testing.tools as tt
|
||||
from IPython.utils.syspathcontext import prepended_to_syspath
|
||||
|
||||
ext1_content = """
|
||||
def load_ipython_extension(ip):
|
||||
print("Running ext1 load")
|
||||
|
||||
def unload_ipython_extension(ip):
|
||||
print("Running ext1 unload")
|
||||
"""
|
||||
|
||||
ext2_content = """
|
||||
def load_ipython_extension(ip):
|
||||
print("Running ext2 load")
|
||||
"""
|
||||
|
||||
ext3_content = """
|
||||
def load_ipython_extension(ip):
|
||||
ip2 = get_ipython()
|
||||
print(ip is ip2)
|
||||
"""
|
||||
|
||||
def test_extension_loading():
|
||||
em = get_ipython().extension_manager
|
||||
with TemporaryDirectory() as td:
|
||||
ext1 = os.path.join(td, "ext1.py")
|
||||
with open(ext1, "w", encoding="utf-8") as f:
|
||||
f.write(ext1_content)
|
||||
|
||||
ext2 = os.path.join(td, "ext2.py")
|
||||
with open(ext2, "w", encoding="utf-8") as f:
|
||||
f.write(ext2_content)
|
||||
|
||||
with prepended_to_syspath(td):
|
||||
assert 'ext1' not in em.loaded
|
||||
assert 'ext2' not in em.loaded
|
||||
|
||||
# Load extension
|
||||
with tt.AssertPrints("Running ext1 load"):
|
||||
assert em.load_extension('ext1') is None
|
||||
assert 'ext1' in em.loaded
|
||||
|
||||
# Should refuse to load it again
|
||||
with tt.AssertNotPrints("Running ext1 load"):
|
||||
assert em.load_extension('ext1') == 'already loaded'
|
||||
|
||||
# Reload
|
||||
with tt.AssertPrints("Running ext1 unload"):
|
||||
with tt.AssertPrints("Running ext1 load", suppress=False):
|
||||
em.reload_extension('ext1')
|
||||
|
||||
# Unload
|
||||
with tt.AssertPrints("Running ext1 unload"):
|
||||
assert em.unload_extension('ext1') is None
|
||||
|
||||
# Can't unload again
|
||||
with tt.AssertNotPrints("Running ext1 unload"):
|
||||
assert em.unload_extension('ext1') == 'not loaded'
|
||||
assert em.unload_extension('ext2') == 'not loaded'
|
||||
|
||||
# Load extension 2
|
||||
with tt.AssertPrints("Running ext2 load"):
|
||||
assert em.load_extension('ext2') is None
|
||||
|
||||
# Can't unload this
|
||||
assert em.unload_extension('ext2') == 'no unload function'
|
||||
|
||||
# But can reload it
|
||||
with tt.AssertPrints("Running ext2 load"):
|
||||
em.reload_extension('ext2')
|
||||
|
||||
|
||||
def test_extension_builtins():
|
||||
em = get_ipython().extension_manager
|
||||
with TemporaryDirectory() as td:
|
||||
ext3 = os.path.join(td, "ext3.py")
|
||||
with open(ext3, "w", encoding="utf-8") as f:
|
||||
f.write(ext3_content)
|
||||
|
||||
assert 'ext3' not in em.loaded
|
||||
|
||||
with prepended_to_syspath(td):
|
||||
# Load extension
|
||||
with tt.AssertPrints("True"):
|
||||
assert em.load_extension('ext3') is None
|
||||
assert 'ext3' in em.loaded
|
||||
|
||||
|
||||
def test_non_extension():
|
||||
em = get_ipython().extension_manager
|
||||
assert em.load_extension("sys") == "no load function"
|
532
.venv/Lib/site-packages/IPython/core/tests/test_formatters.py
Normal file
532
.venv/Lib/site-packages/IPython/core/tests/test_formatters.py
Normal file
@ -0,0 +1,532 @@
|
||||
"""Tests for the Formatters."""
|
||||
|
||||
import warnings
|
||||
from math import pi
|
||||
|
||||
try:
|
||||
import numpy
|
||||
except:
|
||||
numpy = None
|
||||
import pytest
|
||||
|
||||
from IPython import get_ipython
|
||||
from traitlets.config import Config
|
||||
from IPython.core.formatters import (
|
||||
PlainTextFormatter, HTMLFormatter, PDFFormatter, _mod_name_key,
|
||||
DisplayFormatter, JSONFormatter,
|
||||
)
|
||||
from IPython.utils.io import capture_output
|
||||
|
||||
class A(object):
|
||||
def __repr__(self):
|
||||
return 'A()'
|
||||
|
||||
class B(A):
|
||||
def __repr__(self):
|
||||
return 'B()'
|
||||
|
||||
class C:
|
||||
pass
|
||||
|
||||
class BadRepr(object):
|
||||
def __repr__(self):
|
||||
raise ValueError("bad repr")
|
||||
|
||||
class BadPretty(object):
|
||||
_repr_pretty_ = None
|
||||
|
||||
class GoodPretty(object):
|
||||
def _repr_pretty_(self, pp, cycle):
|
||||
pp.text('foo')
|
||||
|
||||
def __repr__(self):
|
||||
return 'GoodPretty()'
|
||||
|
||||
def foo_printer(obj, pp, cycle):
|
||||
pp.text('foo')
|
||||
|
||||
def test_pretty():
|
||||
f = PlainTextFormatter()
|
||||
f.for_type(A, foo_printer)
|
||||
assert f(A()) == "foo"
|
||||
assert f(B()) == "B()"
|
||||
assert f(GoodPretty()) == "foo"
|
||||
# Just don't raise an exception for the following:
|
||||
f(BadPretty())
|
||||
|
||||
f.pprint = False
|
||||
assert f(A()) == "A()"
|
||||
assert f(B()) == "B()"
|
||||
assert f(GoodPretty()) == "GoodPretty()"
|
||||
|
||||
|
||||
def test_deferred():
|
||||
f = PlainTextFormatter()
|
||||
|
||||
def test_precision():
|
||||
"""test various values for float_precision."""
|
||||
f = PlainTextFormatter()
|
||||
assert f(pi) == repr(pi)
|
||||
f.float_precision = 0
|
||||
if numpy:
|
||||
po = numpy.get_printoptions()
|
||||
assert po["precision"] == 0
|
||||
assert f(pi) == "3"
|
||||
f.float_precision = 2
|
||||
if numpy:
|
||||
po = numpy.get_printoptions()
|
||||
assert po["precision"] == 2
|
||||
assert f(pi) == "3.14"
|
||||
f.float_precision = "%g"
|
||||
if numpy:
|
||||
po = numpy.get_printoptions()
|
||||
assert po["precision"] == 2
|
||||
assert f(pi) == "3.14159"
|
||||
f.float_precision = "%e"
|
||||
assert f(pi) == "3.141593e+00"
|
||||
f.float_precision = ""
|
||||
if numpy:
|
||||
po = numpy.get_printoptions()
|
||||
assert po["precision"] == 8
|
||||
assert f(pi) == repr(pi)
|
||||
|
||||
|
||||
def test_bad_precision():
|
||||
"""test various invalid values for float_precision."""
|
||||
f = PlainTextFormatter()
|
||||
def set_fp(p):
|
||||
f.float_precision = p
|
||||
|
||||
pytest.raises(ValueError, set_fp, "%")
|
||||
pytest.raises(ValueError, set_fp, "%.3f%i")
|
||||
pytest.raises(ValueError, set_fp, "foo")
|
||||
pytest.raises(ValueError, set_fp, -1)
|
||||
|
||||
def test_for_type():
|
||||
f = PlainTextFormatter()
|
||||
|
||||
# initial return, None
|
||||
assert f.for_type(C, foo_printer) is None
|
||||
# no func queries
|
||||
assert f.for_type(C) is foo_printer
|
||||
# shouldn't change anything
|
||||
assert f.for_type(C) is foo_printer
|
||||
# None should do the same
|
||||
assert f.for_type(C, None) is foo_printer
|
||||
assert f.for_type(C, None) is foo_printer
|
||||
|
||||
def test_for_type_string():
|
||||
f = PlainTextFormatter()
|
||||
|
||||
type_str = '%s.%s' % (C.__module__, 'C')
|
||||
|
||||
# initial return, None
|
||||
assert f.for_type(type_str, foo_printer) is None
|
||||
# no func queries
|
||||
assert f.for_type(type_str) is foo_printer
|
||||
assert _mod_name_key(C) in f.deferred_printers
|
||||
assert f.for_type(C) is foo_printer
|
||||
assert _mod_name_key(C) not in f.deferred_printers
|
||||
assert C in f.type_printers
|
||||
|
||||
def test_for_type_by_name():
|
||||
f = PlainTextFormatter()
|
||||
|
||||
mod = C.__module__
|
||||
|
||||
# initial return, None
|
||||
assert f.for_type_by_name(mod, "C", foo_printer) is None
|
||||
# no func queries
|
||||
assert f.for_type_by_name(mod, "C") is foo_printer
|
||||
# shouldn't change anything
|
||||
assert f.for_type_by_name(mod, "C") is foo_printer
|
||||
# None should do the same
|
||||
assert f.for_type_by_name(mod, "C", None) is foo_printer
|
||||
assert f.for_type_by_name(mod, "C", None) is foo_printer
|
||||
|
||||
|
||||
def test_lookup():
|
||||
f = PlainTextFormatter()
|
||||
|
||||
f.for_type(C, foo_printer)
|
||||
assert f.lookup(C()) is foo_printer
|
||||
with pytest.raises(KeyError):
|
||||
f.lookup(A())
|
||||
|
||||
def test_lookup_string():
|
||||
f = PlainTextFormatter()
|
||||
type_str = '%s.%s' % (C.__module__, 'C')
|
||||
|
||||
f.for_type(type_str, foo_printer)
|
||||
assert f.lookup(C()) is foo_printer
|
||||
# should move from deferred to imported dict
|
||||
assert _mod_name_key(C) not in f.deferred_printers
|
||||
assert C in f.type_printers
|
||||
|
||||
def test_lookup_by_type():
|
||||
f = PlainTextFormatter()
|
||||
f.for_type(C, foo_printer)
|
||||
assert f.lookup_by_type(C) is foo_printer
|
||||
with pytest.raises(KeyError):
|
||||
f.lookup_by_type(A)
|
||||
|
||||
def test_lookup_by_type_string():
|
||||
f = PlainTextFormatter()
|
||||
type_str = '%s.%s' % (C.__module__, 'C')
|
||||
f.for_type(type_str, foo_printer)
|
||||
|
||||
# verify insertion
|
||||
assert _mod_name_key(C) in f.deferred_printers
|
||||
assert C not in f.type_printers
|
||||
|
||||
assert f.lookup_by_type(type_str) is foo_printer
|
||||
# lookup by string doesn't cause import
|
||||
assert _mod_name_key(C) in f.deferred_printers
|
||||
assert C not in f.type_printers
|
||||
|
||||
assert f.lookup_by_type(C) is foo_printer
|
||||
# should move from deferred to imported dict
|
||||
assert _mod_name_key(C) not in f.deferred_printers
|
||||
assert C in f.type_printers
|
||||
|
||||
def test_in_formatter():
|
||||
f = PlainTextFormatter()
|
||||
f.for_type(C, foo_printer)
|
||||
type_str = '%s.%s' % (C.__module__, 'C')
|
||||
assert C in f
|
||||
assert type_str in f
|
||||
|
||||
def test_string_in_formatter():
|
||||
f = PlainTextFormatter()
|
||||
type_str = '%s.%s' % (C.__module__, 'C')
|
||||
f.for_type(type_str, foo_printer)
|
||||
assert type_str in f
|
||||
assert C in f
|
||||
|
||||
def test_pop():
|
||||
f = PlainTextFormatter()
|
||||
f.for_type(C, foo_printer)
|
||||
assert f.lookup_by_type(C) is foo_printer
|
||||
assert f.pop(C, None) is foo_printer
|
||||
f.for_type(C, foo_printer)
|
||||
assert f.pop(C) is foo_printer
|
||||
with pytest.raises(KeyError):
|
||||
f.lookup_by_type(C)
|
||||
with pytest.raises(KeyError):
|
||||
f.pop(C)
|
||||
with pytest.raises(KeyError):
|
||||
f.pop(A)
|
||||
assert f.pop(A, None) is None
|
||||
|
||||
def test_pop_string():
|
||||
f = PlainTextFormatter()
|
||||
type_str = '%s.%s' % (C.__module__, 'C')
|
||||
|
||||
with pytest.raises(KeyError):
|
||||
f.pop(type_str)
|
||||
|
||||
f.for_type(type_str, foo_printer)
|
||||
f.pop(type_str)
|
||||
with pytest.raises(KeyError):
|
||||
f.lookup_by_type(C)
|
||||
with pytest.raises(KeyError):
|
||||
f.pop(type_str)
|
||||
|
||||
f.for_type(C, foo_printer)
|
||||
assert f.pop(type_str, None) is foo_printer
|
||||
with pytest.raises(KeyError):
|
||||
f.lookup_by_type(C)
|
||||
with pytest.raises(KeyError):
|
||||
f.pop(type_str)
|
||||
assert f.pop(type_str, None) is None
|
||||
|
||||
|
||||
def test_error_method():
|
||||
f = HTMLFormatter()
|
||||
class BadHTML(object):
|
||||
def _repr_html_(self):
|
||||
raise ValueError("Bad HTML")
|
||||
bad = BadHTML()
|
||||
with capture_output() as captured:
|
||||
result = f(bad)
|
||||
assert result is None
|
||||
assert "Traceback" in captured.stdout
|
||||
assert "Bad HTML" in captured.stdout
|
||||
assert "_repr_html_" in captured.stdout
|
||||
|
||||
def test_nowarn_notimplemented():
|
||||
f = HTMLFormatter()
|
||||
class HTMLNotImplemented(object):
|
||||
def _repr_html_(self):
|
||||
raise NotImplementedError
|
||||
h = HTMLNotImplemented()
|
||||
with capture_output() as captured:
|
||||
result = f(h)
|
||||
assert result is None
|
||||
assert "" == captured.stderr
|
||||
assert "" == captured.stdout
|
||||
|
||||
|
||||
def test_warn_error_for_type():
|
||||
f = HTMLFormatter()
|
||||
f.for_type(int, lambda i: name_error)
|
||||
with capture_output() as captured:
|
||||
result = f(5)
|
||||
assert result is None
|
||||
assert "Traceback" in captured.stdout
|
||||
assert "NameError" in captured.stdout
|
||||
assert "name_error" in captured.stdout
|
||||
|
||||
def test_error_pretty_method():
|
||||
f = PlainTextFormatter()
|
||||
class BadPretty(object):
|
||||
def _repr_pretty_(self):
|
||||
return "hello"
|
||||
bad = BadPretty()
|
||||
with capture_output() as captured:
|
||||
result = f(bad)
|
||||
assert result is None
|
||||
assert "Traceback" in captured.stdout
|
||||
assert "_repr_pretty_" in captured.stdout
|
||||
assert "given" in captured.stdout
|
||||
assert "argument" in captured.stdout
|
||||
|
||||
|
||||
def test_bad_repr_traceback():
|
||||
f = PlainTextFormatter()
|
||||
bad = BadRepr()
|
||||
with capture_output() as captured:
|
||||
result = f(bad)
|
||||
# catches error, returns None
|
||||
assert result is None
|
||||
assert "Traceback" in captured.stdout
|
||||
assert "__repr__" in captured.stdout
|
||||
assert "ValueError" in captured.stdout
|
||||
|
||||
|
||||
class MakePDF(object):
|
||||
def _repr_pdf_(self):
|
||||
return 'PDF'
|
||||
|
||||
def test_pdf_formatter():
|
||||
pdf = MakePDF()
|
||||
f = PDFFormatter()
|
||||
assert f(pdf) == "PDF"
|
||||
|
||||
|
||||
def test_print_method_bound():
|
||||
f = HTMLFormatter()
|
||||
class MyHTML(object):
|
||||
def _repr_html_(self):
|
||||
return "hello"
|
||||
with capture_output() as captured:
|
||||
result = f(MyHTML)
|
||||
assert result is None
|
||||
assert "FormatterWarning" not in captured.stderr
|
||||
|
||||
with capture_output() as captured:
|
||||
result = f(MyHTML())
|
||||
assert result == "hello"
|
||||
assert captured.stderr == ""
|
||||
|
||||
|
||||
def test_print_method_weird():
|
||||
|
||||
class TextMagicHat(object):
|
||||
def __getattr__(self, key):
|
||||
return key
|
||||
|
||||
f = HTMLFormatter()
|
||||
|
||||
text_hat = TextMagicHat()
|
||||
assert text_hat._repr_html_ == "_repr_html_"
|
||||
with capture_output() as captured:
|
||||
result = f(text_hat)
|
||||
|
||||
assert result is None
|
||||
assert "FormatterWarning" not in captured.stderr
|
||||
|
||||
class CallableMagicHat(object):
|
||||
def __getattr__(self, key):
|
||||
return lambda : key
|
||||
|
||||
call_hat = CallableMagicHat()
|
||||
with capture_output() as captured:
|
||||
result = f(call_hat)
|
||||
|
||||
assert result is None
|
||||
|
||||
class BadReprArgs(object):
|
||||
def _repr_html_(self, extra, args):
|
||||
return "html"
|
||||
|
||||
bad = BadReprArgs()
|
||||
with capture_output() as captured:
|
||||
result = f(bad)
|
||||
|
||||
assert result is None
|
||||
assert "FormatterWarning" not in captured.stderr
|
||||
|
||||
|
||||
def test_format_config():
|
||||
"""config objects don't pretend to support fancy reprs with lazy attrs"""
|
||||
f = HTMLFormatter()
|
||||
cfg = Config()
|
||||
with capture_output() as captured:
|
||||
result = f(cfg)
|
||||
assert result is None
|
||||
assert captured.stderr == ""
|
||||
|
||||
with capture_output() as captured:
|
||||
result = f(Config)
|
||||
assert result is None
|
||||
assert captured.stderr == ""
|
||||
|
||||
|
||||
def test_pretty_max_seq_length():
|
||||
f = PlainTextFormatter(max_seq_length=1)
|
||||
lis = list(range(3))
|
||||
text = f(lis)
|
||||
assert text == "[0, ...]"
|
||||
f.max_seq_length = 0
|
||||
text = f(lis)
|
||||
assert text == "[0, 1, 2]"
|
||||
text = f(list(range(1024)))
|
||||
lines = text.splitlines()
|
||||
assert len(lines) == 1024
|
||||
|
||||
|
||||
def test_ipython_display_formatter():
|
||||
"""Objects with _ipython_display_ defined bypass other formatters"""
|
||||
f = get_ipython().display_formatter
|
||||
catcher = []
|
||||
class SelfDisplaying(object):
|
||||
def _ipython_display_(self):
|
||||
catcher.append(self)
|
||||
|
||||
class NotSelfDisplaying(object):
|
||||
def __repr__(self):
|
||||
return "NotSelfDisplaying"
|
||||
|
||||
def _ipython_display_(self):
|
||||
raise NotImplementedError
|
||||
|
||||
save_enabled = f.ipython_display_formatter.enabled
|
||||
f.ipython_display_formatter.enabled = True
|
||||
|
||||
yes = SelfDisplaying()
|
||||
no = NotSelfDisplaying()
|
||||
|
||||
d, md = f.format(no)
|
||||
assert d == {"text/plain": repr(no)}
|
||||
assert md == {}
|
||||
assert catcher == []
|
||||
|
||||
d, md = f.format(yes)
|
||||
assert d == {}
|
||||
assert md == {}
|
||||
assert catcher == [yes]
|
||||
|
||||
f.ipython_display_formatter.enabled = save_enabled
|
||||
|
||||
|
||||
def test_repr_mime():
|
||||
class HasReprMime(object):
|
||||
def _repr_mimebundle_(self, include=None, exclude=None):
|
||||
return {
|
||||
'application/json+test.v2': {
|
||||
'x': 'y'
|
||||
},
|
||||
'plain/text' : '<HasReprMime>',
|
||||
'image/png' : 'i-overwrite'
|
||||
}
|
||||
|
||||
def _repr_png_(self):
|
||||
return 'should-be-overwritten'
|
||||
def _repr_html_(self):
|
||||
return '<b>hi!</b>'
|
||||
|
||||
f = get_ipython().display_formatter
|
||||
html_f = f.formatters['text/html']
|
||||
save_enabled = html_f.enabled
|
||||
html_f.enabled = True
|
||||
obj = HasReprMime()
|
||||
d, md = f.format(obj)
|
||||
html_f.enabled = save_enabled
|
||||
|
||||
assert sorted(d) == [
|
||||
"application/json+test.v2",
|
||||
"image/png",
|
||||
"plain/text",
|
||||
"text/html",
|
||||
"text/plain",
|
||||
]
|
||||
assert md == {}
|
||||
|
||||
d, md = f.format(obj, include={"image/png"})
|
||||
assert list(d.keys()) == [
|
||||
"image/png"
|
||||
], "Include should filter out even things from repr_mimebundle"
|
||||
|
||||
assert d["image/png"] == "i-overwrite", "_repr_mimebundle_ take precedence"
|
||||
|
||||
|
||||
def test_pass_correct_include_exclude():
|
||||
class Tester(object):
|
||||
|
||||
def __init__(self, include=None, exclude=None):
|
||||
self.include = include
|
||||
self.exclude = exclude
|
||||
|
||||
def _repr_mimebundle_(self, include, exclude, **kwargs):
|
||||
if include and (include != self.include):
|
||||
raise ValueError('include got modified: display() may be broken.')
|
||||
if exclude and (exclude != self.exclude):
|
||||
raise ValueError('exclude got modified: display() may be broken.')
|
||||
|
||||
return None
|
||||
|
||||
include = {'a', 'b', 'c'}
|
||||
exclude = {'c', 'e' , 'f'}
|
||||
|
||||
f = get_ipython().display_formatter
|
||||
f.format(Tester(include=include, exclude=exclude), include=include, exclude=exclude)
|
||||
f.format(Tester(exclude=exclude), exclude=exclude)
|
||||
f.format(Tester(include=include), include=include)
|
||||
|
||||
|
||||
def test_repr_mime_meta():
|
||||
class HasReprMimeMeta(object):
|
||||
def _repr_mimebundle_(self, include=None, exclude=None):
|
||||
data = {
|
||||
'image/png': 'base64-image-data',
|
||||
}
|
||||
metadata = {
|
||||
'image/png': {
|
||||
'width': 5,
|
||||
'height': 10,
|
||||
}
|
||||
}
|
||||
return (data, metadata)
|
||||
|
||||
f = get_ipython().display_formatter
|
||||
obj = HasReprMimeMeta()
|
||||
d, md = f.format(obj)
|
||||
assert sorted(d) == ["image/png", "text/plain"]
|
||||
assert md == {
|
||||
"image/png": {
|
||||
"width": 5,
|
||||
"height": 10,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def test_repr_mime_failure():
|
||||
class BadReprMime(object):
|
||||
def _repr_mimebundle_(self, include=None, exclude=None):
|
||||
raise RuntimeError
|
||||
|
||||
f = get_ipython().display_formatter
|
||||
obj = BadReprMime()
|
||||
d, md = f.format(obj)
|
||||
assert "text/plain" in d
|
97
.venv/Lib/site-packages/IPython/core/tests/test_handlers.py
Normal file
97
.venv/Lib/site-packages/IPython/core/tests/test_handlers.py
Normal file
@ -0,0 +1,97 @@
|
||||
"""Tests for input handlers.
|
||||
"""
|
||||
#-----------------------------------------------------------------------------
|
||||
# Module imports
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
# our own packages
|
||||
from IPython.core import autocall
|
||||
from IPython.testing import tools as tt
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Globals
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
# Get the public instance of IPython
|
||||
|
||||
failures = []
|
||||
num_tests = 0
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Test functions
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
class CallableIndexable(object):
|
||||
def __getitem__(self, idx): return True
|
||||
def __call__(self, *args, **kws): return True
|
||||
|
||||
|
||||
class Autocallable(autocall.IPyAutocall):
|
||||
def __call__(self):
|
||||
return "called"
|
||||
|
||||
|
||||
def run(tests):
|
||||
"""Loop through a list of (pre, post) inputs, where pre is the string
|
||||
handed to ipython, and post is how that string looks after it's been
|
||||
transformed (i.e. ipython's notion of _i)"""
|
||||
tt.check_pairs(ip.prefilter_manager.prefilter_lines, tests)
|
||||
|
||||
|
||||
def test_handlers():
|
||||
call_idx = CallableIndexable()
|
||||
ip.user_ns['call_idx'] = call_idx
|
||||
|
||||
# For many of the below, we're also checking that leading whitespace
|
||||
# turns off the esc char, which it should unless there is a continuation
|
||||
# line.
|
||||
run(
|
||||
[('"no change"', '"no change"'), # normal
|
||||
(u"lsmagic", "get_ipython().run_line_magic('lsmagic', '')"), # magic
|
||||
#("a = b # PYTHON-MODE", '_i'), # emacs -- avoids _in cache
|
||||
])
|
||||
|
||||
# Objects which are instances of IPyAutocall are *always* autocalled
|
||||
autocallable = Autocallable()
|
||||
ip.user_ns['autocallable'] = autocallable
|
||||
|
||||
# auto
|
||||
ip.run_line_magic("autocall", "0")
|
||||
# Only explicit escapes or instances of IPyAutocallable should get
|
||||
# expanded
|
||||
run(
|
||||
[
|
||||
('len "abc"', 'len "abc"'),
|
||||
("autocallable", "autocallable()"),
|
||||
# Don't add extra brackets (gh-1117)
|
||||
("autocallable()", "autocallable()"),
|
||||
]
|
||||
)
|
||||
ip.run_line_magic("autocall", "1")
|
||||
run(
|
||||
[
|
||||
('len "abc"', 'len("abc")'),
|
||||
('len "abc";', 'len("abc");'), # ; is special -- moves out of parens
|
||||
# Autocall is turned off if first arg is [] and the object
|
||||
# is both callable and indexable. Like so:
|
||||
("len [1,2]", "len([1,2])"), # len doesn't support __getitem__...
|
||||
("call_idx [1]", "call_idx [1]"), # call_idx *does*..
|
||||
("call_idx 1", "call_idx(1)"),
|
||||
("len", "len"), # only at 2 does it auto-call on single args
|
||||
]
|
||||
)
|
||||
ip.run_line_magic("autocall", "2")
|
||||
run(
|
||||
[
|
||||
('len "abc"', 'len("abc")'),
|
||||
('len "abc";', 'len("abc");'),
|
||||
("len [1,2]", "len([1,2])"),
|
||||
("call_idx [1]", "call_idx [1]"),
|
||||
("call_idx 1", "call_idx(1)"),
|
||||
# This is what's different:
|
||||
("len", "len()"), # only at 2 does it auto-call on single args
|
||||
]
|
||||
)
|
||||
ip.run_line_magic("autocall", "1")
|
||||
|
||||
assert failures == []
|
229
.venv/Lib/site-packages/IPython/core/tests/test_history.py
Normal file
229
.venv/Lib/site-packages/IPython/core/tests/test_history.py
Normal file
@ -0,0 +1,229 @@
|
||||
# coding: utf-8
|
||||
"""Tests for the IPython tab-completion machinery.
|
||||
"""
|
||||
#-----------------------------------------------------------------------------
|
||||
# Module imports
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
# stdlib
|
||||
import io
|
||||
import sqlite3
|
||||
import sys
|
||||
import tempfile
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
from tempfile import TemporaryDirectory
|
||||
# our own packages
|
||||
from traitlets.config.loader import Config
|
||||
|
||||
from IPython.core.history import HistoryManager, extract_hist_ranges
|
||||
|
||||
|
||||
def test_proper_default_encoding():
|
||||
assert sys.getdefaultencoding() == "utf-8"
|
||||
|
||||
def test_history():
|
||||
ip = get_ipython()
|
||||
with TemporaryDirectory() as tmpdir:
|
||||
tmp_path = Path(tmpdir)
|
||||
hist_manager_ori = ip.history_manager
|
||||
hist_file = tmp_path / "history.sqlite"
|
||||
try:
|
||||
ip.history_manager = HistoryManager(shell=ip, hist_file=hist_file)
|
||||
hist = ["a=1", "def f():\n test = 1\n return test", "b='€Æ¾÷ß'"]
|
||||
for i, h in enumerate(hist, start=1):
|
||||
ip.history_manager.store_inputs(i, h)
|
||||
|
||||
ip.history_manager.db_log_output = True
|
||||
# Doesn't match the input, but we'll just check it's stored.
|
||||
ip.history_manager.output_hist_reprs[3] = "spam"
|
||||
ip.history_manager.store_output(3)
|
||||
|
||||
assert ip.history_manager.input_hist_raw == [""] + hist
|
||||
|
||||
# Detailed tests for _get_range_session
|
||||
grs = ip.history_manager._get_range_session
|
||||
assert list(grs(start=2, stop=-1)) == list(zip([0], [2], hist[1:-1]))
|
||||
assert list(grs(start=-2)) == list(zip([0, 0], [2, 3], hist[-2:]))
|
||||
assert list(grs(output=True)) == list(
|
||||
zip([0, 0, 0], [1, 2, 3], zip(hist, [None, None, "spam"]))
|
||||
)
|
||||
|
||||
# Check whether specifying a range beyond the end of the current
|
||||
# session results in an error (gh-804)
|
||||
ip.run_line_magic("hist", "2-500")
|
||||
|
||||
# Check that we can write non-ascii characters to a file
|
||||
ip.run_line_magic("hist", "-f %s" % (tmp_path / "test1"))
|
||||
ip.run_line_magic("hist", "-pf %s" % (tmp_path / "test2"))
|
||||
ip.run_line_magic("hist", "-nf %s" % (tmp_path / "test3"))
|
||||
ip.run_line_magic("save", "%s 1-10" % (tmp_path / "test4"))
|
||||
|
||||
# New session
|
||||
ip.history_manager.reset()
|
||||
newcmds = ["z=5", "class X(object):\n pass", "k='p'", "z=5"]
|
||||
for i, cmd in enumerate(newcmds, start=1):
|
||||
ip.history_manager.store_inputs(i, cmd)
|
||||
gothist = ip.history_manager.get_range(start=1, stop=4)
|
||||
assert list(gothist) == list(zip([0, 0, 0], [1, 2, 3], newcmds))
|
||||
# Previous session:
|
||||
gothist = ip.history_manager.get_range(-1, 1, 4)
|
||||
assert list(gothist) == list(zip([1, 1, 1], [1, 2, 3], hist))
|
||||
|
||||
newhist = [(2, i, c) for (i, c) in enumerate(newcmds, 1)]
|
||||
|
||||
# Check get_hist_tail
|
||||
gothist = ip.history_manager.get_tail(5, output=True,
|
||||
include_latest=True)
|
||||
expected = [(1, 3, (hist[-1], "spam"))] \
|
||||
+ [(s, n, (c, None)) for (s, n, c) in newhist]
|
||||
assert list(gothist) == expected
|
||||
|
||||
gothist = ip.history_manager.get_tail(2)
|
||||
expected = newhist[-3:-1]
|
||||
assert list(gothist) == expected
|
||||
|
||||
# Check get_hist_search
|
||||
|
||||
gothist = ip.history_manager.search("*test*")
|
||||
assert list(gothist) == [(1, 2, hist[1])]
|
||||
|
||||
gothist = ip.history_manager.search("*=*")
|
||||
assert list(gothist) == [
|
||||
(1, 1, hist[0]),
|
||||
(1, 2, hist[1]),
|
||||
(1, 3, hist[2]),
|
||||
newhist[0],
|
||||
newhist[2],
|
||||
newhist[3],
|
||||
]
|
||||
|
||||
gothist = ip.history_manager.search("*=*", n=4)
|
||||
assert list(gothist) == [
|
||||
(1, 3, hist[2]),
|
||||
newhist[0],
|
||||
newhist[2],
|
||||
newhist[3],
|
||||
]
|
||||
|
||||
gothist = ip.history_manager.search("*=*", unique=True)
|
||||
assert list(gothist) == [
|
||||
(1, 1, hist[0]),
|
||||
(1, 2, hist[1]),
|
||||
(1, 3, hist[2]),
|
||||
newhist[2],
|
||||
newhist[3],
|
||||
]
|
||||
|
||||
gothist = ip.history_manager.search("*=*", unique=True, n=3)
|
||||
assert list(gothist) == [(1, 3, hist[2]), newhist[2], newhist[3]]
|
||||
|
||||
gothist = ip.history_manager.search("b*", output=True)
|
||||
assert list(gothist) == [(1, 3, (hist[2], "spam"))]
|
||||
|
||||
# Cross testing: check that magic %save can get previous session.
|
||||
testfilename = (tmp_path / "test.py").resolve()
|
||||
ip.run_line_magic("save", str(testfilename) + " ~1/1-3")
|
||||
with io.open(testfilename, encoding="utf-8") as testfile:
|
||||
assert testfile.read() == "# coding: utf-8\n" + "\n".join(hist) + "\n"
|
||||
|
||||
# Duplicate line numbers - check that it doesn't crash, and
|
||||
# gets a new session
|
||||
ip.history_manager.store_inputs(1, "rogue")
|
||||
ip.history_manager.writeout_cache()
|
||||
assert ip.history_manager.session_number == 3
|
||||
|
||||
# Check that session and line values are not just max values
|
||||
sessid, lineno, entry = newhist[-1]
|
||||
assert lineno > 1
|
||||
ip.history_manager.reset()
|
||||
lineno = 1
|
||||
ip.history_manager.store_inputs(lineno, entry)
|
||||
gothist = ip.history_manager.search("*=*", unique=True)
|
||||
hist = list(gothist)[-1]
|
||||
assert sessid < hist[0]
|
||||
assert hist[1:] == (lineno, entry)
|
||||
finally:
|
||||
# Ensure saving thread is shut down before we try to clean up the files
|
||||
ip.history_manager.save_thread.stop()
|
||||
# Forcibly close database rather than relying on garbage collection
|
||||
ip.history_manager.db.close()
|
||||
# Restore history manager
|
||||
ip.history_manager = hist_manager_ori
|
||||
|
||||
|
||||
def test_extract_hist_ranges():
|
||||
instr = "1 2/3 ~4/5-6 ~4/7-~4/9 ~9/2-~7/5 ~10/"
|
||||
expected = [(0, 1, 2), # 0 == current session
|
||||
(2, 3, 4),
|
||||
(-4, 5, 7),
|
||||
(-4, 7, 10),
|
||||
(-9, 2, None), # None == to end
|
||||
(-8, 1, None),
|
||||
(-7, 1, 6),
|
||||
(-10, 1, None)]
|
||||
actual = list(extract_hist_ranges(instr))
|
||||
assert actual == expected
|
||||
|
||||
|
||||
def test_extract_hist_ranges_empty_str():
|
||||
instr = ""
|
||||
expected = [(0, 1, None)] # 0 == current session, None == to end
|
||||
actual = list(extract_hist_ranges(instr))
|
||||
assert actual == expected
|
||||
|
||||
|
||||
def test_magic_rerun():
|
||||
"""Simple test for %rerun (no args -> rerun last line)"""
|
||||
ip = get_ipython()
|
||||
ip.run_cell("a = 10", store_history=True)
|
||||
ip.run_cell("a += 1", store_history=True)
|
||||
assert ip.user_ns["a"] == 11
|
||||
ip.run_cell("%rerun", store_history=True)
|
||||
assert ip.user_ns["a"] == 12
|
||||
|
||||
def test_timestamp_type():
|
||||
ip = get_ipython()
|
||||
info = ip.history_manager.get_session_info()
|
||||
assert isinstance(info[1], datetime)
|
||||
|
||||
def test_hist_file_config():
|
||||
cfg = Config()
|
||||
tfile = tempfile.NamedTemporaryFile(delete=False)
|
||||
cfg.HistoryManager.hist_file = Path(tfile.name)
|
||||
try:
|
||||
hm = HistoryManager(shell=get_ipython(), config=cfg)
|
||||
assert hm.hist_file == cfg.HistoryManager.hist_file
|
||||
finally:
|
||||
try:
|
||||
Path(tfile.name).unlink()
|
||||
except OSError:
|
||||
# same catch as in testing.tools.TempFileMixin
|
||||
# On Windows, even though we close the file, we still can't
|
||||
# delete it. I have no clue why
|
||||
pass
|
||||
|
||||
def test_histmanager_disabled():
|
||||
"""Ensure that disabling the history manager doesn't create a database."""
|
||||
cfg = Config()
|
||||
cfg.HistoryAccessor.enabled = False
|
||||
|
||||
ip = get_ipython()
|
||||
with TemporaryDirectory() as tmpdir:
|
||||
hist_manager_ori = ip.history_manager
|
||||
hist_file = Path(tmpdir) / "history.sqlite"
|
||||
cfg.HistoryManager.hist_file = hist_file
|
||||
try:
|
||||
ip.history_manager = HistoryManager(shell=ip, config=cfg)
|
||||
hist = ["a=1", "def f():\n test = 1\n return test", "b='€Æ¾÷ß'"]
|
||||
for i, h in enumerate(hist, start=1):
|
||||
ip.history_manager.store_inputs(i, h)
|
||||
assert ip.history_manager.input_hist_raw == [""] + hist
|
||||
ip.history_manager.reset()
|
||||
ip.history_manager.end_session()
|
||||
finally:
|
||||
ip.history_manager = hist_manager_ori
|
||||
|
||||
# hist_file should not be created
|
||||
assert hist_file.exists() is False
|
76
.venv/Lib/site-packages/IPython/core/tests/test_hooks.py
Normal file
76
.venv/Lib/site-packages/IPython/core/tests/test_hooks.py
Normal file
@ -0,0 +1,76 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Tests for CommandChainDispatcher."""
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Imports
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
import pytest
|
||||
from IPython.core.error import TryNext
|
||||
from IPython.core.hooks import CommandChainDispatcher
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Local utilities
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
# Define two classes, one which succeeds and one which raises TryNext. Each
|
||||
# sets the attribute `called` to True when it is called.
|
||||
class Okay(object):
|
||||
def __init__(self, message):
|
||||
self.message = message
|
||||
self.called = False
|
||||
def __call__(self):
|
||||
self.called = True
|
||||
return self.message
|
||||
|
||||
class Fail(object):
|
||||
def __init__(self, message):
|
||||
self.message = message
|
||||
self.called = False
|
||||
def __call__(self):
|
||||
self.called = True
|
||||
raise TryNext(self.message)
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Test functions
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
def test_command_chain_dispatcher_ff():
|
||||
"""Test two failing hooks"""
|
||||
fail1 = Fail("fail1")
|
||||
fail2 = Fail("fail2")
|
||||
dp = CommandChainDispatcher([(0, fail1), (10, fail2)])
|
||||
|
||||
with pytest.raises(TryNext) as e:
|
||||
dp()
|
||||
assert str(e.value) == "fail2"
|
||||
|
||||
assert fail1.called is True
|
||||
assert fail2.called is True
|
||||
|
||||
def test_command_chain_dispatcher_fofo():
|
||||
"""Test a mixture of failing and succeeding hooks."""
|
||||
fail1 = Fail("fail1")
|
||||
fail2 = Fail("fail2")
|
||||
okay1 = Okay("okay1")
|
||||
okay2 = Okay("okay2")
|
||||
|
||||
dp = CommandChainDispatcher([(0, fail1),
|
||||
# (5, okay1), # add this later
|
||||
(10, fail2),
|
||||
(15, okay2)])
|
||||
dp.add(okay1, 5)
|
||||
|
||||
assert dp() == "okay1"
|
||||
|
||||
assert fail1.called is True
|
||||
assert okay1.called is True
|
||||
assert fail2.called is False
|
||||
assert okay2.called is False
|
||||
|
||||
def test_command_chain_dispatcher_eq_priority():
|
||||
okay1 = Okay(u'okay1')
|
||||
okay2 = Okay(u'okay2')
|
||||
dp = CommandChainDispatcher([(1, okay1)])
|
||||
dp.add(okay2, 1)
|
52
.venv/Lib/site-packages/IPython/core/tests/test_imports.py
Normal file
52
.venv/Lib/site-packages/IPython/core/tests/test_imports.py
Normal file
@ -0,0 +1,52 @@
|
||||
# encoding: utf-8
|
||||
|
||||
def test_import_completer():
|
||||
from IPython.core import completer
|
||||
|
||||
def test_import_crashhandler():
|
||||
from IPython.core import crashhandler
|
||||
|
||||
def test_import_debugger():
|
||||
from IPython.core import debugger
|
||||
|
||||
def test_import_excolors():
|
||||
from IPython.core import excolors
|
||||
|
||||
def test_import_history():
|
||||
from IPython.core import history
|
||||
|
||||
def test_import_hooks():
|
||||
from IPython.core import hooks
|
||||
|
||||
def test_import_getipython():
|
||||
from IPython.core import getipython
|
||||
|
||||
def test_import_interactiveshell():
|
||||
from IPython.core import interactiveshell
|
||||
|
||||
def test_import_logger():
|
||||
from IPython.core import logger
|
||||
|
||||
def test_import_macro():
|
||||
from IPython.core import macro
|
||||
|
||||
def test_import_magic():
|
||||
from IPython.core import magic
|
||||
|
||||
def test_import_oinspect():
|
||||
from IPython.core import oinspect
|
||||
|
||||
def test_import_prefilter():
|
||||
from IPython.core import prefilter
|
||||
|
||||
def test_import_prompts():
|
||||
from IPython.core import prompts
|
||||
|
||||
def test_import_release():
|
||||
from IPython.core import release
|
||||
|
||||
def test_import_ultratb():
|
||||
from IPython.core import ultratb
|
||||
|
||||
def test_import_usage():
|
||||
from IPython.core import usage
|
642
.venv/Lib/site-packages/IPython/core/tests/test_inputsplitter.py
Normal file
642
.venv/Lib/site-packages/IPython/core/tests/test_inputsplitter.py
Normal file
@ -0,0 +1,642 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Tests for the inputsplitter module."""
|
||||
|
||||
|
||||
# Copyright (c) IPython Development Team.
|
||||
# Distributed under the terms of the Modified BSD License.
|
||||
|
||||
import unittest
|
||||
import pytest
|
||||
import sys
|
||||
|
||||
with pytest.warns(DeprecationWarning, match="inputsplitter"):
|
||||
from IPython.core import inputsplitter as isp
|
||||
from IPython.core.inputtransformer import InputTransformer
|
||||
from IPython.core.tests.test_inputtransformer import syntax, syntax_ml
|
||||
from IPython.testing import tools as tt
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Semi-complete examples (also used as tests)
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
# Note: at the bottom, there's a slightly more complete version of this that
|
||||
# can be useful during development of code here.
|
||||
|
||||
def mini_interactive_loop(input_func):
|
||||
"""Minimal example of the logic of an interactive interpreter loop.
|
||||
|
||||
This serves as an example, and it is used by the test system with a fake
|
||||
raw_input that simulates interactive input."""
|
||||
|
||||
from IPython.core.inputsplitter import InputSplitter
|
||||
|
||||
isp = InputSplitter()
|
||||
# In practice, this input loop would be wrapped in an outside loop to read
|
||||
# input indefinitely, until some exit/quit command was issued. Here we
|
||||
# only illustrate the basic inner loop.
|
||||
while isp.push_accepts_more():
|
||||
indent = ' '*isp.get_indent_spaces()
|
||||
prompt = '>>> ' + indent
|
||||
line = indent + input_func(prompt)
|
||||
isp.push(line)
|
||||
|
||||
# Here we just return input so we can use it in a test suite, but a real
|
||||
# interpreter would instead send it for execution somewhere.
|
||||
src = isp.source_reset()
|
||||
#print 'Input source was:\n', src # dbg
|
||||
return src
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Test utilities, just for local use
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
def pseudo_input(lines):
|
||||
"""Return a function that acts like raw_input but feeds the input list."""
|
||||
ilines = iter(lines)
|
||||
def raw_in(prompt):
|
||||
try:
|
||||
return next(ilines)
|
||||
except StopIteration:
|
||||
return ''
|
||||
return raw_in
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Tests
|
||||
#-----------------------------------------------------------------------------
|
||||
def test_spaces():
|
||||
tests = [('', 0),
|
||||
(' ', 1),
|
||||
('\n', 0),
|
||||
(' \n', 1),
|
||||
('x', 0),
|
||||
(' x', 1),
|
||||
(' x',2),
|
||||
(' x',4),
|
||||
# Note: tabs are counted as a single whitespace!
|
||||
('\tx', 1),
|
||||
('\t x', 2),
|
||||
]
|
||||
tt.check_pairs(isp.num_ini_spaces, tests)
|
||||
|
||||
|
||||
def test_remove_comments():
|
||||
tests = [('text', 'text'),
|
||||
('text # comment', 'text '),
|
||||
('text # comment\n', 'text \n'),
|
||||
('text # comment \n', 'text \n'),
|
||||
('line # c \nline\n','line \nline\n'),
|
||||
('line # c \nline#c2 \nline\nline #c\n\n',
|
||||
'line \nline\nline\nline \n\n'),
|
||||
]
|
||||
tt.check_pairs(isp.remove_comments, tests)
|
||||
|
||||
|
||||
def test_get_input_encoding():
|
||||
encoding = isp.get_input_encoding()
|
||||
assert isinstance(encoding, str)
|
||||
# simple-minded check that at least encoding a simple string works with the
|
||||
# encoding we got.
|
||||
assert "test".encode(encoding) == b"test"
|
||||
|
||||
|
||||
class NoInputEncodingTestCase(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.old_stdin = sys.stdin
|
||||
class X: pass
|
||||
fake_stdin = X()
|
||||
sys.stdin = fake_stdin
|
||||
|
||||
def test(self):
|
||||
# Verify that if sys.stdin has no 'encoding' attribute we do the right
|
||||
# thing
|
||||
enc = isp.get_input_encoding()
|
||||
self.assertEqual(enc, 'ascii')
|
||||
|
||||
def tearDown(self):
|
||||
sys.stdin = self.old_stdin
|
||||
|
||||
|
||||
class InputSplitterTestCase(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.isp = isp.InputSplitter()
|
||||
|
||||
def test_reset(self):
|
||||
isp = self.isp
|
||||
isp.push('x=1')
|
||||
isp.reset()
|
||||
self.assertEqual(isp._buffer, [])
|
||||
self.assertEqual(isp.get_indent_spaces(), 0)
|
||||
self.assertEqual(isp.source, '')
|
||||
self.assertEqual(isp.code, None)
|
||||
self.assertEqual(isp._is_complete, False)
|
||||
|
||||
def test_source(self):
|
||||
self.isp._store('1')
|
||||
self.isp._store('2')
|
||||
self.assertEqual(self.isp.source, '1\n2\n')
|
||||
self.assertEqual(len(self.isp._buffer)>0, True)
|
||||
self.assertEqual(self.isp.source_reset(), '1\n2\n')
|
||||
self.assertEqual(self.isp._buffer, [])
|
||||
self.assertEqual(self.isp.source, '')
|
||||
|
||||
def test_indent(self):
|
||||
isp = self.isp # shorthand
|
||||
isp.push('x=1')
|
||||
self.assertEqual(isp.get_indent_spaces(), 0)
|
||||
isp.push('if 1:\n x=1')
|
||||
self.assertEqual(isp.get_indent_spaces(), 4)
|
||||
isp.push('y=2\n')
|
||||
self.assertEqual(isp.get_indent_spaces(), 0)
|
||||
|
||||
def test_indent2(self):
|
||||
isp = self.isp
|
||||
isp.push('if 1:')
|
||||
self.assertEqual(isp.get_indent_spaces(), 4)
|
||||
isp.push(' x=1')
|
||||
self.assertEqual(isp.get_indent_spaces(), 4)
|
||||
# Blank lines shouldn't change the indent level
|
||||
isp.push(' '*2)
|
||||
self.assertEqual(isp.get_indent_spaces(), 4)
|
||||
|
||||
def test_indent3(self):
|
||||
isp = self.isp
|
||||
# When a multiline statement contains parens or multiline strings, we
|
||||
# shouldn't get confused.
|
||||
isp.push("if 1:")
|
||||
isp.push(" x = (1+\n 2)")
|
||||
self.assertEqual(isp.get_indent_spaces(), 4)
|
||||
|
||||
def test_indent4(self):
|
||||
isp = self.isp
|
||||
# whitespace after ':' should not screw up indent level
|
||||
isp.push('if 1: \n x=1')
|
||||
self.assertEqual(isp.get_indent_spaces(), 4)
|
||||
isp.push('y=2\n')
|
||||
self.assertEqual(isp.get_indent_spaces(), 0)
|
||||
isp.push('if 1:\t\n x=1')
|
||||
self.assertEqual(isp.get_indent_spaces(), 4)
|
||||
isp.push('y=2\n')
|
||||
self.assertEqual(isp.get_indent_spaces(), 0)
|
||||
|
||||
def test_dedent_pass(self):
|
||||
isp = self.isp # shorthand
|
||||
# should NOT cause dedent
|
||||
isp.push('if 1:\n passes = 5')
|
||||
self.assertEqual(isp.get_indent_spaces(), 4)
|
||||
isp.push('if 1:\n pass')
|
||||
self.assertEqual(isp.get_indent_spaces(), 0)
|
||||
isp.push('if 1:\n pass ')
|
||||
self.assertEqual(isp.get_indent_spaces(), 0)
|
||||
|
||||
def test_dedent_break(self):
|
||||
isp = self.isp # shorthand
|
||||
# should NOT cause dedent
|
||||
isp.push('while 1:\n breaks = 5')
|
||||
self.assertEqual(isp.get_indent_spaces(), 4)
|
||||
isp.push('while 1:\n break')
|
||||
self.assertEqual(isp.get_indent_spaces(), 0)
|
||||
isp.push('while 1:\n break ')
|
||||
self.assertEqual(isp.get_indent_spaces(), 0)
|
||||
|
||||
def test_dedent_continue(self):
|
||||
isp = self.isp # shorthand
|
||||
# should NOT cause dedent
|
||||
isp.push('while 1:\n continues = 5')
|
||||
self.assertEqual(isp.get_indent_spaces(), 4)
|
||||
isp.push('while 1:\n continue')
|
||||
self.assertEqual(isp.get_indent_spaces(), 0)
|
||||
isp.push('while 1:\n continue ')
|
||||
self.assertEqual(isp.get_indent_spaces(), 0)
|
||||
|
||||
def test_dedent_raise(self):
|
||||
isp = self.isp # shorthand
|
||||
# should NOT cause dedent
|
||||
isp.push('if 1:\n raised = 4')
|
||||
self.assertEqual(isp.get_indent_spaces(), 4)
|
||||
isp.push('if 1:\n raise TypeError()')
|
||||
self.assertEqual(isp.get_indent_spaces(), 0)
|
||||
isp.push('if 1:\n raise')
|
||||
self.assertEqual(isp.get_indent_spaces(), 0)
|
||||
isp.push('if 1:\n raise ')
|
||||
self.assertEqual(isp.get_indent_spaces(), 0)
|
||||
|
||||
def test_dedent_return(self):
|
||||
isp = self.isp # shorthand
|
||||
# should NOT cause dedent
|
||||
isp.push('if 1:\n returning = 4')
|
||||
self.assertEqual(isp.get_indent_spaces(), 4)
|
||||
isp.push('if 1:\n return 5 + 493')
|
||||
self.assertEqual(isp.get_indent_spaces(), 0)
|
||||
isp.push('if 1:\n return')
|
||||
self.assertEqual(isp.get_indent_spaces(), 0)
|
||||
isp.push('if 1:\n return ')
|
||||
self.assertEqual(isp.get_indent_spaces(), 0)
|
||||
isp.push('if 1:\n return(0)')
|
||||
self.assertEqual(isp.get_indent_spaces(), 0)
|
||||
|
||||
def test_push(self):
|
||||
isp = self.isp
|
||||
self.assertEqual(isp.push('x=1'), True)
|
||||
|
||||
def test_push2(self):
|
||||
isp = self.isp
|
||||
self.assertEqual(isp.push('if 1:'), False)
|
||||
for line in [' x=1', '# a comment', ' y=2']:
|
||||
print(line)
|
||||
self.assertEqual(isp.push(line), True)
|
||||
|
||||
def test_push3(self):
|
||||
isp = self.isp
|
||||
isp.push('if True:')
|
||||
isp.push(' a = 1')
|
||||
self.assertEqual(isp.push('b = [1,'), False)
|
||||
|
||||
def test_push_accepts_more(self):
|
||||
isp = self.isp
|
||||
isp.push('x=1')
|
||||
self.assertEqual(isp.push_accepts_more(), False)
|
||||
|
||||
def test_push_accepts_more2(self):
|
||||
isp = self.isp
|
||||
isp.push('if 1:')
|
||||
self.assertEqual(isp.push_accepts_more(), True)
|
||||
isp.push(' x=1')
|
||||
self.assertEqual(isp.push_accepts_more(), True)
|
||||
isp.push('')
|
||||
self.assertEqual(isp.push_accepts_more(), False)
|
||||
|
||||
def test_push_accepts_more3(self):
|
||||
isp = self.isp
|
||||
isp.push("x = (2+\n3)")
|
||||
self.assertEqual(isp.push_accepts_more(), False)
|
||||
|
||||
def test_push_accepts_more4(self):
|
||||
isp = self.isp
|
||||
# When a multiline statement contains parens or multiline strings, we
|
||||
# shouldn't get confused.
|
||||
# FIXME: we should be able to better handle de-dents in statements like
|
||||
# multiline strings and multiline expressions (continued with \ or
|
||||
# parens). Right now we aren't handling the indentation tracking quite
|
||||
# correctly with this, though in practice it may not be too much of a
|
||||
# problem. We'll need to see.
|
||||
isp.push("if 1:")
|
||||
isp.push(" x = (2+")
|
||||
isp.push(" 3)")
|
||||
self.assertEqual(isp.push_accepts_more(), True)
|
||||
isp.push(" y = 3")
|
||||
self.assertEqual(isp.push_accepts_more(), True)
|
||||
isp.push('')
|
||||
self.assertEqual(isp.push_accepts_more(), False)
|
||||
|
||||
def test_push_accepts_more5(self):
|
||||
isp = self.isp
|
||||
isp.push('try:')
|
||||
isp.push(' a = 5')
|
||||
isp.push('except:')
|
||||
isp.push(' raise')
|
||||
# We want to be able to add an else: block at this point, so it should
|
||||
# wait for a blank line.
|
||||
self.assertEqual(isp.push_accepts_more(), True)
|
||||
|
||||
def test_continuation(self):
|
||||
isp = self.isp
|
||||
isp.push("import os, \\")
|
||||
self.assertEqual(isp.push_accepts_more(), True)
|
||||
isp.push("sys")
|
||||
self.assertEqual(isp.push_accepts_more(), False)
|
||||
|
||||
def test_syntax_error(self):
|
||||
isp = self.isp
|
||||
# Syntax errors immediately produce a 'ready' block, so the invalid
|
||||
# Python can be sent to the kernel for evaluation with possible ipython
|
||||
# special-syntax conversion.
|
||||
isp.push('run foo')
|
||||
self.assertEqual(isp.push_accepts_more(), False)
|
||||
|
||||
def test_unicode(self):
|
||||
self.isp.push(u"Pérez")
|
||||
self.isp.push(u'\xc3\xa9')
|
||||
self.isp.push(u"u'\xc3\xa9'")
|
||||
|
||||
@pytest.mark.xfail(
|
||||
reason="Bug in python 3.9.8 – bpo 45738",
|
||||
condition=sys.version_info in [(3, 9, 8, "final", 0), (3, 11, 0, "alpha", 2)],
|
||||
raises=SystemError,
|
||||
strict=True,
|
||||
)
|
||||
def test_line_continuation(self):
|
||||
""" Test issue #2108."""
|
||||
isp = self.isp
|
||||
# A blank line after a line continuation should not accept more
|
||||
isp.push("1 \\\n\n")
|
||||
self.assertEqual(isp.push_accepts_more(), False)
|
||||
# Whitespace after a \ is a SyntaxError. The only way to test that
|
||||
# here is to test that push doesn't accept more (as with
|
||||
# test_syntax_error() above).
|
||||
isp.push(r"1 \ ")
|
||||
self.assertEqual(isp.push_accepts_more(), False)
|
||||
# Even if the line is continuable (c.f. the regular Python
|
||||
# interpreter)
|
||||
isp.push(r"(1 \ ")
|
||||
self.assertEqual(isp.push_accepts_more(), False)
|
||||
|
||||
def test_check_complete(self):
|
||||
isp = self.isp
|
||||
self.assertEqual(isp.check_complete("a = 1"), ('complete', None))
|
||||
self.assertEqual(isp.check_complete("for a in range(5):"), ('incomplete', 4))
|
||||
self.assertEqual(isp.check_complete("raise = 2"), ('invalid', None))
|
||||
self.assertEqual(isp.check_complete("a = [1,\n2,"), ('incomplete', 0))
|
||||
self.assertEqual(isp.check_complete("def a():\n x=1\n global x"), ('invalid', None))
|
||||
|
||||
class InteractiveLoopTestCase(unittest.TestCase):
|
||||
"""Tests for an interactive loop like a python shell.
|
||||
"""
|
||||
def check_ns(self, lines, ns):
|
||||
"""Validate that the given input lines produce the resulting namespace.
|
||||
|
||||
Note: the input lines are given exactly as they would be typed in an
|
||||
auto-indenting environment, as mini_interactive_loop above already does
|
||||
auto-indenting and prepends spaces to the input.
|
||||
"""
|
||||
src = mini_interactive_loop(pseudo_input(lines))
|
||||
test_ns = {}
|
||||
exec(src, test_ns)
|
||||
# We can't check that the provided ns is identical to the test_ns,
|
||||
# because Python fills test_ns with extra keys (copyright, etc). But
|
||||
# we can check that the given dict is *contained* in test_ns
|
||||
for k,v in ns.items():
|
||||
self.assertEqual(test_ns[k], v)
|
||||
|
||||
def test_simple(self):
|
||||
self.check_ns(['x=1'], dict(x=1))
|
||||
|
||||
def test_simple2(self):
|
||||
self.check_ns(['if 1:', 'x=2'], dict(x=2))
|
||||
|
||||
def test_xy(self):
|
||||
self.check_ns(['x=1; y=2'], dict(x=1, y=2))
|
||||
|
||||
def test_abc(self):
|
||||
self.check_ns(['if 1:','a=1','b=2','c=3'], dict(a=1, b=2, c=3))
|
||||
|
||||
def test_multi(self):
|
||||
self.check_ns(['x =(1+','1+','2)'], dict(x=4))
|
||||
|
||||
|
||||
class IPythonInputTestCase(InputSplitterTestCase):
|
||||
"""By just creating a new class whose .isp is a different instance, we
|
||||
re-run the same test battery on the new input splitter.
|
||||
|
||||
In addition, this runs the tests over the syntax and syntax_ml dicts that
|
||||
were tested by individual functions, as part of the OO interface.
|
||||
|
||||
It also makes some checks on the raw buffer storage.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
self.isp = isp.IPythonInputSplitter()
|
||||
|
||||
def test_syntax(self):
|
||||
"""Call all single-line syntax tests from the main object"""
|
||||
isp = self.isp
|
||||
for example in syntax.values():
|
||||
for raw, out_t in example:
|
||||
if raw.startswith(' '):
|
||||
continue
|
||||
|
||||
isp.push(raw+'\n')
|
||||
out_raw = isp.source_raw
|
||||
out = isp.source_reset()
|
||||
self.assertEqual(out.rstrip(), out_t,
|
||||
tt.pair_fail_msg.format("inputsplitter",raw, out_t, out))
|
||||
self.assertEqual(out_raw.rstrip(), raw.rstrip())
|
||||
|
||||
def test_syntax_multiline(self):
|
||||
isp = self.isp
|
||||
for example in syntax_ml.values():
|
||||
for line_pairs in example:
|
||||
out_t_parts = []
|
||||
raw_parts = []
|
||||
for lraw, out_t_part in line_pairs:
|
||||
if out_t_part is not None:
|
||||
out_t_parts.append(out_t_part)
|
||||
|
||||
if lraw is not None:
|
||||
isp.push(lraw)
|
||||
raw_parts.append(lraw)
|
||||
|
||||
out_raw = isp.source_raw
|
||||
out = isp.source_reset()
|
||||
out_t = '\n'.join(out_t_parts).rstrip()
|
||||
raw = '\n'.join(raw_parts).rstrip()
|
||||
self.assertEqual(out.rstrip(), out_t)
|
||||
self.assertEqual(out_raw.rstrip(), raw)
|
||||
|
||||
def test_syntax_multiline_cell(self):
|
||||
isp = self.isp
|
||||
for example in syntax_ml.values():
|
||||
|
||||
out_t_parts = []
|
||||
for line_pairs in example:
|
||||
raw = '\n'.join(r for r, _ in line_pairs if r is not None)
|
||||
out_t = '\n'.join(t for _,t in line_pairs if t is not None)
|
||||
out = isp.transform_cell(raw)
|
||||
# Match ignoring trailing whitespace
|
||||
self.assertEqual(out.rstrip(), out_t.rstrip())
|
||||
|
||||
def test_cellmagic_preempt(self):
|
||||
isp = self.isp
|
||||
for raw, name, line, cell in [
|
||||
("%%cellm a\nIn[1]:", u'cellm', u'a', u'In[1]:'),
|
||||
("%%cellm \nline\n>>> hi", u'cellm', u'', u'line\n>>> hi'),
|
||||
(">>> %%cellm \nline\n>>> hi", u'cellm', u'', u'line\nhi'),
|
||||
("%%cellm \n>>> hi", u'cellm', u'', u'>>> hi'),
|
||||
("%%cellm \nline1\nline2", u'cellm', u'', u'line1\nline2'),
|
||||
("%%cellm \nline1\\\\\nline2", u'cellm', u'', u'line1\\\\\nline2'),
|
||||
]:
|
||||
expected = "get_ipython().run_cell_magic(%r, %r, %r)" % (
|
||||
name, line, cell
|
||||
)
|
||||
out = isp.transform_cell(raw)
|
||||
self.assertEqual(out.rstrip(), expected.rstrip())
|
||||
|
||||
def test_multiline_passthrough(self):
|
||||
isp = self.isp
|
||||
class CommentTransformer(InputTransformer):
|
||||
def __init__(self):
|
||||
self._lines = []
|
||||
|
||||
def push(self, line):
|
||||
self._lines.append(line + '#')
|
||||
|
||||
def reset(self):
|
||||
text = '\n'.join(self._lines)
|
||||
self._lines = []
|
||||
return text
|
||||
|
||||
isp.physical_line_transforms.insert(0, CommentTransformer())
|
||||
|
||||
for raw, expected in [
|
||||
("a=5", "a=5#"),
|
||||
("%ls foo", "get_ipython().run_line_magic(%r, %r)" % (u'ls', u'foo#')),
|
||||
("!ls foo\n%ls bar", "get_ipython().system(%r)\nget_ipython().run_line_magic(%r, %r)" % (
|
||||
u'ls foo#', u'ls', u'bar#'
|
||||
)),
|
||||
("1\n2\n3\n%ls foo\n4\n5", "1#\n2#\n3#\nget_ipython().run_line_magic(%r, %r)\n4#\n5#" % (u'ls', u'foo#')),
|
||||
]:
|
||||
out = isp.transform_cell(raw)
|
||||
self.assertEqual(out.rstrip(), expected.rstrip())
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Main - use as a script, mostly for developer experiments
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
if __name__ == '__main__':
|
||||
# A simple demo for interactive experimentation. This code will not get
|
||||
# picked up by any test suite.
|
||||
from IPython.core.inputsplitter import IPythonInputSplitter
|
||||
|
||||
# configure here the syntax to use, prompt and whether to autoindent
|
||||
#isp, start_prompt = InputSplitter(), '>>> '
|
||||
isp, start_prompt = IPythonInputSplitter(), 'In> '
|
||||
|
||||
autoindent = True
|
||||
#autoindent = False
|
||||
|
||||
try:
|
||||
while True:
|
||||
prompt = start_prompt
|
||||
while isp.push_accepts_more():
|
||||
indent = ' '*isp.get_indent_spaces()
|
||||
if autoindent:
|
||||
line = indent + input(prompt+indent)
|
||||
else:
|
||||
line = input(prompt)
|
||||
isp.push(line)
|
||||
prompt = '... '
|
||||
|
||||
# Here we just return input so we can use it in a test suite, but a
|
||||
# real interpreter would instead send it for execution somewhere.
|
||||
#src = isp.source; raise EOFError # dbg
|
||||
raw = isp.source_raw
|
||||
src = isp.source_reset()
|
||||
print('Input source was:\n', src)
|
||||
print('Raw source was:\n', raw)
|
||||
except EOFError:
|
||||
print('Bye')
|
||||
|
||||
# Tests for cell magics support
|
||||
|
||||
def test_last_blank():
|
||||
assert isp.last_blank("") is False
|
||||
assert isp.last_blank("abc") is False
|
||||
assert isp.last_blank("abc\n") is False
|
||||
assert isp.last_blank("abc\na") is False
|
||||
|
||||
assert isp.last_blank("\n") is True
|
||||
assert isp.last_blank("\n ") is True
|
||||
assert isp.last_blank("abc\n ") is True
|
||||
assert isp.last_blank("abc\n\n") is True
|
||||
assert isp.last_blank("abc\nd\n\n") is True
|
||||
assert isp.last_blank("abc\nd\ne\n\n") is True
|
||||
assert isp.last_blank("abc \n \n \n\n") is True
|
||||
|
||||
|
||||
def test_last_two_blanks():
|
||||
assert isp.last_two_blanks("") is False
|
||||
assert isp.last_two_blanks("abc") is False
|
||||
assert isp.last_two_blanks("abc\n") is False
|
||||
assert isp.last_two_blanks("abc\n\na") is False
|
||||
assert isp.last_two_blanks("abc\n \n") is False
|
||||
assert isp.last_two_blanks("abc\n\n") is False
|
||||
|
||||
assert isp.last_two_blanks("\n\n") is True
|
||||
assert isp.last_two_blanks("\n\n ") is True
|
||||
assert isp.last_two_blanks("\n \n") is True
|
||||
assert isp.last_two_blanks("abc\n\n ") is True
|
||||
assert isp.last_two_blanks("abc\n\n\n") is True
|
||||
assert isp.last_two_blanks("abc\n\n \n") is True
|
||||
assert isp.last_two_blanks("abc\n\n \n ") is True
|
||||
assert isp.last_two_blanks("abc\n\n \n \n") is True
|
||||
assert isp.last_two_blanks("abc\nd\n\n\n") is True
|
||||
assert isp.last_two_blanks("abc\nd\ne\nf\n\n\n") is True
|
||||
|
||||
|
||||
class CellMagicsCommon(object):
|
||||
|
||||
def test_whole_cell(self):
|
||||
src = "%%cellm line\nbody\n"
|
||||
out = self.sp.transform_cell(src)
|
||||
ref = "get_ipython().run_cell_magic('cellm', 'line', 'body')\n"
|
||||
assert out == ref
|
||||
|
||||
def test_cellmagic_help(self):
|
||||
self.sp.push('%%cellm?')
|
||||
assert self.sp.push_accepts_more() is False
|
||||
|
||||
def tearDown(self):
|
||||
self.sp.reset()
|
||||
|
||||
|
||||
class CellModeCellMagics(CellMagicsCommon, unittest.TestCase):
|
||||
sp = isp.IPythonInputSplitter(line_input_checker=False)
|
||||
|
||||
def test_incremental(self):
|
||||
sp = self.sp
|
||||
sp.push("%%cellm firstline\n")
|
||||
assert sp.push_accepts_more() is True # 1
|
||||
sp.push("line2\n")
|
||||
assert sp.push_accepts_more() is True # 2
|
||||
sp.push("\n")
|
||||
# This should accept a blank line and carry on until the cell is reset
|
||||
assert sp.push_accepts_more() is True # 3
|
||||
|
||||
def test_no_strip_coding(self):
|
||||
src = '\n'.join([
|
||||
'%%writefile foo.py',
|
||||
'# coding: utf-8',
|
||||
'print(u"üñîçø∂é")',
|
||||
])
|
||||
out = self.sp.transform_cell(src)
|
||||
assert "# coding: utf-8" in out
|
||||
|
||||
|
||||
class LineModeCellMagics(CellMagicsCommon, unittest.TestCase):
|
||||
sp = isp.IPythonInputSplitter(line_input_checker=True)
|
||||
|
||||
def test_incremental(self):
|
||||
sp = self.sp
|
||||
sp.push("%%cellm line2\n")
|
||||
assert sp.push_accepts_more() is True # 1
|
||||
sp.push("\n")
|
||||
# In this case, a blank line should end the cell magic
|
||||
assert sp.push_accepts_more() is False # 2
|
||||
|
||||
|
||||
indentation_samples = [
|
||||
('a = 1', 0),
|
||||
('for a in b:', 4),
|
||||
('def f():', 4),
|
||||
('def f(): #comment', 4),
|
||||
('a = ":#not a comment"', 0),
|
||||
('def f():\n a = 1', 4),
|
||||
('def f():\n return 1', 0),
|
||||
('for a in b:\n'
|
||||
' if a < 0:'
|
||||
' continue', 3),
|
||||
('a = {', 4),
|
||||
('a = {\n'
|
||||
' 1,', 5),
|
||||
('b = """123', 0),
|
||||
('', 0),
|
||||
('def f():\n pass', 0),
|
||||
('class Bar:\n def f():\n pass', 4),
|
||||
('class Bar:\n def f():\n raise', 4),
|
||||
]
|
||||
|
||||
def test_find_next_indent():
|
||||
for code, exp in indentation_samples:
|
||||
res = isp.find_next_indent(code)
|
||||
msg = "{!r} != {!r} (expected)\n Code: {!r}".format(res, exp, code)
|
||||
assert res == exp, msg
|
@ -0,0 +1,469 @@
|
||||
import tokenize
|
||||
|
||||
from IPython.testing import tools as tt
|
||||
|
||||
from IPython.core import inputtransformer as ipt
|
||||
|
||||
def transform_and_reset(transformer):
|
||||
transformer = transformer()
|
||||
def transform(inp):
|
||||
try:
|
||||
return transformer.push(inp)
|
||||
finally:
|
||||
transformer.reset()
|
||||
|
||||
return transform
|
||||
|
||||
# Transformer tests
|
||||
def transform_checker(tests, transformer, **kwargs):
|
||||
"""Utility to loop over test inputs"""
|
||||
transformer = transformer(**kwargs)
|
||||
try:
|
||||
for inp, tr in tests:
|
||||
if inp is None:
|
||||
out = transformer.reset()
|
||||
else:
|
||||
out = transformer.push(inp)
|
||||
assert out == tr
|
||||
finally:
|
||||
transformer.reset()
|
||||
|
||||
# Data for all the syntax tests in the form of lists of pairs of
|
||||
# raw/transformed input. We store it here as a global dict so that we can use
|
||||
# it both within single-function tests and also to validate the behavior of the
|
||||
# larger objects
|
||||
|
||||
syntax = \
|
||||
dict(assign_system =
|
||||
[('a =! ls', "a = get_ipython().getoutput('ls')"),
|
||||
('b = !ls', "b = get_ipython().getoutput('ls')"),
|
||||
('c= !ls', "c = get_ipython().getoutput('ls')"),
|
||||
('d == !ls', 'd == !ls'), # Invalid syntax, but we leave == alone.
|
||||
('x=1', 'x=1'), # normal input is unmodified
|
||||
(' ',' '), # blank lines are kept intact
|
||||
# Tuple unpacking
|
||||
("a, b = !echo 'a\\nb'", "a, b = get_ipython().getoutput(\"echo 'a\\\\nb'\")"),
|
||||
("a,= !echo 'a'", "a, = get_ipython().getoutput(\"echo 'a'\")"),
|
||||
("a, *bc = !echo 'a\\nb\\nc'", "a, *bc = get_ipython().getoutput(\"echo 'a\\\\nb\\\\nc'\")"),
|
||||
# Tuple unpacking with regular Python expressions, not our syntax.
|
||||
("a, b = range(2)", "a, b = range(2)"),
|
||||
("a, = range(1)", "a, = range(1)"),
|
||||
("a, *bc = range(3)", "a, *bc = range(3)"),
|
||||
],
|
||||
|
||||
assign_magic =
|
||||
[('a =% who', "a = get_ipython().run_line_magic('who', '')"),
|
||||
('b = %who', "b = get_ipython().run_line_magic('who', '')"),
|
||||
('c= %ls', "c = get_ipython().run_line_magic('ls', '')"),
|
||||
('d == %ls', 'd == %ls'), # Invalid syntax, but we leave == alone.
|
||||
('x=1', 'x=1'), # normal input is unmodified
|
||||
(' ',' '), # blank lines are kept intact
|
||||
("a, b = %foo", "a, b = get_ipython().run_line_magic('foo', '')"),
|
||||
],
|
||||
classic_prompt=[
|
||||
(">>> x=1", "x=1"),
|
||||
("x=1", "x=1"), # normal input is unmodified
|
||||
(" ", " "), # blank lines are kept intact
|
||||
],
|
||||
ipy_prompt=[
|
||||
("In [1]: x=1", "x=1"),
|
||||
("x=1", "x=1"), # normal input is unmodified
|
||||
(" ", " "), # blank lines are kept intact
|
||||
],
|
||||
# Tests for the escape transformer to leave normal code alone
|
||||
escaped_noesc=[
|
||||
(" ", " "),
|
||||
("x=1", "x=1"),
|
||||
],
|
||||
# System calls
|
||||
escaped_shell=[
|
||||
("!ls", "get_ipython().system('ls')"),
|
||||
# Double-escape shell, this means to capture the output of the
|
||||
# subprocess and return it
|
||||
("!!ls", "get_ipython().getoutput('ls')"),
|
||||
],
|
||||
# Help/object info
|
||||
escaped_help=[
|
||||
("?", "get_ipython().show_usage()"),
|
||||
("?x1", "get_ipython().run_line_magic('pinfo', 'x1')"),
|
||||
("??x2", "get_ipython().run_line_magic('pinfo2', 'x2')"),
|
||||
("?a.*s", "get_ipython().run_line_magic('psearch', 'a.*s')"),
|
||||
("?%hist1", "get_ipython().run_line_magic('pinfo', '%hist1')"),
|
||||
("?%%hist2", "get_ipython().run_line_magic('pinfo', '%%hist2')"),
|
||||
("?abc = qwe", "get_ipython().run_line_magic('pinfo', 'abc')"),
|
||||
],
|
||||
end_help=[
|
||||
("x3?", "get_ipython().run_line_magic('pinfo', 'x3')"),
|
||||
("x4??", "get_ipython().run_line_magic('pinfo2', 'x4')"),
|
||||
("%hist1?", "get_ipython().run_line_magic('pinfo', '%hist1')"),
|
||||
("%hist2??", "get_ipython().run_line_magic('pinfo2', '%hist2')"),
|
||||
("%%hist3?", "get_ipython().run_line_magic('pinfo', '%%hist3')"),
|
||||
("%%hist4??", "get_ipython().run_line_magic('pinfo2', '%%hist4')"),
|
||||
("π.foo?", "get_ipython().run_line_magic('pinfo', 'π.foo')"),
|
||||
("f*?", "get_ipython().run_line_magic('psearch', 'f*')"),
|
||||
("ax.*aspe*?", "get_ipython().run_line_magic('psearch', 'ax.*aspe*')"),
|
||||
("a = abc?", "get_ipython().run_line_magic('pinfo', 'abc')"),
|
||||
("a = abc.qe??", "get_ipython().run_line_magic('pinfo2', 'abc.qe')"),
|
||||
("a = *.items?", "get_ipython().run_line_magic('psearch', '*.items')"),
|
||||
("plot(a?", "get_ipython().run_line_magic('pinfo', 'a')"),
|
||||
("a*2 #comment?", "a*2 #comment?"),
|
||||
],
|
||||
# Explicit magic calls
|
||||
escaped_magic=[
|
||||
("%cd", "get_ipython().run_line_magic('cd', '')"),
|
||||
("%cd /home", "get_ipython().run_line_magic('cd', '/home')"),
|
||||
# Backslashes need to be escaped.
|
||||
("%cd C:\\User", "get_ipython().run_line_magic('cd', 'C:\\\\User')"),
|
||||
(" %magic", " get_ipython().run_line_magic('magic', '')"),
|
||||
],
|
||||
# Quoting with separate arguments
|
||||
escaped_quote=[
|
||||
(",f", 'f("")'),
|
||||
(",f x", 'f("x")'),
|
||||
(" ,f y", ' f("y")'),
|
||||
(",f a b", 'f("a", "b")'),
|
||||
],
|
||||
# Quoting with single argument
|
||||
escaped_quote2=[
|
||||
(";f", 'f("")'),
|
||||
(";f x", 'f("x")'),
|
||||
(" ;f y", ' f("y")'),
|
||||
(";f a b", 'f("a b")'),
|
||||
],
|
||||
# Simply apply parens
|
||||
escaped_paren=[
|
||||
("/f", "f()"),
|
||||
("/f x", "f(x)"),
|
||||
(" /f y", " f(y)"),
|
||||
("/f a b", "f(a, b)"),
|
||||
],
|
||||
# Check that we transform prompts before other transforms
|
||||
mixed=[
|
||||
("In [1]: %lsmagic", "get_ipython().run_line_magic('lsmagic', '')"),
|
||||
(">>> %lsmagic", "get_ipython().run_line_magic('lsmagic', '')"),
|
||||
("In [2]: !ls", "get_ipython().system('ls')"),
|
||||
("In [3]: abs?", "get_ipython().run_line_magic('pinfo', 'abs')"),
|
||||
("In [4]: b = %who", "b = get_ipython().run_line_magic('who', '')"),
|
||||
],
|
||||
)
|
||||
|
||||
# multiline syntax examples. Each of these should be a list of lists, with
|
||||
# each entry itself having pairs of raw/transformed input. The union (with
|
||||
# '\n'.join() of the transformed inputs is what the splitter should produce
|
||||
# when fed the raw lines one at a time via push.
|
||||
syntax_ml = \
|
||||
dict(classic_prompt =
|
||||
[ [('>>> for i in range(10):','for i in range(10):'),
|
||||
('... print i',' print i'),
|
||||
('... ', ''),
|
||||
],
|
||||
[('>>> a="""','a="""'),
|
||||
('... 123"""','123"""'),
|
||||
],
|
||||
[('a="""','a="""'),
|
||||
('... 123','123'),
|
||||
('... 456"""','456"""'),
|
||||
],
|
||||
[('a="""','a="""'),
|
||||
('>>> 123','123'),
|
||||
('... 456"""','456"""'),
|
||||
],
|
||||
[('a="""','a="""'),
|
||||
('123','123'),
|
||||
('... 456"""','... 456"""'),
|
||||
],
|
||||
[('....__class__','....__class__'),
|
||||
],
|
||||
[('a=5', 'a=5'),
|
||||
('...', ''),
|
||||
],
|
||||
[('>>> def f(x):', 'def f(x):'),
|
||||
('...', ''),
|
||||
('... return x', ' return x'),
|
||||
],
|
||||
[('board = """....', 'board = """....'),
|
||||
('....', '....'),
|
||||
('...."""', '...."""'),
|
||||
],
|
||||
],
|
||||
|
||||
ipy_prompt =
|
||||
[ [('In [24]: for i in range(10):','for i in range(10):'),
|
||||
(' ....: print i',' print i'),
|
||||
(' ....: ', ''),
|
||||
],
|
||||
[('In [24]: for i in range(10):','for i in range(10):'),
|
||||
# Qt console prompts expand with spaces, not dots
|
||||
(' ...: print i',' print i'),
|
||||
(' ...: ', ''),
|
||||
],
|
||||
[('In [24]: for i in range(10):','for i in range(10):'),
|
||||
# Sometimes whitespace preceding '...' has been removed
|
||||
('...: print i',' print i'),
|
||||
('...: ', ''),
|
||||
],
|
||||
[('In [24]: for i in range(10):','for i in range(10):'),
|
||||
# Space after last continuation prompt has been removed (issue #6674)
|
||||
('...: print i',' print i'),
|
||||
('...:', ''),
|
||||
],
|
||||
[('In [2]: a="""','a="""'),
|
||||
(' ...: 123"""','123"""'),
|
||||
],
|
||||
[('a="""','a="""'),
|
||||
(' ...: 123','123'),
|
||||
(' ...: 456"""','456"""'),
|
||||
],
|
||||
[('a="""','a="""'),
|
||||
('In [1]: 123','123'),
|
||||
(' ...: 456"""','456"""'),
|
||||
],
|
||||
[('a="""','a="""'),
|
||||
('123','123'),
|
||||
(' ...: 456"""',' ...: 456"""'),
|
||||
],
|
||||
],
|
||||
|
||||
multiline_datastructure_prompt =
|
||||
[ [('>>> a = [1,','a = [1,'),
|
||||
('... 2]','2]'),
|
||||
],
|
||||
],
|
||||
|
||||
multiline_datastructure =
|
||||
[ [('b = ("%s"', None),
|
||||
('# comment', None),
|
||||
('%foo )', 'b = ("%s"\n# comment\n%foo )'),
|
||||
],
|
||||
],
|
||||
|
||||
multiline_string =
|
||||
[ [("'''foo?", None),
|
||||
("bar'''", "'''foo?\nbar'''"),
|
||||
],
|
||||
],
|
||||
|
||||
leading_indent =
|
||||
[ [(' print "hi"','print "hi"'),
|
||||
],
|
||||
[(' for a in range(5):','for a in range(5):'),
|
||||
(' a*2',' a*2'),
|
||||
],
|
||||
[(' a="""','a="""'),
|
||||
(' 123"""','123"""'),
|
||||
],
|
||||
[('a="""','a="""'),
|
||||
(' 123"""',' 123"""'),
|
||||
],
|
||||
],
|
||||
|
||||
cellmagic =
|
||||
[ [('%%foo a', None),
|
||||
(None, "get_ipython().run_cell_magic('foo', 'a', '')"),
|
||||
],
|
||||
[('%%bar 123', None),
|
||||
('hello', None),
|
||||
(None , "get_ipython().run_cell_magic('bar', '123', 'hello')"),
|
||||
],
|
||||
[('a=5', 'a=5'),
|
||||
('%%cellmagic', '%%cellmagic'),
|
||||
],
|
||||
],
|
||||
|
||||
escaped =
|
||||
[ [('%abc def \\', None),
|
||||
('ghi', "get_ipython().run_line_magic('abc', 'def ghi')"),
|
||||
],
|
||||
[('%abc def \\', None),
|
||||
('ghi\\', None),
|
||||
(None, "get_ipython().run_line_magic('abc', 'def ghi')"),
|
||||
],
|
||||
],
|
||||
|
||||
assign_magic =
|
||||
[ [('a = %bc de \\', None),
|
||||
('fg', "a = get_ipython().run_line_magic('bc', 'de fg')"),
|
||||
],
|
||||
[('a = %bc de \\', None),
|
||||
('fg\\', None),
|
||||
(None, "a = get_ipython().run_line_magic('bc', 'de fg')"),
|
||||
],
|
||||
],
|
||||
|
||||
assign_system =
|
||||
[ [('a = !bc de \\', None),
|
||||
('fg', "a = get_ipython().getoutput('bc de fg')"),
|
||||
],
|
||||
[('a = !bc de \\', None),
|
||||
('fg\\', None),
|
||||
(None, "a = get_ipython().getoutput('bc de fg')"),
|
||||
],
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
def test_assign_system():
|
||||
tt.check_pairs(transform_and_reset(ipt.assign_from_system), syntax['assign_system'])
|
||||
|
||||
def test_assign_magic():
|
||||
tt.check_pairs(transform_and_reset(ipt.assign_from_magic), syntax['assign_magic'])
|
||||
|
||||
def test_classic_prompt():
|
||||
tt.check_pairs(transform_and_reset(ipt.classic_prompt), syntax['classic_prompt'])
|
||||
for example in syntax_ml['classic_prompt']:
|
||||
transform_checker(example, ipt.classic_prompt)
|
||||
for example in syntax_ml['multiline_datastructure_prompt']:
|
||||
transform_checker(example, ipt.classic_prompt)
|
||||
|
||||
# Check that we don't transform the second line if the first is obviously
|
||||
# IPython syntax
|
||||
transform_checker([
|
||||
('%foo', '%foo'),
|
||||
('>>> bar', '>>> bar'),
|
||||
], ipt.classic_prompt)
|
||||
|
||||
|
||||
def test_ipy_prompt():
|
||||
tt.check_pairs(transform_and_reset(ipt.ipy_prompt), syntax['ipy_prompt'])
|
||||
for example in syntax_ml['ipy_prompt']:
|
||||
transform_checker(example, ipt.ipy_prompt)
|
||||
|
||||
# Check that we don't transform the second line if we're inside a cell magic
|
||||
transform_checker([
|
||||
('%%foo', '%%foo'),
|
||||
('In [1]: bar', 'In [1]: bar'),
|
||||
], ipt.ipy_prompt)
|
||||
|
||||
def test_assemble_logical_lines():
|
||||
tests = \
|
||||
[ [("a = \\", None),
|
||||
("123", "a = 123"),
|
||||
],
|
||||
[("a = \\", None), # Test resetting when within a multi-line string
|
||||
("12 *\\", None),
|
||||
(None, "a = 12 *"),
|
||||
],
|
||||
[("# foo\\", "# foo\\"), # Comments can't be continued like this
|
||||
],
|
||||
]
|
||||
for example in tests:
|
||||
transform_checker(example, ipt.assemble_logical_lines)
|
||||
|
||||
def test_assemble_python_lines():
|
||||
tests = \
|
||||
[ [("a = '''", None),
|
||||
("abc'''", "a = '''\nabc'''"),
|
||||
],
|
||||
[("a = '''", None), # Test resetting when within a multi-line string
|
||||
("def", None),
|
||||
(None, "a = '''\ndef"),
|
||||
],
|
||||
[("a = [1,", None),
|
||||
("2]", "a = [1,\n2]"),
|
||||
],
|
||||
[("a = [1,", None), # Test resetting when within a multi-line string
|
||||
("2,", None),
|
||||
(None, "a = [1,\n2,"),
|
||||
],
|
||||
[("a = '''", None), # Test line continuation within a multi-line string
|
||||
("abc\\", None),
|
||||
("def", None),
|
||||
("'''", "a = '''\nabc\\\ndef\n'''"),
|
||||
],
|
||||
] + syntax_ml['multiline_datastructure']
|
||||
for example in tests:
|
||||
transform_checker(example, ipt.assemble_python_lines)
|
||||
|
||||
|
||||
def test_help_end():
|
||||
tt.check_pairs(transform_and_reset(ipt.help_end), syntax['end_help'])
|
||||
|
||||
def test_escaped_noesc():
|
||||
tt.check_pairs(transform_and_reset(ipt.escaped_commands), syntax['escaped_noesc'])
|
||||
|
||||
|
||||
def test_escaped_shell():
|
||||
tt.check_pairs(transform_and_reset(ipt.escaped_commands), syntax['escaped_shell'])
|
||||
|
||||
|
||||
def test_escaped_help():
|
||||
tt.check_pairs(transform_and_reset(ipt.escaped_commands), syntax['escaped_help'])
|
||||
|
||||
|
||||
def test_escaped_magic():
|
||||
tt.check_pairs(transform_and_reset(ipt.escaped_commands), syntax['escaped_magic'])
|
||||
|
||||
|
||||
def test_escaped_quote():
|
||||
tt.check_pairs(transform_and_reset(ipt.escaped_commands), syntax['escaped_quote'])
|
||||
|
||||
|
||||
def test_escaped_quote2():
|
||||
tt.check_pairs(transform_and_reset(ipt.escaped_commands), syntax['escaped_quote2'])
|
||||
|
||||
|
||||
def test_escaped_paren():
|
||||
tt.check_pairs(transform_and_reset(ipt.escaped_commands), syntax['escaped_paren'])
|
||||
|
||||
|
||||
def test_cellmagic():
|
||||
for example in syntax_ml['cellmagic']:
|
||||
transform_checker(example, ipt.cellmagic)
|
||||
|
||||
line_example = [('%%bar 123', None),
|
||||
('hello', None),
|
||||
('' , "get_ipython().run_cell_magic('bar', '123', 'hello')"),
|
||||
]
|
||||
transform_checker(line_example, ipt.cellmagic, end_on_blank_line=True)
|
||||
|
||||
def test_has_comment():
|
||||
tests = [('text', False),
|
||||
('text #comment', True),
|
||||
('text #comment\n', True),
|
||||
('#comment', True),
|
||||
('#comment\n', True),
|
||||
('a = "#string"', False),
|
||||
('a = "#string" # comment', True),
|
||||
('a #comment not "string"', True),
|
||||
]
|
||||
tt.check_pairs(ipt.has_comment, tests)
|
||||
|
||||
@ipt.TokenInputTransformer.wrap
|
||||
def decistmt(tokens):
|
||||
"""Substitute Decimals for floats in a string of statements.
|
||||
|
||||
Based on an example from the tokenize module docs.
|
||||
"""
|
||||
result = []
|
||||
for toknum, tokval, _, _, _ in tokens:
|
||||
if toknum == tokenize.NUMBER and '.' in tokval: # replace NUMBER tokens
|
||||
yield from [
|
||||
(tokenize.NAME, 'Decimal'),
|
||||
(tokenize.OP, '('),
|
||||
(tokenize.STRING, repr(tokval)),
|
||||
(tokenize.OP, ')')
|
||||
]
|
||||
else:
|
||||
yield (toknum, tokval)
|
||||
|
||||
|
||||
|
||||
def test_token_input_transformer():
|
||||
tests = [('1.2', "Decimal ('1.2')"),
|
||||
('"1.2"', '"1.2"'),
|
||||
]
|
||||
tt.check_pairs(transform_and_reset(decistmt), tests)
|
||||
ml_tests = \
|
||||
[ [("a = 1.2; b = '''x", None),
|
||||
("y'''", "a =Decimal ('1.2');b ='''x\ny'''"),
|
||||
],
|
||||
[("a = [1.2,", None),
|
||||
("3]", "a =[Decimal ('1.2'),\n3 ]"),
|
||||
],
|
||||
[("a = '''foo", None), # Test resetting when within a multi-line string
|
||||
("bar", None),
|
||||
(None, "a = '''foo\nbar"),
|
||||
],
|
||||
]
|
||||
for example in ml_tests:
|
||||
transform_checker(example, decistmt)
|
@ -0,0 +1,443 @@
|
||||
"""Tests for the token-based transformers in IPython.core.inputtransformer2
|
||||
|
||||
Line-based transformers are the simpler ones; token-based transformers are
|
||||
more complex. See test_inputtransformer2_line for tests for line-based
|
||||
transformations.
|
||||
"""
|
||||
import platform
|
||||
import string
|
||||
import sys
|
||||
from textwrap import dedent
|
||||
|
||||
import pytest
|
||||
|
||||
from IPython.core import inputtransformer2 as ipt2
|
||||
from IPython.core.inputtransformer2 import _find_assign_op, make_tokens_by_line
|
||||
|
||||
MULTILINE_MAGIC = (
|
||||
"""\
|
||||
a = f()
|
||||
%foo \\
|
||||
bar
|
||||
g()
|
||||
""".splitlines(
|
||||
keepends=True
|
||||
),
|
||||
(2, 0),
|
||||
"""\
|
||||
a = f()
|
||||
get_ipython().run_line_magic('foo', ' bar')
|
||||
g()
|
||||
""".splitlines(
|
||||
keepends=True
|
||||
),
|
||||
)
|
||||
|
||||
INDENTED_MAGIC = (
|
||||
"""\
|
||||
for a in range(5):
|
||||
%ls
|
||||
""".splitlines(
|
||||
keepends=True
|
||||
),
|
||||
(2, 4),
|
||||
"""\
|
||||
for a in range(5):
|
||||
get_ipython().run_line_magic('ls', '')
|
||||
""".splitlines(
|
||||
keepends=True
|
||||
),
|
||||
)
|
||||
|
||||
CRLF_MAGIC = (
|
||||
["a = f()\n", "%ls\r\n", "g()\n"],
|
||||
(2, 0),
|
||||
["a = f()\n", "get_ipython().run_line_magic('ls', '')\n", "g()\n"],
|
||||
)
|
||||
|
||||
MULTILINE_MAGIC_ASSIGN = (
|
||||
"""\
|
||||
a = f()
|
||||
b = %foo \\
|
||||
bar
|
||||
g()
|
||||
""".splitlines(
|
||||
keepends=True
|
||||
),
|
||||
(2, 4),
|
||||
"""\
|
||||
a = f()
|
||||
b = get_ipython().run_line_magic('foo', ' bar')
|
||||
g()
|
||||
""".splitlines(
|
||||
keepends=True
|
||||
),
|
||||
)
|
||||
|
||||
MULTILINE_SYSTEM_ASSIGN = ("""\
|
||||
a = f()
|
||||
b = !foo \\
|
||||
bar
|
||||
g()
|
||||
""".splitlines(keepends=True), (2, 4), """\
|
||||
a = f()
|
||||
b = get_ipython().getoutput('foo bar')
|
||||
g()
|
||||
""".splitlines(keepends=True))
|
||||
|
||||
#####
|
||||
|
||||
MULTILINE_SYSTEM_ASSIGN_AFTER_DEDENT = (
|
||||
"""\
|
||||
def test():
|
||||
for i in range(1):
|
||||
print(i)
|
||||
res =! ls
|
||||
""".splitlines(
|
||||
keepends=True
|
||||
),
|
||||
(4, 7),
|
||||
"""\
|
||||
def test():
|
||||
for i in range(1):
|
||||
print(i)
|
||||
res =get_ipython().getoutput(\' ls\')
|
||||
""".splitlines(
|
||||
keepends=True
|
||||
),
|
||||
)
|
||||
|
||||
######
|
||||
|
||||
AUTOCALL_QUOTE = ([",f 1 2 3\n"], (1, 0), ['f("1", "2", "3")\n'])
|
||||
|
||||
AUTOCALL_QUOTE2 = ([";f 1 2 3\n"], (1, 0), ['f("1 2 3")\n'])
|
||||
|
||||
AUTOCALL_PAREN = (["/f 1 2 3\n"], (1, 0), ["f(1, 2, 3)\n"])
|
||||
|
||||
SIMPLE_HELP = (["foo?\n"], (1, 0), ["get_ipython().run_line_magic('pinfo', 'foo')\n"])
|
||||
|
||||
DETAILED_HELP = (
|
||||
["foo??\n"],
|
||||
(1, 0),
|
||||
["get_ipython().run_line_magic('pinfo2', 'foo')\n"],
|
||||
)
|
||||
|
||||
MAGIC_HELP = (["%foo?\n"], (1, 0), ["get_ipython().run_line_magic('pinfo', '%foo')\n"])
|
||||
|
||||
HELP_IN_EXPR = (
|
||||
["a = b + c?\n"],
|
||||
(1, 0),
|
||||
["get_ipython().run_line_magic('pinfo', 'c')\n"],
|
||||
)
|
||||
|
||||
HELP_CONTINUED_LINE = (
|
||||
"""\
|
||||
a = \\
|
||||
zip?
|
||||
""".splitlines(
|
||||
keepends=True
|
||||
),
|
||||
(1, 0),
|
||||
[r"get_ipython().run_line_magic('pinfo', 'zip')" + "\n"],
|
||||
)
|
||||
|
||||
HELP_MULTILINE = (
|
||||
"""\
|
||||
(a,
|
||||
b) = zip?
|
||||
""".splitlines(
|
||||
keepends=True
|
||||
),
|
||||
(1, 0),
|
||||
[r"get_ipython().run_line_magic('pinfo', 'zip')" + "\n"],
|
||||
)
|
||||
|
||||
HELP_UNICODE = (
|
||||
["π.foo?\n"],
|
||||
(1, 0),
|
||||
["get_ipython().run_line_magic('pinfo', 'π.foo')\n"],
|
||||
)
|
||||
|
||||
|
||||
def null_cleanup_transformer(lines):
|
||||
"""
|
||||
A cleanup transform that returns an empty list.
|
||||
"""
|
||||
return []
|
||||
|
||||
|
||||
def test_check_make_token_by_line_never_ends_empty():
|
||||
"""
|
||||
Check that not sequence of single or double characters ends up leading to en empty list of tokens
|
||||
"""
|
||||
from string import printable
|
||||
|
||||
for c in printable:
|
||||
assert make_tokens_by_line(c)[-1] != []
|
||||
for k in printable:
|
||||
assert make_tokens_by_line(c + k)[-1] != []
|
||||
|
||||
|
||||
def check_find(transformer, case, match=True):
|
||||
sample, expected_start, _ = case
|
||||
tbl = make_tokens_by_line(sample)
|
||||
res = transformer.find(tbl)
|
||||
if match:
|
||||
# start_line is stored 0-indexed, expected values are 1-indexed
|
||||
assert (res.start_line + 1, res.start_col) == expected_start
|
||||
return res
|
||||
else:
|
||||
assert res is None
|
||||
|
||||
|
||||
def check_transform(transformer_cls, case):
|
||||
lines, start, expected = case
|
||||
transformer = transformer_cls(start)
|
||||
assert transformer.transform(lines) == expected
|
||||
|
||||
|
||||
def test_continued_line():
|
||||
lines = MULTILINE_MAGIC_ASSIGN[0]
|
||||
assert ipt2.find_end_of_continued_line(lines, 1) == 2
|
||||
|
||||
assert ipt2.assemble_continued_line(lines, (1, 5), 2) == "foo bar"
|
||||
|
||||
|
||||
def test_find_assign_magic():
|
||||
check_find(ipt2.MagicAssign, MULTILINE_MAGIC_ASSIGN)
|
||||
check_find(ipt2.MagicAssign, MULTILINE_SYSTEM_ASSIGN, match=False)
|
||||
check_find(ipt2.MagicAssign, MULTILINE_SYSTEM_ASSIGN_AFTER_DEDENT, match=False)
|
||||
|
||||
|
||||
def test_transform_assign_magic():
|
||||
check_transform(ipt2.MagicAssign, MULTILINE_MAGIC_ASSIGN)
|
||||
|
||||
|
||||
def test_find_assign_system():
|
||||
check_find(ipt2.SystemAssign, MULTILINE_SYSTEM_ASSIGN)
|
||||
check_find(ipt2.SystemAssign, MULTILINE_SYSTEM_ASSIGN_AFTER_DEDENT)
|
||||
check_find(ipt2.SystemAssign, (["a = !ls\n"], (1, 5), None))
|
||||
check_find(ipt2.SystemAssign, (["a=!ls\n"], (1, 2), None))
|
||||
check_find(ipt2.SystemAssign, MULTILINE_MAGIC_ASSIGN, match=False)
|
||||
|
||||
|
||||
def test_transform_assign_system():
|
||||
check_transform(ipt2.SystemAssign, MULTILINE_SYSTEM_ASSIGN)
|
||||
check_transform(ipt2.SystemAssign, MULTILINE_SYSTEM_ASSIGN_AFTER_DEDENT)
|
||||
|
||||
|
||||
def test_find_magic_escape():
|
||||
check_find(ipt2.EscapedCommand, MULTILINE_MAGIC)
|
||||
check_find(ipt2.EscapedCommand, INDENTED_MAGIC)
|
||||
check_find(ipt2.EscapedCommand, MULTILINE_MAGIC_ASSIGN, match=False)
|
||||
|
||||
|
||||
def test_transform_magic_escape():
|
||||
check_transform(ipt2.EscapedCommand, MULTILINE_MAGIC)
|
||||
check_transform(ipt2.EscapedCommand, INDENTED_MAGIC)
|
||||
check_transform(ipt2.EscapedCommand, CRLF_MAGIC)
|
||||
|
||||
|
||||
def test_find_autocalls():
|
||||
for case in [AUTOCALL_QUOTE, AUTOCALL_QUOTE2, AUTOCALL_PAREN]:
|
||||
print("Testing %r" % case[0])
|
||||
check_find(ipt2.EscapedCommand, case)
|
||||
|
||||
|
||||
def test_transform_autocall():
|
||||
for case in [AUTOCALL_QUOTE, AUTOCALL_QUOTE2, AUTOCALL_PAREN]:
|
||||
print("Testing %r" % case[0])
|
||||
check_transform(ipt2.EscapedCommand, case)
|
||||
|
||||
|
||||
def test_find_help():
|
||||
for case in [SIMPLE_HELP, DETAILED_HELP, MAGIC_HELP, HELP_IN_EXPR]:
|
||||
check_find(ipt2.HelpEnd, case)
|
||||
|
||||
tf = check_find(ipt2.HelpEnd, HELP_CONTINUED_LINE)
|
||||
assert tf.q_line == 1
|
||||
assert tf.q_col == 3
|
||||
|
||||
tf = check_find(ipt2.HelpEnd, HELP_MULTILINE)
|
||||
assert tf.q_line == 1
|
||||
assert tf.q_col == 8
|
||||
|
||||
# ? in a comment does not trigger help
|
||||
check_find(ipt2.HelpEnd, (["foo # bar?\n"], None, None), match=False)
|
||||
# Nor in a string
|
||||
check_find(ipt2.HelpEnd, (["foo = '''bar?\n"], None, None), match=False)
|
||||
|
||||
|
||||
def test_transform_help():
|
||||
tf = ipt2.HelpEnd((1, 0), (1, 9))
|
||||
assert tf.transform(HELP_IN_EXPR[0]) == HELP_IN_EXPR[2]
|
||||
|
||||
tf = ipt2.HelpEnd((1, 0), (2, 3))
|
||||
assert tf.transform(HELP_CONTINUED_LINE[0]) == HELP_CONTINUED_LINE[2]
|
||||
|
||||
tf = ipt2.HelpEnd((1, 0), (2, 8))
|
||||
assert tf.transform(HELP_MULTILINE[0]) == HELP_MULTILINE[2]
|
||||
|
||||
tf = ipt2.HelpEnd((1, 0), (1, 0))
|
||||
assert tf.transform(HELP_UNICODE[0]) == HELP_UNICODE[2]
|
||||
|
||||
|
||||
def test_find_assign_op_dedent():
|
||||
"""
|
||||
be careful that empty token like dedent are not counted as parens
|
||||
"""
|
||||
|
||||
class Tk:
|
||||
def __init__(self, s):
|
||||
self.string = s
|
||||
|
||||
assert _find_assign_op([Tk(s) for s in ("", "a", "=", "b")]) == 2
|
||||
assert (
|
||||
_find_assign_op([Tk(s) for s in ("", "(", "a", "=", "b", ")", "=", "5")]) == 6
|
||||
)
|
||||
|
||||
|
||||
examples = [
|
||||
pytest.param("a = 1", "complete", None),
|
||||
pytest.param("for a in range(5):", "incomplete", 4),
|
||||
pytest.param("for a in range(5):\n if a > 0:", "incomplete", 8),
|
||||
pytest.param("raise = 2", "invalid", None),
|
||||
pytest.param("a = [1,\n2,", "incomplete", 0),
|
||||
pytest.param("(\n))", "incomplete", 0),
|
||||
pytest.param("\\\r\n", "incomplete", 0),
|
||||
pytest.param("a = '''\n hi", "incomplete", 3),
|
||||
pytest.param("def a():\n x=1\n global x", "invalid", None),
|
||||
pytest.param(
|
||||
"a \\ ",
|
||||
"invalid",
|
||||
None,
|
||||
marks=pytest.mark.xfail(
|
||||
reason="Bug in python 3.9.8 – bpo 45738",
|
||||
condition=sys.version_info
|
||||
in [(3, 9, 8, "final", 0), (3, 11, 0, "alpha", 2)],
|
||||
raises=SystemError,
|
||||
strict=True,
|
||||
),
|
||||
), # Nothing allowed after backslash,
|
||||
pytest.param("1\\\n+2", "complete", None),
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("code, expected, number", examples)
|
||||
def test_check_complete_param(code, expected, number):
|
||||
cc = ipt2.TransformerManager().check_complete
|
||||
assert cc(code) == (expected, number)
|
||||
|
||||
|
||||
@pytest.mark.xfail(platform.python_implementation() == "PyPy", reason="fail on pypy")
|
||||
@pytest.mark.xfail(
|
||||
reason="Bug in python 3.9.8 – bpo 45738",
|
||||
condition=sys.version_info in [(3, 9, 8, "final", 0), (3, 11, 0, "alpha", 2)],
|
||||
raises=SystemError,
|
||||
strict=True,
|
||||
)
|
||||
def test_check_complete():
|
||||
cc = ipt2.TransformerManager().check_complete
|
||||
|
||||
example = dedent(
|
||||
"""
|
||||
if True:
|
||||
a=1"""
|
||||
)
|
||||
|
||||
assert cc(example) == ("incomplete", 4)
|
||||
assert cc(example + "\n") == ("complete", None)
|
||||
assert cc(example + "\n ") == ("complete", None)
|
||||
|
||||
# no need to loop on all the letters/numbers.
|
||||
short = "12abAB" + string.printable[62:]
|
||||
for c in short:
|
||||
# test does not raise:
|
||||
cc(c)
|
||||
for k in short:
|
||||
cc(c + k)
|
||||
|
||||
assert cc("def f():\n x=0\n \\\n ") == ("incomplete", 2)
|
||||
|
||||
|
||||
@pytest.mark.xfail(platform.python_implementation() == "PyPy", reason="fail on pypy")
|
||||
@pytest.mark.parametrize(
|
||||
"value, expected",
|
||||
[
|
||||
('''def foo():\n """''', ("incomplete", 4)),
|
||||
("""async with example:\n pass""", ("incomplete", 4)),
|
||||
("""async with example:\n pass\n """, ("complete", None)),
|
||||
],
|
||||
)
|
||||
def test_check_complete_II(value, expected):
|
||||
"""
|
||||
Test that multiple line strings are properly handled.
|
||||
|
||||
Separate test function for convenience
|
||||
|
||||
"""
|
||||
cc = ipt2.TransformerManager().check_complete
|
||||
assert cc(value) == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"value, expected",
|
||||
[
|
||||
(")", ("invalid", None)),
|
||||
("]", ("invalid", None)),
|
||||
("}", ("invalid", None)),
|
||||
(")(", ("invalid", None)),
|
||||
("][", ("invalid", None)),
|
||||
("}{", ("invalid", None)),
|
||||
("]()(", ("invalid", None)),
|
||||
("())(", ("invalid", None)),
|
||||
(")[](", ("invalid", None)),
|
||||
("()](", ("invalid", None)),
|
||||
],
|
||||
)
|
||||
def test_check_complete_invalidates_sunken_brackets(value, expected):
|
||||
"""
|
||||
Test that a single line with more closing brackets than the opening ones is
|
||||
interpreted as invalid
|
||||
"""
|
||||
cc = ipt2.TransformerManager().check_complete
|
||||
assert cc(value) == expected
|
||||
|
||||
|
||||
def test_null_cleanup_transformer():
|
||||
manager = ipt2.TransformerManager()
|
||||
manager.cleanup_transforms.insert(0, null_cleanup_transformer)
|
||||
assert manager.transform_cell("") == ""
|
||||
|
||||
|
||||
def test_side_effects_I():
|
||||
count = 0
|
||||
|
||||
def counter(lines):
|
||||
nonlocal count
|
||||
count += 1
|
||||
return lines
|
||||
|
||||
counter.has_side_effects = True
|
||||
|
||||
manager = ipt2.TransformerManager()
|
||||
manager.cleanup_transforms.insert(0, counter)
|
||||
assert manager.check_complete("a=1\n") == ("complete", None)
|
||||
assert count == 0
|
||||
|
||||
|
||||
def test_side_effects_II():
|
||||
count = 0
|
||||
|
||||
def counter(lines):
|
||||
nonlocal count
|
||||
count += 1
|
||||
return lines
|
||||
|
||||
counter.has_side_effects = True
|
||||
|
||||
manager = ipt2.TransformerManager()
|
||||
manager.line_transforms.insert(0, counter)
|
||||
assert manager.check_complete("b=1\n") == ("complete", None)
|
||||
assert count == 0
|
@ -0,0 +1,168 @@
|
||||
"""Tests for the line-based transformers in IPython.core.inputtransformer2
|
||||
|
||||
Line-based transformers are the simpler ones; token-based transformers are
|
||||
more complex. See test_inputtransformer2 for tests for token-based transformers.
|
||||
"""
|
||||
import pytest
|
||||
|
||||
from IPython.core import inputtransformer2 as ipt2
|
||||
|
||||
CELL_MAGIC = ("""\
|
||||
%%foo arg
|
||||
body 1
|
||||
body 2
|
||||
""", """\
|
||||
get_ipython().run_cell_magic('foo', 'arg', 'body 1\\nbody 2\\n')
|
||||
""")
|
||||
|
||||
def test_cell_magic():
|
||||
for sample, expected in [CELL_MAGIC]:
|
||||
assert ipt2.cell_magic(sample.splitlines(keepends=True)) == expected.splitlines(
|
||||
keepends=True
|
||||
)
|
||||
|
||||
CLASSIC_PROMPT = ("""\
|
||||
>>> for a in range(5):
|
||||
... print(a)
|
||||
""", """\
|
||||
for a in range(5):
|
||||
print(a)
|
||||
""")
|
||||
|
||||
CLASSIC_PROMPT_L2 = ("""\
|
||||
for a in range(5):
|
||||
... print(a)
|
||||
... print(a ** 2)
|
||||
""", """\
|
||||
for a in range(5):
|
||||
print(a)
|
||||
print(a ** 2)
|
||||
""")
|
||||
|
||||
def test_classic_prompt():
|
||||
for sample, expected in [CLASSIC_PROMPT, CLASSIC_PROMPT_L2]:
|
||||
assert ipt2.classic_prompt(
|
||||
sample.splitlines(keepends=True)
|
||||
) == expected.splitlines(keepends=True)
|
||||
|
||||
IPYTHON_PROMPT = ("""\
|
||||
In [1]: for a in range(5):
|
||||
...: print(a)
|
||||
""", """\
|
||||
for a in range(5):
|
||||
print(a)
|
||||
""")
|
||||
|
||||
IPYTHON_PROMPT_L2 = ("""\
|
||||
for a in range(5):
|
||||
...: print(a)
|
||||
...: print(a ** 2)
|
||||
""", """\
|
||||
for a in range(5):
|
||||
print(a)
|
||||
print(a ** 2)
|
||||
""")
|
||||
|
||||
|
||||
IPYTHON_PROMPT_VI_INS = (
|
||||
"""\
|
||||
[ins] In [11]: def a():
|
||||
...: 123
|
||||
...:
|
||||
...: 123
|
||||
""",
|
||||
"""\
|
||||
def a():
|
||||
123
|
||||
|
||||
123
|
||||
""",
|
||||
)
|
||||
|
||||
IPYTHON_PROMPT_VI_NAV = (
|
||||
"""\
|
||||
[nav] In [11]: def a():
|
||||
...: 123
|
||||
...:
|
||||
...: 123
|
||||
""",
|
||||
"""\
|
||||
def a():
|
||||
123
|
||||
|
||||
123
|
||||
""",
|
||||
)
|
||||
|
||||
|
||||
def test_ipython_prompt():
|
||||
for sample, expected in [
|
||||
IPYTHON_PROMPT,
|
||||
IPYTHON_PROMPT_L2,
|
||||
IPYTHON_PROMPT_VI_INS,
|
||||
IPYTHON_PROMPT_VI_NAV,
|
||||
]:
|
||||
assert ipt2.ipython_prompt(
|
||||
sample.splitlines(keepends=True)
|
||||
) == expected.splitlines(keepends=True)
|
||||
|
||||
|
||||
INDENT_SPACES = ("""\
|
||||
if True:
|
||||
a = 3
|
||||
""", """\
|
||||
if True:
|
||||
a = 3
|
||||
""")
|
||||
|
||||
INDENT_TABS = ("""\
|
||||
\tif True:
|
||||
\t\tb = 4
|
||||
""", """\
|
||||
if True:
|
||||
\tb = 4
|
||||
""")
|
||||
|
||||
def test_leading_indent():
|
||||
for sample, expected in [INDENT_SPACES, INDENT_TABS]:
|
||||
assert ipt2.leading_indent(
|
||||
sample.splitlines(keepends=True)
|
||||
) == expected.splitlines(keepends=True)
|
||||
|
||||
LEADING_EMPTY_LINES = ("""\
|
||||
\t
|
||||
|
||||
if True:
|
||||
a = 3
|
||||
|
||||
b = 4
|
||||
""", """\
|
||||
if True:
|
||||
a = 3
|
||||
|
||||
b = 4
|
||||
""")
|
||||
|
||||
ONLY_EMPTY_LINES = ("""\
|
||||
\t
|
||||
|
||||
""", """\
|
||||
\t
|
||||
|
||||
""")
|
||||
|
||||
def test_leading_empty_lines():
|
||||
for sample, expected in [LEADING_EMPTY_LINES, ONLY_EMPTY_LINES]:
|
||||
assert ipt2.leading_empty_lines(
|
||||
sample.splitlines(keepends=True)
|
||||
) == expected.splitlines(keepends=True)
|
||||
|
||||
CRLF_MAGIC = ([
|
||||
"%%ls\r\n"
|
||||
], [
|
||||
"get_ipython().run_cell_magic('ls', '', '')\n"
|
||||
])
|
||||
|
||||
def test_crlf_magic():
|
||||
for sample, expected in [CRLF_MAGIC]:
|
||||
assert ipt2.cell_magic(sample) == expected
|
1100
.venv/Lib/site-packages/IPython/core/tests/test_interactiveshell.py
Normal file
1100
.venv/Lib/site-packages/IPython/core/tests/test_interactiveshell.py
Normal file
File diff suppressed because it is too large
Load Diff
250
.venv/Lib/site-packages/IPython/core/tests/test_iplib.py
Normal file
250
.venv/Lib/site-packages/IPython/core/tests/test_iplib.py
Normal file
@ -0,0 +1,250 @@
|
||||
"""Tests for the key interactiveshell module, where the main ipython class is defined.
|
||||
"""
|
||||
#-----------------------------------------------------------------------------
|
||||
# Module imports
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
# third party
|
||||
import pytest
|
||||
|
||||
# our own packages
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Test functions
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
def test_reset():
|
||||
"""reset must clear most namespaces."""
|
||||
|
||||
# Check that reset runs without error
|
||||
ip.reset()
|
||||
|
||||
# Once we've reset it (to clear of any junk that might have been there from
|
||||
# other tests, we can count how many variables are in the user's namespace
|
||||
nvars_user_ns = len(ip.user_ns)
|
||||
nvars_hidden = len(ip.user_ns_hidden)
|
||||
|
||||
# Now add a few variables to user_ns, and check that reset clears them
|
||||
ip.user_ns['x'] = 1
|
||||
ip.user_ns['y'] = 1
|
||||
ip.reset()
|
||||
|
||||
# Finally, check that all namespaces have only as many variables as we
|
||||
# expect to find in them:
|
||||
assert len(ip.user_ns) == nvars_user_ns
|
||||
assert len(ip.user_ns_hidden) == nvars_hidden
|
||||
|
||||
|
||||
# Tests for reporting of exceptions in various modes, handling of SystemExit,
|
||||
# and %tb functionality. This is really a mix of testing ultraTB and interactiveshell.
|
||||
|
||||
def doctest_tb_plain():
|
||||
"""
|
||||
In [18]: xmode plain
|
||||
Exception reporting mode: Plain
|
||||
|
||||
In [19]: run simpleerr.py
|
||||
Traceback (most recent call last):
|
||||
File ...:... in <module>
|
||||
bar(mode)
|
||||
File ...:... in bar
|
||||
div0()
|
||||
File ...:... in div0
|
||||
x/y
|
||||
ZeroDivisionError: ...
|
||||
"""
|
||||
|
||||
|
||||
def doctest_tb_context():
|
||||
"""
|
||||
In [3]: xmode context
|
||||
Exception reporting mode: Context
|
||||
|
||||
In [4]: run simpleerr.py
|
||||
---------------------------------------------------------------------------
|
||||
ZeroDivisionError Traceback (most recent call last)
|
||||
<BLANKLINE>
|
||||
... in <module>
|
||||
30 except IndexError:
|
||||
31 mode = 'div'
|
||||
---> 33 bar(mode)
|
||||
<BLANKLINE>
|
||||
... in bar(mode)
|
||||
15 "bar"
|
||||
16 if mode=='div':
|
||||
---> 17 div0()
|
||||
18 elif mode=='exit':
|
||||
19 try:
|
||||
<BLANKLINE>
|
||||
... in div0()
|
||||
6 x = 1
|
||||
7 y = 0
|
||||
----> 8 x/y
|
||||
<BLANKLINE>
|
||||
ZeroDivisionError: ..."""
|
||||
|
||||
|
||||
def doctest_tb_verbose():
|
||||
"""
|
||||
In [5]: xmode verbose
|
||||
Exception reporting mode: Verbose
|
||||
|
||||
In [6]: run simpleerr.py
|
||||
---------------------------------------------------------------------------
|
||||
ZeroDivisionError Traceback (most recent call last)
|
||||
<BLANKLINE>
|
||||
... in <module>
|
||||
30 except IndexError:
|
||||
31 mode = 'div'
|
||||
---> 33 bar(mode)
|
||||
mode = 'div'
|
||||
<BLANKLINE>
|
||||
... in bar(mode='div')
|
||||
15 "bar"
|
||||
16 if mode=='div':
|
||||
---> 17 div0()
|
||||
18 elif mode=='exit':
|
||||
19 try:
|
||||
<BLANKLINE>
|
||||
... in div0()
|
||||
6 x = 1
|
||||
7 y = 0
|
||||
----> 8 x/y
|
||||
x = 1
|
||||
y = 0
|
||||
<BLANKLINE>
|
||||
ZeroDivisionError: ...
|
||||
"""
|
||||
|
||||
|
||||
def doctest_tb_sysexit():
|
||||
"""
|
||||
In [17]: %xmode plain
|
||||
Exception reporting mode: Plain
|
||||
|
||||
In [18]: %run simpleerr.py exit
|
||||
An exception has occurred, use %tb to see the full traceback.
|
||||
SystemExit: (1, 'Mode = exit')
|
||||
|
||||
In [19]: %run simpleerr.py exit 2
|
||||
An exception has occurred, use %tb to see the full traceback.
|
||||
SystemExit: (2, 'Mode = exit')
|
||||
|
||||
In [20]: %tb
|
||||
Traceback (most recent call last):
|
||||
File ...:... in execfile
|
||||
exec(compiler(f.read(), fname, "exec"), glob, loc)
|
||||
File ...:... in <module>
|
||||
bar(mode)
|
||||
File ...:... in bar
|
||||
sysexit(stat, mode)
|
||||
File ...:... in sysexit
|
||||
raise SystemExit(stat, f"Mode = {mode}")
|
||||
SystemExit: (2, 'Mode = exit')
|
||||
|
||||
In [21]: %xmode context
|
||||
Exception reporting mode: Context
|
||||
|
||||
In [22]: %tb
|
||||
---------------------------------------------------------------------------
|
||||
SystemExit Traceback (most recent call last)
|
||||
File ..., in execfile(fname, glob, loc, compiler)
|
||||
... with open(fname, "rb") as f:
|
||||
... compiler = compiler or compile
|
||||
---> ... exec(compiler(f.read(), fname, "exec"), glob, loc)
|
||||
...<module>
|
||||
30 except IndexError:
|
||||
31 mode = 'div'
|
||||
---> 33 bar(mode)
|
||||
<BLANKLINE>
|
||||
...bar(mode)
|
||||
21 except:
|
||||
22 stat = 1
|
||||
---> 23 sysexit(stat, mode)
|
||||
24 else:
|
||||
25 raise ValueError('Unknown mode')
|
||||
<BLANKLINE>
|
||||
...sysexit(stat, mode)
|
||||
10 def sysexit(stat, mode):
|
||||
---> 11 raise SystemExit(stat, f"Mode = {mode}")
|
||||
<BLANKLINE>
|
||||
SystemExit: (2, 'Mode = exit')
|
||||
"""
|
||||
|
||||
|
||||
def doctest_tb_sysexit_verbose():
|
||||
"""
|
||||
In [18]: %run simpleerr.py exit
|
||||
An exception has occurred, use %tb to see the full traceback.
|
||||
SystemExit: (1, 'Mode = exit')
|
||||
|
||||
In [19]: %run simpleerr.py exit 2
|
||||
An exception has occurred, use %tb to see the full traceback.
|
||||
SystemExit: (2, 'Mode = exit')
|
||||
|
||||
In [23]: %xmode verbose
|
||||
Exception reporting mode: Verbose
|
||||
|
||||
In [24]: %tb
|
||||
---------------------------------------------------------------------------
|
||||
SystemExit Traceback (most recent call last)
|
||||
<BLANKLINE>
|
||||
... in <module>
|
||||
30 except IndexError:
|
||||
31 mode = 'div'
|
||||
---> 33 bar(mode)
|
||||
mode = 'exit'
|
||||
<BLANKLINE>
|
||||
... in bar(mode='exit')
|
||||
... except:
|
||||
... stat = 1
|
||||
---> ... sysexit(stat, mode)
|
||||
mode = 'exit'
|
||||
stat = 2
|
||||
... else:
|
||||
... raise ValueError('Unknown mode')
|
||||
<BLANKLINE>
|
||||
... in sysexit(stat=2, mode='exit')
|
||||
10 def sysexit(stat, mode):
|
||||
---> 11 raise SystemExit(stat, f"Mode = {mode}")
|
||||
stat = 2
|
||||
<BLANKLINE>
|
||||
SystemExit: (2, 'Mode = exit')
|
||||
"""
|
||||
|
||||
|
||||
def test_run_cell():
|
||||
import textwrap
|
||||
|
||||
ip.run_cell("a = 10\na+=1")
|
||||
ip.run_cell("assert a == 11\nassert 1")
|
||||
|
||||
assert ip.user_ns["a"] == 11
|
||||
complex = textwrap.dedent(
|
||||
"""
|
||||
if 1:
|
||||
print "hello"
|
||||
if 1:
|
||||
print "world"
|
||||
|
||||
if 2:
|
||||
print "foo"
|
||||
|
||||
if 3:
|
||||
print "bar"
|
||||
|
||||
if 4:
|
||||
print "bar"
|
||||
|
||||
"""
|
||||
)
|
||||
# Simply verifies that this kind of input is run
|
||||
ip.run_cell(complex)
|
||||
|
||||
|
||||
def test_db():
|
||||
"""Test the internal database used for variable persistence."""
|
||||
ip.db["__unittest_"] = 12
|
||||
assert ip.db["__unittest_"] == 12
|
||||
del ip.db["__unittest_"]
|
||||
assert "__unittest_" not in ip.db
|
27
.venv/Lib/site-packages/IPython/core/tests/test_logger.py
Normal file
27
.venv/Lib/site-packages/IPython/core/tests/test_logger.py
Normal file
@ -0,0 +1,27 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Test IPython.core.logger"""
|
||||
|
||||
import os.path
|
||||
|
||||
import pytest
|
||||
from tempfile import TemporaryDirectory
|
||||
|
||||
|
||||
def test_logstart_inaccessible_file():
|
||||
with pytest.raises(IOError):
|
||||
_ip.logger.logstart(logfname="/") # Opening that filename will fail.
|
||||
|
||||
try:
|
||||
_ip.run_cell("a=1") # Check it doesn't try to log this
|
||||
finally:
|
||||
_ip.logger.log_active = False # If this fails, don't let later tests fail
|
||||
|
||||
def test_logstart_unicode():
|
||||
with TemporaryDirectory() as tdir:
|
||||
logfname = os.path.join(tdir, "test_unicode.log")
|
||||
_ip.run_cell("'abc€'")
|
||||
try:
|
||||
_ip.magic("logstart -to %s" % logfname)
|
||||
_ip.run_cell("'abc€'")
|
||||
finally:
|
||||
_ip.logger.logstop()
|
1452
.venv/Lib/site-packages/IPython/core/tests/test_magic.py
Normal file
1452
.venv/Lib/site-packages/IPython/core/tests/test_magic.py
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,140 @@
|
||||
#-----------------------------------------------------------------------------
|
||||
# Copyright (C) 2010-2011, IPython Development Team.
|
||||
#
|
||||
# Distributed under the terms of the Modified BSD License.
|
||||
#
|
||||
# The full license is in the file COPYING.txt, distributed with this software.
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
import argparse
|
||||
import sys
|
||||
|
||||
from IPython.core.magic_arguments import (argument, argument_group, kwds,
|
||||
magic_arguments, parse_argstring, real_name)
|
||||
|
||||
|
||||
@magic_arguments()
|
||||
@argument('-f', '--foo', help="an argument")
|
||||
def magic_foo1(self, args):
|
||||
""" A docstring.
|
||||
"""
|
||||
return parse_argstring(magic_foo1, args)
|
||||
|
||||
|
||||
@magic_arguments()
|
||||
def magic_foo2(self, args):
|
||||
""" A docstring.
|
||||
"""
|
||||
return parse_argstring(magic_foo2, args)
|
||||
|
||||
|
||||
@magic_arguments()
|
||||
@argument('-f', '--foo', help="an argument")
|
||||
@argument_group('Group')
|
||||
@argument('-b', '--bar', help="a grouped argument")
|
||||
@argument_group('Second Group')
|
||||
@argument('-z', '--baz', help="another grouped argument")
|
||||
def magic_foo3(self, args):
|
||||
""" A docstring.
|
||||
"""
|
||||
return parse_argstring(magic_foo3, args)
|
||||
|
||||
|
||||
@magic_arguments()
|
||||
@kwds(argument_default=argparse.SUPPRESS)
|
||||
@argument('-f', '--foo', help="an argument")
|
||||
def magic_foo4(self, args):
|
||||
""" A docstring.
|
||||
"""
|
||||
return parse_argstring(magic_foo4, args)
|
||||
|
||||
|
||||
@magic_arguments('frobnicate')
|
||||
@argument('-f', '--foo', help="an argument")
|
||||
def magic_foo5(self, args):
|
||||
""" A docstring.
|
||||
"""
|
||||
return parse_argstring(magic_foo5, args)
|
||||
|
||||
|
||||
@magic_arguments()
|
||||
@argument('-f', '--foo', help="an argument")
|
||||
def magic_magic_foo(self, args):
|
||||
""" A docstring.
|
||||
"""
|
||||
return parse_argstring(magic_magic_foo, args)
|
||||
|
||||
|
||||
@magic_arguments()
|
||||
@argument('-f', '--foo', help="an argument")
|
||||
def foo(self, args):
|
||||
""" A docstring.
|
||||
"""
|
||||
return parse_argstring(foo, args)
|
||||
|
||||
|
||||
def test_magic_arguments():
|
||||
# “optional arguments” was replaced with “options” in argparse help
|
||||
# https://docs.python.org/3/whatsnew/3.10.html#argparse
|
||||
# https://bugs.python.org/issue9694
|
||||
options = "optional arguments" if sys.version_info < (3, 10) else "options"
|
||||
|
||||
assert (
|
||||
magic_foo1.__doc__
|
||||
== f"::\n\n %foo1 [-f FOO]\n\n A docstring.\n\n{options}:\n -f FOO, --foo FOO an argument\n"
|
||||
)
|
||||
assert getattr(magic_foo1, "argcmd_name", None) == None
|
||||
assert real_name(magic_foo1) == "foo1"
|
||||
assert magic_foo1(None, "") == argparse.Namespace(foo=None)
|
||||
assert hasattr(magic_foo1, "has_arguments")
|
||||
|
||||
assert magic_foo2.__doc__ == "::\n\n %foo2\n\n A docstring.\n"
|
||||
assert getattr(magic_foo2, "argcmd_name", None) == None
|
||||
assert real_name(magic_foo2) == "foo2"
|
||||
assert magic_foo2(None, "") == argparse.Namespace()
|
||||
assert hasattr(magic_foo2, "has_arguments")
|
||||
|
||||
assert (
|
||||
magic_foo3.__doc__
|
||||
== f"::\n\n %foo3 [-f FOO] [-b BAR] [-z BAZ]\n\n A docstring.\n\n{options}:\n -f FOO, --foo FOO an argument\n\nGroup:\n -b BAR, --bar BAR a grouped argument\n\nSecond Group:\n -z BAZ, --baz BAZ another grouped argument\n"
|
||||
)
|
||||
assert getattr(magic_foo3, "argcmd_name", None) == None
|
||||
assert real_name(magic_foo3) == "foo3"
|
||||
assert magic_foo3(None, "") == argparse.Namespace(bar=None, baz=None, foo=None)
|
||||
assert hasattr(magic_foo3, "has_arguments")
|
||||
|
||||
assert (
|
||||
magic_foo4.__doc__
|
||||
== f"::\n\n %foo4 [-f FOO]\n\n A docstring.\n\n{options}:\n -f FOO, --foo FOO an argument\n"
|
||||
)
|
||||
assert getattr(magic_foo4, "argcmd_name", None) == None
|
||||
assert real_name(magic_foo4) == "foo4"
|
||||
assert magic_foo4(None, "") == argparse.Namespace()
|
||||
assert hasattr(magic_foo4, "has_arguments")
|
||||
|
||||
assert (
|
||||
magic_foo5.__doc__
|
||||
== f"::\n\n %frobnicate [-f FOO]\n\n A docstring.\n\n{options}:\n -f FOO, --foo FOO an argument\n"
|
||||
)
|
||||
assert getattr(magic_foo5, "argcmd_name", None) == "frobnicate"
|
||||
assert real_name(magic_foo5) == "frobnicate"
|
||||
assert magic_foo5(None, "") == argparse.Namespace(foo=None)
|
||||
assert hasattr(magic_foo5, "has_arguments")
|
||||
|
||||
assert (
|
||||
magic_magic_foo.__doc__
|
||||
== f"::\n\n %magic_foo [-f FOO]\n\n A docstring.\n\n{options}:\n -f FOO, --foo FOO an argument\n"
|
||||
)
|
||||
assert getattr(magic_magic_foo, "argcmd_name", None) == None
|
||||
assert real_name(magic_magic_foo) == "magic_foo"
|
||||
assert magic_magic_foo(None, "") == argparse.Namespace(foo=None)
|
||||
assert hasattr(magic_magic_foo, "has_arguments")
|
||||
|
||||
assert (
|
||||
foo.__doc__
|
||||
== f"::\n\n %foo [-f FOO]\n\n A docstring.\n\n{options}:\n -f FOO, --foo FOO an argument\n"
|
||||
)
|
||||
assert getattr(foo, "argcmd_name", None) == None
|
||||
assert real_name(foo) == "foo"
|
||||
assert foo(None, "") == argparse.Namespace(foo=None)
|
||||
assert hasattr(foo, "has_arguments")
|
@ -0,0 +1,216 @@
|
||||
"""Tests for various magic functions specific to the terminal frontend."""
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Imports
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
import sys
|
||||
from io import StringIO
|
||||
from unittest import TestCase
|
||||
|
||||
from IPython.testing import tools as tt
|
||||
#-----------------------------------------------------------------------------
|
||||
# Test functions begin
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
MINIMAL_LAZY_MAGIC = """
|
||||
from IPython.core.magic import (
|
||||
Magics,
|
||||
magics_class,
|
||||
line_magic,
|
||||
cell_magic,
|
||||
)
|
||||
|
||||
|
||||
@magics_class
|
||||
class LazyMagics(Magics):
|
||||
@line_magic
|
||||
def lazy_line(self, line):
|
||||
print("Lazy Line")
|
||||
|
||||
@cell_magic
|
||||
def lazy_cell(self, line, cell):
|
||||
print("Lazy Cell")
|
||||
|
||||
|
||||
def load_ipython_extension(ipython):
|
||||
ipython.register_magics(LazyMagics)
|
||||
"""
|
||||
|
||||
def check_cpaste(code, should_fail=False):
|
||||
"""Execute code via 'cpaste' and ensure it was executed, unless
|
||||
should_fail is set.
|
||||
"""
|
||||
ip.user_ns['code_ran'] = False
|
||||
|
||||
src = StringIO()
|
||||
src.write(code)
|
||||
src.write('\n--\n')
|
||||
src.seek(0)
|
||||
|
||||
stdin_save = sys.stdin
|
||||
sys.stdin = src
|
||||
|
||||
try:
|
||||
context = tt.AssertPrints if should_fail else tt.AssertNotPrints
|
||||
with context("Traceback (most recent call last)"):
|
||||
ip.run_line_magic("cpaste", "")
|
||||
|
||||
if not should_fail:
|
||||
assert ip.user_ns['code_ran'], "%r failed" % code
|
||||
finally:
|
||||
sys.stdin = stdin_save
|
||||
|
||||
def test_cpaste():
|
||||
"""Test cpaste magic"""
|
||||
|
||||
def runf():
|
||||
"""Marker function: sets a flag when executed.
|
||||
"""
|
||||
ip.user_ns['code_ran'] = True
|
||||
return 'runf' # return string so '+ runf()' doesn't result in success
|
||||
|
||||
tests = {'pass': ["runf()",
|
||||
"In [1]: runf()",
|
||||
"In [1]: if 1:\n ...: runf()",
|
||||
"> > > runf()",
|
||||
">>> runf()",
|
||||
" >>> runf()",
|
||||
],
|
||||
|
||||
'fail': ["1 + runf()",
|
||||
"++ runf()",
|
||||
]}
|
||||
|
||||
ip.user_ns['runf'] = runf
|
||||
|
||||
for code in tests['pass']:
|
||||
check_cpaste(code)
|
||||
|
||||
for code in tests['fail']:
|
||||
check_cpaste(code, should_fail=True)
|
||||
|
||||
|
||||
|
||||
class PasteTestCase(TestCase):
|
||||
"""Multiple tests for clipboard pasting"""
|
||||
|
||||
def paste(self, txt, flags='-q'):
|
||||
"""Paste input text, by default in quiet mode"""
|
||||
ip.hooks.clipboard_get = lambda: txt
|
||||
ip.run_line_magic("paste", flags)
|
||||
|
||||
def setUp(self):
|
||||
# Inject fake clipboard hook but save original so we can restore it later
|
||||
self.original_clip = ip.hooks.clipboard_get
|
||||
|
||||
def tearDown(self):
|
||||
# Restore original hook
|
||||
ip.hooks.clipboard_get = self.original_clip
|
||||
|
||||
def test_paste(self):
|
||||
ip.user_ns.pop("x", None)
|
||||
self.paste("x = 1")
|
||||
self.assertEqual(ip.user_ns["x"], 1)
|
||||
ip.user_ns.pop("x")
|
||||
|
||||
def test_paste_pyprompt(self):
|
||||
ip.user_ns.pop("x", None)
|
||||
self.paste(">>> x=2")
|
||||
self.assertEqual(ip.user_ns["x"], 2)
|
||||
ip.user_ns.pop("x")
|
||||
|
||||
def test_paste_py_multi(self):
|
||||
self.paste(
|
||||
"""
|
||||
>>> x = [1,2,3]
|
||||
>>> y = []
|
||||
>>> for i in x:
|
||||
... y.append(i**2)
|
||||
...
|
||||
"""
|
||||
)
|
||||
self.assertEqual(ip.user_ns["x"], [1, 2, 3])
|
||||
self.assertEqual(ip.user_ns["y"], [1, 4, 9])
|
||||
|
||||
def test_paste_py_multi_r(self):
|
||||
"Now, test that self.paste -r works"
|
||||
self.test_paste_py_multi()
|
||||
self.assertEqual(ip.user_ns.pop("x"), [1, 2, 3])
|
||||
self.assertEqual(ip.user_ns.pop("y"), [1, 4, 9])
|
||||
self.assertFalse("x" in ip.user_ns)
|
||||
ip.run_line_magic("paste", "-r")
|
||||
self.assertEqual(ip.user_ns["x"], [1, 2, 3])
|
||||
self.assertEqual(ip.user_ns["y"], [1, 4, 9])
|
||||
|
||||
def test_paste_email(self):
|
||||
"Test pasting of email-quoted contents"
|
||||
self.paste(
|
||||
"""\
|
||||
>> def foo(x):
|
||||
>> return x + 1
|
||||
>> xx = foo(1.1)"""
|
||||
)
|
||||
self.assertEqual(ip.user_ns["xx"], 2.1)
|
||||
|
||||
def test_paste_email2(self):
|
||||
"Email again; some programs add a space also at each quoting level"
|
||||
self.paste(
|
||||
"""\
|
||||
> > def foo(x):
|
||||
> > return x + 1
|
||||
> > yy = foo(2.1) """
|
||||
)
|
||||
self.assertEqual(ip.user_ns["yy"], 3.1)
|
||||
|
||||
def test_paste_email_py(self):
|
||||
"Email quoting of interactive input"
|
||||
self.paste(
|
||||
"""\
|
||||
>> >>> def f(x):
|
||||
>> ... return x+1
|
||||
>> ...
|
||||
>> >>> zz = f(2.5) """
|
||||
)
|
||||
self.assertEqual(ip.user_ns["zz"], 3.5)
|
||||
|
||||
def test_paste_echo(self):
|
||||
"Also test self.paste echoing, by temporarily faking the writer"
|
||||
w = StringIO()
|
||||
old_write = sys.stdout.write
|
||||
sys.stdout.write = w.write
|
||||
code = """
|
||||
a = 100
|
||||
b = 200"""
|
||||
try:
|
||||
self.paste(code,'')
|
||||
out = w.getvalue()
|
||||
finally:
|
||||
sys.stdout.write = old_write
|
||||
self.assertEqual(ip.user_ns["a"], 100)
|
||||
self.assertEqual(ip.user_ns["b"], 200)
|
||||
assert out == code + "\n## -- End pasted text --\n"
|
||||
|
||||
def test_paste_leading_commas(self):
|
||||
"Test multiline strings with leading commas"
|
||||
tm = ip.magics_manager.registry['TerminalMagics']
|
||||
s = '''\
|
||||
a = """
|
||||
,1,2,3
|
||||
"""'''
|
||||
ip.user_ns.pop("foo", None)
|
||||
tm.store_or_execute(s, "foo")
|
||||
self.assertIn("foo", ip.user_ns)
|
||||
|
||||
def test_paste_trailing_question(self):
|
||||
"Test pasting sources with trailing question marks"
|
||||
tm = ip.magics_manager.registry['TerminalMagics']
|
||||
s = '''\
|
||||
def funcfoo():
|
||||
if True: #am i true?
|
||||
return 'fooresult'
|
||||
'''
|
||||
ip.user_ns.pop('funcfoo', None)
|
||||
self.paste(s)
|
||||
self.assertEqual(ip.user_ns["funcfoo"](), "fooresult")
|
476
.venv/Lib/site-packages/IPython/core/tests/test_oinspect.py
Normal file
476
.venv/Lib/site-packages/IPython/core/tests/test_oinspect.py
Normal file
@ -0,0 +1,476 @@
|
||||
"""Tests for the object inspection functionality.
|
||||
"""
|
||||
|
||||
# Copyright (c) IPython Development Team.
|
||||
# Distributed under the terms of the Modified BSD License.
|
||||
|
||||
|
||||
from inspect import signature, Signature, Parameter
|
||||
import inspect
|
||||
import os
|
||||
import pytest
|
||||
import re
|
||||
import sys
|
||||
|
||||
from .. import oinspect
|
||||
|
||||
from decorator import decorator
|
||||
|
||||
from IPython.testing.tools import AssertPrints, AssertNotPrints
|
||||
from IPython.utils.path import compress_user
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Globals and constants
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
inspector = None
|
||||
|
||||
def setup_module():
|
||||
global inspector
|
||||
inspector = oinspect.Inspector()
|
||||
|
||||
|
||||
class SourceModuleMainTest:
|
||||
__module__ = "__main__"
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Local utilities
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
# WARNING: since this test checks the line number where a function is
|
||||
# defined, if any code is inserted above, the following line will need to be
|
||||
# updated. Do NOT insert any whitespace between the next line and the function
|
||||
# definition below.
|
||||
THIS_LINE_NUMBER = 46 # Put here the actual number of this line
|
||||
|
||||
|
||||
def test_find_source_lines():
|
||||
assert oinspect.find_source_lines(test_find_source_lines) == THIS_LINE_NUMBER + 3
|
||||
assert oinspect.find_source_lines(type) is None
|
||||
assert oinspect.find_source_lines(SourceModuleMainTest) is None
|
||||
assert oinspect.find_source_lines(SourceModuleMainTest()) is None
|
||||
|
||||
|
||||
def test_getsource():
|
||||
assert oinspect.getsource(type) is None
|
||||
assert oinspect.getsource(SourceModuleMainTest) is None
|
||||
assert oinspect.getsource(SourceModuleMainTest()) is None
|
||||
|
||||
|
||||
def test_inspect_getfile_raises_exception():
|
||||
"""Check oinspect.find_file/getsource/find_source_lines expectations"""
|
||||
with pytest.raises(TypeError):
|
||||
inspect.getfile(type)
|
||||
with pytest.raises(OSError if sys.version_info >= (3, 10) else TypeError):
|
||||
inspect.getfile(SourceModuleMainTest)
|
||||
|
||||
|
||||
# A couple of utilities to ensure these tests work the same from a source or a
|
||||
# binary install
|
||||
def pyfile(fname):
|
||||
return os.path.normcase(re.sub('.py[co]$', '.py', fname))
|
||||
|
||||
|
||||
def match_pyfiles(f1, f2):
|
||||
assert pyfile(f1) == pyfile(f2)
|
||||
|
||||
|
||||
def test_find_file():
|
||||
match_pyfiles(oinspect.find_file(test_find_file), os.path.abspath(__file__))
|
||||
assert oinspect.find_file(type) is None
|
||||
assert oinspect.find_file(SourceModuleMainTest) is None
|
||||
assert oinspect.find_file(SourceModuleMainTest()) is None
|
||||
|
||||
|
||||
def test_find_file_decorated1():
|
||||
|
||||
@decorator
|
||||
def noop1(f):
|
||||
def wrapper(*a, **kw):
|
||||
return f(*a, **kw)
|
||||
return wrapper
|
||||
|
||||
@noop1
|
||||
def f(x):
|
||||
"My docstring"
|
||||
|
||||
match_pyfiles(oinspect.find_file(f), os.path.abspath(__file__))
|
||||
assert f.__doc__ == "My docstring"
|
||||
|
||||
|
||||
def test_find_file_decorated2():
|
||||
|
||||
@decorator
|
||||
def noop2(f, *a, **kw):
|
||||
return f(*a, **kw)
|
||||
|
||||
@noop2
|
||||
@noop2
|
||||
@noop2
|
||||
def f(x):
|
||||
"My docstring 2"
|
||||
|
||||
match_pyfiles(oinspect.find_file(f), os.path.abspath(__file__))
|
||||
assert f.__doc__ == "My docstring 2"
|
||||
|
||||
|
||||
def test_find_file_magic():
|
||||
run = ip.find_line_magic('run')
|
||||
assert oinspect.find_file(run) is not None
|
||||
|
||||
|
||||
# A few generic objects we can then inspect in the tests below
|
||||
|
||||
class Call(object):
|
||||
"""This is the class docstring."""
|
||||
|
||||
def __init__(self, x, y=1):
|
||||
"""This is the constructor docstring."""
|
||||
|
||||
def __call__(self, *a, **kw):
|
||||
"""This is the call docstring."""
|
||||
|
||||
def method(self, x, z=2):
|
||||
"""Some method's docstring"""
|
||||
|
||||
class HasSignature(object):
|
||||
"""This is the class docstring."""
|
||||
__signature__ = Signature([Parameter('test', Parameter.POSITIONAL_OR_KEYWORD)])
|
||||
|
||||
def __init__(self, *args):
|
||||
"""This is the init docstring"""
|
||||
|
||||
|
||||
class SimpleClass(object):
|
||||
def method(self, x, z=2):
|
||||
"""Some method's docstring"""
|
||||
|
||||
|
||||
class Awkward(object):
|
||||
def __getattr__(self, name):
|
||||
raise Exception(name)
|
||||
|
||||
class NoBoolCall:
|
||||
"""
|
||||
callable with `__bool__` raising should still be inspect-able.
|
||||
"""
|
||||
|
||||
def __call__(self):
|
||||
"""does nothing"""
|
||||
pass
|
||||
|
||||
def __bool__(self):
|
||||
"""just raise NotImplemented"""
|
||||
raise NotImplementedError('Must be implemented')
|
||||
|
||||
|
||||
class SerialLiar(object):
|
||||
"""Attribute accesses always get another copy of the same class.
|
||||
|
||||
unittest.mock.call does something similar, but it's not ideal for testing
|
||||
as the failure mode is to eat all your RAM. This gives up after 10k levels.
|
||||
"""
|
||||
def __init__(self, max_fibbing_twig, lies_told=0):
|
||||
if lies_told > 10000:
|
||||
raise RuntimeError('Nose too long, honesty is the best policy')
|
||||
self.max_fibbing_twig = max_fibbing_twig
|
||||
self.lies_told = lies_told
|
||||
max_fibbing_twig[0] = max(max_fibbing_twig[0], lies_told)
|
||||
|
||||
def __getattr__(self, item):
|
||||
return SerialLiar(self.max_fibbing_twig, self.lies_told + 1)
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Tests
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
def test_info():
|
||||
"Check that Inspector.info fills out various fields as expected."
|
||||
i = inspector.info(Call, oname="Call")
|
||||
assert i["type_name"] == "type"
|
||||
expected_class = str(type(type)) # <class 'type'> (Python 3) or <type 'type'>
|
||||
assert i["base_class"] == expected_class
|
||||
assert re.search(
|
||||
"<class 'IPython.core.tests.test_oinspect.Call'( at 0x[0-9a-f]{1,9})?>",
|
||||
i["string_form"],
|
||||
)
|
||||
fname = __file__
|
||||
if fname.endswith(".pyc"):
|
||||
fname = fname[:-1]
|
||||
# case-insensitive comparison needed on some filesystems
|
||||
# e.g. Windows:
|
||||
assert i["file"].lower() == compress_user(fname).lower()
|
||||
assert i["definition"] == None
|
||||
assert i["docstring"] == Call.__doc__
|
||||
assert i["source"] == None
|
||||
assert i["isclass"] is True
|
||||
assert i["init_definition"] == "Call(x, y=1)"
|
||||
assert i["init_docstring"] == Call.__init__.__doc__
|
||||
|
||||
i = inspector.info(Call, detail_level=1)
|
||||
assert i["source"] is not None
|
||||
assert i["docstring"] == None
|
||||
|
||||
c = Call(1)
|
||||
c.__doc__ = "Modified instance docstring"
|
||||
i = inspector.info(c)
|
||||
assert i["type_name"] == "Call"
|
||||
assert i["docstring"] == "Modified instance docstring"
|
||||
assert i["class_docstring"] == Call.__doc__
|
||||
assert i["init_docstring"] == Call.__init__.__doc__
|
||||
assert i["call_docstring"] == Call.__call__.__doc__
|
||||
|
||||
|
||||
def test_class_signature():
|
||||
info = inspector.info(HasSignature, "HasSignature")
|
||||
assert info["init_definition"] == "HasSignature(test)"
|
||||
assert info["init_docstring"] == HasSignature.__init__.__doc__
|
||||
|
||||
|
||||
def test_info_awkward():
|
||||
# Just test that this doesn't throw an error.
|
||||
inspector.info(Awkward())
|
||||
|
||||
def test_bool_raise():
|
||||
inspector.info(NoBoolCall())
|
||||
|
||||
def test_info_serialliar():
|
||||
fib_tracker = [0]
|
||||
inspector.info(SerialLiar(fib_tracker))
|
||||
|
||||
# Nested attribute access should be cut off at 100 levels deep to avoid
|
||||
# infinite loops: https://github.com/ipython/ipython/issues/9122
|
||||
assert fib_tracker[0] < 9000
|
||||
|
||||
def support_function_one(x, y=2, *a, **kw):
|
||||
"""A simple function."""
|
||||
|
||||
def test_calldef_none():
|
||||
# We should ignore __call__ for all of these.
|
||||
for obj in [support_function_one, SimpleClass().method, any, str.upper]:
|
||||
i = inspector.info(obj)
|
||||
assert i["call_def"] is None
|
||||
|
||||
|
||||
def f_kwarg(pos, *, kwonly):
|
||||
pass
|
||||
|
||||
def test_definition_kwonlyargs():
|
||||
i = inspector.info(f_kwarg, oname="f_kwarg") # analysis:ignore
|
||||
assert i["definition"] == "f_kwarg(pos, *, kwonly)"
|
||||
|
||||
|
||||
def test_getdoc():
|
||||
class A(object):
|
||||
"""standard docstring"""
|
||||
pass
|
||||
|
||||
class B(object):
|
||||
"""standard docstring"""
|
||||
def getdoc(self):
|
||||
return "custom docstring"
|
||||
|
||||
class C(object):
|
||||
"""standard docstring"""
|
||||
def getdoc(self):
|
||||
return None
|
||||
|
||||
a = A()
|
||||
b = B()
|
||||
c = C()
|
||||
|
||||
assert oinspect.getdoc(a) == "standard docstring"
|
||||
assert oinspect.getdoc(b) == "custom docstring"
|
||||
assert oinspect.getdoc(c) == "standard docstring"
|
||||
|
||||
|
||||
def test_empty_property_has_no_source():
|
||||
i = inspector.info(property(), detail_level=1)
|
||||
assert i["source"] is None
|
||||
|
||||
|
||||
def test_property_sources():
|
||||
# A simple adder whose source and signature stays
|
||||
# the same across Python distributions
|
||||
def simple_add(a, b):
|
||||
"Adds two numbers"
|
||||
return a + b
|
||||
|
||||
class A(object):
|
||||
@property
|
||||
def foo(self):
|
||||
return 'bar'
|
||||
|
||||
foo = foo.setter(lambda self, v: setattr(self, 'bar', v))
|
||||
|
||||
dname = property(oinspect.getdoc)
|
||||
adder = property(simple_add)
|
||||
|
||||
i = inspector.info(A.foo, detail_level=1)
|
||||
assert "def foo(self):" in i["source"]
|
||||
assert "lambda self, v:" in i["source"]
|
||||
|
||||
i = inspector.info(A.dname, detail_level=1)
|
||||
assert "def getdoc(obj)" in i["source"]
|
||||
|
||||
i = inspector.info(A.adder, detail_level=1)
|
||||
assert "def simple_add(a, b)" in i["source"]
|
||||
|
||||
|
||||
def test_property_docstring_is_in_info_for_detail_level_0():
|
||||
class A(object):
|
||||
@property
|
||||
def foobar(self):
|
||||
"""This is `foobar` property."""
|
||||
pass
|
||||
|
||||
ip.user_ns["a_obj"] = A()
|
||||
assert (
|
||||
"This is `foobar` property."
|
||||
== ip.object_inspect("a_obj.foobar", detail_level=0)["docstring"]
|
||||
)
|
||||
|
||||
ip.user_ns["a_cls"] = A
|
||||
assert (
|
||||
"This is `foobar` property."
|
||||
== ip.object_inspect("a_cls.foobar", detail_level=0)["docstring"]
|
||||
)
|
||||
|
||||
|
||||
def test_pdef():
|
||||
# See gh-1914
|
||||
def foo(): pass
|
||||
inspector.pdef(foo, 'foo')
|
||||
|
||||
|
||||
def test_pinfo_nonascii():
|
||||
# See gh-1177
|
||||
from . import nonascii2
|
||||
ip.user_ns['nonascii2'] = nonascii2
|
||||
ip._inspect('pinfo', 'nonascii2', detail_level=1)
|
||||
|
||||
def test_pinfo_type():
|
||||
"""
|
||||
type can fail in various edge case, for example `type.__subclass__()`
|
||||
"""
|
||||
ip._inspect('pinfo', 'type')
|
||||
|
||||
|
||||
def test_pinfo_docstring_no_source():
|
||||
"""Docstring should be included with detail_level=1 if there is no source"""
|
||||
with AssertPrints('Docstring:'):
|
||||
ip._inspect('pinfo', 'str.format', detail_level=0)
|
||||
with AssertPrints('Docstring:'):
|
||||
ip._inspect('pinfo', 'str.format', detail_level=1)
|
||||
|
||||
|
||||
def test_pinfo_no_docstring_if_source():
|
||||
"""Docstring should not be included with detail_level=1 if source is found"""
|
||||
def foo():
|
||||
"""foo has a docstring"""
|
||||
|
||||
ip.user_ns['foo'] = foo
|
||||
|
||||
with AssertPrints('Docstring:'):
|
||||
ip._inspect('pinfo', 'foo', detail_level=0)
|
||||
with AssertPrints('Source:'):
|
||||
ip._inspect('pinfo', 'foo', detail_level=1)
|
||||
with AssertNotPrints('Docstring:'):
|
||||
ip._inspect('pinfo', 'foo', detail_level=1)
|
||||
|
||||
|
||||
def test_pinfo_docstring_if_detail_and_no_source():
|
||||
""" Docstring should be displayed if source info not available """
|
||||
obj_def = '''class Foo(object):
|
||||
""" This is a docstring for Foo """
|
||||
def bar(self):
|
||||
""" This is a docstring for Foo.bar """
|
||||
pass
|
||||
'''
|
||||
|
||||
ip.run_cell(obj_def)
|
||||
ip.run_cell('foo = Foo()')
|
||||
|
||||
with AssertNotPrints("Source:"):
|
||||
with AssertPrints('Docstring:'):
|
||||
ip._inspect('pinfo', 'foo', detail_level=0)
|
||||
with AssertPrints('Docstring:'):
|
||||
ip._inspect('pinfo', 'foo', detail_level=1)
|
||||
with AssertPrints('Docstring:'):
|
||||
ip._inspect('pinfo', 'foo.bar', detail_level=0)
|
||||
|
||||
with AssertNotPrints('Docstring:'):
|
||||
with AssertPrints('Source:'):
|
||||
ip._inspect('pinfo', 'foo.bar', detail_level=1)
|
||||
|
||||
|
||||
def test_pinfo_magic():
|
||||
with AssertPrints('Docstring:'):
|
||||
ip._inspect('pinfo', 'lsmagic', detail_level=0)
|
||||
|
||||
with AssertPrints('Source:'):
|
||||
ip._inspect('pinfo', 'lsmagic', detail_level=1)
|
||||
|
||||
|
||||
def test_init_colors():
|
||||
# ensure colors are not present in signature info
|
||||
info = inspector.info(HasSignature)
|
||||
init_def = info["init_definition"]
|
||||
assert "[0m" not in init_def
|
||||
|
||||
|
||||
def test_builtin_init():
|
||||
info = inspector.info(list)
|
||||
init_def = info['init_definition']
|
||||
assert init_def is not None
|
||||
|
||||
|
||||
def test_render_signature_short():
|
||||
def short_fun(a=1): pass
|
||||
sig = oinspect._render_signature(
|
||||
signature(short_fun),
|
||||
short_fun.__name__,
|
||||
)
|
||||
assert sig == "short_fun(a=1)"
|
||||
|
||||
|
||||
def test_render_signature_long():
|
||||
from typing import Optional
|
||||
|
||||
def long_function(
|
||||
a_really_long_parameter: int,
|
||||
and_another_long_one: bool = False,
|
||||
let_us_make_sure_this_is_looong: Optional[str] = None,
|
||||
) -> bool: pass
|
||||
|
||||
sig = oinspect._render_signature(
|
||||
signature(long_function),
|
||||
long_function.__name__,
|
||||
)
|
||||
assert sig in [
|
||||
# Python >=3.9
|
||||
'''\
|
||||
long_function(
|
||||
a_really_long_parameter: int,
|
||||
and_another_long_one: bool = False,
|
||||
let_us_make_sure_this_is_looong: Optional[str] = None,
|
||||
) -> bool\
|
||||
''',
|
||||
# Python >=3.7
|
||||
'''\
|
||||
long_function(
|
||||
a_really_long_parameter: int,
|
||||
and_another_long_one: bool = False,
|
||||
let_us_make_sure_this_is_looong: Union[str, NoneType] = None,
|
||||
) -> bool\
|
||||
''', # Python <=3.6
|
||||
'''\
|
||||
long_function(
|
||||
a_really_long_parameter:int,
|
||||
and_another_long_one:bool=False,
|
||||
let_us_make_sure_this_is_looong:Union[str, NoneType]=None,
|
||||
) -> bool\
|
||||
''',
|
||||
]
|
20
.venv/Lib/site-packages/IPython/core/tests/test_page.py
Normal file
20
.venv/Lib/site-packages/IPython/core/tests/test_page.py
Normal file
@ -0,0 +1,20 @@
|
||||
#-----------------------------------------------------------------------------
|
||||
# Copyright (C) 2010-2011 The IPython Development Team.
|
||||
#
|
||||
# Distributed under the terms of the BSD License.
|
||||
#
|
||||
# The full license is in the file COPYING.txt, distributed with this software.
|
||||
#-----------------------------------------------------------------------------
|
||||
import io
|
||||
|
||||
# N.B. For the test suite, page.page is overridden (see IPython.testing.globalipapp)
|
||||
from IPython.core import page
|
||||
|
||||
def test_detect_screen_size():
|
||||
"""Simple smoketest for page._detect_screen_size."""
|
||||
try:
|
||||
page._detect_screen_size(True, 25)
|
||||
except (TypeError, io.UnsupportedOperation):
|
||||
# This can happen in the test suite, because stdout may not have a
|
||||
# fileno.
|
||||
pass
|
201
.venv/Lib/site-packages/IPython/core/tests/test_paths.py
Normal file
201
.venv/Lib/site-packages/IPython/core/tests/test_paths.py
Normal file
@ -0,0 +1,201 @@
|
||||
import errno
|
||||
import os
|
||||
import shutil
|
||||
import sys
|
||||
import tempfile
|
||||
import warnings
|
||||
from unittest.mock import patch
|
||||
|
||||
from tempfile import TemporaryDirectory
|
||||
from testpath import assert_isdir, assert_isfile, modified_env
|
||||
|
||||
from IPython import paths
|
||||
from IPython.testing.decorators import skip_win32
|
||||
|
||||
TMP_TEST_DIR = os.path.realpath(tempfile.mkdtemp())
|
||||
HOME_TEST_DIR = os.path.join(TMP_TEST_DIR, "home_test_dir")
|
||||
XDG_TEST_DIR = os.path.join(HOME_TEST_DIR, "xdg_test_dir")
|
||||
XDG_CACHE_DIR = os.path.join(HOME_TEST_DIR, "xdg_cache_dir")
|
||||
IP_TEST_DIR = os.path.join(HOME_TEST_DIR,'.ipython')
|
||||
|
||||
def setup_module():
|
||||
"""Setup testenvironment for the module:
|
||||
|
||||
- Adds dummy home dir tree
|
||||
"""
|
||||
# Do not mask exceptions here. In particular, catching WindowsError is a
|
||||
# problem because that exception is only defined on Windows...
|
||||
os.makedirs(IP_TEST_DIR)
|
||||
os.makedirs(os.path.join(XDG_TEST_DIR, 'ipython'))
|
||||
os.makedirs(os.path.join(XDG_CACHE_DIR, 'ipython'))
|
||||
|
||||
|
||||
def teardown_module():
|
||||
"""Teardown testenvironment for the module:
|
||||
|
||||
- Remove dummy home dir tree
|
||||
"""
|
||||
# Note: we remove the parent test dir, which is the root of all test
|
||||
# subdirs we may have created. Use shutil instead of os.removedirs, so
|
||||
# that non-empty directories are all recursively removed.
|
||||
shutil.rmtree(TMP_TEST_DIR)
|
||||
|
||||
def patch_get_home_dir(dirpath):
|
||||
return patch.object(paths, 'get_home_dir', return_value=dirpath)
|
||||
|
||||
|
||||
def test_get_ipython_dir_1():
|
||||
"""test_get_ipython_dir_1, Testcase to see if we can call get_ipython_dir without Exceptions."""
|
||||
env_ipdir = os.path.join("someplace", ".ipython")
|
||||
with patch.object(paths, '_writable_dir', return_value=True), \
|
||||
modified_env({'IPYTHONDIR': env_ipdir}):
|
||||
ipdir = paths.get_ipython_dir()
|
||||
|
||||
assert ipdir == env_ipdir
|
||||
|
||||
def test_get_ipython_dir_2():
|
||||
"""test_get_ipython_dir_2, Testcase to see if we can call get_ipython_dir without Exceptions."""
|
||||
with patch_get_home_dir('someplace'), \
|
||||
patch.object(paths, 'get_xdg_dir', return_value=None), \
|
||||
patch.object(paths, '_writable_dir', return_value=True), \
|
||||
patch('os.name', "posix"), \
|
||||
modified_env({'IPYTHON_DIR': None,
|
||||
'IPYTHONDIR': None,
|
||||
'XDG_CONFIG_HOME': None
|
||||
}):
|
||||
ipdir = paths.get_ipython_dir()
|
||||
|
||||
assert ipdir == os.path.join("someplace", ".ipython")
|
||||
|
||||
def test_get_ipython_dir_3():
|
||||
"""test_get_ipython_dir_3, use XDG if defined and exists, and .ipython doesn't exist."""
|
||||
tmphome = TemporaryDirectory()
|
||||
try:
|
||||
with patch_get_home_dir(tmphome.name), \
|
||||
patch('os.name', 'posix'), \
|
||||
modified_env({
|
||||
'IPYTHON_DIR': None,
|
||||
'IPYTHONDIR': None,
|
||||
'XDG_CONFIG_HOME': XDG_TEST_DIR,
|
||||
}), warnings.catch_warnings(record=True) as w:
|
||||
ipdir = paths.get_ipython_dir()
|
||||
|
||||
assert ipdir == os.path.join(tmphome.name, XDG_TEST_DIR, "ipython")
|
||||
assert len(w) == 0
|
||||
finally:
|
||||
tmphome.cleanup()
|
||||
|
||||
def test_get_ipython_dir_4():
|
||||
"""test_get_ipython_dir_4, warn if XDG and home both exist."""
|
||||
with patch_get_home_dir(HOME_TEST_DIR), \
|
||||
patch('os.name', 'posix'):
|
||||
try:
|
||||
os.mkdir(os.path.join(XDG_TEST_DIR, 'ipython'))
|
||||
except OSError as e:
|
||||
if e.errno != errno.EEXIST:
|
||||
raise
|
||||
|
||||
|
||||
with modified_env({
|
||||
'IPYTHON_DIR': None,
|
||||
'IPYTHONDIR': None,
|
||||
'XDG_CONFIG_HOME': XDG_TEST_DIR,
|
||||
}), warnings.catch_warnings(record=True) as w:
|
||||
ipdir = paths.get_ipython_dir()
|
||||
|
||||
assert len(w) == 1
|
||||
assert "Ignoring" in str(w[0])
|
||||
|
||||
|
||||
def test_get_ipython_dir_5():
|
||||
"""test_get_ipython_dir_5, use .ipython if exists and XDG defined, but doesn't exist."""
|
||||
with patch_get_home_dir(HOME_TEST_DIR), \
|
||||
patch('os.name', 'posix'):
|
||||
try:
|
||||
os.rmdir(os.path.join(XDG_TEST_DIR, 'ipython'))
|
||||
except OSError as e:
|
||||
if e.errno != errno.ENOENT:
|
||||
raise
|
||||
|
||||
with modified_env({
|
||||
'IPYTHON_DIR': None,
|
||||
'IPYTHONDIR': None,
|
||||
'XDG_CONFIG_HOME': XDG_TEST_DIR,
|
||||
}):
|
||||
ipdir = paths.get_ipython_dir()
|
||||
|
||||
assert ipdir == IP_TEST_DIR
|
||||
|
||||
def test_get_ipython_dir_6():
|
||||
"""test_get_ipython_dir_6, use home over XDG if defined and neither exist."""
|
||||
xdg = os.path.join(HOME_TEST_DIR, 'somexdg')
|
||||
os.mkdir(xdg)
|
||||
shutil.rmtree(os.path.join(HOME_TEST_DIR, '.ipython'))
|
||||
print(paths._writable_dir)
|
||||
with patch_get_home_dir(HOME_TEST_DIR), \
|
||||
patch.object(paths, 'get_xdg_dir', return_value=xdg), \
|
||||
patch('os.name', 'posix'), \
|
||||
modified_env({
|
||||
'IPYTHON_DIR': None,
|
||||
'IPYTHONDIR': None,
|
||||
'XDG_CONFIG_HOME': None,
|
||||
}), warnings.catch_warnings(record=True) as w:
|
||||
ipdir = paths.get_ipython_dir()
|
||||
|
||||
assert ipdir == os.path.join(HOME_TEST_DIR, ".ipython")
|
||||
assert len(w) == 0
|
||||
|
||||
def test_get_ipython_dir_7():
|
||||
"""test_get_ipython_dir_7, test home directory expansion on IPYTHONDIR"""
|
||||
home_dir = os.path.normpath(os.path.expanduser('~'))
|
||||
with modified_env({'IPYTHONDIR': os.path.join('~', 'somewhere')}), \
|
||||
patch.object(paths, '_writable_dir', return_value=True):
|
||||
ipdir = paths.get_ipython_dir()
|
||||
assert ipdir == os.path.join(home_dir, "somewhere")
|
||||
|
||||
|
||||
@skip_win32
|
||||
def test_get_ipython_dir_8():
|
||||
"""test_get_ipython_dir_8, test / home directory"""
|
||||
if not os.access("/", os.W_OK):
|
||||
# test only when HOME directory actually writable
|
||||
return
|
||||
|
||||
with patch.object(paths, "_writable_dir", lambda path: bool(path)), patch.object(
|
||||
paths, "get_xdg_dir", return_value=None
|
||||
), modified_env(
|
||||
{
|
||||
"IPYTHON_DIR": None,
|
||||
"IPYTHONDIR": None,
|
||||
"HOME": "/",
|
||||
}
|
||||
):
|
||||
assert paths.get_ipython_dir() == "/.ipython"
|
||||
|
||||
|
||||
def test_get_ipython_cache_dir():
|
||||
with modified_env({'HOME': HOME_TEST_DIR}):
|
||||
if os.name == "posix":
|
||||
# test default
|
||||
os.makedirs(os.path.join(HOME_TEST_DIR, ".cache"))
|
||||
with modified_env({'XDG_CACHE_HOME': None}):
|
||||
ipdir = paths.get_ipython_cache_dir()
|
||||
assert os.path.join(HOME_TEST_DIR, ".cache", "ipython") == ipdir
|
||||
assert_isdir(ipdir)
|
||||
|
||||
# test env override
|
||||
with modified_env({"XDG_CACHE_HOME": XDG_CACHE_DIR}):
|
||||
ipdir = paths.get_ipython_cache_dir()
|
||||
assert_isdir(ipdir)
|
||||
assert ipdir == os.path.join(XDG_CACHE_DIR, "ipython")
|
||||
else:
|
||||
assert paths.get_ipython_cache_dir() == paths.get_ipython_dir()
|
||||
|
||||
def test_get_ipython_package_dir():
|
||||
ipdir = paths.get_ipython_package_dir()
|
||||
assert_isdir(ipdir)
|
||||
|
||||
|
||||
def test_get_ipython_module_path():
|
||||
ipapp_path = paths.get_ipython_module_path('IPython.terminal.ipapp')
|
||||
assert_isfile(ipapp_path)
|
127
.venv/Lib/site-packages/IPython/core/tests/test_prefilter.py
Normal file
127
.venv/Lib/site-packages/IPython/core/tests/test_prefilter.py
Normal file
@ -0,0 +1,127 @@
|
||||
"""Tests for input manipulation machinery."""
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Imports
|
||||
#-----------------------------------------------------------------------------
|
||||
import pytest
|
||||
|
||||
from IPython.core.prefilter import AutocallChecker
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Tests
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
def test_prefilter():
|
||||
"""Test user input conversions"""
|
||||
|
||||
# pairs of (raw, expected correct) input
|
||||
pairs = [ ('2+2','2+2'),
|
||||
]
|
||||
|
||||
for raw, correct in pairs:
|
||||
assert ip.prefilter(raw) == correct
|
||||
|
||||
def test_prefilter_shadowed():
|
||||
def dummy_magic(line): pass
|
||||
|
||||
prev_automagic_state = ip.automagic
|
||||
ip.automagic = True
|
||||
ip.autocall = 0
|
||||
|
||||
try:
|
||||
# These should not be transformed - they are shadowed by other names
|
||||
for name in ['if', 'zip', 'get_ipython']: # keyword, builtin, global
|
||||
ip.register_magic_function(dummy_magic, magic_name=name)
|
||||
res = ip.prefilter(name + " foo")
|
||||
assert res == name + " foo"
|
||||
del ip.magics_manager.magics["line"][name]
|
||||
|
||||
# These should be transformed
|
||||
for name in ['fi', 'piz', 'nohtypi_teg']:
|
||||
ip.register_magic_function(dummy_magic, magic_name=name)
|
||||
res = ip.prefilter(name + " foo")
|
||||
assert res != name + " foo"
|
||||
del ip.magics_manager.magics["line"][name]
|
||||
|
||||
finally:
|
||||
ip.automagic = prev_automagic_state
|
||||
|
||||
def test_autocall_binops():
|
||||
"""See https://github.com/ipython/ipython/issues/81"""
|
||||
ip.magic('autocall 2')
|
||||
f = lambda x: x
|
||||
ip.user_ns['f'] = f
|
||||
try:
|
||||
assert ip.prefilter("f 1") == "f(1)"
|
||||
for t in ["f +1", "f -1"]:
|
||||
assert ip.prefilter(t) == t
|
||||
|
||||
# Run tests again with a more permissive exclude_regexp, which will
|
||||
# allow transformation of binary operations ('f -1' -> 'f(-1)').
|
||||
pm = ip.prefilter_manager
|
||||
ac = AutocallChecker(shell=pm.shell, prefilter_manager=pm,
|
||||
config=pm.config)
|
||||
try:
|
||||
ac.priority = 1
|
||||
ac.exclude_regexp = r'^[,&^\|\*/]|^is |^not |^in |^and |^or '
|
||||
pm.sort_checkers()
|
||||
|
||||
assert ip.prefilter("f -1") == "f(-1)"
|
||||
assert ip.prefilter("f +1") == "f(+1)"
|
||||
finally:
|
||||
pm.unregister_checker(ac)
|
||||
finally:
|
||||
ip.magic('autocall 0')
|
||||
del ip.user_ns['f']
|
||||
|
||||
|
||||
def test_issue_114():
|
||||
"""Check that multiline string literals don't expand as magic
|
||||
see http://github.com/ipython/ipython/issues/114"""
|
||||
|
||||
template = '"""\n%s\n"""'
|
||||
# Store the current value of multi_line_specials and turn it off before
|
||||
# running test, since it could be true (case in which the test doesn't make
|
||||
# sense, as multiline string literals *will* expand as magic in that case).
|
||||
msp = ip.prefilter_manager.multi_line_specials
|
||||
ip.prefilter_manager.multi_line_specials = False
|
||||
try:
|
||||
for mgk in ip.magics_manager.lsmagic()['line']:
|
||||
raw = template % mgk
|
||||
assert ip.prefilter(raw) == raw
|
||||
finally:
|
||||
ip.prefilter_manager.multi_line_specials = msp
|
||||
|
||||
|
||||
def test_prefilter_attribute_errors():
|
||||
"""Capture exceptions thrown by user objects on attribute access.
|
||||
|
||||
See http://github.com/ipython/ipython/issues/988."""
|
||||
|
||||
class X(object):
|
||||
def __getattr__(self, k):
|
||||
raise ValueError('broken object')
|
||||
def __call__(self, x):
|
||||
return x
|
||||
|
||||
# Create a callable broken object
|
||||
ip.user_ns['x'] = X()
|
||||
ip.magic('autocall 2')
|
||||
try:
|
||||
# Even if x throws an attribute error when looking at its rewrite
|
||||
# attribute, we should not crash. So the test here is simply making
|
||||
# the prefilter call and not having an exception.
|
||||
ip.prefilter('x 1')
|
||||
finally:
|
||||
del ip.user_ns['x']
|
||||
ip.magic('autocall 0')
|
||||
|
||||
|
||||
def test_autocall_should_support_unicode():
|
||||
ip.magic('autocall 2')
|
||||
ip.user_ns['π'] = lambda x: x
|
||||
try:
|
||||
assert ip.prefilter("π 3") == "π(3)"
|
||||
finally:
|
||||
ip.magic('autocall 0')
|
||||
del ip.user_ns['π']
|
155
.venv/Lib/site-packages/IPython/core/tests/test_profile.py
Normal file
155
.venv/Lib/site-packages/IPython/core/tests/test_profile.py
Normal file
@ -0,0 +1,155 @@
|
||||
# coding: utf-8
|
||||
"""Tests for profile-related functions.
|
||||
|
||||
Currently only the startup-dir functionality is tested, but more tests should
|
||||
be added for:
|
||||
|
||||
* ipython profile create
|
||||
* ipython profile list
|
||||
* ipython profile create --parallel
|
||||
* security dir permissions
|
||||
|
||||
Authors
|
||||
-------
|
||||
|
||||
* MinRK
|
||||
|
||||
"""
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Imports
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
import shutil
|
||||
import sys
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
from unittest import TestCase
|
||||
|
||||
from tempfile import TemporaryDirectory
|
||||
|
||||
from IPython.core.profileapp import list_bundled_profiles, list_profiles_in
|
||||
from IPython.core.profiledir import ProfileDir
|
||||
from IPython.testing import decorators as dec
|
||||
from IPython.testing import tools as tt
|
||||
from IPython.utils.process import getoutput
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Globals
|
||||
#-----------------------------------------------------------------------------
|
||||
TMP_TEST_DIR = Path(tempfile.mkdtemp())
|
||||
HOME_TEST_DIR = TMP_TEST_DIR / "home_test_dir"
|
||||
IP_TEST_DIR = HOME_TEST_DIR / ".ipython"
|
||||
|
||||
#
|
||||
# Setup/teardown functions/decorators
|
||||
#
|
||||
|
||||
def setup_module():
|
||||
"""Setup test environment for the module:
|
||||
|
||||
- Adds dummy home dir tree
|
||||
"""
|
||||
# Do not mask exceptions here. In particular, catching WindowsError is a
|
||||
# problem because that exception is only defined on Windows...
|
||||
(Path.cwd() / IP_TEST_DIR).mkdir(parents=True)
|
||||
|
||||
|
||||
def teardown_module():
|
||||
"""Teardown test environment for the module:
|
||||
|
||||
- Remove dummy home dir tree
|
||||
"""
|
||||
# Note: we remove the parent test dir, which is the root of all test
|
||||
# subdirs we may have created. Use shutil instead of os.removedirs, so
|
||||
# that non-empty directories are all recursively removed.
|
||||
shutil.rmtree(TMP_TEST_DIR)
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Test functions
|
||||
#-----------------------------------------------------------------------------
|
||||
class ProfileStartupTest(TestCase):
|
||||
def setUp(self):
|
||||
# create profile dir
|
||||
self.pd = ProfileDir.create_profile_dir_by_name(IP_TEST_DIR, "test")
|
||||
self.options = ["--ipython-dir", IP_TEST_DIR, "--profile", "test"]
|
||||
self.fname = TMP_TEST_DIR / "test.py"
|
||||
|
||||
def tearDown(self):
|
||||
# We must remove this profile right away so its presence doesn't
|
||||
# confuse other tests.
|
||||
shutil.rmtree(self.pd.location)
|
||||
|
||||
def init(self, startup_file, startup, test):
|
||||
# write startup python file
|
||||
with open(Path(self.pd.startup_dir) / startup_file, "w", encoding="utf-8") as f:
|
||||
f.write(startup)
|
||||
# write simple test file, to check that the startup file was run
|
||||
with open(self.fname, "w", encoding="utf-8") as f:
|
||||
f.write(test)
|
||||
|
||||
def validate(self, output):
|
||||
tt.ipexec_validate(self.fname, output, "", options=self.options)
|
||||
|
||||
def test_startup_py(self):
|
||||
self.init('00-start.py', 'zzz=123\n', 'print(zzz)\n')
|
||||
self.validate('123')
|
||||
|
||||
def test_startup_ipy(self):
|
||||
self.init('00-start.ipy', '%xmode plain\n', '')
|
||||
self.validate('Exception reporting mode: Plain')
|
||||
|
||||
|
||||
def test_list_profiles_in():
|
||||
# No need to remove these directories and files, as they will get nuked in
|
||||
# the module-level teardown.
|
||||
td = Path(tempfile.mkdtemp(dir=TMP_TEST_DIR))
|
||||
for name in ("profile_foo", "profile_hello", "not_a_profile"):
|
||||
Path(td / name).mkdir(parents=True)
|
||||
if dec.unicode_paths:
|
||||
Path(td / "profile_ünicode").mkdir(parents=True)
|
||||
|
||||
with open(td / "profile_file", "w", encoding="utf-8") as f:
|
||||
f.write("I am not a profile directory")
|
||||
profiles = list_profiles_in(td)
|
||||
|
||||
# unicode normalization can turn u'ünicode' into u'u\0308nicode',
|
||||
# so only check for *nicode, and that creating a ProfileDir from the
|
||||
# name remains valid
|
||||
found_unicode = False
|
||||
for p in list(profiles):
|
||||
if p.endswith('nicode'):
|
||||
pd = ProfileDir.find_profile_dir_by_name(td, p)
|
||||
profiles.remove(p)
|
||||
found_unicode = True
|
||||
break
|
||||
if dec.unicode_paths:
|
||||
assert found_unicode is True
|
||||
assert set(profiles) == {"foo", "hello"}
|
||||
|
||||
|
||||
def test_list_bundled_profiles():
|
||||
# This variable will need to be updated when a new profile gets bundled
|
||||
bundled = sorted(list_bundled_profiles())
|
||||
assert bundled == []
|
||||
|
||||
|
||||
def test_profile_create_ipython_dir():
|
||||
"""ipython profile create respects --ipython-dir"""
|
||||
with TemporaryDirectory() as td:
|
||||
getoutput(
|
||||
[
|
||||
sys.executable,
|
||||
"-m",
|
||||
"IPython",
|
||||
"profile",
|
||||
"create",
|
||||
"foo",
|
||||
"--ipython-dir=%s" % td,
|
||||
]
|
||||
)
|
||||
profile_dir = Path(td) / "profile_foo"
|
||||
assert Path(profile_dir).exists()
|
||||
ipython_config = profile_dir / "ipython_config.py"
|
||||
assert Path(ipython_config).exists()
|
30
.venv/Lib/site-packages/IPython/core/tests/test_prompts.py
Normal file
30
.venv/Lib/site-packages/IPython/core/tests/test_prompts.py
Normal file
@ -0,0 +1,30 @@
|
||||
# -*- coding: utf-8
|
||||
"""Tests for prompt generation."""
|
||||
|
||||
import unittest
|
||||
|
||||
from IPython.core.prompts import LazyEvaluate
|
||||
|
||||
class PromptTests(unittest.TestCase):
|
||||
def test_lazy_eval_unicode(self):
|
||||
u = u'ünicødé'
|
||||
lz = LazyEvaluate(lambda : u)
|
||||
self.assertEqual(str(lz), u)
|
||||
self.assertEqual(format(lz), u)
|
||||
|
||||
def test_lazy_eval_nonascii_bytes(self):
|
||||
u = u'ünicødé'
|
||||
b = u.encode('utf8')
|
||||
lz = LazyEvaluate(lambda : b)
|
||||
# unicode(lz) would fail
|
||||
self.assertEqual(str(lz), str(b))
|
||||
self.assertEqual(format(lz), str(b))
|
||||
|
||||
def test_lazy_eval_float(self):
|
||||
f = 0.503
|
||||
lz = LazyEvaluate(lambda : f)
|
||||
|
||||
self.assertEqual(str(lz), str(f))
|
||||
self.assertEqual(format(lz), str(f))
|
||||
self.assertEqual(format(lz, '.1'), '0.5')
|
||||
|
274
.venv/Lib/site-packages/IPython/core/tests/test_pylabtools.py
Normal file
274
.venv/Lib/site-packages/IPython/core/tests/test_pylabtools.py
Normal file
@ -0,0 +1,274 @@
|
||||
"""Tests for pylab tools module.
|
||||
"""
|
||||
|
||||
# Copyright (c) IPython Development Team.
|
||||
# Distributed under the terms of the Modified BSD License.
|
||||
|
||||
|
||||
from binascii import a2b_base64
|
||||
from io import BytesIO
|
||||
|
||||
import pytest
|
||||
|
||||
matplotlib = pytest.importorskip("matplotlib")
|
||||
matplotlib.use('Agg')
|
||||
from matplotlib.figure import Figure
|
||||
|
||||
from matplotlib import pyplot as plt
|
||||
from matplotlib_inline import backend_inline
|
||||
import numpy as np
|
||||
|
||||
from IPython.core.getipython import get_ipython
|
||||
from IPython.core.interactiveshell import InteractiveShell
|
||||
from IPython.core.display import _PNG, _JPEG
|
||||
from .. import pylabtools as pt
|
||||
|
||||
from IPython.testing import decorators as dec
|
||||
|
||||
|
||||
def test_figure_to_svg():
|
||||
# simple empty-figure test
|
||||
fig = plt.figure()
|
||||
assert pt.print_figure(fig, "svg") is None
|
||||
|
||||
plt.close('all')
|
||||
|
||||
# simple check for at least svg-looking output
|
||||
fig = plt.figure()
|
||||
ax = fig.add_subplot(1,1,1)
|
||||
ax.plot([1,2,3])
|
||||
plt.draw()
|
||||
svg = pt.print_figure(fig, "svg")[:100].lower()
|
||||
assert "doctype svg" in svg
|
||||
|
||||
|
||||
def _check_pil_jpeg_bytes():
|
||||
"""Skip if PIL can't write JPEGs to BytesIO objects"""
|
||||
# PIL's JPEG plugin can't write to BytesIO objects
|
||||
# Pillow fixes this
|
||||
from PIL import Image
|
||||
buf = BytesIO()
|
||||
img = Image.new("RGB", (4,4))
|
||||
try:
|
||||
img.save(buf, 'jpeg')
|
||||
except Exception as e:
|
||||
ename = e.__class__.__name__
|
||||
raise pytest.skip("PIL can't write JPEG to BytesIO: %s: %s" % (ename, e)) from e
|
||||
|
||||
@dec.skip_without("PIL.Image")
|
||||
def test_figure_to_jpeg():
|
||||
_check_pil_jpeg_bytes()
|
||||
# simple check for at least jpeg-looking output
|
||||
fig = plt.figure()
|
||||
ax = fig.add_subplot(1,1,1)
|
||||
ax.plot([1,2,3])
|
||||
plt.draw()
|
||||
jpeg = pt.print_figure(fig, 'jpeg', pil_kwargs={'optimize': 50})[:100].lower()
|
||||
assert jpeg.startswith(_JPEG)
|
||||
|
||||
def test_retina_figure():
|
||||
# simple empty-figure test
|
||||
fig = plt.figure()
|
||||
assert pt.retina_figure(fig) == None
|
||||
plt.close('all')
|
||||
|
||||
fig = plt.figure()
|
||||
ax = fig.add_subplot(1,1,1)
|
||||
ax.plot([1,2,3])
|
||||
plt.draw()
|
||||
png, md = pt.retina_figure(fig)
|
||||
assert png.startswith(_PNG)
|
||||
assert "width" in md
|
||||
assert "height" in md
|
||||
|
||||
|
||||
_fmt_mime_map = {
|
||||
'png': 'image/png',
|
||||
'jpeg': 'image/jpeg',
|
||||
'pdf': 'application/pdf',
|
||||
'retina': 'image/png',
|
||||
'svg': 'image/svg+xml',
|
||||
}
|
||||
|
||||
def test_select_figure_formats_str():
|
||||
ip = get_ipython()
|
||||
for fmt, active_mime in _fmt_mime_map.items():
|
||||
pt.select_figure_formats(ip, fmt)
|
||||
for mime, f in ip.display_formatter.formatters.items():
|
||||
if mime == active_mime:
|
||||
assert Figure in f
|
||||
else:
|
||||
assert Figure not in f
|
||||
|
||||
def test_select_figure_formats_kwargs():
|
||||
ip = get_ipython()
|
||||
kwargs = dict(bbox_inches="tight")
|
||||
pt.select_figure_formats(ip, "png", **kwargs)
|
||||
formatter = ip.display_formatter.formatters["image/png"]
|
||||
f = formatter.lookup_by_type(Figure)
|
||||
cell = f.keywords
|
||||
expected = kwargs
|
||||
expected["base64"] = True
|
||||
expected["fmt"] = "png"
|
||||
assert cell == expected
|
||||
|
||||
# check that the formatter doesn't raise
|
||||
fig = plt.figure()
|
||||
ax = fig.add_subplot(1,1,1)
|
||||
ax.plot([1,2,3])
|
||||
plt.draw()
|
||||
formatter.enabled = True
|
||||
png = formatter(fig)
|
||||
assert isinstance(png, str)
|
||||
png_bytes = a2b_base64(png)
|
||||
assert png_bytes.startswith(_PNG)
|
||||
|
||||
def test_select_figure_formats_set():
|
||||
ip = get_ipython()
|
||||
for fmts in [
|
||||
{'png', 'svg'},
|
||||
['png'],
|
||||
('jpeg', 'pdf', 'retina'),
|
||||
{'svg'},
|
||||
]:
|
||||
active_mimes = {_fmt_mime_map[fmt] for fmt in fmts}
|
||||
pt.select_figure_formats(ip, fmts)
|
||||
for mime, f in ip.display_formatter.formatters.items():
|
||||
if mime in active_mimes:
|
||||
assert Figure in f
|
||||
else:
|
||||
assert Figure not in f
|
||||
|
||||
def test_select_figure_formats_bad():
|
||||
ip = get_ipython()
|
||||
with pytest.raises(ValueError):
|
||||
pt.select_figure_formats(ip, 'foo')
|
||||
with pytest.raises(ValueError):
|
||||
pt.select_figure_formats(ip, {'png', 'foo'})
|
||||
with pytest.raises(ValueError):
|
||||
pt.select_figure_formats(ip, ['retina', 'pdf', 'bar', 'bad'])
|
||||
|
||||
def test_import_pylab():
|
||||
ns = {}
|
||||
pt.import_pylab(ns, import_all=False)
|
||||
assert "plt" in ns
|
||||
assert ns["np"] == np
|
||||
|
||||
|
||||
from traitlets.config import Config
|
||||
|
||||
|
||||
class TestPylabSwitch(object):
|
||||
class Shell(InteractiveShell):
|
||||
def init_history(self):
|
||||
"""Sets up the command history, and starts regular autosaves."""
|
||||
self.config.HistoryManager.hist_file = ":memory:"
|
||||
super().init_history()
|
||||
|
||||
def enable_gui(self, gui):
|
||||
pass
|
||||
|
||||
def setup(self):
|
||||
import matplotlib
|
||||
def act_mpl(backend):
|
||||
matplotlib.rcParams['backend'] = backend
|
||||
|
||||
# Save rcParams since they get modified
|
||||
self._saved_rcParams = matplotlib.rcParams
|
||||
self._saved_rcParamsOrig = matplotlib.rcParamsOrig
|
||||
matplotlib.rcParams = dict(backend='Qt4Agg')
|
||||
matplotlib.rcParamsOrig = dict(backend='Qt4Agg')
|
||||
|
||||
# Mock out functions
|
||||
self._save_am = pt.activate_matplotlib
|
||||
pt.activate_matplotlib = act_mpl
|
||||
self._save_ip = pt.import_pylab
|
||||
pt.import_pylab = lambda *a,**kw:None
|
||||
self._save_cis = backend_inline.configure_inline_support
|
||||
backend_inline.configure_inline_support = lambda *a, **kw: None
|
||||
|
||||
def teardown(self):
|
||||
pt.activate_matplotlib = self._save_am
|
||||
pt.import_pylab = self._save_ip
|
||||
backend_inline.configure_inline_support = self._save_cis
|
||||
import matplotlib
|
||||
matplotlib.rcParams = self._saved_rcParams
|
||||
matplotlib.rcParamsOrig = self._saved_rcParamsOrig
|
||||
|
||||
def test_qt(self):
|
||||
|
||||
s = self.Shell()
|
||||
gui, backend = s.enable_matplotlib(None)
|
||||
assert gui == "qt"
|
||||
assert s.pylab_gui_select == "qt"
|
||||
|
||||
gui, backend = s.enable_matplotlib("inline")
|
||||
assert gui == "inline"
|
||||
assert s.pylab_gui_select == "qt"
|
||||
|
||||
gui, backend = s.enable_matplotlib("qt")
|
||||
assert gui == "qt"
|
||||
assert s.pylab_gui_select == "qt"
|
||||
|
||||
gui, backend = s.enable_matplotlib("inline")
|
||||
assert gui == "inline"
|
||||
assert s.pylab_gui_select == "qt"
|
||||
|
||||
gui, backend = s.enable_matplotlib()
|
||||
assert gui == "qt"
|
||||
assert s.pylab_gui_select == "qt"
|
||||
|
||||
def test_inline(self):
|
||||
s = self.Shell()
|
||||
gui, backend = s.enable_matplotlib("inline")
|
||||
assert gui == "inline"
|
||||
assert s.pylab_gui_select == None
|
||||
|
||||
gui, backend = s.enable_matplotlib("inline")
|
||||
assert gui == "inline"
|
||||
assert s.pylab_gui_select == None
|
||||
|
||||
gui, backend = s.enable_matplotlib("qt")
|
||||
assert gui == "qt"
|
||||
assert s.pylab_gui_select == "qt"
|
||||
|
||||
def test_inline_twice(self):
|
||||
"Using '%matplotlib inline' twice should not reset formatters"
|
||||
|
||||
ip = self.Shell()
|
||||
gui, backend = ip.enable_matplotlib("inline")
|
||||
assert gui == "inline"
|
||||
|
||||
fmts = {'png'}
|
||||
active_mimes = {_fmt_mime_map[fmt] for fmt in fmts}
|
||||
pt.select_figure_formats(ip, fmts)
|
||||
|
||||
gui, backend = ip.enable_matplotlib("inline")
|
||||
assert gui == "inline"
|
||||
|
||||
for mime, f in ip.display_formatter.formatters.items():
|
||||
if mime in active_mimes:
|
||||
assert Figure in f
|
||||
else:
|
||||
assert Figure not in f
|
||||
|
||||
def test_qt_gtk(self):
|
||||
s = self.Shell()
|
||||
gui, backend = s.enable_matplotlib("qt")
|
||||
assert gui == "qt"
|
||||
assert s.pylab_gui_select == "qt"
|
||||
|
||||
gui, backend = s.enable_matplotlib("gtk")
|
||||
assert gui == "qt"
|
||||
assert s.pylab_gui_select == "qt"
|
||||
|
||||
|
||||
def test_no_gui_backends():
|
||||
for k in ['agg', 'svg', 'pdf', 'ps']:
|
||||
assert k not in pt.backend2gui
|
||||
|
||||
|
||||
def test_figure_no_canvas():
|
||||
fig = Figure()
|
||||
fig.canvas = None
|
||||
pt.print_figure(fig)
|
622
.venv/Lib/site-packages/IPython/core/tests/test_run.py
Normal file
622
.venv/Lib/site-packages/IPython/core/tests/test_run.py
Normal file
@ -0,0 +1,622 @@
|
||||
# encoding: utf-8
|
||||
"""Tests for code execution (%run and related), which is particularly tricky.
|
||||
|
||||
Because of how %run manages namespaces, and the fact that we are trying here to
|
||||
verify subtle object deletion and reference counting issues, the %run tests
|
||||
will be kept in this separate file. This makes it easier to aggregate in one
|
||||
place the tricks needed to handle it; most other magics are much easier to test
|
||||
and we do so in a common test_magic file.
|
||||
|
||||
Note that any test using `run -i` should make sure to do a `reset` afterwards,
|
||||
as otherwise it may influence later tests.
|
||||
"""
|
||||
|
||||
# Copyright (c) IPython Development Team.
|
||||
# Distributed under the terms of the Modified BSD License.
|
||||
|
||||
|
||||
|
||||
import functools
|
||||
import os
|
||||
import platform
|
||||
import random
|
||||
import string
|
||||
import sys
|
||||
import textwrap
|
||||
import unittest
|
||||
from os.path import join as pjoin
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
from tempfile import TemporaryDirectory
|
||||
|
||||
from IPython.core import debugger
|
||||
from IPython.testing import decorators as dec
|
||||
from IPython.testing import tools as tt
|
||||
from IPython.utils.io import capture_output
|
||||
|
||||
|
||||
def doctest_refbug():
|
||||
"""Very nasty problem with references held by multiple runs of a script.
|
||||
See: https://github.com/ipython/ipython/issues/141
|
||||
|
||||
In [1]: _ip.clear_main_mod_cache()
|
||||
# random
|
||||
|
||||
In [2]: %run refbug
|
||||
|
||||
In [3]: call_f()
|
||||
lowercased: hello
|
||||
|
||||
In [4]: %run refbug
|
||||
|
||||
In [5]: call_f()
|
||||
lowercased: hello
|
||||
lowercased: hello
|
||||
"""
|
||||
|
||||
|
||||
def doctest_run_builtins():
|
||||
r"""Check that %run doesn't damage __builtins__.
|
||||
|
||||
In [1]: import tempfile
|
||||
|
||||
In [2]: bid1 = id(__builtins__)
|
||||
|
||||
In [3]: fname = tempfile.mkstemp('.py')[1]
|
||||
|
||||
In [3]: f = open(fname, 'w', encoding='utf-8')
|
||||
|
||||
In [4]: dummy= f.write('pass\n')
|
||||
|
||||
In [5]: f.flush()
|
||||
|
||||
In [6]: t1 = type(__builtins__)
|
||||
|
||||
In [7]: %run $fname
|
||||
|
||||
In [7]: f.close()
|
||||
|
||||
In [8]: bid2 = id(__builtins__)
|
||||
|
||||
In [9]: t2 = type(__builtins__)
|
||||
|
||||
In [10]: t1 == t2
|
||||
Out[10]: True
|
||||
|
||||
In [10]: bid1 == bid2
|
||||
Out[10]: True
|
||||
|
||||
In [12]: try:
|
||||
....: os.unlink(fname)
|
||||
....: except:
|
||||
....: pass
|
||||
....:
|
||||
"""
|
||||
|
||||
|
||||
def doctest_run_option_parser():
|
||||
r"""Test option parser in %run.
|
||||
|
||||
In [1]: %run print_argv.py
|
||||
[]
|
||||
|
||||
In [2]: %run print_argv.py print*.py
|
||||
['print_argv.py']
|
||||
|
||||
In [3]: %run -G print_argv.py print*.py
|
||||
['print*.py']
|
||||
|
||||
"""
|
||||
|
||||
|
||||
@dec.skip_win32
|
||||
def doctest_run_option_parser_for_posix():
|
||||
r"""Test option parser in %run (Linux/OSX specific).
|
||||
|
||||
You need double quote to escape glob in POSIX systems:
|
||||
|
||||
In [1]: %run print_argv.py print\\*.py
|
||||
['print*.py']
|
||||
|
||||
You can't use quote to escape glob in POSIX systems:
|
||||
|
||||
In [2]: %run print_argv.py 'print*.py'
|
||||
['print_argv.py']
|
||||
|
||||
"""
|
||||
|
||||
|
||||
doctest_run_option_parser_for_posix.__skip_doctest__ = sys.platform == "win32"
|
||||
|
||||
|
||||
@dec.skip_if_not_win32
|
||||
def doctest_run_option_parser_for_windows():
|
||||
r"""Test option parser in %run (Windows specific).
|
||||
|
||||
In Windows, you can't escape ``*` `by backslash:
|
||||
|
||||
In [1]: %run print_argv.py print\\*.py
|
||||
['print\\\\*.py']
|
||||
|
||||
You can use quote to escape glob:
|
||||
|
||||
In [2]: %run print_argv.py 'print*.py'
|
||||
["'print*.py'"]
|
||||
|
||||
"""
|
||||
|
||||
|
||||
doctest_run_option_parser_for_windows.__skip_doctest__ = sys.platform != "win32"
|
||||
|
||||
|
||||
def doctest_reset_del():
|
||||
"""Test that resetting doesn't cause errors in __del__ methods.
|
||||
|
||||
In [2]: class A(object):
|
||||
...: def __del__(self):
|
||||
...: print(str("Hi"))
|
||||
...:
|
||||
|
||||
In [3]: a = A()
|
||||
|
||||
In [4]: get_ipython().reset(); import gc; x = gc.collect(0)
|
||||
Hi
|
||||
|
||||
In [5]: 1+1
|
||||
Out[5]: 2
|
||||
"""
|
||||
|
||||
# For some tests, it will be handy to organize them in a class with a common
|
||||
# setup that makes a temp file
|
||||
|
||||
class TestMagicRunPass(tt.TempFileMixin):
|
||||
|
||||
def setUp(self):
|
||||
content = "a = [1,2,3]\nb = 1"
|
||||
self.mktmp(content)
|
||||
|
||||
def run_tmpfile(self):
|
||||
_ip = get_ipython()
|
||||
# This fails on Windows if self.tmpfile.name has spaces or "~" in it.
|
||||
# See below and ticket https://bugs.launchpad.net/bugs/366353
|
||||
_ip.magic('run %s' % self.fname)
|
||||
|
||||
def run_tmpfile_p(self):
|
||||
_ip = get_ipython()
|
||||
# This fails on Windows if self.tmpfile.name has spaces or "~" in it.
|
||||
# See below and ticket https://bugs.launchpad.net/bugs/366353
|
||||
_ip.magic('run -p %s' % self.fname)
|
||||
|
||||
def test_builtins_id(self):
|
||||
"""Check that %run doesn't damage __builtins__ """
|
||||
_ip = get_ipython()
|
||||
# Test that the id of __builtins__ is not modified by %run
|
||||
bid1 = id(_ip.user_ns['__builtins__'])
|
||||
self.run_tmpfile()
|
||||
bid2 = id(_ip.user_ns['__builtins__'])
|
||||
assert bid1 == bid2
|
||||
|
||||
def test_builtins_type(self):
|
||||
"""Check that the type of __builtins__ doesn't change with %run.
|
||||
|
||||
However, the above could pass if __builtins__ was already modified to
|
||||
be a dict (it should be a module) by a previous use of %run. So we
|
||||
also check explicitly that it really is a module:
|
||||
"""
|
||||
_ip = get_ipython()
|
||||
self.run_tmpfile()
|
||||
assert type(_ip.user_ns["__builtins__"]) == type(sys)
|
||||
|
||||
def test_run_profile(self):
|
||||
"""Test that the option -p, which invokes the profiler, do not
|
||||
crash by invoking execfile"""
|
||||
self.run_tmpfile_p()
|
||||
|
||||
def test_run_debug_twice(self):
|
||||
# https://github.com/ipython/ipython/issues/10028
|
||||
_ip = get_ipython()
|
||||
with tt.fake_input(['c']):
|
||||
_ip.magic('run -d %s' % self.fname)
|
||||
with tt.fake_input(['c']):
|
||||
_ip.magic('run -d %s' % self.fname)
|
||||
|
||||
def test_run_debug_twice_with_breakpoint(self):
|
||||
"""Make a valid python temp file."""
|
||||
_ip = get_ipython()
|
||||
with tt.fake_input(['b 2', 'c', 'c']):
|
||||
_ip.magic('run -d %s' % self.fname)
|
||||
|
||||
with tt.fake_input(['c']):
|
||||
with tt.AssertNotPrints('KeyError'):
|
||||
_ip.magic('run -d %s' % self.fname)
|
||||
|
||||
|
||||
class TestMagicRunSimple(tt.TempFileMixin):
|
||||
|
||||
def test_simpledef(self):
|
||||
"""Test that simple class definitions work."""
|
||||
src = ("class foo: pass\n"
|
||||
"def f(): return foo()")
|
||||
self.mktmp(src)
|
||||
_ip.magic("run %s" % self.fname)
|
||||
_ip.run_cell("t = isinstance(f(), foo)")
|
||||
assert _ip.user_ns["t"] is True
|
||||
|
||||
@pytest.mark.xfail(
|
||||
platform.python_implementation() == "PyPy",
|
||||
reason="expecting __del__ call on exit is unreliable and doesn't happen on PyPy",
|
||||
)
|
||||
def test_obj_del(self):
|
||||
"""Test that object's __del__ methods are called on exit."""
|
||||
src = ("class A(object):\n"
|
||||
" def __del__(self):\n"
|
||||
" print('object A deleted')\n"
|
||||
"a = A()\n")
|
||||
self.mktmp(src)
|
||||
err = None
|
||||
tt.ipexec_validate(self.fname, 'object A deleted', err)
|
||||
|
||||
def test_aggressive_namespace_cleanup(self):
|
||||
"""Test that namespace cleanup is not too aggressive GH-238
|
||||
|
||||
Returning from another run magic deletes the namespace"""
|
||||
# see ticket https://github.com/ipython/ipython/issues/238
|
||||
|
||||
with tt.TempFileMixin() as empty:
|
||||
empty.mktmp("")
|
||||
# On Windows, the filename will have \users in it, so we need to use the
|
||||
# repr so that the \u becomes \\u.
|
||||
src = (
|
||||
"ip = get_ipython()\n"
|
||||
"for i in range(5):\n"
|
||||
" try:\n"
|
||||
" ip.magic(%r)\n"
|
||||
" except NameError as e:\n"
|
||||
" print(i)\n"
|
||||
" break\n" % ("run " + empty.fname)
|
||||
)
|
||||
self.mktmp(src)
|
||||
_ip.magic("run %s" % self.fname)
|
||||
_ip.run_cell("ip == get_ipython()")
|
||||
assert _ip.user_ns["i"] == 4
|
||||
|
||||
def test_run_second(self):
|
||||
"""Test that running a second file doesn't clobber the first, gh-3547"""
|
||||
self.mktmp("avar = 1\n" "def afunc():\n" " return avar\n")
|
||||
|
||||
with tt.TempFileMixin() as empty:
|
||||
empty.mktmp("")
|
||||
|
||||
_ip.magic("run %s" % self.fname)
|
||||
_ip.magic("run %s" % empty.fname)
|
||||
assert _ip.user_ns["afunc"]() == 1
|
||||
|
||||
def test_tclass(self):
|
||||
mydir = os.path.dirname(__file__)
|
||||
tc = os.path.join(mydir, "tclass")
|
||||
src = f"""\
|
||||
import gc
|
||||
%run "{tc}" C-first
|
||||
gc.collect(0)
|
||||
%run "{tc}" C-second
|
||||
gc.collect(0)
|
||||
%run "{tc}" C-third
|
||||
gc.collect(0)
|
||||
%reset -f
|
||||
"""
|
||||
self.mktmp(src, ".ipy")
|
||||
out = """\
|
||||
ARGV 1-: ['C-first']
|
||||
ARGV 1-: ['C-second']
|
||||
tclass.py: deleting object: C-first
|
||||
ARGV 1-: ['C-third']
|
||||
tclass.py: deleting object: C-second
|
||||
tclass.py: deleting object: C-third
|
||||
"""
|
||||
err = None
|
||||
tt.ipexec_validate(self.fname, out, err)
|
||||
|
||||
def test_run_i_after_reset(self):
|
||||
"""Check that %run -i still works after %reset (gh-693)"""
|
||||
src = "yy = zz\n"
|
||||
self.mktmp(src)
|
||||
_ip.run_cell("zz = 23")
|
||||
try:
|
||||
_ip.magic("run -i %s" % self.fname)
|
||||
assert _ip.user_ns["yy"] == 23
|
||||
finally:
|
||||
_ip.magic('reset -f')
|
||||
|
||||
_ip.run_cell("zz = 23")
|
||||
try:
|
||||
_ip.magic("run -i %s" % self.fname)
|
||||
assert _ip.user_ns["yy"] == 23
|
||||
finally:
|
||||
_ip.magic('reset -f')
|
||||
|
||||
def test_unicode(self):
|
||||
"""Check that files in odd encodings are accepted."""
|
||||
mydir = os.path.dirname(__file__)
|
||||
na = os.path.join(mydir, 'nonascii.py')
|
||||
_ip.magic('run "%s"' % na)
|
||||
assert _ip.user_ns["u"] == "Ўт№Ф"
|
||||
|
||||
def test_run_py_file_attribute(self):
|
||||
"""Test handling of `__file__` attribute in `%run <file>.py`."""
|
||||
src = "t = __file__\n"
|
||||
self.mktmp(src)
|
||||
_missing = object()
|
||||
file1 = _ip.user_ns.get('__file__', _missing)
|
||||
_ip.magic('run %s' % self.fname)
|
||||
file2 = _ip.user_ns.get('__file__', _missing)
|
||||
|
||||
# Check that __file__ was equal to the filename in the script's
|
||||
# namespace.
|
||||
assert _ip.user_ns["t"] == self.fname
|
||||
|
||||
# Check that __file__ was not leaked back into user_ns.
|
||||
assert file1 == file2
|
||||
|
||||
def test_run_ipy_file_attribute(self):
|
||||
"""Test handling of `__file__` attribute in `%run <file.ipy>`."""
|
||||
src = "t = __file__\n"
|
||||
self.mktmp(src, ext='.ipy')
|
||||
_missing = object()
|
||||
file1 = _ip.user_ns.get('__file__', _missing)
|
||||
_ip.magic('run %s' % self.fname)
|
||||
file2 = _ip.user_ns.get('__file__', _missing)
|
||||
|
||||
# Check that __file__ was equal to the filename in the script's
|
||||
# namespace.
|
||||
assert _ip.user_ns["t"] == self.fname
|
||||
|
||||
# Check that __file__ was not leaked back into user_ns.
|
||||
assert file1 == file2
|
||||
|
||||
def test_run_formatting(self):
|
||||
""" Test that %run -t -N<N> does not raise a TypeError for N > 1."""
|
||||
src = "pass"
|
||||
self.mktmp(src)
|
||||
_ip.magic('run -t -N 1 %s' % self.fname)
|
||||
_ip.magic('run -t -N 10 %s' % self.fname)
|
||||
|
||||
def test_ignore_sys_exit(self):
|
||||
"""Test the -e option to ignore sys.exit()"""
|
||||
src = "import sys; sys.exit(1)"
|
||||
self.mktmp(src)
|
||||
with tt.AssertPrints('SystemExit'):
|
||||
_ip.magic('run %s' % self.fname)
|
||||
|
||||
with tt.AssertNotPrints('SystemExit'):
|
||||
_ip.magic('run -e %s' % self.fname)
|
||||
|
||||
def test_run_nb(self):
|
||||
"""Test %run notebook.ipynb"""
|
||||
pytest.importorskip("nbformat")
|
||||
from nbformat import v4, writes
|
||||
nb = v4.new_notebook(
|
||||
cells=[
|
||||
v4.new_markdown_cell("The Ultimate Question of Everything"),
|
||||
v4.new_code_cell("answer=42")
|
||||
]
|
||||
)
|
||||
src = writes(nb, version=4)
|
||||
self.mktmp(src, ext='.ipynb')
|
||||
|
||||
_ip.magic("run %s" % self.fname)
|
||||
|
||||
assert _ip.user_ns["answer"] == 42
|
||||
|
||||
def test_run_nb_error(self):
|
||||
"""Test %run notebook.ipynb error"""
|
||||
pytest.importorskip("nbformat")
|
||||
from nbformat import v4, writes
|
||||
|
||||
# %run when a file name isn't provided
|
||||
pytest.raises(Exception, _ip.magic, "run")
|
||||
|
||||
# %run when a file doesn't exist
|
||||
pytest.raises(Exception, _ip.magic, "run foobar.ipynb")
|
||||
|
||||
# %run on a notebook with an error
|
||||
nb = v4.new_notebook(
|
||||
cells=[
|
||||
v4.new_code_cell("0/0")
|
||||
]
|
||||
)
|
||||
src = writes(nb, version=4)
|
||||
self.mktmp(src, ext='.ipynb')
|
||||
pytest.raises(Exception, _ip.magic, "run %s" % self.fname)
|
||||
|
||||
def test_file_options(self):
|
||||
src = ('import sys\n'
|
||||
'a = " ".join(sys.argv[1:])\n')
|
||||
self.mktmp(src)
|
||||
test_opts = "-x 3 --verbose"
|
||||
_ip.run_line_magic("run", "{0} {1}".format(self.fname, test_opts))
|
||||
assert _ip.user_ns["a"] == test_opts
|
||||
|
||||
|
||||
class TestMagicRunWithPackage(unittest.TestCase):
|
||||
|
||||
def writefile(self, name, content):
|
||||
path = os.path.join(self.tempdir.name, name)
|
||||
d = os.path.dirname(path)
|
||||
if not os.path.isdir(d):
|
||||
os.makedirs(d)
|
||||
with open(path, "w", encoding="utf-8") as f:
|
||||
f.write(textwrap.dedent(content))
|
||||
|
||||
def setUp(self):
|
||||
self.package = package = 'tmp{0}'.format(''.join([random.choice(string.ascii_letters) for i in range(10)]))
|
||||
"""Temporary (probably) valid python package name."""
|
||||
|
||||
self.value = int(random.random() * 10000)
|
||||
|
||||
self.tempdir = TemporaryDirectory()
|
||||
self.__orig_cwd = os.getcwd()
|
||||
sys.path.insert(0, self.tempdir.name)
|
||||
|
||||
self.writefile(os.path.join(package, '__init__.py'), '')
|
||||
self.writefile(os.path.join(package, 'sub.py'), """
|
||||
x = {0!r}
|
||||
""".format(self.value))
|
||||
self.writefile(os.path.join(package, 'relative.py'), """
|
||||
from .sub import x
|
||||
""")
|
||||
self.writefile(os.path.join(package, 'absolute.py'), """
|
||||
from {0}.sub import x
|
||||
""".format(package))
|
||||
self.writefile(os.path.join(package, 'args.py'), """
|
||||
import sys
|
||||
a = " ".join(sys.argv[1:])
|
||||
""".format(package))
|
||||
|
||||
def tearDown(self):
|
||||
os.chdir(self.__orig_cwd)
|
||||
sys.path[:] = [p for p in sys.path if p != self.tempdir.name]
|
||||
self.tempdir.cleanup()
|
||||
|
||||
def check_run_submodule(self, submodule, opts=''):
|
||||
_ip.user_ns.pop('x', None)
|
||||
_ip.magic('run {2} -m {0}.{1}'.format(self.package, submodule, opts))
|
||||
self.assertEqual(_ip.user_ns['x'], self.value,
|
||||
'Variable `x` is not loaded from module `{0}`.'
|
||||
.format(submodule))
|
||||
|
||||
def test_run_submodule_with_absolute_import(self):
|
||||
self.check_run_submodule('absolute')
|
||||
|
||||
def test_run_submodule_with_relative_import(self):
|
||||
"""Run submodule that has a relative import statement (#2727)."""
|
||||
self.check_run_submodule('relative')
|
||||
|
||||
def test_prun_submodule_with_absolute_import(self):
|
||||
self.check_run_submodule('absolute', '-p')
|
||||
|
||||
def test_prun_submodule_with_relative_import(self):
|
||||
self.check_run_submodule('relative', '-p')
|
||||
|
||||
def with_fake_debugger(func):
|
||||
@functools.wraps(func)
|
||||
def wrapper(*args, **kwds):
|
||||
with patch.object(debugger.Pdb, 'run', staticmethod(eval)):
|
||||
return func(*args, **kwds)
|
||||
return wrapper
|
||||
|
||||
@with_fake_debugger
|
||||
def test_debug_run_submodule_with_absolute_import(self):
|
||||
self.check_run_submodule('absolute', '-d')
|
||||
|
||||
@with_fake_debugger
|
||||
def test_debug_run_submodule_with_relative_import(self):
|
||||
self.check_run_submodule('relative', '-d')
|
||||
|
||||
def test_module_options(self):
|
||||
_ip.user_ns.pop("a", None)
|
||||
test_opts = "-x abc -m test"
|
||||
_ip.run_line_magic("run", "-m {0}.args {1}".format(self.package, test_opts))
|
||||
assert _ip.user_ns["a"] == test_opts
|
||||
|
||||
def test_module_options_with_separator(self):
|
||||
_ip.user_ns.pop("a", None)
|
||||
test_opts = "-x abc -m test"
|
||||
_ip.run_line_magic("run", "-m {0}.args -- {1}".format(self.package, test_opts))
|
||||
assert _ip.user_ns["a"] == test_opts
|
||||
|
||||
|
||||
def test_run__name__():
|
||||
with TemporaryDirectory() as td:
|
||||
path = pjoin(td, "foo.py")
|
||||
with open(path, "w", encoding="utf-8") as f:
|
||||
f.write("q = __name__")
|
||||
|
||||
_ip.user_ns.pop("q", None)
|
||||
_ip.magic("run {}".format(path))
|
||||
assert _ip.user_ns.pop("q") == "__main__"
|
||||
|
||||
_ip.magic("run -n {}".format(path))
|
||||
assert _ip.user_ns.pop("q") == "foo"
|
||||
|
||||
try:
|
||||
_ip.magic("run -i -n {}".format(path))
|
||||
assert _ip.user_ns.pop("q") == "foo"
|
||||
finally:
|
||||
_ip.magic('reset -f')
|
||||
|
||||
|
||||
def test_run_tb():
|
||||
"""Test traceback offset in %run"""
|
||||
with TemporaryDirectory() as td:
|
||||
path = pjoin(td, "foo.py")
|
||||
with open(path, "w", encoding="utf-8") as f:
|
||||
f.write(
|
||||
"\n".join(
|
||||
[
|
||||
"def foo():",
|
||||
" return bar()",
|
||||
"def bar():",
|
||||
" raise RuntimeError('hello!')",
|
||||
"foo()",
|
||||
]
|
||||
)
|
||||
)
|
||||
with capture_output() as io:
|
||||
_ip.magic('run {}'.format(path))
|
||||
out = io.stdout
|
||||
assert "execfile" not in out
|
||||
assert "RuntimeError" in out
|
||||
assert out.count("---->") == 3
|
||||
del ip.user_ns['bar']
|
||||
del ip.user_ns['foo']
|
||||
|
||||
|
||||
def test_multiprocessing_run():
|
||||
"""Set we can run mutiprocesgin without messing up up main namespace
|
||||
|
||||
Note that import `nose.tools as nt` mdify the value s
|
||||
sys.module['__mp_main__'] so we need to temporarily set it to None to test
|
||||
the issue.
|
||||
"""
|
||||
with TemporaryDirectory() as td:
|
||||
mpm = sys.modules.get('__mp_main__')
|
||||
sys.modules['__mp_main__'] = None
|
||||
try:
|
||||
path = pjoin(td, "test.py")
|
||||
with open(path, "w", encoding="utf-8") as f:
|
||||
f.write("import multiprocessing\nprint('hoy')")
|
||||
with capture_output() as io:
|
||||
_ip.run_line_magic('run', path)
|
||||
_ip.run_cell("i_m_undefined")
|
||||
out = io.stdout
|
||||
assert "hoy" in out
|
||||
assert "AttributeError" not in out
|
||||
assert "NameError" in out
|
||||
assert out.count("---->") == 1
|
||||
except:
|
||||
raise
|
||||
finally:
|
||||
sys.modules['__mp_main__'] = mpm
|
||||
|
||||
|
||||
def test_script_tb():
|
||||
"""Test traceback offset in `ipython script.py`"""
|
||||
with TemporaryDirectory() as td:
|
||||
path = pjoin(td, "foo.py")
|
||||
with open(path, "w", encoding="utf-8") as f:
|
||||
f.write(
|
||||
"\n".join(
|
||||
[
|
||||
"def foo():",
|
||||
" return bar()",
|
||||
"def bar():",
|
||||
" raise RuntimeError('hello!')",
|
||||
"foo()",
|
||||
]
|
||||
)
|
||||
)
|
||||
out, err = tt.ipexec(path)
|
||||
assert "execfile" not in out
|
||||
assert "RuntimeError" in out
|
||||
assert out.count("---->") == 3
|
56
.venv/Lib/site-packages/IPython/core/tests/test_shellapp.py
Normal file
56
.venv/Lib/site-packages/IPython/core/tests/test_shellapp.py
Normal file
@ -0,0 +1,56 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Tests for shellapp module.
|
||||
|
||||
Authors
|
||||
-------
|
||||
* Bradley Froehle
|
||||
"""
|
||||
#-----------------------------------------------------------------------------
|
||||
# Copyright (C) 2012 The IPython Development Team
|
||||
#
|
||||
# Distributed under the terms of the BSD License. The full license is in
|
||||
# the file COPYING, distributed as part of this software.
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Imports
|
||||
#-----------------------------------------------------------------------------
|
||||
import unittest
|
||||
|
||||
from IPython.testing import decorators as dec
|
||||
from IPython.testing import tools as tt
|
||||
|
||||
|
||||
class TestFileToRun(tt.TempFileMixin, unittest.TestCase):
|
||||
"""Test the behavior of the file_to_run parameter."""
|
||||
|
||||
def test_py_script_file_attribute(self):
|
||||
"""Test that `__file__` is set when running `ipython file.py`"""
|
||||
src = "print(__file__)\n"
|
||||
self.mktmp(src)
|
||||
|
||||
err = None
|
||||
tt.ipexec_validate(self.fname, self.fname, err)
|
||||
|
||||
def test_ipy_script_file_attribute(self):
|
||||
"""Test that `__file__` is set when running `ipython file.ipy`"""
|
||||
src = "print(__file__)\n"
|
||||
self.mktmp(src, ext='.ipy')
|
||||
|
||||
err = None
|
||||
tt.ipexec_validate(self.fname, self.fname, err)
|
||||
|
||||
# The commands option to ipexec_validate doesn't work on Windows, and it
|
||||
# doesn't seem worth fixing
|
||||
@dec.skip_win32
|
||||
def test_py_script_file_attribute_interactively(self):
|
||||
"""Test that `__file__` is not set after `ipython -i file.py`"""
|
||||
src = "True\n"
|
||||
self.mktmp(src)
|
||||
|
||||
out, err = tt.ipexec(
|
||||
self.fname,
|
||||
options=["-i"],
|
||||
commands=['"__file__" in globals()', "print(123)", "exit()"],
|
||||
)
|
||||
assert "False" in out, f"Subprocess stderr:\n{err}\n-----"
|
@ -0,0 +1,38 @@
|
||||
# coding: utf-8
|
||||
|
||||
from IPython.core.splitinput import split_user_input, LineInfo
|
||||
from IPython.testing import tools as tt
|
||||
|
||||
tests = [
|
||||
("x=1", ("", "", "x", "=1")),
|
||||
("?", ("", "?", "", "")),
|
||||
("??", ("", "??", "", "")),
|
||||
(" ?", (" ", "?", "", "")),
|
||||
(" ??", (" ", "??", "", "")),
|
||||
("??x", ("", "??", "x", "")),
|
||||
("?x=1", ("", "?", "x", "=1")),
|
||||
("!ls", ("", "!", "ls", "")),
|
||||
(" !ls", (" ", "!", "ls", "")),
|
||||
("!!ls", ("", "!!", "ls", "")),
|
||||
(" !!ls", (" ", "!!", "ls", "")),
|
||||
(",ls", ("", ",", "ls", "")),
|
||||
(";ls", ("", ";", "ls", "")),
|
||||
(" ;ls", (" ", ";", "ls", "")),
|
||||
("f.g(x)", ("", "", "f.g", "(x)")),
|
||||
("f.g (x)", ("", "", "f.g", "(x)")),
|
||||
("?%hist1", ("", "?", "%hist1", "")),
|
||||
("?%%hist2", ("", "?", "%%hist2", "")),
|
||||
("??%hist3", ("", "??", "%hist3", "")),
|
||||
("??%%hist4", ("", "??", "%%hist4", "")),
|
||||
("?x*", ("", "?", "x*", "")),
|
||||
]
|
||||
tests.append(("Pérez Fernando", ("", "", "Pérez", "Fernando")))
|
||||
|
||||
|
||||
def test_split_user_input():
|
||||
return tt.check_pairs(split_user_input, tests)
|
||||
|
||||
def test_LineInfo():
|
||||
"""Simple test for LineInfo construction and str()"""
|
||||
linfo = LineInfo(" %cd /home")
|
||||
assert str(linfo) == "LineInfo [ |%|cd|/home]"
|
409
.venv/Lib/site-packages/IPython/core/tests/test_ultratb.py
Normal file
409
.venv/Lib/site-packages/IPython/core/tests/test_ultratb.py
Normal file
@ -0,0 +1,409 @@
|
||||
# encoding: utf-8
|
||||
"""Tests for IPython.core.ultratb
|
||||
"""
|
||||
import io
|
||||
import logging
|
||||
import os.path
|
||||
import platform
|
||||
import re
|
||||
import sys
|
||||
import traceback
|
||||
import unittest
|
||||
from textwrap import dedent
|
||||
|
||||
from tempfile import TemporaryDirectory
|
||||
|
||||
from IPython.core.ultratb import ColorTB, VerboseTB
|
||||
from IPython.testing import tools as tt
|
||||
from IPython.testing.decorators import onlyif_unicode_paths
|
||||
from IPython.utils.syspathcontext import prepended_to_syspath
|
||||
|
||||
file_1 = """1
|
||||
2
|
||||
3
|
||||
def f():
|
||||
1/0
|
||||
"""
|
||||
|
||||
file_2 = """def f():
|
||||
1/0
|
||||
"""
|
||||
|
||||
|
||||
def recursionlimit(frames):
|
||||
"""
|
||||
decorator to set the recursion limit temporarily
|
||||
"""
|
||||
|
||||
def inner(test_function):
|
||||
def wrapper(*args, **kwargs):
|
||||
rl = sys.getrecursionlimit()
|
||||
sys.setrecursionlimit(frames)
|
||||
try:
|
||||
return test_function(*args, **kwargs)
|
||||
finally:
|
||||
sys.setrecursionlimit(rl)
|
||||
|
||||
return wrapper
|
||||
|
||||
return inner
|
||||
|
||||
|
||||
class ChangedPyFileTest(unittest.TestCase):
|
||||
def test_changing_py_file(self):
|
||||
"""Traceback produced if the line where the error occurred is missing?
|
||||
|
||||
https://github.com/ipython/ipython/issues/1456
|
||||
"""
|
||||
with TemporaryDirectory() as td:
|
||||
fname = os.path.join(td, "foo.py")
|
||||
with open(fname, "w", encoding="utf-8") as f:
|
||||
f.write(file_1)
|
||||
|
||||
with prepended_to_syspath(td):
|
||||
ip.run_cell("import foo")
|
||||
|
||||
with tt.AssertPrints("ZeroDivisionError"):
|
||||
ip.run_cell("foo.f()")
|
||||
|
||||
# Make the file shorter, so the line of the error is missing.
|
||||
with open(fname, "w", encoding="utf-8") as f:
|
||||
f.write(file_2)
|
||||
|
||||
# For some reason, this was failing on the *second* call after
|
||||
# changing the file, so we call f() twice.
|
||||
with tt.AssertNotPrints("Internal Python error", channel='stderr'):
|
||||
with tt.AssertPrints("ZeroDivisionError"):
|
||||
ip.run_cell("foo.f()")
|
||||
with tt.AssertPrints("ZeroDivisionError"):
|
||||
ip.run_cell("foo.f()")
|
||||
|
||||
iso_8859_5_file = u'''# coding: iso-8859-5
|
||||
|
||||
def fail():
|
||||
"""дбИЖ"""
|
||||
1/0 # дбИЖ
|
||||
'''
|
||||
|
||||
class NonAsciiTest(unittest.TestCase):
|
||||
@onlyif_unicode_paths
|
||||
def test_nonascii_path(self):
|
||||
# Non-ascii directory name as well.
|
||||
with TemporaryDirectory(suffix=u'é') as td:
|
||||
fname = os.path.join(td, u"fooé.py")
|
||||
with open(fname, "w", encoding="utf-8") as f:
|
||||
f.write(file_1)
|
||||
|
||||
with prepended_to_syspath(td):
|
||||
ip.run_cell("import foo")
|
||||
|
||||
with tt.AssertPrints("ZeroDivisionError"):
|
||||
ip.run_cell("foo.f()")
|
||||
|
||||
def test_iso8859_5(self):
|
||||
with TemporaryDirectory() as td:
|
||||
fname = os.path.join(td, 'dfghjkl.py')
|
||||
|
||||
with io.open(fname, 'w', encoding='iso-8859-5') as f:
|
||||
f.write(iso_8859_5_file)
|
||||
|
||||
with prepended_to_syspath(td):
|
||||
ip.run_cell("from dfghjkl import fail")
|
||||
|
||||
with tt.AssertPrints("ZeroDivisionError"):
|
||||
with tt.AssertPrints(u'дбИЖ', suppress=False):
|
||||
ip.run_cell('fail()')
|
||||
|
||||
def test_nonascii_msg(self):
|
||||
cell = u"raise Exception('é')"
|
||||
expected = u"Exception('é')"
|
||||
ip.run_cell("%xmode plain")
|
||||
with tt.AssertPrints(expected):
|
||||
ip.run_cell(cell)
|
||||
|
||||
ip.run_cell("%xmode verbose")
|
||||
with tt.AssertPrints(expected):
|
||||
ip.run_cell(cell)
|
||||
|
||||
ip.run_cell("%xmode context")
|
||||
with tt.AssertPrints(expected):
|
||||
ip.run_cell(cell)
|
||||
|
||||
ip.run_cell("%xmode minimal")
|
||||
with tt.AssertPrints(u"Exception: é"):
|
||||
ip.run_cell(cell)
|
||||
|
||||
# Put this back into Context mode for later tests.
|
||||
ip.run_cell("%xmode context")
|
||||
|
||||
class NestedGenExprTestCase(unittest.TestCase):
|
||||
"""
|
||||
Regression test for the following issues:
|
||||
https://github.com/ipython/ipython/issues/8293
|
||||
https://github.com/ipython/ipython/issues/8205
|
||||
"""
|
||||
def test_nested_genexpr(self):
|
||||
code = dedent(
|
||||
"""\
|
||||
class SpecificException(Exception):
|
||||
pass
|
||||
|
||||
def foo(x):
|
||||
raise SpecificException("Success!")
|
||||
|
||||
sum(sum(foo(x) for _ in [0]) for x in [0])
|
||||
"""
|
||||
)
|
||||
with tt.AssertPrints('SpecificException: Success!', suppress=False):
|
||||
ip.run_cell(code)
|
||||
|
||||
|
||||
indentationerror_file = """if True:
|
||||
zoon()
|
||||
"""
|
||||
|
||||
class IndentationErrorTest(unittest.TestCase):
|
||||
def test_indentationerror_shows_line(self):
|
||||
# See issue gh-2398
|
||||
with tt.AssertPrints("IndentationError"):
|
||||
with tt.AssertPrints("zoon()", suppress=False):
|
||||
ip.run_cell(indentationerror_file)
|
||||
|
||||
with TemporaryDirectory() as td:
|
||||
fname = os.path.join(td, "foo.py")
|
||||
with open(fname, "w", encoding="utf-8") as f:
|
||||
f.write(indentationerror_file)
|
||||
|
||||
with tt.AssertPrints("IndentationError"):
|
||||
with tt.AssertPrints("zoon()", suppress=False):
|
||||
ip.magic('run %s' % fname)
|
||||
|
||||
se_file_1 = """1
|
||||
2
|
||||
7/
|
||||
"""
|
||||
|
||||
se_file_2 = """7/
|
||||
"""
|
||||
|
||||
class SyntaxErrorTest(unittest.TestCase):
|
||||
|
||||
def test_syntaxerror_no_stacktrace_at_compile_time(self):
|
||||
syntax_error_at_compile_time = """
|
||||
def foo():
|
||||
..
|
||||
"""
|
||||
with tt.AssertPrints("SyntaxError"):
|
||||
ip.run_cell(syntax_error_at_compile_time)
|
||||
|
||||
with tt.AssertNotPrints("foo()"):
|
||||
ip.run_cell(syntax_error_at_compile_time)
|
||||
|
||||
def test_syntaxerror_stacktrace_when_running_compiled_code(self):
|
||||
syntax_error_at_runtime = """
|
||||
def foo():
|
||||
eval("..")
|
||||
|
||||
def bar():
|
||||
foo()
|
||||
|
||||
bar()
|
||||
"""
|
||||
with tt.AssertPrints("SyntaxError"):
|
||||
ip.run_cell(syntax_error_at_runtime)
|
||||
# Assert syntax error during runtime generate stacktrace
|
||||
with tt.AssertPrints(["foo()", "bar()"]):
|
||||
ip.run_cell(syntax_error_at_runtime)
|
||||
del ip.user_ns['bar']
|
||||
del ip.user_ns['foo']
|
||||
|
||||
def test_changing_py_file(self):
|
||||
with TemporaryDirectory() as td:
|
||||
fname = os.path.join(td, "foo.py")
|
||||
with open(fname, "w", encoding="utf-8") as f:
|
||||
f.write(se_file_1)
|
||||
|
||||
with tt.AssertPrints(["7/", "SyntaxError"]):
|
||||
ip.magic("run " + fname)
|
||||
|
||||
# Modify the file
|
||||
with open(fname, "w", encoding="utf-8") as f:
|
||||
f.write(se_file_2)
|
||||
|
||||
# The SyntaxError should point to the correct line
|
||||
with tt.AssertPrints(["7/", "SyntaxError"]):
|
||||
ip.magic("run " + fname)
|
||||
|
||||
def test_non_syntaxerror(self):
|
||||
# SyntaxTB may be called with an error other than a SyntaxError
|
||||
# See e.g. gh-4361
|
||||
try:
|
||||
raise ValueError('QWERTY')
|
||||
except ValueError:
|
||||
with tt.AssertPrints('QWERTY'):
|
||||
ip.showsyntaxerror()
|
||||
|
||||
import sys
|
||||
|
||||
if sys.version_info < (3, 9) and platform.python_implementation() != "PyPy":
|
||||
"""
|
||||
New 3.9 Pgen Parser does not raise Memory error, except on failed malloc.
|
||||
"""
|
||||
class MemoryErrorTest(unittest.TestCase):
|
||||
def test_memoryerror(self):
|
||||
memoryerror_code = "(" * 200 + ")" * 200
|
||||
with tt.AssertPrints("MemoryError"):
|
||||
ip.run_cell(memoryerror_code)
|
||||
|
||||
|
||||
class Python3ChainedExceptionsTest(unittest.TestCase):
|
||||
DIRECT_CAUSE_ERROR_CODE = """
|
||||
try:
|
||||
x = 1 + 2
|
||||
print(not_defined_here)
|
||||
except Exception as e:
|
||||
x += 55
|
||||
x - 1
|
||||
y = {}
|
||||
raise KeyError('uh') from e
|
||||
"""
|
||||
|
||||
EXCEPTION_DURING_HANDLING_CODE = """
|
||||
try:
|
||||
x = 1 + 2
|
||||
print(not_defined_here)
|
||||
except Exception as e:
|
||||
x += 55
|
||||
x - 1
|
||||
y = {}
|
||||
raise KeyError('uh')
|
||||
"""
|
||||
|
||||
SUPPRESS_CHAINING_CODE = """
|
||||
try:
|
||||
1/0
|
||||
except Exception:
|
||||
raise ValueError("Yikes") from None
|
||||
"""
|
||||
|
||||
def test_direct_cause_error(self):
|
||||
with tt.AssertPrints(["KeyError", "NameError", "direct cause"]):
|
||||
ip.run_cell(self.DIRECT_CAUSE_ERROR_CODE)
|
||||
|
||||
def test_exception_during_handling_error(self):
|
||||
with tt.AssertPrints(["KeyError", "NameError", "During handling"]):
|
||||
ip.run_cell(self.EXCEPTION_DURING_HANDLING_CODE)
|
||||
|
||||
def test_suppress_exception_chaining(self):
|
||||
with tt.AssertNotPrints("ZeroDivisionError"), \
|
||||
tt.AssertPrints("ValueError", suppress=False):
|
||||
ip.run_cell(self.SUPPRESS_CHAINING_CODE)
|
||||
|
||||
def test_plain_direct_cause_error(self):
|
||||
with tt.AssertPrints(["KeyError", "NameError", "direct cause"]):
|
||||
ip.run_cell("%xmode Plain")
|
||||
ip.run_cell(self.DIRECT_CAUSE_ERROR_CODE)
|
||||
ip.run_cell("%xmode Verbose")
|
||||
|
||||
def test_plain_exception_during_handling_error(self):
|
||||
with tt.AssertPrints(["KeyError", "NameError", "During handling"]):
|
||||
ip.run_cell("%xmode Plain")
|
||||
ip.run_cell(self.EXCEPTION_DURING_HANDLING_CODE)
|
||||
ip.run_cell("%xmode Verbose")
|
||||
|
||||
def test_plain_suppress_exception_chaining(self):
|
||||
with tt.AssertNotPrints("ZeroDivisionError"), \
|
||||
tt.AssertPrints("ValueError", suppress=False):
|
||||
ip.run_cell("%xmode Plain")
|
||||
ip.run_cell(self.SUPPRESS_CHAINING_CODE)
|
||||
ip.run_cell("%xmode Verbose")
|
||||
|
||||
|
||||
class RecursionTest(unittest.TestCase):
|
||||
DEFINITIONS = """
|
||||
def non_recurs():
|
||||
1/0
|
||||
|
||||
def r1():
|
||||
r1()
|
||||
|
||||
def r3a():
|
||||
r3b()
|
||||
|
||||
def r3b():
|
||||
r3c()
|
||||
|
||||
def r3c():
|
||||
r3a()
|
||||
|
||||
def r3o1():
|
||||
r3a()
|
||||
|
||||
def r3o2():
|
||||
r3o1()
|
||||
"""
|
||||
def setUp(self):
|
||||
ip.run_cell(self.DEFINITIONS)
|
||||
|
||||
def test_no_recursion(self):
|
||||
with tt.AssertNotPrints("skipping similar frames"):
|
||||
ip.run_cell("non_recurs()")
|
||||
|
||||
@recursionlimit(200)
|
||||
def test_recursion_one_frame(self):
|
||||
with tt.AssertPrints(re.compile(
|
||||
r"\[\.\.\. skipping similar frames: r1 at line 5 \(\d{2,3} times\)\]")
|
||||
):
|
||||
ip.run_cell("r1()")
|
||||
|
||||
@recursionlimit(160)
|
||||
def test_recursion_three_frames(self):
|
||||
with tt.AssertPrints("[... skipping similar frames: "), \
|
||||
tt.AssertPrints(re.compile(r"r3a at line 8 \(\d{2} times\)"), suppress=False), \
|
||||
tt.AssertPrints(re.compile(r"r3b at line 11 \(\d{2} times\)"), suppress=False), \
|
||||
tt.AssertPrints(re.compile(r"r3c at line 14 \(\d{2} times\)"), suppress=False):
|
||||
ip.run_cell("r3o2()")
|
||||
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
# module testing (minimal)
|
||||
def test_handlers():
|
||||
def spam(c, d_e):
|
||||
(d, e) = d_e
|
||||
x = c + d
|
||||
y = c * d
|
||||
foo(x, y)
|
||||
|
||||
def foo(a, b, bar=1):
|
||||
eggs(a, b + bar)
|
||||
|
||||
def eggs(f, g, z=globals()):
|
||||
h = f + g
|
||||
i = f - g
|
||||
return h / i
|
||||
|
||||
buff = io.StringIO()
|
||||
|
||||
buff.write('')
|
||||
buff.write('*** Before ***')
|
||||
try:
|
||||
buff.write(spam(1, (2, 3)))
|
||||
except:
|
||||
traceback.print_exc(file=buff)
|
||||
|
||||
handler = ColorTB(ostream=buff)
|
||||
buff.write('*** ColorTB ***')
|
||||
try:
|
||||
buff.write(spam(1, (2, 3)))
|
||||
except:
|
||||
handler(*sys.exc_info())
|
||||
buff.write('')
|
||||
|
||||
handler = VerboseTB(ostream=buff)
|
||||
buff.write('*** VerboseTB ***')
|
||||
try:
|
||||
buff.write(spam(1, (2, 3)))
|
||||
except:
|
||||
handler(*sys.exc_info())
|
||||
buff.write('')
|
Reference in New Issue
Block a user