##// END OF EJS Templates
Merge pull request #2460 from bfroehle/ipy_file_inject...
Bradley M. Froehle -
r9018:49f4b46d merge
parent child Browse files
Show More
@@ -0,0 +1,51 b''
1 # -*- coding: utf-8 -*-
2 """Tests for shellapp module.
3
4 Authors
5 -------
6 * Bradley Froehle
7 """
8 #-----------------------------------------------------------------------------
9 # Copyright (C) 2012 The IPython Development Team
10 #
11 # Distributed under the terms of the BSD License. The full license is in
12 # the file COPYING, distributed as part of this software.
13 #-----------------------------------------------------------------------------
14
15 #-----------------------------------------------------------------------------
16 # Imports
17 #-----------------------------------------------------------------------------
18 import unittest
19
20 import nose.tools as nt
21
22 from IPython.testing import decorators as dec
23 from IPython.testing import tools as tt
24
25 class TestFileToRun(unittest.TestCase, tt.TempFileMixin):
26 """Test the behavior of the file_to_run parameter."""
27
28 def test_py_script_file_attribute(self):
29 """Test that `__file__` is set when running `ipython file.py`"""
30 src = "print(__file__)\n"
31 self.mktmp(src)
32
33 if dec.module_not_available('sqlite3'):
34 err = 'WARNING: IPython History requires SQLite, your history will not be saved\n'
35 else:
36 err = None
37 tt.ipexec_validate(self.fname, self.fname, err)
38
39 def test_ipy_script_file_attribute(self):
40 """Test that `__file__` is set when running `ipython file.ipy`"""
41 src = "print(__file__)\n"
42 self.mktmp(src, ext='.ipy')
43
44 if dec.module_not_available('sqlite3'):
45 err = 'WARNING: IPython History requires SQLite, your history will not be saved\n'
46 else:
47 err = None
48 tt.ipexec_validate(self.fname, self.fname, err)
49
50 # Ideally we would also test that `__file__` is not set in the
51 # interactive namespace after running `ipython -i <file>`.
@@ -0,0 +1,71 b''
1 # encoding: utf-8
2 """
3 Context managers for temporarily updating dictionaries.
4
5 Authors:
6
7 * Bradley Froehle
8 """
9
10 #-----------------------------------------------------------------------------
11 # Copyright (C) 2012 The IPython Development Team
12 #
13 # Distributed under the terms of the BSD License. The full license is in
14 # the file COPYING, distributed as part of this software.
15 #-----------------------------------------------------------------------------
16
17 #-----------------------------------------------------------------------------
18 # Code
19 #-----------------------------------------------------------------------------
20
21 class preserve_keys(object):
22 """Preserve a set of keys in a dictionary.
23
24 Upon entering the context manager the current values of the keys
25 will be saved. Upon exiting, the dictionary will be updated to
26 restore the original value of the preserved keys. Preserved keys
27 which did not exist when entering the context manager will be
28 deleted.
29
30 Example
31 -------
32
33 >>> d = {'a': 1, 'b': 2, 'c': 3}
34 >>> with preserve_keys(d, 'b', 'c', 'd'):
35 ... del d['a']
36 ... del d['b'] # will be reset to 2
37 ... d['c'] = None # will be reset to 3
38 ... d['d'] = 4 # will be deleted
39 ... d['e'] = 5
40 ... print(sorted(d.items()))
41 ...
42 [('c', None), ('d', 4), ('e', 5)]
43 >>> print(sorted(d.items()))
44 [('b', 2), ('c', 3), ('e', 5)]
45 """
46
47 def __init__(self, dictionary, *keys):
48 self.dictionary = dictionary
49 self.keys = keys
50
51 def __enter__(self):
52 # Actions to perform upon exiting.
53 to_delete = []
54 to_update = {}
55
56 d = self.dictionary
57 for k in self.keys:
58 if k in d:
59 to_update[k] = d[k]
60 else:
61 to_delete.append(k)
62
63 self.to_delete = to_delete
64 self.to_update = to_update
65
66 def __exit__(self, *exc_info):
67 d = self.dictionary
68
69 for k in self.to_delete:
70 d.pop(k, None)
71 d.update(self.to_update)
@@ -42,6 +42,7 b' from IPython.core.magic import (Magics, magics_class, line_magic, cell_magic,'
42 line_cell_magic, on_off, needs_local_scope)
42 line_cell_magic, on_off, needs_local_scope)
43 from IPython.testing.skipdoctest import skip_doctest
43 from IPython.testing.skipdoctest import skip_doctest
44 from IPython.utils import py3compat
44 from IPython.utils import py3compat
45 from IPython.utils.contexts import preserve_keys
45 from IPython.utils.io import capture_output
46 from IPython.utils.io import capture_output
46 from IPython.utils.ipstruct import Struct
47 from IPython.utils.ipstruct import Struct
47 from IPython.utils.module_paths import find_mod
48 from IPython.utils.module_paths import find_mod
@@ -478,7 +479,9 b' python-profiler package from non-free.""")'
478 return
479 return
479
480
480 if filename.lower().endswith('.ipy'):
481 if filename.lower().endswith('.ipy'):
481 self.shell.safe_execfile_ipy(filename)
482 with preserve_keys(self.shell.user_ns, '__file__'):
483 self.shell.user_ns['__file__'] = filename
484 self.shell.safe_execfile_ipy(filename)
482 return
485 return
483
486
484 # Control the response to exit() calls made by the script being run
487 # Control the response to exit() calls made by the script being run
@@ -644,7 +647,8 b' python-profiler package from non-free.""")'
644 # worry about a possible KeyError.
647 # worry about a possible KeyError.
645 prog_ns.pop('__name__', None)
648 prog_ns.pop('__name__', None)
646
649
647 self.shell.user_ns.update(prog_ns)
650 with preserve_keys(self.shell.user_ns, '__file__'):
651 self.shell.user_ns.update(prog_ns)
648 finally:
652 finally:
649 # It's a bit of a mystery why, but __builtins__ can change from
653 # It's a bit of a mystery why, but __builtins__ can change from
650 # being a module to becoming a dict missing some key data after
654 # being a module to becoming a dict missing some key data after
@@ -31,6 +31,7 b' from IPython.config.configurable import Configurable'
31 from IPython.config.loader import Config
31 from IPython.config.loader import Config
32 from IPython.core import pylabtools
32 from IPython.core import pylabtools
33 from IPython.utils import py3compat
33 from IPython.utils import py3compat
34 from IPython.utils.contexts import preserve_keys
34 from IPython.utils.path import filefind
35 from IPython.utils.path import filefind
35 from IPython.utils.traitlets import (
36 from IPython.utils.traitlets import (
36 Unicode, Instance, List, Bool, CaselessStrEnum
37 Unicode, Instance, List, Bool, CaselessStrEnum
@@ -277,20 +278,18 b' class InteractiveShellApp(Configurable):'
277 sys.argv = [ py3compat.cast_bytes(a) for a in sys.argv ]
278 sys.argv = [ py3compat.cast_bytes(a) for a in sys.argv ]
278 try:
279 try:
279 if os.path.isfile(full_filename):
280 if os.path.isfile(full_filename):
280 if full_filename.endswith('.ipy'):
281 self.log.info("Running file in user namespace: %s" %
281 self.log.info("Running file in user namespace: %s" %
282 full_filename)
282 full_filename)
283 # Ensure that __file__ is always defined to match Python
283 self.shell.safe_execfile_ipy(full_filename)
284 # behavior.
284 else:
285 with preserve_keys(self.shell.user_ns, '__file__'):
285 # default to python, even without extension
286 self.log.info("Running file in user namespace: %s" %
287 full_filename)
288 # Ensure that __file__ is always defined to match Python behavior
289 self.shell.user_ns['__file__'] = fname
286 self.shell.user_ns['__file__'] = fname
290 try:
287 if full_filename.endswith('.ipy'):
291 self.shell.safe_execfile(full_filename, self.shell.user_ns)
288 self.shell.safe_execfile_ipy(full_filename)
292 finally:
289 else:
293 del self.shell.user_ns['__file__']
290 # default to python, even without extension
291 self.shell.safe_execfile(full_filename,
292 self.shell.user_ns)
294 finally:
293 finally:
295 sys.argv = save_argv
294 sys.argv = save_argv
296
295
@@ -298,3 +298,35 b' tclass.py: deleting object: C-third'
298 na = os.path.join(mydir, 'nonascii.py')
298 na = os.path.join(mydir, 'nonascii.py')
299 _ip.magic('run "%s"' % na)
299 _ip.magic('run "%s"' % na)
300 nt.assert_equal(_ip.user_ns['u'], u'Ўт№Ф')
300 nt.assert_equal(_ip.user_ns['u'], u'Ўт№Ф')
301
302 def test_run_py_file_attribute(self):
303 """Test handling of `__file__` attribute in `%run <file>.py`."""
304 src = "t = __file__\n"
305 self.mktmp(src)
306 _missing = object()
307 file1 = _ip.user_ns.get('__file__', _missing)
308 _ip.magic('run %s' % self.fname)
309 file2 = _ip.user_ns.get('__file__', _missing)
310
311 # Check that __file__ was equal to the filename in the script's
312 # namespace.
313 nt.assert_equal(_ip.user_ns['t'], self.fname)
314
315 # Check that __file__ was not leaked back into user_ns.
316 nt.assert_equal(file1, file2)
317
318 def test_run_ipy_file_attribute(self):
319 """Test handling of `__file__` attribute in `%run <file.ipy>`."""
320 src = "t = __file__\n"
321 self.mktmp(src, ext='.ipy')
322 _missing = object()
323 file1 = _ip.user_ns.get('__file__', _missing)
324 _ip.magic('run %s' % self.fname)
325 file2 = _ip.user_ns.get('__file__', _missing)
326
327 # Check that __file__ was equal to the filename in the script's
328 # namespace.
329 nt.assert_equal(_ip.user_ns['t'], self.fname)
330
331 # Check that __file__ was not leaked back into user_ns.
332 nt.assert_equal(file1, file2)
General Comments 0
You need to be logged in to leave comments. Login now