##// END OF EJS Templates
save future compile directives from ipython -i module.py
Thomas Ballinger -
Show More
@@ -2565,10 +2565,16 b' class InteractiveShell(SingletonConfigurable):'
2565 2565 silenced for zero status, as it is so common).
2566 2566 raise_exceptions : bool (False)
2567 2567 If True raise exceptions everywhere. Meant for testing.
2568 shell_futures : bool (False)
2569 If True, the code will share future statements with the interactive
2570 shell. It will both be affected by previous __future__ imports, and
2571 any __future__ imports in the code will affect the shell. If False,
2572 __future__ imports are not shared in either direction.
2568 2573
2569 2574 """
2570 2575 kw.setdefault('exit_ignore', False)
2571 2576 kw.setdefault('raise_exceptions', False)
2577 kw.setdefault('shell_futures', False)
2572 2578
2573 2579 fname = os.path.abspath(os.path.expanduser(fname))
2574 2580
@@ -2587,7 +2593,10 b' class InteractiveShell(SingletonConfigurable):'
2587 2593
2588 2594 with prepended_to_syspath(dname):
2589 2595 try:
2590 py3compat.execfile(fname,*where)
2596 glob, loc = (where + (None, ))[:2]
2597 py3compat.execfile(
2598 fname, glob, loc,
2599 self.compile if kw['shell_futures'] else None)
2591 2600 except SystemExit as status:
2592 2601 # If the call was made with 0 or None exit status (sys.exit(0)
2593 2602 # or sys.exit() ), don't bother showing a traceback, as both of
@@ -2608,7 +2617,7 b' class InteractiveShell(SingletonConfigurable):'
2608 2617 # tb offset is 2 because we wrap execfile
2609 2618 self.showtraceback(tb_offset=2)
2610 2619
2611 def safe_execfile_ipy(self, fname):
2620 def safe_execfile_ipy(self, fname, shell_futures=False):
2612 2621 """Like safe_execfile, but for .ipy or .ipynb files with IPython syntax.
2613 2622
2614 2623 Parameters
@@ -2616,6 +2625,11 b' class InteractiveShell(SingletonConfigurable):'
2616 2625 fname : str
2617 2626 The name of the file to execute. The filename must have a
2618 2627 .ipy or .ipynb extension.
2628 shell_futures : bool (False)
2629 If True, the code will share future statements with the interactive
2630 shell. It will both be affected by previous __future__ imports, and
2631 any __future__ imports in the code will affect the shell. If False,
2632 __future__ imports are not shared in either direction.
2619 2633 """
2620 2634 fname = os.path.abspath(os.path.expanduser(fname))
2621 2635
@@ -2654,7 +2668,7 b' class InteractiveShell(SingletonConfigurable):'
2654 2668 # raised in user code. It would be nice if there were
2655 2669 # versions of run_cell that did raise, so
2656 2670 # we could catch the errors.
2657 self.run_cell(cell, silent=True, shell_futures=False)
2671 self.run_cell(cell, silent=True, shell_futures=shell_futures)
2658 2672 except:
2659 2673 self.showtraceback()
2660 2674 warn('Unknown failure executing file: <%s>' % fname)
@@ -324,7 +324,7 b' class InteractiveShellApp(Configurable):'
324 324 self.log.warn("Unknown error in handling IPythonApp.exec_lines:")
325 325 self.shell.showtraceback()
326 326
327 def _exec_file(self, fname):
327 def _exec_file(self, fname, shell_futures=False):
328 328 try:
329 329 full_filename = filefind(fname, [u'.', self.ipython_dir])
330 330 except IOError as e:
@@ -346,11 +346,13 b' class InteractiveShellApp(Configurable):'
346 346 with preserve_keys(self.shell.user_ns, '__file__'):
347 347 self.shell.user_ns['__file__'] = fname
348 348 if full_filename.endswith('.ipy'):
349 self.shell.safe_execfile_ipy(full_filename)
349 self.shell.safe_execfile_ipy(full_filename,
350 shell_futures=shell_futures)
350 351 else:
351 352 # default to python, even without extension
352 353 self.shell.safe_execfile(full_filename,
353 self.shell.user_ns)
354 self.shell.user_ns,
355 shell_futures=shell_futures)
354 356 finally:
355 357 sys.argv = save_argv
356 358
@@ -418,7 +420,7 b' class InteractiveShellApp(Configurable):'
418 420 elif self.file_to_run:
419 421 fname = self.file_to_run
420 422 try:
421 self._exec_file(fname)
423 self._exec_file(fname, shell_futures=True)
422 424 except:
423 425 self.log.warn("Error in executing file in user namespace: %s" %
424 426 fname)
@@ -19,6 +19,11 b' import unittest'
19 19
20 20 from IPython.testing import decorators as dec
21 21 from IPython.testing import tools as tt
22 from IPython.utils.py3compat import PY3
23
24 sqlite_err_maybe = dec.module_not_available('sqlite3')
25 SQLITE_NOT_AVAILABLE_ERROR = ('WARNING: IPython History requires SQLite,'
26 ' your history will not be saved\n')
22 27
23 28 class TestFileToRun(unittest.TestCase, tt.TempFileMixin):
24 29 """Test the behavior of the file_to_run parameter."""
@@ -28,10 +33,7 b' class TestFileToRun(unittest.TestCase, tt.TempFileMixin):'
28 33 src = "print(__file__)\n"
29 34 self.mktmp(src)
30 35
31 if dec.module_not_available('sqlite3'):
32 err = 'WARNING: IPython History requires SQLite, your history will not be saved\n'
33 else:
34 err = None
36 err = SQLITE_NOT_AVAILABLE_ERROR if sqlite_err_maybe else None
35 37 tt.ipexec_validate(self.fname, self.fname, err)
36 38
37 39 def test_ipy_script_file_attribute(self):
@@ -39,11 +41,24 b' class TestFileToRun(unittest.TestCase, tt.TempFileMixin):'
39 41 src = "print(__file__)\n"
40 42 self.mktmp(src, ext='.ipy')
41 43
42 if dec.module_not_available('sqlite3'):
43 err = 'WARNING: IPython History requires SQLite, your history will not be saved\n'
44 else:
45 err = None
44 err = SQLITE_NOT_AVAILABLE_ERROR if sqlite_err_maybe else None
46 45 tt.ipexec_validate(self.fname, self.fname, err)
47 46
48 # Ideally we would also test that `__file__` is not set in the
49 # interactive namespace after running `ipython -i <file>`.
47 def test_py_script_file_attribute_interactively(self):
48 """Test that `__file__` is not set after `ipython -i file.py`"""
49 src = "True\n"
50 self.mktmp(src)
51
52 err = SQLITE_NOT_AVAILABLE_ERROR if sqlite_err_maybe else None
53 tt.ipexec_validate(self.fname, 'False', err, options=['-i'],
54 commands=['"__file__" in globals()', 'exit()'])
55
56 @dec.skipif(PY3)
57 def test_py_script_file_compiler_directive(self):
58 """Test `__future__` compiler directives with `ipython -i file.py`"""
59 src = "from __future__ import division\n"
60 self.mktmp(src)
61
62 err = SQLITE_NOT_AVAILABLE_ERROR if sqlite_err_maybe else None
63 tt.ipexec_validate(self.fname, 'float', err, options=['-i'],
64 commands=['type(1/2)', 'exit()'])
@@ -177,7 +177,7 b' def get_ipython_cmd(as_string=False):'
177 177
178 178 return ipython_cmd
179 179
180 def ipexec(fname, options=None):
180 def ipexec(fname, options=None, commands=()):
181 181 """Utility to call 'ipython filename'.
182 182
183 183 Starts IPython with a minimal and safe configuration to make startup as fast
@@ -193,6 +193,9 b' def ipexec(fname, options=None):'
193 193 options : optional, list
194 194 Extra command-line flags to be passed to IPython.
195 195
196 commands : optional, list
197 Commands to send in on stdin
198
196 199 Returns
197 200 -------
198 201 (stdout, stderr) of ipython subprocess.
@@ -215,8 +218,8 b' def ipexec(fname, options=None):'
215 218 full_cmd = ipython_cmd + cmdargs + [full_fname]
216 219 env = os.environ.copy()
217 220 env.pop('PYTHONWARNINGS', None) # Avoid extraneous warnings appearing on stderr
218 p = Popen(full_cmd, stdout=PIPE, stderr=PIPE, env=env)
219 out, err = p.communicate()
221 p = Popen(full_cmd, stdout=PIPE, stderr=PIPE, stdin=PIPE, env=env)
222 out, err = p.communicate(input=py3compat.str_to_bytes('\n'.join(commands)) or None)
220 223 out, err = py3compat.bytes_to_str(out), py3compat.bytes_to_str(err)
221 224 # `import readline` causes 'ESC[?1034h' to be output sometimes,
222 225 # so strip that out before doing comparisons
@@ -226,7 +229,7 b' def ipexec(fname, options=None):'
226 229
227 230
228 231 def ipexec_validate(fname, expected_out, expected_err='',
229 options=None):
232 options=None, commands=()):
230 233 """Utility to call 'ipython filename' and validate output/error.
231 234
232 235 This function raises an AssertionError if the validation fails.
@@ -254,7 +257,7 b" def ipexec_validate(fname, expected_out, expected_err='',"
254 257
255 258 import nose.tools as nt
256 259
257 out, err = ipexec(fname, options)
260 out, err = ipexec(fname, options, commands)
258 261 #print 'OUT', out # dbg
259 262 #print 'ERR', err # dbg
260 263 # If there are any errors, we must check those befor stdout, as they may be
@@ -102,10 +102,11 b' if sys.version_info[0] >= 3:'
102 102
103 103 MethodType = types.MethodType
104 104
105 def execfile(fname, glob, loc=None):
105 def execfile(fname, glob, loc=None, compiler=None):
106 106 loc = loc if (loc is not None) else glob
107 107 with open(fname, 'rb') as f:
108 exec(compile(f.read(), fname, 'exec'), glob, loc)
108 compiler = compiler or compile
109 exec(compiler(f.read(), fname, 'exec'), glob, loc)
109 110
110 111 # Refactor print statements in doctests.
111 112 _print_statement_re = re.compile(r"\bprint (?P<expr>.*)$", re.MULTILINE)
@@ -185,7 +186,7 b' else:'
185 186 return s.format(u='u')
186 187
187 188 if sys.platform == 'win32':
188 def execfile(fname, glob=None, loc=None):
189 def execfile(fname, glob=None, loc=None, compiler=None):
189 190 loc = loc if (loc is not None) else glob
190 191 # The rstrip() is necessary b/c trailing whitespace in files will
191 192 # cause an IndentationError in Python 2.6 (this was fixed in 2.7,
@@ -197,14 +198,21 b' else:'
197 198 filename = unicode_to_str(fname)
198 199 else:
199 200 filename = fname
200 exec(compile(scripttext, filename, 'exec'), glob, loc)
201 compiler = compiler or compile
202 exec(compiler(scripttext, filename, 'exec'), glob, loc)
203
201 204 else:
202 def execfile(fname, *where):
205 def execfile(fname, glob=None, loc=None, compiler=None):
203 206 if isinstance(fname, unicode):
204 207 filename = fname.encode(sys.getfilesystemencoding())
205 208 else:
206 209 filename = fname
210 where = [ns for ns in [glob, loc] if ns is not None]
211 if compiler is None:
207 212 builtin_mod.execfile(filename, *where)
213 else:
214 scripttext = builtin_mod.open(fname).read().rstrip() + '\n'
215 exec(compiler(scripttext, filename, 'exec'), glob, loc)
208 216
209 217
210 218 def annotate(**kwargs):
General Comments 0
You need to be logged in to leave comments. Login now