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