##// END OF EJS Templates
test for autocall regression...
Paul Ivanov -
Show More
@@ -1,139 +1,149
1 """Tests for input manipulation machinery."""
1 """Tests for input manipulation machinery."""
2
2
3 #-----------------------------------------------------------------------------
3 #-----------------------------------------------------------------------------
4 # Imports
4 # Imports
5 #-----------------------------------------------------------------------------
5 #-----------------------------------------------------------------------------
6 import pytest
6 import pytest
7
7
8 from IPython.core.prefilter import AutocallChecker
8 from IPython.core.prefilter import AutocallChecker
9
9
10 #-----------------------------------------------------------------------------
10 #-----------------------------------------------------------------------------
11 # Tests
11 # Tests
12 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
13
13
14 def test_prefilter():
14 def test_prefilter():
15 """Test user input conversions"""
15 """Test user input conversions"""
16
16
17 # pairs of (raw, expected correct) input
17 # pairs of (raw, expected correct) input
18 pairs = [ ('2+2','2+2'),
18 pairs = [ ('2+2','2+2'),
19 ]
19 ]
20
20
21 for raw, correct in pairs:
21 for raw, correct in pairs:
22 assert ip.prefilter(raw) == correct
22 assert ip.prefilter(raw) == correct
23
23
24 def test_prefilter_shadowed():
24 def test_prefilter_shadowed():
25 def dummy_magic(line): pass
25 def dummy_magic(line): pass
26
26
27 prev_automagic_state = ip.automagic
27 prev_automagic_state = ip.automagic
28 ip.automagic = True
28 ip.automagic = True
29 ip.autocall = 0
29 ip.autocall = 0
30
30
31 try:
31 try:
32 # These should not be transformed - they are shadowed by other names
32 # These should not be transformed - they are shadowed by other names
33 for name in ['if', 'zip', 'get_ipython']: # keyword, builtin, global
33 for name in ['if', 'zip', 'get_ipython']: # keyword, builtin, global
34 ip.register_magic_function(dummy_magic, magic_name=name)
34 ip.register_magic_function(dummy_magic, magic_name=name)
35 res = ip.prefilter(name + " foo")
35 res = ip.prefilter(name + " foo")
36 assert res == name + " foo"
36 assert res == name + " foo"
37 del ip.magics_manager.magics["line"][name]
37 del ip.magics_manager.magics["line"][name]
38
38
39 # These should be transformed
39 # These should be transformed
40 for name in ['fi', 'piz', 'nohtypi_teg']:
40 for name in ['fi', 'piz', 'nohtypi_teg']:
41 ip.register_magic_function(dummy_magic, magic_name=name)
41 ip.register_magic_function(dummy_magic, magic_name=name)
42 res = ip.prefilter(name + " foo")
42 res = ip.prefilter(name + " foo")
43 assert res != name + " foo"
43 assert res != name + " foo"
44 del ip.magics_manager.magics["line"][name]
44 del ip.magics_manager.magics["line"][name]
45
45
46 finally:
46 finally:
47 ip.automagic = prev_automagic_state
47 ip.automagic = prev_automagic_state
48
48
49 def test_autocall_binops():
49 def test_autocall_binops():
50 """See https://github.com/ipython/ipython/issues/81"""
50 """See https://github.com/ipython/ipython/issues/81"""
51 ip.run_line_magic("autocall", "2")
51 ip.run_line_magic("autocall", "2")
52 f = lambda x: x
52 f = lambda x: x
53 ip.user_ns['f'] = f
53 ip.user_ns['f'] = f
54 try:
54 try:
55 assert ip.prefilter("f 1") == "f(1)"
55 assert ip.prefilter("f 1") == "f(1)"
56 for t in ["f +1", "f -1"]:
56 for t in ["f +1", "f -1"]:
57 assert ip.prefilter(t) == t
57 assert ip.prefilter(t) == t
58
58
59 # Run tests again with a more permissive exclude_regexp, which will
59 # Run tests again with a more permissive exclude_regexp, which will
60 # allow transformation of binary operations ('f -1' -> 'f(-1)').
60 # allow transformation of binary operations ('f -1' -> 'f(-1)').
61 pm = ip.prefilter_manager
61 pm = ip.prefilter_manager
62 ac = AutocallChecker(shell=pm.shell, prefilter_manager=pm,
62 ac = AutocallChecker(shell=pm.shell, prefilter_manager=pm,
63 config=pm.config)
63 config=pm.config)
64 try:
64 try:
65 ac.priority = 1
65 ac.priority = 1
66 ac.exclude_regexp = r'^[,&^\|\*/]|^is |^not |^in |^and |^or '
66 ac.exclude_regexp = r'^[,&^\|\*/]|^is |^not |^in |^and |^or '
67 pm.sort_checkers()
67 pm.sort_checkers()
68
68
69 assert ip.prefilter("f -1") == "f(-1)"
69 assert ip.prefilter("f -1") == "f(-1)"
70 assert ip.prefilter("f +1") == "f(+1)"
70 assert ip.prefilter("f +1") == "f(+1)"
71 finally:
71 finally:
72 pm.unregister_checker(ac)
72 pm.unregister_checker(ac)
73 finally:
73 finally:
74 ip.run_line_magic("autocall", "0")
74 ip.run_line_magic("autocall", "0")
75 del ip.user_ns["f"]
75 del ip.user_ns["f"]
76
76
77
77
78 def test_issue_114():
78 def test_issue_114():
79 """Check that multiline string literals don't expand as magic
79 """Check that multiline string literals don't expand as magic
80 see http://github.com/ipython/ipython/issues/114"""
80 see http://github.com/ipython/ipython/issues/114"""
81
81
82 template = '"""\n%s\n"""'
82 template = '"""\n%s\n"""'
83 # Store the current value of multi_line_specials and turn it off before
83 # Store the current value of multi_line_specials and turn it off before
84 # running test, since it could be true (case in which the test doesn't make
84 # running test, since it could be true (case in which the test doesn't make
85 # sense, as multiline string literals *will* expand as magic in that case).
85 # sense, as multiline string literals *will* expand as magic in that case).
86 msp = ip.prefilter_manager.multi_line_specials
86 msp = ip.prefilter_manager.multi_line_specials
87 ip.prefilter_manager.multi_line_specials = False
87 ip.prefilter_manager.multi_line_specials = False
88 try:
88 try:
89 for mgk in ip.magics_manager.lsmagic()['line']:
89 for mgk in ip.magics_manager.lsmagic()['line']:
90 raw = template % mgk
90 raw = template % mgk
91 assert ip.prefilter(raw) == raw
91 assert ip.prefilter(raw) == raw
92 finally:
92 finally:
93 ip.prefilter_manager.multi_line_specials = msp
93 ip.prefilter_manager.multi_line_specials = msp
94
94
95
95
96 def test_prefilter_attribute_errors():
96 def test_prefilter_attribute_errors():
97 """Capture exceptions thrown by user objects on attribute access.
97 """Capture exceptions thrown by user objects on attribute access.
98
98
99 See http://github.com/ipython/ipython/issues/988."""
99 See http://github.com/ipython/ipython/issues/988."""
100
100
101 class X(object):
101 class X(object):
102 def __getattr__(self, k):
102 def __getattr__(self, k):
103 raise ValueError('broken object')
103 raise ValueError('broken object')
104 def __call__(self, x):
104 def __call__(self, x):
105 return x
105 return x
106
106
107 # Create a callable broken object
107 # Create a callable broken object
108 ip.user_ns["x"] = X()
108 ip.user_ns["x"] = X()
109 ip.run_line_magic("autocall", "2")
109 ip.run_line_magic("autocall", "2")
110 try:
110 try:
111 # Even if x throws an attribute error when looking at its rewrite
111 # Even if x throws an attribute error when looking at its rewrite
112 # attribute, we should not crash. So the test here is simply making
112 # attribute, we should not crash. So the test here is simply making
113 # the prefilter call and not having an exception.
113 # the prefilter call and not having an exception.
114 ip.prefilter('x 1')
114 ip.prefilter('x 1')
115 finally:
115 finally:
116 del ip.user_ns["x"]
116 del ip.user_ns["x"]
117 ip.run_line_magic("autocall", "0")
117 ip.run_line_magic("autocall", "0")
118
118
119
119
120 def test_autocall_type_ann():
120 def test_autocall_type_ann():
121 ip.run_cell("import collections.abc")
121 ip.run_cell("import collections.abc")
122 ip.run_line_magic("autocall", "1")
122 ip.run_line_magic("autocall", "1")
123 try:
123 try:
124 assert (
124 assert (
125 ip.prefilter("collections.abc.Callable[[int], None]")
125 ip.prefilter("collections.abc.Callable[[int], None]")
126 == "collections.abc.Callable[[int], None]"
126 == "collections.abc.Callable[[int], None]"
127 )
127 )
128 finally:
128 finally:
129 ip.run_line_magic("autocall", "0")
129 ip.run_line_magic("autocall", "0")
130
130
131
131
132 def test_autocall_should_support_unicode():
132 def test_autocall_should_support_unicode():
133 ip.run_line_magic("autocall", "2")
133 ip.run_line_magic("autocall", "2")
134 ip.user_ns["π"] = lambda x: x
134 ip.user_ns["π"] = lambda x: x
135 try:
135 try:
136 assert ip.prefilter("π 3") == "π(3)"
136 assert ip.prefilter("π 3") == "π(3)"
137 finally:
137 finally:
138 ip.run_line_magic("autocall", "0")
138 ip.run_line_magic("autocall", "0")
139 del ip.user_ns["π"]
139 del ip.user_ns["π"]
140
141
142 def test_autocall_regression_gh_14513():
143 ip.run_line_magic("autocall", "2")
144 ip.user_ns["foo"] = dict()
145 try:
146 assert ip.prefilter("foo") == "foo"
147 finally:
148 ip.run_line_magic("autocall", "0")
149 del ip.user_ns["foo"]
General Comments 0
You need to be logged in to leave comments. Login now