##// END OF EJS Templates
Merge pull request #13546 from Carreau/cleanup-dep-magic...
Matthias Bussonnier -
r27553:3da1ce6e merge
parent child Browse files
Show More
@@ -1,66 +1,66 b''
1 1 from IPython.utils.capture import capture_output
2 2
3 3 import pytest
4 4
5 5 def test_alias_lifecycle():
6 6 name = 'test_alias1'
7 7 cmd = 'echo "Hello"'
8 8 am = _ip.alias_manager
9 9 am.clear_aliases()
10 10 am.define_alias(name, cmd)
11 11 assert am.is_alias(name)
12 12 assert am.retrieve_alias(name) == cmd
13 13 assert (name, cmd) in am.aliases
14 14
15 15 # Test running the alias
16 16 orig_system = _ip.system
17 17 result = []
18 18 _ip.system = result.append
19 19 try:
20 20 _ip.run_cell('%{}'.format(name))
21 21 result = [c.strip() for c in result]
22 22 assert result == [cmd]
23 23 finally:
24 24 _ip.system = orig_system
25 25
26 26 # Test removing the alias
27 27 am.undefine_alias(name)
28 28 assert not am.is_alias(name)
29 29 with pytest.raises(ValueError):
30 30 am.retrieve_alias(name)
31 31 assert (name, cmd) not in am.aliases
32 32
33 33
34 34 def test_alias_args_error():
35 35 """Error expanding with wrong number of arguments"""
36 36 _ip.alias_manager.define_alias('parts', 'echo first %s second %s')
37 37 # capture stderr:
38 38 with capture_output() as cap:
39 39 _ip.run_cell('parts 1')
40 40
41 41 assert cap.stderr.split(":")[0] == "UsageError"
42 42
43 43
44 44 def test_alias_args_commented():
45 45 """Check that alias correctly ignores 'commented out' args"""
46 _ip.magic('alias commetarg echo this is %%s a commented out arg')
47
46 _ip.run_line_magic("alias", "commentarg echo this is %%s a commented out arg")
47
48 48 with capture_output() as cap:
49 _ip.run_cell('commetarg')
50
49 _ip.run_cell("commentarg")
50
51 51 # strip() is for pytest compat; testing via iptest patch IPython shell
52 52 # in testing.globalipapp and replace the system call which messed up the
53 53 # \r\n
54 54 assert cap.stdout.strip() == 'this is %s a commented out arg'
55 55
56 56 def test_alias_args_commented_nargs():
57 57 """Check that alias correctly counts args, excluding those commented out"""
58 58 am = _ip.alias_manager
59 59 alias_name = 'comargcount'
60 60 cmd = 'echo this is %%s a commented out arg and this is not %s'
61 61
62 62 am.define_alias(alias_name, cmd)
63 63 assert am.is_alias(alias_name)
64 64
65 65 thealias = am.get_alias(alias_name)
66 66 assert thealias.nargs == 1
@@ -1,91 +1,97 b''
1 1 """Tests for input handlers.
2 2 """
3 3 #-----------------------------------------------------------------------------
4 4 # Module imports
5 5 #-----------------------------------------------------------------------------
6 6
7 7 # our own packages
8 8 from IPython.core import autocall
9 9 from IPython.testing import tools as tt
10 10
11 11 #-----------------------------------------------------------------------------
12 12 # Globals
13 13 #-----------------------------------------------------------------------------
14 14
15 15 # Get the public instance of IPython
16 16
17 17 failures = []
18 18 num_tests = 0
19 19
20 20 #-----------------------------------------------------------------------------
21 21 # Test functions
22 22 #-----------------------------------------------------------------------------
23 23
24 24 class CallableIndexable(object):
25 25 def __getitem__(self, idx): return True
26 26 def __call__(self, *args, **kws): return True
27 27
28 28
29 29 class Autocallable(autocall.IPyAutocall):
30 30 def __call__(self):
31 31 return "called"
32 32
33 33
34 34 def run(tests):
35 35 """Loop through a list of (pre, post) inputs, where pre is the string
36 36 handed to ipython, and post is how that string looks after it's been
37 37 transformed (i.e. ipython's notion of _i)"""
38 38 tt.check_pairs(ip.prefilter_manager.prefilter_lines, tests)
39 39
40 40
41 41 def test_handlers():
42 42 call_idx = CallableIndexable()
43 43 ip.user_ns['call_idx'] = call_idx
44 44
45 45 # For many of the below, we're also checking that leading whitespace
46 46 # turns off the esc char, which it should unless there is a continuation
47 47 # line.
48 48 run(
49 49 [('"no change"', '"no change"'), # normal
50 50 (u"lsmagic", "get_ipython().run_line_magic('lsmagic', '')"), # magic
51 51 #("a = b # PYTHON-MODE", '_i'), # emacs -- avoids _in cache
52 52 ])
53 53
54 54 # Objects which are instances of IPyAutocall are *always* autocalled
55 55 autocallable = Autocallable()
56 56 ip.user_ns['autocallable'] = autocallable
57 57
58 58 # auto
59 ip.magic('autocall 0')
59 ip.run_line_magic("autocall", "0")
60 60 # Only explicit escapes or instances of IPyAutocallable should get
61 61 # expanded
62 run([
63 ('len "abc"', 'len "abc"'),
64 ('autocallable', 'autocallable()'),
65 # Don't add extra brackets (gh-1117)
66 ('autocallable()', 'autocallable()'),
67 ])
68 ip.magic('autocall 1')
69 run([
70 ('len "abc"', 'len("abc")'),
71 ('len "abc";', 'len("abc");'), # ; is special -- moves out of parens
72 # Autocall is turned off if first arg is [] and the object
73 # is both callable and indexable. Like so:
74 ('len [1,2]', 'len([1,2])'), # len doesn't support __getitem__...
75 ('call_idx [1]', 'call_idx [1]'), # call_idx *does*..
76 ('call_idx 1', 'call_idx(1)'),
77 ('len', 'len'), # only at 2 does it auto-call on single args
78 ])
79 ip.magic('autocall 2')
80 run([
81 ('len "abc"', 'len("abc")'),
82 ('len "abc";', 'len("abc");'),
83 ('len [1,2]', 'len([1,2])'),
84 ('call_idx [1]', 'call_idx [1]'),
85 ('call_idx 1', 'call_idx(1)'),
86 # This is what's different:
87 ('len', 'len()'), # only at 2 does it auto-call on single args
88 ])
89 ip.magic('autocall 1')
62 run(
63 [
64 ('len "abc"', 'len "abc"'),
65 ("autocallable", "autocallable()"),
66 # Don't add extra brackets (gh-1117)
67 ("autocallable()", "autocallable()"),
68 ]
69 )
70 ip.run_line_magic("autocall", "1")
71 run(
72 [
73 ('len "abc"', 'len("abc")'),
74 ('len "abc";', 'len("abc");'), # ; is special -- moves out of parens
75 # Autocall is turned off if first arg is [] and the object
76 # is both callable and indexable. Like so:
77 ("len [1,2]", "len([1,2])"), # len doesn't support __getitem__...
78 ("call_idx [1]", "call_idx [1]"), # call_idx *does*..
79 ("call_idx 1", "call_idx(1)"),
80 ("len", "len"), # only at 2 does it auto-call on single args
81 ]
82 )
83 ip.run_line_magic("autocall", "2")
84 run(
85 [
86 ('len "abc"', 'len("abc")'),
87 ('len "abc";', 'len("abc");'),
88 ("len [1,2]", "len([1,2])"),
89 ("call_idx [1]", "call_idx [1]"),
90 ("call_idx 1", "call_idx(1)"),
91 # This is what's different:
92 ("len", "len()"), # only at 2 does it auto-call on single args
93 ]
94 )
95 ip.run_line_magic("autocall", "1")
90 96
91 97 assert failures == []
@@ -1,229 +1,229 b''
1 1 # coding: utf-8
2 2 """Tests for the IPython tab-completion machinery.
3 3 """
4 4 #-----------------------------------------------------------------------------
5 5 # Module imports
6 6 #-----------------------------------------------------------------------------
7 7
8 8 # stdlib
9 9 import io
10 10 import sqlite3
11 11 import sys
12 12 import tempfile
13 13 from datetime import datetime
14 14 from pathlib import Path
15 15
16 16 from tempfile import TemporaryDirectory
17 17 # our own packages
18 18 from traitlets.config.loader import Config
19 19
20 20 from IPython.core.history import HistoryManager, extract_hist_ranges
21 21
22 22
23 23 def test_proper_default_encoding():
24 24 assert sys.getdefaultencoding() == "utf-8"
25 25
26 26 def test_history():
27 27 ip = get_ipython()
28 28 with TemporaryDirectory() as tmpdir:
29 29 tmp_path = Path(tmpdir)
30 30 hist_manager_ori = ip.history_manager
31 31 hist_file = tmp_path / "history.sqlite"
32 32 try:
33 33 ip.history_manager = HistoryManager(shell=ip, hist_file=hist_file)
34 34 hist = ["a=1", "def f():\n test = 1\n return test", "b='€Æ¾÷ß'"]
35 35 for i, h in enumerate(hist, start=1):
36 36 ip.history_manager.store_inputs(i, h)
37 37
38 38 ip.history_manager.db_log_output = True
39 39 # Doesn't match the input, but we'll just check it's stored.
40 40 ip.history_manager.output_hist_reprs[3] = "spam"
41 41 ip.history_manager.store_output(3)
42 42
43 43 assert ip.history_manager.input_hist_raw == [""] + hist
44 44
45 45 # Detailed tests for _get_range_session
46 46 grs = ip.history_manager._get_range_session
47 47 assert list(grs(start=2, stop=-1)) == list(zip([0], [2], hist[1:-1]))
48 48 assert list(grs(start=-2)) == list(zip([0, 0], [2, 3], hist[-2:]))
49 49 assert list(grs(output=True)) == list(
50 50 zip([0, 0, 0], [1, 2, 3], zip(hist, [None, None, "spam"]))
51 51 )
52 52
53 53 # Check whether specifying a range beyond the end of the current
54 54 # session results in an error (gh-804)
55 ip.magic('%hist 2-500')
55 ip.run_line_magic("hist", "2-500")
56 56
57 57 # Check that we can write non-ascii characters to a file
58 ip.magic("%%hist -f %s" % (tmp_path / "test1"))
59 ip.magic("%%hist -pf %s" % (tmp_path / "test2"))
60 ip.magic("%%hist -nf %s" % (tmp_path / "test3"))
61 ip.magic("%%save %s 1-10" % (tmp_path / "test4"))
58 ip.run_line_magic("hist", "-f %s" % (tmp_path / "test1"))
59 ip.run_line_magic("hist", "-pf %s" % (tmp_path / "test2"))
60 ip.run_line_magic("hist", "-nf %s" % (tmp_path / "test3"))
61 ip.run_line_magic("save", "%s 1-10" % (tmp_path / "test4"))
62 62
63 63 # New session
64 64 ip.history_manager.reset()
65 65 newcmds = ["z=5", "class X(object):\n pass", "k='p'", "z=5"]
66 66 for i, cmd in enumerate(newcmds, start=1):
67 67 ip.history_manager.store_inputs(i, cmd)
68 68 gothist = ip.history_manager.get_range(start=1, stop=4)
69 69 assert list(gothist) == list(zip([0, 0, 0], [1, 2, 3], newcmds))
70 70 # Previous session:
71 71 gothist = ip.history_manager.get_range(-1, 1, 4)
72 72 assert list(gothist) == list(zip([1, 1, 1], [1, 2, 3], hist))
73 73
74 74 newhist = [(2, i, c) for (i, c) in enumerate(newcmds, 1)]
75 75
76 76 # Check get_hist_tail
77 77 gothist = ip.history_manager.get_tail(5, output=True,
78 78 include_latest=True)
79 79 expected = [(1, 3, (hist[-1], "spam"))] \
80 80 + [(s, n, (c, None)) for (s, n, c) in newhist]
81 81 assert list(gothist) == expected
82 82
83 83 gothist = ip.history_manager.get_tail(2)
84 84 expected = newhist[-3:-1]
85 85 assert list(gothist) == expected
86 86
87 87 # Check get_hist_search
88 88
89 89 gothist = ip.history_manager.search("*test*")
90 90 assert list(gothist) == [(1, 2, hist[1])]
91 91
92 92 gothist = ip.history_manager.search("*=*")
93 93 assert list(gothist) == [
94 94 (1, 1, hist[0]),
95 95 (1, 2, hist[1]),
96 96 (1, 3, hist[2]),
97 97 newhist[0],
98 98 newhist[2],
99 99 newhist[3],
100 100 ]
101 101
102 102 gothist = ip.history_manager.search("*=*", n=4)
103 103 assert list(gothist) == [
104 104 (1, 3, hist[2]),
105 105 newhist[0],
106 106 newhist[2],
107 107 newhist[3],
108 108 ]
109 109
110 110 gothist = ip.history_manager.search("*=*", unique=True)
111 111 assert list(gothist) == [
112 112 (1, 1, hist[0]),
113 113 (1, 2, hist[1]),
114 114 (1, 3, hist[2]),
115 115 newhist[2],
116 116 newhist[3],
117 117 ]
118 118
119 119 gothist = ip.history_manager.search("*=*", unique=True, n=3)
120 120 assert list(gothist) == [(1, 3, hist[2]), newhist[2], newhist[3]]
121 121
122 122 gothist = ip.history_manager.search("b*", output=True)
123 123 assert list(gothist) == [(1, 3, (hist[2], "spam"))]
124 124
125 125 # Cross testing: check that magic %save can get previous session.
126 126 testfilename = (tmp_path / "test.py").resolve()
127 ip.magic("save " + str(testfilename) + " ~1/1-3")
127 ip.run_line_magic("save", str(testfilename) + " ~1/1-3")
128 128 with io.open(testfilename, encoding="utf-8") as testfile:
129 129 assert testfile.read() == "# coding: utf-8\n" + "\n".join(hist) + "\n"
130 130
131 131 # Duplicate line numbers - check that it doesn't crash, and
132 132 # gets a new session
133 133 ip.history_manager.store_inputs(1, "rogue")
134 134 ip.history_manager.writeout_cache()
135 135 assert ip.history_manager.session_number == 3
136 136
137 137 # Check that session and line values are not just max values
138 138 sessid, lineno, entry = newhist[-1]
139 139 assert lineno > 1
140 140 ip.history_manager.reset()
141 141 lineno = 1
142 142 ip.history_manager.store_inputs(lineno, entry)
143 143 gothist = ip.history_manager.search("*=*", unique=True)
144 144 hist = list(gothist)[-1]
145 145 assert sessid < hist[0]
146 146 assert hist[1:] == (lineno, entry)
147 147 finally:
148 148 # Ensure saving thread is shut down before we try to clean up the files
149 149 ip.history_manager.save_thread.stop()
150 150 # Forcibly close database rather than relying on garbage collection
151 151 ip.history_manager.db.close()
152 152 # Restore history manager
153 153 ip.history_manager = hist_manager_ori
154 154
155 155
156 156 def test_extract_hist_ranges():
157 157 instr = "1 2/3 ~4/5-6 ~4/7-~4/9 ~9/2-~7/5 ~10/"
158 158 expected = [(0, 1, 2), # 0 == current session
159 159 (2, 3, 4),
160 160 (-4, 5, 7),
161 161 (-4, 7, 10),
162 162 (-9, 2, None), # None == to end
163 163 (-8, 1, None),
164 164 (-7, 1, 6),
165 165 (-10, 1, None)]
166 166 actual = list(extract_hist_ranges(instr))
167 167 assert actual == expected
168 168
169 169
170 170 def test_extract_hist_ranges_empty_str():
171 171 instr = ""
172 172 expected = [(0, 1, None)] # 0 == current session, None == to end
173 173 actual = list(extract_hist_ranges(instr))
174 174 assert actual == expected
175 175
176 176
177 177 def test_magic_rerun():
178 178 """Simple test for %rerun (no args -> rerun last line)"""
179 179 ip = get_ipython()
180 180 ip.run_cell("a = 10", store_history=True)
181 181 ip.run_cell("a += 1", store_history=True)
182 182 assert ip.user_ns["a"] == 11
183 183 ip.run_cell("%rerun", store_history=True)
184 184 assert ip.user_ns["a"] == 12
185 185
186 186 def test_timestamp_type():
187 187 ip = get_ipython()
188 188 info = ip.history_manager.get_session_info()
189 189 assert isinstance(info[1], datetime)
190 190
191 191 def test_hist_file_config():
192 192 cfg = Config()
193 193 tfile = tempfile.NamedTemporaryFile(delete=False)
194 194 cfg.HistoryManager.hist_file = Path(tfile.name)
195 195 try:
196 196 hm = HistoryManager(shell=get_ipython(), config=cfg)
197 197 assert hm.hist_file == cfg.HistoryManager.hist_file
198 198 finally:
199 199 try:
200 200 Path(tfile.name).unlink()
201 201 except OSError:
202 202 # same catch as in testing.tools.TempFileMixin
203 203 # On Windows, even though we close the file, we still can't
204 204 # delete it. I have no clue why
205 205 pass
206 206
207 207 def test_histmanager_disabled():
208 208 """Ensure that disabling the history manager doesn't create a database."""
209 209 cfg = Config()
210 210 cfg.HistoryAccessor.enabled = False
211 211
212 212 ip = get_ipython()
213 213 with TemporaryDirectory() as tmpdir:
214 214 hist_manager_ori = ip.history_manager
215 215 hist_file = Path(tmpdir) / "history.sqlite"
216 216 cfg.HistoryManager.hist_file = hist_file
217 217 try:
218 218 ip.history_manager = HistoryManager(shell=ip, config=cfg)
219 219 hist = ["a=1", "def f():\n test = 1\n return test", "b='€Æ¾÷ß'"]
220 220 for i, h in enumerate(hist, start=1):
221 221 ip.history_manager.store_inputs(i, h)
222 222 assert ip.history_manager.input_hist_raw == [""] + hist
223 223 ip.history_manager.reset()
224 224 ip.history_manager.end_session()
225 225 finally:
226 226 ip.history_manager = hist_manager_ori
227 227
228 228 # hist_file should not be created
229 229 assert hist_file.exists() is False
General Comments 0
You need to be logged in to leave comments. Login now