##// END OF EJS Templates
TST: Remove unneeded requirement on pywin32...
Nikita Kniazev -
Show More
@@ -1,167 +1,156 b''
1 # coding: utf-8
1 # coding: utf-8
2 """Tests for profile-related functions.
2 """Tests for profile-related functions.
3
3
4 Currently only the startup-dir functionality is tested, but more tests should
4 Currently only the startup-dir functionality is tested, but more tests should
5 be added for:
5 be added for:
6
6
7 * ipython profile create
7 * ipython profile create
8 * ipython profile list
8 * ipython profile list
9 * ipython profile create --parallel
9 * ipython profile create --parallel
10 * security dir permissions
10 * security dir permissions
11
11
12 Authors
12 Authors
13 -------
13 -------
14
14
15 * MinRK
15 * MinRK
16
16
17 """
17 """
18
18
19 #-----------------------------------------------------------------------------
19 #-----------------------------------------------------------------------------
20 # Imports
20 # Imports
21 #-----------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
22
22
23 import shutil
23 import shutil
24 import sys
24 import sys
25 import tempfile
25 import tempfile
26
26
27 from pathlib import Path
27 from pathlib import Path
28 from unittest import TestCase
28 from unittest import TestCase
29
29
30 from IPython.core.profileapp import list_profiles_in, list_bundled_profiles
30 from IPython.core.profileapp import list_profiles_in, list_bundled_profiles
31 from IPython.core.profiledir import ProfileDir
31 from IPython.core.profiledir import ProfileDir
32
32
33 from IPython.testing import decorators as dec
33 from IPython.testing import decorators as dec
34 from IPython.testing import tools as tt
34 from IPython.testing import tools as tt
35 from IPython.utils.process import getoutput
35 from IPython.utils.process import getoutput
36 from IPython.utils.tempdir import TemporaryDirectory
36 from IPython.utils.tempdir import TemporaryDirectory
37
37
38 #-----------------------------------------------------------------------------
38 #-----------------------------------------------------------------------------
39 # Globals
39 # Globals
40 #-----------------------------------------------------------------------------
40 #-----------------------------------------------------------------------------
41 TMP_TEST_DIR = Path(tempfile.mkdtemp())
41 TMP_TEST_DIR = Path(tempfile.mkdtemp())
42 HOME_TEST_DIR = TMP_TEST_DIR / "home_test_dir"
42 HOME_TEST_DIR = TMP_TEST_DIR / "home_test_dir"
43 IP_TEST_DIR = HOME_TEST_DIR / ".ipython"
43 IP_TEST_DIR = HOME_TEST_DIR / ".ipython"
44
44
45 #
45 #
46 # Setup/teardown functions/decorators
46 # Setup/teardown functions/decorators
47 #
47 #
48
48
49 def setup_module():
49 def setup_module():
50 """Setup test environment for the module:
50 """Setup test environment for the module:
51
51
52 - Adds dummy home dir tree
52 - Adds dummy home dir tree
53 """
53 """
54 # Do not mask exceptions here. In particular, catching WindowsError is a
54 # Do not mask exceptions here. In particular, catching WindowsError is a
55 # problem because that exception is only defined on Windows...
55 # problem because that exception is only defined on Windows...
56 (Path.cwd() / IP_TEST_DIR).mkdir(parents=True)
56 (Path.cwd() / IP_TEST_DIR).mkdir(parents=True)
57
57
58
58
59 def teardown_module():
59 def teardown_module():
60 """Teardown test environment for the module:
60 """Teardown test environment for the module:
61
61
62 - Remove dummy home dir tree
62 - Remove dummy home dir tree
63 """
63 """
64 # Note: we remove the parent test dir, which is the root of all test
64 # Note: we remove the parent test dir, which is the root of all test
65 # subdirs we may have created. Use shutil instead of os.removedirs, so
65 # subdirs we may have created. Use shutil instead of os.removedirs, so
66 # that non-empty directories are all recursively removed.
66 # that non-empty directories are all recursively removed.
67 shutil.rmtree(TMP_TEST_DIR)
67 shutil.rmtree(TMP_TEST_DIR)
68
68
69
69
70 #-----------------------------------------------------------------------------
70 #-----------------------------------------------------------------------------
71 # Test functions
71 # Test functions
72 #-----------------------------------------------------------------------------
72 #-----------------------------------------------------------------------------
73 def win32_without_pywin32():
74 if sys.platform == 'win32':
75 try:
76 import pywin32
77 except ImportError:
78 return True
79 return False
80
81
82 class ProfileStartupTest(TestCase):
73 class ProfileStartupTest(TestCase):
83 def setUp(self):
74 def setUp(self):
84 # create profile dir
75 # create profile dir
85 self.pd = ProfileDir.create_profile_dir_by_name(IP_TEST_DIR, "test")
76 self.pd = ProfileDir.create_profile_dir_by_name(IP_TEST_DIR, "test")
86 self.options = ["--ipython-dir", IP_TEST_DIR, "--profile", "test"]
77 self.options = ["--ipython-dir", IP_TEST_DIR, "--profile", "test"]
87 self.fname = TMP_TEST_DIR / "test.py"
78 self.fname = TMP_TEST_DIR / "test.py"
88
79
89 def tearDown(self):
80 def tearDown(self):
90 # We must remove this profile right away so its presence doesn't
81 # We must remove this profile right away so its presence doesn't
91 # confuse other tests.
82 # confuse other tests.
92 shutil.rmtree(self.pd.location)
83 shutil.rmtree(self.pd.location)
93
84
94 def init(self, startup_file, startup, test):
85 def init(self, startup_file, startup, test):
95 # write startup python file
86 # write startup python file
96 with open(Path(self.pd.startup_dir) / startup_file, "w") as f:
87 with open(Path(self.pd.startup_dir) / startup_file, "w") as f:
97 f.write(startup)
88 f.write(startup)
98 # write simple test file, to check that the startup file was run
89 # write simple test file, to check that the startup file was run
99 with open(self.fname, 'w') as f:
90 with open(self.fname, 'w') as f:
100 f.write(test)
91 f.write(test)
101
92
102 def validate(self, output):
93 def validate(self, output):
103 tt.ipexec_validate(self.fname, output, '', options=self.options)
94 tt.ipexec_validate(self.fname, output, '', options=self.options)
104
95
105 @dec.skipif(win32_without_pywin32(), "Test requires pywin32 on Windows")
106 def test_startup_py(self):
96 def test_startup_py(self):
107 self.init('00-start.py', 'zzz=123\n', 'print(zzz)\n')
97 self.init('00-start.py', 'zzz=123\n', 'print(zzz)\n')
108 self.validate('123')
98 self.validate('123')
109
99
110 @dec.skipif(win32_without_pywin32(), "Test requires pywin32 on Windows")
111 def test_startup_ipy(self):
100 def test_startup_ipy(self):
112 self.init('00-start.ipy', '%xmode plain\n', '')
101 self.init('00-start.ipy', '%xmode plain\n', '')
113 self.validate('Exception reporting mode: Plain')
102 self.validate('Exception reporting mode: Plain')
114
103
115
104
116 def test_list_profiles_in():
105 def test_list_profiles_in():
117 # No need to remove these directories and files, as they will get nuked in
106 # No need to remove these directories and files, as they will get nuked in
118 # the module-level teardown.
107 # the module-level teardown.
119 td = Path(tempfile.mkdtemp(dir=TMP_TEST_DIR))
108 td = Path(tempfile.mkdtemp(dir=TMP_TEST_DIR))
120 for name in ("profile_foo", "profile_hello", "not_a_profile"):
109 for name in ("profile_foo", "profile_hello", "not_a_profile"):
121 Path(td / name).mkdir(parents=True)
110 Path(td / name).mkdir(parents=True)
122 if dec.unicode_paths:
111 if dec.unicode_paths:
123 Path(td / u"profile_ΓΌnicode").mkdir(parents=True)
112 Path(td / u"profile_ΓΌnicode").mkdir(parents=True)
124
113
125 with open(td / "profile_file", "w") as f:
114 with open(td / "profile_file", "w") as f:
126 f.write("I am not a profile directory")
115 f.write("I am not a profile directory")
127 profiles = list_profiles_in(td)
116 profiles = list_profiles_in(td)
128
117
129 # unicode normalization can turn u'ΓΌnicode' into u'u\0308nicode',
118 # unicode normalization can turn u'ΓΌnicode' into u'u\0308nicode',
130 # so only check for *nicode, and that creating a ProfileDir from the
119 # so only check for *nicode, and that creating a ProfileDir from the
131 # name remains valid
120 # name remains valid
132 found_unicode = False
121 found_unicode = False
133 for p in list(profiles):
122 for p in list(profiles):
134 if p.endswith('nicode'):
123 if p.endswith('nicode'):
135 pd = ProfileDir.find_profile_dir_by_name(td, p)
124 pd = ProfileDir.find_profile_dir_by_name(td, p)
136 profiles.remove(p)
125 profiles.remove(p)
137 found_unicode = True
126 found_unicode = True
138 break
127 break
139 if dec.unicode_paths:
128 if dec.unicode_paths:
140 assert found_unicode is True
129 assert found_unicode is True
141 assert set(profiles) == {"foo", "hello"}
130 assert set(profiles) == {"foo", "hello"}
142
131
143
132
144 def test_list_bundled_profiles():
133 def test_list_bundled_profiles():
145 # This variable will need to be updated when a new profile gets bundled
134 # This variable will need to be updated when a new profile gets bundled
146 bundled = sorted(list_bundled_profiles())
135 bundled = sorted(list_bundled_profiles())
147 assert bundled == []
136 assert bundled == []
148
137
149
138
150 def test_profile_create_ipython_dir():
139 def test_profile_create_ipython_dir():
151 """ipython profile create respects --ipython-dir"""
140 """ipython profile create respects --ipython-dir"""
152 with TemporaryDirectory() as td:
141 with TemporaryDirectory() as td:
153 getoutput(
142 getoutput(
154 [
143 [
155 sys.executable,
144 sys.executable,
156 "-m",
145 "-m",
157 "IPython",
146 "IPython",
158 "profile",
147 "profile",
159 "create",
148 "create",
160 "foo",
149 "foo",
161 "--ipython-dir=%s" % td,
150 "--ipython-dir=%s" % td,
162 ]
151 ]
163 )
152 )
164 profile_dir = Path(td) / "profile_foo"
153 profile_dir = Path(td) / "profile_foo"
165 assert Path(profile_dir).exists()
154 assert Path(profile_dir).exists()
166 ipython_config = profile_dir / "ipython_config.py"
155 ipython_config = profile_dir / "ipython_config.py"
167 assert Path(ipython_config).exists()
156 assert Path(ipython_config).exists()
@@ -1,599 +1,594 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """Tests for code execution (%run and related), which is particularly tricky.
2 """Tests for code execution (%run and related), which is particularly tricky.
3
3
4 Because of how %run manages namespaces, and the fact that we are trying here to
4 Because of how %run manages namespaces, and the fact that we are trying here to
5 verify subtle object deletion and reference counting issues, the %run tests
5 verify subtle object deletion and reference counting issues, the %run tests
6 will be kept in this separate file. This makes it easier to aggregate in one
6 will be kept in this separate file. This makes it easier to aggregate in one
7 place the tricks needed to handle it; most other magics are much easier to test
7 place the tricks needed to handle it; most other magics are much easier to test
8 and we do so in a common test_magic file.
8 and we do so in a common test_magic file.
9
9
10 Note that any test using `run -i` should make sure to do a `reset` afterwards,
10 Note that any test using `run -i` should make sure to do a `reset` afterwards,
11 as otherwise it may influence later tests.
11 as otherwise it may influence later tests.
12 """
12 """
13
13
14 # Copyright (c) IPython Development Team.
14 # Copyright (c) IPython Development Team.
15 # Distributed under the terms of the Modified BSD License.
15 # Distributed under the terms of the Modified BSD License.
16
16
17
17
18
18
19 import functools
19 import functools
20 import os
20 import os
21 from os.path import join as pjoin
21 from os.path import join as pjoin
22 import random
22 import random
23 import string
23 import string
24 import sys
24 import sys
25 import textwrap
25 import textwrap
26 import unittest
26 import unittest
27 from unittest.mock import patch
27 from unittest.mock import patch
28
28
29 import pytest
29 import pytest
30
30
31 from IPython.testing import decorators as dec
31 from IPython.testing import decorators as dec
32 from IPython.testing import tools as tt
32 from IPython.testing import tools as tt
33 from IPython.utils.io import capture_output
33 from IPython.utils.io import capture_output
34 from IPython.utils.tempdir import TemporaryDirectory
34 from IPython.utils.tempdir import TemporaryDirectory
35 from IPython.core import debugger
35 from IPython.core import debugger
36
36
37 def doctest_refbug():
37 def doctest_refbug():
38 """Very nasty problem with references held by multiple runs of a script.
38 """Very nasty problem with references held by multiple runs of a script.
39 See: https://github.com/ipython/ipython/issues/141
39 See: https://github.com/ipython/ipython/issues/141
40
40
41 In [1]: _ip.clear_main_mod_cache()
41 In [1]: _ip.clear_main_mod_cache()
42 # random
42 # random
43
43
44 In [2]: %run refbug
44 In [2]: %run refbug
45
45
46 In [3]: call_f()
46 In [3]: call_f()
47 lowercased: hello
47 lowercased: hello
48
48
49 In [4]: %run refbug
49 In [4]: %run refbug
50
50
51 In [5]: call_f()
51 In [5]: call_f()
52 lowercased: hello
52 lowercased: hello
53 lowercased: hello
53 lowercased: hello
54 """
54 """
55
55
56
56
57 def doctest_run_builtins():
57 def doctest_run_builtins():
58 r"""Check that %run doesn't damage __builtins__.
58 r"""Check that %run doesn't damage __builtins__.
59
59
60 In [1]: import tempfile
60 In [1]: import tempfile
61
61
62 In [2]: bid1 = id(__builtins__)
62 In [2]: bid1 = id(__builtins__)
63
63
64 In [3]: fname = tempfile.mkstemp('.py')[1]
64 In [3]: fname = tempfile.mkstemp('.py')[1]
65
65
66 In [3]: f = open(fname,'w')
66 In [3]: f = open(fname,'w')
67
67
68 In [4]: dummy= f.write('pass\n')
68 In [4]: dummy= f.write('pass\n')
69
69
70 In [5]: f.flush()
70 In [5]: f.flush()
71
71
72 In [6]: t1 = type(__builtins__)
72 In [6]: t1 = type(__builtins__)
73
73
74 In [7]: %run $fname
74 In [7]: %run $fname
75
75
76 In [7]: f.close()
76 In [7]: f.close()
77
77
78 In [8]: bid2 = id(__builtins__)
78 In [8]: bid2 = id(__builtins__)
79
79
80 In [9]: t2 = type(__builtins__)
80 In [9]: t2 = type(__builtins__)
81
81
82 In [10]: t1 == t2
82 In [10]: t1 == t2
83 Out[10]: True
83 Out[10]: True
84
84
85 In [10]: bid1 == bid2
85 In [10]: bid1 == bid2
86 Out[10]: True
86 Out[10]: True
87
87
88 In [12]: try:
88 In [12]: try:
89 ....: os.unlink(fname)
89 ....: os.unlink(fname)
90 ....: except:
90 ....: except:
91 ....: pass
91 ....: pass
92 ....:
92 ....:
93 """
93 """
94
94
95
95
96 def doctest_run_option_parser():
96 def doctest_run_option_parser():
97 r"""Test option parser in %run.
97 r"""Test option parser in %run.
98
98
99 In [1]: %run print_argv.py
99 In [1]: %run print_argv.py
100 []
100 []
101
101
102 In [2]: %run print_argv.py print*.py
102 In [2]: %run print_argv.py print*.py
103 ['print_argv.py']
103 ['print_argv.py']
104
104
105 In [3]: %run -G print_argv.py print*.py
105 In [3]: %run -G print_argv.py print*.py
106 ['print*.py']
106 ['print*.py']
107
107
108 """
108 """
109
109
110
110
111 @dec.skip_win32
111 @dec.skip_win32
112 def doctest_run_option_parser_for_posix():
112 def doctest_run_option_parser_for_posix():
113 r"""Test option parser in %run (Linux/OSX specific).
113 r"""Test option parser in %run (Linux/OSX specific).
114
114
115 You need double quote to escape glob in POSIX systems:
115 You need double quote to escape glob in POSIX systems:
116
116
117 In [1]: %run print_argv.py print\\*.py
117 In [1]: %run print_argv.py print\\*.py
118 ['print*.py']
118 ['print*.py']
119
119
120 You can't use quote to escape glob in POSIX systems:
120 You can't use quote to escape glob in POSIX systems:
121
121
122 In [2]: %run print_argv.py 'print*.py'
122 In [2]: %run print_argv.py 'print*.py'
123 ['print_argv.py']
123 ['print_argv.py']
124
124
125 """
125 """
126
126
127
127
128 @dec.skip_if_not_win32
128 @dec.skip_if_not_win32
129 def doctest_run_option_parser_for_windows():
129 def doctest_run_option_parser_for_windows():
130 r"""Test option parser in %run (Windows specific).
130 r"""Test option parser in %run (Windows specific).
131
131
132 In Windows, you can't escape ``*` `by backslash:
132 In Windows, you can't escape ``*` `by backslash:
133
133
134 In [1]: %run print_argv.py print\\*.py
134 In [1]: %run print_argv.py print\\*.py
135 ['print\\*.py']
135 ['print\\*.py']
136
136
137 You can use quote to escape glob:
137 You can use quote to escape glob:
138
138
139 In [2]: %run print_argv.py 'print*.py'
139 In [2]: %run print_argv.py 'print*.py'
140 ['print*.py']
140 ['print*.py']
141
141
142 """
142 """
143
143
144
144
145 def doctest_reset_del():
145 def doctest_reset_del():
146 """Test that resetting doesn't cause errors in __del__ methods.
146 """Test that resetting doesn't cause errors in __del__ methods.
147
147
148 In [2]: class A(object):
148 In [2]: class A(object):
149 ...: def __del__(self):
149 ...: def __del__(self):
150 ...: print(str("Hi"))
150 ...: print(str("Hi"))
151 ...:
151 ...:
152
152
153 In [3]: a = A()
153 In [3]: a = A()
154
154
155 In [4]: get_ipython().reset()
155 In [4]: get_ipython().reset()
156 Hi
156 Hi
157
157
158 In [5]: 1+1
158 In [5]: 1+1
159 Out[5]: 2
159 Out[5]: 2
160 """
160 """
161
161
162 # For some tests, it will be handy to organize them in a class with a common
162 # For some tests, it will be handy to organize them in a class with a common
163 # setup that makes a temp file
163 # setup that makes a temp file
164
164
165 class TestMagicRunPass(tt.TempFileMixin):
165 class TestMagicRunPass(tt.TempFileMixin):
166
166
167 def setUp(self):
167 def setUp(self):
168 content = "a = [1,2,3]\nb = 1"
168 content = "a = [1,2,3]\nb = 1"
169 self.mktmp(content)
169 self.mktmp(content)
170
170
171 def run_tmpfile(self):
171 def run_tmpfile(self):
172 _ip = get_ipython()
172 _ip = get_ipython()
173 # This fails on Windows if self.tmpfile.name has spaces or "~" in it.
173 # This fails on Windows if self.tmpfile.name has spaces or "~" in it.
174 # See below and ticket https://bugs.launchpad.net/bugs/366353
174 # See below and ticket https://bugs.launchpad.net/bugs/366353
175 _ip.magic('run %s' % self.fname)
175 _ip.magic('run %s' % self.fname)
176
176
177 def run_tmpfile_p(self):
177 def run_tmpfile_p(self):
178 _ip = get_ipython()
178 _ip = get_ipython()
179 # This fails on Windows if self.tmpfile.name has spaces or "~" in it.
179 # This fails on Windows if self.tmpfile.name has spaces or "~" in it.
180 # See below and ticket https://bugs.launchpad.net/bugs/366353
180 # See below and ticket https://bugs.launchpad.net/bugs/366353
181 _ip.magic('run -p %s' % self.fname)
181 _ip.magic('run -p %s' % self.fname)
182
182
183 def test_builtins_id(self):
183 def test_builtins_id(self):
184 """Check that %run doesn't damage __builtins__ """
184 """Check that %run doesn't damage __builtins__ """
185 _ip = get_ipython()
185 _ip = get_ipython()
186 # Test that the id of __builtins__ is not modified by %run
186 # Test that the id of __builtins__ is not modified by %run
187 bid1 = id(_ip.user_ns['__builtins__'])
187 bid1 = id(_ip.user_ns['__builtins__'])
188 self.run_tmpfile()
188 self.run_tmpfile()
189 bid2 = id(_ip.user_ns['__builtins__'])
189 bid2 = id(_ip.user_ns['__builtins__'])
190 assert bid1 == bid2
190 assert bid1 == bid2
191
191
192 def test_builtins_type(self):
192 def test_builtins_type(self):
193 """Check that the type of __builtins__ doesn't change with %run.
193 """Check that the type of __builtins__ doesn't change with %run.
194
194
195 However, the above could pass if __builtins__ was already modified to
195 However, the above could pass if __builtins__ was already modified to
196 be a dict (it should be a module) by a previous use of %run. So we
196 be a dict (it should be a module) by a previous use of %run. So we
197 also check explicitly that it really is a module:
197 also check explicitly that it really is a module:
198 """
198 """
199 _ip = get_ipython()
199 _ip = get_ipython()
200 self.run_tmpfile()
200 self.run_tmpfile()
201 assert type(_ip.user_ns["__builtins__"]) == type(sys)
201 assert type(_ip.user_ns["__builtins__"]) == type(sys)
202
202
203 def test_run_profile(self):
203 def test_run_profile(self):
204 """Test that the option -p, which invokes the profiler, do not
204 """Test that the option -p, which invokes the profiler, do not
205 crash by invoking execfile"""
205 crash by invoking execfile"""
206 self.run_tmpfile_p()
206 self.run_tmpfile_p()
207
207
208 def test_run_debug_twice(self):
208 def test_run_debug_twice(self):
209 # https://github.com/ipython/ipython/issues/10028
209 # https://github.com/ipython/ipython/issues/10028
210 _ip = get_ipython()
210 _ip = get_ipython()
211 with tt.fake_input(['c']):
211 with tt.fake_input(['c']):
212 _ip.magic('run -d %s' % self.fname)
212 _ip.magic('run -d %s' % self.fname)
213 with tt.fake_input(['c']):
213 with tt.fake_input(['c']):
214 _ip.magic('run -d %s' % self.fname)
214 _ip.magic('run -d %s' % self.fname)
215
215
216 def test_run_debug_twice_with_breakpoint(self):
216 def test_run_debug_twice_with_breakpoint(self):
217 """Make a valid python temp file."""
217 """Make a valid python temp file."""
218 _ip = get_ipython()
218 _ip = get_ipython()
219 with tt.fake_input(['b 2', 'c', 'c']):
219 with tt.fake_input(['b 2', 'c', 'c']):
220 _ip.magic('run -d %s' % self.fname)
220 _ip.magic('run -d %s' % self.fname)
221
221
222 with tt.fake_input(['c']):
222 with tt.fake_input(['c']):
223 with tt.AssertNotPrints('KeyError'):
223 with tt.AssertNotPrints('KeyError'):
224 _ip.magic('run -d %s' % self.fname)
224 _ip.magic('run -d %s' % self.fname)
225
225
226
226
227 class TestMagicRunSimple(tt.TempFileMixin):
227 class TestMagicRunSimple(tt.TempFileMixin):
228
228
229 def test_simpledef(self):
229 def test_simpledef(self):
230 """Test that simple class definitions work."""
230 """Test that simple class definitions work."""
231 src = ("class foo: pass\n"
231 src = ("class foo: pass\n"
232 "def f(): return foo()")
232 "def f(): return foo()")
233 self.mktmp(src)
233 self.mktmp(src)
234 _ip.magic("run %s" % self.fname)
234 _ip.magic("run %s" % self.fname)
235 _ip.run_cell("t = isinstance(f(), foo)")
235 _ip.run_cell("t = isinstance(f(), foo)")
236 assert _ip.user_ns["t"] is True
236 assert _ip.user_ns["t"] is True
237
237
238 def test_obj_del(self):
238 def test_obj_del(self):
239 """Test that object's __del__ methods are called on exit."""
239 """Test that object's __del__ methods are called on exit."""
240 if sys.platform == 'win32':
241 try:
242 import win32api
243 except ImportError as e:
244 raise unittest.SkipTest("Test requires pywin32") from e
245 src = ("class A(object):\n"
240 src = ("class A(object):\n"
246 " def __del__(self):\n"
241 " def __del__(self):\n"
247 " print('object A deleted')\n"
242 " print('object A deleted')\n"
248 "a = A()\n")
243 "a = A()\n")
249 self.mktmp(src)
244 self.mktmp(src)
250 err = None
245 err = None
251 tt.ipexec_validate(self.fname, 'object A deleted', err)
246 tt.ipexec_validate(self.fname, 'object A deleted', err)
252
247
253 def test_aggressive_namespace_cleanup(self):
248 def test_aggressive_namespace_cleanup(self):
254 """Test that namespace cleanup is not too aggressive GH-238
249 """Test that namespace cleanup is not too aggressive GH-238
255
250
256 Returning from another run magic deletes the namespace"""
251 Returning from another run magic deletes the namespace"""
257 # see ticket https://github.com/ipython/ipython/issues/238
252 # see ticket https://github.com/ipython/ipython/issues/238
258
253
259 with tt.TempFileMixin() as empty:
254 with tt.TempFileMixin() as empty:
260 empty.mktmp("")
255 empty.mktmp("")
261 # On Windows, the filename will have \users in it, so we need to use the
256 # On Windows, the filename will have \users in it, so we need to use the
262 # repr so that the \u becomes \\u.
257 # repr so that the \u becomes \\u.
263 src = (
258 src = (
264 "ip = get_ipython()\n"
259 "ip = get_ipython()\n"
265 "for i in range(5):\n"
260 "for i in range(5):\n"
266 " try:\n"
261 " try:\n"
267 " ip.magic(%r)\n"
262 " ip.magic(%r)\n"
268 " except NameError as e:\n"
263 " except NameError as e:\n"
269 " print(i)\n"
264 " print(i)\n"
270 " break\n" % ("run " + empty.fname)
265 " break\n" % ("run " + empty.fname)
271 )
266 )
272 self.mktmp(src)
267 self.mktmp(src)
273 _ip.magic("run %s" % self.fname)
268 _ip.magic("run %s" % self.fname)
274 _ip.run_cell("ip == get_ipython()")
269 _ip.run_cell("ip == get_ipython()")
275 assert _ip.user_ns["i"] == 4
270 assert _ip.user_ns["i"] == 4
276
271
277 def test_run_second(self):
272 def test_run_second(self):
278 """Test that running a second file doesn't clobber the first, gh-3547"""
273 """Test that running a second file doesn't clobber the first, gh-3547"""
279 self.mktmp("avar = 1\n" "def afunc():\n" " return avar\n")
274 self.mktmp("avar = 1\n" "def afunc():\n" " return avar\n")
280
275
281 with tt.TempFileMixin() as empty:
276 with tt.TempFileMixin() as empty:
282 empty.mktmp("")
277 empty.mktmp("")
283
278
284 _ip.magic("run %s" % self.fname)
279 _ip.magic("run %s" % self.fname)
285 _ip.magic("run %s" % empty.fname)
280 _ip.magic("run %s" % empty.fname)
286 assert _ip.user_ns["afunc"]() == 1
281 assert _ip.user_ns["afunc"]() == 1
287
282
288 @dec.skip_win32
283 @dec.skip_win32
289 def test_tclass(self):
284 def test_tclass(self):
290 mydir = os.path.dirname(__file__)
285 mydir = os.path.dirname(__file__)
291 tc = os.path.join(mydir, 'tclass')
286 tc = os.path.join(mydir, 'tclass')
292 src = ("%%run '%s' C-first\n"
287 src = ("%%run '%s' C-first\n"
293 "%%run '%s' C-second\n"
288 "%%run '%s' C-second\n"
294 "%%run '%s' C-third\n") % (tc, tc, tc)
289 "%%run '%s' C-third\n") % (tc, tc, tc)
295 self.mktmp(src, '.ipy')
290 self.mktmp(src, '.ipy')
296 out = """\
291 out = """\
297 ARGV 1-: ['C-first']
292 ARGV 1-: ['C-first']
298 ARGV 1-: ['C-second']
293 ARGV 1-: ['C-second']
299 tclass.py: deleting object: C-first
294 tclass.py: deleting object: C-first
300 ARGV 1-: ['C-third']
295 ARGV 1-: ['C-third']
301 tclass.py: deleting object: C-second
296 tclass.py: deleting object: C-second
302 tclass.py: deleting object: C-third
297 tclass.py: deleting object: C-third
303 """
298 """
304 err = None
299 err = None
305 tt.ipexec_validate(self.fname, out, err)
300 tt.ipexec_validate(self.fname, out, err)
306
301
307 def test_run_i_after_reset(self):
302 def test_run_i_after_reset(self):
308 """Check that %run -i still works after %reset (gh-693)"""
303 """Check that %run -i still works after %reset (gh-693)"""
309 src = "yy = zz\n"
304 src = "yy = zz\n"
310 self.mktmp(src)
305 self.mktmp(src)
311 _ip.run_cell("zz = 23")
306 _ip.run_cell("zz = 23")
312 try:
307 try:
313 _ip.magic("run -i %s" % self.fname)
308 _ip.magic("run -i %s" % self.fname)
314 assert _ip.user_ns["yy"] == 23
309 assert _ip.user_ns["yy"] == 23
315 finally:
310 finally:
316 _ip.magic('reset -f')
311 _ip.magic('reset -f')
317
312
318 _ip.run_cell("zz = 23")
313 _ip.run_cell("zz = 23")
319 try:
314 try:
320 _ip.magic("run -i %s" % self.fname)
315 _ip.magic("run -i %s" % self.fname)
321 assert _ip.user_ns["yy"] == 23
316 assert _ip.user_ns["yy"] == 23
322 finally:
317 finally:
323 _ip.magic('reset -f')
318 _ip.magic('reset -f')
324
319
325 def test_unicode(self):
320 def test_unicode(self):
326 """Check that files in odd encodings are accepted."""
321 """Check that files in odd encodings are accepted."""
327 mydir = os.path.dirname(__file__)
322 mydir = os.path.dirname(__file__)
328 na = os.path.join(mydir, 'nonascii.py')
323 na = os.path.join(mydir, 'nonascii.py')
329 _ip.magic('run "%s"' % na)
324 _ip.magic('run "%s"' % na)
330 assert _ip.user_ns["u"] == "ΠŽΡ‚β„–Π€"
325 assert _ip.user_ns["u"] == "ΠŽΡ‚β„–Π€"
331
326
332 def test_run_py_file_attribute(self):
327 def test_run_py_file_attribute(self):
333 """Test handling of `__file__` attribute in `%run <file>.py`."""
328 """Test handling of `__file__` attribute in `%run <file>.py`."""
334 src = "t = __file__\n"
329 src = "t = __file__\n"
335 self.mktmp(src)
330 self.mktmp(src)
336 _missing = object()
331 _missing = object()
337 file1 = _ip.user_ns.get('__file__', _missing)
332 file1 = _ip.user_ns.get('__file__', _missing)
338 _ip.magic('run %s' % self.fname)
333 _ip.magic('run %s' % self.fname)
339 file2 = _ip.user_ns.get('__file__', _missing)
334 file2 = _ip.user_ns.get('__file__', _missing)
340
335
341 # Check that __file__ was equal to the filename in the script's
336 # Check that __file__ was equal to the filename in the script's
342 # namespace.
337 # namespace.
343 assert _ip.user_ns["t"] == self.fname
338 assert _ip.user_ns["t"] == self.fname
344
339
345 # Check that __file__ was not leaked back into user_ns.
340 # Check that __file__ was not leaked back into user_ns.
346 assert file1 == file2
341 assert file1 == file2
347
342
348 def test_run_ipy_file_attribute(self):
343 def test_run_ipy_file_attribute(self):
349 """Test handling of `__file__` attribute in `%run <file.ipy>`."""
344 """Test handling of `__file__` attribute in `%run <file.ipy>`."""
350 src = "t = __file__\n"
345 src = "t = __file__\n"
351 self.mktmp(src, ext='.ipy')
346 self.mktmp(src, ext='.ipy')
352 _missing = object()
347 _missing = object()
353 file1 = _ip.user_ns.get('__file__', _missing)
348 file1 = _ip.user_ns.get('__file__', _missing)
354 _ip.magic('run %s' % self.fname)
349 _ip.magic('run %s' % self.fname)
355 file2 = _ip.user_ns.get('__file__', _missing)
350 file2 = _ip.user_ns.get('__file__', _missing)
356
351
357 # Check that __file__ was equal to the filename in the script's
352 # Check that __file__ was equal to the filename in the script's
358 # namespace.
353 # namespace.
359 assert _ip.user_ns["t"] == self.fname
354 assert _ip.user_ns["t"] == self.fname
360
355
361 # Check that __file__ was not leaked back into user_ns.
356 # Check that __file__ was not leaked back into user_ns.
362 assert file1 == file2
357 assert file1 == file2
363
358
364 def test_run_formatting(self):
359 def test_run_formatting(self):
365 """ Test that %run -t -N<N> does not raise a TypeError for N > 1."""
360 """ Test that %run -t -N<N> does not raise a TypeError for N > 1."""
366 src = "pass"
361 src = "pass"
367 self.mktmp(src)
362 self.mktmp(src)
368 _ip.magic('run -t -N 1 %s' % self.fname)
363 _ip.magic('run -t -N 1 %s' % self.fname)
369 _ip.magic('run -t -N 10 %s' % self.fname)
364 _ip.magic('run -t -N 10 %s' % self.fname)
370
365
371 def test_ignore_sys_exit(self):
366 def test_ignore_sys_exit(self):
372 """Test the -e option to ignore sys.exit()"""
367 """Test the -e option to ignore sys.exit()"""
373 src = "import sys; sys.exit(1)"
368 src = "import sys; sys.exit(1)"
374 self.mktmp(src)
369 self.mktmp(src)
375 with tt.AssertPrints('SystemExit'):
370 with tt.AssertPrints('SystemExit'):
376 _ip.magic('run %s' % self.fname)
371 _ip.magic('run %s' % self.fname)
377
372
378 with tt.AssertNotPrints('SystemExit'):
373 with tt.AssertNotPrints('SystemExit'):
379 _ip.magic('run -e %s' % self.fname)
374 _ip.magic('run -e %s' % self.fname)
380
375
381 def test_run_nb(self):
376 def test_run_nb(self):
382 """Test %run notebook.ipynb"""
377 """Test %run notebook.ipynb"""
383 from nbformat import v4, writes
378 from nbformat import v4, writes
384 nb = v4.new_notebook(
379 nb = v4.new_notebook(
385 cells=[
380 cells=[
386 v4.new_markdown_cell("The Ultimate Question of Everything"),
381 v4.new_markdown_cell("The Ultimate Question of Everything"),
387 v4.new_code_cell("answer=42")
382 v4.new_code_cell("answer=42")
388 ]
383 ]
389 )
384 )
390 src = writes(nb, version=4)
385 src = writes(nb, version=4)
391 self.mktmp(src, ext='.ipynb')
386 self.mktmp(src, ext='.ipynb')
392
387
393 _ip.magic("run %s" % self.fname)
388 _ip.magic("run %s" % self.fname)
394
389
395 assert _ip.user_ns["answer"] == 42
390 assert _ip.user_ns["answer"] == 42
396
391
397 def test_run_nb_error(self):
392 def test_run_nb_error(self):
398 """Test %run notebook.ipynb error"""
393 """Test %run notebook.ipynb error"""
399 from nbformat import v4, writes
394 from nbformat import v4, writes
400 # %run when a file name isn't provided
395 # %run when a file name isn't provided
401 pytest.raises(Exception, _ip.magic, "run")
396 pytest.raises(Exception, _ip.magic, "run")
402
397
403 # %run when a file doesn't exist
398 # %run when a file doesn't exist
404 pytest.raises(Exception, _ip.magic, "run foobar.ipynb")
399 pytest.raises(Exception, _ip.magic, "run foobar.ipynb")
405
400
406 # %run on a notebook with an error
401 # %run on a notebook with an error
407 nb = v4.new_notebook(
402 nb = v4.new_notebook(
408 cells=[
403 cells=[
409 v4.new_code_cell("0/0")
404 v4.new_code_cell("0/0")
410 ]
405 ]
411 )
406 )
412 src = writes(nb, version=4)
407 src = writes(nb, version=4)
413 self.mktmp(src, ext='.ipynb')
408 self.mktmp(src, ext='.ipynb')
414 pytest.raises(Exception, _ip.magic, "run %s" % self.fname)
409 pytest.raises(Exception, _ip.magic, "run %s" % self.fname)
415
410
416 def test_file_options(self):
411 def test_file_options(self):
417 src = ('import sys\n'
412 src = ('import sys\n'
418 'a = " ".join(sys.argv[1:])\n')
413 'a = " ".join(sys.argv[1:])\n')
419 self.mktmp(src)
414 self.mktmp(src)
420 test_opts = "-x 3 --verbose"
415 test_opts = "-x 3 --verbose"
421 _ip.run_line_magic("run", "{0} {1}".format(self.fname, test_opts))
416 _ip.run_line_magic("run", "{0} {1}".format(self.fname, test_opts))
422 assert _ip.user_ns["a"] == test_opts
417 assert _ip.user_ns["a"] == test_opts
423
418
424
419
425 class TestMagicRunWithPackage(unittest.TestCase):
420 class TestMagicRunWithPackage(unittest.TestCase):
426
421
427 def writefile(self, name, content):
422 def writefile(self, name, content):
428 path = os.path.join(self.tempdir.name, name)
423 path = os.path.join(self.tempdir.name, name)
429 d = os.path.dirname(path)
424 d = os.path.dirname(path)
430 if not os.path.isdir(d):
425 if not os.path.isdir(d):
431 os.makedirs(d)
426 os.makedirs(d)
432 with open(path, 'w') as f:
427 with open(path, 'w') as f:
433 f.write(textwrap.dedent(content))
428 f.write(textwrap.dedent(content))
434
429
435 def setUp(self):
430 def setUp(self):
436 self.package = package = 'tmp{0}'.format(''.join([random.choice(string.ascii_letters) for i in range(10)]))
431 self.package = package = 'tmp{0}'.format(''.join([random.choice(string.ascii_letters) for i in range(10)]))
437 """Temporary (probably) valid python package name."""
432 """Temporary (probably) valid python package name."""
438
433
439 self.value = int(random.random() * 10000)
434 self.value = int(random.random() * 10000)
440
435
441 self.tempdir = TemporaryDirectory()
436 self.tempdir = TemporaryDirectory()
442 self.__orig_cwd = os.getcwd()
437 self.__orig_cwd = os.getcwd()
443 sys.path.insert(0, self.tempdir.name)
438 sys.path.insert(0, self.tempdir.name)
444
439
445 self.writefile(os.path.join(package, '__init__.py'), '')
440 self.writefile(os.path.join(package, '__init__.py'), '')
446 self.writefile(os.path.join(package, 'sub.py'), """
441 self.writefile(os.path.join(package, 'sub.py'), """
447 x = {0!r}
442 x = {0!r}
448 """.format(self.value))
443 """.format(self.value))
449 self.writefile(os.path.join(package, 'relative.py'), """
444 self.writefile(os.path.join(package, 'relative.py'), """
450 from .sub import x
445 from .sub import x
451 """)
446 """)
452 self.writefile(os.path.join(package, 'absolute.py'), """
447 self.writefile(os.path.join(package, 'absolute.py'), """
453 from {0}.sub import x
448 from {0}.sub import x
454 """.format(package))
449 """.format(package))
455 self.writefile(os.path.join(package, 'args.py'), """
450 self.writefile(os.path.join(package, 'args.py'), """
456 import sys
451 import sys
457 a = " ".join(sys.argv[1:])
452 a = " ".join(sys.argv[1:])
458 """.format(package))
453 """.format(package))
459
454
460 def tearDown(self):
455 def tearDown(self):
461 os.chdir(self.__orig_cwd)
456 os.chdir(self.__orig_cwd)
462 sys.path[:] = [p for p in sys.path if p != self.tempdir.name]
457 sys.path[:] = [p for p in sys.path if p != self.tempdir.name]
463 self.tempdir.cleanup()
458 self.tempdir.cleanup()
464
459
465 def check_run_submodule(self, submodule, opts=''):
460 def check_run_submodule(self, submodule, opts=''):
466 _ip.user_ns.pop('x', None)
461 _ip.user_ns.pop('x', None)
467 _ip.magic('run {2} -m {0}.{1}'.format(self.package, submodule, opts))
462 _ip.magic('run {2} -m {0}.{1}'.format(self.package, submodule, opts))
468 self.assertEqual(_ip.user_ns['x'], self.value,
463 self.assertEqual(_ip.user_ns['x'], self.value,
469 'Variable `x` is not loaded from module `{0}`.'
464 'Variable `x` is not loaded from module `{0}`.'
470 .format(submodule))
465 .format(submodule))
471
466
472 def test_run_submodule_with_absolute_import(self):
467 def test_run_submodule_with_absolute_import(self):
473 self.check_run_submodule('absolute')
468 self.check_run_submodule('absolute')
474
469
475 def test_run_submodule_with_relative_import(self):
470 def test_run_submodule_with_relative_import(self):
476 """Run submodule that has a relative import statement (#2727)."""
471 """Run submodule that has a relative import statement (#2727)."""
477 self.check_run_submodule('relative')
472 self.check_run_submodule('relative')
478
473
479 def test_prun_submodule_with_absolute_import(self):
474 def test_prun_submodule_with_absolute_import(self):
480 self.check_run_submodule('absolute', '-p')
475 self.check_run_submodule('absolute', '-p')
481
476
482 def test_prun_submodule_with_relative_import(self):
477 def test_prun_submodule_with_relative_import(self):
483 self.check_run_submodule('relative', '-p')
478 self.check_run_submodule('relative', '-p')
484
479
485 def with_fake_debugger(func):
480 def with_fake_debugger(func):
486 @functools.wraps(func)
481 @functools.wraps(func)
487 def wrapper(*args, **kwds):
482 def wrapper(*args, **kwds):
488 with patch.object(debugger.Pdb, 'run', staticmethod(eval)):
483 with patch.object(debugger.Pdb, 'run', staticmethod(eval)):
489 return func(*args, **kwds)
484 return func(*args, **kwds)
490 return wrapper
485 return wrapper
491
486
492 @with_fake_debugger
487 @with_fake_debugger
493 def test_debug_run_submodule_with_absolute_import(self):
488 def test_debug_run_submodule_with_absolute_import(self):
494 self.check_run_submodule('absolute', '-d')
489 self.check_run_submodule('absolute', '-d')
495
490
496 @with_fake_debugger
491 @with_fake_debugger
497 def test_debug_run_submodule_with_relative_import(self):
492 def test_debug_run_submodule_with_relative_import(self):
498 self.check_run_submodule('relative', '-d')
493 self.check_run_submodule('relative', '-d')
499
494
500 def test_module_options(self):
495 def test_module_options(self):
501 _ip.user_ns.pop("a", None)
496 _ip.user_ns.pop("a", None)
502 test_opts = "-x abc -m test"
497 test_opts = "-x abc -m test"
503 _ip.run_line_magic("run", "-m {0}.args {1}".format(self.package, test_opts))
498 _ip.run_line_magic("run", "-m {0}.args {1}".format(self.package, test_opts))
504 assert _ip.user_ns["a"] == test_opts
499 assert _ip.user_ns["a"] == test_opts
505
500
506 def test_module_options_with_separator(self):
501 def test_module_options_with_separator(self):
507 _ip.user_ns.pop("a", None)
502 _ip.user_ns.pop("a", None)
508 test_opts = "-x abc -m test"
503 test_opts = "-x abc -m test"
509 _ip.run_line_magic("run", "-m {0}.args -- {1}".format(self.package, test_opts))
504 _ip.run_line_magic("run", "-m {0}.args -- {1}".format(self.package, test_opts))
510 assert _ip.user_ns["a"] == test_opts
505 assert _ip.user_ns["a"] == test_opts
511
506
512
507
513 def test_run__name__():
508 def test_run__name__():
514 with TemporaryDirectory() as td:
509 with TemporaryDirectory() as td:
515 path = pjoin(td, 'foo.py')
510 path = pjoin(td, 'foo.py')
516 with open(path, 'w') as f:
511 with open(path, 'w') as f:
517 f.write("q = __name__")
512 f.write("q = __name__")
518
513
519 _ip.user_ns.pop("q", None)
514 _ip.user_ns.pop("q", None)
520 _ip.magic("run {}".format(path))
515 _ip.magic("run {}".format(path))
521 assert _ip.user_ns.pop("q") == "__main__"
516 assert _ip.user_ns.pop("q") == "__main__"
522
517
523 _ip.magic("run -n {}".format(path))
518 _ip.magic("run -n {}".format(path))
524 assert _ip.user_ns.pop("q") == "foo"
519 assert _ip.user_ns.pop("q") == "foo"
525
520
526 try:
521 try:
527 _ip.magic("run -i -n {}".format(path))
522 _ip.magic("run -i -n {}".format(path))
528 assert _ip.user_ns.pop("q") == "foo"
523 assert _ip.user_ns.pop("q") == "foo"
529 finally:
524 finally:
530 _ip.magic('reset -f')
525 _ip.magic('reset -f')
531
526
532
527
533 def test_run_tb():
528 def test_run_tb():
534 """Test traceback offset in %run"""
529 """Test traceback offset in %run"""
535 with TemporaryDirectory() as td:
530 with TemporaryDirectory() as td:
536 path = pjoin(td, 'foo.py')
531 path = pjoin(td, 'foo.py')
537 with open(path, 'w') as f:
532 with open(path, 'w') as f:
538 f.write('\n'.join([
533 f.write('\n'.join([
539 "def foo():",
534 "def foo():",
540 " return bar()",
535 " return bar()",
541 "def bar():",
536 "def bar():",
542 " raise RuntimeError('hello!')",
537 " raise RuntimeError('hello!')",
543 "foo()",
538 "foo()",
544 ]))
539 ]))
545 with capture_output() as io:
540 with capture_output() as io:
546 _ip.magic('run {}'.format(path))
541 _ip.magic('run {}'.format(path))
547 out = io.stdout
542 out = io.stdout
548 assert "execfile" not in out
543 assert "execfile" not in out
549 assert "RuntimeError" in out
544 assert "RuntimeError" in out
550 assert out.count("---->") == 3
545 assert out.count("---->") == 3
551 del ip.user_ns['bar']
546 del ip.user_ns['bar']
552 del ip.user_ns['foo']
547 del ip.user_ns['foo']
553
548
554
549
555 def test_multiprocessing_run():
550 def test_multiprocessing_run():
556 """Set we can run mutiprocesgin without messing up up main namespace
551 """Set we can run mutiprocesgin without messing up up main namespace
557
552
558 Note that import `nose.tools as nt` mdify the value s
553 Note that import `nose.tools as nt` mdify the value s
559 sys.module['__mp_main__'] so we need to temporarily set it to None to test
554 sys.module['__mp_main__'] so we need to temporarily set it to None to test
560 the issue.
555 the issue.
561 """
556 """
562 with TemporaryDirectory() as td:
557 with TemporaryDirectory() as td:
563 mpm = sys.modules.get('__mp_main__')
558 mpm = sys.modules.get('__mp_main__')
564 assert mpm is not None
559 assert mpm is not None
565 sys.modules['__mp_main__'] = None
560 sys.modules['__mp_main__'] = None
566 try:
561 try:
567 path = pjoin(td, 'test.py')
562 path = pjoin(td, 'test.py')
568 with open(path, 'w') as f:
563 with open(path, 'w') as f:
569 f.write("import multiprocessing\nprint('hoy')")
564 f.write("import multiprocessing\nprint('hoy')")
570 with capture_output() as io:
565 with capture_output() as io:
571 _ip.run_line_magic('run', path)
566 _ip.run_line_magic('run', path)
572 _ip.run_cell("i_m_undefined")
567 _ip.run_cell("i_m_undefined")
573 out = io.stdout
568 out = io.stdout
574 assert "hoy" in out
569 assert "hoy" in out
575 assert "AttributeError" not in out
570 assert "AttributeError" not in out
576 assert "NameError" in out
571 assert "NameError" in out
577 assert out.count("---->") == 1
572 assert out.count("---->") == 1
578 except:
573 except:
579 raise
574 raise
580 finally:
575 finally:
581 sys.modules['__mp_main__'] = mpm
576 sys.modules['__mp_main__'] = mpm
582
577
583 @dec.knownfailureif(sys.platform == 'win32', "writes to io.stdout aren't captured on Windows")
578 @dec.knownfailureif(sys.platform == 'win32', "writes to io.stdout aren't captured on Windows")
584 def test_script_tb():
579 def test_script_tb():
585 """Test traceback offset in `ipython script.py`"""
580 """Test traceback offset in `ipython script.py`"""
586 with TemporaryDirectory() as td:
581 with TemporaryDirectory() as td:
587 path = pjoin(td, 'foo.py')
582 path = pjoin(td, 'foo.py')
588 with open(path, 'w') as f:
583 with open(path, 'w') as f:
589 f.write('\n'.join([
584 f.write('\n'.join([
590 "def foo():",
585 "def foo():",
591 " return bar()",
586 " return bar()",
592 "def bar():",
587 "def bar():",
593 " raise RuntimeError('hello!')",
588 " raise RuntimeError('hello!')",
594 "foo()",
589 "foo()",
595 ]))
590 ]))
596 out, err = tt.ipexec(path)
591 out, err = tt.ipexec(path)
597 assert "execfile" not in out
592 assert "execfile" not in out
598 assert "RuntimeError" in out
593 assert "RuntimeError" in out
599 assert out.count("---->") == 3
594 assert out.count("---->") == 3
@@ -1,39 +1,39 b''
1 build: false
1 build: false
2 matrix:
2 matrix:
3 fast_finish: true # immediately finish build once one of the jobs fails.
3 fast_finish: true # immediately finish build once one of the jobs fails.
4
4
5 environment:
5 environment:
6 global:
6 global:
7 COLUMNS: 120 # Appveyor web viwer window width is 130 chars
7 COLUMNS: 120 # Appveyor web viwer window width is 130 chars
8
8
9 matrix:
9 matrix:
10
10
11 - PYTHON: "C:\\Python37-x64"
11 - PYTHON: "C:\\Python37-x64"
12 PYTHON_VERSION: "3.7.x"
12 PYTHON_VERSION: "3.7.x"
13 PYTHON_ARCH: "64"
13 PYTHON_ARCH: "64"
14
14
15 - PYTHON: "C:\\Python38"
15 - PYTHON: "C:\\Python38"
16 PYTHON_VERSION: "3.8.x"
16 PYTHON_VERSION: "3.8.x"
17 PYTHON_ARCH: "32"
17 PYTHON_ARCH: "32"
18
18
19 - PYTHON: "C:\\Python38-x64"
19 - PYTHON: "C:\\Python38-x64"
20 PYTHON_VERSION: "3.8.x"
20 PYTHON_VERSION: "3.8.x"
21 PYTHON_ARCH: "64"
21 PYTHON_ARCH: "64"
22
22
23 init:
23 init:
24 - "ECHO %PYTHON% %PYTHON_VERSION% %PYTHON_ARCH%"
24 - "ECHO %PYTHON% %PYTHON_VERSION% %PYTHON_ARCH%"
25
25
26 install:
26 install:
27 - "SET PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%"
27 - "SET PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%"
28 - python -m pip install --upgrade setuptools pip
28 - python -m pip install --upgrade setuptools pip
29 - pip install nose coverage pytest pytest-cov pytest-trio pywin32 matplotlib pandas
29 - pip install nose coverage pytest pytest-cov pytest-trio matplotlib pandas
30 - pip install -e .[test]
30 - pip install -e .[test]
31 - mkdir results
31 - mkdir results
32 - cd results
32 - cd results
33 test_script:
33 test_script:
34 - iptest --coverage xml
34 - iptest --coverage xml
35 - cd ..
35 - cd ..
36 - pytest --color=yes -ra --cov --cov-report=xml
36 - pytest --color=yes -ra --cov --cov-report=xml
37 on_finish:
37 on_finish:
38 - curl -Os https://uploader.codecov.io/latest/windows/codecov.exe
38 - curl -Os https://uploader.codecov.io/latest/windows/codecov.exe
39 - codecov -e PYTHON_VERSION,PYTHON_ARCH
39 - codecov -e PYTHON_VERSION,PYTHON_ARCH
General Comments 0
You need to be logged in to leave comments. Login now