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