##// END OF EJS Templates
save future compile directives from ipython -i module.py
Thomas Ballinger -
Show More

The requested changes are too big and content was truncated. Show full diff

1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
@@ -1,438 +1,440 b''
1 1 # encoding: utf-8
2 2 """
3 3 A mixin for :class:`~IPython.core.application.Application` classes that
4 4 launch InteractiveShell instances, load extensions, etc.
5 5
6 6 Authors
7 7 -------
8 8
9 9 * Min Ragan-Kelley
10 10 """
11 11
12 12 #-----------------------------------------------------------------------------
13 13 # Copyright (C) 2008-2011 The IPython Development Team
14 14 #
15 15 # Distributed under the terms of the BSD License. The full license is in
16 16 # the file COPYING, distributed as part of this software.
17 17 #-----------------------------------------------------------------------------
18 18
19 19 #-----------------------------------------------------------------------------
20 20 # Imports
21 21 #-----------------------------------------------------------------------------
22 22
23 23 from __future__ import absolute_import
24 24 from __future__ import print_function
25 25
26 26 import glob
27 27 import os
28 28 import sys
29 29
30 30 from IPython.config.application import boolean_flag
31 31 from IPython.config.configurable import Configurable
32 32 from IPython.config.loader import Config
33 33 from IPython.core import pylabtools
34 34 from IPython.utils import py3compat
35 35 from IPython.utils.contexts import preserve_keys
36 36 from IPython.utils.path import filefind
37 37 from IPython.utils.traitlets import (
38 38 Unicode, Instance, List, Bool, CaselessStrEnum
39 39 )
40 40 from IPython.lib.inputhook import guis
41 41
42 42 #-----------------------------------------------------------------------------
43 43 # Aliases and Flags
44 44 #-----------------------------------------------------------------------------
45 45
46 46 gui_keys = tuple(sorted([ key for key in guis if key is not None ]))
47 47
48 48 backend_keys = sorted(pylabtools.backends.keys())
49 49 backend_keys.insert(0, 'auto')
50 50
51 51 shell_flags = {}
52 52
53 53 addflag = lambda *args: shell_flags.update(boolean_flag(*args))
54 54 addflag('autoindent', 'InteractiveShell.autoindent',
55 55 'Turn on autoindenting.', 'Turn off autoindenting.'
56 56 )
57 57 addflag('automagic', 'InteractiveShell.automagic',
58 58 """Turn on the auto calling of magic commands. Type %%magic at the
59 59 IPython prompt for more information.""",
60 60 'Turn off the auto calling of magic commands.'
61 61 )
62 62 addflag('pdb', 'InteractiveShell.pdb',
63 63 "Enable auto calling the pdb debugger after every exception.",
64 64 "Disable auto calling the pdb debugger after every exception."
65 65 )
66 66 # pydb flag doesn't do any config, as core.debugger switches on import,
67 67 # which is before parsing. This just allows the flag to be passed.
68 68 shell_flags.update(dict(
69 69 pydb = ({},
70 70 """Use the third party 'pydb' package as debugger, instead of pdb.
71 71 Requires that pydb is installed."""
72 72 )
73 73 ))
74 74 addflag('pprint', 'PlainTextFormatter.pprint',
75 75 "Enable auto pretty printing of results.",
76 76 "Disable auto pretty printing of results."
77 77 )
78 78 addflag('color-info', 'InteractiveShell.color_info',
79 79 """IPython can display information about objects via a set of func-
80 80 tions, and optionally can use colors for this, syntax highlighting
81 81 source code and various other elements. However, because this
82 82 information is passed through a pager (like 'less') and many pagers get
83 83 confused with color codes, this option is off by default. You can test
84 84 it and turn it on permanently in your ipython_config.py file if it
85 85 works for you. Test it and turn it on permanently if it works with
86 86 your system. The magic function %%color_info allows you to toggle this
87 87 interactively for testing.""",
88 88 "Disable using colors for info related things."
89 89 )
90 90 addflag('deep-reload', 'InteractiveShell.deep_reload',
91 91 """Enable deep (recursive) reloading by default. IPython can use the
92 92 deep_reload module which reloads changes in modules recursively (it
93 93 replaces the reload() function, so you don't need to change anything to
94 94 use it). deep_reload() forces a full reload of modules whose code may
95 95 have changed, which the default reload() function does not. When
96 96 deep_reload is off, IPython will use the normal reload(), but
97 97 deep_reload will still be available as dreload(). This feature is off
98 98 by default [which means that you have both normal reload() and
99 99 dreload()].""",
100 100 "Disable deep (recursive) reloading by default."
101 101 )
102 102 nosep_config = Config()
103 103 nosep_config.InteractiveShell.separate_in = ''
104 104 nosep_config.InteractiveShell.separate_out = ''
105 105 nosep_config.InteractiveShell.separate_out2 = ''
106 106
107 107 shell_flags['nosep']=(nosep_config, "Eliminate all spacing between prompts.")
108 108 shell_flags['pylab'] = (
109 109 {'InteractiveShellApp' : {'pylab' : 'auto'}},
110 110 """Pre-load matplotlib and numpy for interactive use with
111 111 the default matplotlib backend."""
112 112 )
113 113 shell_flags['matplotlib'] = (
114 114 {'InteractiveShellApp' : {'matplotlib' : 'auto'}},
115 115 """Configure matplotlib for interactive use with
116 116 the default matplotlib backend."""
117 117 )
118 118
119 119 # it's possible we don't want short aliases for *all* of these:
120 120 shell_aliases = dict(
121 121 autocall='InteractiveShell.autocall',
122 122 colors='InteractiveShell.colors',
123 123 logfile='InteractiveShell.logfile',
124 124 logappend='InteractiveShell.logappend',
125 125 c='InteractiveShellApp.code_to_run',
126 126 m='InteractiveShellApp.module_to_run',
127 127 ext='InteractiveShellApp.extra_extension',
128 128 gui='InteractiveShellApp.gui',
129 129 pylab='InteractiveShellApp.pylab',
130 130 matplotlib='InteractiveShellApp.matplotlib',
131 131 )
132 132 shell_aliases['cache-size'] = 'InteractiveShell.cache_size'
133 133
134 134 #-----------------------------------------------------------------------------
135 135 # Main classes and functions
136 136 #-----------------------------------------------------------------------------
137 137
138 138 class InteractiveShellApp(Configurable):
139 139 """A Mixin for applications that start InteractiveShell instances.
140 140
141 141 Provides configurables for loading extensions and executing files
142 142 as part of configuring a Shell environment.
143 143
144 144 The following methods should be called by the :meth:`initialize` method
145 145 of the subclass:
146 146
147 147 - :meth:`init_path`
148 148 - :meth:`init_shell` (to be implemented by the subclass)
149 149 - :meth:`init_gui_pylab`
150 150 - :meth:`init_extensions`
151 151 - :meth:`init_code`
152 152 """
153 153 extensions = List(Unicode, config=True,
154 154 help="A list of dotted module names of IPython extensions to load."
155 155 )
156 156 extra_extension = Unicode('', config=True,
157 157 help="dotted module name of an IPython extension to load."
158 158 )
159 159 def _extra_extension_changed(self, name, old, new):
160 160 if new:
161 161 # add to self.extensions
162 162 self.extensions.append(new)
163 163
164 164 # Extensions that are always loaded (not configurable)
165 165 default_extensions = List(Unicode, [u'storemagic'], config=False)
166 166
167 167 hide_initial_ns = Bool(True, config=True,
168 168 help="""Should variables loaded at startup (by startup files, exec_lines, etc.)
169 169 be hidden from tools like %who?"""
170 170 )
171 171
172 172 exec_files = List(Unicode, config=True,
173 173 help="""List of files to run at IPython startup."""
174 174 )
175 175 exec_PYTHONSTARTUP = Bool(True, config=True,
176 176 help="""Run the file referenced by the PYTHONSTARTUP environment
177 177 variable at IPython startup."""
178 178 )
179 179 file_to_run = Unicode('', config=True,
180 180 help="""A file to be run""")
181 181
182 182 exec_lines = List(Unicode, config=True,
183 183 help="""lines of code to run at IPython startup."""
184 184 )
185 185 code_to_run = Unicode('', config=True,
186 186 help="Execute the given command string."
187 187 )
188 188 module_to_run = Unicode('', config=True,
189 189 help="Run the module as a script."
190 190 )
191 191 gui = CaselessStrEnum(gui_keys, config=True,
192 192 help="Enable GUI event loop integration with any of {0}.".format(gui_keys)
193 193 )
194 194 matplotlib = CaselessStrEnum(backend_keys,
195 195 config=True,
196 196 help="""Configure matplotlib for interactive use with
197 197 the default matplotlib backend."""
198 198 )
199 199 pylab = CaselessStrEnum(backend_keys,
200 200 config=True,
201 201 help="""Pre-load matplotlib and numpy for interactive use,
202 202 selecting a particular matplotlib backend and loop integration.
203 203 """
204 204 )
205 205 pylab_import_all = Bool(True, config=True,
206 206 help="""If true, IPython will populate the user namespace with numpy, pylab, etc.
207 207 and an ``import *`` is done from numpy and pylab, when using pylab mode.
208 208
209 209 When False, pylab mode should not import any names into the user namespace.
210 210 """
211 211 )
212 212 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
213 213
214 214 user_ns = Instance(dict, args=None, allow_none=True)
215 215 def _user_ns_changed(self, name, old, new):
216 216 if self.shell is not None:
217 217 self.shell.user_ns = new
218 218 self.shell.init_user_ns()
219 219
220 220 def init_path(self):
221 221 """Add current working directory, '', to sys.path"""
222 222 if sys.path[0] != '':
223 223 sys.path.insert(0, '')
224 224
225 225 def init_shell(self):
226 226 raise NotImplementedError("Override in subclasses")
227 227
228 228 def init_gui_pylab(self):
229 229 """Enable GUI event loop integration, taking pylab into account."""
230 230 enable = False
231 231 shell = self.shell
232 232 if self.pylab:
233 233 enable = lambda key: shell.enable_pylab(key, import_all=self.pylab_import_all)
234 234 key = self.pylab
235 235 elif self.matplotlib:
236 236 enable = shell.enable_matplotlib
237 237 key = self.matplotlib
238 238 elif self.gui:
239 239 enable = shell.enable_gui
240 240 key = self.gui
241 241
242 242 if not enable:
243 243 return
244 244
245 245 try:
246 246 r = enable(key)
247 247 except ImportError:
248 248 self.log.warn("Eventloop or matplotlib integration failed. Is matplotlib installed?")
249 249 self.shell.showtraceback()
250 250 return
251 251 except Exception:
252 252 self.log.warn("GUI event loop or pylab initialization failed")
253 253 self.shell.showtraceback()
254 254 return
255 255
256 256 if isinstance(r, tuple):
257 257 gui, backend = r[:2]
258 258 self.log.info("Enabling GUI event loop integration, "
259 259 "eventloop=%s, matplotlib=%s", gui, backend)
260 260 if key == "auto":
261 261 print("Using matplotlib backend: %s" % backend)
262 262 else:
263 263 gui = r
264 264 self.log.info("Enabling GUI event loop integration, "
265 265 "eventloop=%s", gui)
266 266
267 267 def init_extensions(self):
268 268 """Load all IPython extensions in IPythonApp.extensions.
269 269
270 270 This uses the :meth:`ExtensionManager.load_extensions` to load all
271 271 the extensions listed in ``self.extensions``.
272 272 """
273 273 try:
274 274 self.log.debug("Loading IPython extensions...")
275 275 extensions = self.default_extensions + self.extensions
276 276 for ext in extensions:
277 277 try:
278 278 self.log.info("Loading IPython extension: %s" % ext)
279 279 self.shell.extension_manager.load_extension(ext)
280 280 except:
281 281 self.log.warn("Error in loading extension: %s" % ext +
282 282 "\nCheck your config files in %s" % self.profile_dir.location
283 283 )
284 284 self.shell.showtraceback()
285 285 except:
286 286 self.log.warn("Unknown error in loading extensions:")
287 287 self.shell.showtraceback()
288 288
289 289 def init_code(self):
290 290 """run the pre-flight code, specified via exec_lines"""
291 291 self._run_startup_files()
292 292 self._run_exec_lines()
293 293 self._run_exec_files()
294 294
295 295 # Hide variables defined here from %who etc.
296 296 if self.hide_initial_ns:
297 297 self.shell.user_ns_hidden.update(self.shell.user_ns)
298 298
299 299 # command-line execution (ipython -i script.py, ipython -m module)
300 300 # should *not* be excluded from %whos
301 301 self._run_cmd_line_code()
302 302 self._run_module()
303 303
304 304 # flush output, so itwon't be attached to the first cell
305 305 sys.stdout.flush()
306 306 sys.stderr.flush()
307 307
308 308 def _run_exec_lines(self):
309 309 """Run lines of code in IPythonApp.exec_lines in the user's namespace."""
310 310 if not self.exec_lines:
311 311 return
312 312 try:
313 313 self.log.debug("Running code from IPythonApp.exec_lines...")
314 314 for line in self.exec_lines:
315 315 try:
316 316 self.log.info("Running code in user namespace: %s" %
317 317 line)
318 318 self.shell.run_cell(line, store_history=False)
319 319 except:
320 320 self.log.warn("Error in executing line in user "
321 321 "namespace: %s" % line)
322 322 self.shell.showtraceback()
323 323 except:
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:
331 331 self.log.warn("File not found: %r"%fname)
332 332 return
333 333 # Make sure that the running script gets a proper sys.argv as if it
334 334 # were run from a system shell.
335 335 save_argv = sys.argv
336 336 sys.argv = [full_filename] + self.extra_args[1:]
337 337 # protect sys.argv from potential unicode strings on Python 2:
338 338 if not py3compat.PY3:
339 339 sys.argv = [ py3compat.cast_bytes(a) for a in sys.argv ]
340 340 try:
341 341 if os.path.isfile(full_filename):
342 342 self.log.info("Running file in user namespace: %s" %
343 343 full_filename)
344 344 # Ensure that __file__ is always defined to match Python
345 345 # behavior.
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
357 359 def _run_startup_files(self):
358 360 """Run files from profile startup directory"""
359 361 startup_dir = self.profile_dir.startup_dir
360 362 startup_files = []
361 363
362 364 if self.exec_PYTHONSTARTUP and os.environ.get('PYTHONSTARTUP', False) and \
363 365 not (self.file_to_run or self.code_to_run or self.module_to_run):
364 366 python_startup = os.environ['PYTHONSTARTUP']
365 367 self.log.debug("Running PYTHONSTARTUP file %s...", python_startup)
366 368 try:
367 369 self._exec_file(python_startup)
368 370 except:
369 371 self.log.warn("Unknown error in handling PYTHONSTARTUP file %s:", python_startup)
370 372 self.shell.showtraceback()
371 373 finally:
372 374 # Many PYTHONSTARTUP files set up the readline completions,
373 375 # but this is often at odds with IPython's own completions.
374 376 # Do not allow PYTHONSTARTUP to set up readline.
375 377 if self.shell.has_readline:
376 378 self.shell.set_readline_completer()
377 379
378 380 startup_files += glob.glob(os.path.join(startup_dir, '*.py'))
379 381 startup_files += glob.glob(os.path.join(startup_dir, '*.ipy'))
380 382 if not startup_files:
381 383 return
382 384
383 385 self.log.debug("Running startup files from %s...", startup_dir)
384 386 try:
385 387 for fname in sorted(startup_files):
386 388 self._exec_file(fname)
387 389 except:
388 390 self.log.warn("Unknown error in handling startup files:")
389 391 self.shell.showtraceback()
390 392
391 393 def _run_exec_files(self):
392 394 """Run files from IPythonApp.exec_files"""
393 395 if not self.exec_files:
394 396 return
395 397
396 398 self.log.debug("Running files in IPythonApp.exec_files...")
397 399 try:
398 400 for fname in self.exec_files:
399 401 self._exec_file(fname)
400 402 except:
401 403 self.log.warn("Unknown error in handling IPythonApp.exec_files:")
402 404 self.shell.showtraceback()
403 405
404 406 def _run_cmd_line_code(self):
405 407 """Run code or file specified at the command-line"""
406 408 if self.code_to_run:
407 409 line = self.code_to_run
408 410 try:
409 411 self.log.info("Running code given at command line (c=): %s" %
410 412 line)
411 413 self.shell.run_cell(line, store_history=False)
412 414 except:
413 415 self.log.warn("Error in executing line in user namespace: %s" %
414 416 line)
415 417 self.shell.showtraceback()
416 418
417 419 # Like Python itself, ignore the second if the first of these is present
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)
425 427 self.shell.showtraceback()
426 428
427 429 def _run_module(self):
428 430 """Run module specified at the command-line."""
429 431 if self.module_to_run:
430 432 # Make sure that the module gets a proper sys.argv as if it were
431 433 # run using `python -m`.
432 434 save_argv = sys.argv
433 435 sys.argv = [sys.executable] + self.extra_args
434 436 try:
435 437 self.shell.safe_run_module(self.module_to_run,
436 438 self.shell.user_ns)
437 439 finally:
438 440 sys.argv = save_argv
@@ -1,49 +1,64 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Tests for shellapp module.
3 3
4 4 Authors
5 5 -------
6 6 * Bradley Froehle
7 7 """
8 8 #-----------------------------------------------------------------------------
9 9 # Copyright (C) 2012 The IPython Development Team
10 10 #
11 11 # Distributed under the terms of the BSD License. The full license is in
12 12 # the file COPYING, distributed as part of this software.
13 13 #-----------------------------------------------------------------------------
14 14
15 15 #-----------------------------------------------------------------------------
16 16 # Imports
17 17 #-----------------------------------------------------------------------------
18 18 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."""
25 30
26 31 def test_py_script_file_attribute(self):
27 32 """Test that `__file__` is set when running `ipython file.py`"""
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):
38 40 """Test that `__file__` is set when running `ipython file.ipy`"""
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()'])
@@ -1,467 +1,470 b''
1 1 """Generic testing tools.
2 2
3 3 Authors
4 4 -------
5 5 - Fernando Perez <Fernando.Perez@berkeley.edu>
6 6 """
7 7
8 8 from __future__ import absolute_import
9 9
10 10 #-----------------------------------------------------------------------------
11 11 # Copyright (C) 2009 The IPython Development Team
12 12 #
13 13 # Distributed under the terms of the BSD License. The full license is in
14 14 # the file COPYING, distributed as part of this software.
15 15 #-----------------------------------------------------------------------------
16 16
17 17 #-----------------------------------------------------------------------------
18 18 # Imports
19 19 #-----------------------------------------------------------------------------
20 20
21 21 import os
22 22 import re
23 23 import sys
24 24 import tempfile
25 25
26 26 from contextlib import contextmanager
27 27 from io import StringIO
28 28 from subprocess import Popen, PIPE
29 29
30 30 try:
31 31 # These tools are used by parts of the runtime, so we make the nose
32 32 # dependency optional at this point. Nose is a hard dependency to run the
33 33 # test suite, but NOT to use ipython itself.
34 34 import nose.tools as nt
35 35 has_nose = True
36 36 except ImportError:
37 37 has_nose = False
38 38
39 39 from IPython.config.loader import Config
40 40 from IPython.utils.process import get_output_error_code
41 41 from IPython.utils.text import list_strings
42 42 from IPython.utils.io import temp_pyfile, Tee
43 43 from IPython.utils import py3compat
44 44 from IPython.utils.encoding import DEFAULT_ENCODING
45 45
46 46 from . import decorators as dec
47 47 from . import skipdoctest
48 48
49 49 #-----------------------------------------------------------------------------
50 50 # Functions and classes
51 51 #-----------------------------------------------------------------------------
52 52
53 53 # The docstring for full_path doctests differently on win32 (different path
54 54 # separator) so just skip the doctest there. The example remains informative.
55 55 doctest_deco = skipdoctest.skip_doctest if sys.platform == 'win32' else dec.null_deco
56 56
57 57 @doctest_deco
58 58 def full_path(startPath,files):
59 59 """Make full paths for all the listed files, based on startPath.
60 60
61 61 Only the base part of startPath is kept, since this routine is typically
62 62 used with a script's ``__file__`` variable as startPath. The base of startPath
63 63 is then prepended to all the listed files, forming the output list.
64 64
65 65 Parameters
66 66 ----------
67 67 startPath : string
68 68 Initial path to use as the base for the results. This path is split
69 69 using os.path.split() and only its first component is kept.
70 70
71 71 files : string or list
72 72 One or more files.
73 73
74 74 Examples
75 75 --------
76 76
77 77 >>> full_path('/foo/bar.py',['a.txt','b.txt'])
78 78 ['/foo/a.txt', '/foo/b.txt']
79 79
80 80 >>> full_path('/foo',['a.txt','b.txt'])
81 81 ['/a.txt', '/b.txt']
82 82
83 83 If a single file is given, the output is still a list::
84 84
85 85 >>> full_path('/foo','a.txt')
86 86 ['/a.txt']
87 87 """
88 88
89 89 files = list_strings(files)
90 90 base = os.path.split(startPath)[0]
91 91 return [ os.path.join(base,f) for f in files ]
92 92
93 93
94 94 def parse_test_output(txt):
95 95 """Parse the output of a test run and return errors, failures.
96 96
97 97 Parameters
98 98 ----------
99 99 txt : str
100 100 Text output of a test run, assumed to contain a line of one of the
101 101 following forms::
102 102
103 103 'FAILED (errors=1)'
104 104 'FAILED (failures=1)'
105 105 'FAILED (errors=1, failures=1)'
106 106
107 107 Returns
108 108 -------
109 109 nerr, nfail
110 110 number of errors and failures.
111 111 """
112 112
113 113 err_m = re.search(r'^FAILED \(errors=(\d+)\)', txt, re.MULTILINE)
114 114 if err_m:
115 115 nerr = int(err_m.group(1))
116 116 nfail = 0
117 117 return nerr, nfail
118 118
119 119 fail_m = re.search(r'^FAILED \(failures=(\d+)\)', txt, re.MULTILINE)
120 120 if fail_m:
121 121 nerr = 0
122 122 nfail = int(fail_m.group(1))
123 123 return nerr, nfail
124 124
125 125 both_m = re.search(r'^FAILED \(errors=(\d+), failures=(\d+)\)', txt,
126 126 re.MULTILINE)
127 127 if both_m:
128 128 nerr = int(both_m.group(1))
129 129 nfail = int(both_m.group(2))
130 130 return nerr, nfail
131 131
132 132 # If the input didn't match any of these forms, assume no error/failures
133 133 return 0, 0
134 134
135 135
136 136 # So nose doesn't think this is a test
137 137 parse_test_output.__test__ = False
138 138
139 139
140 140 def default_argv():
141 141 """Return a valid default argv for creating testing instances of ipython"""
142 142
143 143 return ['--quick', # so no config file is loaded
144 144 # Other defaults to minimize side effects on stdout
145 145 '--colors=NoColor', '--no-term-title','--no-banner',
146 146 '--autocall=0']
147 147
148 148
149 149 def default_config():
150 150 """Return a config object with good defaults for testing."""
151 151 config = Config()
152 152 config.TerminalInteractiveShell.colors = 'NoColor'
153 153 config.TerminalTerminalInteractiveShell.term_title = False,
154 154 config.TerminalInteractiveShell.autocall = 0
155 155 f = tempfile.NamedTemporaryFile(suffix=u'test_hist.sqlite', delete=False)
156 156 config.HistoryManager.hist_file = f.name
157 157 f.close()
158 158 config.HistoryManager.db_cache_size = 10000
159 159 return config
160 160
161 161
162 162 def get_ipython_cmd(as_string=False):
163 163 """
164 164 Return appropriate IPython command line name. By default, this will return
165 165 a list that can be used with subprocess.Popen, for example, but passing
166 166 `as_string=True` allows for returning the IPython command as a string.
167 167
168 168 Parameters
169 169 ----------
170 170 as_string: bool
171 171 Flag to allow to return the command as a string.
172 172 """
173 173 ipython_cmd = [sys.executable, "-m", "IPython"]
174 174
175 175 if as_string:
176 176 ipython_cmd = " ".join(ipython_cmd)
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
184 184 as possible.
185 185
186 186 Note that this starts IPython in a subprocess!
187 187
188 188 Parameters
189 189 ----------
190 190 fname : str
191 191 Name of file to be executed (should have .py or .ipy extension).
192 192
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.
199 202 """
200 203 if options is None: options = []
201 204
202 205 # For these subprocess calls, eliminate all prompt printing so we only see
203 206 # output from script execution
204 207 prompt_opts = [ '--PromptManager.in_template=""',
205 208 '--PromptManager.in2_template=""',
206 209 '--PromptManager.out_template=""'
207 210 ]
208 211 cmdargs = default_argv() + prompt_opts + options
209 212
210 213 test_dir = os.path.dirname(__file__)
211 214
212 215 ipython_cmd = get_ipython_cmd()
213 216 # Absolute path for filename
214 217 full_fname = os.path.join(test_dir, fname)
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
223 226 if out:
224 227 out = re.sub(r'\x1b\[[^h]+h', '', out)
225 228 return out, err
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.
233 236
234 237 Note that this starts IPython in a subprocess!
235 238
236 239 Parameters
237 240 ----------
238 241 fname : str
239 242 Name of the file to be executed (should have .py or .ipy extension).
240 243
241 244 expected_out : str
242 245 Expected stdout of the process.
243 246
244 247 expected_err : optional, str
245 248 Expected stderr of the process.
246 249
247 250 options : optional, list
248 251 Extra command-line flags to be passed to IPython.
249 252
250 253 Returns
251 254 -------
252 255 None
253 256 """
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
261 264 # more informative than simply having an empty stdout.
262 265 if err:
263 266 if expected_err:
264 267 nt.assert_equal("\n".join(err.strip().splitlines()), "\n".join(expected_err.strip().splitlines()))
265 268 else:
266 269 raise ValueError('Running file %r produced error: %r' %
267 270 (fname, err))
268 271 # If no errors or output on stderr was expected, match stdout
269 272 nt.assert_equal("\n".join(out.strip().splitlines()), "\n".join(expected_out.strip().splitlines()))
270 273
271 274
272 275 class TempFileMixin(object):
273 276 """Utility class to create temporary Python/IPython files.
274 277
275 278 Meant as a mixin class for test cases."""
276 279
277 280 def mktmp(self, src, ext='.py'):
278 281 """Make a valid python temp file."""
279 282 fname, f = temp_pyfile(src, ext)
280 283 self.tmpfile = f
281 284 self.fname = fname
282 285
283 286 def tearDown(self):
284 287 if hasattr(self, 'tmpfile'):
285 288 # If the tmpfile wasn't made because of skipped tests, like in
286 289 # win32, there's nothing to cleanup.
287 290 self.tmpfile.close()
288 291 try:
289 292 os.unlink(self.fname)
290 293 except:
291 294 # On Windows, even though we close the file, we still can't
292 295 # delete it. I have no clue why
293 296 pass
294 297
295 298 pair_fail_msg = ("Testing {0}\n\n"
296 299 "In:\n"
297 300 " {1!r}\n"
298 301 "Expected:\n"
299 302 " {2!r}\n"
300 303 "Got:\n"
301 304 " {3!r}\n")
302 305 def check_pairs(func, pairs):
303 306 """Utility function for the common case of checking a function with a
304 307 sequence of input/output pairs.
305 308
306 309 Parameters
307 310 ----------
308 311 func : callable
309 312 The function to be tested. Should accept a single argument.
310 313 pairs : iterable
311 314 A list of (input, expected_output) tuples.
312 315
313 316 Returns
314 317 -------
315 318 None. Raises an AssertionError if any output does not match the expected
316 319 value.
317 320 """
318 321 name = getattr(func, "func_name", getattr(func, "__name__", "<unknown>"))
319 322 for inp, expected in pairs:
320 323 out = func(inp)
321 324 assert out == expected, pair_fail_msg.format(name, inp, expected, out)
322 325
323 326
324 327 if py3compat.PY3:
325 328 MyStringIO = StringIO
326 329 else:
327 330 # In Python 2, stdout/stderr can have either bytes or unicode written to them,
328 331 # so we need a class that can handle both.
329 332 class MyStringIO(StringIO):
330 333 def write(self, s):
331 334 s = py3compat.cast_unicode(s, encoding=DEFAULT_ENCODING)
332 335 super(MyStringIO, self).write(s)
333 336
334 337 _re_type = type(re.compile(r''))
335 338
336 339 notprinted_msg = """Did not find {0!r} in printed output (on {1}):
337 340 -------
338 341 {2!s}
339 342 -------
340 343 """
341 344
342 345 class AssertPrints(object):
343 346 """Context manager for testing that code prints certain text.
344 347
345 348 Examples
346 349 --------
347 350 >>> with AssertPrints("abc", suppress=False):
348 351 ... print("abcd")
349 352 ... print("def")
350 353 ...
351 354 abcd
352 355 def
353 356 """
354 357 def __init__(self, s, channel='stdout', suppress=True):
355 358 self.s = s
356 359 if isinstance(self.s, (py3compat.string_types, _re_type)):
357 360 self.s = [self.s]
358 361 self.channel = channel
359 362 self.suppress = suppress
360 363
361 364 def __enter__(self):
362 365 self.orig_stream = getattr(sys, self.channel)
363 366 self.buffer = MyStringIO()
364 367 self.tee = Tee(self.buffer, channel=self.channel)
365 368 setattr(sys, self.channel, self.buffer if self.suppress else self.tee)
366 369
367 370 def __exit__(self, etype, value, traceback):
368 371 try:
369 372 if value is not None:
370 373 # If an error was raised, don't check anything else
371 374 return False
372 375 self.tee.flush()
373 376 setattr(sys, self.channel, self.orig_stream)
374 377 printed = self.buffer.getvalue()
375 378 for s in self.s:
376 379 if isinstance(s, _re_type):
377 380 assert s.search(printed), notprinted_msg.format(s.pattern, self.channel, printed)
378 381 else:
379 382 assert s in printed, notprinted_msg.format(s, self.channel, printed)
380 383 return False
381 384 finally:
382 385 self.tee.close()
383 386
384 387 printed_msg = """Found {0!r} in printed output (on {1}):
385 388 -------
386 389 {2!s}
387 390 -------
388 391 """
389 392
390 393 class AssertNotPrints(AssertPrints):
391 394 """Context manager for checking that certain output *isn't* produced.
392 395
393 396 Counterpart of AssertPrints"""
394 397 def __exit__(self, etype, value, traceback):
395 398 try:
396 399 if value is not None:
397 400 # If an error was raised, don't check anything else
398 401 self.tee.close()
399 402 return False
400 403 self.tee.flush()
401 404 setattr(sys, self.channel, self.orig_stream)
402 405 printed = self.buffer.getvalue()
403 406 for s in self.s:
404 407 if isinstance(s, _re_type):
405 408 assert not s.search(printed),printed_msg.format(
406 409 s.pattern, self.channel, printed)
407 410 else:
408 411 assert s not in printed, printed_msg.format(
409 412 s, self.channel, printed)
410 413 return False
411 414 finally:
412 415 self.tee.close()
413 416
414 417 @contextmanager
415 418 def mute_warn():
416 419 from IPython.utils import warn
417 420 save_warn = warn.warn
418 421 warn.warn = lambda *a, **kw: None
419 422 try:
420 423 yield
421 424 finally:
422 425 warn.warn = save_warn
423 426
424 427 @contextmanager
425 428 def make_tempfile(name):
426 429 """ Create an empty, named, temporary file for the duration of the context.
427 430 """
428 431 f = open(name, 'w')
429 432 f.close()
430 433 try:
431 434 yield
432 435 finally:
433 436 os.unlink(name)
434 437
435 438
436 439 @contextmanager
437 440 def monkeypatch(obj, name, attr):
438 441 """
439 442 Context manager to replace attribute named `name` in `obj` with `attr`.
440 443 """
441 444 orig = getattr(obj, name)
442 445 setattr(obj, name, attr)
443 446 yield
444 447 setattr(obj, name, orig)
445 448
446 449
447 450 def help_output_test(subcommand=''):
448 451 """test that `ipython [subcommand] -h` works"""
449 452 cmd = get_ipython_cmd() + [subcommand, '-h']
450 453 out, err, rc = get_output_error_code(cmd)
451 454 nt.assert_equal(rc, 0, err)
452 455 nt.assert_not_in("Traceback", err)
453 456 nt.assert_in("Options", out)
454 457 nt.assert_in("--help-all", out)
455 458 return out, err
456 459
457 460
458 461 def help_all_output_test(subcommand=''):
459 462 """test that `ipython [subcommand] --help-all` works"""
460 463 cmd = get_ipython_cmd() + [subcommand, '--help-all']
461 464 out, err, rc = get_output_error_code(cmd)
462 465 nt.assert_equal(rc, 0, err)
463 466 nt.assert_not_in("Traceback", err)
464 467 nt.assert_in("Options", out)
465 468 nt.assert_in("Class parameters", out)
466 469 return out, err
467 470
@@ -1,247 +1,255 b''
1 1 # coding: utf-8
2 2 """Compatibility tricks for Python 3. Mainly to do with unicode."""
3 3 import functools
4 4 import os
5 5 import sys
6 6 import re
7 7 import types
8 8
9 9 from .encoding import DEFAULT_ENCODING
10 10
11 11 def no_code(x, encoding=None):
12 12 return x
13 13
14 14 def decode(s, encoding=None):
15 15 encoding = encoding or DEFAULT_ENCODING
16 16 return s.decode(encoding, "replace")
17 17
18 18 def encode(u, encoding=None):
19 19 encoding = encoding or DEFAULT_ENCODING
20 20 return u.encode(encoding, "replace")
21 21
22 22
23 23 def cast_unicode(s, encoding=None):
24 24 if isinstance(s, bytes):
25 25 return decode(s, encoding)
26 26 return s
27 27
28 28 def cast_bytes(s, encoding=None):
29 29 if not isinstance(s, bytes):
30 30 return encode(s, encoding)
31 31 return s
32 32
33 33 def _modify_str_or_docstring(str_change_func):
34 34 @functools.wraps(str_change_func)
35 35 def wrapper(func_or_str):
36 36 if isinstance(func_or_str, string_types):
37 37 func = None
38 38 doc = func_or_str
39 39 else:
40 40 func = func_or_str
41 41 doc = func.__doc__
42 42
43 43 doc = str_change_func(doc)
44 44
45 45 if func:
46 46 func.__doc__ = doc
47 47 return func
48 48 return doc
49 49 return wrapper
50 50
51 51 def safe_unicode(e):
52 52 """unicode(e) with various fallbacks. Used for exceptions, which may not be
53 53 safe to call unicode() on.
54 54 """
55 55 try:
56 56 return unicode_type(e)
57 57 except UnicodeError:
58 58 pass
59 59
60 60 try:
61 61 return str_to_unicode(str(e))
62 62 except UnicodeError:
63 63 pass
64 64
65 65 try:
66 66 return str_to_unicode(repr(e))
67 67 except UnicodeError:
68 68 pass
69 69
70 70 return u'Unrecoverably corrupt evalue'
71 71
72 72 if sys.version_info[0] >= 3:
73 73 PY3 = True
74 74
75 75 # keep reference to builtin_mod because the kernel overrides that value
76 76 # to forward requests to a frontend.
77 77 def input(prompt=''):
78 78 return builtin_mod.input(prompt)
79 79
80 80 builtin_mod_name = "builtins"
81 81 import builtins as builtin_mod
82 82
83 83 str_to_unicode = no_code
84 84 unicode_to_str = no_code
85 85 str_to_bytes = encode
86 86 bytes_to_str = decode
87 87 cast_bytes_py2 = no_code
88 88 cast_unicode_py2 = no_code
89 89
90 90 string_types = (str,)
91 91 unicode_type = str
92 92
93 93 def isidentifier(s, dotted=False):
94 94 if dotted:
95 95 return all(isidentifier(a) for a in s.split("."))
96 96 return s.isidentifier()
97 97
98 98 xrange = range
99 99 def iteritems(d): return iter(d.items())
100 100 def itervalues(d): return iter(d.values())
101 101 getcwd = os.getcwd
102 102
103 103 MethodType = types.MethodType
104
105 def execfile(fname, glob, loc=None):
104
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)
112 113 def _print_statement_sub(match):
113 114 expr = match.groups('expr')
114 115 return "print(%s)" % expr
115 116
116 117 @_modify_str_or_docstring
117 118 def doctest_refactor_print(doc):
118 119 """Refactor 'print x' statements in a doctest to print(x) style. 2to3
119 120 unfortunately doesn't pick up on our doctests.
120 121
121 122 Can accept a string or a function, so it can be used as a decorator."""
122 123 return _print_statement_re.sub(_print_statement_sub, doc)
123 124
124 125 # Abstract u'abc' syntax:
125 126 @_modify_str_or_docstring
126 127 def u_format(s):
127 128 """"{u}'abc'" --> "'abc'" (Python 3)
128 129
129 130 Accepts a string or a function, so it can be used as a decorator."""
130 131 return s.format(u='')
131 132
132 133 def get_closure(f):
133 134 """Get a function's closure attribute"""
134 135 return f.__closure__
135 136
136 137 else:
137 138 PY3 = False
138 139
139 140 # keep reference to builtin_mod because the kernel overrides that value
140 141 # to forward requests to a frontend.
141 142 def input(prompt=''):
142 143 return builtin_mod.raw_input(prompt)
143 144
144 145 builtin_mod_name = "__builtin__"
145 146 import __builtin__ as builtin_mod
146 147
147 148 str_to_unicode = decode
148 149 unicode_to_str = encode
149 150 str_to_bytes = no_code
150 151 bytes_to_str = no_code
151 152 cast_bytes_py2 = cast_bytes
152 153 cast_unicode_py2 = cast_unicode
153 154
154 155 string_types = (str, unicode)
155 156 unicode_type = unicode
156 157
157 158 import re
158 159 _name_re = re.compile(r"[a-zA-Z_][a-zA-Z0-9_]*$")
159 160 def isidentifier(s, dotted=False):
160 161 if dotted:
161 162 return all(isidentifier(a) for a in s.split("."))
162 163 return bool(_name_re.match(s))
163 164
164 165 xrange = xrange
165 166 def iteritems(d): return d.iteritems()
166 167 def itervalues(d): return d.itervalues()
167 168 getcwd = os.getcwdu
168 169
169 170 def MethodType(func, instance):
170 171 return types.MethodType(func, instance, type(instance))
171 172
172 173 def doctest_refactor_print(func_or_str):
173 174 return func_or_str
174 175
175 176 def get_closure(f):
176 177 """Get a function's closure attribute"""
177 178 return f.func_closure
178 179
179 180 # Abstract u'abc' syntax:
180 181 @_modify_str_or_docstring
181 182 def u_format(s):
182 183 """"{u}'abc'" --> "u'abc'" (Python 2)
183 184
184 185 Accepts a string or a function, so it can be used as a decorator."""
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,
192 193 # but we still support 2.6). See issue 1027.
193 194 scripttext = builtin_mod.open(fname).read().rstrip() + '\n'
194 195 # compile converts unicode filename to str assuming
195 196 # ascii. Let's do the conversion before calling compile
196 197 if isinstance(fname, unicode):
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
207 builtin_mod.execfile(filename, *where)
210 where = [ns for ns in [glob, loc] if ns is not None]
211 if compiler is None:
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):
211 219 """Python 3 compatible function annotation for Python 2."""
212 220 if not kwargs:
213 221 raise ValueError('annotations must be provided as keyword arguments')
214 222 def dec(f):
215 223 if hasattr(f, '__annotations__'):
216 224 for k, v in kwargs.items():
217 225 f.__annotations__[k] = v
218 226 else:
219 227 f.__annotations__ = kwargs
220 228 return f
221 229 return dec
222 230
223 231
224 232 # Parts below taken from six:
225 233 # Copyright (c) 2010-2013 Benjamin Peterson
226 234 #
227 235 # Permission is hereby granted, free of charge, to any person obtaining a copy
228 236 # of this software and associated documentation files (the "Software"), to deal
229 237 # in the Software without restriction, including without limitation the rights
230 238 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
231 239 # copies of the Software, and to permit persons to whom the Software is
232 240 # furnished to do so, subject to the following conditions:
233 241 #
234 242 # The above copyright notice and this permission notice shall be included in all
235 243 # copies or substantial portions of the Software.
236 244 #
237 245 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
238 246 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
239 247 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
240 248 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
241 249 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
242 250 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
243 251 # SOFTWARE.
244 252
245 253 def with_metaclass(meta, *bases):
246 254 """Create a base class with a metaclass."""
247 255 return meta("_NewBase", bases, {})
General Comments 0
You need to be logged in to leave comments. Login now