##// END OF EJS Templates
Merge pull request #4469 from takluyver/py3-getcwdu...
Min RK -
r13456:5bf4949f merge
parent child Browse files
Show More

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

@@ -1,381 +1,382 b''
1 1 # encoding: utf-8
2 2 """
3 3 An application for IPython.
4 4
5 5 All top-level applications should use the classes in this module for
6 6 handling configuration and creating configurables.
7 7
8 8 The job of an :class:`Application` is to create the master configuration
9 9 object and then create the configurable objects, passing the config to them.
10 10
11 11 Authors:
12 12
13 13 * Brian Granger
14 14 * Fernando Perez
15 15 * Min RK
16 16
17 17 """
18 18
19 19 #-----------------------------------------------------------------------------
20 20 # Copyright (C) 2008 The IPython Development Team
21 21 #
22 22 # Distributed under the terms of the BSD License. The full license is in
23 23 # the file COPYING, distributed as part of this software.
24 24 #-----------------------------------------------------------------------------
25 25
26 26 #-----------------------------------------------------------------------------
27 27 # Imports
28 28 #-----------------------------------------------------------------------------
29 29
30 30 import atexit
31 31 import errno
32 32 import glob
33 33 import logging
34 34 import os
35 35 import shutil
36 36 import sys
37 37
38 38 from IPython.config.application import Application, catch_config_error
39 39 from IPython.config.loader import ConfigFileNotFound
40 40 from IPython.core import release, crashhandler
41 41 from IPython.core.profiledir import ProfileDir, ProfileDirError
42 42 from IPython.utils.path import get_ipython_dir, get_ipython_package_dir
43 from IPython.utils import py3compat
43 44 from IPython.utils.traitlets import List, Unicode, Type, Bool, Dict, Set, Instance
44 45
45 46 #-----------------------------------------------------------------------------
46 47 # Classes and functions
47 48 #-----------------------------------------------------------------------------
48 49
49 50
50 51 #-----------------------------------------------------------------------------
51 52 # Base Application Class
52 53 #-----------------------------------------------------------------------------
53 54
54 55 # aliases and flags
55 56
56 57 base_aliases = {
57 58 'profile-dir' : 'ProfileDir.location',
58 59 'profile' : 'BaseIPythonApplication.profile',
59 60 'ipython-dir' : 'BaseIPythonApplication.ipython_dir',
60 61 'log-level' : 'Application.log_level',
61 62 'config' : 'BaseIPythonApplication.extra_config_file',
62 63 }
63 64
64 65 base_flags = dict(
65 66 debug = ({'Application' : {'log_level' : logging.DEBUG}},
66 67 "set log level to logging.DEBUG (maximize logging output)"),
67 68 quiet = ({'Application' : {'log_level' : logging.CRITICAL}},
68 69 "set log level to logging.CRITICAL (minimize logging output)"),
69 70 init = ({'BaseIPythonApplication' : {
70 71 'copy_config_files' : True,
71 72 'auto_create' : True}
72 73 }, """Initialize profile with default config files. This is equivalent
73 74 to running `ipython profile create <profile>` prior to startup.
74 75 """)
75 76 )
76 77
77 78
78 79 class BaseIPythonApplication(Application):
79 80
80 81 name = Unicode(u'ipython')
81 82 description = Unicode(u'IPython: an enhanced interactive Python shell.')
82 83 version = Unicode(release.version)
83 84
84 85 aliases = Dict(base_aliases)
85 86 flags = Dict(base_flags)
86 87 classes = List([ProfileDir])
87 88
88 89 # Track whether the config_file has changed,
89 90 # because some logic happens only if we aren't using the default.
90 91 config_file_specified = Set()
91 92
92 93 config_file_name = Unicode()
93 94 def _config_file_name_default(self):
94 95 return self.name.replace('-','_') + u'_config.py'
95 96 def _config_file_name_changed(self, name, old, new):
96 97 if new != old:
97 98 self.config_file_specified.add(new)
98 99
99 100 # The directory that contains IPython's builtin profiles.
100 101 builtin_profile_dir = Unicode(
101 102 os.path.join(get_ipython_package_dir(), u'config', u'profile', u'default')
102 103 )
103 104
104 105 config_file_paths = List(Unicode)
105 106 def _config_file_paths_default(self):
106 return [os.getcwdu()]
107 return [py3compat.getcwd()]
107 108
108 109 extra_config_file = Unicode(config=True,
109 110 help="""Path to an extra config file to load.
110 111
111 112 If specified, load this config file in addition to any other IPython config.
112 113 """)
113 114 def _extra_config_file_changed(self, name, old, new):
114 115 try:
115 116 self.config_files.remove(old)
116 117 except ValueError:
117 118 pass
118 119 self.config_file_specified.add(new)
119 120 self.config_files.append(new)
120 121
121 122 profile = Unicode(u'default', config=True,
122 123 help="""The IPython profile to use."""
123 124 )
124 125
125 126 def _profile_changed(self, name, old, new):
126 127 self.builtin_profile_dir = os.path.join(
127 128 get_ipython_package_dir(), u'config', u'profile', new
128 129 )
129 130
130 131 ipython_dir = Unicode(config=True,
131 132 help="""
132 133 The name of the IPython directory. This directory is used for logging
133 134 configuration (through profiles), history storage, etc. The default
134 135 is usually $HOME/.ipython. This options can also be specified through
135 136 the environment variable IPYTHONDIR.
136 137 """
137 138 )
138 139 def _ipython_dir_default(self):
139 140 d = get_ipython_dir()
140 141 self._ipython_dir_changed('ipython_dir', d, d)
141 142 return d
142 143
143 144 _in_init_profile_dir = False
144 145 profile_dir = Instance(ProfileDir)
145 146 def _profile_dir_default(self):
146 147 # avoid recursion
147 148 if self._in_init_profile_dir:
148 149 return
149 150 # profile_dir requested early, force initialization
150 151 self.init_profile_dir()
151 152 return self.profile_dir
152 153
153 154 overwrite = Bool(False, config=True,
154 155 help="""Whether to overwrite existing config files when copying""")
155 156 auto_create = Bool(False, config=True,
156 157 help="""Whether to create profile dir if it doesn't exist""")
157 158
158 159 config_files = List(Unicode)
159 160 def _config_files_default(self):
160 161 return [self.config_file_name]
161 162
162 163 copy_config_files = Bool(False, config=True,
163 164 help="""Whether to install the default config files into the profile dir.
164 165 If a new profile is being created, and IPython contains config files for that
165 166 profile, then they will be staged into the new directory. Otherwise,
166 167 default config files will be automatically generated.
167 168 """)
168 169
169 170 verbose_crash = Bool(False, config=True,
170 171 help="""Create a massive crash report when IPython encounters what may be an
171 172 internal error. The default is to append a short message to the
172 173 usual traceback""")
173 174
174 175 # The class to use as the crash handler.
175 176 crash_handler_class = Type(crashhandler.CrashHandler)
176 177
177 178 @catch_config_error
178 179 def __init__(self, **kwargs):
179 180 super(BaseIPythonApplication, self).__init__(**kwargs)
180 181 # ensure current working directory exists
181 182 try:
182 directory = os.getcwdu()
183 directory = py3compat.getcwd()
183 184 except:
184 185 # raise exception
185 186 self.log.error("Current working directory doesn't exist.")
186 187 raise
187 188
188 189 #-------------------------------------------------------------------------
189 190 # Various stages of Application creation
190 191 #-------------------------------------------------------------------------
191 192
192 193 def init_crash_handler(self):
193 194 """Create a crash handler, typically setting sys.excepthook to it."""
194 195 self.crash_handler = self.crash_handler_class(self)
195 196 sys.excepthook = self.excepthook
196 197 def unset_crashhandler():
197 198 sys.excepthook = sys.__excepthook__
198 199 atexit.register(unset_crashhandler)
199 200
200 201 def excepthook(self, etype, evalue, tb):
201 202 """this is sys.excepthook after init_crashhandler
202 203
203 204 set self.verbose_crash=True to use our full crashhandler, instead of
204 205 a regular traceback with a short message (crash_handler_lite)
205 206 """
206 207
207 208 if self.verbose_crash:
208 209 return self.crash_handler(etype, evalue, tb)
209 210 else:
210 211 return crashhandler.crash_handler_lite(etype, evalue, tb)
211 212
212 213 def _ipython_dir_changed(self, name, old, new):
213 214 if old in sys.path:
214 215 sys.path.remove(old)
215 216 sys.path.append(os.path.abspath(new))
216 217 if not os.path.isdir(new):
217 218 os.makedirs(new, mode=0o777)
218 219 readme = os.path.join(new, 'README')
219 220 readme_src = os.path.join(get_ipython_package_dir(), u'config', u'profile', 'README')
220 221 if not os.path.exists(readme) and os.path.exists(readme_src):
221 222 shutil.copy(readme_src, readme)
222 223 for d in ('extensions', 'nbextensions'):
223 224 path = os.path.join(new, d)
224 225 if not os.path.exists(path):
225 226 try:
226 227 os.mkdir(path)
227 228 except OSError as e:
228 229 if e.errno != errno.EEXIST:
229 230 self.log.error("couldn't create path %s: %s", path, e)
230 231 self.log.debug("IPYTHONDIR set to: %s" % new)
231 232
232 233 def load_config_file(self, suppress_errors=True):
233 234 """Load the config file.
234 235
235 236 By default, errors in loading config are handled, and a warning
236 237 printed on screen. For testing, the suppress_errors option is set
237 238 to False, so errors will make tests fail.
238 239 """
239 240 self.log.debug("Searching path %s for config files", self.config_file_paths)
240 241 base_config = 'ipython_config.py'
241 242 self.log.debug("Attempting to load config file: %s" %
242 243 base_config)
243 244 try:
244 245 Application.load_config_file(
245 246 self,
246 247 base_config,
247 248 path=self.config_file_paths
248 249 )
249 250 except ConfigFileNotFound:
250 251 # ignore errors loading parent
251 252 self.log.debug("Config file %s not found", base_config)
252 253 pass
253 254
254 255 for config_file_name in self.config_files:
255 256 if not config_file_name or config_file_name == base_config:
256 257 continue
257 258 self.log.debug("Attempting to load config file: %s" %
258 259 self.config_file_name)
259 260 try:
260 261 Application.load_config_file(
261 262 self,
262 263 config_file_name,
263 264 path=self.config_file_paths
264 265 )
265 266 except ConfigFileNotFound:
266 267 # Only warn if the default config file was NOT being used.
267 268 if config_file_name in self.config_file_specified:
268 269 msg = self.log.warn
269 270 else:
270 271 msg = self.log.debug
271 272 msg("Config file not found, skipping: %s", config_file_name)
272 273 except:
273 274 # For testing purposes.
274 275 if not suppress_errors:
275 276 raise
276 277 self.log.warn("Error loading config file: %s" %
277 278 self.config_file_name, exc_info=True)
278 279
279 280 def init_profile_dir(self):
280 281 """initialize the profile dir"""
281 282 self._in_init_profile_dir = True
282 283 if self.profile_dir is not None:
283 284 # already ran
284 285 return
285 286 if 'ProfileDir.location' not in self.config:
286 287 # location not specified, find by profile name
287 288 try:
288 289 p = ProfileDir.find_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
289 290 except ProfileDirError:
290 291 # not found, maybe create it (always create default profile)
291 292 if self.auto_create or self.profile == 'default':
292 293 try:
293 294 p = ProfileDir.create_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
294 295 except ProfileDirError:
295 296 self.log.fatal("Could not create profile: %r"%self.profile)
296 297 self.exit(1)
297 298 else:
298 299 self.log.info("Created profile dir: %r"%p.location)
299 300 else:
300 301 self.log.fatal("Profile %r not found."%self.profile)
301 302 self.exit(1)
302 303 else:
303 304 self.log.info("Using existing profile dir: %r"%p.location)
304 305 else:
305 306 location = self.config.ProfileDir.location
306 307 # location is fully specified
307 308 try:
308 309 p = ProfileDir.find_profile_dir(location, self.config)
309 310 except ProfileDirError:
310 311 # not found, maybe create it
311 312 if self.auto_create:
312 313 try:
313 314 p = ProfileDir.create_profile_dir(location, self.config)
314 315 except ProfileDirError:
315 316 self.log.fatal("Could not create profile directory: %r"%location)
316 317 self.exit(1)
317 318 else:
318 319 self.log.info("Creating new profile dir: %r"%location)
319 320 else:
320 321 self.log.fatal("Profile directory %r not found."%location)
321 322 self.exit(1)
322 323 else:
323 324 self.log.info("Using existing profile dir: %r"%location)
324 325
325 326 self.profile_dir = p
326 327 self.config_file_paths.append(p.location)
327 328 self._in_init_profile_dir = False
328 329
329 330 def init_config_files(self):
330 331 """[optionally] copy default config files into profile dir."""
331 332 # copy config files
332 333 path = self.builtin_profile_dir
333 334 if self.copy_config_files:
334 335 src = self.profile
335 336
336 337 cfg = self.config_file_name
337 338 if path and os.path.exists(os.path.join(path, cfg)):
338 339 self.log.warn("Staging %r from %s into %r [overwrite=%s]"%(
339 340 cfg, src, self.profile_dir.location, self.overwrite)
340 341 )
341 342 self.profile_dir.copy_config_file(cfg, path=path, overwrite=self.overwrite)
342 343 else:
343 344 self.stage_default_config_file()
344 345 else:
345 346 # Still stage *bundled* config files, but not generated ones
346 347 # This is necessary for `ipython profile=sympy` to load the profile
347 348 # on the first go
348 349 files = glob.glob(os.path.join(path, '*.py'))
349 350 for fullpath in files:
350 351 cfg = os.path.basename(fullpath)
351 352 if self.profile_dir.copy_config_file(cfg, path=path, overwrite=False):
352 353 # file was copied
353 354 self.log.warn("Staging bundled %s from %s into %r"%(
354 355 cfg, self.profile, self.profile_dir.location)
355 356 )
356 357
357 358
358 359 def stage_default_config_file(self):
359 360 """auto generate default config file, and stage it into the profile."""
360 361 s = self.generate_config_file()
361 362 fname = os.path.join(self.profile_dir.location, self.config_file_name)
362 363 if self.overwrite or not os.path.exists(fname):
363 364 self.log.warn("Generating default config file: %r"%(fname))
364 365 with open(fname, 'w') as f:
365 366 f.write(s)
366 367
367 368 @catch_config_error
368 369 def initialize(self, argv=None):
369 370 # don't hook up crash handler before parsing command-line
370 371 self.parse_command_line(argv)
371 372 self.init_crash_handler()
372 373 if self.subapp is not None:
373 374 # stop here if subapp is taking over
374 375 return
375 376 cl_config = self.config
376 377 self.init_profile_dir()
377 378 self.init_config_files()
378 379 self.load_config_file()
379 380 # enforce cl-opts override configfile opts:
380 381 self.update_config(cl_config)
381 382
@@ -1,216 +1,216 b''
1 1 # encoding: utf-8
2 2 """sys.excepthook for IPython itself, leaves a detailed report on disk.
3 3
4 4 Authors:
5 5
6 6 * Fernando Perez
7 7 * Brian E. Granger
8 8 """
9 9
10 10 #-----------------------------------------------------------------------------
11 11 # Copyright (C) 2001-2007 Fernando Perez. <fperez@colorado.edu>
12 12 # Copyright (C) 2008-2011 The IPython Development Team
13 13 #
14 14 # Distributed under the terms of the BSD License. The full license is in
15 15 # the file COPYING, distributed as part of this software.
16 16 #-----------------------------------------------------------------------------
17 17
18 18 #-----------------------------------------------------------------------------
19 19 # Imports
20 20 #-----------------------------------------------------------------------------
21 21 from __future__ import print_function
22 22
23 23 import os
24 24 import sys
25 25 import traceback
26 26 from pprint import pformat
27 27
28 28 from IPython.core import ultratb
29 29 from IPython.core.release import author_email
30 30 from IPython.utils.sysinfo import sys_info
31 from IPython.utils.py3compat import input
31 from IPython.utils.py3compat import input, getcwd
32 32
33 33 #-----------------------------------------------------------------------------
34 34 # Code
35 35 #-----------------------------------------------------------------------------
36 36
37 37 # Template for the user message.
38 38 _default_message_template = """\
39 39 Oops, {app_name} crashed. We do our best to make it stable, but...
40 40
41 41 A crash report was automatically generated with the following information:
42 42 - A verbatim copy of the crash traceback.
43 43 - A copy of your input history during this session.
44 44 - Data on your current {app_name} configuration.
45 45
46 46 It was left in the file named:
47 47 \t'{crash_report_fname}'
48 48 If you can email this file to the developers, the information in it will help
49 49 them in understanding and correcting the problem.
50 50
51 51 You can mail it to: {contact_name} at {contact_email}
52 52 with the subject '{app_name} Crash Report'.
53 53
54 54 If you want to do it now, the following command will work (under Unix):
55 55 mail -s '{app_name} Crash Report' {contact_email} < {crash_report_fname}
56 56
57 57 To ensure accurate tracking of this issue, please file a report about it at:
58 58 {bug_tracker}
59 59 """
60 60
61 61 _lite_message_template = """
62 62 If you suspect this is an IPython bug, please report it at:
63 63 https://github.com/ipython/ipython/issues
64 64 or send an email to the mailing list at {email}
65 65
66 66 You can print a more detailed traceback right now with "%tb", or use "%debug"
67 67 to interactively debug it.
68 68
69 69 Extra-detailed tracebacks for bug-reporting purposes can be enabled via:
70 70 {config}Application.verbose_crash=True
71 71 """
72 72
73 73
74 74 class CrashHandler(object):
75 75 """Customizable crash handlers for IPython applications.
76 76
77 77 Instances of this class provide a :meth:`__call__` method which can be
78 78 used as a ``sys.excepthook``. The :meth:`__call__` signature is::
79 79
80 80 def __call__(self, etype, evalue, etb)
81 81 """
82 82
83 83 message_template = _default_message_template
84 84 section_sep = '\n\n'+'*'*75+'\n\n'
85 85
86 86 def __init__(self, app, contact_name=None, contact_email=None,
87 87 bug_tracker=None, show_crash_traceback=True, call_pdb=False):
88 88 """Create a new crash handler
89 89
90 90 Parameters
91 91 ----------
92 92 app : Application
93 93 A running :class:`Application` instance, which will be queried at
94 94 crash time for internal information.
95 95
96 96 contact_name : str
97 97 A string with the name of the person to contact.
98 98
99 99 contact_email : str
100 100 A string with the email address of the contact.
101 101
102 102 bug_tracker : str
103 103 A string with the URL for your project's bug tracker.
104 104
105 105 show_crash_traceback : bool
106 106 If false, don't print the crash traceback on stderr, only generate
107 107 the on-disk report
108 108
109 109 Non-argument instance attributes:
110 110
111 111 These instances contain some non-argument attributes which allow for
112 112 further customization of the crash handler's behavior. Please see the
113 113 source for further details.
114 114 """
115 115 self.crash_report_fname = "Crash_report_%s.txt" % app.name
116 116 self.app = app
117 117 self.call_pdb = call_pdb
118 118 #self.call_pdb = True # dbg
119 119 self.show_crash_traceback = show_crash_traceback
120 120 self.info = dict(app_name = app.name,
121 121 contact_name = contact_name,
122 122 contact_email = contact_email,
123 123 bug_tracker = bug_tracker,
124 124 crash_report_fname = self.crash_report_fname)
125 125
126 126
127 127 def __call__(self, etype, evalue, etb):
128 128 """Handle an exception, call for compatible with sys.excepthook"""
129 129
130 130 # do not allow the crash handler to be called twice without reinstalling it
131 131 # this prevents unlikely errors in the crash handling from entering an
132 132 # infinite loop.
133 133 sys.excepthook = sys.__excepthook__
134 134
135 135 # Report tracebacks shouldn't use color in general (safer for users)
136 136 color_scheme = 'NoColor'
137 137
138 138 # Use this ONLY for developer debugging (keep commented out for release)
139 139 #color_scheme = 'Linux' # dbg
140 140 try:
141 141 rptdir = self.app.ipython_dir
142 142 except:
143 rptdir = os.getcwdu()
143 rptdir = getcwd()
144 144 if rptdir is None or not os.path.isdir(rptdir):
145 rptdir = os.getcwdu()
145 rptdir = getcwd()
146 146 report_name = os.path.join(rptdir,self.crash_report_fname)
147 147 # write the report filename into the instance dict so it can get
148 148 # properly expanded out in the user message template
149 149 self.crash_report_fname = report_name
150 150 self.info['crash_report_fname'] = report_name
151 151 TBhandler = ultratb.VerboseTB(
152 152 color_scheme=color_scheme,
153 153 long_header=1,
154 154 call_pdb=self.call_pdb,
155 155 )
156 156 if self.call_pdb:
157 157 TBhandler(etype,evalue,etb)
158 158 return
159 159 else:
160 160 traceback = TBhandler.text(etype,evalue,etb,context=31)
161 161
162 162 # print traceback to screen
163 163 if self.show_crash_traceback:
164 164 print(traceback, file=sys.stderr)
165 165
166 166 # and generate a complete report on disk
167 167 try:
168 168 report = open(report_name,'w')
169 169 except:
170 170 print('Could not create crash report on disk.', file=sys.stderr)
171 171 return
172 172
173 173 # Inform user on stderr of what happened
174 174 print('\n'+'*'*70+'\n', file=sys.stderr)
175 175 print(self.message_template.format(**self.info), file=sys.stderr)
176 176
177 177 # Construct report on disk
178 178 report.write(self.make_report(traceback))
179 179 report.close()
180 180 input("Hit <Enter> to quit (your terminal may close):")
181 181
182 182 def make_report(self,traceback):
183 183 """Return a string containing a crash report."""
184 184
185 185 sec_sep = self.section_sep
186 186
187 187 report = ['*'*75+'\n\n'+'IPython post-mortem report\n\n']
188 188 rpt_add = report.append
189 189 rpt_add(sys_info())
190 190
191 191 try:
192 192 config = pformat(self.app.config)
193 193 rpt_add(sec_sep)
194 194 rpt_add('Application name: %s\n\n' % self.app_name)
195 195 rpt_add('Current user configuration structure:\n\n')
196 196 rpt_add(config)
197 197 except:
198 198 pass
199 199 rpt_add(sec_sep+'Crash traceback:\n\n' + traceback)
200 200
201 201 return ''.join(report)
202 202
203 203
204 204 def crash_handler_lite(etype, evalue, tb):
205 205 """a light excepthook, adding a small message to the usual traceback"""
206 206 traceback.print_exception(etype, evalue, tb)
207 207
208 208 from IPython.core.interactiveshell import InteractiveShell
209 209 if InteractiveShell.initialized():
210 210 # we are in a Shell environment, give %magic example
211 211 config = "%config "
212 212 else:
213 213 # we are not in a shell, show generic config
214 214 config = "c."
215 215 print(_lite_message_template.format(email=author_email, config=config), file=sys.stderr)
216 216
@@ -1,807 +1,808 b''
1 1 """ History related magics and functionality """
2 2 #-----------------------------------------------------------------------------
3 3 # Copyright (C) 2010-2011 The IPython Development Team.
4 4 #
5 5 # Distributed under the terms of the BSD License.
6 6 #
7 7 # The full license is in the file COPYING.txt, distributed with this software.
8 8 #-----------------------------------------------------------------------------
9 9
10 10 #-----------------------------------------------------------------------------
11 11 # Imports
12 12 #-----------------------------------------------------------------------------
13 13 from __future__ import print_function
14 14
15 15 # Stdlib imports
16 16 import atexit
17 17 import datetime
18 18 import os
19 19 import re
20 20 try:
21 21 import sqlite3
22 22 except ImportError:
23 23 try:
24 24 from pysqlite2 import dbapi2 as sqlite3
25 25 except ImportError:
26 26 sqlite3 = None
27 27 import threading
28 28
29 29 # Our own packages
30 30 from IPython.config.configurable import Configurable
31 31 from IPython.external.decorator import decorator
32 32 from IPython.utils.path import locate_profile
33 from IPython.utils import py3compat
33 34 from IPython.utils.traitlets import (
34 35 Any, Bool, Dict, Instance, Integer, List, Unicode, TraitError,
35 36 )
36 37 from IPython.utils.warn import warn
37 38
38 39 #-----------------------------------------------------------------------------
39 40 # Classes and functions
40 41 #-----------------------------------------------------------------------------
41 42
42 43 class DummyDB(object):
43 44 """Dummy DB that will act as a black hole for history.
44 45
45 46 Only used in the absence of sqlite"""
46 47 def execute(*args, **kwargs):
47 48 return []
48 49
49 50 def commit(self, *args, **kwargs):
50 51 pass
51 52
52 53 def __enter__(self, *args, **kwargs):
53 54 pass
54 55
55 56 def __exit__(self, *args, **kwargs):
56 57 pass
57 58
58 59
59 60 @decorator
60 61 def needs_sqlite(f, self, *a, **kw):
61 62 """return an empty list in the absence of sqlite"""
62 63 if sqlite3 is None or not self.enabled:
63 64 return []
64 65 else:
65 66 return f(self, *a, **kw)
66 67
67 68
68 69 if sqlite3 is not None:
69 70 DatabaseError = sqlite3.DatabaseError
70 71 else:
71 72 class DatabaseError(Exception):
72 73 "Dummy exception when sqlite could not be imported. Should never occur."
73 74
74 75 @decorator
75 76 def catch_corrupt_db(f, self, *a, **kw):
76 77 """A decorator which wraps HistoryAccessor method calls to catch errors from
77 78 a corrupt SQLite database, move the old database out of the way, and create
78 79 a new one.
79 80 """
80 81 try:
81 82 return f(self, *a, **kw)
82 83 except DatabaseError:
83 84 if os.path.isfile(self.hist_file):
84 85 # Try to move the file out of the way
85 86 base,ext = os.path.splitext(self.hist_file)
86 87 newpath = base + '-corrupt' + ext
87 88 os.rename(self.hist_file, newpath)
88 89 self.init_db()
89 90 print("ERROR! History file wasn't a valid SQLite database.",
90 91 "It was moved to %s" % newpath, "and a new file created.")
91 92 return []
92 93
93 94 else:
94 95 # The hist_file is probably :memory: or something else.
95 96 raise
96 97
97 98
98 99
99 100 class HistoryAccessor(Configurable):
100 101 """Access the history database without adding to it.
101 102
102 103 This is intended for use by standalone history tools. IPython shells use
103 104 HistoryManager, below, which is a subclass of this."""
104 105
105 106 # String holding the path to the history file
106 107 hist_file = Unicode(config=True,
107 108 help="""Path to file to use for SQLite history database.
108 109
109 110 By default, IPython will put the history database in the IPython
110 111 profile directory. If you would rather share one history among
111 112 profiles, you can set this value in each, so that they are consistent.
112 113
113 114 Due to an issue with fcntl, SQLite is known to misbehave on some NFS
114 115 mounts. If you see IPython hanging, try setting this to something on a
115 116 local disk, e.g::
116 117
117 118 ipython --HistoryManager.hist_file=/tmp/ipython_hist.sqlite
118 119
119 120 """)
120 121
121 122 enabled = Bool(True, config=True,
122 123 help="""enable the SQLite history
123 124
124 125 set enabled=False to disable the SQLite history,
125 126 in which case there will be no stored history, no SQLite connection,
126 127 and no background saving thread. This may be necessary in some
127 128 threaded environments where IPython is embedded.
128 129 """
129 130 )
130 131
131 132 connection_options = Dict(config=True,
132 133 help="""Options for configuring the SQLite connection
133 134
134 135 These options are passed as keyword args to sqlite3.connect
135 136 when establishing database conenctions.
136 137 """
137 138 )
138 139
139 140 # The SQLite database
140 141 db = Any()
141 142 def _db_changed(self, name, old, new):
142 143 """validate the db, since it can be an Instance of two different types"""
143 144 connection_types = (DummyDB,)
144 145 if sqlite3 is not None:
145 146 connection_types = (DummyDB, sqlite3.Connection)
146 147 if not isinstance(new, connection_types):
147 148 msg = "%s.db must be sqlite3 Connection or DummyDB, not %r" % \
148 149 (self.__class__.__name__, new)
149 150 raise TraitError(msg)
150 151
151 152 def __init__(self, profile='default', hist_file=u'', **traits):
152 153 """Create a new history accessor.
153 154
154 155 Parameters
155 156 ----------
156 157 profile : str
157 158 The name of the profile from which to open history.
158 159 hist_file : str
159 160 Path to an SQLite history database stored by IPython. If specified,
160 161 hist_file overrides profile.
161 162 config :
162 163 Config object. hist_file can also be set through this.
163 164 """
164 165 # We need a pointer back to the shell for various tasks.
165 166 super(HistoryAccessor, self).__init__(**traits)
166 167 # defer setting hist_file from kwarg until after init,
167 168 # otherwise the default kwarg value would clobber any value
168 169 # set by config
169 170 if hist_file:
170 171 self.hist_file = hist_file
171 172
172 173 if self.hist_file == u'':
173 174 # No one has set the hist_file, yet.
174 175 self.hist_file = self._get_hist_file_name(profile)
175 176
176 177 if sqlite3 is None and self.enabled:
177 178 warn("IPython History requires SQLite, your history will not be saved")
178 179 self.enabled = False
179 180
180 181 self.init_db()
181 182
182 183 def _get_hist_file_name(self, profile='default'):
183 184 """Find the history file for the given profile name.
184 185
185 186 This is overridden by the HistoryManager subclass, to use the shell's
186 187 active profile.
187 188
188 189 Parameters
189 190 ----------
190 191 profile : str
191 192 The name of a profile which has a history file.
192 193 """
193 194 return os.path.join(locate_profile(profile), 'history.sqlite')
194 195
195 196 @catch_corrupt_db
196 197 def init_db(self):
197 198 """Connect to the database, and create tables if necessary."""
198 199 if not self.enabled:
199 200 self.db = DummyDB()
200 201 return
201 202
202 203 # use detect_types so that timestamps return datetime objects
203 204 kwargs = dict(detect_types=sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES)
204 205 kwargs.update(self.connection_options)
205 206 self.db = sqlite3.connect(self.hist_file, **kwargs)
206 207 self.db.execute("""CREATE TABLE IF NOT EXISTS sessions (session integer
207 208 primary key autoincrement, start timestamp,
208 209 end timestamp, num_cmds integer, remark text)""")
209 210 self.db.execute("""CREATE TABLE IF NOT EXISTS history
210 211 (session integer, line integer, source text, source_raw text,
211 212 PRIMARY KEY (session, line))""")
212 213 # Output history is optional, but ensure the table's there so it can be
213 214 # enabled later.
214 215 self.db.execute("""CREATE TABLE IF NOT EXISTS output_history
215 216 (session integer, line integer, output text,
216 217 PRIMARY KEY (session, line))""")
217 218 self.db.commit()
218 219
219 220 def writeout_cache(self):
220 221 """Overridden by HistoryManager to dump the cache before certain
221 222 database lookups."""
222 223 pass
223 224
224 225 ## -------------------------------
225 226 ## Methods for retrieving history:
226 227 ## -------------------------------
227 228 def _run_sql(self, sql, params, raw=True, output=False):
228 229 """Prepares and runs an SQL query for the history database.
229 230
230 231 Parameters
231 232 ----------
232 233 sql : str
233 234 Any filtering expressions to go after SELECT ... FROM ...
234 235 params : tuple
235 236 Parameters passed to the SQL query (to replace "?")
236 237 raw, output : bool
237 238 See :meth:`get_range`
238 239
239 240 Returns
240 241 -------
241 242 Tuples as :meth:`get_range`
242 243 """
243 244 toget = 'source_raw' if raw else 'source'
244 245 sqlfrom = "history"
245 246 if output:
246 247 sqlfrom = "history LEFT JOIN output_history USING (session, line)"
247 248 toget = "history.%s, output_history.output" % toget
248 249 cur = self.db.execute("SELECT session, line, %s FROM %s " %\
249 250 (toget, sqlfrom) + sql, params)
250 251 if output: # Regroup into 3-tuples, and parse JSON
251 252 return ((ses, lin, (inp, out)) for ses, lin, inp, out in cur)
252 253 return cur
253 254
254 255 @needs_sqlite
255 256 @catch_corrupt_db
256 257 def get_session_info(self, session=0):
257 258 """get info about a session
258 259
259 260 Parameters
260 261 ----------
261 262
262 263 session : int
263 264 Session number to retrieve. The current session is 0, and negative
264 265 numbers count back from current session, so -1 is previous session.
265 266
266 267 Returns
267 268 -------
268 269
269 270 (session_id [int], start [datetime], end [datetime], num_cmds [int],
270 271 remark [unicode])
271 272
272 273 Sessions that are running or did not exit cleanly will have `end=None`
273 274 and `num_cmds=None`.
274 275
275 276 """
276 277
277 278 if session <= 0:
278 279 session += self.session_number
279 280
280 281 query = "SELECT * from sessions where session == ?"
281 282 return self.db.execute(query, (session,)).fetchone()
282 283
283 284 @catch_corrupt_db
284 285 def get_tail(self, n=10, raw=True, output=False, include_latest=False):
285 286 """Get the last n lines from the history database.
286 287
287 288 Parameters
288 289 ----------
289 290 n : int
290 291 The number of lines to get
291 292 raw, output : bool
292 293 See :meth:`get_range`
293 294 include_latest : bool
294 295 If False (default), n+1 lines are fetched, and the latest one
295 296 is discarded. This is intended to be used where the function
296 297 is called by a user command, which it should not return.
297 298
298 299 Returns
299 300 -------
300 301 Tuples as :meth:`get_range`
301 302 """
302 303 self.writeout_cache()
303 304 if not include_latest:
304 305 n += 1
305 306 cur = self._run_sql("ORDER BY session DESC, line DESC LIMIT ?",
306 307 (n,), raw=raw, output=output)
307 308 if not include_latest:
308 309 return reversed(list(cur)[1:])
309 310 return reversed(list(cur))
310 311
311 312 @catch_corrupt_db
312 313 def search(self, pattern="*", raw=True, search_raw=True,
313 314 output=False, n=None, unique=False):
314 315 """Search the database using unix glob-style matching (wildcards
315 316 * and ?).
316 317
317 318 Parameters
318 319 ----------
319 320 pattern : str
320 321 The wildcarded pattern to match when searching
321 322 search_raw : bool
322 323 If True, search the raw input, otherwise, the parsed input
323 324 raw, output : bool
324 325 See :meth:`get_range`
325 326 n : None or int
326 327 If an integer is given, it defines the limit of
327 328 returned entries.
328 329 unique : bool
329 330 When it is true, return only unique entries.
330 331
331 332 Returns
332 333 -------
333 334 Tuples as :meth:`get_range`
334 335 """
335 336 tosearch = "source_raw" if search_raw else "source"
336 337 if output:
337 338 tosearch = "history." + tosearch
338 339 self.writeout_cache()
339 340 sqlform = "WHERE %s GLOB ?" % tosearch
340 341 params = (pattern,)
341 342 if unique:
342 343 sqlform += ' GROUP BY {0}'.format(tosearch)
343 344 if n is not None:
344 345 sqlform += " ORDER BY session DESC, line DESC LIMIT ?"
345 346 params += (n,)
346 347 elif unique:
347 348 sqlform += " ORDER BY session, line"
348 349 cur = self._run_sql(sqlform, params, raw=raw, output=output)
349 350 if n is not None:
350 351 return reversed(list(cur))
351 352 return cur
352 353
353 354 @catch_corrupt_db
354 355 def get_range(self, session, start=1, stop=None, raw=True,output=False):
355 356 """Retrieve input by session.
356 357
357 358 Parameters
358 359 ----------
359 360 session : int
360 361 Session number to retrieve.
361 362 start : int
362 363 First line to retrieve.
363 364 stop : int
364 365 End of line range (excluded from output itself). If None, retrieve
365 366 to the end of the session.
366 367 raw : bool
367 368 If True, return untranslated input
368 369 output : bool
369 370 If True, attempt to include output. This will be 'real' Python
370 371 objects for the current session, or text reprs from previous
371 372 sessions if db_log_output was enabled at the time. Where no output
372 373 is found, None is used.
373 374
374 375 Returns
375 376 -------
376 377 An iterator over the desired lines. Each line is a 3-tuple, either
377 378 (session, line, input) if output is False, or
378 379 (session, line, (input, output)) if output is True.
379 380 """
380 381 if stop:
381 382 lineclause = "line >= ? AND line < ?"
382 383 params = (session, start, stop)
383 384 else:
384 385 lineclause = "line>=?"
385 386 params = (session, start)
386 387
387 388 return self._run_sql("WHERE session==? AND %s" % lineclause,
388 389 params, raw=raw, output=output)
389 390
390 391 def get_range_by_str(self, rangestr, raw=True, output=False):
391 392 """Get lines of history from a string of ranges, as used by magic
392 393 commands %hist, %save, %macro, etc.
393 394
394 395 Parameters
395 396 ----------
396 397 rangestr : str
397 398 A string specifying ranges, e.g. "5 ~2/1-4". See
398 399 :func:`magic_history` for full details.
399 400 raw, output : bool
400 401 As :meth:`get_range`
401 402
402 403 Returns
403 404 -------
404 405 Tuples as :meth:`get_range`
405 406 """
406 407 for sess, s, e in extract_hist_ranges(rangestr):
407 408 for line in self.get_range(sess, s, e, raw=raw, output=output):
408 409 yield line
409 410
410 411
411 412 class HistoryManager(HistoryAccessor):
412 413 """A class to organize all history-related functionality in one place.
413 414 """
414 415 # Public interface
415 416
416 417 # An instance of the IPython shell we are attached to
417 418 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
418 419 # Lists to hold processed and raw history. These start with a blank entry
419 420 # so that we can index them starting from 1
420 421 input_hist_parsed = List([""])
421 422 input_hist_raw = List([""])
422 423 # A list of directories visited during session
423 424 dir_hist = List()
424 425 def _dir_hist_default(self):
425 426 try:
426 return [os.getcwdu()]
427 return [py3compat.getcwd()]
427 428 except OSError:
428 429 return []
429 430
430 431 # A dict of output history, keyed with ints from the shell's
431 432 # execution count.
432 433 output_hist = Dict()
433 434 # The text/plain repr of outputs.
434 435 output_hist_reprs = Dict()
435 436
436 437 # The number of the current session in the history database
437 438 session_number = Integer()
438 439 # Should we log output to the database? (default no)
439 440 db_log_output = Bool(False, config=True)
440 441 # Write to database every x commands (higher values save disk access & power)
441 442 # Values of 1 or less effectively disable caching.
442 443 db_cache_size = Integer(0, config=True)
443 444 # The input and output caches
444 445 db_input_cache = List()
445 446 db_output_cache = List()
446 447
447 448 # History saving in separate thread
448 449 save_thread = Instance('IPython.core.history.HistorySavingThread')
449 450 try: # Event is a function returning an instance of _Event...
450 451 save_flag = Instance(threading._Event)
451 452 except AttributeError: # ...until Python 3.3, when it's a class.
452 453 save_flag = Instance(threading.Event)
453 454
454 455 # Private interface
455 456 # Variables used to store the three last inputs from the user. On each new
456 457 # history update, we populate the user's namespace with these, shifted as
457 458 # necessary.
458 459 _i00 = Unicode(u'')
459 460 _i = Unicode(u'')
460 461 _ii = Unicode(u'')
461 462 _iii = Unicode(u'')
462 463
463 464 # A regex matching all forms of the exit command, so that we don't store
464 465 # them in the history (it's annoying to rewind the first entry and land on
465 466 # an exit call).
466 467 _exit_re = re.compile(r"(exit|quit)(\s*\(.*\))?$")
467 468
468 469 def __init__(self, shell=None, config=None, **traits):
469 470 """Create a new history manager associated with a shell instance.
470 471 """
471 472 # We need a pointer back to the shell for various tasks.
472 473 super(HistoryManager, self).__init__(shell=shell, config=config,
473 474 **traits)
474 475 self.save_flag = threading.Event()
475 476 self.db_input_cache_lock = threading.Lock()
476 477 self.db_output_cache_lock = threading.Lock()
477 478 if self.enabled and self.hist_file != ':memory:':
478 479 self.save_thread = HistorySavingThread(self)
479 480 self.save_thread.start()
480 481
481 482 self.new_session()
482 483
483 484 def _get_hist_file_name(self, profile=None):
484 485 """Get default history file name based on the Shell's profile.
485 486
486 487 The profile parameter is ignored, but must exist for compatibility with
487 488 the parent class."""
488 489 profile_dir = self.shell.profile_dir.location
489 490 return os.path.join(profile_dir, 'history.sqlite')
490 491
491 492 @needs_sqlite
492 493 def new_session(self, conn=None):
493 494 """Get a new session number."""
494 495 if conn is None:
495 496 conn = self.db
496 497
497 498 with conn:
498 499 cur = conn.execute("""INSERT INTO sessions VALUES (NULL, ?, NULL,
499 500 NULL, "") """, (datetime.datetime.now(),))
500 501 self.session_number = cur.lastrowid
501 502
502 503 def end_session(self):
503 504 """Close the database session, filling in the end time and line count."""
504 505 self.writeout_cache()
505 506 with self.db:
506 507 self.db.execute("""UPDATE sessions SET end=?, num_cmds=? WHERE
507 508 session==?""", (datetime.datetime.now(),
508 509 len(self.input_hist_parsed)-1, self.session_number))
509 510 self.session_number = 0
510 511
511 512 def name_session(self, name):
512 513 """Give the current session a name in the history database."""
513 514 with self.db:
514 515 self.db.execute("UPDATE sessions SET remark=? WHERE session==?",
515 516 (name, self.session_number))
516 517
517 518 def reset(self, new_session=True):
518 519 """Clear the session history, releasing all object references, and
519 520 optionally open a new session."""
520 521 self.output_hist.clear()
521 522 # The directory history can't be completely empty
522 self.dir_hist[:] = [os.getcwdu()]
523 self.dir_hist[:] = [py3compat.getcwd()]
523 524
524 525 if new_session:
525 526 if self.session_number:
526 527 self.end_session()
527 528 self.input_hist_parsed[:] = [""]
528 529 self.input_hist_raw[:] = [""]
529 530 self.new_session()
530 531
531 532 # ------------------------------
532 533 # Methods for retrieving history
533 534 # ------------------------------
534 535 def _get_range_session(self, start=1, stop=None, raw=True, output=False):
535 536 """Get input and output history from the current session. Called by
536 537 get_range, and takes similar parameters."""
537 538 input_hist = self.input_hist_raw if raw else self.input_hist_parsed
538 539
539 540 n = len(input_hist)
540 541 if start < 0:
541 542 start += n
542 543 if not stop or (stop > n):
543 544 stop = n
544 545 elif stop < 0:
545 546 stop += n
546 547
547 548 for i in range(start, stop):
548 549 if output:
549 550 line = (input_hist[i], self.output_hist_reprs.get(i))
550 551 else:
551 552 line = input_hist[i]
552 553 yield (0, i, line)
553 554
554 555 def get_range(self, session=0, start=1, stop=None, raw=True,output=False):
555 556 """Retrieve input by session.
556 557
557 558 Parameters
558 559 ----------
559 560 session : int
560 561 Session number to retrieve. The current session is 0, and negative
561 562 numbers count back from current session, so -1 is previous session.
562 563 start : int
563 564 First line to retrieve.
564 565 stop : int
565 566 End of line range (excluded from output itself). If None, retrieve
566 567 to the end of the session.
567 568 raw : bool
568 569 If True, return untranslated input
569 570 output : bool
570 571 If True, attempt to include output. This will be 'real' Python
571 572 objects for the current session, or text reprs from previous
572 573 sessions if db_log_output was enabled at the time. Where no output
573 574 is found, None is used.
574 575
575 576 Returns
576 577 -------
577 578 An iterator over the desired lines. Each line is a 3-tuple, either
578 579 (session, line, input) if output is False, or
579 580 (session, line, (input, output)) if output is True.
580 581 """
581 582 if session <= 0:
582 583 session += self.session_number
583 584 if session==self.session_number: # Current session
584 585 return self._get_range_session(start, stop, raw, output)
585 586 return super(HistoryManager, self).get_range(session, start, stop, raw,
586 587 output)
587 588
588 589 ## ----------------------------
589 590 ## Methods for storing history:
590 591 ## ----------------------------
591 592 def store_inputs(self, line_num, source, source_raw=None):
592 593 """Store source and raw input in history and create input cache
593 594 variables _i*.
594 595
595 596 Parameters
596 597 ----------
597 598 line_num : int
598 599 The prompt number of this input.
599 600
600 601 source : str
601 602 Python input.
602 603
603 604 source_raw : str, optional
604 605 If given, this is the raw input without any IPython transformations
605 606 applied to it. If not given, ``source`` is used.
606 607 """
607 608 if source_raw is None:
608 609 source_raw = source
609 610 source = source.rstrip('\n')
610 611 source_raw = source_raw.rstrip('\n')
611 612
612 613 # do not store exit/quit commands
613 614 if self._exit_re.match(source_raw.strip()):
614 615 return
615 616
616 617 self.input_hist_parsed.append(source)
617 618 self.input_hist_raw.append(source_raw)
618 619
619 620 with self.db_input_cache_lock:
620 621 self.db_input_cache.append((line_num, source, source_raw))
621 622 # Trigger to flush cache and write to DB.
622 623 if len(self.db_input_cache) >= self.db_cache_size:
623 624 self.save_flag.set()
624 625
625 626 # update the auto _i variables
626 627 self._iii = self._ii
627 628 self._ii = self._i
628 629 self._i = self._i00
629 630 self._i00 = source_raw
630 631
631 632 # hackish access to user namespace to create _i1,_i2... dynamically
632 633 new_i = '_i%s' % line_num
633 634 to_main = {'_i': self._i,
634 635 '_ii': self._ii,
635 636 '_iii': self._iii,
636 637 new_i : self._i00 }
637 638
638 639 if self.shell is not None:
639 640 self.shell.push(to_main, interactive=False)
640 641
641 642 def store_output(self, line_num):
642 643 """If database output logging is enabled, this saves all the
643 644 outputs from the indicated prompt number to the database. It's
644 645 called by run_cell after code has been executed.
645 646
646 647 Parameters
647 648 ----------
648 649 line_num : int
649 650 The line number from which to save outputs
650 651 """
651 652 if (not self.db_log_output) or (line_num not in self.output_hist_reprs):
652 653 return
653 654 output = self.output_hist_reprs[line_num]
654 655
655 656 with self.db_output_cache_lock:
656 657 self.db_output_cache.append((line_num, output))
657 658 if self.db_cache_size <= 1:
658 659 self.save_flag.set()
659 660
660 661 def _writeout_input_cache(self, conn):
661 662 with conn:
662 663 for line in self.db_input_cache:
663 664 conn.execute("INSERT INTO history VALUES (?, ?, ?, ?)",
664 665 (self.session_number,)+line)
665 666
666 667 def _writeout_output_cache(self, conn):
667 668 with conn:
668 669 for line in self.db_output_cache:
669 670 conn.execute("INSERT INTO output_history VALUES (?, ?, ?)",
670 671 (self.session_number,)+line)
671 672
672 673 @needs_sqlite
673 674 def writeout_cache(self, conn=None):
674 675 """Write any entries in the cache to the database."""
675 676 if conn is None:
676 677 conn = self.db
677 678
678 679 with self.db_input_cache_lock:
679 680 try:
680 681 self._writeout_input_cache(conn)
681 682 except sqlite3.IntegrityError:
682 683 self.new_session(conn)
683 684 print("ERROR! Session/line number was not unique in",
684 685 "database. History logging moved to new session",
685 686 self.session_number)
686 687 try:
687 688 # Try writing to the new session. If this fails, don't
688 689 # recurse
689 690 self._writeout_input_cache(conn)
690 691 except sqlite3.IntegrityError:
691 692 pass
692 693 finally:
693 694 self.db_input_cache = []
694 695
695 696 with self.db_output_cache_lock:
696 697 try:
697 698 self._writeout_output_cache(conn)
698 699 except sqlite3.IntegrityError:
699 700 print("!! Session/line number for output was not unique",
700 701 "in database. Output will not be stored.")
701 702 finally:
702 703 self.db_output_cache = []
703 704
704 705
705 706 class HistorySavingThread(threading.Thread):
706 707 """This thread takes care of writing history to the database, so that
707 708 the UI isn't held up while that happens.
708 709
709 710 It waits for the HistoryManager's save_flag to be set, then writes out
710 711 the history cache. The main thread is responsible for setting the flag when
711 712 the cache size reaches a defined threshold."""
712 713 daemon = True
713 714 stop_now = False
714 715 enabled = True
715 716 def __init__(self, history_manager):
716 717 super(HistorySavingThread, self).__init__(name="IPythonHistorySavingThread")
717 718 self.history_manager = history_manager
718 719 self.enabled = history_manager.enabled
719 720 atexit.register(self.stop)
720 721
721 722 @needs_sqlite
722 723 def run(self):
723 724 # We need a separate db connection per thread:
724 725 try:
725 726 self.db = sqlite3.connect(self.history_manager.hist_file,
726 727 **self.history_manager.connection_options
727 728 )
728 729 while True:
729 730 self.history_manager.save_flag.wait()
730 731 if self.stop_now:
731 732 return
732 733 self.history_manager.save_flag.clear()
733 734 self.history_manager.writeout_cache(self.db)
734 735 except Exception as e:
735 736 print(("The history saving thread hit an unexpected error (%s)."
736 737 "History will not be written to the database.") % repr(e))
737 738
738 739 def stop(self):
739 740 """This can be called from the main thread to safely stop this thread.
740 741
741 742 Note that it does not attempt to write out remaining history before
742 743 exiting. That should be done by calling the HistoryManager's
743 744 end_session method."""
744 745 self.stop_now = True
745 746 self.history_manager.save_flag.set()
746 747 self.join()
747 748
748 749
749 750 # To match, e.g. ~5/8-~2/3
750 751 range_re = re.compile(r"""
751 752 ((?P<startsess>~?\d+)/)?
752 753 (?P<start>\d+)?
753 754 ((?P<sep>[\-:])
754 755 ((?P<endsess>~?\d+)/)?
755 756 (?P<end>\d+))?
756 757 $""", re.VERBOSE)
757 758
758 759
759 760 def extract_hist_ranges(ranges_str):
760 761 """Turn a string of history ranges into 3-tuples of (session, start, stop).
761 762
762 763 Examples
763 764 --------
764 765 list(extract_input_ranges("~8/5-~7/4 2"))
765 766 [(-8, 5, None), (-7, 1, 4), (0, 2, 3)]
766 767 """
767 768 for range_str in ranges_str.split():
768 769 rmatch = range_re.match(range_str)
769 770 if not rmatch:
770 771 continue
771 772 start = rmatch.group("start")
772 773 if start:
773 774 start = int(start)
774 775 end = rmatch.group("end")
775 776 # If no end specified, get (a, a + 1)
776 777 end = int(end) if end else start + 1
777 778 else: # start not specified
778 779 if not rmatch.group('startsess'): # no startsess
779 780 continue
780 781 start = 1
781 782 end = None # provide the entire session hist
782 783
783 784 if rmatch.group("sep") == "-": # 1-3 == 1:4 --> [1, 2, 3]
784 785 end += 1
785 786 startsess = rmatch.group("startsess") or "0"
786 787 endsess = rmatch.group("endsess") or startsess
787 788 startsess = int(startsess.replace("~","-"))
788 789 endsess = int(endsess.replace("~","-"))
789 790 assert endsess >= startsess, "start session must be earlier than end session"
790 791
791 792 if endsess == startsess:
792 793 yield (startsess, start, end)
793 794 continue
794 795 # Multiple sessions in one range:
795 796 yield (startsess, start, None)
796 797 for sess in range(startsess+1, endsess):
797 798 yield (sess, 1, None)
798 799 yield (endsess, 1, end)
799 800
800 801
801 802 def _format_lineno(session, line):
802 803 """Helper function to format line numbers properly."""
803 804 if session == 0:
804 805 return str(line)
805 806 return "%s#%s" % (session, line)
806 807
807 808
@@ -1,3164 +1,3164 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Main IPython class."""
3 3
4 4 #-----------------------------------------------------------------------------
5 5 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de>
6 6 # Copyright (C) 2001-2007 Fernando Perez. <fperez@colorado.edu>
7 7 # Copyright (C) 2008-2011 The IPython Development Team
8 8 #
9 9 # Distributed under the terms of the BSD License. The full license is in
10 10 # the file COPYING, distributed as part of this software.
11 11 #-----------------------------------------------------------------------------
12 12
13 13 #-----------------------------------------------------------------------------
14 14 # Imports
15 15 #-----------------------------------------------------------------------------
16 16
17 17 from __future__ import absolute_import
18 18 from __future__ import print_function
19 19
20 20 import __future__
21 21 import abc
22 22 import ast
23 23 import atexit
24 24 import functools
25 25 import os
26 26 import re
27 27 import runpy
28 28 import sys
29 29 import tempfile
30 30 import types
31 31 import subprocess
32 32 from io import open as io_open
33 33
34 34 from IPython.config.configurable import SingletonConfigurable
35 35 from IPython.core import debugger, oinspect
36 36 from IPython.core import magic
37 37 from IPython.core import page
38 38 from IPython.core import prefilter
39 39 from IPython.core import shadowns
40 40 from IPython.core import ultratb
41 41 from IPython.core.alias import AliasManager, AliasError
42 42 from IPython.core.autocall import ExitAutocall
43 43 from IPython.core.builtin_trap import BuiltinTrap
44 44 from IPython.core.compilerop import CachingCompiler, check_linecache_ipython
45 45 from IPython.core.display_trap import DisplayTrap
46 46 from IPython.core.displayhook import DisplayHook
47 47 from IPython.core.displaypub import DisplayPublisher
48 48 from IPython.core.error import UsageError
49 49 from IPython.core.extensions import ExtensionManager
50 50 from IPython.core.formatters import DisplayFormatter
51 51 from IPython.core.history import HistoryManager
52 52 from IPython.core.inputsplitter import IPythonInputSplitter, ESC_MAGIC, ESC_MAGIC2
53 53 from IPython.core.logger import Logger
54 54 from IPython.core.macro import Macro
55 55 from IPython.core.payload import PayloadManager
56 56 from IPython.core.prefilter import PrefilterManager
57 57 from IPython.core.profiledir import ProfileDir
58 58 from IPython.core.prompts import PromptManager
59 59 from IPython.lib.latextools import LaTeXTool
60 60 from IPython.testing.skipdoctest import skip_doctest
61 61 from IPython.utils import PyColorize
62 62 from IPython.utils import io
63 63 from IPython.utils import py3compat
64 64 from IPython.utils import openpy
65 65 from IPython.utils.decorators import undoc
66 66 from IPython.utils.io import ask_yes_no
67 67 from IPython.utils.ipstruct import Struct
68 68 from IPython.utils.path import get_home_dir, get_ipython_dir, get_py_filename, unquote_filename
69 69 from IPython.utils.pickleshare import PickleShareDB
70 70 from IPython.utils.process import system, getoutput
71 71 from IPython.utils.py3compat import (builtin_mod, unicode_type, string_types,
72 72 with_metaclass, iteritems)
73 73 from IPython.utils.strdispatch import StrDispatch
74 74 from IPython.utils.syspathcontext import prepended_to_syspath
75 75 from IPython.utils.text import (format_screen, LSString, SList,
76 76 DollarFormatter)
77 77 from IPython.utils.traitlets import (Integer, CBool, CaselessStrEnum, Enum,
78 78 List, Unicode, Instance, Type)
79 79 from IPython.utils.warn import warn, error
80 80 import IPython.core.hooks
81 81
82 82 #-----------------------------------------------------------------------------
83 83 # Globals
84 84 #-----------------------------------------------------------------------------
85 85
86 86 # compiled regexps for autoindent management
87 87 dedent_re = re.compile(r'^\s+raise|^\s+return|^\s+pass')
88 88
89 89 #-----------------------------------------------------------------------------
90 90 # Utilities
91 91 #-----------------------------------------------------------------------------
92 92
93 93 @undoc
94 94 def softspace(file, newvalue):
95 95 """Copied from code.py, to remove the dependency"""
96 96
97 97 oldvalue = 0
98 98 try:
99 99 oldvalue = file.softspace
100 100 except AttributeError:
101 101 pass
102 102 try:
103 103 file.softspace = newvalue
104 104 except (AttributeError, TypeError):
105 105 # "attribute-less object" or "read-only attributes"
106 106 pass
107 107 return oldvalue
108 108
109 109 @undoc
110 110 def no_op(*a, **kw): pass
111 111
112 112 @undoc
113 113 class NoOpContext(object):
114 114 def __enter__(self): pass
115 115 def __exit__(self, type, value, traceback): pass
116 116 no_op_context = NoOpContext()
117 117
118 118 class SpaceInInput(Exception): pass
119 119
120 120 @undoc
121 121 class Bunch: pass
122 122
123 123
124 124 def get_default_colors():
125 125 if sys.platform=='darwin':
126 126 return "LightBG"
127 127 elif os.name=='nt':
128 128 return 'Linux'
129 129 else:
130 130 return 'Linux'
131 131
132 132
133 133 class SeparateUnicode(Unicode):
134 134 """A Unicode subclass to validate separate_in, separate_out, etc.
135 135
136 136 This is a Unicode based trait that converts '0'->'' and '\\n'->'\n'.
137 137 """
138 138
139 139 def validate(self, obj, value):
140 140 if value == '0': value = ''
141 141 value = value.replace('\\n','\n')
142 142 return super(SeparateUnicode, self).validate(obj, value)
143 143
144 144
145 145 class ReadlineNoRecord(object):
146 146 """Context manager to execute some code, then reload readline history
147 147 so that interactive input to the code doesn't appear when pressing up."""
148 148 def __init__(self, shell):
149 149 self.shell = shell
150 150 self._nested_level = 0
151 151
152 152 def __enter__(self):
153 153 if self._nested_level == 0:
154 154 try:
155 155 self.orig_length = self.current_length()
156 156 self.readline_tail = self.get_readline_tail()
157 157 except (AttributeError, IndexError): # Can fail with pyreadline
158 158 self.orig_length, self.readline_tail = 999999, []
159 159 self._nested_level += 1
160 160
161 161 def __exit__(self, type, value, traceback):
162 162 self._nested_level -= 1
163 163 if self._nested_level == 0:
164 164 # Try clipping the end if it's got longer
165 165 try:
166 166 e = self.current_length() - self.orig_length
167 167 if e > 0:
168 168 for _ in range(e):
169 169 self.shell.readline.remove_history_item(self.orig_length)
170 170
171 171 # If it still doesn't match, just reload readline history.
172 172 if self.current_length() != self.orig_length \
173 173 or self.get_readline_tail() != self.readline_tail:
174 174 self.shell.refill_readline_hist()
175 175 except (AttributeError, IndexError):
176 176 pass
177 177 # Returning False will cause exceptions to propagate
178 178 return False
179 179
180 180 def current_length(self):
181 181 return self.shell.readline.get_current_history_length()
182 182
183 183 def get_readline_tail(self, n=10):
184 184 """Get the last n items in readline history."""
185 185 end = self.shell.readline.get_current_history_length() + 1
186 186 start = max(end-n, 1)
187 187 ghi = self.shell.readline.get_history_item
188 188 return [ghi(x) for x in range(start, end)]
189 189
190 190
191 191 @undoc
192 192 class DummyMod(object):
193 193 """A dummy module used for IPython's interactive module when
194 194 a namespace must be assigned to the module's __dict__."""
195 195 pass
196 196
197 197 #-----------------------------------------------------------------------------
198 198 # Main IPython class
199 199 #-----------------------------------------------------------------------------
200 200
201 201 class InteractiveShell(SingletonConfigurable):
202 202 """An enhanced, interactive shell for Python."""
203 203
204 204 _instance = None
205 205
206 206 ast_transformers = List([], config=True, help=
207 207 """
208 208 A list of ast.NodeTransformer subclass instances, which will be applied
209 209 to user input before code is run.
210 210 """
211 211 )
212 212
213 213 autocall = Enum((0,1,2), default_value=0, config=True, help=
214 214 """
215 215 Make IPython automatically call any callable object even if you didn't
216 216 type explicit parentheses. For example, 'str 43' becomes 'str(43)'
217 217 automatically. The value can be '0' to disable the feature, '1' for
218 218 'smart' autocall, where it is not applied if there are no more
219 219 arguments on the line, and '2' for 'full' autocall, where all callable
220 220 objects are automatically called (even if no arguments are present).
221 221 """
222 222 )
223 223 # TODO: remove all autoindent logic and put into frontends.
224 224 # We can't do this yet because even runlines uses the autoindent.
225 225 autoindent = CBool(True, config=True, help=
226 226 """
227 227 Autoindent IPython code entered interactively.
228 228 """
229 229 )
230 230 automagic = CBool(True, config=True, help=
231 231 """
232 232 Enable magic commands to be called without the leading %.
233 233 """
234 234 )
235 235 cache_size = Integer(1000, config=True, help=
236 236 """
237 237 Set the size of the output cache. The default is 1000, you can
238 238 change it permanently in your config file. Setting it to 0 completely
239 239 disables the caching system, and the minimum value accepted is 20 (if
240 240 you provide a value less than 20, it is reset to 0 and a warning is
241 241 issued). This limit is defined because otherwise you'll spend more
242 242 time re-flushing a too small cache than working
243 243 """
244 244 )
245 245 color_info = CBool(True, config=True, help=
246 246 """
247 247 Use colors for displaying information about objects. Because this
248 248 information is passed through a pager (like 'less'), and some pagers
249 249 get confused with color codes, this capability can be turned off.
250 250 """
251 251 )
252 252 colors = CaselessStrEnum(('NoColor','LightBG','Linux'),
253 253 default_value=get_default_colors(), config=True,
254 254 help="Set the color scheme (NoColor, Linux, or LightBG)."
255 255 )
256 256 colors_force = CBool(False, help=
257 257 """
258 258 Force use of ANSI color codes, regardless of OS and readline
259 259 availability.
260 260 """
261 261 # FIXME: This is essentially a hack to allow ZMQShell to show colors
262 262 # without readline on Win32. When the ZMQ formatting system is
263 263 # refactored, this should be removed.
264 264 )
265 265 debug = CBool(False, config=True)
266 266 deep_reload = CBool(False, config=True, help=
267 267 """
268 268 Enable deep (recursive) reloading by default. IPython can use the
269 269 deep_reload module which reloads changes in modules recursively (it
270 270 replaces the reload() function, so you don't need to change anything to
271 271 use it). deep_reload() forces a full reload of modules whose code may
272 272 have changed, which the default reload() function does not. When
273 273 deep_reload is off, IPython will use the normal reload(), but
274 274 deep_reload will still be available as dreload().
275 275 """
276 276 )
277 277 disable_failing_post_execute = CBool(False, config=True,
278 278 help="Don't call post-execute functions that have failed in the past."
279 279 )
280 280 display_formatter = Instance(DisplayFormatter)
281 281 displayhook_class = Type(DisplayHook)
282 282 display_pub_class = Type(DisplayPublisher)
283 283 data_pub_class = None
284 284
285 285 exit_now = CBool(False)
286 286 exiter = Instance(ExitAutocall)
287 287 def _exiter_default(self):
288 288 return ExitAutocall(self)
289 289 # Monotonically increasing execution counter
290 290 execution_count = Integer(1)
291 291 filename = Unicode("<ipython console>")
292 292 ipython_dir= Unicode('', config=True) # Set to get_ipython_dir() in __init__
293 293
294 294 # Input splitter, to transform input line by line and detect when a block
295 295 # is ready to be executed.
296 296 input_splitter = Instance('IPython.core.inputsplitter.IPythonInputSplitter',
297 297 (), {'line_input_checker': True})
298 298
299 299 # This InputSplitter instance is used to transform completed cells before
300 300 # running them. It allows cell magics to contain blank lines.
301 301 input_transformer_manager = Instance('IPython.core.inputsplitter.IPythonInputSplitter',
302 302 (), {'line_input_checker': False})
303 303
304 304 logstart = CBool(False, config=True, help=
305 305 """
306 306 Start logging to the default log file.
307 307 """
308 308 )
309 309 logfile = Unicode('', config=True, help=
310 310 """
311 311 The name of the logfile to use.
312 312 """
313 313 )
314 314 logappend = Unicode('', config=True, help=
315 315 """
316 316 Start logging to the given file in append mode.
317 317 """
318 318 )
319 319 object_info_string_level = Enum((0,1,2), default_value=0,
320 320 config=True)
321 321 pdb = CBool(False, config=True, help=
322 322 """
323 323 Automatically call the pdb debugger after every exception.
324 324 """
325 325 )
326 326 multiline_history = CBool(sys.platform != 'win32', config=True,
327 327 help="Save multi-line entries as one entry in readline history"
328 328 )
329 329
330 330 # deprecated prompt traits:
331 331
332 332 prompt_in1 = Unicode('In [\\#]: ', config=True,
333 333 help="Deprecated, use PromptManager.in_template")
334 334 prompt_in2 = Unicode(' .\\D.: ', config=True,
335 335 help="Deprecated, use PromptManager.in2_template")
336 336 prompt_out = Unicode('Out[\\#]: ', config=True,
337 337 help="Deprecated, use PromptManager.out_template")
338 338 prompts_pad_left = CBool(True, config=True,
339 339 help="Deprecated, use PromptManager.justify")
340 340
341 341 def _prompt_trait_changed(self, name, old, new):
342 342 table = {
343 343 'prompt_in1' : 'in_template',
344 344 'prompt_in2' : 'in2_template',
345 345 'prompt_out' : 'out_template',
346 346 'prompts_pad_left' : 'justify',
347 347 }
348 348 warn("InteractiveShell.{name} is deprecated, use PromptManager.{newname}".format(
349 349 name=name, newname=table[name])
350 350 )
351 351 # protect against weird cases where self.config may not exist:
352 352 if self.config is not None:
353 353 # propagate to corresponding PromptManager trait
354 354 setattr(self.config.PromptManager, table[name], new)
355 355
356 356 _prompt_in1_changed = _prompt_trait_changed
357 357 _prompt_in2_changed = _prompt_trait_changed
358 358 _prompt_out_changed = _prompt_trait_changed
359 359 _prompt_pad_left_changed = _prompt_trait_changed
360 360
361 361 show_rewritten_input = CBool(True, config=True,
362 362 help="Show rewritten input, e.g. for autocall."
363 363 )
364 364
365 365 quiet = CBool(False, config=True)
366 366
367 367 history_length = Integer(10000, config=True)
368 368
369 369 # The readline stuff will eventually be moved to the terminal subclass
370 370 # but for now, we can't do that as readline is welded in everywhere.
371 371 readline_use = CBool(True, config=True)
372 372 readline_remove_delims = Unicode('-/~', config=True)
373 373 readline_delims = Unicode() # set by init_readline()
374 374 # don't use \M- bindings by default, because they
375 375 # conflict with 8-bit encodings. See gh-58,gh-88
376 376 readline_parse_and_bind = List([
377 377 'tab: complete',
378 378 '"\C-l": clear-screen',
379 379 'set show-all-if-ambiguous on',
380 380 '"\C-o": tab-insert',
381 381 '"\C-r": reverse-search-history',
382 382 '"\C-s": forward-search-history',
383 383 '"\C-p": history-search-backward',
384 384 '"\C-n": history-search-forward',
385 385 '"\e[A": history-search-backward',
386 386 '"\e[B": history-search-forward',
387 387 '"\C-k": kill-line',
388 388 '"\C-u": unix-line-discard',
389 389 ], allow_none=False, config=True)
390 390
391 391 ast_node_interactivity = Enum(['all', 'last', 'last_expr', 'none'],
392 392 default_value='last_expr', config=True,
393 393 help="""
394 394 'all', 'last', 'last_expr' or 'none', specifying which nodes should be
395 395 run interactively (displaying output from expressions).""")
396 396
397 397 # TODO: this part of prompt management should be moved to the frontends.
398 398 # Use custom TraitTypes that convert '0'->'' and '\\n'->'\n'
399 399 separate_in = SeparateUnicode('\n', config=True)
400 400 separate_out = SeparateUnicode('', config=True)
401 401 separate_out2 = SeparateUnicode('', config=True)
402 402 wildcards_case_sensitive = CBool(True, config=True)
403 403 xmode = CaselessStrEnum(('Context','Plain', 'Verbose'),
404 404 default_value='Context', config=True)
405 405
406 406 # Subcomponents of InteractiveShell
407 407 alias_manager = Instance('IPython.core.alias.AliasManager')
408 408 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager')
409 409 builtin_trap = Instance('IPython.core.builtin_trap.BuiltinTrap')
410 410 display_trap = Instance('IPython.core.display_trap.DisplayTrap')
411 411 extension_manager = Instance('IPython.core.extensions.ExtensionManager')
412 412 payload_manager = Instance('IPython.core.payload.PayloadManager')
413 413 history_manager = Instance('IPython.core.history.HistoryManager')
414 414 magics_manager = Instance('IPython.core.magic.MagicsManager')
415 415
416 416 profile_dir = Instance('IPython.core.application.ProfileDir')
417 417 @property
418 418 def profile(self):
419 419 if self.profile_dir is not None:
420 420 name = os.path.basename(self.profile_dir.location)
421 421 return name.replace('profile_','')
422 422
423 423
424 424 # Private interface
425 425 _post_execute = Instance(dict)
426 426
427 427 # Tracks any GUI loop loaded for pylab
428 428 pylab_gui_select = None
429 429
430 430 def __init__(self, ipython_dir=None, profile_dir=None,
431 431 user_module=None, user_ns=None,
432 432 custom_exceptions=((), None), **kwargs):
433 433
434 434 # This is where traits with a config_key argument are updated
435 435 # from the values on config.
436 436 super(InteractiveShell, self).__init__(**kwargs)
437 437 self.configurables = [self]
438 438
439 439 # These are relatively independent and stateless
440 440 self.init_ipython_dir(ipython_dir)
441 441 self.init_profile_dir(profile_dir)
442 442 self.init_instance_attrs()
443 443 self.init_environment()
444 444
445 445 # Check if we're in a virtualenv, and set up sys.path.
446 446 self.init_virtualenv()
447 447
448 448 # Create namespaces (user_ns, user_global_ns, etc.)
449 449 self.init_create_namespaces(user_module, user_ns)
450 450 # This has to be done after init_create_namespaces because it uses
451 451 # something in self.user_ns, but before init_sys_modules, which
452 452 # is the first thing to modify sys.
453 453 # TODO: When we override sys.stdout and sys.stderr before this class
454 454 # is created, we are saving the overridden ones here. Not sure if this
455 455 # is what we want to do.
456 456 self.save_sys_module_state()
457 457 self.init_sys_modules()
458 458
459 459 # While we're trying to have each part of the code directly access what
460 460 # it needs without keeping redundant references to objects, we have too
461 461 # much legacy code that expects ip.db to exist.
462 462 self.db = PickleShareDB(os.path.join(self.profile_dir.location, 'db'))
463 463
464 464 self.init_history()
465 465 self.init_encoding()
466 466 self.init_prefilter()
467 467
468 468 self.init_syntax_highlighting()
469 469 self.init_hooks()
470 470 self.init_pushd_popd_magic()
471 471 # self.init_traceback_handlers use to be here, but we moved it below
472 472 # because it and init_io have to come after init_readline.
473 473 self.init_user_ns()
474 474 self.init_logger()
475 475 self.init_builtins()
476 476
477 477 # The following was in post_config_initialization
478 478 self.init_inspector()
479 479 # init_readline() must come before init_io(), because init_io uses
480 480 # readline related things.
481 481 self.init_readline()
482 482 # We save this here in case user code replaces raw_input, but it needs
483 483 # to be after init_readline(), because PyPy's readline works by replacing
484 484 # raw_input.
485 485 if py3compat.PY3:
486 486 self.raw_input_original = input
487 487 else:
488 488 self.raw_input_original = raw_input
489 489 # init_completer must come after init_readline, because it needs to
490 490 # know whether readline is present or not system-wide to configure the
491 491 # completers, since the completion machinery can now operate
492 492 # independently of readline (e.g. over the network)
493 493 self.init_completer()
494 494 # TODO: init_io() needs to happen before init_traceback handlers
495 495 # because the traceback handlers hardcode the stdout/stderr streams.
496 496 # This logic in in debugger.Pdb and should eventually be changed.
497 497 self.init_io()
498 498 self.init_traceback_handlers(custom_exceptions)
499 499 self.init_prompts()
500 500 self.init_display_formatter()
501 501 self.init_display_pub()
502 502 self.init_data_pub()
503 503 self.init_displayhook()
504 504 self.init_latextool()
505 505 self.init_magics()
506 506 self.init_alias()
507 507 self.init_logstart()
508 508 self.init_pdb()
509 509 self.init_extension_manager()
510 510 self.init_payload()
511 511 self.init_comms()
512 512 self.hooks.late_startup_hook()
513 513 atexit.register(self.atexit_operations)
514 514
515 515 def get_ipython(self):
516 516 """Return the currently running IPython instance."""
517 517 return self
518 518
519 519 #-------------------------------------------------------------------------
520 520 # Trait changed handlers
521 521 #-------------------------------------------------------------------------
522 522
523 523 def _ipython_dir_changed(self, name, new):
524 524 if not os.path.isdir(new):
525 525 os.makedirs(new, mode = 0o777)
526 526
527 527 def set_autoindent(self,value=None):
528 528 """Set the autoindent flag, checking for readline support.
529 529
530 530 If called with no arguments, it acts as a toggle."""
531 531
532 532 if value != 0 and not self.has_readline:
533 533 if os.name == 'posix':
534 534 warn("The auto-indent feature requires the readline library")
535 535 self.autoindent = 0
536 536 return
537 537 if value is None:
538 538 self.autoindent = not self.autoindent
539 539 else:
540 540 self.autoindent = value
541 541
542 542 #-------------------------------------------------------------------------
543 543 # init_* methods called by __init__
544 544 #-------------------------------------------------------------------------
545 545
546 546 def init_ipython_dir(self, ipython_dir):
547 547 if ipython_dir is not None:
548 548 self.ipython_dir = ipython_dir
549 549 return
550 550
551 551 self.ipython_dir = get_ipython_dir()
552 552
553 553 def init_profile_dir(self, profile_dir):
554 554 if profile_dir is not None:
555 555 self.profile_dir = profile_dir
556 556 return
557 557 self.profile_dir =\
558 558 ProfileDir.create_profile_dir_by_name(self.ipython_dir, 'default')
559 559
560 560 def init_instance_attrs(self):
561 561 self.more = False
562 562
563 563 # command compiler
564 564 self.compile = CachingCompiler()
565 565
566 566 # Make an empty namespace, which extension writers can rely on both
567 567 # existing and NEVER being used by ipython itself. This gives them a
568 568 # convenient location for storing additional information and state
569 569 # their extensions may require, without fear of collisions with other
570 570 # ipython names that may develop later.
571 571 self.meta = Struct()
572 572
573 573 # Temporary files used for various purposes. Deleted at exit.
574 574 self.tempfiles = []
575 575
576 576 # Keep track of readline usage (later set by init_readline)
577 577 self.has_readline = False
578 578
579 579 # keep track of where we started running (mainly for crash post-mortem)
580 580 # This is not being used anywhere currently.
581 self.starting_dir = os.getcwdu()
581 self.starting_dir = py3compat.getcwd()
582 582
583 583 # Indentation management
584 584 self.indent_current_nsp = 0
585 585
586 586 # Dict to track post-execution functions that have been registered
587 587 self._post_execute = {}
588 588
589 589 def init_environment(self):
590 590 """Any changes we need to make to the user's environment."""
591 591 pass
592 592
593 593 def init_encoding(self):
594 594 # Get system encoding at startup time. Certain terminals (like Emacs
595 595 # under Win32 have it set to None, and we need to have a known valid
596 596 # encoding to use in the raw_input() method
597 597 try:
598 598 self.stdin_encoding = sys.stdin.encoding or 'ascii'
599 599 except AttributeError:
600 600 self.stdin_encoding = 'ascii'
601 601
602 602 def init_syntax_highlighting(self):
603 603 # Python source parser/formatter for syntax highlighting
604 604 pyformat = PyColorize.Parser().format
605 605 self.pycolorize = lambda src: pyformat(src,'str',self.colors)
606 606
607 607 def init_pushd_popd_magic(self):
608 608 # for pushd/popd management
609 609 self.home_dir = get_home_dir()
610 610
611 611 self.dir_stack = []
612 612
613 613 def init_logger(self):
614 614 self.logger = Logger(self.home_dir, logfname='ipython_log.py',
615 615 logmode='rotate')
616 616
617 617 def init_logstart(self):
618 618 """Initialize logging in case it was requested at the command line.
619 619 """
620 620 if self.logappend:
621 621 self.magic('logstart %s append' % self.logappend)
622 622 elif self.logfile:
623 623 self.magic('logstart %s' % self.logfile)
624 624 elif self.logstart:
625 625 self.magic('logstart')
626 626
627 627 def init_builtins(self):
628 628 # A single, static flag that we set to True. Its presence indicates
629 629 # that an IPython shell has been created, and we make no attempts at
630 630 # removing on exit or representing the existence of more than one
631 631 # IPython at a time.
632 632 builtin_mod.__dict__['__IPYTHON__'] = True
633 633
634 634 # In 0.11 we introduced '__IPYTHON__active' as an integer we'd try to
635 635 # manage on enter/exit, but with all our shells it's virtually
636 636 # impossible to get all the cases right. We're leaving the name in for
637 637 # those who adapted their codes to check for this flag, but will
638 638 # eventually remove it after a few more releases.
639 639 builtin_mod.__dict__['__IPYTHON__active'] = \
640 640 'Deprecated, check for __IPYTHON__'
641 641
642 642 self.builtin_trap = BuiltinTrap(shell=self)
643 643
644 644 def init_inspector(self):
645 645 # Object inspector
646 646 self.inspector = oinspect.Inspector(oinspect.InspectColors,
647 647 PyColorize.ANSICodeColors,
648 648 'NoColor',
649 649 self.object_info_string_level)
650 650
651 651 def init_io(self):
652 652 # This will just use sys.stdout and sys.stderr. If you want to
653 653 # override sys.stdout and sys.stderr themselves, you need to do that
654 654 # *before* instantiating this class, because io holds onto
655 655 # references to the underlying streams.
656 656 if (sys.platform == 'win32' or sys.platform == 'cli') and self.has_readline:
657 657 io.stdout = io.stderr = io.IOStream(self.readline._outputfile)
658 658 else:
659 659 io.stdout = io.IOStream(sys.stdout)
660 660 io.stderr = io.IOStream(sys.stderr)
661 661
662 662 def init_prompts(self):
663 663 self.prompt_manager = PromptManager(shell=self, parent=self)
664 664 self.configurables.append(self.prompt_manager)
665 665 # Set system prompts, so that scripts can decide if they are running
666 666 # interactively.
667 667 sys.ps1 = 'In : '
668 668 sys.ps2 = '...: '
669 669 sys.ps3 = 'Out: '
670 670
671 671 def init_display_formatter(self):
672 672 self.display_formatter = DisplayFormatter(parent=self)
673 673 self.configurables.append(self.display_formatter)
674 674
675 675 def init_display_pub(self):
676 676 self.display_pub = self.display_pub_class(parent=self)
677 677 self.configurables.append(self.display_pub)
678 678
679 679 def init_data_pub(self):
680 680 if not self.data_pub_class:
681 681 self.data_pub = None
682 682 return
683 683 self.data_pub = self.data_pub_class(parent=self)
684 684 self.configurables.append(self.data_pub)
685 685
686 686 def init_displayhook(self):
687 687 # Initialize displayhook, set in/out prompts and printing system
688 688 self.displayhook = self.displayhook_class(
689 689 parent=self,
690 690 shell=self,
691 691 cache_size=self.cache_size,
692 692 )
693 693 self.configurables.append(self.displayhook)
694 694 # This is a context manager that installs/revmoes the displayhook at
695 695 # the appropriate time.
696 696 self.display_trap = DisplayTrap(hook=self.displayhook)
697 697
698 698 def init_latextool(self):
699 699 """Configure LaTeXTool."""
700 700 cfg = LaTeXTool.instance(parent=self)
701 701 if cfg not in self.configurables:
702 702 self.configurables.append(cfg)
703 703
704 704 def init_virtualenv(self):
705 705 """Add a virtualenv to sys.path so the user can import modules from it.
706 706 This isn't perfect: it doesn't use the Python interpreter with which the
707 707 virtualenv was built, and it ignores the --no-site-packages option. A
708 708 warning will appear suggesting the user installs IPython in the
709 709 virtualenv, but for many cases, it probably works well enough.
710 710
711 711 Adapted from code snippets online.
712 712
713 713 http://blog.ufsoft.org/2009/1/29/ipython-and-virtualenv
714 714 """
715 715 if 'VIRTUAL_ENV' not in os.environ:
716 716 # Not in a virtualenv
717 717 return
718 718
719 719 if sys.executable.startswith(os.environ['VIRTUAL_ENV']):
720 720 # Running properly in the virtualenv, don't need to do anything
721 721 return
722 722
723 723 warn("Attempting to work in a virtualenv. If you encounter problems, please "
724 724 "install IPython inside the virtualenv.")
725 725 if sys.platform == "win32":
726 726 virtual_env = os.path.join(os.environ['VIRTUAL_ENV'], 'Lib', 'site-packages')
727 727 else:
728 728 virtual_env = os.path.join(os.environ['VIRTUAL_ENV'], 'lib',
729 729 'python%d.%d' % sys.version_info[:2], 'site-packages')
730 730
731 731 import site
732 732 sys.path.insert(0, virtual_env)
733 733 site.addsitedir(virtual_env)
734 734
735 735 #-------------------------------------------------------------------------
736 736 # Things related to injections into the sys module
737 737 #-------------------------------------------------------------------------
738 738
739 739 def save_sys_module_state(self):
740 740 """Save the state of hooks in the sys module.
741 741
742 742 This has to be called after self.user_module is created.
743 743 """
744 744 self._orig_sys_module_state = {}
745 745 self._orig_sys_module_state['stdin'] = sys.stdin
746 746 self._orig_sys_module_state['stdout'] = sys.stdout
747 747 self._orig_sys_module_state['stderr'] = sys.stderr
748 748 self._orig_sys_module_state['excepthook'] = sys.excepthook
749 749 self._orig_sys_modules_main_name = self.user_module.__name__
750 750 self._orig_sys_modules_main_mod = sys.modules.get(self.user_module.__name__)
751 751
752 752 def restore_sys_module_state(self):
753 753 """Restore the state of the sys module."""
754 754 try:
755 755 for k, v in iteritems(self._orig_sys_module_state):
756 756 setattr(sys, k, v)
757 757 except AttributeError:
758 758 pass
759 759 # Reset what what done in self.init_sys_modules
760 760 if self._orig_sys_modules_main_mod is not None:
761 761 sys.modules[self._orig_sys_modules_main_name] = self._orig_sys_modules_main_mod
762 762
763 763 #-------------------------------------------------------------------------
764 764 # Things related to hooks
765 765 #-------------------------------------------------------------------------
766 766
767 767 def init_hooks(self):
768 768 # hooks holds pointers used for user-side customizations
769 769 self.hooks = Struct()
770 770
771 771 self.strdispatchers = {}
772 772
773 773 # Set all default hooks, defined in the IPython.hooks module.
774 774 hooks = IPython.core.hooks
775 775 for hook_name in hooks.__all__:
776 776 # default hooks have priority 100, i.e. low; user hooks should have
777 777 # 0-100 priority
778 778 self.set_hook(hook_name,getattr(hooks,hook_name), 100)
779 779
780 780 def set_hook(self,name,hook, priority = 50, str_key = None, re_key = None):
781 781 """set_hook(name,hook) -> sets an internal IPython hook.
782 782
783 783 IPython exposes some of its internal API as user-modifiable hooks. By
784 784 adding your function to one of these hooks, you can modify IPython's
785 785 behavior to call at runtime your own routines."""
786 786
787 787 # At some point in the future, this should validate the hook before it
788 788 # accepts it. Probably at least check that the hook takes the number
789 789 # of args it's supposed to.
790 790
791 791 f = types.MethodType(hook,self)
792 792
793 793 # check if the hook is for strdispatcher first
794 794 if str_key is not None:
795 795 sdp = self.strdispatchers.get(name, StrDispatch())
796 796 sdp.add_s(str_key, f, priority )
797 797 self.strdispatchers[name] = sdp
798 798 return
799 799 if re_key is not None:
800 800 sdp = self.strdispatchers.get(name, StrDispatch())
801 801 sdp.add_re(re.compile(re_key), f, priority )
802 802 self.strdispatchers[name] = sdp
803 803 return
804 804
805 805 dp = getattr(self.hooks, name, None)
806 806 if name not in IPython.core.hooks.__all__:
807 807 print("Warning! Hook '%s' is not one of %s" % \
808 808 (name, IPython.core.hooks.__all__ ))
809 809 if not dp:
810 810 dp = IPython.core.hooks.CommandChainDispatcher()
811 811
812 812 try:
813 813 dp.add(f,priority)
814 814 except AttributeError:
815 815 # it was not commandchain, plain old func - replace
816 816 dp = f
817 817
818 818 setattr(self.hooks,name, dp)
819 819
820 820 def register_post_execute(self, func):
821 821 """Register a function for calling after code execution.
822 822 """
823 823 if not callable(func):
824 824 raise ValueError('argument %s must be callable' % func)
825 825 self._post_execute[func] = True
826 826
827 827 #-------------------------------------------------------------------------
828 828 # Things related to the "main" module
829 829 #-------------------------------------------------------------------------
830 830
831 831 def new_main_mod(self, filename, modname):
832 832 """Return a new 'main' module object for user code execution.
833 833
834 834 ``filename`` should be the path of the script which will be run in the
835 835 module. Requests with the same filename will get the same module, with
836 836 its namespace cleared.
837 837
838 838 ``modname`` should be the module name - normally either '__main__' or
839 839 the basename of the file without the extension.
840 840
841 841 When scripts are executed via %run, we must keep a reference to their
842 842 __main__ module around so that Python doesn't
843 843 clear it, rendering references to module globals useless.
844 844
845 845 This method keeps said reference in a private dict, keyed by the
846 846 absolute path of the script. This way, for multiple executions of the
847 847 same script we only keep one copy of the namespace (the last one),
848 848 thus preventing memory leaks from old references while allowing the
849 849 objects from the last execution to be accessible.
850 850 """
851 851 filename = os.path.abspath(filename)
852 852 try:
853 853 main_mod = self._main_mod_cache[filename]
854 854 except KeyError:
855 855 main_mod = self._main_mod_cache[filename] = types.ModuleType(modname,
856 856 doc="Module created for script run in IPython")
857 857 else:
858 858 main_mod.__dict__.clear()
859 859 main_mod.__name__ = modname
860 860
861 861 main_mod.__file__ = filename
862 862 # It seems pydoc (and perhaps others) needs any module instance to
863 863 # implement a __nonzero__ method
864 864 main_mod.__nonzero__ = lambda : True
865 865
866 866 return main_mod
867 867
868 868 def clear_main_mod_cache(self):
869 869 """Clear the cache of main modules.
870 870
871 871 Mainly for use by utilities like %reset.
872 872
873 873 Examples
874 874 --------
875 875
876 876 In [15]: import IPython
877 877
878 878 In [16]: m = _ip.new_main_mod(IPython.__file__, 'IPython')
879 879
880 880 In [17]: len(_ip._main_mod_cache) > 0
881 881 Out[17]: True
882 882
883 883 In [18]: _ip.clear_main_mod_cache()
884 884
885 885 In [19]: len(_ip._main_mod_cache) == 0
886 886 Out[19]: True
887 887 """
888 888 self._main_mod_cache.clear()
889 889
890 890 #-------------------------------------------------------------------------
891 891 # Things related to debugging
892 892 #-------------------------------------------------------------------------
893 893
894 894 def init_pdb(self):
895 895 # Set calling of pdb on exceptions
896 896 # self.call_pdb is a property
897 897 self.call_pdb = self.pdb
898 898
899 899 def _get_call_pdb(self):
900 900 return self._call_pdb
901 901
902 902 def _set_call_pdb(self,val):
903 903
904 904 if val not in (0,1,False,True):
905 905 raise ValueError('new call_pdb value must be boolean')
906 906
907 907 # store value in instance
908 908 self._call_pdb = val
909 909
910 910 # notify the actual exception handlers
911 911 self.InteractiveTB.call_pdb = val
912 912
913 913 call_pdb = property(_get_call_pdb,_set_call_pdb,None,
914 914 'Control auto-activation of pdb at exceptions')
915 915
916 916 def debugger(self,force=False):
917 917 """Call the pydb/pdb debugger.
918 918
919 919 Keywords:
920 920
921 921 - force(False): by default, this routine checks the instance call_pdb
922 922 flag and does not actually invoke the debugger if the flag is false.
923 923 The 'force' option forces the debugger to activate even if the flag
924 924 is false.
925 925 """
926 926
927 927 if not (force or self.call_pdb):
928 928 return
929 929
930 930 if not hasattr(sys,'last_traceback'):
931 931 error('No traceback has been produced, nothing to debug.')
932 932 return
933 933
934 934 # use pydb if available
935 935 if debugger.has_pydb:
936 936 from pydb import pm
937 937 else:
938 938 # fallback to our internal debugger
939 939 pm = lambda : self.InteractiveTB.debugger(force=True)
940 940
941 941 with self.readline_no_record:
942 942 pm()
943 943
944 944 #-------------------------------------------------------------------------
945 945 # Things related to IPython's various namespaces
946 946 #-------------------------------------------------------------------------
947 947 default_user_namespaces = True
948 948
949 949 def init_create_namespaces(self, user_module=None, user_ns=None):
950 950 # Create the namespace where the user will operate. user_ns is
951 951 # normally the only one used, and it is passed to the exec calls as
952 952 # the locals argument. But we do carry a user_global_ns namespace
953 953 # given as the exec 'globals' argument, This is useful in embedding
954 954 # situations where the ipython shell opens in a context where the
955 955 # distinction between locals and globals is meaningful. For
956 956 # non-embedded contexts, it is just the same object as the user_ns dict.
957 957
958 958 # FIXME. For some strange reason, __builtins__ is showing up at user
959 959 # level as a dict instead of a module. This is a manual fix, but I
960 960 # should really track down where the problem is coming from. Alex
961 961 # Schmolck reported this problem first.
962 962
963 963 # A useful post by Alex Martelli on this topic:
964 964 # Re: inconsistent value from __builtins__
965 965 # Von: Alex Martelli <aleaxit@yahoo.com>
966 966 # Datum: Freitag 01 Oktober 2004 04:45:34 nachmittags/abends
967 967 # Gruppen: comp.lang.python
968 968
969 969 # Michael Hohn <hohn@hooknose.lbl.gov> wrote:
970 970 # > >>> print type(builtin_check.get_global_binding('__builtins__'))
971 971 # > <type 'dict'>
972 972 # > >>> print type(__builtins__)
973 973 # > <type 'module'>
974 974 # > Is this difference in return value intentional?
975 975
976 976 # Well, it's documented that '__builtins__' can be either a dictionary
977 977 # or a module, and it's been that way for a long time. Whether it's
978 978 # intentional (or sensible), I don't know. In any case, the idea is
979 979 # that if you need to access the built-in namespace directly, you
980 980 # should start with "import __builtin__" (note, no 's') which will
981 981 # definitely give you a module. Yeah, it's somewhat confusing:-(.
982 982
983 983 # These routines return a properly built module and dict as needed by
984 984 # the rest of the code, and can also be used by extension writers to
985 985 # generate properly initialized namespaces.
986 986 if (user_ns is not None) or (user_module is not None):
987 987 self.default_user_namespaces = False
988 988 self.user_module, self.user_ns = self.prepare_user_module(user_module, user_ns)
989 989
990 990 # A record of hidden variables we have added to the user namespace, so
991 991 # we can list later only variables defined in actual interactive use.
992 992 self.user_ns_hidden = {}
993 993
994 994 # Now that FakeModule produces a real module, we've run into a nasty
995 995 # problem: after script execution (via %run), the module where the user
996 996 # code ran is deleted. Now that this object is a true module (needed
997 997 # so docetst and other tools work correctly), the Python module
998 998 # teardown mechanism runs over it, and sets to None every variable
999 999 # present in that module. Top-level references to objects from the
1000 1000 # script survive, because the user_ns is updated with them. However,
1001 1001 # calling functions defined in the script that use other things from
1002 1002 # the script will fail, because the function's closure had references
1003 1003 # to the original objects, which are now all None. So we must protect
1004 1004 # these modules from deletion by keeping a cache.
1005 1005 #
1006 1006 # To avoid keeping stale modules around (we only need the one from the
1007 1007 # last run), we use a dict keyed with the full path to the script, so
1008 1008 # only the last version of the module is held in the cache. Note,
1009 1009 # however, that we must cache the module *namespace contents* (their
1010 1010 # __dict__). Because if we try to cache the actual modules, old ones
1011 1011 # (uncached) could be destroyed while still holding references (such as
1012 1012 # those held by GUI objects that tend to be long-lived)>
1013 1013 #
1014 1014 # The %reset command will flush this cache. See the cache_main_mod()
1015 1015 # and clear_main_mod_cache() methods for details on use.
1016 1016
1017 1017 # This is the cache used for 'main' namespaces
1018 1018 self._main_mod_cache = {}
1019 1019
1020 1020 # A table holding all the namespaces IPython deals with, so that
1021 1021 # introspection facilities can search easily.
1022 1022 self.ns_table = {'user_global':self.user_module.__dict__,
1023 1023 'user_local':self.user_ns,
1024 1024 'builtin':builtin_mod.__dict__
1025 1025 }
1026 1026
1027 1027 @property
1028 1028 def user_global_ns(self):
1029 1029 return self.user_module.__dict__
1030 1030
1031 1031 def prepare_user_module(self, user_module=None, user_ns=None):
1032 1032 """Prepare the module and namespace in which user code will be run.
1033 1033
1034 1034 When IPython is started normally, both parameters are None: a new module
1035 1035 is created automatically, and its __dict__ used as the namespace.
1036 1036
1037 1037 If only user_module is provided, its __dict__ is used as the namespace.
1038 1038 If only user_ns is provided, a dummy module is created, and user_ns
1039 1039 becomes the global namespace. If both are provided (as they may be
1040 1040 when embedding), user_ns is the local namespace, and user_module
1041 1041 provides the global namespace.
1042 1042
1043 1043 Parameters
1044 1044 ----------
1045 1045 user_module : module, optional
1046 1046 The current user module in which IPython is being run. If None,
1047 1047 a clean module will be created.
1048 1048 user_ns : dict, optional
1049 1049 A namespace in which to run interactive commands.
1050 1050
1051 1051 Returns
1052 1052 -------
1053 1053 A tuple of user_module and user_ns, each properly initialised.
1054 1054 """
1055 1055 if user_module is None and user_ns is not None:
1056 1056 user_ns.setdefault("__name__", "__main__")
1057 1057 user_module = DummyMod()
1058 1058 user_module.__dict__ = user_ns
1059 1059
1060 1060 if user_module is None:
1061 1061 user_module = types.ModuleType("__main__",
1062 1062 doc="Automatically created module for IPython interactive environment")
1063 1063
1064 1064 # We must ensure that __builtin__ (without the final 's') is always
1065 1065 # available and pointing to the __builtin__ *module*. For more details:
1066 1066 # http://mail.python.org/pipermail/python-dev/2001-April/014068.html
1067 1067 user_module.__dict__.setdefault('__builtin__', builtin_mod)
1068 1068 user_module.__dict__.setdefault('__builtins__', builtin_mod)
1069 1069
1070 1070 if user_ns is None:
1071 1071 user_ns = user_module.__dict__
1072 1072
1073 1073 return user_module, user_ns
1074 1074
1075 1075 def init_sys_modules(self):
1076 1076 # We need to insert into sys.modules something that looks like a
1077 1077 # module but which accesses the IPython namespace, for shelve and
1078 1078 # pickle to work interactively. Normally they rely on getting
1079 1079 # everything out of __main__, but for embedding purposes each IPython
1080 1080 # instance has its own private namespace, so we can't go shoving
1081 1081 # everything into __main__.
1082 1082
1083 1083 # note, however, that we should only do this for non-embedded
1084 1084 # ipythons, which really mimic the __main__.__dict__ with their own
1085 1085 # namespace. Embedded instances, on the other hand, should not do
1086 1086 # this because they need to manage the user local/global namespaces
1087 1087 # only, but they live within a 'normal' __main__ (meaning, they
1088 1088 # shouldn't overtake the execution environment of the script they're
1089 1089 # embedded in).
1090 1090
1091 1091 # This is overridden in the InteractiveShellEmbed subclass to a no-op.
1092 1092 main_name = self.user_module.__name__
1093 1093 sys.modules[main_name] = self.user_module
1094 1094
1095 1095 def init_user_ns(self):
1096 1096 """Initialize all user-visible namespaces to their minimum defaults.
1097 1097
1098 1098 Certain history lists are also initialized here, as they effectively
1099 1099 act as user namespaces.
1100 1100
1101 1101 Notes
1102 1102 -----
1103 1103 All data structures here are only filled in, they are NOT reset by this
1104 1104 method. If they were not empty before, data will simply be added to
1105 1105 therm.
1106 1106 """
1107 1107 # This function works in two parts: first we put a few things in
1108 1108 # user_ns, and we sync that contents into user_ns_hidden so that these
1109 1109 # initial variables aren't shown by %who. After the sync, we add the
1110 1110 # rest of what we *do* want the user to see with %who even on a new
1111 1111 # session (probably nothing, so theye really only see their own stuff)
1112 1112
1113 1113 # The user dict must *always* have a __builtin__ reference to the
1114 1114 # Python standard __builtin__ namespace, which must be imported.
1115 1115 # This is so that certain operations in prompt evaluation can be
1116 1116 # reliably executed with builtins. Note that we can NOT use
1117 1117 # __builtins__ (note the 's'), because that can either be a dict or a
1118 1118 # module, and can even mutate at runtime, depending on the context
1119 1119 # (Python makes no guarantees on it). In contrast, __builtin__ is
1120 1120 # always a module object, though it must be explicitly imported.
1121 1121
1122 1122 # For more details:
1123 1123 # http://mail.python.org/pipermail/python-dev/2001-April/014068.html
1124 1124 ns = dict()
1125 1125
1126 1126 # Put 'help' in the user namespace
1127 1127 try:
1128 1128 from site import _Helper
1129 1129 ns['help'] = _Helper()
1130 1130 except ImportError:
1131 1131 warn('help() not available - check site.py')
1132 1132
1133 1133 # make global variables for user access to the histories
1134 1134 ns['_ih'] = self.history_manager.input_hist_parsed
1135 1135 ns['_oh'] = self.history_manager.output_hist
1136 1136 ns['_dh'] = self.history_manager.dir_hist
1137 1137
1138 1138 ns['_sh'] = shadowns
1139 1139
1140 1140 # user aliases to input and output histories. These shouldn't show up
1141 1141 # in %who, as they can have very large reprs.
1142 1142 ns['In'] = self.history_manager.input_hist_parsed
1143 1143 ns['Out'] = self.history_manager.output_hist
1144 1144
1145 1145 # Store myself as the public api!!!
1146 1146 ns['get_ipython'] = self.get_ipython
1147 1147
1148 1148 ns['exit'] = self.exiter
1149 1149 ns['quit'] = self.exiter
1150 1150
1151 1151 # Sync what we've added so far to user_ns_hidden so these aren't seen
1152 1152 # by %who
1153 1153 self.user_ns_hidden.update(ns)
1154 1154
1155 1155 # Anything put into ns now would show up in %who. Think twice before
1156 1156 # putting anything here, as we really want %who to show the user their
1157 1157 # stuff, not our variables.
1158 1158
1159 1159 # Finally, update the real user's namespace
1160 1160 self.user_ns.update(ns)
1161 1161
1162 1162 @property
1163 1163 def all_ns_refs(self):
1164 1164 """Get a list of references to all the namespace dictionaries in which
1165 1165 IPython might store a user-created object.
1166 1166
1167 1167 Note that this does not include the displayhook, which also caches
1168 1168 objects from the output."""
1169 1169 return [self.user_ns, self.user_global_ns, self.user_ns_hidden] + \
1170 1170 [m.__dict__ for m in self._main_mod_cache.values()]
1171 1171
1172 1172 def reset(self, new_session=True):
1173 1173 """Clear all internal namespaces, and attempt to release references to
1174 1174 user objects.
1175 1175
1176 1176 If new_session is True, a new history session will be opened.
1177 1177 """
1178 1178 # Clear histories
1179 1179 self.history_manager.reset(new_session)
1180 1180 # Reset counter used to index all histories
1181 1181 if new_session:
1182 1182 self.execution_count = 1
1183 1183
1184 1184 # Flush cached output items
1185 1185 if self.displayhook.do_full_cache:
1186 1186 self.displayhook.flush()
1187 1187
1188 1188 # The main execution namespaces must be cleared very carefully,
1189 1189 # skipping the deletion of the builtin-related keys, because doing so
1190 1190 # would cause errors in many object's __del__ methods.
1191 1191 if self.user_ns is not self.user_global_ns:
1192 1192 self.user_ns.clear()
1193 1193 ns = self.user_global_ns
1194 1194 drop_keys = set(ns.keys())
1195 1195 drop_keys.discard('__builtin__')
1196 1196 drop_keys.discard('__builtins__')
1197 1197 drop_keys.discard('__name__')
1198 1198 for k in drop_keys:
1199 1199 del ns[k]
1200 1200
1201 1201 self.user_ns_hidden.clear()
1202 1202
1203 1203 # Restore the user namespaces to minimal usability
1204 1204 self.init_user_ns()
1205 1205
1206 1206 # Restore the default and user aliases
1207 1207 self.alias_manager.clear_aliases()
1208 1208 self.alias_manager.init_aliases()
1209 1209
1210 1210 # Flush the private list of module references kept for script
1211 1211 # execution protection
1212 1212 self.clear_main_mod_cache()
1213 1213
1214 1214 def del_var(self, varname, by_name=False):
1215 1215 """Delete a variable from the various namespaces, so that, as
1216 1216 far as possible, we're not keeping any hidden references to it.
1217 1217
1218 1218 Parameters
1219 1219 ----------
1220 1220 varname : str
1221 1221 The name of the variable to delete.
1222 1222 by_name : bool
1223 1223 If True, delete variables with the given name in each
1224 1224 namespace. If False (default), find the variable in the user
1225 1225 namespace, and delete references to it.
1226 1226 """
1227 1227 if varname in ('__builtin__', '__builtins__'):
1228 1228 raise ValueError("Refusing to delete %s" % varname)
1229 1229
1230 1230 ns_refs = self.all_ns_refs
1231 1231
1232 1232 if by_name: # Delete by name
1233 1233 for ns in ns_refs:
1234 1234 try:
1235 1235 del ns[varname]
1236 1236 except KeyError:
1237 1237 pass
1238 1238 else: # Delete by object
1239 1239 try:
1240 1240 obj = self.user_ns[varname]
1241 1241 except KeyError:
1242 1242 raise NameError("name '%s' is not defined" % varname)
1243 1243 # Also check in output history
1244 1244 ns_refs.append(self.history_manager.output_hist)
1245 1245 for ns in ns_refs:
1246 1246 to_delete = [n for n, o in iteritems(ns) if o is obj]
1247 1247 for name in to_delete:
1248 1248 del ns[name]
1249 1249
1250 1250 # displayhook keeps extra references, but not in a dictionary
1251 1251 for name in ('_', '__', '___'):
1252 1252 if getattr(self.displayhook, name) is obj:
1253 1253 setattr(self.displayhook, name, None)
1254 1254
1255 1255 def reset_selective(self, regex=None):
1256 1256 """Clear selective variables from internal namespaces based on a
1257 1257 specified regular expression.
1258 1258
1259 1259 Parameters
1260 1260 ----------
1261 1261 regex : string or compiled pattern, optional
1262 1262 A regular expression pattern that will be used in searching
1263 1263 variable names in the users namespaces.
1264 1264 """
1265 1265 if regex is not None:
1266 1266 try:
1267 1267 m = re.compile(regex)
1268 1268 except TypeError:
1269 1269 raise TypeError('regex must be a string or compiled pattern')
1270 1270 # Search for keys in each namespace that match the given regex
1271 1271 # If a match is found, delete the key/value pair.
1272 1272 for ns in self.all_ns_refs:
1273 1273 for var in ns:
1274 1274 if m.search(var):
1275 1275 del ns[var]
1276 1276
1277 1277 def push(self, variables, interactive=True):
1278 1278 """Inject a group of variables into the IPython user namespace.
1279 1279
1280 1280 Parameters
1281 1281 ----------
1282 1282 variables : dict, str or list/tuple of str
1283 1283 The variables to inject into the user's namespace. If a dict, a
1284 1284 simple update is done. If a str, the string is assumed to have
1285 1285 variable names separated by spaces. A list/tuple of str can also
1286 1286 be used to give the variable names. If just the variable names are
1287 1287 give (list/tuple/str) then the variable values looked up in the
1288 1288 callers frame.
1289 1289 interactive : bool
1290 1290 If True (default), the variables will be listed with the ``who``
1291 1291 magic.
1292 1292 """
1293 1293 vdict = None
1294 1294
1295 1295 # We need a dict of name/value pairs to do namespace updates.
1296 1296 if isinstance(variables, dict):
1297 1297 vdict = variables
1298 1298 elif isinstance(variables, string_types+(list, tuple)):
1299 1299 if isinstance(variables, string_types):
1300 1300 vlist = variables.split()
1301 1301 else:
1302 1302 vlist = variables
1303 1303 vdict = {}
1304 1304 cf = sys._getframe(1)
1305 1305 for name in vlist:
1306 1306 try:
1307 1307 vdict[name] = eval(name, cf.f_globals, cf.f_locals)
1308 1308 except:
1309 1309 print('Could not get variable %s from %s' %
1310 1310 (name,cf.f_code.co_name))
1311 1311 else:
1312 1312 raise ValueError('variables must be a dict/str/list/tuple')
1313 1313
1314 1314 # Propagate variables to user namespace
1315 1315 self.user_ns.update(vdict)
1316 1316
1317 1317 # And configure interactive visibility
1318 1318 user_ns_hidden = self.user_ns_hidden
1319 1319 if interactive:
1320 1320 for name in vdict:
1321 1321 user_ns_hidden.pop(name, None)
1322 1322 else:
1323 1323 user_ns_hidden.update(vdict)
1324 1324
1325 1325 def drop_by_id(self, variables):
1326 1326 """Remove a dict of variables from the user namespace, if they are the
1327 1327 same as the values in the dictionary.
1328 1328
1329 1329 This is intended for use by extensions: variables that they've added can
1330 1330 be taken back out if they are unloaded, without removing any that the
1331 1331 user has overwritten.
1332 1332
1333 1333 Parameters
1334 1334 ----------
1335 1335 variables : dict
1336 1336 A dictionary mapping object names (as strings) to the objects.
1337 1337 """
1338 1338 for name, obj in iteritems(variables):
1339 1339 if name in self.user_ns and self.user_ns[name] is obj:
1340 1340 del self.user_ns[name]
1341 1341 self.user_ns_hidden.pop(name, None)
1342 1342
1343 1343 #-------------------------------------------------------------------------
1344 1344 # Things related to object introspection
1345 1345 #-------------------------------------------------------------------------
1346 1346
1347 1347 def _ofind(self, oname, namespaces=None):
1348 1348 """Find an object in the available namespaces.
1349 1349
1350 1350 self._ofind(oname) -> dict with keys: found,obj,ospace,ismagic
1351 1351
1352 1352 Has special code to detect magic functions.
1353 1353 """
1354 1354 oname = oname.strip()
1355 1355 #print '1- oname: <%r>' % oname # dbg
1356 1356 if not oname.startswith(ESC_MAGIC) and \
1357 1357 not oname.startswith(ESC_MAGIC2) and \
1358 1358 not py3compat.isidentifier(oname, dotted=True):
1359 1359 return dict(found=False)
1360 1360
1361 1361 alias_ns = None
1362 1362 if namespaces is None:
1363 1363 # Namespaces to search in:
1364 1364 # Put them in a list. The order is important so that we
1365 1365 # find things in the same order that Python finds them.
1366 1366 namespaces = [ ('Interactive', self.user_ns),
1367 1367 ('Interactive (global)', self.user_global_ns),
1368 1368 ('Python builtin', builtin_mod.__dict__),
1369 1369 ]
1370 1370
1371 1371 # initialize results to 'null'
1372 1372 found = False; obj = None; ospace = None; ds = None;
1373 1373 ismagic = False; isalias = False; parent = None
1374 1374
1375 1375 # We need to special-case 'print', which as of python2.6 registers as a
1376 1376 # function but should only be treated as one if print_function was
1377 1377 # loaded with a future import. In this case, just bail.
1378 1378 if (oname == 'print' and not py3compat.PY3 and not \
1379 1379 (self.compile.compiler_flags & __future__.CO_FUTURE_PRINT_FUNCTION)):
1380 1380 return {'found':found, 'obj':obj, 'namespace':ospace,
1381 1381 'ismagic':ismagic, 'isalias':isalias, 'parent':parent}
1382 1382
1383 1383 # Look for the given name by splitting it in parts. If the head is
1384 1384 # found, then we look for all the remaining parts as members, and only
1385 1385 # declare success if we can find them all.
1386 1386 oname_parts = oname.split('.')
1387 1387 oname_head, oname_rest = oname_parts[0],oname_parts[1:]
1388 1388 for nsname,ns in namespaces:
1389 1389 try:
1390 1390 obj = ns[oname_head]
1391 1391 except KeyError:
1392 1392 continue
1393 1393 else:
1394 1394 #print 'oname_rest:', oname_rest # dbg
1395 1395 for part in oname_rest:
1396 1396 try:
1397 1397 parent = obj
1398 1398 obj = getattr(obj,part)
1399 1399 except:
1400 1400 # Blanket except b/c some badly implemented objects
1401 1401 # allow __getattr__ to raise exceptions other than
1402 1402 # AttributeError, which then crashes IPython.
1403 1403 break
1404 1404 else:
1405 1405 # If we finish the for loop (no break), we got all members
1406 1406 found = True
1407 1407 ospace = nsname
1408 1408 break # namespace loop
1409 1409
1410 1410 # Try to see if it's magic
1411 1411 if not found:
1412 1412 obj = None
1413 1413 if oname.startswith(ESC_MAGIC2):
1414 1414 oname = oname.lstrip(ESC_MAGIC2)
1415 1415 obj = self.find_cell_magic(oname)
1416 1416 elif oname.startswith(ESC_MAGIC):
1417 1417 oname = oname.lstrip(ESC_MAGIC)
1418 1418 obj = self.find_line_magic(oname)
1419 1419 else:
1420 1420 # search without prefix, so run? will find %run?
1421 1421 obj = self.find_line_magic(oname)
1422 1422 if obj is None:
1423 1423 obj = self.find_cell_magic(oname)
1424 1424 if obj is not None:
1425 1425 found = True
1426 1426 ospace = 'IPython internal'
1427 1427 ismagic = True
1428 1428
1429 1429 # Last try: special-case some literals like '', [], {}, etc:
1430 1430 if not found and oname_head in ["''",'""','[]','{}','()']:
1431 1431 obj = eval(oname_head)
1432 1432 found = True
1433 1433 ospace = 'Interactive'
1434 1434
1435 1435 return {'found':found, 'obj':obj, 'namespace':ospace,
1436 1436 'ismagic':ismagic, 'isalias':isalias, 'parent':parent}
1437 1437
1438 1438 def _ofind_property(self, oname, info):
1439 1439 """Second part of object finding, to look for property details."""
1440 1440 if info.found:
1441 1441 # Get the docstring of the class property if it exists.
1442 1442 path = oname.split('.')
1443 1443 root = '.'.join(path[:-1])
1444 1444 if info.parent is not None:
1445 1445 try:
1446 1446 target = getattr(info.parent, '__class__')
1447 1447 # The object belongs to a class instance.
1448 1448 try:
1449 1449 target = getattr(target, path[-1])
1450 1450 # The class defines the object.
1451 1451 if isinstance(target, property):
1452 1452 oname = root + '.__class__.' + path[-1]
1453 1453 info = Struct(self._ofind(oname))
1454 1454 except AttributeError: pass
1455 1455 except AttributeError: pass
1456 1456
1457 1457 # We return either the new info or the unmodified input if the object
1458 1458 # hadn't been found
1459 1459 return info
1460 1460
1461 1461 def _object_find(self, oname, namespaces=None):
1462 1462 """Find an object and return a struct with info about it."""
1463 1463 inf = Struct(self._ofind(oname, namespaces))
1464 1464 return Struct(self._ofind_property(oname, inf))
1465 1465
1466 1466 def _inspect(self, meth, oname, namespaces=None, **kw):
1467 1467 """Generic interface to the inspector system.
1468 1468
1469 1469 This function is meant to be called by pdef, pdoc & friends."""
1470 1470 info = self._object_find(oname, namespaces)
1471 1471 if info.found:
1472 1472 pmethod = getattr(self.inspector, meth)
1473 1473 formatter = format_screen if info.ismagic else None
1474 1474 if meth == 'pdoc':
1475 1475 pmethod(info.obj, oname, formatter)
1476 1476 elif meth == 'pinfo':
1477 1477 pmethod(info.obj, oname, formatter, info, **kw)
1478 1478 else:
1479 1479 pmethod(info.obj, oname)
1480 1480 else:
1481 1481 print('Object `%s` not found.' % oname)
1482 1482 return 'not found' # so callers can take other action
1483 1483
1484 1484 def object_inspect(self, oname, detail_level=0):
1485 1485 with self.builtin_trap:
1486 1486 info = self._object_find(oname)
1487 1487 if info.found:
1488 1488 return self.inspector.info(info.obj, oname, info=info,
1489 1489 detail_level=detail_level
1490 1490 )
1491 1491 else:
1492 1492 return oinspect.object_info(name=oname, found=False)
1493 1493
1494 1494 #-------------------------------------------------------------------------
1495 1495 # Things related to history management
1496 1496 #-------------------------------------------------------------------------
1497 1497
1498 1498 def init_history(self):
1499 1499 """Sets up the command history, and starts regular autosaves."""
1500 1500 self.history_manager = HistoryManager(shell=self, parent=self)
1501 1501 self.configurables.append(self.history_manager)
1502 1502
1503 1503 #-------------------------------------------------------------------------
1504 1504 # Things related to exception handling and tracebacks (not debugging)
1505 1505 #-------------------------------------------------------------------------
1506 1506
1507 1507 def init_traceback_handlers(self, custom_exceptions):
1508 1508 # Syntax error handler.
1509 1509 self.SyntaxTB = ultratb.SyntaxTB(color_scheme='NoColor')
1510 1510
1511 1511 # The interactive one is initialized with an offset, meaning we always
1512 1512 # want to remove the topmost item in the traceback, which is our own
1513 1513 # internal code. Valid modes: ['Plain','Context','Verbose']
1514 1514 self.InteractiveTB = ultratb.AutoFormattedTB(mode = 'Plain',
1515 1515 color_scheme='NoColor',
1516 1516 tb_offset = 1,
1517 1517 check_cache=check_linecache_ipython)
1518 1518
1519 1519 # The instance will store a pointer to the system-wide exception hook,
1520 1520 # so that runtime code (such as magics) can access it. This is because
1521 1521 # during the read-eval loop, it may get temporarily overwritten.
1522 1522 self.sys_excepthook = sys.excepthook
1523 1523
1524 1524 # and add any custom exception handlers the user may have specified
1525 1525 self.set_custom_exc(*custom_exceptions)
1526 1526
1527 1527 # Set the exception mode
1528 1528 self.InteractiveTB.set_mode(mode=self.xmode)
1529 1529
1530 1530 def set_custom_exc(self, exc_tuple, handler):
1531 1531 """set_custom_exc(exc_tuple,handler)
1532 1532
1533 1533 Set a custom exception handler, which will be called if any of the
1534 1534 exceptions in exc_tuple occur in the mainloop (specifically, in the
1535 1535 run_code() method).
1536 1536
1537 1537 Parameters
1538 1538 ----------
1539 1539
1540 1540 exc_tuple : tuple of exception classes
1541 1541 A *tuple* of exception classes, for which to call the defined
1542 1542 handler. It is very important that you use a tuple, and NOT A
1543 1543 LIST here, because of the way Python's except statement works. If
1544 1544 you only want to trap a single exception, use a singleton tuple::
1545 1545
1546 1546 exc_tuple == (MyCustomException,)
1547 1547
1548 1548 handler : callable
1549 1549 handler must have the following signature::
1550 1550
1551 1551 def my_handler(self, etype, value, tb, tb_offset=None):
1552 1552 ...
1553 1553 return structured_traceback
1554 1554
1555 1555 Your handler must return a structured traceback (a list of strings),
1556 1556 or None.
1557 1557
1558 1558 This will be made into an instance method (via types.MethodType)
1559 1559 of IPython itself, and it will be called if any of the exceptions
1560 1560 listed in the exc_tuple are caught. If the handler is None, an
1561 1561 internal basic one is used, which just prints basic info.
1562 1562
1563 1563 To protect IPython from crashes, if your handler ever raises an
1564 1564 exception or returns an invalid result, it will be immediately
1565 1565 disabled.
1566 1566
1567 1567 WARNING: by putting in your own exception handler into IPython's main
1568 1568 execution loop, you run a very good chance of nasty crashes. This
1569 1569 facility should only be used if you really know what you are doing."""
1570 1570
1571 1571 assert type(exc_tuple)==type(()) , \
1572 1572 "The custom exceptions must be given AS A TUPLE."
1573 1573
1574 1574 def dummy_handler(self,etype,value,tb,tb_offset=None):
1575 1575 print('*** Simple custom exception handler ***')
1576 1576 print('Exception type :',etype)
1577 1577 print('Exception value:',value)
1578 1578 print('Traceback :',tb)
1579 1579 #print 'Source code :','\n'.join(self.buffer)
1580 1580
1581 1581 def validate_stb(stb):
1582 1582 """validate structured traceback return type
1583 1583
1584 1584 return type of CustomTB *should* be a list of strings, but allow
1585 1585 single strings or None, which are harmless.
1586 1586
1587 1587 This function will *always* return a list of strings,
1588 1588 and will raise a TypeError if stb is inappropriate.
1589 1589 """
1590 1590 msg = "CustomTB must return list of strings, not %r" % stb
1591 1591 if stb is None:
1592 1592 return []
1593 1593 elif isinstance(stb, string_types):
1594 1594 return [stb]
1595 1595 elif not isinstance(stb, list):
1596 1596 raise TypeError(msg)
1597 1597 # it's a list
1598 1598 for line in stb:
1599 1599 # check every element
1600 1600 if not isinstance(line, string_types):
1601 1601 raise TypeError(msg)
1602 1602 return stb
1603 1603
1604 1604 if handler is None:
1605 1605 wrapped = dummy_handler
1606 1606 else:
1607 1607 def wrapped(self,etype,value,tb,tb_offset=None):
1608 1608 """wrap CustomTB handler, to protect IPython from user code
1609 1609
1610 1610 This makes it harder (but not impossible) for custom exception
1611 1611 handlers to crash IPython.
1612 1612 """
1613 1613 try:
1614 1614 stb = handler(self,etype,value,tb,tb_offset=tb_offset)
1615 1615 return validate_stb(stb)
1616 1616 except:
1617 1617 # clear custom handler immediately
1618 1618 self.set_custom_exc((), None)
1619 1619 print("Custom TB Handler failed, unregistering", file=io.stderr)
1620 1620 # show the exception in handler first
1621 1621 stb = self.InteractiveTB.structured_traceback(*sys.exc_info())
1622 1622 print(self.InteractiveTB.stb2text(stb), file=io.stdout)
1623 1623 print("The original exception:", file=io.stdout)
1624 1624 stb = self.InteractiveTB.structured_traceback(
1625 1625 (etype,value,tb), tb_offset=tb_offset
1626 1626 )
1627 1627 return stb
1628 1628
1629 1629 self.CustomTB = types.MethodType(wrapped,self)
1630 1630 self.custom_exceptions = exc_tuple
1631 1631
1632 1632 def excepthook(self, etype, value, tb):
1633 1633 """One more defense for GUI apps that call sys.excepthook.
1634 1634
1635 1635 GUI frameworks like wxPython trap exceptions and call
1636 1636 sys.excepthook themselves. I guess this is a feature that
1637 1637 enables them to keep running after exceptions that would
1638 1638 otherwise kill their mainloop. This is a bother for IPython
1639 1639 which excepts to catch all of the program exceptions with a try:
1640 1640 except: statement.
1641 1641
1642 1642 Normally, IPython sets sys.excepthook to a CrashHandler instance, so if
1643 1643 any app directly invokes sys.excepthook, it will look to the user like
1644 1644 IPython crashed. In order to work around this, we can disable the
1645 1645 CrashHandler and replace it with this excepthook instead, which prints a
1646 1646 regular traceback using our InteractiveTB. In this fashion, apps which
1647 1647 call sys.excepthook will generate a regular-looking exception from
1648 1648 IPython, and the CrashHandler will only be triggered by real IPython
1649 1649 crashes.
1650 1650
1651 1651 This hook should be used sparingly, only in places which are not likely
1652 1652 to be true IPython errors.
1653 1653 """
1654 1654 self.showtraceback((etype,value,tb),tb_offset=0)
1655 1655
1656 1656 def _get_exc_info(self, exc_tuple=None):
1657 1657 """get exc_info from a given tuple, sys.exc_info() or sys.last_type etc.
1658 1658
1659 1659 Ensures sys.last_type,value,traceback hold the exc_info we found,
1660 1660 from whichever source.
1661 1661
1662 1662 raises ValueError if none of these contain any information
1663 1663 """
1664 1664 if exc_tuple is None:
1665 1665 etype, value, tb = sys.exc_info()
1666 1666 else:
1667 1667 etype, value, tb = exc_tuple
1668 1668
1669 1669 if etype is None:
1670 1670 if hasattr(sys, 'last_type'):
1671 1671 etype, value, tb = sys.last_type, sys.last_value, \
1672 1672 sys.last_traceback
1673 1673
1674 1674 if etype is None:
1675 1675 raise ValueError("No exception to find")
1676 1676
1677 1677 # Now store the exception info in sys.last_type etc.
1678 1678 # WARNING: these variables are somewhat deprecated and not
1679 1679 # necessarily safe to use in a threaded environment, but tools
1680 1680 # like pdb depend on their existence, so let's set them. If we
1681 1681 # find problems in the field, we'll need to revisit their use.
1682 1682 sys.last_type = etype
1683 1683 sys.last_value = value
1684 1684 sys.last_traceback = tb
1685 1685
1686 1686 return etype, value, tb
1687 1687
1688 1688 def show_usage_error(self, exc):
1689 1689 """Show a short message for UsageErrors
1690 1690
1691 1691 These are special exceptions that shouldn't show a traceback.
1692 1692 """
1693 1693 self.write_err("UsageError: %s" % exc)
1694 1694
1695 1695 def showtraceback(self,exc_tuple = None,filename=None,tb_offset=None,
1696 1696 exception_only=False):
1697 1697 """Display the exception that just occurred.
1698 1698
1699 1699 If nothing is known about the exception, this is the method which
1700 1700 should be used throughout the code for presenting user tracebacks,
1701 1701 rather than directly invoking the InteractiveTB object.
1702 1702
1703 1703 A specific showsyntaxerror() also exists, but this method can take
1704 1704 care of calling it if needed, so unless you are explicitly catching a
1705 1705 SyntaxError exception, don't try to analyze the stack manually and
1706 1706 simply call this method."""
1707 1707
1708 1708 try:
1709 1709 try:
1710 1710 etype, value, tb = self._get_exc_info(exc_tuple)
1711 1711 except ValueError:
1712 1712 self.write_err('No traceback available to show.\n')
1713 1713 return
1714 1714
1715 1715 if issubclass(etype, SyntaxError):
1716 1716 # Though this won't be called by syntax errors in the input
1717 1717 # line, there may be SyntaxError cases with imported code.
1718 1718 self.showsyntaxerror(filename)
1719 1719 elif etype is UsageError:
1720 1720 self.show_usage_error(value)
1721 1721 else:
1722 1722 if exception_only:
1723 1723 stb = ['An exception has occurred, use %tb to see '
1724 1724 'the full traceback.\n']
1725 1725 stb.extend(self.InteractiveTB.get_exception_only(etype,
1726 1726 value))
1727 1727 else:
1728 1728 try:
1729 1729 # Exception classes can customise their traceback - we
1730 1730 # use this in IPython.parallel for exceptions occurring
1731 1731 # in the engines. This should return a list of strings.
1732 1732 stb = value._render_traceback_()
1733 1733 except Exception:
1734 1734 stb = self.InteractiveTB.structured_traceback(etype,
1735 1735 value, tb, tb_offset=tb_offset)
1736 1736
1737 1737 self._showtraceback(etype, value, stb)
1738 1738 if self.call_pdb:
1739 1739 # drop into debugger
1740 1740 self.debugger(force=True)
1741 1741 return
1742 1742
1743 1743 # Actually show the traceback
1744 1744 self._showtraceback(etype, value, stb)
1745 1745
1746 1746 except KeyboardInterrupt:
1747 1747 self.write_err("\nKeyboardInterrupt\n")
1748 1748
1749 1749 def _showtraceback(self, etype, evalue, stb):
1750 1750 """Actually show a traceback.
1751 1751
1752 1752 Subclasses may override this method to put the traceback on a different
1753 1753 place, like a side channel.
1754 1754 """
1755 1755 print(self.InteractiveTB.stb2text(stb), file=io.stdout)
1756 1756
1757 1757 def showsyntaxerror(self, filename=None):
1758 1758 """Display the syntax error that just occurred.
1759 1759
1760 1760 This doesn't display a stack trace because there isn't one.
1761 1761
1762 1762 If a filename is given, it is stuffed in the exception instead
1763 1763 of what was there before (because Python's parser always uses
1764 1764 "<string>" when reading from a string).
1765 1765 """
1766 1766 etype, value, last_traceback = self._get_exc_info()
1767 1767
1768 1768 if filename and issubclass(etype, SyntaxError):
1769 1769 try:
1770 1770 value.filename = filename
1771 1771 except:
1772 1772 # Not the format we expect; leave it alone
1773 1773 pass
1774 1774
1775 1775 stb = self.SyntaxTB.structured_traceback(etype, value, [])
1776 1776 self._showtraceback(etype, value, stb)
1777 1777
1778 1778 # This is overridden in TerminalInteractiveShell to show a message about
1779 1779 # the %paste magic.
1780 1780 def showindentationerror(self):
1781 1781 """Called by run_cell when there's an IndentationError in code entered
1782 1782 at the prompt.
1783 1783
1784 1784 This is overridden in TerminalInteractiveShell to show a message about
1785 1785 the %paste magic."""
1786 1786 self.showsyntaxerror()
1787 1787
1788 1788 #-------------------------------------------------------------------------
1789 1789 # Things related to readline
1790 1790 #-------------------------------------------------------------------------
1791 1791
1792 1792 def init_readline(self):
1793 1793 """Command history completion/saving/reloading."""
1794 1794
1795 1795 if self.readline_use:
1796 1796 import IPython.utils.rlineimpl as readline
1797 1797
1798 1798 self.rl_next_input = None
1799 1799 self.rl_do_indent = False
1800 1800
1801 1801 if not self.readline_use or not readline.have_readline:
1802 1802 self.has_readline = False
1803 1803 self.readline = None
1804 1804 # Set a number of methods that depend on readline to be no-op
1805 1805 self.readline_no_record = no_op_context
1806 1806 self.set_readline_completer = no_op
1807 1807 self.set_custom_completer = no_op
1808 1808 if self.readline_use:
1809 1809 warn('Readline services not available or not loaded.')
1810 1810 else:
1811 1811 self.has_readline = True
1812 1812 self.readline = readline
1813 1813 sys.modules['readline'] = readline
1814 1814
1815 1815 # Platform-specific configuration
1816 1816 if os.name == 'nt':
1817 1817 # FIXME - check with Frederick to see if we can harmonize
1818 1818 # naming conventions with pyreadline to avoid this
1819 1819 # platform-dependent check
1820 1820 self.readline_startup_hook = readline.set_pre_input_hook
1821 1821 else:
1822 1822 self.readline_startup_hook = readline.set_startup_hook
1823 1823
1824 1824 # Load user's initrc file (readline config)
1825 1825 # Or if libedit is used, load editrc.
1826 1826 inputrc_name = os.environ.get('INPUTRC')
1827 1827 if inputrc_name is None:
1828 1828 inputrc_name = '.inputrc'
1829 1829 if readline.uses_libedit:
1830 1830 inputrc_name = '.editrc'
1831 1831 inputrc_name = os.path.join(self.home_dir, inputrc_name)
1832 1832 if os.path.isfile(inputrc_name):
1833 1833 try:
1834 1834 readline.read_init_file(inputrc_name)
1835 1835 except:
1836 1836 warn('Problems reading readline initialization file <%s>'
1837 1837 % inputrc_name)
1838 1838
1839 1839 # Configure readline according to user's prefs
1840 1840 # This is only done if GNU readline is being used. If libedit
1841 1841 # is being used (as on Leopard) the readline config is
1842 1842 # not run as the syntax for libedit is different.
1843 1843 if not readline.uses_libedit:
1844 1844 for rlcommand in self.readline_parse_and_bind:
1845 1845 #print "loading rl:",rlcommand # dbg
1846 1846 readline.parse_and_bind(rlcommand)
1847 1847
1848 1848 # Remove some chars from the delimiters list. If we encounter
1849 1849 # unicode chars, discard them.
1850 1850 delims = readline.get_completer_delims()
1851 1851 if not py3compat.PY3:
1852 1852 delims = delims.encode("ascii", "ignore")
1853 1853 for d in self.readline_remove_delims:
1854 1854 delims = delims.replace(d, "")
1855 1855 delims = delims.replace(ESC_MAGIC, '')
1856 1856 readline.set_completer_delims(delims)
1857 1857 # Store these so we can restore them if something like rpy2 modifies
1858 1858 # them.
1859 1859 self.readline_delims = delims
1860 1860 # otherwise we end up with a monster history after a while:
1861 1861 readline.set_history_length(self.history_length)
1862 1862
1863 1863 self.refill_readline_hist()
1864 1864 self.readline_no_record = ReadlineNoRecord(self)
1865 1865
1866 1866 # Configure auto-indent for all platforms
1867 1867 self.set_autoindent(self.autoindent)
1868 1868
1869 1869 def refill_readline_hist(self):
1870 1870 # Load the last 1000 lines from history
1871 1871 self.readline.clear_history()
1872 1872 stdin_encoding = sys.stdin.encoding or "utf-8"
1873 1873 last_cell = u""
1874 1874 for _, _, cell in self.history_manager.get_tail(1000,
1875 1875 include_latest=True):
1876 1876 # Ignore blank lines and consecutive duplicates
1877 1877 cell = cell.rstrip()
1878 1878 if cell and (cell != last_cell):
1879 1879 try:
1880 1880 if self.multiline_history:
1881 1881 self.readline.add_history(py3compat.unicode_to_str(cell,
1882 1882 stdin_encoding))
1883 1883 else:
1884 1884 for line in cell.splitlines():
1885 1885 self.readline.add_history(py3compat.unicode_to_str(line,
1886 1886 stdin_encoding))
1887 1887 last_cell = cell
1888 1888
1889 1889 except TypeError:
1890 1890 # The history DB can get corrupted so it returns strings
1891 1891 # containing null bytes, which readline objects to.
1892 1892 continue
1893 1893
1894 1894 @skip_doctest
1895 1895 def set_next_input(self, s):
1896 1896 """ Sets the 'default' input string for the next command line.
1897 1897
1898 1898 Requires readline.
1899 1899
1900 1900 Example::
1901 1901
1902 1902 In [1]: _ip.set_next_input("Hello Word")
1903 1903 In [2]: Hello Word_ # cursor is here
1904 1904 """
1905 1905 self.rl_next_input = py3compat.cast_bytes_py2(s)
1906 1906
1907 1907 # Maybe move this to the terminal subclass?
1908 1908 def pre_readline(self):
1909 1909 """readline hook to be used at the start of each line.
1910 1910
1911 1911 Currently it handles auto-indent only."""
1912 1912
1913 1913 if self.rl_do_indent:
1914 1914 self.readline.insert_text(self._indent_current_str())
1915 1915 if self.rl_next_input is not None:
1916 1916 self.readline.insert_text(self.rl_next_input)
1917 1917 self.rl_next_input = None
1918 1918
1919 1919 def _indent_current_str(self):
1920 1920 """return the current level of indentation as a string"""
1921 1921 return self.input_splitter.indent_spaces * ' '
1922 1922
1923 1923 #-------------------------------------------------------------------------
1924 1924 # Things related to text completion
1925 1925 #-------------------------------------------------------------------------
1926 1926
1927 1927 def init_completer(self):
1928 1928 """Initialize the completion machinery.
1929 1929
1930 1930 This creates completion machinery that can be used by client code,
1931 1931 either interactively in-process (typically triggered by the readline
1932 1932 library), programatically (such as in test suites) or out-of-prcess
1933 1933 (typically over the network by remote frontends).
1934 1934 """
1935 1935 from IPython.core.completer import IPCompleter
1936 1936 from IPython.core.completerlib import (module_completer,
1937 1937 magic_run_completer, cd_completer, reset_completer)
1938 1938
1939 1939 self.Completer = IPCompleter(shell=self,
1940 1940 namespace=self.user_ns,
1941 1941 global_namespace=self.user_global_ns,
1942 1942 use_readline=self.has_readline,
1943 1943 parent=self,
1944 1944 )
1945 1945 self.configurables.append(self.Completer)
1946 1946
1947 1947 # Add custom completers to the basic ones built into IPCompleter
1948 1948 sdisp = self.strdispatchers.get('complete_command', StrDispatch())
1949 1949 self.strdispatchers['complete_command'] = sdisp
1950 1950 self.Completer.custom_completers = sdisp
1951 1951
1952 1952 self.set_hook('complete_command', module_completer, str_key = 'import')
1953 1953 self.set_hook('complete_command', module_completer, str_key = 'from')
1954 1954 self.set_hook('complete_command', magic_run_completer, str_key = '%run')
1955 1955 self.set_hook('complete_command', cd_completer, str_key = '%cd')
1956 1956 self.set_hook('complete_command', reset_completer, str_key = '%reset')
1957 1957
1958 1958 # Only configure readline if we truly are using readline. IPython can
1959 1959 # do tab-completion over the network, in GUIs, etc, where readline
1960 1960 # itself may be absent
1961 1961 if self.has_readline:
1962 1962 self.set_readline_completer()
1963 1963
1964 1964 def complete(self, text, line=None, cursor_pos=None):
1965 1965 """Return the completed text and a list of completions.
1966 1966
1967 1967 Parameters
1968 1968 ----------
1969 1969
1970 1970 text : string
1971 1971 A string of text to be completed on. It can be given as empty and
1972 1972 instead a line/position pair are given. In this case, the
1973 1973 completer itself will split the line like readline does.
1974 1974
1975 1975 line : string, optional
1976 1976 The complete line that text is part of.
1977 1977
1978 1978 cursor_pos : int, optional
1979 1979 The position of the cursor on the input line.
1980 1980
1981 1981 Returns
1982 1982 -------
1983 1983 text : string
1984 1984 The actual text that was completed.
1985 1985
1986 1986 matches : list
1987 1987 A sorted list with all possible completions.
1988 1988
1989 1989 The optional arguments allow the completion to take more context into
1990 1990 account, and are part of the low-level completion API.
1991 1991
1992 1992 This is a wrapper around the completion mechanism, similar to what
1993 1993 readline does at the command line when the TAB key is hit. By
1994 1994 exposing it as a method, it can be used by other non-readline
1995 1995 environments (such as GUIs) for text completion.
1996 1996
1997 1997 Simple usage example:
1998 1998
1999 1999 In [1]: x = 'hello'
2000 2000
2001 2001 In [2]: _ip.complete('x.l')
2002 2002 Out[2]: ('x.l', ['x.ljust', 'x.lower', 'x.lstrip'])
2003 2003 """
2004 2004
2005 2005 # Inject names into __builtin__ so we can complete on the added names.
2006 2006 with self.builtin_trap:
2007 2007 return self.Completer.complete(text, line, cursor_pos)
2008 2008
2009 2009 def set_custom_completer(self, completer, pos=0):
2010 2010 """Adds a new custom completer function.
2011 2011
2012 2012 The position argument (defaults to 0) is the index in the completers
2013 2013 list where you want the completer to be inserted."""
2014 2014
2015 2015 newcomp = types.MethodType(completer,self.Completer)
2016 2016 self.Completer.matchers.insert(pos,newcomp)
2017 2017
2018 2018 def set_readline_completer(self):
2019 2019 """Reset readline's completer to be our own."""
2020 2020 self.readline.set_completer(self.Completer.rlcomplete)
2021 2021
2022 2022 def set_completer_frame(self, frame=None):
2023 2023 """Set the frame of the completer."""
2024 2024 if frame:
2025 2025 self.Completer.namespace = frame.f_locals
2026 2026 self.Completer.global_namespace = frame.f_globals
2027 2027 else:
2028 2028 self.Completer.namespace = self.user_ns
2029 2029 self.Completer.global_namespace = self.user_global_ns
2030 2030
2031 2031 #-------------------------------------------------------------------------
2032 2032 # Things related to magics
2033 2033 #-------------------------------------------------------------------------
2034 2034
2035 2035 def init_magics(self):
2036 2036 from IPython.core import magics as m
2037 2037 self.magics_manager = magic.MagicsManager(shell=self,
2038 2038 parent=self,
2039 2039 user_magics=m.UserMagics(self))
2040 2040 self.configurables.append(self.magics_manager)
2041 2041
2042 2042 # Expose as public API from the magics manager
2043 2043 self.register_magics = self.magics_manager.register
2044 2044 self.define_magic = self.magics_manager.define_magic
2045 2045
2046 2046 self.register_magics(m.AutoMagics, m.BasicMagics, m.CodeMagics,
2047 2047 m.ConfigMagics, m.DeprecatedMagics, m.DisplayMagics, m.ExecutionMagics,
2048 2048 m.ExtensionMagics, m.HistoryMagics, m.LoggingMagics,
2049 2049 m.NamespaceMagics, m.OSMagics, m.PylabMagics, m.ScriptMagics,
2050 2050 )
2051 2051
2052 2052 # Register Magic Aliases
2053 2053 mman = self.magics_manager
2054 2054 # FIXME: magic aliases should be defined by the Magics classes
2055 2055 # or in MagicsManager, not here
2056 2056 mman.register_alias('ed', 'edit')
2057 2057 mman.register_alias('hist', 'history')
2058 2058 mman.register_alias('rep', 'recall')
2059 2059 mman.register_alias('SVG', 'svg', 'cell')
2060 2060 mman.register_alias('HTML', 'html', 'cell')
2061 2061 mman.register_alias('file', 'writefile', 'cell')
2062 2062
2063 2063 # FIXME: Move the color initialization to the DisplayHook, which
2064 2064 # should be split into a prompt manager and displayhook. We probably
2065 2065 # even need a centralize colors management object.
2066 2066 self.magic('colors %s' % self.colors)
2067 2067
2068 2068 # Defined here so that it's included in the documentation
2069 2069 @functools.wraps(magic.MagicsManager.register_function)
2070 2070 def register_magic_function(self, func, magic_kind='line', magic_name=None):
2071 2071 self.magics_manager.register_function(func,
2072 2072 magic_kind=magic_kind, magic_name=magic_name)
2073 2073
2074 2074 def run_line_magic(self, magic_name, line):
2075 2075 """Execute the given line magic.
2076 2076
2077 2077 Parameters
2078 2078 ----------
2079 2079 magic_name : str
2080 2080 Name of the desired magic function, without '%' prefix.
2081 2081
2082 2082 line : str
2083 2083 The rest of the input line as a single string.
2084 2084 """
2085 2085 fn = self.find_line_magic(magic_name)
2086 2086 if fn is None:
2087 2087 cm = self.find_cell_magic(magic_name)
2088 2088 etpl = "Line magic function `%%%s` not found%s."
2089 2089 extra = '' if cm is None else (' (But cell magic `%%%%%s` exists, '
2090 2090 'did you mean that instead?)' % magic_name )
2091 2091 error(etpl % (magic_name, extra))
2092 2092 else:
2093 2093 # Note: this is the distance in the stack to the user's frame.
2094 2094 # This will need to be updated if the internal calling logic gets
2095 2095 # refactored, or else we'll be expanding the wrong variables.
2096 2096 stack_depth = 2
2097 2097 magic_arg_s = self.var_expand(line, stack_depth)
2098 2098 # Put magic args in a list so we can call with f(*a) syntax
2099 2099 args = [magic_arg_s]
2100 2100 kwargs = {}
2101 2101 # Grab local namespace if we need it:
2102 2102 if getattr(fn, "needs_local_scope", False):
2103 2103 kwargs['local_ns'] = sys._getframe(stack_depth).f_locals
2104 2104 with self.builtin_trap:
2105 2105 result = fn(*args,**kwargs)
2106 2106 return result
2107 2107
2108 2108 def run_cell_magic(self, magic_name, line, cell):
2109 2109 """Execute the given cell magic.
2110 2110
2111 2111 Parameters
2112 2112 ----------
2113 2113 magic_name : str
2114 2114 Name of the desired magic function, without '%' prefix.
2115 2115
2116 2116 line : str
2117 2117 The rest of the first input line as a single string.
2118 2118
2119 2119 cell : str
2120 2120 The body of the cell as a (possibly multiline) string.
2121 2121 """
2122 2122 fn = self.find_cell_magic(magic_name)
2123 2123 if fn is None:
2124 2124 lm = self.find_line_magic(magic_name)
2125 2125 etpl = "Cell magic `%%{0}` not found{1}."
2126 2126 extra = '' if lm is None else (' (But line magic `%{0}` exists, '
2127 2127 'did you mean that instead?)'.format(magic_name))
2128 2128 error(etpl.format(magic_name, extra))
2129 2129 elif cell == '':
2130 2130 message = '%%{0} is a cell magic, but the cell body is empty.'.format(magic_name)
2131 2131 if self.find_line_magic(magic_name) is not None:
2132 2132 message += ' Did you mean the line magic %{0} (single %)?'.format(magic_name)
2133 2133 raise UsageError(message)
2134 2134 else:
2135 2135 # Note: this is the distance in the stack to the user's frame.
2136 2136 # This will need to be updated if the internal calling logic gets
2137 2137 # refactored, or else we'll be expanding the wrong variables.
2138 2138 stack_depth = 2
2139 2139 magic_arg_s = self.var_expand(line, stack_depth)
2140 2140 with self.builtin_trap:
2141 2141 result = fn(magic_arg_s, cell)
2142 2142 return result
2143 2143
2144 2144 def find_line_magic(self, magic_name):
2145 2145 """Find and return a line magic by name.
2146 2146
2147 2147 Returns None if the magic isn't found."""
2148 2148 return self.magics_manager.magics['line'].get(magic_name)
2149 2149
2150 2150 def find_cell_magic(self, magic_name):
2151 2151 """Find and return a cell magic by name.
2152 2152
2153 2153 Returns None if the magic isn't found."""
2154 2154 return self.magics_manager.magics['cell'].get(magic_name)
2155 2155
2156 2156 def find_magic(self, magic_name, magic_kind='line'):
2157 2157 """Find and return a magic of the given type by name.
2158 2158
2159 2159 Returns None if the magic isn't found."""
2160 2160 return self.magics_manager.magics[magic_kind].get(magic_name)
2161 2161
2162 2162 def magic(self, arg_s):
2163 2163 """DEPRECATED. Use run_line_magic() instead.
2164 2164
2165 2165 Call a magic function by name.
2166 2166
2167 2167 Input: a string containing the name of the magic function to call and
2168 2168 any additional arguments to be passed to the magic.
2169 2169
2170 2170 magic('name -opt foo bar') is equivalent to typing at the ipython
2171 2171 prompt:
2172 2172
2173 2173 In[1]: %name -opt foo bar
2174 2174
2175 2175 To call a magic without arguments, simply use magic('name').
2176 2176
2177 2177 This provides a proper Python function to call IPython's magics in any
2178 2178 valid Python code you can type at the interpreter, including loops and
2179 2179 compound statements.
2180 2180 """
2181 2181 # TODO: should we issue a loud deprecation warning here?
2182 2182 magic_name, _, magic_arg_s = arg_s.partition(' ')
2183 2183 magic_name = magic_name.lstrip(prefilter.ESC_MAGIC)
2184 2184 return self.run_line_magic(magic_name, magic_arg_s)
2185 2185
2186 2186 #-------------------------------------------------------------------------
2187 2187 # Things related to macros
2188 2188 #-------------------------------------------------------------------------
2189 2189
2190 2190 def define_macro(self, name, themacro):
2191 2191 """Define a new macro
2192 2192
2193 2193 Parameters
2194 2194 ----------
2195 2195 name : str
2196 2196 The name of the macro.
2197 2197 themacro : str or Macro
2198 2198 The action to do upon invoking the macro. If a string, a new
2199 2199 Macro object is created by passing the string to it.
2200 2200 """
2201 2201
2202 2202 from IPython.core import macro
2203 2203
2204 2204 if isinstance(themacro, string_types):
2205 2205 themacro = macro.Macro(themacro)
2206 2206 if not isinstance(themacro, macro.Macro):
2207 2207 raise ValueError('A macro must be a string or a Macro instance.')
2208 2208 self.user_ns[name] = themacro
2209 2209
2210 2210 #-------------------------------------------------------------------------
2211 2211 # Things related to the running of system commands
2212 2212 #-------------------------------------------------------------------------
2213 2213
2214 2214 def system_piped(self, cmd):
2215 2215 """Call the given cmd in a subprocess, piping stdout/err
2216 2216
2217 2217 Parameters
2218 2218 ----------
2219 2219 cmd : str
2220 2220 Command to execute (can not end in '&', as background processes are
2221 2221 not supported. Should not be a command that expects input
2222 2222 other than simple text.
2223 2223 """
2224 2224 if cmd.rstrip().endswith('&'):
2225 2225 # this is *far* from a rigorous test
2226 2226 # We do not support backgrounding processes because we either use
2227 2227 # pexpect or pipes to read from. Users can always just call
2228 2228 # os.system() or use ip.system=ip.system_raw
2229 2229 # if they really want a background process.
2230 2230 raise OSError("Background processes not supported.")
2231 2231
2232 2232 # we explicitly do NOT return the subprocess status code, because
2233 2233 # a non-None value would trigger :func:`sys.displayhook` calls.
2234 2234 # Instead, we store the exit_code in user_ns.
2235 2235 self.user_ns['_exit_code'] = system(self.var_expand(cmd, depth=1))
2236 2236
2237 2237 def system_raw(self, cmd):
2238 2238 """Call the given cmd in a subprocess using os.system on Windows or
2239 2239 subprocess.call using the system shell on other platforms.
2240 2240
2241 2241 Parameters
2242 2242 ----------
2243 2243 cmd : str
2244 2244 Command to execute.
2245 2245 """
2246 2246 cmd = self.var_expand(cmd, depth=1)
2247 2247 # protect os.system from UNC paths on Windows, which it can't handle:
2248 2248 if sys.platform == 'win32':
2249 2249 from IPython.utils._process_win32 import AvoidUNCPath
2250 2250 with AvoidUNCPath() as path:
2251 2251 if path is not None:
2252 2252 cmd = '"pushd %s &&"%s' % (path, cmd)
2253 2253 cmd = py3compat.unicode_to_str(cmd)
2254 2254 ec = os.system(cmd)
2255 2255 else:
2256 2256 cmd = py3compat.unicode_to_str(cmd)
2257 2257 # Call the cmd using the OS shell, instead of the default /bin/sh, if set.
2258 2258 ec = subprocess.call(cmd, shell=True, executable=os.environ.get('SHELL', None))
2259 2259 # exit code is positive for program failure, or negative for
2260 2260 # terminating signal number.
2261 2261
2262 2262 # We explicitly do NOT return the subprocess status code, because
2263 2263 # a non-None value would trigger :func:`sys.displayhook` calls.
2264 2264 # Instead, we store the exit_code in user_ns.
2265 2265 self.user_ns['_exit_code'] = ec
2266 2266
2267 2267 # use piped system by default, because it is better behaved
2268 2268 system = system_piped
2269 2269
2270 2270 def getoutput(self, cmd, split=True, depth=0):
2271 2271 """Get output (possibly including stderr) from a subprocess.
2272 2272
2273 2273 Parameters
2274 2274 ----------
2275 2275 cmd : str
2276 2276 Command to execute (can not end in '&', as background processes are
2277 2277 not supported.
2278 2278 split : bool, optional
2279 2279 If True, split the output into an IPython SList. Otherwise, an
2280 2280 IPython LSString is returned. These are objects similar to normal
2281 2281 lists and strings, with a few convenience attributes for easier
2282 2282 manipulation of line-based output. You can use '?' on them for
2283 2283 details.
2284 2284 depth : int, optional
2285 2285 How many frames above the caller are the local variables which should
2286 2286 be expanded in the command string? The default (0) assumes that the
2287 2287 expansion variables are in the stack frame calling this function.
2288 2288 """
2289 2289 if cmd.rstrip().endswith('&'):
2290 2290 # this is *far* from a rigorous test
2291 2291 raise OSError("Background processes not supported.")
2292 2292 out = getoutput(self.var_expand(cmd, depth=depth+1))
2293 2293 if split:
2294 2294 out = SList(out.splitlines())
2295 2295 else:
2296 2296 out = LSString(out)
2297 2297 return out
2298 2298
2299 2299 #-------------------------------------------------------------------------
2300 2300 # Things related to aliases
2301 2301 #-------------------------------------------------------------------------
2302 2302
2303 2303 def init_alias(self):
2304 2304 self.alias_manager = AliasManager(shell=self, parent=self)
2305 2305 self.configurables.append(self.alias_manager)
2306 2306
2307 2307 #-------------------------------------------------------------------------
2308 2308 # Things related to extensions
2309 2309 #-------------------------------------------------------------------------
2310 2310
2311 2311 def init_extension_manager(self):
2312 2312 self.extension_manager = ExtensionManager(shell=self, parent=self)
2313 2313 self.configurables.append(self.extension_manager)
2314 2314
2315 2315 #-------------------------------------------------------------------------
2316 2316 # Things related to payloads
2317 2317 #-------------------------------------------------------------------------
2318 2318
2319 2319 def init_payload(self):
2320 2320 self.payload_manager = PayloadManager(parent=self)
2321 2321 self.configurables.append(self.payload_manager)
2322 2322
2323 2323 #-------------------------------------------------------------------------
2324 2324 # Things related to widgets
2325 2325 #-------------------------------------------------------------------------
2326 2326
2327 2327 def init_comms(self):
2328 2328 # not implemented in the base class
2329 2329 pass
2330 2330
2331 2331 #-------------------------------------------------------------------------
2332 2332 # Things related to the prefilter
2333 2333 #-------------------------------------------------------------------------
2334 2334
2335 2335 def init_prefilter(self):
2336 2336 self.prefilter_manager = PrefilterManager(shell=self, parent=self)
2337 2337 self.configurables.append(self.prefilter_manager)
2338 2338 # Ultimately this will be refactored in the new interpreter code, but
2339 2339 # for now, we should expose the main prefilter method (there's legacy
2340 2340 # code out there that may rely on this).
2341 2341 self.prefilter = self.prefilter_manager.prefilter_lines
2342 2342
2343 2343 def auto_rewrite_input(self, cmd):
2344 2344 """Print to the screen the rewritten form of the user's command.
2345 2345
2346 2346 This shows visual feedback by rewriting input lines that cause
2347 2347 automatic calling to kick in, like::
2348 2348
2349 2349 /f x
2350 2350
2351 2351 into::
2352 2352
2353 2353 ------> f(x)
2354 2354
2355 2355 after the user's input prompt. This helps the user understand that the
2356 2356 input line was transformed automatically by IPython.
2357 2357 """
2358 2358 if not self.show_rewritten_input:
2359 2359 return
2360 2360
2361 2361 rw = self.prompt_manager.render('rewrite') + cmd
2362 2362
2363 2363 try:
2364 2364 # plain ascii works better w/ pyreadline, on some machines, so
2365 2365 # we use it and only print uncolored rewrite if we have unicode
2366 2366 rw = str(rw)
2367 2367 print(rw, file=io.stdout)
2368 2368 except UnicodeEncodeError:
2369 2369 print("------> " + cmd)
2370 2370
2371 2371 #-------------------------------------------------------------------------
2372 2372 # Things related to extracting values/expressions from kernel and user_ns
2373 2373 #-------------------------------------------------------------------------
2374 2374
2375 2375 def _user_obj_error(self):
2376 2376 """return simple exception dict
2377 2377
2378 2378 for use in user_variables / expressions
2379 2379 """
2380 2380
2381 2381 etype, evalue, tb = self._get_exc_info()
2382 2382 stb = self.InteractiveTB.get_exception_only(etype, evalue)
2383 2383
2384 2384 exc_info = {
2385 2385 u'status' : 'error',
2386 2386 u'traceback' : stb,
2387 2387 u'ename' : unicode_type(etype.__name__),
2388 2388 u'evalue' : py3compat.safe_unicode(evalue),
2389 2389 }
2390 2390
2391 2391 return exc_info
2392 2392
2393 2393 def _format_user_obj(self, obj):
2394 2394 """format a user object to display dict
2395 2395
2396 2396 for use in user_expressions / variables
2397 2397 """
2398 2398
2399 2399 data, md = self.display_formatter.format(obj)
2400 2400 value = {
2401 2401 'status' : 'ok',
2402 2402 'data' : data,
2403 2403 'metadata' : md,
2404 2404 }
2405 2405 return value
2406 2406
2407 2407 def user_variables(self, names):
2408 2408 """Get a list of variable names from the user's namespace.
2409 2409
2410 2410 Parameters
2411 2411 ----------
2412 2412 names : list of strings
2413 2413 A list of names of variables to be read from the user namespace.
2414 2414
2415 2415 Returns
2416 2416 -------
2417 2417 A dict, keyed by the input names and with the rich mime-type repr(s) of each value.
2418 2418 Each element will be a sub-dict of the same form as a display_data message.
2419 2419 """
2420 2420 out = {}
2421 2421 user_ns = self.user_ns
2422 2422
2423 2423 for varname in names:
2424 2424 try:
2425 2425 value = self._format_user_obj(user_ns[varname])
2426 2426 except:
2427 2427 value = self._user_obj_error()
2428 2428 out[varname] = value
2429 2429 return out
2430 2430
2431 2431 def user_expressions(self, expressions):
2432 2432 """Evaluate a dict of expressions in the user's namespace.
2433 2433
2434 2434 Parameters
2435 2435 ----------
2436 2436 expressions : dict
2437 2437 A dict with string keys and string values. The expression values
2438 2438 should be valid Python expressions, each of which will be evaluated
2439 2439 in the user namespace.
2440 2440
2441 2441 Returns
2442 2442 -------
2443 2443 A dict, keyed like the input expressions dict, with the rich mime-typed
2444 2444 display_data of each value.
2445 2445 """
2446 2446 out = {}
2447 2447 user_ns = self.user_ns
2448 2448 global_ns = self.user_global_ns
2449 2449
2450 2450 for key, expr in iteritems(expressions):
2451 2451 try:
2452 2452 value = self._format_user_obj(eval(expr, global_ns, user_ns))
2453 2453 except:
2454 2454 value = self._user_obj_error()
2455 2455 out[key] = value
2456 2456 return out
2457 2457
2458 2458 #-------------------------------------------------------------------------
2459 2459 # Things related to the running of code
2460 2460 #-------------------------------------------------------------------------
2461 2461
2462 2462 def ex(self, cmd):
2463 2463 """Execute a normal python statement in user namespace."""
2464 2464 with self.builtin_trap:
2465 2465 exec(cmd, self.user_global_ns, self.user_ns)
2466 2466
2467 2467 def ev(self, expr):
2468 2468 """Evaluate python expression expr in user namespace.
2469 2469
2470 2470 Returns the result of evaluation
2471 2471 """
2472 2472 with self.builtin_trap:
2473 2473 return eval(expr, self.user_global_ns, self.user_ns)
2474 2474
2475 2475 def safe_execfile(self, fname, *where, **kw):
2476 2476 """A safe version of the builtin execfile().
2477 2477
2478 2478 This version will never throw an exception, but instead print
2479 2479 helpful error messages to the screen. This only works on pure
2480 2480 Python files with the .py extension.
2481 2481
2482 2482 Parameters
2483 2483 ----------
2484 2484 fname : string
2485 2485 The name of the file to be executed.
2486 2486 where : tuple
2487 2487 One or two namespaces, passed to execfile() as (globals,locals).
2488 2488 If only one is given, it is passed as both.
2489 2489 exit_ignore : bool (False)
2490 2490 If True, then silence SystemExit for non-zero status (it is always
2491 2491 silenced for zero status, as it is so common).
2492 2492 raise_exceptions : bool (False)
2493 2493 If True raise exceptions everywhere. Meant for testing.
2494 2494
2495 2495 """
2496 2496 kw.setdefault('exit_ignore', False)
2497 2497 kw.setdefault('raise_exceptions', False)
2498 2498
2499 2499 fname = os.path.abspath(os.path.expanduser(fname))
2500 2500
2501 2501 # Make sure we can open the file
2502 2502 try:
2503 2503 with open(fname) as thefile:
2504 2504 pass
2505 2505 except:
2506 2506 warn('Could not open file <%s> for safe execution.' % fname)
2507 2507 return
2508 2508
2509 2509 # Find things also in current directory. This is needed to mimic the
2510 2510 # behavior of running a script from the system command line, where
2511 2511 # Python inserts the script's directory into sys.path
2512 2512 dname = os.path.dirname(fname)
2513 2513
2514 2514 with prepended_to_syspath(dname):
2515 2515 try:
2516 2516 py3compat.execfile(fname,*where)
2517 2517 except SystemExit as status:
2518 2518 # If the call was made with 0 or None exit status (sys.exit(0)
2519 2519 # or sys.exit() ), don't bother showing a traceback, as both of
2520 2520 # these are considered normal by the OS:
2521 2521 # > python -c'import sys;sys.exit(0)'; echo $?
2522 2522 # 0
2523 2523 # > python -c'import sys;sys.exit()'; echo $?
2524 2524 # 0
2525 2525 # For other exit status, we show the exception unless
2526 2526 # explicitly silenced, but only in short form.
2527 2527 if kw['raise_exceptions']:
2528 2528 raise
2529 2529 if status.code and not kw['exit_ignore']:
2530 2530 self.showtraceback(exception_only=True)
2531 2531 except:
2532 2532 if kw['raise_exceptions']:
2533 2533 raise
2534 2534 self.showtraceback()
2535 2535
2536 2536 def safe_execfile_ipy(self, fname):
2537 2537 """Like safe_execfile, but for .ipy files with IPython syntax.
2538 2538
2539 2539 Parameters
2540 2540 ----------
2541 2541 fname : str
2542 2542 The name of the file to execute. The filename must have a
2543 2543 .ipy extension.
2544 2544 """
2545 2545 fname = os.path.abspath(os.path.expanduser(fname))
2546 2546
2547 2547 # Make sure we can open the file
2548 2548 try:
2549 2549 with open(fname) as thefile:
2550 2550 pass
2551 2551 except:
2552 2552 warn('Could not open file <%s> for safe execution.' % fname)
2553 2553 return
2554 2554
2555 2555 # Find things also in current directory. This is needed to mimic the
2556 2556 # behavior of running a script from the system command line, where
2557 2557 # Python inserts the script's directory into sys.path
2558 2558 dname = os.path.dirname(fname)
2559 2559
2560 2560 with prepended_to_syspath(dname):
2561 2561 try:
2562 2562 with open(fname) as thefile:
2563 2563 # self.run_cell currently captures all exceptions
2564 2564 # raised in user code. It would be nice if there were
2565 2565 # versions of runlines, execfile that did raise, so
2566 2566 # we could catch the errors.
2567 2567 self.run_cell(thefile.read(), store_history=False, shell_futures=False)
2568 2568 except:
2569 2569 self.showtraceback()
2570 2570 warn('Unknown failure executing file: <%s>' % fname)
2571 2571
2572 2572 def safe_run_module(self, mod_name, where):
2573 2573 """A safe version of runpy.run_module().
2574 2574
2575 2575 This version will never throw an exception, but instead print
2576 2576 helpful error messages to the screen.
2577 2577
2578 2578 `SystemExit` exceptions with status code 0 or None are ignored.
2579 2579
2580 2580 Parameters
2581 2581 ----------
2582 2582 mod_name : string
2583 2583 The name of the module to be executed.
2584 2584 where : dict
2585 2585 The globals namespace.
2586 2586 """
2587 2587 try:
2588 2588 try:
2589 2589 where.update(
2590 2590 runpy.run_module(str(mod_name), run_name="__main__",
2591 2591 alter_sys=True)
2592 2592 )
2593 2593 except SystemExit as status:
2594 2594 if status.code:
2595 2595 raise
2596 2596 except:
2597 2597 self.showtraceback()
2598 2598 warn('Unknown failure executing module: <%s>' % mod_name)
2599 2599
2600 2600 def _run_cached_cell_magic(self, magic_name, line):
2601 2601 """Special method to call a cell magic with the data stored in self.
2602 2602 """
2603 2603 cell = self._current_cell_magic_body
2604 2604 self._current_cell_magic_body = None
2605 2605 return self.run_cell_magic(magic_name, line, cell)
2606 2606
2607 2607 def run_cell(self, raw_cell, store_history=False, silent=False, shell_futures=True):
2608 2608 """Run a complete IPython cell.
2609 2609
2610 2610 Parameters
2611 2611 ----------
2612 2612 raw_cell : str
2613 2613 The code (including IPython code such as %magic functions) to run.
2614 2614 store_history : bool
2615 2615 If True, the raw and translated cell will be stored in IPython's
2616 2616 history. For user code calling back into IPython's machinery, this
2617 2617 should be set to False.
2618 2618 silent : bool
2619 2619 If True, avoid side-effects, such as implicit displayhooks and
2620 2620 and logging. silent=True forces store_history=False.
2621 2621 shell_futures : bool
2622 2622 If True, the code will share future statements with the interactive
2623 2623 shell. It will both be affected by previous __future__ imports, and
2624 2624 any __future__ imports in the code will affect the shell. If False,
2625 2625 __future__ imports are not shared in either direction.
2626 2626 """
2627 2627 if (not raw_cell) or raw_cell.isspace():
2628 2628 return
2629 2629
2630 2630 if silent:
2631 2631 store_history = False
2632 2632
2633 2633 self.input_transformer_manager.push(raw_cell)
2634 2634 cell = self.input_transformer_manager.source_reset()
2635 2635
2636 2636 # Our own compiler remembers the __future__ environment. If we want to
2637 2637 # run code with a separate __future__ environment, use the default
2638 2638 # compiler
2639 2639 compiler = self.compile if shell_futures else CachingCompiler()
2640 2640
2641 2641 with self.builtin_trap:
2642 2642 prefilter_failed = False
2643 2643 if len(cell.splitlines()) == 1:
2644 2644 try:
2645 2645 # use prefilter_lines to handle trailing newlines
2646 2646 # restore trailing newline for ast.parse
2647 2647 cell = self.prefilter_manager.prefilter_lines(cell) + '\n'
2648 2648 except AliasError as e:
2649 2649 error(e)
2650 2650 prefilter_failed = True
2651 2651 except Exception:
2652 2652 # don't allow prefilter errors to crash IPython
2653 2653 self.showtraceback()
2654 2654 prefilter_failed = True
2655 2655
2656 2656 # Store raw and processed history
2657 2657 if store_history:
2658 2658 self.history_manager.store_inputs(self.execution_count,
2659 2659 cell, raw_cell)
2660 2660 if not silent:
2661 2661 self.logger.log(cell, raw_cell)
2662 2662
2663 2663 if not prefilter_failed:
2664 2664 # don't run if prefilter failed
2665 2665 cell_name = self.compile.cache(cell, self.execution_count)
2666 2666
2667 2667 with self.display_trap:
2668 2668 try:
2669 2669 code_ast = compiler.ast_parse(cell, filename=cell_name)
2670 2670 except IndentationError:
2671 2671 self.showindentationerror()
2672 2672 if store_history:
2673 2673 self.execution_count += 1
2674 2674 return None
2675 2675 except (OverflowError, SyntaxError, ValueError, TypeError,
2676 2676 MemoryError):
2677 2677 self.showsyntaxerror()
2678 2678 if store_history:
2679 2679 self.execution_count += 1
2680 2680 return None
2681 2681
2682 2682 code_ast = self.transform_ast(code_ast)
2683 2683
2684 2684 interactivity = "none" if silent else self.ast_node_interactivity
2685 2685 self.run_ast_nodes(code_ast.body, cell_name,
2686 2686 interactivity=interactivity, compiler=compiler)
2687 2687
2688 2688 # Execute any registered post-execution functions.
2689 2689 # unless we are silent
2690 2690 post_exec = [] if silent else iteritems(self._post_execute)
2691 2691
2692 2692 for func, status in post_exec:
2693 2693 if self.disable_failing_post_execute and not status:
2694 2694 continue
2695 2695 try:
2696 2696 func()
2697 2697 except KeyboardInterrupt:
2698 2698 print("\nKeyboardInterrupt", file=io.stderr)
2699 2699 except Exception:
2700 2700 # register as failing:
2701 2701 self._post_execute[func] = False
2702 2702 self.showtraceback()
2703 2703 print('\n'.join([
2704 2704 "post-execution function %r produced an error." % func,
2705 2705 "If this problem persists, you can disable failing post-exec functions with:",
2706 2706 "",
2707 2707 " get_ipython().disable_failing_post_execute = True"
2708 2708 ]), file=io.stderr)
2709 2709
2710 2710 if store_history:
2711 2711 # Write output to the database. Does nothing unless
2712 2712 # history output logging is enabled.
2713 2713 self.history_manager.store_output(self.execution_count)
2714 2714 # Each cell is a *single* input, regardless of how many lines it has
2715 2715 self.execution_count += 1
2716 2716
2717 2717 def transform_ast(self, node):
2718 2718 """Apply the AST transformations from self.ast_transformers
2719 2719
2720 2720 Parameters
2721 2721 ----------
2722 2722 node : ast.Node
2723 2723 The root node to be transformed. Typically called with the ast.Module
2724 2724 produced by parsing user input.
2725 2725
2726 2726 Returns
2727 2727 -------
2728 2728 An ast.Node corresponding to the node it was called with. Note that it
2729 2729 may also modify the passed object, so don't rely on references to the
2730 2730 original AST.
2731 2731 """
2732 2732 for transformer in self.ast_transformers:
2733 2733 try:
2734 2734 node = transformer.visit(node)
2735 2735 except Exception:
2736 2736 warn("AST transformer %r threw an error. It will be unregistered." % transformer)
2737 2737 self.ast_transformers.remove(transformer)
2738 2738
2739 2739 if self.ast_transformers:
2740 2740 ast.fix_missing_locations(node)
2741 2741 return node
2742 2742
2743 2743
2744 2744 def run_ast_nodes(self, nodelist, cell_name, interactivity='last_expr',
2745 2745 compiler=compile):
2746 2746 """Run a sequence of AST nodes. The execution mode depends on the
2747 2747 interactivity parameter.
2748 2748
2749 2749 Parameters
2750 2750 ----------
2751 2751 nodelist : list
2752 2752 A sequence of AST nodes to run.
2753 2753 cell_name : str
2754 2754 Will be passed to the compiler as the filename of the cell. Typically
2755 2755 the value returned by ip.compile.cache(cell).
2756 2756 interactivity : str
2757 2757 'all', 'last', 'last_expr' or 'none', specifying which nodes should be
2758 2758 run interactively (displaying output from expressions). 'last_expr'
2759 2759 will run the last node interactively only if it is an expression (i.e.
2760 2760 expressions in loops or other blocks are not displayed. Other values
2761 2761 for this parameter will raise a ValueError.
2762 2762 compiler : callable
2763 2763 A function with the same interface as the built-in compile(), to turn
2764 2764 the AST nodes into code objects. Default is the built-in compile().
2765 2765 """
2766 2766 if not nodelist:
2767 2767 return
2768 2768
2769 2769 if interactivity == 'last_expr':
2770 2770 if isinstance(nodelist[-1], ast.Expr):
2771 2771 interactivity = "last"
2772 2772 else:
2773 2773 interactivity = "none"
2774 2774
2775 2775 if interactivity == 'none':
2776 2776 to_run_exec, to_run_interactive = nodelist, []
2777 2777 elif interactivity == 'last':
2778 2778 to_run_exec, to_run_interactive = nodelist[:-1], nodelist[-1:]
2779 2779 elif interactivity == 'all':
2780 2780 to_run_exec, to_run_interactive = [], nodelist
2781 2781 else:
2782 2782 raise ValueError("Interactivity was %r" % interactivity)
2783 2783
2784 2784 exec_count = self.execution_count
2785 2785
2786 2786 try:
2787 2787 for i, node in enumerate(to_run_exec):
2788 2788 mod = ast.Module([node])
2789 2789 code = compiler(mod, cell_name, "exec")
2790 2790 if self.run_code(code):
2791 2791 return True
2792 2792
2793 2793 for i, node in enumerate(to_run_interactive):
2794 2794 mod = ast.Interactive([node])
2795 2795 code = compiler(mod, cell_name, "single")
2796 2796 if self.run_code(code):
2797 2797 return True
2798 2798
2799 2799 # Flush softspace
2800 2800 if softspace(sys.stdout, 0):
2801 2801 print()
2802 2802
2803 2803 except:
2804 2804 # It's possible to have exceptions raised here, typically by
2805 2805 # compilation of odd code (such as a naked 'return' outside a
2806 2806 # function) that did parse but isn't valid. Typically the exception
2807 2807 # is a SyntaxError, but it's safest just to catch anything and show
2808 2808 # the user a traceback.
2809 2809
2810 2810 # We do only one try/except outside the loop to minimize the impact
2811 2811 # on runtime, and also because if any node in the node list is
2812 2812 # broken, we should stop execution completely.
2813 2813 self.showtraceback()
2814 2814
2815 2815 return False
2816 2816
2817 2817 def run_code(self, code_obj):
2818 2818 """Execute a code object.
2819 2819
2820 2820 When an exception occurs, self.showtraceback() is called to display a
2821 2821 traceback.
2822 2822
2823 2823 Parameters
2824 2824 ----------
2825 2825 code_obj : code object
2826 2826 A compiled code object, to be executed
2827 2827
2828 2828 Returns
2829 2829 -------
2830 2830 False : successful execution.
2831 2831 True : an error occurred.
2832 2832 """
2833 2833
2834 2834 # Set our own excepthook in case the user code tries to call it
2835 2835 # directly, so that the IPython crash handler doesn't get triggered
2836 2836 old_excepthook,sys.excepthook = sys.excepthook, self.excepthook
2837 2837
2838 2838 # we save the original sys.excepthook in the instance, in case config
2839 2839 # code (such as magics) needs access to it.
2840 2840 self.sys_excepthook = old_excepthook
2841 2841 outflag = 1 # happens in more places, so it's easier as default
2842 2842 try:
2843 2843 try:
2844 2844 self.hooks.pre_run_code_hook()
2845 2845 #rprint('Running code', repr(code_obj)) # dbg
2846 2846 exec(code_obj, self.user_global_ns, self.user_ns)
2847 2847 finally:
2848 2848 # Reset our crash handler in place
2849 2849 sys.excepthook = old_excepthook
2850 2850 except SystemExit:
2851 2851 self.showtraceback(exception_only=True)
2852 2852 warn("To exit: use 'exit', 'quit', or Ctrl-D.", level=1)
2853 2853 except self.custom_exceptions:
2854 2854 etype,value,tb = sys.exc_info()
2855 2855 self.CustomTB(etype,value,tb)
2856 2856 except:
2857 2857 self.showtraceback()
2858 2858 else:
2859 2859 outflag = 0
2860 2860 return outflag
2861 2861
2862 2862 # For backwards compatibility
2863 2863 runcode = run_code
2864 2864
2865 2865 #-------------------------------------------------------------------------
2866 2866 # Things related to GUI support and pylab
2867 2867 #-------------------------------------------------------------------------
2868 2868
2869 2869 def enable_gui(self, gui=None):
2870 2870 raise NotImplementedError('Implement enable_gui in a subclass')
2871 2871
2872 2872 def enable_matplotlib(self, gui=None):
2873 2873 """Enable interactive matplotlib and inline figure support.
2874 2874
2875 2875 This takes the following steps:
2876 2876
2877 2877 1. select the appropriate eventloop and matplotlib backend
2878 2878 2. set up matplotlib for interactive use with that backend
2879 2879 3. configure formatters for inline figure display
2880 2880 4. enable the selected gui eventloop
2881 2881
2882 2882 Parameters
2883 2883 ----------
2884 2884 gui : optional, string
2885 2885 If given, dictates the choice of matplotlib GUI backend to use
2886 2886 (should be one of IPython's supported backends, 'qt', 'osx', 'tk',
2887 2887 'gtk', 'wx' or 'inline'), otherwise we use the default chosen by
2888 2888 matplotlib (as dictated by the matplotlib build-time options plus the
2889 2889 user's matplotlibrc configuration file). Note that not all backends
2890 2890 make sense in all contexts, for example a terminal ipython can't
2891 2891 display figures inline.
2892 2892 """
2893 2893 from IPython.core import pylabtools as pt
2894 2894 gui, backend = pt.find_gui_and_backend(gui, self.pylab_gui_select)
2895 2895
2896 2896 if gui != 'inline':
2897 2897 # If we have our first gui selection, store it
2898 2898 if self.pylab_gui_select is None:
2899 2899 self.pylab_gui_select = gui
2900 2900 # Otherwise if they are different
2901 2901 elif gui != self.pylab_gui_select:
2902 2902 print ('Warning: Cannot change to a different GUI toolkit: %s.'
2903 2903 ' Using %s instead.' % (gui, self.pylab_gui_select))
2904 2904 gui, backend = pt.find_gui_and_backend(self.pylab_gui_select)
2905 2905
2906 2906 pt.activate_matplotlib(backend)
2907 2907 pt.configure_inline_support(self, backend)
2908 2908
2909 2909 # Now we must activate the gui pylab wants to use, and fix %run to take
2910 2910 # plot updates into account
2911 2911 self.enable_gui(gui)
2912 2912 self.magics_manager.registry['ExecutionMagics'].default_runner = \
2913 2913 pt.mpl_runner(self.safe_execfile)
2914 2914
2915 2915 return gui, backend
2916 2916
2917 2917 def enable_pylab(self, gui=None, import_all=True, welcome_message=False):
2918 2918 """Activate pylab support at runtime.
2919 2919
2920 2920 This turns on support for matplotlib, preloads into the interactive
2921 2921 namespace all of numpy and pylab, and configures IPython to correctly
2922 2922 interact with the GUI event loop. The GUI backend to be used can be
2923 2923 optionally selected with the optional ``gui`` argument.
2924 2924
2925 2925 This method only adds preloading the namespace to InteractiveShell.enable_matplotlib.
2926 2926
2927 2927 Parameters
2928 2928 ----------
2929 2929 gui : optional, string
2930 2930 If given, dictates the choice of matplotlib GUI backend to use
2931 2931 (should be one of IPython's supported backends, 'qt', 'osx', 'tk',
2932 2932 'gtk', 'wx' or 'inline'), otherwise we use the default chosen by
2933 2933 matplotlib (as dictated by the matplotlib build-time options plus the
2934 2934 user's matplotlibrc configuration file). Note that not all backends
2935 2935 make sense in all contexts, for example a terminal ipython can't
2936 2936 display figures inline.
2937 2937 import_all : optional, bool, default: True
2938 2938 Whether to do `from numpy import *` and `from pylab import *`
2939 2939 in addition to module imports.
2940 2940 welcome_message : deprecated
2941 2941 This argument is ignored, no welcome message will be displayed.
2942 2942 """
2943 2943 from IPython.core.pylabtools import import_pylab
2944 2944
2945 2945 gui, backend = self.enable_matplotlib(gui)
2946 2946
2947 2947 # We want to prevent the loading of pylab to pollute the user's
2948 2948 # namespace as shown by the %who* magics, so we execute the activation
2949 2949 # code in an empty namespace, and we update *both* user_ns and
2950 2950 # user_ns_hidden with this information.
2951 2951 ns = {}
2952 2952 import_pylab(ns, import_all)
2953 2953 # warn about clobbered names
2954 2954 ignored = set(["__builtins__"])
2955 2955 both = set(ns).intersection(self.user_ns).difference(ignored)
2956 2956 clobbered = [ name for name in both if self.user_ns[name] is not ns[name] ]
2957 2957 self.user_ns.update(ns)
2958 2958 self.user_ns_hidden.update(ns)
2959 2959 return gui, backend, clobbered
2960 2960
2961 2961 #-------------------------------------------------------------------------
2962 2962 # Utilities
2963 2963 #-------------------------------------------------------------------------
2964 2964
2965 2965 def var_expand(self, cmd, depth=0, formatter=DollarFormatter()):
2966 2966 """Expand python variables in a string.
2967 2967
2968 2968 The depth argument indicates how many frames above the caller should
2969 2969 be walked to look for the local namespace where to expand variables.
2970 2970
2971 2971 The global namespace for expansion is always the user's interactive
2972 2972 namespace.
2973 2973 """
2974 2974 ns = self.user_ns.copy()
2975 2975 ns.update(sys._getframe(depth+1).f_locals)
2976 2976 try:
2977 2977 # We have to use .vformat() here, because 'self' is a valid and common
2978 2978 # name, and expanding **ns for .format() would make it collide with
2979 2979 # the 'self' argument of the method.
2980 2980 cmd = formatter.vformat(cmd, args=[], kwargs=ns)
2981 2981 except Exception:
2982 2982 # if formatter couldn't format, just let it go untransformed
2983 2983 pass
2984 2984 return cmd
2985 2985
2986 2986 def mktempfile(self, data=None, prefix='ipython_edit_'):
2987 2987 """Make a new tempfile and return its filename.
2988 2988
2989 2989 This makes a call to tempfile.mktemp, but it registers the created
2990 2990 filename internally so ipython cleans it up at exit time.
2991 2991
2992 2992 Optional inputs:
2993 2993
2994 2994 - data(None): if data is given, it gets written out to the temp file
2995 2995 immediately, and the file is closed again."""
2996 2996
2997 2997 filename = tempfile.mktemp('.py', prefix)
2998 2998 self.tempfiles.append(filename)
2999 2999
3000 3000 if data:
3001 3001 tmp_file = open(filename,'w')
3002 3002 tmp_file.write(data)
3003 3003 tmp_file.close()
3004 3004 return filename
3005 3005
3006 3006 # TODO: This should be removed when Term is refactored.
3007 3007 def write(self,data):
3008 3008 """Write a string to the default output"""
3009 3009 io.stdout.write(data)
3010 3010
3011 3011 # TODO: This should be removed when Term is refactored.
3012 3012 def write_err(self,data):
3013 3013 """Write a string to the default error output"""
3014 3014 io.stderr.write(data)
3015 3015
3016 3016 def ask_yes_no(self, prompt, default=None):
3017 3017 if self.quiet:
3018 3018 return True
3019 3019 return ask_yes_no(prompt,default)
3020 3020
3021 3021 def show_usage(self):
3022 3022 """Show a usage message"""
3023 3023 page.page(IPython.core.usage.interactive_usage)
3024 3024
3025 3025 def extract_input_lines(self, range_str, raw=False):
3026 3026 """Return as a string a set of input history slices.
3027 3027
3028 3028 Parameters
3029 3029 ----------
3030 3030 range_str : string
3031 3031 The set of slices is given as a string, like "~5/6-~4/2 4:8 9",
3032 3032 since this function is for use by magic functions which get their
3033 3033 arguments as strings. The number before the / is the session
3034 3034 number: ~n goes n back from the current session.
3035 3035
3036 3036 Optional Parameters:
3037 3037 - raw(False): by default, the processed input is used. If this is
3038 3038 true, the raw input history is used instead.
3039 3039
3040 3040 Note that slices can be called with two notations:
3041 3041
3042 3042 N:M -> standard python form, means including items N...(M-1).
3043 3043
3044 3044 N-M -> include items N..M (closed endpoint).
3045 3045 """
3046 3046 lines = self.history_manager.get_range_by_str(range_str, raw=raw)
3047 3047 return "\n".join(x for _, _, x in lines)
3048 3048
3049 3049 def find_user_code(self, target, raw=True, py_only=False, skip_encoding_cookie=True):
3050 3050 """Get a code string from history, file, url, or a string or macro.
3051 3051
3052 3052 This is mainly used by magic functions.
3053 3053
3054 3054 Parameters
3055 3055 ----------
3056 3056
3057 3057 target : str
3058 3058
3059 3059 A string specifying code to retrieve. This will be tried respectively
3060 3060 as: ranges of input history (see %history for syntax), url,
3061 3061 correspnding .py file, filename, or an expression evaluating to a
3062 3062 string or Macro in the user namespace.
3063 3063
3064 3064 raw : bool
3065 3065 If true (default), retrieve raw history. Has no effect on the other
3066 3066 retrieval mechanisms.
3067 3067
3068 3068 py_only : bool (default False)
3069 3069 Only try to fetch python code, do not try alternative methods to decode file
3070 3070 if unicode fails.
3071 3071
3072 3072 Returns
3073 3073 -------
3074 3074 A string of code.
3075 3075
3076 3076 ValueError is raised if nothing is found, and TypeError if it evaluates
3077 3077 to an object of another type. In each case, .args[0] is a printable
3078 3078 message.
3079 3079 """
3080 3080 code = self.extract_input_lines(target, raw=raw) # Grab history
3081 3081 if code:
3082 3082 return code
3083 3083 utarget = unquote_filename(target)
3084 3084 try:
3085 3085 if utarget.startswith(('http://', 'https://')):
3086 3086 return openpy.read_py_url(utarget, skip_encoding_cookie=skip_encoding_cookie)
3087 3087 except UnicodeDecodeError:
3088 3088 if not py_only :
3089 3089 from urllib import urlopen # Deferred import
3090 3090 response = urlopen(target)
3091 3091 return response.read().decode('latin1')
3092 3092 raise ValueError(("'%s' seem to be unreadable.") % utarget)
3093 3093
3094 3094 potential_target = [target]
3095 3095 try :
3096 3096 potential_target.insert(0,get_py_filename(target))
3097 3097 except IOError:
3098 3098 pass
3099 3099
3100 3100 for tgt in potential_target :
3101 3101 if os.path.isfile(tgt): # Read file
3102 3102 try :
3103 3103 return openpy.read_py_file(tgt, skip_encoding_cookie=skip_encoding_cookie)
3104 3104 except UnicodeDecodeError :
3105 3105 if not py_only :
3106 3106 with io_open(tgt,'r', encoding='latin1') as f :
3107 3107 return f.read()
3108 3108 raise ValueError(("'%s' seem to be unreadable.") % target)
3109 3109 elif os.path.isdir(os.path.expanduser(tgt)):
3110 3110 raise ValueError("'%s' is a directory, not a regular file." % target)
3111 3111
3112 3112 try: # User namespace
3113 3113 codeobj = eval(target, self.user_ns)
3114 3114 except Exception:
3115 3115 raise ValueError(("'%s' was not found in history, as a file, url, "
3116 3116 "nor in the user namespace.") % target)
3117 3117 if isinstance(codeobj, string_types):
3118 3118 return codeobj
3119 3119 elif isinstance(codeobj, Macro):
3120 3120 return codeobj.value
3121 3121
3122 3122 raise TypeError("%s is neither a string nor a macro." % target,
3123 3123 codeobj)
3124 3124
3125 3125 #-------------------------------------------------------------------------
3126 3126 # Things related to IPython exiting
3127 3127 #-------------------------------------------------------------------------
3128 3128 def atexit_operations(self):
3129 3129 """This will be executed at the time of exit.
3130 3130
3131 3131 Cleanup operations and saving of persistent data that is done
3132 3132 unconditionally by IPython should be performed here.
3133 3133
3134 3134 For things that may depend on startup flags or platform specifics (such
3135 3135 as having readline or not), register a separate atexit function in the
3136 3136 code that has the appropriate information, rather than trying to
3137 3137 clutter
3138 3138 """
3139 3139 # Close the history session (this stores the end time and line count)
3140 3140 # this must be *before* the tempfile cleanup, in case of temporary
3141 3141 # history db
3142 3142 self.history_manager.end_session()
3143 3143
3144 3144 # Cleanup all tempfiles left around
3145 3145 for tfile in self.tempfiles:
3146 3146 try:
3147 3147 os.unlink(tfile)
3148 3148 except OSError:
3149 3149 pass
3150 3150
3151 3151 # Clear all user namespaces to release all references cleanly.
3152 3152 self.reset(new_session=False)
3153 3153
3154 3154 # Run user hooks
3155 3155 self.hooks.shutdown_hook()
3156 3156
3157 3157 def cleanup(self):
3158 3158 self.restore_sys_module_state()
3159 3159
3160 3160
3161 3161 class InteractiveShellABC(with_metaclass(abc.ABCMeta, object)):
3162 3162 """An abstract base class for InteractiveShell."""
3163 3163
3164 3164 InteractiveShellABC.register(InteractiveShell)
@@ -1,740 +1,741 b''
1 1 """Implementation of magic functions for interaction with the OS.
2 2
3 3 Note: this module is named 'osm' instead of 'os' to avoid a collision with the
4 4 builtin.
5 5 """
6 6 from __future__ import print_function
7 7 #-----------------------------------------------------------------------------
8 8 # Copyright (c) 2012 The IPython Development Team.
9 9 #
10 10 # Distributed under the terms of the Modified BSD License.
11 11 #
12 12 # The full license is in the file COPYING.txt, distributed with this software.
13 13 #-----------------------------------------------------------------------------
14 14
15 15 #-----------------------------------------------------------------------------
16 16 # Imports
17 17 #-----------------------------------------------------------------------------
18 18
19 19 # Stdlib
20 20 import io
21 21 import os
22 22 import re
23 23 import sys
24 24 from pprint import pformat
25 25
26 26 # Our own packages
27 27 from IPython.core import magic_arguments
28 28 from IPython.core import oinspect
29 29 from IPython.core import page
30 30 from IPython.core.alias import AliasError, Alias
31 31 from IPython.core.error import UsageError
32 32 from IPython.core.magic import (
33 33 Magics, compress_dhist, magics_class, line_magic, cell_magic, line_cell_magic
34 34 )
35 35 from IPython.testing.skipdoctest import skip_doctest
36 36 from IPython.utils.openpy import source_to_unicode
37 37 from IPython.utils.path import unquote_filename
38 38 from IPython.utils.process import abbrev_cwd
39 from IPython.utils import py3compat
39 40 from IPython.utils.py3compat import unicode_type
40 41 from IPython.utils.terminal import set_term_title
41 42
42 43 #-----------------------------------------------------------------------------
43 44 # Magic implementation classes
44 45 #-----------------------------------------------------------------------------
45 46 @magics_class
46 47 class OSMagics(Magics):
47 48 """Magics to interact with the underlying OS (shell-type functionality).
48 49 """
49 50
50 51 @skip_doctest
51 52 @line_magic
52 53 def alias(self, parameter_s=''):
53 54 """Define an alias for a system command.
54 55
55 56 '%alias alias_name cmd' defines 'alias_name' as an alias for 'cmd'
56 57
57 58 Then, typing 'alias_name params' will execute the system command 'cmd
58 59 params' (from your underlying operating system).
59 60
60 61 Aliases have lower precedence than magic functions and Python normal
61 62 variables, so if 'foo' is both a Python variable and an alias, the
62 63 alias can not be executed until 'del foo' removes the Python variable.
63 64
64 65 You can use the %l specifier in an alias definition to represent the
65 66 whole line when the alias is called. For example::
66 67
67 68 In [2]: alias bracket echo "Input in brackets: <%l>"
68 69 In [3]: bracket hello world
69 70 Input in brackets: <hello world>
70 71
71 72 You can also define aliases with parameters using %s specifiers (one
72 73 per parameter)::
73 74
74 75 In [1]: alias parts echo first %s second %s
75 76 In [2]: %parts A B
76 77 first A second B
77 78 In [3]: %parts A
78 79 Incorrect number of arguments: 2 expected.
79 80 parts is an alias to: 'echo first %s second %s'
80 81
81 82 Note that %l and %s are mutually exclusive. You can only use one or
82 83 the other in your aliases.
83 84
84 85 Aliases expand Python variables just like system calls using ! or !!
85 86 do: all expressions prefixed with '$' get expanded. For details of
86 87 the semantic rules, see PEP-215:
87 88 http://www.python.org/peps/pep-0215.html. This is the library used by
88 89 IPython for variable expansion. If you want to access a true shell
89 90 variable, an extra $ is necessary to prevent its expansion by
90 91 IPython::
91 92
92 93 In [6]: alias show echo
93 94 In [7]: PATH='A Python string'
94 95 In [8]: show $PATH
95 96 A Python string
96 97 In [9]: show $$PATH
97 98 /usr/local/lf9560/bin:/usr/local/intel/compiler70/ia32/bin:...
98 99
99 100 You can use the alias facility to acess all of $PATH. See the %rehash
100 101 and %rehashx functions, which automatically create aliases for the
101 102 contents of your $PATH.
102 103
103 104 If called with no parameters, %alias prints the current alias table."""
104 105
105 106 par = parameter_s.strip()
106 107 if not par:
107 108 aliases = sorted(self.shell.alias_manager.aliases)
108 109 # stored = self.shell.db.get('stored_aliases', {} )
109 110 # for k, v in stored:
110 111 # atab.append(k, v[0])
111 112
112 113 print("Total number of aliases:", len(aliases))
113 114 sys.stdout.flush()
114 115 return aliases
115 116
116 117 # Now try to define a new one
117 118 try:
118 119 alias,cmd = par.split(None, 1)
119 120 except TypeError:
120 121 print(oinspect.getdoc(self.alias))
121 122 return
122 123
123 124 try:
124 125 self.shell.alias_manager.define_alias(alias, cmd)
125 126 except AliasError as e:
126 127 print(e)
127 128 # end magic_alias
128 129
129 130 @line_magic
130 131 def unalias(self, parameter_s=''):
131 132 """Remove an alias"""
132 133
133 134 aname = parameter_s.strip()
134 135 try:
135 136 self.shell.alias_manager.undefine_alias(aname)
136 137 except ValueError as e:
137 138 print(e)
138 139 return
139 140
140 141 stored = self.shell.db.get('stored_aliases', {} )
141 142 if aname in stored:
142 143 print("Removing %stored alias",aname)
143 144 del stored[aname]
144 145 self.shell.db['stored_aliases'] = stored
145 146
146 147 @line_magic
147 148 def rehashx(self, parameter_s=''):
148 149 """Update the alias table with all executable files in $PATH.
149 150
150 151 This version explicitly checks that every entry in $PATH is a file
151 152 with execute access (os.X_OK), so it is much slower than %rehash.
152 153
153 154 Under Windows, it checks executability as a match against a
154 155 '|'-separated string of extensions, stored in the IPython config
155 156 variable win_exec_ext. This defaults to 'exe|com|bat'.
156 157
157 158 This function also resets the root module cache of module completer,
158 159 used on slow filesystems.
159 160 """
160 161 from IPython.core.alias import InvalidAliasError
161 162
162 163 # for the benefit of module completer in ipy_completers.py
163 164 del self.shell.db['rootmodules_cache']
164 165
165 166 path = [os.path.abspath(os.path.expanduser(p)) for p in
166 167 os.environ.get('PATH','').split(os.pathsep)]
167 168 path = filter(os.path.isdir,path)
168 169
169 170 syscmdlist = []
170 171 # Now define isexec in a cross platform manner.
171 172 if os.name == 'posix':
172 173 isexec = lambda fname:os.path.isfile(fname) and \
173 174 os.access(fname,os.X_OK)
174 175 else:
175 176 try:
176 177 winext = os.environ['pathext'].replace(';','|').replace('.','')
177 178 except KeyError:
178 179 winext = 'exe|com|bat|py'
179 180 if 'py' not in winext:
180 181 winext += '|py'
181 182 execre = re.compile(r'(.*)\.(%s)$' % winext,re.IGNORECASE)
182 183 isexec = lambda fname:os.path.isfile(fname) and execre.match(fname)
183 savedir = os.getcwdu()
184 savedir = py3compat.getcwd()
184 185
185 186 # Now walk the paths looking for executables to alias.
186 187 try:
187 188 # write the whole loop for posix/Windows so we don't have an if in
188 189 # the innermost part
189 190 if os.name == 'posix':
190 191 for pdir in path:
191 192 os.chdir(pdir)
192 193 for ff in os.listdir(pdir):
193 194 if isexec(ff):
194 195 try:
195 196 # Removes dots from the name since ipython
196 197 # will assume names with dots to be python.
197 198 if not self.shell.alias_manager.is_alias(ff):
198 199 self.shell.alias_manager.define_alias(
199 200 ff.replace('.',''), ff)
200 201 except InvalidAliasError:
201 202 pass
202 203 else:
203 204 syscmdlist.append(ff)
204 205 else:
205 206 no_alias = Alias.blacklist
206 207 for pdir in path:
207 208 os.chdir(pdir)
208 209 for ff in os.listdir(pdir):
209 210 base, ext = os.path.splitext(ff)
210 211 if isexec(ff) and base.lower() not in no_alias:
211 212 if ext.lower() == '.exe':
212 213 ff = base
213 214 try:
214 215 # Removes dots from the name since ipython
215 216 # will assume names with dots to be python.
216 217 self.shell.alias_manager.define_alias(
217 218 base.lower().replace('.',''), ff)
218 219 except InvalidAliasError:
219 220 pass
220 221 syscmdlist.append(ff)
221 222 self.shell.db['syscmdlist'] = syscmdlist
222 223 finally:
223 224 os.chdir(savedir)
224 225
225 226 @skip_doctest
226 227 @line_magic
227 228 def pwd(self, parameter_s=''):
228 229 """Return the current working directory path.
229 230
230 231 Examples
231 232 --------
232 233 ::
233 234
234 235 In [9]: pwd
235 236 Out[9]: '/home/tsuser/sprint/ipython'
236 237 """
237 return os.getcwdu()
238 return py3compat.getcwd()
238 239
239 240 @skip_doctest
240 241 @line_magic
241 242 def cd(self, parameter_s=''):
242 243 """Change the current working directory.
243 244
244 245 This command automatically maintains an internal list of directories
245 246 you visit during your IPython session, in the variable _dh. The
246 247 command %dhist shows this history nicely formatted. You can also
247 248 do 'cd -<tab>' to see directory history conveniently.
248 249
249 250 Usage:
250 251
251 252 cd 'dir': changes to directory 'dir'.
252 253
253 254 cd -: changes to the last visited directory.
254 255
255 256 cd -<n>: changes to the n-th directory in the directory history.
256 257
257 258 cd --foo: change to directory that matches 'foo' in history
258 259
259 260 cd -b <bookmark_name>: jump to a bookmark set by %bookmark
260 261 (note: cd <bookmark_name> is enough if there is no
261 262 directory <bookmark_name>, but a bookmark with the name exists.)
262 263 'cd -b <tab>' allows you to tab-complete bookmark names.
263 264
264 265 Options:
265 266
266 267 -q: quiet. Do not print the working directory after the cd command is
267 268 executed. By default IPython's cd command does print this directory,
268 269 since the default prompts do not display path information.
269 270
270 271 Note that !cd doesn't work for this purpose because the shell where
271 272 !command runs is immediately discarded after executing 'command'.
272 273
273 274 Examples
274 275 --------
275 276 ::
276 277
277 278 In [10]: cd parent/child
278 279 /home/tsuser/parent/child
279 280 """
280 281
281 oldcwd = os.getcwdu()
282 oldcwd = py3compat.getcwd()
282 283 numcd = re.match(r'(-)(\d+)$',parameter_s)
283 284 # jump in directory history by number
284 285 if numcd:
285 286 nn = int(numcd.group(2))
286 287 try:
287 288 ps = self.shell.user_ns['_dh'][nn]
288 289 except IndexError:
289 290 print('The requested directory does not exist in history.')
290 291 return
291 292 else:
292 293 opts = {}
293 294 elif parameter_s.startswith('--'):
294 295 ps = None
295 296 fallback = None
296 297 pat = parameter_s[2:]
297 298 dh = self.shell.user_ns['_dh']
298 299 # first search only by basename (last component)
299 300 for ent in reversed(dh):
300 301 if pat in os.path.basename(ent) and os.path.isdir(ent):
301 302 ps = ent
302 303 break
303 304
304 305 if fallback is None and pat in ent and os.path.isdir(ent):
305 306 fallback = ent
306 307
307 308 # if we have no last part match, pick the first full path match
308 309 if ps is None:
309 310 ps = fallback
310 311
311 312 if ps is None:
312 313 print("No matching entry in directory history")
313 314 return
314 315 else:
315 316 opts = {}
316 317
317 318
318 319 else:
319 320 #turn all non-space-escaping backslashes to slashes,
320 321 # for c:\windows\directory\names\
321 322 parameter_s = re.sub(r'\\(?! )','/', parameter_s)
322 323 opts,ps = self.parse_options(parameter_s,'qb',mode='string')
323 324 # jump to previous
324 325 if ps == '-':
325 326 try:
326 327 ps = self.shell.user_ns['_dh'][-2]
327 328 except IndexError:
328 329 raise UsageError('%cd -: No previous directory to change to.')
329 330 # jump to bookmark if needed
330 331 else:
331 332 if not os.path.isdir(ps) or 'b' in opts:
332 333 bkms = self.shell.db.get('bookmarks', {})
333 334
334 335 if ps in bkms:
335 336 target = bkms[ps]
336 337 print('(bookmark:%s) -> %s' % (ps, target))
337 338 ps = target
338 339 else:
339 340 if 'b' in opts:
340 341 raise UsageError("Bookmark '%s' not found. "
341 342 "Use '%%bookmark -l' to see your bookmarks." % ps)
342 343
343 344 # strip extra quotes on Windows, because os.chdir doesn't like them
344 345 ps = unquote_filename(ps)
345 346 # at this point ps should point to the target dir
346 347 if ps:
347 348 try:
348 349 os.chdir(os.path.expanduser(ps))
349 350 if hasattr(self.shell, 'term_title') and self.shell.term_title:
350 351 set_term_title('IPython: ' + abbrev_cwd())
351 352 except OSError:
352 353 print(sys.exc_info()[1])
353 354 else:
354 cwd = os.getcwdu()
355 cwd = py3compat.getcwd()
355 356 dhist = self.shell.user_ns['_dh']
356 357 if oldcwd != cwd:
357 358 dhist.append(cwd)
358 359 self.shell.db['dhist'] = compress_dhist(dhist)[-100:]
359 360
360 361 else:
361 362 os.chdir(self.shell.home_dir)
362 363 if hasattr(self.shell, 'term_title') and self.shell.term_title:
363 364 set_term_title('IPython: ' + '~')
364 cwd = os.getcwdu()
365 cwd = py3compat.getcwd()
365 366 dhist = self.shell.user_ns['_dh']
366 367
367 368 if oldcwd != cwd:
368 369 dhist.append(cwd)
369 370 self.shell.db['dhist'] = compress_dhist(dhist)[-100:]
370 371 if not 'q' in opts and self.shell.user_ns['_dh']:
371 372 print(self.shell.user_ns['_dh'][-1])
372 373
373 374
374 375 @line_magic
375 376 def env(self, parameter_s=''):
376 377 """List environment variables."""
377 378
378 379 return dict(os.environ)
379 380
380 381 @line_magic
381 382 def pushd(self, parameter_s=''):
382 383 """Place the current dir on stack and change directory.
383 384
384 385 Usage:\\
385 386 %pushd ['dirname']
386 387 """
387 388
388 389 dir_s = self.shell.dir_stack
389 390 tgt = os.path.expanduser(unquote_filename(parameter_s))
390 cwd = os.getcwdu().replace(self.shell.home_dir,'~')
391 cwd = py3compat.getcwd().replace(self.shell.home_dir,'~')
391 392 if tgt:
392 393 self.cd(parameter_s)
393 394 dir_s.insert(0,cwd)
394 395 return self.shell.magic('dirs')
395 396
396 397 @line_magic
397 398 def popd(self, parameter_s=''):
398 399 """Change to directory popped off the top of the stack.
399 400 """
400 401 if not self.shell.dir_stack:
401 402 raise UsageError("%popd on empty stack")
402 403 top = self.shell.dir_stack.pop(0)
403 404 self.cd(top)
404 405 print("popd ->",top)
405 406
406 407 @line_magic
407 408 def dirs(self, parameter_s=''):
408 409 """Return the current directory stack."""
409 410
410 411 return self.shell.dir_stack
411 412
412 413 @line_magic
413 414 def dhist(self, parameter_s=''):
414 415 """Print your history of visited directories.
415 416
416 417 %dhist -> print full history\\
417 418 %dhist n -> print last n entries only\\
418 419 %dhist n1 n2 -> print entries between n1 and n2 (n2 not included)\\
419 420
420 421 This history is automatically maintained by the %cd command, and
421 422 always available as the global list variable _dh. You can use %cd -<n>
422 423 to go to directory number <n>.
423 424
424 425 Note that most of time, you should view directory history by entering
425 426 cd -<TAB>.
426 427
427 428 """
428 429
429 430 dh = self.shell.user_ns['_dh']
430 431 if parameter_s:
431 432 try:
432 433 args = map(int,parameter_s.split())
433 434 except:
434 435 self.arg_err(self.dhist)
435 436 return
436 437 if len(args) == 1:
437 438 ini,fin = max(len(dh)-(args[0]),0),len(dh)
438 439 elif len(args) == 2:
439 440 ini,fin = args
440 441 fin = min(fin, len(dh))
441 442 else:
442 443 self.arg_err(self.dhist)
443 444 return
444 445 else:
445 446 ini,fin = 0,len(dh)
446 447 print('Directory history (kept in _dh)')
447 448 for i in range(ini, fin):
448 449 print("%d: %s" % (i, dh[i]))
449 450
450 451 @skip_doctest
451 452 @line_magic
452 453 def sc(self, parameter_s=''):
453 454 """Shell capture - run shell command and capture output (DEPRECATED use !).
454 455
455 456 DEPRECATED. Suboptimal, retained for backwards compatibility.
456 457
457 458 You should use the form 'var = !command' instead. Example:
458 459
459 460 "%sc -l myfiles = ls ~" should now be written as
460 461
461 462 "myfiles = !ls ~"
462 463
463 464 myfiles.s, myfiles.l and myfiles.n still apply as documented
464 465 below.
465 466
466 467 --
467 468 %sc [options] varname=command
468 469
469 470 IPython will run the given command using commands.getoutput(), and
470 471 will then update the user's interactive namespace with a variable
471 472 called varname, containing the value of the call. Your command can
472 473 contain shell wildcards, pipes, etc.
473 474
474 475 The '=' sign in the syntax is mandatory, and the variable name you
475 476 supply must follow Python's standard conventions for valid names.
476 477
477 478 (A special format without variable name exists for internal use)
478 479
479 480 Options:
480 481
481 482 -l: list output. Split the output on newlines into a list before
482 483 assigning it to the given variable. By default the output is stored
483 484 as a single string.
484 485
485 486 -v: verbose. Print the contents of the variable.
486 487
487 488 In most cases you should not need to split as a list, because the
488 489 returned value is a special type of string which can automatically
489 490 provide its contents either as a list (split on newlines) or as a
490 491 space-separated string. These are convenient, respectively, either
491 492 for sequential processing or to be passed to a shell command.
492 493
493 494 For example::
494 495
495 496 # Capture into variable a
496 497 In [1]: sc a=ls *py
497 498
498 499 # a is a string with embedded newlines
499 500 In [2]: a
500 501 Out[2]: 'setup.py\\nwin32_manual_post_install.py'
501 502
502 503 # which can be seen as a list:
503 504 In [3]: a.l
504 505 Out[3]: ['setup.py', 'win32_manual_post_install.py']
505 506
506 507 # or as a whitespace-separated string:
507 508 In [4]: a.s
508 509 Out[4]: 'setup.py win32_manual_post_install.py'
509 510
510 511 # a.s is useful to pass as a single command line:
511 512 In [5]: !wc -l $a.s
512 513 146 setup.py
513 514 130 win32_manual_post_install.py
514 515 276 total
515 516
516 517 # while the list form is useful to loop over:
517 518 In [6]: for f in a.l:
518 519 ...: !wc -l $f
519 520 ...:
520 521 146 setup.py
521 522 130 win32_manual_post_install.py
522 523
523 524 Similarly, the lists returned by the -l option are also special, in
524 525 the sense that you can equally invoke the .s attribute on them to
525 526 automatically get a whitespace-separated string from their contents::
526 527
527 528 In [7]: sc -l b=ls *py
528 529
529 530 In [8]: b
530 531 Out[8]: ['setup.py', 'win32_manual_post_install.py']
531 532
532 533 In [9]: b.s
533 534 Out[9]: 'setup.py win32_manual_post_install.py'
534 535
535 536 In summary, both the lists and strings used for output capture have
536 537 the following special attributes::
537 538
538 539 .l (or .list) : value as list.
539 540 .n (or .nlstr): value as newline-separated string.
540 541 .s (or .spstr): value as space-separated string.
541 542 """
542 543
543 544 opts,args = self.parse_options(parameter_s, 'lv')
544 545 # Try to get a variable name and command to run
545 546 try:
546 547 # the variable name must be obtained from the parse_options
547 548 # output, which uses shlex.split to strip options out.
548 549 var,_ = args.split('=', 1)
549 550 var = var.strip()
550 551 # But the command has to be extracted from the original input
551 552 # parameter_s, not on what parse_options returns, to avoid the
552 553 # quote stripping which shlex.split performs on it.
553 554 _,cmd = parameter_s.split('=', 1)
554 555 except ValueError:
555 556 var,cmd = '',''
556 557 # If all looks ok, proceed
557 558 split = 'l' in opts
558 559 out = self.shell.getoutput(cmd, split=split)
559 560 if 'v' in opts:
560 561 print('%s ==\n%s' % (var, pformat(out)))
561 562 if var:
562 563 self.shell.user_ns.update({var:out})
563 564 else:
564 565 return out
565 566
566 567 @line_cell_magic
567 568 def sx(self, line='', cell=None):
568 569 """Shell execute - run shell command and capture output (!! is short-hand).
569 570
570 571 %sx command
571 572
572 573 IPython will run the given command using commands.getoutput(), and
573 574 return the result formatted as a list (split on '\\n'). Since the
574 575 output is _returned_, it will be stored in ipython's regular output
575 576 cache Out[N] and in the '_N' automatic variables.
576 577
577 578 Notes:
578 579
579 580 1) If an input line begins with '!!', then %sx is automatically
580 581 invoked. That is, while::
581 582
582 583 !ls
583 584
584 585 causes ipython to simply issue system('ls'), typing::
585 586
586 587 !!ls
587 588
588 589 is a shorthand equivalent to::
589 590
590 591 %sx ls
591 592
592 593 2) %sx differs from %sc in that %sx automatically splits into a list,
593 594 like '%sc -l'. The reason for this is to make it as easy as possible
594 595 to process line-oriented shell output via further python commands.
595 596 %sc is meant to provide much finer control, but requires more
596 597 typing.
597 598
598 599 3) Just like %sc -l, this is a list with special attributes:
599 600 ::
600 601
601 602 .l (or .list) : value as list.
602 603 .n (or .nlstr): value as newline-separated string.
603 604 .s (or .spstr): value as whitespace-separated string.
604 605
605 606 This is very useful when trying to use such lists as arguments to
606 607 system commands."""
607 608
608 609 if cell is None:
609 610 # line magic
610 611 return self.shell.getoutput(line)
611 612 else:
612 613 opts,args = self.parse_options(line, '', 'out=')
613 614 output = self.shell.getoutput(cell)
614 615 out_name = opts.get('out', opts.get('o'))
615 616 if out_name:
616 617 self.shell.user_ns[out_name] = output
617 618 else:
618 619 return output
619 620
620 621 system = line_cell_magic('system')(sx)
621 622 bang = cell_magic('!')(sx)
622 623
623 624 @line_magic
624 625 def bookmark(self, parameter_s=''):
625 626 """Manage IPython's bookmark system.
626 627
627 628 %bookmark <name> - set bookmark to current dir
628 629 %bookmark <name> <dir> - set bookmark to <dir>
629 630 %bookmark -l - list all bookmarks
630 631 %bookmark -d <name> - remove bookmark
631 632 %bookmark -r - remove all bookmarks
632 633
633 634 You can later on access a bookmarked folder with::
634 635
635 636 %cd -b <name>
636 637
637 638 or simply '%cd <name>' if there is no directory called <name> AND
638 639 there is such a bookmark defined.
639 640
640 641 Your bookmarks persist through IPython sessions, but they are
641 642 associated with each profile."""
642 643
643 644 opts,args = self.parse_options(parameter_s,'drl',mode='list')
644 645 if len(args) > 2:
645 646 raise UsageError("%bookmark: too many arguments")
646 647
647 648 bkms = self.shell.db.get('bookmarks',{})
648 649
649 650 if 'd' in opts:
650 651 try:
651 652 todel = args[0]
652 653 except IndexError:
653 654 raise UsageError(
654 655 "%bookmark -d: must provide a bookmark to delete")
655 656 else:
656 657 try:
657 658 del bkms[todel]
658 659 except KeyError:
659 660 raise UsageError(
660 661 "%%bookmark -d: Can't delete bookmark '%s'" % todel)
661 662
662 663 elif 'r' in opts:
663 664 bkms = {}
664 665 elif 'l' in opts:
665 666 bks = bkms.keys()
666 667 bks.sort()
667 668 if bks:
668 669 size = max(map(len, bks))
669 670 else:
670 671 size = 0
671 672 fmt = '%-'+str(size)+'s -> %s'
672 673 print('Current bookmarks:')
673 674 for bk in bks:
674 675 print(fmt % (bk, bkms[bk]))
675 676 else:
676 677 if not args:
677 678 raise UsageError("%bookmark: You must specify the bookmark name")
678 679 elif len(args)==1:
679 bkms[args[0]] = os.getcwdu()
680 bkms[args[0]] = py3compat.getcwd()
680 681 elif len(args)==2:
681 682 bkms[args[0]] = args[1]
682 683 self.shell.db['bookmarks'] = bkms
683 684
684 685 @line_magic
685 686 def pycat(self, parameter_s=''):
686 687 """Show a syntax-highlighted file through a pager.
687 688
688 689 This magic is similar to the cat utility, but it will assume the file
689 690 to be Python source and will show it with syntax highlighting.
690 691
691 692 This magic command can either take a local filename, an url,
692 693 an history range (see %history) or a macro as argument ::
693 694
694 695 %pycat myscript.py
695 696 %pycat 7-27
696 697 %pycat myMacro
697 698 %pycat http://www.example.com/myscript.py
698 699 """
699 700 if not parameter_s:
700 701 raise UsageError('Missing filename, URL, input history range, '
701 702 'or macro.')
702 703
703 704 try :
704 705 cont = self.shell.find_user_code(parameter_s, skip_encoding_cookie=False)
705 706 except (ValueError, IOError):
706 707 print("Error: no such file, variable, URL, history range or macro")
707 708 return
708 709
709 710 page.page(self.shell.pycolorize(source_to_unicode(cont)))
710 711
711 712 @magic_arguments.magic_arguments()
712 713 @magic_arguments.argument(
713 714 '-a', '--append', action='store_true', default=False,
714 715 help='Append contents of the cell to an existing file. '
715 716 'The file will be created if it does not exist.'
716 717 )
717 718 @magic_arguments.argument(
718 719 'filename', type=unicode_type,
719 720 help='file to write'
720 721 )
721 722 @cell_magic
722 723 def writefile(self, line, cell):
723 724 """Write the contents of the cell to a file.
724 725
725 726 The file will be overwritten unless the -a (--append) flag is specified.
726 727 """
727 728 args = magic_arguments.parse_argstring(self.writefile, line)
728 729 filename = os.path.expanduser(unquote_filename(args.filename))
729 730
730 731 if os.path.exists(filename):
731 732 if args.append:
732 733 print("Appending to %s" % filename)
733 734 else:
734 735 print("Overwriting %s" % filename)
735 736 else:
736 737 print("Writing %s" % filename)
737 738
738 739 mode = 'a' if args.append else 'w'
739 740 with io.open(filename, mode, encoding='utf-8') as f:
740 741 f.write(cell)
@@ -1,314 +1,315 b''
1 1 # encoding: utf-8
2 2 """
3 3 An application for managing IPython profiles.
4 4
5 5 To be invoked as the `ipython profile` subcommand.
6 6
7 7 Authors:
8 8
9 9 * Min RK
10 10
11 11 """
12 12 from __future__ import print_function
13 13
14 14 #-----------------------------------------------------------------------------
15 15 # Copyright (C) 2008 The IPython Development Team
16 16 #
17 17 # Distributed under the terms of the BSD License. The full license is in
18 18 # the file COPYING, distributed as part of this software.
19 19 #-----------------------------------------------------------------------------
20 20
21 21 #-----------------------------------------------------------------------------
22 22 # Imports
23 23 #-----------------------------------------------------------------------------
24 24
25 25 import os
26 26
27 27 from IPython.config.application import Application
28 28 from IPython.core.application import (
29 29 BaseIPythonApplication, base_flags
30 30 )
31 31 from IPython.core.profiledir import ProfileDir
32 32 from IPython.utils.importstring import import_item
33 33 from IPython.utils.path import get_ipython_dir, get_ipython_package_dir
34 from IPython.utils import py3compat
34 35 from IPython.utils.traitlets import Unicode, Bool, Dict
35 36
36 37 #-----------------------------------------------------------------------------
37 38 # Constants
38 39 #-----------------------------------------------------------------------------
39 40
40 41 create_help = """Create an IPython profile by name
41 42
42 43 Create an ipython profile directory by its name or
43 44 profile directory path. Profile directories contain
44 45 configuration, log and security related files and are named
45 46 using the convention 'profile_<name>'. By default they are
46 47 located in your ipython directory. Once created, you will
47 48 can edit the configuration files in the profile
48 49 directory to configure IPython. Most users will create a
49 50 profile directory by name,
50 51 `ipython profile create myprofile`, which will put the directory
51 52 in `<ipython_dir>/profile_myprofile`.
52 53 """
53 54 list_help = """List available IPython profiles
54 55
55 56 List all available profiles, by profile location, that can
56 57 be found in the current working directly or in the ipython
57 58 directory. Profile directories are named using the convention
58 59 'profile_<profile>'.
59 60 """
60 61 profile_help = """Manage IPython profiles
61 62
62 63 Profile directories contain
63 64 configuration, log and security related files and are named
64 65 using the convention 'profile_<name>'. By default they are
65 66 located in your ipython directory. You can create profiles
66 67 with `ipython profile create <name>`, or see the profiles you
67 68 already have with `ipython profile list`
68 69
69 70 To get started configuring IPython, simply do:
70 71
71 72 $> ipython profile create
72 73
73 74 and IPython will create the default profile in <ipython_dir>/profile_default,
74 75 where you can edit ipython_config.py to start configuring IPython.
75 76
76 77 """
77 78
78 79 _list_examples = "ipython profile list # list all profiles"
79 80
80 81 _create_examples = """
81 82 ipython profile create foo # create profile foo w/ default config files
82 83 ipython profile create foo --reset # restage default config files over current
83 84 ipython profile create foo --parallel # also stage parallel config files
84 85 """
85 86
86 87 _main_examples = """
87 88 ipython profile create -h # show the help string for the create subcommand
88 89 ipython profile list -h # show the help string for the list subcommand
89 90
90 91 ipython locate profile foo # print the path to the directory for profile 'foo'
91 92 """
92 93
93 94 #-----------------------------------------------------------------------------
94 95 # Profile Application Class (for `ipython profile` subcommand)
95 96 #-----------------------------------------------------------------------------
96 97
97 98
98 99 def list_profiles_in(path):
99 100 """list profiles in a given root directory"""
100 101 files = os.listdir(path)
101 102 profiles = []
102 103 for f in files:
103 104 try:
104 105 full_path = os.path.join(path, f)
105 106 except UnicodeError:
106 107 continue
107 108 if os.path.isdir(full_path) and f.startswith('profile_'):
108 109 profiles.append(f.split('_',1)[-1])
109 110 return profiles
110 111
111 112
112 113 def list_bundled_profiles():
113 114 """list profiles that are bundled with IPython."""
114 115 path = os.path.join(get_ipython_package_dir(), u'config', u'profile')
115 116 files = os.listdir(path)
116 117 profiles = []
117 118 for profile in files:
118 119 full_path = os.path.join(path, profile)
119 120 if os.path.isdir(full_path) and profile != "__pycache__":
120 121 profiles.append(profile)
121 122 return profiles
122 123
123 124
124 125 class ProfileLocate(BaseIPythonApplication):
125 126 description = """print the path to an IPython profile dir"""
126 127
127 128 def parse_command_line(self, argv=None):
128 129 super(ProfileLocate, self).parse_command_line(argv)
129 130 if self.extra_args:
130 131 self.profile = self.extra_args[0]
131 132
132 133 def start(self):
133 134 print(self.profile_dir.location)
134 135
135 136
136 137 class ProfileList(Application):
137 138 name = u'ipython-profile'
138 139 description = list_help
139 140 examples = _list_examples
140 141
141 142 aliases = Dict({
142 143 'ipython-dir' : 'ProfileList.ipython_dir',
143 144 'log-level' : 'Application.log_level',
144 145 })
145 146 flags = Dict(dict(
146 147 debug = ({'Application' : {'log_level' : 0}},
147 148 "Set Application.log_level to 0, maximizing log output."
148 149 )
149 150 ))
150 151
151 152 ipython_dir = Unicode(get_ipython_dir(), config=True,
152 153 help="""
153 154 The name of the IPython directory. This directory is used for logging
154 155 configuration (through profiles), history storage, etc. The default
155 156 is usually $HOME/.ipython. This options can also be specified through
156 157 the environment variable IPYTHONDIR.
157 158 """
158 159 )
159 160
160 161
161 162 def _print_profiles(self, profiles):
162 163 """print list of profiles, indented."""
163 164 for profile in profiles:
164 165 print(' %s' % profile)
165 166
166 167 def list_profile_dirs(self):
167 168 profiles = list_bundled_profiles()
168 169 if profiles:
169 170 print()
170 171 print("Available profiles in IPython:")
171 172 self._print_profiles(profiles)
172 173 print()
173 174 print(" The first request for a bundled profile will copy it")
174 175 print(" into your IPython directory (%s)," % self.ipython_dir)
175 176 print(" where you can customize it.")
176 177
177 178 profiles = list_profiles_in(self.ipython_dir)
178 179 if profiles:
179 180 print()
180 181 print("Available profiles in %s:" % self.ipython_dir)
181 182 self._print_profiles(profiles)
182 183
183 profiles = list_profiles_in(os.getcwdu())
184 profiles = list_profiles_in(py3compat.getcwd())
184 185 if profiles:
185 186 print()
186 print("Available profiles in current directory (%s):" % os.getcwdu())
187 print("Available profiles in current directory (%s):" % py3compat.getcwd())
187 188 self._print_profiles(profiles)
188 189
189 190 print()
190 191 print("To use any of the above profiles, start IPython with:")
191 192 print(" ipython --profile=<name>")
192 193 print()
193 194
194 195 def start(self):
195 196 self.list_profile_dirs()
196 197
197 198
198 199 create_flags = {}
199 200 create_flags.update(base_flags)
200 201 # don't include '--init' flag, which implies running profile create in other apps
201 202 create_flags.pop('init')
202 203 create_flags['reset'] = ({'ProfileCreate': {'overwrite' : True}},
203 204 "reset config files in this profile to the defaults.")
204 205 create_flags['parallel'] = ({'ProfileCreate': {'parallel' : True}},
205 206 "Include the config files for parallel "
206 207 "computing apps (ipengine, ipcontroller, etc.)")
207 208
208 209
209 210 class ProfileCreate(BaseIPythonApplication):
210 211 name = u'ipython-profile'
211 212 description = create_help
212 213 examples = _create_examples
213 214 auto_create = Bool(True, config=False)
214 215 def _log_format_default(self):
215 216 return "[%(name)s] %(message)s"
216 217
217 218 def _copy_config_files_default(self):
218 219 return True
219 220
220 221 parallel = Bool(False, config=True,
221 222 help="whether to include parallel computing config files")
222 223 def _parallel_changed(self, name, old, new):
223 224 parallel_files = [ 'ipcontroller_config.py',
224 225 'ipengine_config.py',
225 226 'ipcluster_config.py'
226 227 ]
227 228 if new:
228 229 for cf in parallel_files:
229 230 self.config_files.append(cf)
230 231 else:
231 232 for cf in parallel_files:
232 233 if cf in self.config_files:
233 234 self.config_files.remove(cf)
234 235
235 236 def parse_command_line(self, argv):
236 237 super(ProfileCreate, self).parse_command_line(argv)
237 238 # accept positional arg as profile name
238 239 if self.extra_args:
239 240 self.profile = self.extra_args[0]
240 241
241 242 flags = Dict(create_flags)
242 243
243 244 classes = [ProfileDir]
244 245
245 246 def _import_app(self, app_path):
246 247 """import an app class"""
247 248 app = None
248 249 name = app_path.rsplit('.', 1)[-1]
249 250 try:
250 251 app = import_item(app_path)
251 except ImportError as e:
252 except ImportError:
252 253 self.log.info("Couldn't import %s, config file will be excluded", name)
253 254 except Exception:
254 255 self.log.warn('Unexpected error importing %s', name, exc_info=True)
255 256 return app
256 257
257 258 def init_config_files(self):
258 259 super(ProfileCreate, self).init_config_files()
259 260 # use local imports, since these classes may import from here
260 261 from IPython.terminal.ipapp import TerminalIPythonApp
261 262 apps = [TerminalIPythonApp]
262 263 for app_path in (
263 264 'IPython.qt.console.qtconsoleapp.IPythonQtConsoleApp',
264 265 'IPython.html.notebookapp.NotebookApp',
265 266 'IPython.nbconvert.nbconvertapp.NbConvertApp',
266 267 ):
267 268 app = self._import_app(app_path)
268 269 if app is not None:
269 270 apps.append(app)
270 271 if self.parallel:
271 272 from IPython.parallel.apps.ipcontrollerapp import IPControllerApp
272 273 from IPython.parallel.apps.ipengineapp import IPEngineApp
273 274 from IPython.parallel.apps.ipclusterapp import IPClusterStart
274 275 from IPython.parallel.apps.iploggerapp import IPLoggerApp
275 276 apps.extend([
276 277 IPControllerApp,
277 278 IPEngineApp,
278 279 IPClusterStart,
279 280 IPLoggerApp,
280 281 ])
281 282 for App in apps:
282 283 app = App()
283 284 app.config.update(self.config)
284 285 app.log = self.log
285 286 app.overwrite = self.overwrite
286 287 app.copy_config_files=True
287 288 app.profile = self.profile
288 289 app.init_profile_dir()
289 290 app.init_config_files()
290 291
291 292 def stage_default_config_file(self):
292 293 pass
293 294
294 295
295 296 class ProfileApp(Application):
296 297 name = u'ipython-profile'
297 298 description = profile_help
298 299 examples = _main_examples
299 300
300 301 subcommands = Dict(dict(
301 302 create = (ProfileCreate, ProfileCreate.description.splitlines()[0]),
302 303 list = (ProfileList, ProfileList.description.splitlines()[0]),
303 304 locate = (ProfileLocate, ProfileLocate.description.splitlines()[0]),
304 305 ))
305 306
306 307 def start(self):
307 308 if self.subapp is None:
308 309 print("No subcommand specified. Must specify one of: %s"%(self.subcommands.keys()))
309 310 print()
310 311 self.print_description()
311 312 self.print_subcommands()
312 313 self.exit(1)
313 314 else:
314 315 return self.subapp.start()
@@ -1,273 +1,274 b''
1 1 # encoding: utf-8
2 2 """
3 3 An object for managing IPython profile directories.
4 4
5 5 Authors:
6 6
7 7 * Brian Granger
8 8 * Fernando Perez
9 9 * Min RK
10 10
11 11 """
12 12
13 13 #-----------------------------------------------------------------------------
14 14 # Copyright (C) 2011 The IPython Development Team
15 15 #
16 16 # Distributed under the terms of the BSD License. The full license is in
17 17 # the file COPYING, distributed as part of this software.
18 18 #-----------------------------------------------------------------------------
19 19
20 20 #-----------------------------------------------------------------------------
21 21 # Imports
22 22 #-----------------------------------------------------------------------------
23 23
24 24 import os
25 25 import shutil
26 26 import errno
27 27
28 28 from IPython.config.configurable import LoggingConfigurable
29 29 from IPython.utils.path import get_ipython_package_dir, expand_path
30 from IPython.utils import py3compat
30 31 from IPython.utils.traitlets import Unicode, Bool
31 32
32 33 #-----------------------------------------------------------------------------
33 34 # Classes and functions
34 35 #-----------------------------------------------------------------------------
35 36
36 37
37 38 #-----------------------------------------------------------------------------
38 39 # Module errors
39 40 #-----------------------------------------------------------------------------
40 41
41 42 class ProfileDirError(Exception):
42 43 pass
43 44
44 45
45 46 #-----------------------------------------------------------------------------
46 47 # Class for managing profile directories
47 48 #-----------------------------------------------------------------------------
48 49
49 50 class ProfileDir(LoggingConfigurable):
50 51 """An object to manage the profile directory and its resources.
51 52
52 53 The profile directory is used by all IPython applications, to manage
53 54 configuration, logging and security.
54 55
55 56 This object knows how to find, create and manage these directories. This
56 57 should be used by any code that wants to handle profiles.
57 58 """
58 59
59 60 security_dir_name = Unicode('security')
60 61 log_dir_name = Unicode('log')
61 62 startup_dir_name = Unicode('startup')
62 63 pid_dir_name = Unicode('pid')
63 64 static_dir_name = Unicode('static')
64 65 security_dir = Unicode(u'')
65 66 log_dir = Unicode(u'')
66 67 startup_dir = Unicode(u'')
67 68 pid_dir = Unicode(u'')
68 69 static_dir = Unicode(u'')
69 70
70 71 location = Unicode(u'', config=True,
71 72 help="""Set the profile location directly. This overrides the logic used by the
72 73 `profile` option.""",
73 74 )
74 75
75 76 _location_isset = Bool(False) # flag for detecting multiply set location
76 77
77 78 def _location_changed(self, name, old, new):
78 79 if self._location_isset:
79 80 raise RuntimeError("Cannot set profile location more than once.")
80 81 self._location_isset = True
81 82 if not os.path.isdir(new):
82 83 os.makedirs(new)
83 84
84 85 # ensure config files exist:
85 86 self.security_dir = os.path.join(new, self.security_dir_name)
86 87 self.log_dir = os.path.join(new, self.log_dir_name)
87 88 self.startup_dir = os.path.join(new, self.startup_dir_name)
88 89 self.pid_dir = os.path.join(new, self.pid_dir_name)
89 90 self.static_dir = os.path.join(new, self.static_dir_name)
90 91 self.check_dirs()
91 92
92 93 def _log_dir_changed(self, name, old, new):
93 94 self.check_log_dir()
94 95
95 96 def _mkdir(self, path, mode=None):
96 97 """ensure a directory exists at a given path
97 98
98 99 This is a version of os.mkdir, with the following differences:
99 100
100 101 - returns True if it created the directory, False otherwise
101 102 - ignores EEXIST, protecting against race conditions where
102 103 the dir may have been created in between the check and
103 104 the creation
104 105 - sets permissions if requested and the dir already exists
105 106 """
106 107 if os.path.exists(path):
107 108 if mode and os.stat(path).st_mode != mode:
108 109 try:
109 110 os.chmod(path, mode)
110 111 except OSError:
111 112 self.log.warn(
112 113 "Could not set permissions on %s",
113 114 path
114 115 )
115 116 return False
116 117 try:
117 118 if mode:
118 119 os.mkdir(path, mode)
119 120 else:
120 121 os.mkdir(path)
121 122 except OSError as e:
122 123 if e.errno == errno.EEXIST:
123 124 return False
124 125 else:
125 126 raise
126 127
127 128 return True
128 129
129 130 def check_log_dir(self):
130 131 self._mkdir(self.log_dir)
131 132
132 133 def _startup_dir_changed(self, name, old, new):
133 134 self.check_startup_dir()
134 135
135 136 def check_startup_dir(self):
136 137 self._mkdir(self.startup_dir)
137 138
138 139 readme = os.path.join(self.startup_dir, 'README')
139 140 src = os.path.join(get_ipython_package_dir(), u'config', u'profile', u'README_STARTUP')
140 141
141 142 if not os.path.exists(src):
142 143 self.log.warn("Could not copy README_STARTUP to startup dir. Source file %s does not exist.", src)
143 144
144 145 if os.path.exists(src) and not os.path.exists(readme):
145 146 shutil.copy(src, readme)
146 147
147 148 def _security_dir_changed(self, name, old, new):
148 149 self.check_security_dir()
149 150
150 151 def check_security_dir(self):
151 152 self._mkdir(self.security_dir, 0o40700)
152 153
153 154 def _pid_dir_changed(self, name, old, new):
154 155 self.check_pid_dir()
155 156
156 157 def check_pid_dir(self):
157 158 self._mkdir(self.pid_dir, 0o40700)
158 159
159 160 def _static_dir_changed(self, name, old, new):
160 161 self.check_startup_dir()
161 162
162 163 def check_static_dir(self):
163 164 self._mkdir(self.static_dir)
164 165 custom = os.path.join(self.static_dir, 'custom')
165 166 self._mkdir(custom)
166 167 from IPython.html import DEFAULT_STATIC_FILES_PATH
167 168 for fname in ('custom.js', 'custom.css'):
168 169 src = os.path.join(DEFAULT_STATIC_FILES_PATH, 'custom', fname)
169 170 dest = os.path.join(custom, fname)
170 171 if not os.path.exists(src):
171 172 self.log.warn("Could not copy default file to static dir. Source file %s does not exist.", src)
172 173 continue
173 174 if not os.path.exists(dest):
174 175 shutil.copy(src, dest)
175 176
176 177 def check_dirs(self):
177 178 self.check_security_dir()
178 179 self.check_log_dir()
179 180 self.check_pid_dir()
180 181 self.check_startup_dir()
181 182 self.check_static_dir()
182 183
183 184 def copy_config_file(self, config_file, path=None, overwrite=False):
184 185 """Copy a default config file into the active profile directory.
185 186
186 187 Default configuration files are kept in :mod:`IPython.config.default`.
187 188 This function moves these from that location to the working profile
188 189 directory.
189 190 """
190 191 dst = os.path.join(self.location, config_file)
191 192 if os.path.isfile(dst) and not overwrite:
192 193 return False
193 194 if path is None:
194 195 path = os.path.join(get_ipython_package_dir(), u'config', u'profile', u'default')
195 196 src = os.path.join(path, config_file)
196 197 shutil.copy(src, dst)
197 198 return True
198 199
199 200 @classmethod
200 201 def create_profile_dir(cls, profile_dir, config=None):
201 202 """Create a new profile directory given a full path.
202 203
203 204 Parameters
204 205 ----------
205 206 profile_dir : str
206 207 The full path to the profile directory. If it does exist, it will
207 208 be used. If not, it will be created.
208 209 """
209 210 return cls(location=profile_dir, config=config)
210 211
211 212 @classmethod
212 213 def create_profile_dir_by_name(cls, path, name=u'default', config=None):
213 214 """Create a profile dir by profile name and path.
214 215
215 216 Parameters
216 217 ----------
217 218 path : unicode
218 219 The path (directory) to put the profile directory in.
219 220 name : unicode
220 221 The name of the profile. The name of the profile directory will
221 222 be "profile_<profile>".
222 223 """
223 224 if not os.path.isdir(path):
224 225 raise ProfileDirError('Directory not found: %s' % path)
225 226 profile_dir = os.path.join(path, u'profile_' + name)
226 227 return cls(location=profile_dir, config=config)
227 228
228 229 @classmethod
229 230 def find_profile_dir_by_name(cls, ipython_dir, name=u'default', config=None):
230 231 """Find an existing profile dir by profile name, return its ProfileDir.
231 232
232 233 This searches through a sequence of paths for a profile dir. If it
233 234 is not found, a :class:`ProfileDirError` exception will be raised.
234 235
235 236 The search path algorithm is:
236 1. ``os.getcwdu()``
237 1. ``py3compat.getcwd()``
237 238 2. ``ipython_dir``
238 239
239 240 Parameters
240 241 ----------
241 242 ipython_dir : unicode or str
242 243 The IPython directory to use.
243 244 name : unicode or str
244 245 The name of the profile. The name of the profile directory
245 246 will be "profile_<profile>".
246 247 """
247 248 dirname = u'profile_' + name
248 paths = [os.getcwdu(), ipython_dir]
249 paths = [py3compat.getcwd(), ipython_dir]
249 250 for p in paths:
250 251 profile_dir = os.path.join(p, dirname)
251 252 if os.path.isdir(profile_dir):
252 253 return cls(location=profile_dir, config=config)
253 254 else:
254 255 raise ProfileDirError('Profile directory not found in paths: %s' % dirname)
255 256
256 257 @classmethod
257 258 def find_profile_dir(cls, profile_dir, config=None):
258 259 """Find/create a profile dir and return its ProfileDir.
259 260
260 261 This will create the profile directory if it doesn't exist.
261 262
262 263 Parameters
263 264 ----------
264 265 profile_dir : unicode or str
265 266 The path of the profile directory. This is expanded using
266 267 :func:`IPython.utils.genutils.expand_path`.
267 268 """
268 269 profile_dir = expand_path(profile_dir)
269 270 if not os.path.isdir(profile_dir):
270 271 raise ProfileDirError('Profile directory not found: %s' % profile_dir)
271 272 return cls(location=profile_dir, config=config)
272 273
273 274
@@ -1,439 +1,439 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Classes for handling input/output prompts.
3 3
4 4 Authors:
5 5
6 6 * Fernando Perez
7 7 * Brian Granger
8 8 * Thomas Kluyver
9 9 """
10 10
11 11 #-----------------------------------------------------------------------------
12 12 # Copyright (C) 2008-2011 The IPython Development Team
13 13 # Copyright (C) 2001-2007 Fernando Perez <fperez@colorado.edu>
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 import os
24 24 import re
25 25 import socket
26 26 import sys
27 27 import time
28 28
29 29 from string import Formatter
30 30
31 31 from IPython.config.configurable import Configurable
32 32 from IPython.core import release
33 33 from IPython.utils import coloransi, py3compat
34 34 from IPython.utils.traitlets import (Unicode, Instance, Dict, Bool, Int)
35 35
36 36 #-----------------------------------------------------------------------------
37 37 # Color schemes for prompts
38 38 #-----------------------------------------------------------------------------
39 39
40 40 InputColors = coloransi.InputTermColors # just a shorthand
41 41 Colors = coloransi.TermColors # just a shorthand
42 42
43 43 color_lists = dict(normal=Colors(), inp=InputColors(), nocolor=coloransi.NoColors())
44 44
45 45 PColNoColors = coloransi.ColorScheme(
46 46 'NoColor',
47 47 in_prompt = InputColors.NoColor, # Input prompt
48 48 in_number = InputColors.NoColor, # Input prompt number
49 49 in_prompt2 = InputColors.NoColor, # Continuation prompt
50 50 in_normal = InputColors.NoColor, # color off (usu. Colors.Normal)
51 51
52 52 out_prompt = Colors.NoColor, # Output prompt
53 53 out_number = Colors.NoColor, # Output prompt number
54 54
55 55 normal = Colors.NoColor # color off (usu. Colors.Normal)
56 56 )
57 57
58 58 # make some schemes as instances so we can copy them for modification easily:
59 59 PColLinux = coloransi.ColorScheme(
60 60 'Linux',
61 61 in_prompt = InputColors.Green,
62 62 in_number = InputColors.LightGreen,
63 63 in_prompt2 = InputColors.Green,
64 64 in_normal = InputColors.Normal, # color off (usu. Colors.Normal)
65 65
66 66 out_prompt = Colors.Red,
67 67 out_number = Colors.LightRed,
68 68
69 69 normal = Colors.Normal
70 70 )
71 71
72 72 # Slightly modified Linux for light backgrounds
73 73 PColLightBG = PColLinux.copy('LightBG')
74 74
75 75 PColLightBG.colors.update(
76 76 in_prompt = InputColors.Blue,
77 77 in_number = InputColors.LightBlue,
78 78 in_prompt2 = InputColors.Blue
79 79 )
80 80
81 81 #-----------------------------------------------------------------------------
82 82 # Utilities
83 83 #-----------------------------------------------------------------------------
84 84
85 85 class LazyEvaluate(object):
86 86 """This is used for formatting strings with values that need to be updated
87 87 at that time, such as the current time or working directory."""
88 88 def __init__(self, func, *args, **kwargs):
89 89 self.func = func
90 90 self.args = args
91 91 self.kwargs = kwargs
92 92
93 93 def __call__(self, **kwargs):
94 94 self.kwargs.update(kwargs)
95 95 return self.func(*self.args, **self.kwargs)
96 96
97 97 def __str__(self):
98 98 return str(self())
99 99
100 100 def __unicode__(self):
101 101 return py3compat.unicode_type(self())
102 102
103 103 def __format__(self, format_spec):
104 104 return format(self(), format_spec)
105 105
106 106 def multiple_replace(dict, text):
107 107 """ Replace in 'text' all occurences of any key in the given
108 108 dictionary by its corresponding value. Returns the new string."""
109 109
110 110 # Function by Xavier Defrang, originally found at:
111 111 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/81330
112 112
113 113 # Create a regular expression from the dictionary keys
114 114 regex = re.compile("(%s)" % "|".join(map(re.escape, dict.keys())))
115 115 # For each match, look-up corresponding value in dictionary
116 116 return regex.sub(lambda mo: dict[mo.string[mo.start():mo.end()]], text)
117 117
118 118 #-----------------------------------------------------------------------------
119 119 # Special characters that can be used in prompt templates, mainly bash-like
120 120 #-----------------------------------------------------------------------------
121 121
122 122 # If $HOME isn't defined (Windows), make it an absurd string so that it can
123 123 # never be expanded out into '~'. Basically anything which can never be a
124 124 # reasonable directory name will do, we just want the $HOME -> '~' operation
125 125 # to become a no-op. We pre-compute $HOME here so it's not done on every
126 126 # prompt call.
127 127
128 128 # FIXME:
129 129
130 130 # - This should be turned into a class which does proper namespace management,
131 131 # since the prompt specials need to be evaluated in a certain namespace.
132 132 # Currently it's just globals, which need to be managed manually by code
133 133 # below.
134 134
135 135 # - I also need to split up the color schemes from the prompt specials
136 136 # somehow. I don't have a clean design for that quite yet.
137 137
138 138 HOME = py3compat.str_to_unicode(os.environ.get("HOME","//////:::::ZZZZZ,,,~~~"))
139 139
140 140 # This is needed on FreeBSD, and maybe other systems which symlink /home to
141 141 # /usr/home, but retain the $HOME variable as pointing to /home
142 142 HOME = os.path.realpath(HOME)
143 143
144 144 # We precompute a few more strings here for the prompt_specials, which are
145 145 # fixed once ipython starts. This reduces the runtime overhead of computing
146 146 # prompt strings.
147 147 USER = py3compat.str_to_unicode(os.environ.get("USER",''))
148 148 HOSTNAME = py3compat.str_to_unicode(socket.gethostname())
149 149 HOSTNAME_SHORT = HOSTNAME.split(".")[0]
150 150 ROOT_SYMBOL = "#" if (os.name=='nt' or os.getuid()==0) else "$"
151 151
152 152 prompt_abbreviations = {
153 153 # Prompt/history count
154 154 '%n' : '{color.number}' '{count}' '{color.prompt}',
155 155 r'\#': '{color.number}' '{count}' '{color.prompt}',
156 156 # Just the prompt counter number, WITHOUT any coloring wrappers, so users
157 157 # can get numbers displayed in whatever color they want.
158 158 r'\N': '{count}',
159 159
160 160 # Prompt/history count, with the actual digits replaced by dots. Used
161 161 # mainly in continuation prompts (prompt_in2)
162 162 r'\D': '{dots}',
163 163
164 164 # Current time
165 165 r'\T' : '{time}',
166 166 # Current working directory
167 167 r'\w': '{cwd}',
168 168 # Basename of current working directory.
169 169 # (use os.sep to make this portable across OSes)
170 170 r'\W' : '{cwd_last}',
171 171 # These X<N> are an extension to the normal bash prompts. They return
172 172 # N terms of the path, after replacing $HOME with '~'
173 173 r'\X0': '{cwd_x[0]}',
174 174 r'\X1': '{cwd_x[1]}',
175 175 r'\X2': '{cwd_x[2]}',
176 176 r'\X3': '{cwd_x[3]}',
177 177 r'\X4': '{cwd_x[4]}',
178 178 r'\X5': '{cwd_x[5]}',
179 179 # Y<N> are similar to X<N>, but they show '~' if it's the directory
180 180 # N+1 in the list. Somewhat like %cN in tcsh.
181 181 r'\Y0': '{cwd_y[0]}',
182 182 r'\Y1': '{cwd_y[1]}',
183 183 r'\Y2': '{cwd_y[2]}',
184 184 r'\Y3': '{cwd_y[3]}',
185 185 r'\Y4': '{cwd_y[4]}',
186 186 r'\Y5': '{cwd_y[5]}',
187 187 # Hostname up to first .
188 188 r'\h': HOSTNAME_SHORT,
189 189 # Full hostname
190 190 r'\H': HOSTNAME,
191 191 # Username of current user
192 192 r'\u': USER,
193 193 # Escaped '\'
194 194 '\\\\': '\\',
195 195 # Newline
196 196 r'\n': '\n',
197 197 # Carriage return
198 198 r'\r': '\r',
199 199 # Release version
200 200 r'\v': release.version,
201 201 # Root symbol ($ or #)
202 202 r'\$': ROOT_SYMBOL,
203 203 }
204 204
205 205 #-----------------------------------------------------------------------------
206 206 # More utilities
207 207 #-----------------------------------------------------------------------------
208 208
209 209 def cwd_filt(depth):
210 210 """Return the last depth elements of the current working directory.
211 211
212 212 $HOME is always replaced with '~'.
213 213 If depth==0, the full path is returned."""
214 214
215 cwd = os.getcwdu().replace(HOME,"~")
215 cwd = py3compat.getcwd().replace(HOME,"~")
216 216 out = os.sep.join(cwd.split(os.sep)[-depth:])
217 217 return out or os.sep
218 218
219 219 def cwd_filt2(depth):
220 220 """Return the last depth elements of the current working directory.
221 221
222 222 $HOME is always replaced with '~'.
223 223 If depth==0, the full path is returned."""
224 224
225 full_cwd = os.getcwdu()
225 full_cwd = py3compat.getcwd()
226 226 cwd = full_cwd.replace(HOME,"~").split(os.sep)
227 227 if '~' in cwd and len(cwd) == depth+1:
228 228 depth += 1
229 229 drivepart = ''
230 230 if sys.platform == 'win32' and len(cwd) > depth:
231 231 drivepart = os.path.splitdrive(full_cwd)[0]
232 232 out = drivepart + '/'.join(cwd[-depth:])
233 233
234 234 return out or os.sep
235 235
236 236 #-----------------------------------------------------------------------------
237 237 # Prompt classes
238 238 #-----------------------------------------------------------------------------
239 239
240 240 lazily_evaluate = {'time': LazyEvaluate(time.strftime, "%H:%M:%S"),
241 'cwd': LazyEvaluate(os.getcwdu),
242 'cwd_last': LazyEvaluate(lambda: os.getcwdu().split(os.sep)[-1]),
243 'cwd_x': [LazyEvaluate(lambda: os.getcwdu().replace(HOME,"~"))] +\
241 'cwd': LazyEvaluate(py3compat.getcwd),
242 'cwd_last': LazyEvaluate(lambda: py3compat.getcwd().split(os.sep)[-1]),
243 'cwd_x': [LazyEvaluate(lambda: py3compat.getcwd().replace(HOME,"~"))] +\
244 244 [LazyEvaluate(cwd_filt, x) for x in range(1,6)],
245 245 'cwd_y': [LazyEvaluate(cwd_filt2, x) for x in range(6)]
246 246 }
247 247
248 248 def _lenlastline(s):
249 249 """Get the length of the last line. More intelligent than
250 250 len(s.splitlines()[-1]).
251 251 """
252 252 if not s or s.endswith(('\n', '\r')):
253 253 return 0
254 254 return len(s.splitlines()[-1])
255 255
256 256
257 257 class UserNSFormatter(Formatter):
258 258 """A Formatter that falls back on a shell's user_ns and __builtins__ for name resolution"""
259 259 def __init__(self, shell):
260 260 self.shell = shell
261 261
262 262 def get_value(self, key, args, kwargs):
263 263 # try regular formatting first:
264 264 try:
265 265 return Formatter.get_value(self, key, args, kwargs)
266 266 except Exception:
267 267 pass
268 268 # next, look in user_ns and builtins:
269 269 for container in (self.shell.user_ns, __builtins__):
270 270 if key in container:
271 271 return container[key]
272 272 # nothing found, put error message in its place
273 273 return "<ERROR: '%s' not found>" % key
274 274
275 275
276 276 class PromptManager(Configurable):
277 277 """This is the primary interface for producing IPython's prompts."""
278 278 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
279 279
280 280 color_scheme_table = Instance(coloransi.ColorSchemeTable)
281 281 color_scheme = Unicode('Linux', config=True)
282 282 def _color_scheme_changed(self, name, new_value):
283 283 self.color_scheme_table.set_active_scheme(new_value)
284 284 for pname in ['in', 'in2', 'out', 'rewrite']:
285 285 # We need to recalculate the number of invisible characters
286 286 self.update_prompt(pname)
287 287
288 288 lazy_evaluate_fields = Dict(help="""
289 289 This maps field names used in the prompt templates to functions which
290 290 will be called when the prompt is rendered. This allows us to include
291 291 things like the current time in the prompts. Functions are only called
292 292 if they are used in the prompt.
293 293 """)
294 294 def _lazy_evaluate_fields_default(self): return lazily_evaluate.copy()
295 295
296 296 in_template = Unicode('In [\\#]: ', config=True,
297 297 help="Input prompt. '\\#' will be transformed to the prompt number")
298 298 in2_template = Unicode(' .\\D.: ', config=True,
299 299 help="Continuation prompt.")
300 300 out_template = Unicode('Out[\\#]: ', config=True,
301 301 help="Output prompt. '\\#' will be transformed to the prompt number")
302 302
303 303 justify = Bool(True, config=True, help="""
304 304 If True (default), each prompt will be right-aligned with the
305 305 preceding one.
306 306 """)
307 307
308 308 # We actually store the expanded templates here:
309 309 templates = Dict()
310 310
311 311 # The number of characters in the last prompt rendered, not including
312 312 # colour characters.
313 313 width = Int()
314 314 txtwidth = Int() # Not including right-justification
315 315
316 316 # The number of characters in each prompt which don't contribute to width
317 317 invisible_chars = Dict()
318 318 def _invisible_chars_default(self):
319 319 return {'in': 0, 'in2': 0, 'out': 0, 'rewrite':0}
320 320
321 321 def __init__(self, shell, **kwargs):
322 322 super(PromptManager, self).__init__(shell=shell, **kwargs)
323 323
324 324 # Prepare colour scheme table
325 325 self.color_scheme_table = coloransi.ColorSchemeTable([PColNoColors,
326 326 PColLinux, PColLightBG], self.color_scheme)
327 327
328 328 self._formatter = UserNSFormatter(shell)
329 329 # Prepare templates & numbers of invisible characters
330 330 self.update_prompt('in', self.in_template)
331 331 self.update_prompt('in2', self.in2_template)
332 332 self.update_prompt('out', self.out_template)
333 333 self.update_prompt('rewrite')
334 334 self.on_trait_change(self._update_prompt_trait, ['in_template',
335 335 'in2_template', 'out_template'])
336 336
337 337 def update_prompt(self, name, new_template=None):
338 338 """This is called when a prompt template is updated. It processes
339 339 abbreviations used in the prompt template (like \#) and calculates how
340 340 many invisible characters (ANSI colour escapes) the resulting prompt
341 341 contains.
342 342
343 343 It is also called for each prompt on changing the colour scheme. In both
344 344 cases, traitlets should take care of calling this automatically.
345 345 """
346 346 if new_template is not None:
347 347 self.templates[name] = multiple_replace(prompt_abbreviations, new_template)
348 348 # We count invisible characters (colour escapes) on the last line of the
349 349 # prompt, to calculate the width for lining up subsequent prompts.
350 350 invis_chars = _lenlastline(self._render(name, color=True)) - \
351 351 _lenlastline(self._render(name, color=False))
352 352 self.invisible_chars[name] = invis_chars
353 353
354 354 def _update_prompt_trait(self, traitname, new_template):
355 355 name = traitname[:-9] # Cut off '_template'
356 356 self.update_prompt(name, new_template)
357 357
358 358 def _render(self, name, color=True, **kwargs):
359 359 """Render but don't justify, or update the width or txtwidth attributes.
360 360 """
361 361 if name == 'rewrite':
362 362 return self._render_rewrite(color=color)
363 363
364 364 if color:
365 365 scheme = self.color_scheme_table.active_colors
366 366 if name=='out':
367 367 colors = color_lists['normal']
368 368 colors.number, colors.prompt, colors.normal = \
369 369 scheme.out_number, scheme.out_prompt, scheme.normal
370 370 else:
371 371 colors = color_lists['inp']
372 372 colors.number, colors.prompt, colors.normal = \
373 373 scheme.in_number, scheme.in_prompt, scheme.in_normal
374 374 if name=='in2':
375 375 colors.prompt = scheme.in_prompt2
376 376 else:
377 377 # No color
378 378 colors = color_lists['nocolor']
379 379 colors.number, colors.prompt, colors.normal = '', '', ''
380 380
381 381 count = self.shell.execution_count # Shorthand
382 382 # Build the dictionary to be passed to string formatting
383 383 fmtargs = dict(color=colors, count=count,
384 384 dots="."*len(str(count)),
385 385 width=self.width, txtwidth=self.txtwidth )
386 386 fmtargs.update(self.lazy_evaluate_fields)
387 387 fmtargs.update(kwargs)
388 388
389 389 # Prepare the prompt
390 390 prompt = colors.prompt + self.templates[name] + colors.normal
391 391
392 392 # Fill in required fields
393 393 return self._formatter.format(prompt, **fmtargs)
394 394
395 395 def _render_rewrite(self, color=True):
396 396 """Render the ---> rewrite prompt."""
397 397 if color:
398 398 scheme = self.color_scheme_table.active_colors
399 399 # We need a non-input version of these escapes
400 400 color_prompt = scheme.in_prompt.replace("\001","").replace("\002","")
401 401 color_normal = scheme.normal
402 402 else:
403 403 color_prompt, color_normal = '', ''
404 404
405 405 return color_prompt + "-> ".rjust(self.txtwidth, "-") + color_normal
406 406
407 407 def render(self, name, color=True, just=None, **kwargs):
408 408 """
409 409 Render the selected prompt.
410 410
411 411 Parameters
412 412 ----------
413 413 name : str
414 414 Which prompt to render. One of 'in', 'in2', 'out', 'rewrite'
415 415 color : bool
416 416 If True (default), include ANSI escape sequences for a coloured prompt.
417 417 just : bool
418 418 If True, justify the prompt to the width of the last prompt. The
419 419 default is stored in self.justify.
420 420 **kwargs :
421 421 Additional arguments will be passed to the string formatting operation,
422 422 so they can override the values that would otherwise fill in the
423 423 template.
424 424
425 425 Returns
426 426 -------
427 427 A string containing the rendered prompt.
428 428 """
429 429 res = self._render(name, color=color, **kwargs)
430 430
431 431 # Handle justification of prompt
432 432 invis_chars = self.invisible_chars[name] if color else 0
433 433 self.txtwidth = _lenlastline(res) - invis_chars
434 434 just = self.justify if (just is None) else just
435 435 # If the prompt spans more than one line, don't try to justify it:
436 436 if just and name != 'in' and ('\n' not in res) and ('\r' not in res):
437 437 res = res.rjust(self.width + invis_chars)
438 438 self.width = _lenlastline(res) - invis_chars
439 439 return res
@@ -1,50 +1,50 b''
1 1 # coding: utf-8
2 2 """Tests for IPython.core.application"""
3 3
4 4 import os
5 5 import tempfile
6 6
7 7 from IPython.core.application import BaseIPythonApplication
8 8 from IPython.testing import decorators as dec
9 9 from IPython.utils import py3compat
10 10
11 11 @dec.onlyif_unicode_paths
12 12 def test_unicode_cwd():
13 13 """Check that IPython starts with non-ascii characters in the path."""
14 14 wd = tempfile.mkdtemp(suffix=u"€")
15 15
16 old_wd = os.getcwdu()
16 old_wd = py3compat.getcwd()
17 17 os.chdir(wd)
18 #raise Exception(repr(os.getcwdu()))
18 #raise Exception(repr(py3compat.getcwd()))
19 19 try:
20 20 app = BaseIPythonApplication()
21 21 # The lines below are copied from Application.initialize()
22 22 app.init_profile_dir()
23 23 app.init_config_files()
24 24 app.load_config_file(suppress_errors=False)
25 25 finally:
26 26 os.chdir(old_wd)
27 27
28 28 @dec.onlyif_unicode_paths
29 29 def test_unicode_ipdir():
30 30 """Check that IPython starts with non-ascii characters in the IP dir."""
31 31 ipdir = tempfile.mkdtemp(suffix=u"€")
32 32
33 33 # Create the config file, so it tries to load it.
34 34 with open(os.path.join(ipdir, 'ipython_config.py'), "w") as f:
35 35 pass
36 36
37 37 old_ipdir1 = os.environ.pop("IPYTHONDIR", None)
38 38 old_ipdir2 = os.environ.pop("IPYTHON_DIR", None)
39 39 os.environ["IPYTHONDIR"] = py3compat.unicode_to_str(ipdir, "utf-8")
40 40 try:
41 41 app = BaseIPythonApplication()
42 42 # The lines below are copied from Application.initialize()
43 43 app.init_profile_dir()
44 44 app.init_config_files()
45 45 app.load_config_file(suppress_errors=False)
46 46 finally:
47 47 if old_ipdir1:
48 48 os.environ["IPYTHONDIR"] = old_ipdir1
49 49 if old_ipdir2:
50 50 os.environ["IPYTHONDIR"] = old_ipdir2
@@ -1,393 +1,394 b''
1 1 """Tests for the IPython tab-completion machinery.
2 2 """
3 3 #-----------------------------------------------------------------------------
4 4 # Module imports
5 5 #-----------------------------------------------------------------------------
6 6
7 7 # stdlib
8 8 import os
9 9 import sys
10 10 import unittest
11 11
12 12 # third party
13 13 import nose.tools as nt
14 14
15 15 # our own packages
16 16 from IPython.config.loader import Config
17 17 from IPython.core import completer
18 18 from IPython.external.decorators import knownfailureif
19 19 from IPython.utils.tempdir import TemporaryDirectory
20 20 from IPython.utils.generics import complete_object
21 from IPython.utils import py3compat
21 22 from IPython.utils.py3compat import string_types, unicode_type
22 23
23 24 #-----------------------------------------------------------------------------
24 25 # Test functions
25 26 #-----------------------------------------------------------------------------
26 27 def test_protect_filename():
27 28 pairs = [ ('abc','abc'),
28 29 (' abc',r'\ abc'),
29 30 ('a bc',r'a\ bc'),
30 31 ('a bc',r'a\ \ bc'),
31 32 (' bc',r'\ \ bc'),
32 33 ]
33 34 # On posix, we also protect parens and other special characters
34 35 if sys.platform != 'win32':
35 36 pairs.extend( [('a(bc',r'a\(bc'),
36 37 ('a)bc',r'a\)bc'),
37 38 ('a( )bc',r'a\(\ \)bc'),
38 39 ('a[1]bc', r'a\[1\]bc'),
39 40 ('a{1}bc', r'a\{1\}bc'),
40 41 ('a#bc', r'a\#bc'),
41 42 ('a?bc', r'a\?bc'),
42 43 ('a=bc', r'a\=bc'),
43 44 ('a\\bc', r'a\\bc'),
44 45 ('a|bc', r'a\|bc'),
45 46 ('a;bc', r'a\;bc'),
46 47 ('a:bc', r'a\:bc'),
47 48 ("a'bc", r"a\'bc"),
48 49 ('a*bc', r'a\*bc'),
49 50 ('a"bc', r'a\"bc'),
50 51 ('a^bc', r'a\^bc'),
51 52 ('a&bc', r'a\&bc'),
52 53 ] )
53 54 # run the actual tests
54 55 for s1, s2 in pairs:
55 56 s1p = completer.protect_filename(s1)
56 57 nt.assert_equal(s1p, s2)
57 58
58 59
59 60 def check_line_split(splitter, test_specs):
60 61 for part1, part2, split in test_specs:
61 62 cursor_pos = len(part1)
62 63 line = part1+part2
63 64 out = splitter.split_line(line, cursor_pos)
64 65 nt.assert_equal(out, split)
65 66
66 67
67 68 def test_line_split():
68 69 """Basic line splitter test with default specs."""
69 70 sp = completer.CompletionSplitter()
70 71 # The format of the test specs is: part1, part2, expected answer. Parts 1
71 72 # and 2 are joined into the 'line' sent to the splitter, as if the cursor
72 73 # was at the end of part1. So an empty part2 represents someone hitting
73 74 # tab at the end of the line, the most common case.
74 75 t = [('run some/scrip', '', 'some/scrip'),
75 76 ('run scripts/er', 'ror.py foo', 'scripts/er'),
76 77 ('echo $HOM', '', 'HOM'),
77 78 ('print sys.pa', '', 'sys.pa'),
78 79 ('print(sys.pa', '', 'sys.pa'),
79 80 ("execfile('scripts/er", '', 'scripts/er'),
80 81 ('a[x.', '', 'x.'),
81 82 ('a[x.', 'y', 'x.'),
82 83 ('cd "some_file/', '', 'some_file/'),
83 84 ]
84 85 check_line_split(sp, t)
85 86 # Ensure splitting works OK with unicode by re-running the tests with
86 87 # all inputs turned into unicode
87 88 check_line_split(sp, [ map(unicode_type, p) for p in t] )
88 89
89 90
90 91 def test_custom_completion_error():
91 92 """Test that errors from custom attribute completers are silenced."""
92 93 ip = get_ipython()
93 94 class A(object): pass
94 95 ip.user_ns['a'] = A()
95 96
96 97 @complete_object.when_type(A)
97 98 def complete_A(a, existing_completions):
98 99 raise TypeError("this should be silenced")
99 100
100 101 ip.complete("a.")
101 102
102 103
103 104 def test_unicode_completions():
104 105 ip = get_ipython()
105 106 # Some strings that trigger different types of completion. Check them both
106 107 # in str and unicode forms
107 108 s = ['ru', '%ru', 'cd /', 'floa', 'float(x)/']
108 109 for t in s + list(map(unicode_type, s)):
109 110 # We don't need to check exact completion values (they may change
110 111 # depending on the state of the namespace, but at least no exceptions
111 112 # should be thrown and the return value should be a pair of text, list
112 113 # values.
113 114 text, matches = ip.complete(t)
114 115 nt.assert_true(isinstance(text, string_types))
115 116 nt.assert_true(isinstance(matches, list))
116 117
117 118
118 119 class CompletionSplitterTestCase(unittest.TestCase):
119 120 def setUp(self):
120 121 self.sp = completer.CompletionSplitter()
121 122
122 123 def test_delim_setting(self):
123 124 self.sp.delims = ' '
124 125 nt.assert_equal(self.sp.delims, ' ')
125 126 nt.assert_equal(self.sp._delim_expr, '[\ ]')
126 127
127 128 def test_spaces(self):
128 129 """Test with only spaces as split chars."""
129 130 self.sp.delims = ' '
130 131 t = [('foo', '', 'foo'),
131 132 ('run foo', '', 'foo'),
132 133 ('run foo', 'bar', 'foo'),
133 134 ]
134 135 check_line_split(self.sp, t)
135 136
136 137
137 138 def test_has_open_quotes1():
138 139 for s in ["'", "'''", "'hi' '"]:
139 140 nt.assert_equal(completer.has_open_quotes(s), "'")
140 141
141 142
142 143 def test_has_open_quotes2():
143 144 for s in ['"', '"""', '"hi" "']:
144 145 nt.assert_equal(completer.has_open_quotes(s), '"')
145 146
146 147
147 148 def test_has_open_quotes3():
148 149 for s in ["''", "''' '''", "'hi' 'ipython'"]:
149 150 nt.assert_false(completer.has_open_quotes(s))
150 151
151 152
152 153 def test_has_open_quotes4():
153 154 for s in ['""', '""" """', '"hi" "ipython"']:
154 155 nt.assert_false(completer.has_open_quotes(s))
155 156
156 157
157 158 @knownfailureif(sys.platform == 'win32', "abspath completions fail on Windows")
158 159 def test_abspath_file_completions():
159 160 ip = get_ipython()
160 161 with TemporaryDirectory() as tmpdir:
161 162 prefix = os.path.join(tmpdir, 'foo')
162 163 suffixes = ['1', '2']
163 164 names = [prefix+s for s in suffixes]
164 165 for n in names:
165 166 open(n, 'w').close()
166 167
167 168 # Check simple completion
168 169 c = ip.complete(prefix)[1]
169 170 nt.assert_equal(c, names)
170 171
171 172 # Now check with a function call
172 173 cmd = 'a = f("%s' % prefix
173 174 c = ip.complete(prefix, cmd)[1]
174 175 comp = [prefix+s for s in suffixes]
175 176 nt.assert_equal(c, comp)
176 177
177 178
178 179 def test_local_file_completions():
179 180 ip = get_ipython()
180 cwd = os.getcwdu()
181 cwd = py3compat.getcwd()
181 182 try:
182 183 with TemporaryDirectory() as tmpdir:
183 184 os.chdir(tmpdir)
184 185 prefix = './foo'
185 186 suffixes = ['1', '2']
186 187 names = [prefix+s for s in suffixes]
187 188 for n in names:
188 189 open(n, 'w').close()
189 190
190 191 # Check simple completion
191 192 c = ip.complete(prefix)[1]
192 193 nt.assert_equal(c, names)
193 194
194 195 # Now check with a function call
195 196 cmd = 'a = f("%s' % prefix
196 197 c = ip.complete(prefix, cmd)[1]
197 198 comp = [prefix+s for s in suffixes]
198 199 nt.assert_equal(c, comp)
199 200 finally:
200 201 # prevent failures from making chdir stick
201 202 os.chdir(cwd)
202 203
203 204
204 205 def test_greedy_completions():
205 206 ip = get_ipython()
206 207 greedy_original = ip.Completer.greedy
207 208 try:
208 209 ip.Completer.greedy = False
209 210 ip.ex('a=list(range(5))')
210 211 _,c = ip.complete('.',line='a[0].')
211 212 nt.assert_false('a[0].real' in c,
212 213 "Shouldn't have completed on a[0]: %s"%c)
213 214 ip.Completer.greedy = True
214 215 _,c = ip.complete('.',line='a[0].')
215 216 nt.assert_true('a[0].real' in c, "Should have completed on a[0]: %s"%c)
216 217 finally:
217 218 ip.Completer.greedy = greedy_original
218 219
219 220
220 221 def test_omit__names():
221 222 # also happens to test IPCompleter as a configurable
222 223 ip = get_ipython()
223 224 ip._hidden_attr = 1
224 225 c = ip.Completer
225 226 ip.ex('ip=get_ipython()')
226 227 cfg = Config()
227 228 cfg.IPCompleter.omit__names = 0
228 229 c.update_config(cfg)
229 230 s,matches = c.complete('ip.')
230 231 nt.assert_in('ip.__str__', matches)
231 232 nt.assert_in('ip._hidden_attr', matches)
232 233 cfg.IPCompleter.omit__names = 1
233 234 c.update_config(cfg)
234 235 s,matches = c.complete('ip.')
235 236 nt.assert_not_in('ip.__str__', matches)
236 237 nt.assert_in('ip._hidden_attr', matches)
237 238 cfg.IPCompleter.omit__names = 2
238 239 c.update_config(cfg)
239 240 s,matches = c.complete('ip.')
240 241 nt.assert_not_in('ip.__str__', matches)
241 242 nt.assert_not_in('ip._hidden_attr', matches)
242 243 del ip._hidden_attr
243 244
244 245
245 246 def test_limit_to__all__False_ok():
246 247 ip = get_ipython()
247 248 c = ip.Completer
248 249 ip.ex('class D: x=24')
249 250 ip.ex('d=D()')
250 251 cfg = Config()
251 252 cfg.IPCompleter.limit_to__all__ = False
252 253 c.update_config(cfg)
253 254 s, matches = c.complete('d.')
254 255 nt.assert_in('d.x', matches)
255 256
256 257
257 258 def test_limit_to__all__True_ok():
258 259 ip = get_ipython()
259 260 c = ip.Completer
260 261 ip.ex('class D: x=24')
261 262 ip.ex('d=D()')
262 263 ip.ex("d.__all__=['z']")
263 264 cfg = Config()
264 265 cfg.IPCompleter.limit_to__all__ = True
265 266 c.update_config(cfg)
266 267 s, matches = c.complete('d.')
267 268 nt.assert_in('d.z', matches)
268 269 nt.assert_not_in('d.x', matches)
269 270
270 271
271 272 def test_get__all__entries_ok():
272 273 class A(object):
273 274 __all__ = ['x', 1]
274 275 words = completer.get__all__entries(A())
275 276 nt.assert_equal(words, ['x'])
276 277
277 278
278 279 def test_get__all__entries_no__all__ok():
279 280 class A(object):
280 281 pass
281 282 words = completer.get__all__entries(A())
282 283 nt.assert_equal(words, [])
283 284
284 285
285 286 def test_func_kw_completions():
286 287 ip = get_ipython()
287 288 c = ip.Completer
288 289 ip.ex('def myfunc(a=1,b=2): return a+b')
289 290 s, matches = c.complete(None, 'myfunc(1,b')
290 291 nt.assert_in('b=', matches)
291 292 # Simulate completing with cursor right after b (pos==10):
292 293 s, matches = c.complete(None, 'myfunc(1,b)', 10)
293 294 nt.assert_in('b=', matches)
294 295 s, matches = c.complete(None, 'myfunc(a="escaped\\")string",b')
295 296 nt.assert_in('b=', matches)
296 297 #builtin function
297 298 s, matches = c.complete(None, 'min(k, k')
298 299 nt.assert_in('key=', matches)
299 300
300 301
301 302 def test_default_arguments_from_docstring():
302 303 doc = min.__doc__
303 304 ip = get_ipython()
304 305 c = ip.Completer
305 306 kwd = c._default_arguments_from_docstring(
306 307 'min(iterable[, key=func]) -> value')
307 308 nt.assert_equal(kwd, ['key'])
308 309 #with cython type etc
309 310 kwd = c._default_arguments_from_docstring(
310 311 'Minuit.migrad(self, int ncall=10000, resume=True, int nsplit=1)\n')
311 312 nt.assert_equal(kwd, ['ncall', 'resume', 'nsplit'])
312 313 #white spaces
313 314 kwd = c._default_arguments_from_docstring(
314 315 '\n Minuit.migrad(self, int ncall=10000, resume=True, int nsplit=1)\n')
315 316 nt.assert_equal(kwd, ['ncall', 'resume', 'nsplit'])
316 317
317 318 def test_line_magics():
318 319 ip = get_ipython()
319 320 c = ip.Completer
320 321 s, matches = c.complete(None, 'lsmag')
321 322 nt.assert_in('%lsmagic', matches)
322 323 s, matches = c.complete(None, '%lsmag')
323 324 nt.assert_in('%lsmagic', matches)
324 325
325 326
326 327 def test_cell_magics():
327 328 from IPython.core.magic import register_cell_magic
328 329
329 330 @register_cell_magic
330 331 def _foo_cellm(line, cell):
331 332 pass
332 333
333 334 ip = get_ipython()
334 335 c = ip.Completer
335 336
336 337 s, matches = c.complete(None, '_foo_ce')
337 338 nt.assert_in('%%_foo_cellm', matches)
338 339 s, matches = c.complete(None, '%%_foo_ce')
339 340 nt.assert_in('%%_foo_cellm', matches)
340 341
341 342
342 343 def test_line_cell_magics():
343 344 from IPython.core.magic import register_line_cell_magic
344 345
345 346 @register_line_cell_magic
346 347 def _bar_cellm(line, cell):
347 348 pass
348 349
349 350 ip = get_ipython()
350 351 c = ip.Completer
351 352
352 353 # The policy here is trickier, see comments in completion code. The
353 354 # returned values depend on whether the user passes %% or not explicitly,
354 355 # and this will show a difference if the same name is both a line and cell
355 356 # magic.
356 357 s, matches = c.complete(None, '_bar_ce')
357 358 nt.assert_in('%_bar_cellm', matches)
358 359 nt.assert_in('%%_bar_cellm', matches)
359 360 s, matches = c.complete(None, '%_bar_ce')
360 361 nt.assert_in('%_bar_cellm', matches)
361 362 nt.assert_in('%%_bar_cellm', matches)
362 363 s, matches = c.complete(None, '%%_bar_ce')
363 364 nt.assert_not_in('%_bar_cellm', matches)
364 365 nt.assert_in('%%_bar_cellm', matches)
365 366
366 367
367 368 def test_magic_completion_order():
368 369
369 370 ip = get_ipython()
370 371 c = ip.Completer
371 372
372 373 # Test ordering of magics and non-magics with the same name
373 374 # We want the non-magic first
374 375
375 376 # Before importing matplotlib, there should only be one option:
376 377
377 378 text, matches = c.complete('mat')
378 379 nt.assert_equal(matches, ["%matplotlib"])
379 380
380 381
381 382 ip.run_cell("matplotlib = 1") # introduce name into namespace
382 383
383 384 # After the import, there should be two options, ordered like this:
384 385 text, matches = c.complete('mat')
385 386 nt.assert_equal(matches, ["matplotlib", "%matplotlib"])
386 387
387 388
388 389 ip.run_cell("timeit = 1") # define a user variable called 'timeit'
389 390
390 391 # Order of user variable and line and cell magics with same name:
391 392 text, matches = c.complete('timeit')
392 393 nt.assert_equal(matches, ["timeit", "%timeit","%%timeit"])
393 394
@@ -1,120 +1,121 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Tests for completerlib.
3 3
4 4 """
5 5 from __future__ import absolute_import
6 6
7 7 #-----------------------------------------------------------------------------
8 8 # Imports
9 9 #-----------------------------------------------------------------------------
10 10
11 11 import os
12 12 import shutil
13 13 import sys
14 14 import tempfile
15 15 import unittest
16 16 from os.path import join
17 17
18 18 from IPython.core.completerlib import magic_run_completer, module_completion
19 from IPython.utils import py3compat
19 20 from IPython.utils.tempdir import TemporaryDirectory
20 21 from IPython.testing.decorators import onlyif_unicode_paths
21 22
22 23
23 24 class MockEvent(object):
24 25 def __init__(self, line):
25 26 self.line = line
26 27
27 28 #-----------------------------------------------------------------------------
28 29 # Test functions begin
29 30 #-----------------------------------------------------------------------------
30 31 class Test_magic_run_completer(unittest.TestCase):
31 32 def setUp(self):
32 33 self.BASETESTDIR = tempfile.mkdtemp()
33 34 for fil in [u"aao.py", u"a.py", u"b.py"]:
34 35 with open(join(self.BASETESTDIR, fil), "w") as sfile:
35 36 sfile.write("pass\n")
36 self.oldpath = os.getcwdu()
37 self.oldpath = py3compat.getcwd()
37 38 os.chdir(self.BASETESTDIR)
38 39
39 40 def tearDown(self):
40 41 os.chdir(self.oldpath)
41 42 shutil.rmtree(self.BASETESTDIR)
42 43
43 44 def test_1(self):
44 45 """Test magic_run_completer, should match two alterntives
45 46 """
46 47 event = MockEvent(u"%run a")
47 48 mockself = None
48 49 match = set(magic_run_completer(mockself, event))
49 50 self.assertEqual(match, set([u"a.py", u"aao.py"]))
50 51
51 52 def test_2(self):
52 53 """Test magic_run_completer, should match one alterntive
53 54 """
54 55 event = MockEvent(u"%run aa")
55 56 mockself = None
56 57 match = set(magic_run_completer(mockself, event))
57 58 self.assertEqual(match, set([u"aao.py"]))
58 59
59 60 def test_3(self):
60 61 """Test magic_run_completer with unterminated " """
61 62 event = MockEvent(u'%run "a')
62 63 mockself = None
63 64 match = set(magic_run_completer(mockself, event))
64 65 self.assertEqual(match, set([u"a.py", u"aao.py"]))
65 66
66 67 def test_import_invalid_module(self):
67 68 """Testing of issue https://github.com/ipython/ipython/issues/1107"""
68 69 invalid_module_names = set(['foo-bar', 'foo:bar', '10foo'])
69 70 valid_module_names = set(['foobar'])
70 71 with TemporaryDirectory() as tmpdir:
71 72 sys.path.insert( 0, tmpdir )
72 73 for name in invalid_module_names | valid_module_names:
73 74 filename = os.path.join(tmpdir, name + '.py')
74 75 open(filename, 'w').close()
75 76
76 77 s = set( module_completion('import foo') )
77 78 intersection = s.intersection(invalid_module_names)
78 79 self.assertFalse(intersection, intersection)
79 80
80 81 assert valid_module_names.issubset(s), valid_module_names.intersection(s)
81 82
82 83 class Test_magic_run_completer_nonascii(unittest.TestCase):
83 84 @onlyif_unicode_paths
84 85 def setUp(self):
85 86 self.BASETESTDIR = tempfile.mkdtemp()
86 87 for fil in [u"aaø.py", u"a.py", u"b.py"]:
87 88 with open(join(self.BASETESTDIR, fil), "w") as sfile:
88 89 sfile.write("pass\n")
89 self.oldpath = os.getcwdu()
90 self.oldpath = py3compat.getcwd()
90 91 os.chdir(self.BASETESTDIR)
91 92
92 93 def tearDown(self):
93 94 os.chdir(self.oldpath)
94 95 shutil.rmtree(self.BASETESTDIR)
95 96
96 97 @onlyif_unicode_paths
97 98 def test_1(self):
98 99 """Test magic_run_completer, should match two alterntives
99 100 """
100 101 event = MockEvent(u"%run a")
101 102 mockself = None
102 103 match = set(magic_run_completer(mockself, event))
103 104 self.assertEqual(match, set([u"a.py", u"aaø.py"]))
104 105
105 106 @onlyif_unicode_paths
106 107 def test_2(self):
107 108 """Test magic_run_completer, should match one alterntive
108 109 """
109 110 event = MockEvent(u"%run aa")
110 111 mockself = None
111 112 match = set(magic_run_completer(mockself, event))
112 113 self.assertEqual(match, set([u"aaø.py"]))
113 114
114 115 @onlyif_unicode_paths
115 116 def test_3(self):
116 117 """Test magic_run_completer with unterminated " """
117 118 event = MockEvent(u'%run "a')
118 119 mockself = None
119 120 match = set(magic_run_completer(mockself, event))
120 121 self.assertEqual(match, set([u"a.py", u"aaø.py"]))
@@ -1,676 +1,677 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Tests for the key interactiveshell module.
3 3
4 4 Historically the main classes in interactiveshell have been under-tested. This
5 5 module should grow as many single-method tests as possible to trap many of the
6 6 recurring bugs we seem to encounter with high-level interaction.
7 7
8 8 Authors
9 9 -------
10 10 * Fernando Perez
11 11 """
12 12 #-----------------------------------------------------------------------------
13 13 # Copyright (C) 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 # stdlib
23 23 import ast
24 24 import os
25 25 import signal
26 26 import shutil
27 27 import sys
28 28 import tempfile
29 29 import unittest
30 30 from os.path import join
31 31
32 32 # third-party
33 33 import nose.tools as nt
34 34
35 35 # Our own
36 36 from IPython.testing.decorators import skipif, skip_win32, onlyif_unicode_paths
37 37 from IPython.testing import tools as tt
38 38 from IPython.utils import io
39 from IPython.utils import py3compat
39 40 from IPython.utils.py3compat import unicode_type, PY3
40 41
41 42 if PY3:
42 43 from io import StringIO
43 44 else:
44 45 from StringIO import StringIO
45 46
46 47 #-----------------------------------------------------------------------------
47 48 # Globals
48 49 #-----------------------------------------------------------------------------
49 50 # This is used by every single test, no point repeating it ad nauseam
50 51 ip = get_ipython()
51 52
52 53 #-----------------------------------------------------------------------------
53 54 # Tests
54 55 #-----------------------------------------------------------------------------
55 56
56 57 class InteractiveShellTestCase(unittest.TestCase):
57 58 def test_naked_string_cells(self):
58 59 """Test that cells with only naked strings are fully executed"""
59 60 # First, single-line inputs
60 61 ip.run_cell('"a"\n')
61 62 self.assertEqual(ip.user_ns['_'], 'a')
62 63 # And also multi-line cells
63 64 ip.run_cell('"""a\nb"""\n')
64 65 self.assertEqual(ip.user_ns['_'], 'a\nb')
65 66
66 67 def test_run_empty_cell(self):
67 68 """Just make sure we don't get a horrible error with a blank
68 69 cell of input. Yes, I did overlook that."""
69 70 old_xc = ip.execution_count
70 71 ip.run_cell('')
71 72 self.assertEqual(ip.execution_count, old_xc)
72 73
73 74 def test_run_cell_multiline(self):
74 75 """Multi-block, multi-line cells must execute correctly.
75 76 """
76 77 src = '\n'.join(["x=1",
77 78 "y=2",
78 79 "if 1:",
79 80 " x += 1",
80 81 " y += 1",])
81 82 ip.run_cell(src)
82 83 self.assertEqual(ip.user_ns['x'], 2)
83 84 self.assertEqual(ip.user_ns['y'], 3)
84 85
85 86 def test_multiline_string_cells(self):
86 87 "Code sprinkled with multiline strings should execute (GH-306)"
87 88 ip.run_cell('tmp=0')
88 89 self.assertEqual(ip.user_ns['tmp'], 0)
89 90 ip.run_cell('tmp=1;"""a\nb"""\n')
90 91 self.assertEqual(ip.user_ns['tmp'], 1)
91 92
92 93 def test_dont_cache_with_semicolon(self):
93 94 "Ending a line with semicolon should not cache the returned object (GH-307)"
94 95 oldlen = len(ip.user_ns['Out'])
95 96 a = ip.run_cell('1;', store_history=True)
96 97 newlen = len(ip.user_ns['Out'])
97 98 self.assertEqual(oldlen, newlen)
98 99 #also test the default caching behavior
99 100 ip.run_cell('1', store_history=True)
100 101 newlen = len(ip.user_ns['Out'])
101 102 self.assertEqual(oldlen+1, newlen)
102 103
103 104 def test_In_variable(self):
104 105 "Verify that In variable grows with user input (GH-284)"
105 106 oldlen = len(ip.user_ns['In'])
106 107 ip.run_cell('1;', store_history=True)
107 108 newlen = len(ip.user_ns['In'])
108 109 self.assertEqual(oldlen+1, newlen)
109 110 self.assertEqual(ip.user_ns['In'][-1],'1;')
110 111
111 112 def test_magic_names_in_string(self):
112 113 ip.run_cell('a = """\n%exit\n"""')
113 114 self.assertEqual(ip.user_ns['a'], '\n%exit\n')
114 115
115 116 def test_trailing_newline(self):
116 117 """test that running !(command) does not raise a SyntaxError"""
117 118 ip.run_cell('!(true)\n', False)
118 119 ip.run_cell('!(true)\n\n\n', False)
119 120
120 121 def test_gh_597(self):
121 122 """Pretty-printing lists of objects with non-ascii reprs may cause
122 123 problems."""
123 124 class Spam(object):
124 125 def __repr__(self):
125 126 return "\xe9"*50
126 127 import IPython.core.formatters
127 128 f = IPython.core.formatters.PlainTextFormatter()
128 129 f([Spam(),Spam()])
129 130
130 131
131 132 def test_future_flags(self):
132 133 """Check that future flags are used for parsing code (gh-777)"""
133 134 ip.run_cell('from __future__ import print_function')
134 135 try:
135 136 ip.run_cell('prfunc_return_val = print(1,2, sep=" ")')
136 137 assert 'prfunc_return_val' in ip.user_ns
137 138 finally:
138 139 # Reset compiler flags so we don't mess up other tests.
139 140 ip.compile.reset_compiler_flags()
140 141
141 142 def test_future_unicode(self):
142 143 """Check that unicode_literals is imported from __future__ (gh #786)"""
143 144 try:
144 145 ip.run_cell(u'byte_str = "a"')
145 146 assert isinstance(ip.user_ns['byte_str'], str) # string literals are byte strings by default
146 147 ip.run_cell('from __future__ import unicode_literals')
147 148 ip.run_cell(u'unicode_str = "a"')
148 149 assert isinstance(ip.user_ns['unicode_str'], unicode_type) # strings literals are now unicode
149 150 finally:
150 151 # Reset compiler flags so we don't mess up other tests.
151 152 ip.compile.reset_compiler_flags()
152 153
153 154 def test_can_pickle(self):
154 155 "Can we pickle objects defined interactively (GH-29)"
155 156 ip = get_ipython()
156 157 ip.reset()
157 158 ip.run_cell(("class Mylist(list):\n"
158 159 " def __init__(self,x=[]):\n"
159 160 " list.__init__(self,x)"))
160 161 ip.run_cell("w=Mylist([1,2,3])")
161 162
162 163 from pickle import dumps
163 164
164 165 # We need to swap in our main module - this is only necessary
165 166 # inside the test framework, because IPython puts the interactive module
166 167 # in place (but the test framework undoes this).
167 168 _main = sys.modules['__main__']
168 169 sys.modules['__main__'] = ip.user_module
169 170 try:
170 171 res = dumps(ip.user_ns["w"])
171 172 finally:
172 173 sys.modules['__main__'] = _main
173 174 self.assertTrue(isinstance(res, bytes))
174 175
175 176 def test_global_ns(self):
176 177 "Code in functions must be able to access variables outside them."
177 178 ip = get_ipython()
178 179 ip.run_cell("a = 10")
179 180 ip.run_cell(("def f(x):\n"
180 181 " return x + a"))
181 182 ip.run_cell("b = f(12)")
182 183 self.assertEqual(ip.user_ns["b"], 22)
183 184
184 185 def test_bad_custom_tb(self):
185 186 """Check that InteractiveShell is protected from bad custom exception handlers"""
186 187 from IPython.utils import io
187 188 save_stderr = io.stderr
188 189 try:
189 190 # capture stderr
190 191 io.stderr = StringIO()
191 192 ip.set_custom_exc((IOError,), lambda etype,value,tb: 1/0)
192 193 self.assertEqual(ip.custom_exceptions, (IOError,))
193 194 ip.run_cell(u'raise IOError("foo")')
194 195 self.assertEqual(ip.custom_exceptions, ())
195 196 self.assertTrue("Custom TB Handler failed" in io.stderr.getvalue())
196 197 finally:
197 198 io.stderr = save_stderr
198 199
199 200 def test_bad_custom_tb_return(self):
200 201 """Check that InteractiveShell is protected from bad return types in custom exception handlers"""
201 202 from IPython.utils import io
202 203 save_stderr = io.stderr
203 204 try:
204 205 # capture stderr
205 206 io.stderr = StringIO()
206 207 ip.set_custom_exc((NameError,),lambda etype,value,tb, tb_offset=None: 1)
207 208 self.assertEqual(ip.custom_exceptions, (NameError,))
208 209 ip.run_cell(u'a=abracadabra')
209 210 self.assertEqual(ip.custom_exceptions, ())
210 211 self.assertTrue("Custom TB Handler failed" in io.stderr.getvalue())
211 212 finally:
212 213 io.stderr = save_stderr
213 214
214 215 def test_drop_by_id(self):
215 216 myvars = {"a":object(), "b":object(), "c": object()}
216 217 ip.push(myvars, interactive=False)
217 218 for name in myvars:
218 219 assert name in ip.user_ns, name
219 220 assert name in ip.user_ns_hidden, name
220 221 ip.user_ns['b'] = 12
221 222 ip.drop_by_id(myvars)
222 223 for name in ["a", "c"]:
223 224 assert name not in ip.user_ns, name
224 225 assert name not in ip.user_ns_hidden, name
225 226 assert ip.user_ns['b'] == 12
226 227 ip.reset()
227 228
228 229 def test_var_expand(self):
229 230 ip.user_ns['f'] = u'Ca\xf1o'
230 231 self.assertEqual(ip.var_expand(u'echo $f'), u'echo Ca\xf1o')
231 232 self.assertEqual(ip.var_expand(u'echo {f}'), u'echo Ca\xf1o')
232 233 self.assertEqual(ip.var_expand(u'echo {f[:-1]}'), u'echo Ca\xf1')
233 234 self.assertEqual(ip.var_expand(u'echo {1*2}'), u'echo 2')
234 235
235 236 ip.user_ns['f'] = b'Ca\xc3\xb1o'
236 237 # This should not raise any exception:
237 238 ip.var_expand(u'echo $f')
238 239
239 240 def test_var_expand_local(self):
240 241 """Test local variable expansion in !system and %magic calls"""
241 242 # !system
242 243 ip.run_cell('def test():\n'
243 244 ' lvar = "ttt"\n'
244 245 ' ret = !echo {lvar}\n'
245 246 ' return ret[0]\n')
246 247 res = ip.user_ns['test']()
247 248 nt.assert_in('ttt', res)
248 249
249 250 # %magic
250 251 ip.run_cell('def makemacro():\n'
251 252 ' macroname = "macro_var_expand_locals"\n'
252 253 ' %macro {macroname} codestr\n')
253 254 ip.user_ns['codestr'] = "str(12)"
254 255 ip.run_cell('makemacro()')
255 256 nt.assert_in('macro_var_expand_locals', ip.user_ns)
256 257
257 258 def test_var_expand_self(self):
258 259 """Test variable expansion with the name 'self', which was failing.
259 260
260 261 See https://github.com/ipython/ipython/issues/1878#issuecomment-7698218
261 262 """
262 263 ip.run_cell('class cTest:\n'
263 264 ' classvar="see me"\n'
264 265 ' def test(self):\n'
265 266 ' res = !echo Variable: {self.classvar}\n'
266 267 ' return res[0]\n')
267 268 nt.assert_in('see me', ip.user_ns['cTest']().test())
268 269
269 270 def test_bad_var_expand(self):
270 271 """var_expand on invalid formats shouldn't raise"""
271 272 # SyntaxError
272 273 self.assertEqual(ip.var_expand(u"{'a':5}"), u"{'a':5}")
273 274 # NameError
274 275 self.assertEqual(ip.var_expand(u"{asdf}"), u"{asdf}")
275 276 # ZeroDivisionError
276 277 self.assertEqual(ip.var_expand(u"{1/0}"), u"{1/0}")
277 278
278 279 def test_silent_nopostexec(self):
279 280 """run_cell(silent=True) doesn't invoke post-exec funcs"""
280 281 d = dict(called=False)
281 282 def set_called():
282 283 d['called'] = True
283 284
284 285 ip.register_post_execute(set_called)
285 286 ip.run_cell("1", silent=True)
286 287 self.assertFalse(d['called'])
287 288 # double-check that non-silent exec did what we expected
288 289 # silent to avoid
289 290 ip.run_cell("1")
290 291 self.assertTrue(d['called'])
291 292 # remove post-exec
292 293 ip._post_execute.pop(set_called)
293 294
294 295 def test_silent_noadvance(self):
295 296 """run_cell(silent=True) doesn't advance execution_count"""
296 297 ec = ip.execution_count
297 298 # silent should force store_history=False
298 299 ip.run_cell("1", store_history=True, silent=True)
299 300
300 301 self.assertEqual(ec, ip.execution_count)
301 302 # double-check that non-silent exec did what we expected
302 303 # silent to avoid
303 304 ip.run_cell("1", store_history=True)
304 305 self.assertEqual(ec+1, ip.execution_count)
305 306
306 307 def test_silent_nodisplayhook(self):
307 308 """run_cell(silent=True) doesn't trigger displayhook"""
308 309 d = dict(called=False)
309 310
310 311 trap = ip.display_trap
311 312 save_hook = trap.hook
312 313
313 314 def failing_hook(*args, **kwargs):
314 315 d['called'] = True
315 316
316 317 try:
317 318 trap.hook = failing_hook
318 319 ip.run_cell("1", silent=True)
319 320 self.assertFalse(d['called'])
320 321 # double-check that non-silent exec did what we expected
321 322 # silent to avoid
322 323 ip.run_cell("1")
323 324 self.assertTrue(d['called'])
324 325 finally:
325 326 trap.hook = save_hook
326 327
327 328 @skipif(sys.version_info[0] >= 3, "softspace removed in py3")
328 329 def test_print_softspace(self):
329 330 """Verify that softspace is handled correctly when executing multiple
330 331 statements.
331 332
332 333 In [1]: print 1; print 2
333 334 1
334 335 2
335 336
336 337 In [2]: print 1,; print 2
337 338 1 2
338 339 """
339 340
340 341 def test_ofind_line_magic(self):
341 342 from IPython.core.magic import register_line_magic
342 343
343 344 @register_line_magic
344 345 def lmagic(line):
345 346 "A line magic"
346 347
347 348 # Get info on line magic
348 349 lfind = ip._ofind('lmagic')
349 350 info = dict(found=True, isalias=False, ismagic=True,
350 351 namespace = 'IPython internal', obj= lmagic.__wrapped__,
351 352 parent = None)
352 353 nt.assert_equal(lfind, info)
353 354
354 355 def test_ofind_cell_magic(self):
355 356 from IPython.core.magic import register_cell_magic
356 357
357 358 @register_cell_magic
358 359 def cmagic(line, cell):
359 360 "A cell magic"
360 361
361 362 # Get info on cell magic
362 363 find = ip._ofind('cmagic')
363 364 info = dict(found=True, isalias=False, ismagic=True,
364 365 namespace = 'IPython internal', obj= cmagic.__wrapped__,
365 366 parent = None)
366 367 nt.assert_equal(find, info)
367 368
368 369 def test_custom_exception(self):
369 370 called = []
370 371 def my_handler(shell, etype, value, tb, tb_offset=None):
371 372 called.append(etype)
372 373 shell.showtraceback((etype, value, tb), tb_offset=tb_offset)
373 374
374 375 ip.set_custom_exc((ValueError,), my_handler)
375 376 try:
376 377 ip.run_cell("raise ValueError('test')")
377 378 # Check that this was called, and only once.
378 379 self.assertEqual(called, [ValueError])
379 380 finally:
380 381 # Reset the custom exception hook
381 382 ip.set_custom_exc((), None)
382 383
383 384 @skipif(sys.version_info[0] >= 3, "no differences with __future__ in py3")
384 385 def test_future_environment(self):
385 386 "Can we run code with & without the shell's __future__ imports?"
386 387 ip.run_cell("from __future__ import division")
387 388 ip.run_cell("a = 1/2", shell_futures=True)
388 389 self.assertEqual(ip.user_ns['a'], 0.5)
389 390 ip.run_cell("b = 1/2", shell_futures=False)
390 391 self.assertEqual(ip.user_ns['b'], 0)
391 392
392 393 ip.compile.reset_compiler_flags()
393 394 # This shouldn't leak to the shell's compiler
394 395 ip.run_cell("from __future__ import division \nc=1/2", shell_futures=False)
395 396 self.assertEqual(ip.user_ns['c'], 0.5)
396 397 ip.run_cell("d = 1/2", shell_futures=True)
397 398 self.assertEqual(ip.user_ns['d'], 0)
398 399
399 400
400 401 class TestSafeExecfileNonAsciiPath(unittest.TestCase):
401 402
402 403 @onlyif_unicode_paths
403 404 def setUp(self):
404 405 self.BASETESTDIR = tempfile.mkdtemp()
405 406 self.TESTDIR = join(self.BASETESTDIR, u"åäö")
406 407 os.mkdir(self.TESTDIR)
407 408 with open(join(self.TESTDIR, u"åäötestscript.py"), "w") as sfile:
408 409 sfile.write("pass\n")
409 self.oldpath = os.getcwdu()
410 self.oldpath = py3compat.getcwd()
410 411 os.chdir(self.TESTDIR)
411 412 self.fname = u"åäötestscript.py"
412 413
413 414 def tearDown(self):
414 415 os.chdir(self.oldpath)
415 416 shutil.rmtree(self.BASETESTDIR)
416 417
417 418 @onlyif_unicode_paths
418 419 def test_1(self):
419 420 """Test safe_execfile with non-ascii path
420 421 """
421 422 ip.safe_execfile(self.fname, {}, raise_exceptions=True)
422 423
423 424 class ExitCodeChecks(tt.TempFileMixin):
424 425 def test_exit_code_ok(self):
425 426 self.system('exit 0')
426 427 self.assertEqual(ip.user_ns['_exit_code'], 0)
427 428
428 429 def test_exit_code_error(self):
429 430 self.system('exit 1')
430 431 self.assertEqual(ip.user_ns['_exit_code'], 1)
431 432
432 433 @skipif(not hasattr(signal, 'SIGALRM'))
433 434 def test_exit_code_signal(self):
434 435 self.mktmp("import signal, time\n"
435 436 "signal.setitimer(signal.ITIMER_REAL, 0.1)\n"
436 437 "time.sleep(1)\n")
437 438 self.system("%s %s" % (sys.executable, self.fname))
438 439 self.assertEqual(ip.user_ns['_exit_code'], -signal.SIGALRM)
439 440
440 441 class TestSystemRaw(unittest.TestCase, ExitCodeChecks):
441 442 system = ip.system_raw
442 443
443 444 @onlyif_unicode_paths
444 445 def test_1(self):
445 446 """Test system_raw with non-ascii cmd
446 447 """
447 448 cmd = u'''python -c "'åäö'" '''
448 449 ip.system_raw(cmd)
449 450
450 451 # TODO: Exit codes are currently ignored on Windows.
451 452 class TestSystemPipedExitCode(unittest.TestCase, ExitCodeChecks):
452 453 system = ip.system_piped
453 454
454 455 @skip_win32
455 456 def test_exit_code_ok(self):
456 457 ExitCodeChecks.test_exit_code_ok(self)
457 458
458 459 @skip_win32
459 460 def test_exit_code_error(self):
460 461 ExitCodeChecks.test_exit_code_error(self)
461 462
462 463 @skip_win32
463 464 def test_exit_code_signal(self):
464 465 ExitCodeChecks.test_exit_code_signal(self)
465 466
466 467 class TestModules(unittest.TestCase, tt.TempFileMixin):
467 468 def test_extraneous_loads(self):
468 469 """Test we're not loading modules on startup that we shouldn't.
469 470 """
470 471 self.mktmp("import sys\n"
471 472 "print('numpy' in sys.modules)\n"
472 473 "print('IPython.parallel' in sys.modules)\n"
473 474 "print('IPython.kernel.zmq' in sys.modules)\n"
474 475 )
475 476 out = "False\nFalse\nFalse\n"
476 477 tt.ipexec_validate(self.fname, out)
477 478
478 479 class Negator(ast.NodeTransformer):
479 480 """Negates all number literals in an AST."""
480 481 def visit_Num(self, node):
481 482 node.n = -node.n
482 483 return node
483 484
484 485 class TestAstTransform(unittest.TestCase):
485 486 def setUp(self):
486 487 self.negator = Negator()
487 488 ip.ast_transformers.append(self.negator)
488 489
489 490 def tearDown(self):
490 491 ip.ast_transformers.remove(self.negator)
491 492
492 493 def test_run_cell(self):
493 494 with tt.AssertPrints('-34'):
494 495 ip.run_cell('print (12 + 22)')
495 496
496 497 # A named reference to a number shouldn't be transformed.
497 498 ip.user_ns['n'] = 55
498 499 with tt.AssertNotPrints('-55'):
499 500 ip.run_cell('print (n)')
500 501
501 502 def test_timeit(self):
502 503 called = set()
503 504 def f(x):
504 505 called.add(x)
505 506 ip.push({'f':f})
506 507
507 508 with tt.AssertPrints("best of "):
508 509 ip.run_line_magic("timeit", "-n1 f(1)")
509 510 self.assertEqual(called, set([-1]))
510 511 called.clear()
511 512
512 513 with tt.AssertPrints("best of "):
513 514 ip.run_cell_magic("timeit", "-n1 f(2)", "f(3)")
514 515 self.assertEqual(called, set([-2, -3]))
515 516
516 517 def test_time(self):
517 518 called = []
518 519 def f(x):
519 520 called.append(x)
520 521 ip.push({'f':f})
521 522
522 523 # Test with an expression
523 524 with tt.AssertPrints("Wall time: "):
524 525 ip.run_line_magic("time", "f(5+9)")
525 526 self.assertEqual(called, [-14])
526 527 called[:] = []
527 528
528 529 # Test with a statement (different code path)
529 530 with tt.AssertPrints("Wall time: "):
530 531 ip.run_line_magic("time", "a = f(-3 + -2)")
531 532 self.assertEqual(called, [5])
532 533
533 534 def test_macro(self):
534 535 ip.push({'a':10})
535 536 # The AST transformation makes this do a+=-1
536 537 ip.define_macro("amacro", "a+=1\nprint(a)")
537 538
538 539 with tt.AssertPrints("9"):
539 540 ip.run_cell("amacro")
540 541 with tt.AssertPrints("8"):
541 542 ip.run_cell("amacro")
542 543
543 544 class IntegerWrapper(ast.NodeTransformer):
544 545 """Wraps all integers in a call to Integer()"""
545 546 def visit_Num(self, node):
546 547 if isinstance(node.n, int):
547 548 return ast.Call(func=ast.Name(id='Integer', ctx=ast.Load()),
548 549 args=[node], keywords=[])
549 550 return node
550 551
551 552 class TestAstTransform2(unittest.TestCase):
552 553 def setUp(self):
553 554 self.intwrapper = IntegerWrapper()
554 555 ip.ast_transformers.append(self.intwrapper)
555 556
556 557 self.calls = []
557 558 def Integer(*args):
558 559 self.calls.append(args)
559 560 return args
560 561 ip.push({"Integer": Integer})
561 562
562 563 def tearDown(self):
563 564 ip.ast_transformers.remove(self.intwrapper)
564 565 del ip.user_ns['Integer']
565 566
566 567 def test_run_cell(self):
567 568 ip.run_cell("n = 2")
568 569 self.assertEqual(self.calls, [(2,)])
569 570
570 571 # This shouldn't throw an error
571 572 ip.run_cell("o = 2.0")
572 573 self.assertEqual(ip.user_ns['o'], 2.0)
573 574
574 575 def test_timeit(self):
575 576 called = set()
576 577 def f(x):
577 578 called.add(x)
578 579 ip.push({'f':f})
579 580
580 581 with tt.AssertPrints("best of "):
581 582 ip.run_line_magic("timeit", "-n1 f(1)")
582 583 self.assertEqual(called, set([(1,)]))
583 584 called.clear()
584 585
585 586 with tt.AssertPrints("best of "):
586 587 ip.run_cell_magic("timeit", "-n1 f(2)", "f(3)")
587 588 self.assertEqual(called, set([(2,), (3,)]))
588 589
589 590 class ErrorTransformer(ast.NodeTransformer):
590 591 """Throws an error when it sees a number."""
591 592 def visit_Num(self):
592 593 raise ValueError("test")
593 594
594 595 class TestAstTransformError(unittest.TestCase):
595 596 def test_unregistering(self):
596 597 err_transformer = ErrorTransformer()
597 598 ip.ast_transformers.append(err_transformer)
598 599
599 600 with tt.AssertPrints("unregister", channel='stderr'):
600 601 ip.run_cell("1 + 2")
601 602
602 603 # This should have been removed.
603 604 nt.assert_not_in(err_transformer, ip.ast_transformers)
604 605
605 606 def test__IPYTHON__():
606 607 # This shouldn't raise a NameError, that's all
607 608 __IPYTHON__
608 609
609 610
610 611 class DummyRepr(object):
611 612 def __repr__(self):
612 613 return "DummyRepr"
613 614
614 615 def _repr_html_(self):
615 616 return "<b>dummy</b>"
616 617
617 618 def _repr_javascript_(self):
618 619 return "console.log('hi');", {'key': 'value'}
619 620
620 621
621 622 def test_user_variables():
622 623 # enable all formatters
623 624 ip.display_formatter.active_types = ip.display_formatter.format_types
624 625
625 626 ip.user_ns['dummy'] = d = DummyRepr()
626 627 keys = set(['dummy', 'doesnotexist'])
627 628 r = ip.user_variables(keys)
628 629
629 630 nt.assert_equal(keys, set(r.keys()))
630 631 dummy = r['dummy']
631 632 nt.assert_equal(set(['status', 'data', 'metadata']), set(dummy.keys()))
632 633 nt.assert_equal(dummy['status'], 'ok')
633 634 data = dummy['data']
634 635 metadata = dummy['metadata']
635 636 nt.assert_equal(data.get('text/html'), d._repr_html_())
636 637 js, jsmd = d._repr_javascript_()
637 638 nt.assert_equal(data.get('application/javascript'), js)
638 639 nt.assert_equal(metadata.get('application/javascript'), jsmd)
639 640
640 641 dne = r['doesnotexist']
641 642 nt.assert_equal(dne['status'], 'error')
642 643 nt.assert_equal(dne['ename'], 'KeyError')
643 644
644 645 # back to text only
645 646 ip.display_formatter.active_types = ['text/plain']
646 647
647 648 def test_user_expression():
648 649 # enable all formatters
649 650 ip.display_formatter.active_types = ip.display_formatter.format_types
650 651 query = {
651 652 'a' : '1 + 2',
652 653 'b' : '1/0',
653 654 }
654 655 r = ip.user_expressions(query)
655 656 import pprint
656 657 pprint.pprint(r)
657 658 nt.assert_equal(r.keys(), query.keys())
658 659 a = r['a']
659 660 nt.assert_equal(set(['status', 'data', 'metadata']), set(a.keys()))
660 661 nt.assert_equal(a['status'], 'ok')
661 662 data = a['data']
662 663 metadata = a['metadata']
663 664 nt.assert_equal(data.get('text/plain'), '3')
664 665
665 666 b = r['b']
666 667 nt.assert_equal(b['status'], 'error')
667 668 nt.assert_equal(b['ename'], 'ZeroDivisionError')
668 669
669 670 # back to text only
670 671 ip.display_formatter.active_types = ['text/plain']
671 672
672 673
673 674
674 675
675 676
676 677
@@ -1,944 +1,944 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Tests for various magic functions.
3 3
4 4 Needs to be run by nose (to make ipython session available).
5 5 """
6 6 from __future__ import absolute_import
7 7
8 8 #-----------------------------------------------------------------------------
9 9 # Imports
10 10 #-----------------------------------------------------------------------------
11 11
12 12 import io
13 13 import os
14 14 import sys
15 15 from unittest import TestCase
16 16
17 17 try:
18 18 from importlib import invalidate_caches # Required from Python 3.3
19 19 except ImportError:
20 20 def invalidate_caches():
21 21 pass
22 22
23 23 import nose.tools as nt
24 24
25 25 from IPython.core import magic
26 26 from IPython.core.magic import (Magics, magics_class, line_magic,
27 27 cell_magic, line_cell_magic,
28 28 register_line_magic, register_cell_magic,
29 29 register_line_cell_magic)
30 30 from IPython.core.magics import execution, script, code
31 31 from IPython.nbformat.v3.tests.nbexamples import nb0
32 32 from IPython.nbformat import current
33 33 from IPython.testing import decorators as dec
34 34 from IPython.testing import tools as tt
35 35 from IPython.utils import py3compat
36 36 from IPython.utils.io import capture_output
37 37 from IPython.utils.tempdir import TemporaryDirectory
38 38 from IPython.utils.process import find_cmd
39 39
40 40 if py3compat.PY3:
41 41 from io import StringIO
42 42 else:
43 43 from StringIO import StringIO
44 44
45 45 #-----------------------------------------------------------------------------
46 46 # Test functions begin
47 47 #-----------------------------------------------------------------------------
48 48
49 49 @magic.magics_class
50 50 class DummyMagics(magic.Magics): pass
51 51
52 52 def test_extract_code_ranges():
53 53 instr = "1 3 5-6 7-9 10:15 17: :10 10- -13 :"
54 54 expected = [(0, 1),
55 55 (2, 3),
56 56 (4, 6),
57 57 (6, 9),
58 58 (9, 14),
59 59 (16, None),
60 60 (None, 9),
61 61 (9, None),
62 62 (None, 13),
63 63 (None, None)]
64 64 actual = list(code.extract_code_ranges(instr))
65 65 nt.assert_equal(actual, expected)
66 66
67 67 def test_extract_symbols():
68 68 source = """import foo\na = 10\ndef b():\n return 42\n\n\nclass A: pass\n\n\n"""
69 69 symbols_args = ["a", "b", "A", "A,b", "A,a", "z"]
70 70 expected = [([], ['a']),
71 71 (["def b():\n return 42\n"], []),
72 72 (["class A: pass\n"], []),
73 73 (["class A: pass\n", "def b():\n return 42\n"], []),
74 74 (["class A: pass\n"], ['a']),
75 75 ([], ['z'])]
76 76 for symbols, exp in zip(symbols_args, expected):
77 77 nt.assert_equal(code.extract_symbols(source, symbols), exp)
78 78
79 79
80 80 def test_extract_symbols_raises_exception_with_non_python_code():
81 81 source = ("=begin A Ruby program :)=end\n"
82 82 "def hello\n"
83 83 "puts 'Hello world'\n"
84 84 "end")
85 85 with nt.assert_raises(SyntaxError):
86 86 code.extract_symbols(source, "hello")
87 87
88 88 def test_config():
89 89 """ test that config magic does not raise
90 90 can happen if Configurable init is moved too early into
91 91 Magics.__init__ as then a Config object will be registerd as a
92 92 magic.
93 93 """
94 94 ## should not raise.
95 95 _ip.magic('config')
96 96
97 97 def test_rehashx():
98 98 # clear up everything
99 99 _ip = get_ipython()
100 100 _ip.alias_manager.clear_aliases()
101 101 del _ip.db['syscmdlist']
102 102
103 103 _ip.magic('rehashx')
104 104 # Practically ALL ipython development systems will have more than 10 aliases
105 105
106 106 nt.assert_true(len(_ip.alias_manager.aliases) > 10)
107 107 for name, cmd in _ip.alias_manager.aliases:
108 108 # we must strip dots from alias names
109 109 nt.assert_not_in('.', name)
110 110
111 111 # rehashx must fill up syscmdlist
112 112 scoms = _ip.db['syscmdlist']
113 113 nt.assert_true(len(scoms) > 10)
114 114
115 115
116 116 def test_magic_parse_options():
117 117 """Test that we don't mangle paths when parsing magic options."""
118 118 ip = get_ipython()
119 119 path = 'c:\\x'
120 120 m = DummyMagics(ip)
121 121 opts = m.parse_options('-f %s' % path,'f:')[0]
122 122 # argv splitting is os-dependent
123 123 if os.name == 'posix':
124 124 expected = 'c:x'
125 125 else:
126 126 expected = path
127 127 nt.assert_equal(opts['f'], expected)
128 128
129 129 def test_magic_parse_long_options():
130 130 """Magic.parse_options can handle --foo=bar long options"""
131 131 ip = get_ipython()
132 132 m = DummyMagics(ip)
133 133 opts, _ = m.parse_options('--foo --bar=bubble', 'a', 'foo', 'bar=')
134 134 nt.assert_in('foo', opts)
135 135 nt.assert_in('bar', opts)
136 136 nt.assert_equal(opts['bar'], "bubble")
137 137
138 138
139 139 @dec.skip_without('sqlite3')
140 140 def doctest_hist_f():
141 141 """Test %hist -f with temporary filename.
142 142
143 143 In [9]: import tempfile
144 144
145 145 In [10]: tfile = tempfile.mktemp('.py','tmp-ipython-')
146 146
147 147 In [11]: %hist -nl -f $tfile 3
148 148
149 149 In [13]: import os; os.unlink(tfile)
150 150 """
151 151
152 152
153 153 @dec.skip_without('sqlite3')
154 154 def doctest_hist_r():
155 155 """Test %hist -r
156 156
157 157 XXX - This test is not recording the output correctly. For some reason, in
158 158 testing mode the raw history isn't getting populated. No idea why.
159 159 Disabling the output checking for now, though at least we do run it.
160 160
161 161 In [1]: 'hist' in _ip.lsmagic()
162 162 Out[1]: True
163 163
164 164 In [2]: x=1
165 165
166 166 In [3]: %hist -rl 2
167 167 x=1 # random
168 168 %hist -r 2
169 169 """
170 170
171 171
172 172 @dec.skip_without('sqlite3')
173 173 def doctest_hist_op():
174 174 """Test %hist -op
175 175
176 176 In [1]: class b(float):
177 177 ...: pass
178 178 ...:
179 179
180 180 In [2]: class s(object):
181 181 ...: def __str__(self):
182 182 ...: return 's'
183 183 ...:
184 184
185 185 In [3]:
186 186
187 187 In [4]: class r(b):
188 188 ...: def __repr__(self):
189 189 ...: return 'r'
190 190 ...:
191 191
192 192 In [5]: class sr(s,r): pass
193 193 ...:
194 194
195 195 In [6]:
196 196
197 197 In [7]: bb=b()
198 198
199 199 In [8]: ss=s()
200 200
201 201 In [9]: rr=r()
202 202
203 203 In [10]: ssrr=sr()
204 204
205 205 In [11]: 4.5
206 206 Out[11]: 4.5
207 207
208 208 In [12]: str(ss)
209 209 Out[12]: 's'
210 210
211 211 In [13]:
212 212
213 213 In [14]: %hist -op
214 214 >>> class b:
215 215 ... pass
216 216 ...
217 217 >>> class s(b):
218 218 ... def __str__(self):
219 219 ... return 's'
220 220 ...
221 221 >>>
222 222 >>> class r(b):
223 223 ... def __repr__(self):
224 224 ... return 'r'
225 225 ...
226 226 >>> class sr(s,r): pass
227 227 >>>
228 228 >>> bb=b()
229 229 >>> ss=s()
230 230 >>> rr=r()
231 231 >>> ssrr=sr()
232 232 >>> 4.5
233 233 4.5
234 234 >>> str(ss)
235 235 's'
236 236 >>>
237 237 """
238 238
239 239
240 240 @dec.skip_without('sqlite3')
241 241 def test_macro():
242 242 ip = get_ipython()
243 243 ip.history_manager.reset() # Clear any existing history.
244 244 cmds = ["a=1", "def b():\n return a**2", "print(a,b())"]
245 245 for i, cmd in enumerate(cmds, start=1):
246 246 ip.history_manager.store_inputs(i, cmd)
247 247 ip.magic("macro test 1-3")
248 248 nt.assert_equal(ip.user_ns["test"].value, "\n".join(cmds)+"\n")
249 249
250 250 # List macros
251 251 nt.assert_in("test", ip.magic("macro"))
252 252
253 253
254 254 @dec.skip_without('sqlite3')
255 255 def test_macro_run():
256 256 """Test that we can run a multi-line macro successfully."""
257 257 ip = get_ipython()
258 258 ip.history_manager.reset()
259 259 cmds = ["a=10", "a+=1", py3compat.doctest_refactor_print("print a"),
260 260 "%macro test 2-3"]
261 261 for cmd in cmds:
262 262 ip.run_cell(cmd, store_history=True)
263 263 nt.assert_equal(ip.user_ns["test"].value,
264 264 py3compat.doctest_refactor_print("a+=1\nprint a\n"))
265 265 with tt.AssertPrints("12"):
266 266 ip.run_cell("test")
267 267 with tt.AssertPrints("13"):
268 268 ip.run_cell("test")
269 269
270 270
271 271 def test_magic_magic():
272 272 """Test %magic"""
273 273 ip = get_ipython()
274 274 with capture_output() as captured:
275 275 ip.magic("magic")
276 276
277 277 stdout = captured.stdout
278 278 nt.assert_in('%magic', stdout)
279 279 nt.assert_in('IPython', stdout)
280 280 nt.assert_in('Available', stdout)
281 281
282 282
283 283 @dec.skipif_not_numpy
284 284 def test_numpy_reset_array_undec():
285 285 "Test '%reset array' functionality"
286 286 _ip.ex('import numpy as np')
287 287 _ip.ex('a = np.empty(2)')
288 288 nt.assert_in('a', _ip.user_ns)
289 289 _ip.magic('reset -f array')
290 290 nt.assert_not_in('a', _ip.user_ns)
291 291
292 292 def test_reset_out():
293 293 "Test '%reset out' magic"
294 294 _ip.run_cell("parrot = 'dead'", store_history=True)
295 295 # test '%reset -f out', make an Out prompt
296 296 _ip.run_cell("parrot", store_history=True)
297 297 nt.assert_true('dead' in [_ip.user_ns[x] for x in ('_','__','___')])
298 298 _ip.magic('reset -f out')
299 299 nt.assert_false('dead' in [_ip.user_ns[x] for x in ('_','__','___')])
300 300 nt.assert_equal(len(_ip.user_ns['Out']), 0)
301 301
302 302 def test_reset_in():
303 303 "Test '%reset in' magic"
304 304 # test '%reset -f in'
305 305 _ip.run_cell("parrot", store_history=True)
306 306 nt.assert_true('parrot' in [_ip.user_ns[x] for x in ('_i','_ii','_iii')])
307 307 _ip.magic('%reset -f in')
308 308 nt.assert_false('parrot' in [_ip.user_ns[x] for x in ('_i','_ii','_iii')])
309 309 nt.assert_equal(len(set(_ip.user_ns['In'])), 1)
310 310
311 311 def test_reset_dhist():
312 312 "Test '%reset dhist' magic"
313 313 _ip.run_cell("tmp = [d for d in _dh]") # copy before clearing
314 314 _ip.magic('cd ' + os.path.dirname(nt.__file__))
315 315 _ip.magic('cd -')
316 316 nt.assert_true(len(_ip.user_ns['_dh']) > 0)
317 317 _ip.magic('reset -f dhist')
318 318 nt.assert_equal(len(_ip.user_ns['_dh']), 0)
319 319 _ip.run_cell("_dh = [d for d in tmp]") #restore
320 320
321 321 def test_reset_in_length():
322 322 "Test that '%reset in' preserves In[] length"
323 323 _ip.run_cell("print 'foo'")
324 324 _ip.run_cell("reset -f in")
325 325 nt.assert_equal(len(_ip.user_ns['In']), _ip.displayhook.prompt_count+1)
326 326
327 327 def test_tb_syntaxerror():
328 328 """test %tb after a SyntaxError"""
329 329 ip = get_ipython()
330 330 ip.run_cell("for")
331 331
332 332 # trap and validate stdout
333 333 save_stdout = sys.stdout
334 334 try:
335 335 sys.stdout = StringIO()
336 336 ip.run_cell("%tb")
337 337 out = sys.stdout.getvalue()
338 338 finally:
339 339 sys.stdout = save_stdout
340 340 # trim output, and only check the last line
341 341 last_line = out.rstrip().splitlines()[-1].strip()
342 342 nt.assert_equal(last_line, "SyntaxError: invalid syntax")
343 343
344 344
345 345 def test_time():
346 346 ip = get_ipython()
347 347
348 348 with tt.AssertPrints("Wall time: "):
349 349 ip.run_cell("%time None")
350 350
351 351 ip.run_cell("def f(kmjy):\n"
352 352 " %time print (2*kmjy)")
353 353
354 354 with tt.AssertPrints("Wall time: "):
355 355 with tt.AssertPrints("hihi", suppress=False):
356 356 ip.run_cell("f('hi')")
357 357
358 358
359 359 @dec.skip_win32
360 360 def test_time2():
361 361 ip = get_ipython()
362 362
363 363 with tt.AssertPrints("CPU times: user "):
364 364 ip.run_cell("%time None")
365 365
366 366 def test_time3():
367 367 """Erroneous magic function calls, issue gh-3334"""
368 368 ip = get_ipython()
369 369 ip.user_ns.pop('run', None)
370 370
371 371 with tt.AssertNotPrints("not found", channel='stderr'):
372 372 ip.run_cell("%%time\n"
373 373 "run = 0\n"
374 374 "run += 1")
375 375
376 376 def test_doctest_mode():
377 377 "Toggle doctest_mode twice, it should be a no-op and run without error"
378 378 _ip.magic('doctest_mode')
379 379 _ip.magic('doctest_mode')
380 380
381 381
382 382 def test_parse_options():
383 383 """Tests for basic options parsing in magics."""
384 384 # These are only the most minimal of tests, more should be added later. At
385 385 # the very least we check that basic text/unicode calls work OK.
386 386 m = DummyMagics(_ip)
387 387 nt.assert_equal(m.parse_options('foo', '')[1], 'foo')
388 388 nt.assert_equal(m.parse_options(u'foo', '')[1], u'foo')
389 389
390 390
391 391 def test_dirops():
392 392 """Test various directory handling operations."""
393 # curpath = lambda :os.path.splitdrive(os.getcwdu())[1].replace('\\','/')
394 curpath = os.getcwdu
395 startdir = os.getcwdu()
393 # curpath = lambda :os.path.splitdrive(py3compat.getcwd())[1].replace('\\','/')
394 curpath = py3compat.getcwd
395 startdir = py3compat.getcwd()
396 396 ipdir = os.path.realpath(_ip.ipython_dir)
397 397 try:
398 398 _ip.magic('cd "%s"' % ipdir)
399 399 nt.assert_equal(curpath(), ipdir)
400 400 _ip.magic('cd -')
401 401 nt.assert_equal(curpath(), startdir)
402 402 _ip.magic('pushd "%s"' % ipdir)
403 403 nt.assert_equal(curpath(), ipdir)
404 404 _ip.magic('popd')
405 405 nt.assert_equal(curpath(), startdir)
406 406 finally:
407 407 os.chdir(startdir)
408 408
409 409
410 410 def test_xmode():
411 411 # Calling xmode three times should be a no-op
412 412 xmode = _ip.InteractiveTB.mode
413 413 for i in range(3):
414 414 _ip.magic("xmode")
415 415 nt.assert_equal(_ip.InteractiveTB.mode, xmode)
416 416
417 417 def test_reset_hard():
418 418 monitor = []
419 419 class A(object):
420 420 def __del__(self):
421 421 monitor.append(1)
422 422 def __repr__(self):
423 423 return "<A instance>"
424 424
425 425 _ip.user_ns["a"] = A()
426 426 _ip.run_cell("a")
427 427
428 428 nt.assert_equal(monitor, [])
429 429 _ip.magic("reset -f")
430 430 nt.assert_equal(monitor, [1])
431 431
432 432 class TestXdel(tt.TempFileMixin):
433 433 def test_xdel(self):
434 434 """Test that references from %run are cleared by xdel."""
435 435 src = ("class A(object):\n"
436 436 " monitor = []\n"
437 437 " def __del__(self):\n"
438 438 " self.monitor.append(1)\n"
439 439 "a = A()\n")
440 440 self.mktmp(src)
441 441 # %run creates some hidden references...
442 442 _ip.magic("run %s" % self.fname)
443 443 # ... as does the displayhook.
444 444 _ip.run_cell("a")
445 445
446 446 monitor = _ip.user_ns["A"].monitor
447 447 nt.assert_equal(monitor, [])
448 448
449 449 _ip.magic("xdel a")
450 450
451 451 # Check that a's __del__ method has been called.
452 452 nt.assert_equal(monitor, [1])
453 453
454 454 def doctest_who():
455 455 """doctest for %who
456 456
457 457 In [1]: %reset -f
458 458
459 459 In [2]: alpha = 123
460 460
461 461 In [3]: beta = 'beta'
462 462
463 463 In [4]: %who int
464 464 alpha
465 465
466 466 In [5]: %who str
467 467 beta
468 468
469 469 In [6]: %whos
470 470 Variable Type Data/Info
471 471 ----------------------------
472 472 alpha int 123
473 473 beta str beta
474 474
475 475 In [7]: %who_ls
476 476 Out[7]: ['alpha', 'beta']
477 477 """
478 478
479 479 def test_whos():
480 480 """Check that whos is protected against objects where repr() fails."""
481 481 class A(object):
482 482 def __repr__(self):
483 483 raise Exception()
484 484 _ip.user_ns['a'] = A()
485 485 _ip.magic("whos")
486 486
487 487 @py3compat.u_format
488 488 def doctest_precision():
489 489 """doctest for %precision
490 490
491 491 In [1]: f = get_ipython().display_formatter.formatters['text/plain']
492 492
493 493 In [2]: %precision 5
494 494 Out[2]: {u}'%.5f'
495 495
496 496 In [3]: f.float_format
497 497 Out[3]: {u}'%.5f'
498 498
499 499 In [4]: %precision %e
500 500 Out[4]: {u}'%e'
501 501
502 502 In [5]: f(3.1415927)
503 503 Out[5]: {u}'3.141593e+00'
504 504 """
505 505
506 506 def test_psearch():
507 507 with tt.AssertPrints("dict.fromkeys"):
508 508 _ip.run_cell("dict.fr*?")
509 509
510 510 def test_timeit_shlex():
511 511 """test shlex issues with timeit (#1109)"""
512 512 _ip.ex("def f(*a,**kw): pass")
513 513 _ip.magic('timeit -n1 "this is a bug".count(" ")')
514 514 _ip.magic('timeit -r1 -n1 f(" ", 1)')
515 515 _ip.magic('timeit -r1 -n1 f(" ", 1, " ", 2, " ")')
516 516 _ip.magic('timeit -r1 -n1 ("a " + "b")')
517 517 _ip.magic('timeit -r1 -n1 f("a " + "b")')
518 518 _ip.magic('timeit -r1 -n1 f("a " + "b ")')
519 519
520 520
521 521 def test_timeit_arguments():
522 522 "Test valid timeit arguments, should not cause SyntaxError (GH #1269)"
523 523 _ip.magic("timeit ('#')")
524 524
525 525
526 526 def test_timeit_special_syntax():
527 527 "Test %%timeit with IPython special syntax"
528 528 @register_line_magic
529 529 def lmagic(line):
530 530 ip = get_ipython()
531 531 ip.user_ns['lmagic_out'] = line
532 532
533 533 # line mode test
534 534 _ip.run_line_magic('timeit', '-n1 -r1 %lmagic my line')
535 535 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line')
536 536 # cell mode test
537 537 _ip.run_cell_magic('timeit', '-n1 -r1', '%lmagic my line2')
538 538 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line2')
539 539
540 540 def test_timeit_return():
541 541 """
542 542 test wether timeit -o return object
543 543 """
544 544
545 545 res = _ip.run_line_magic('timeit','-n10 -r10 -o 1')
546 546 assert(res is not None)
547 547
548 548 def test_timeit_quiet():
549 549 """
550 550 test quiet option of timeit magic
551 551 """
552 552 with tt.AssertNotPrints("loops"):
553 553 _ip.run_cell("%timeit -n1 -r1 -q 1")
554 554
555 555 @dec.skipif(execution.profile is None)
556 556 def test_prun_special_syntax():
557 557 "Test %%prun with IPython special syntax"
558 558 @register_line_magic
559 559 def lmagic(line):
560 560 ip = get_ipython()
561 561 ip.user_ns['lmagic_out'] = line
562 562
563 563 # line mode test
564 564 _ip.run_line_magic('prun', '-q %lmagic my line')
565 565 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line')
566 566 # cell mode test
567 567 _ip.run_cell_magic('prun', '-q', '%lmagic my line2')
568 568 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line2')
569 569
570 570 @dec.skipif(execution.profile is None)
571 571 def test_prun_quotes():
572 572 "Test that prun does not clobber string escapes (GH #1302)"
573 573 _ip.magic(r"prun -q x = '\t'")
574 574 nt.assert_equal(_ip.user_ns['x'], '\t')
575 575
576 576 def test_extension():
577 577 tmpdir = TemporaryDirectory()
578 578 orig_ipython_dir = _ip.ipython_dir
579 579 try:
580 580 _ip.ipython_dir = tmpdir.name
581 581 nt.assert_raises(ImportError, _ip.magic, "load_ext daft_extension")
582 582 url = os.path.join(os.path.dirname(__file__), "daft_extension.py")
583 583 _ip.magic("install_ext %s" % url)
584 584 _ip.user_ns.pop('arq', None)
585 585 invalidate_caches() # Clear import caches
586 586 _ip.magic("load_ext daft_extension")
587 587 nt.assert_equal(_ip.user_ns['arq'], 185)
588 588 _ip.magic("unload_ext daft_extension")
589 589 assert 'arq' not in _ip.user_ns
590 590 finally:
591 591 _ip.ipython_dir = orig_ipython_dir
592 592 tmpdir.cleanup()
593 593
594 594 def test_notebook_export_json():
595 595 with TemporaryDirectory() as td:
596 596 outfile = os.path.join(td, "nb.ipynb")
597 597 _ip.ex(py3compat.u_format(u"u = {u}'héllo'"))
598 598 _ip.magic("notebook -e %s" % outfile)
599 599
600 600 def test_notebook_export_py():
601 601 with TemporaryDirectory() as td:
602 602 outfile = os.path.join(td, "nb.py")
603 603 _ip.ex(py3compat.u_format(u"u = {u}'héllo'"))
604 604 _ip.magic("notebook -e %s" % outfile)
605 605
606 606 def test_notebook_reformat_py():
607 607 with TemporaryDirectory() as td:
608 608 infile = os.path.join(td, "nb.ipynb")
609 609 with io.open(infile, 'w', encoding='utf-8') as f:
610 610 current.write(nb0, f, 'json')
611 611
612 612 _ip.ex(py3compat.u_format(u"u = {u}'héllo'"))
613 613 _ip.magic("notebook -f py %s" % infile)
614 614
615 615 def test_notebook_reformat_json():
616 616 with TemporaryDirectory() as td:
617 617 infile = os.path.join(td, "nb.py")
618 618 with io.open(infile, 'w', encoding='utf-8') as f:
619 619 current.write(nb0, f, 'py')
620 620
621 621 _ip.ex(py3compat.u_format(u"u = {u}'héllo'"))
622 622 _ip.magic("notebook -f ipynb %s" % infile)
623 623 _ip.magic("notebook -f json %s" % infile)
624 624
625 625 def test_env():
626 626 env = _ip.magic("env")
627 627 assert isinstance(env, dict), type(env)
628 628
629 629
630 630 class CellMagicTestCase(TestCase):
631 631
632 632 def check_ident(self, magic):
633 633 # Manually called, we get the result
634 634 out = _ip.run_cell_magic(magic, 'a', 'b')
635 635 nt.assert_equal(out, ('a','b'))
636 636 # Via run_cell, it goes into the user's namespace via displayhook
637 637 _ip.run_cell('%%' + magic +' c\nd')
638 638 nt.assert_equal(_ip.user_ns['_'], ('c','d'))
639 639
640 640 def test_cell_magic_func_deco(self):
641 641 "Cell magic using simple decorator"
642 642 @register_cell_magic
643 643 def cellm(line, cell):
644 644 return line, cell
645 645
646 646 self.check_ident('cellm')
647 647
648 648 def test_cell_magic_reg(self):
649 649 "Cell magic manually registered"
650 650 def cellm(line, cell):
651 651 return line, cell
652 652
653 653 _ip.register_magic_function(cellm, 'cell', 'cellm2')
654 654 self.check_ident('cellm2')
655 655
656 656 def test_cell_magic_class(self):
657 657 "Cell magics declared via a class"
658 658 @magics_class
659 659 class MyMagics(Magics):
660 660
661 661 @cell_magic
662 662 def cellm3(self, line, cell):
663 663 return line, cell
664 664
665 665 _ip.register_magics(MyMagics)
666 666 self.check_ident('cellm3')
667 667
668 668 def test_cell_magic_class2(self):
669 669 "Cell magics declared via a class, #2"
670 670 @magics_class
671 671 class MyMagics2(Magics):
672 672
673 673 @cell_magic('cellm4')
674 674 def cellm33(self, line, cell):
675 675 return line, cell
676 676
677 677 _ip.register_magics(MyMagics2)
678 678 self.check_ident('cellm4')
679 679 # Check that nothing is registered as 'cellm33'
680 680 c33 = _ip.find_cell_magic('cellm33')
681 681 nt.assert_equal(c33, None)
682 682
683 683 def test_file():
684 684 """Basic %%file"""
685 685 ip = get_ipython()
686 686 with TemporaryDirectory() as td:
687 687 fname = os.path.join(td, 'file1')
688 688 ip.run_cell_magic("file", fname, u'\n'.join([
689 689 'line1',
690 690 'line2',
691 691 ]))
692 692 with open(fname) as f:
693 693 s = f.read()
694 694 nt.assert_in('line1\n', s)
695 695 nt.assert_in('line2', s)
696 696
697 697 def test_file_var_expand():
698 698 """%%file $filename"""
699 699 ip = get_ipython()
700 700 with TemporaryDirectory() as td:
701 701 fname = os.path.join(td, 'file1')
702 702 ip.user_ns['filename'] = fname
703 703 ip.run_cell_magic("file", '$filename', u'\n'.join([
704 704 'line1',
705 705 'line2',
706 706 ]))
707 707 with open(fname) as f:
708 708 s = f.read()
709 709 nt.assert_in('line1\n', s)
710 710 nt.assert_in('line2', s)
711 711
712 712 def test_file_unicode():
713 713 """%%file with unicode cell"""
714 714 ip = get_ipython()
715 715 with TemporaryDirectory() as td:
716 716 fname = os.path.join(td, 'file1')
717 717 ip.run_cell_magic("file", fname, u'\n'.join([
718 718 u'liné1',
719 719 u'liné2',
720 720 ]))
721 721 with io.open(fname, encoding='utf-8') as f:
722 722 s = f.read()
723 723 nt.assert_in(u'liné1\n', s)
724 724 nt.assert_in(u'liné2', s)
725 725
726 726 def test_file_amend():
727 727 """%%file -a amends files"""
728 728 ip = get_ipython()
729 729 with TemporaryDirectory() as td:
730 730 fname = os.path.join(td, 'file2')
731 731 ip.run_cell_magic("file", fname, u'\n'.join([
732 732 'line1',
733 733 'line2',
734 734 ]))
735 735 ip.run_cell_magic("file", "-a %s" % fname, u'\n'.join([
736 736 'line3',
737 737 'line4',
738 738 ]))
739 739 with open(fname) as f:
740 740 s = f.read()
741 741 nt.assert_in('line1\n', s)
742 742 nt.assert_in('line3\n', s)
743 743
744 744
745 745 def test_script_config():
746 746 ip = get_ipython()
747 747 ip.config.ScriptMagics.script_magics = ['whoda']
748 748 sm = script.ScriptMagics(shell=ip)
749 749 nt.assert_in('whoda', sm.magics['cell'])
750 750
751 751 @dec.skip_win32
752 752 def test_script_out():
753 753 ip = get_ipython()
754 754 ip.run_cell_magic("script", "--out output sh", "echo 'hi'")
755 755 nt.assert_equal(ip.user_ns['output'], 'hi\n')
756 756
757 757 @dec.skip_win32
758 758 def test_script_err():
759 759 ip = get_ipython()
760 760 ip.run_cell_magic("script", "--err error sh", "echo 'hello' >&2")
761 761 nt.assert_equal(ip.user_ns['error'], 'hello\n')
762 762
763 763 @dec.skip_win32
764 764 def test_script_out_err():
765 765 ip = get_ipython()
766 766 ip.run_cell_magic("script", "--out output --err error sh", "echo 'hi'\necho 'hello' >&2")
767 767 nt.assert_equal(ip.user_ns['output'], 'hi\n')
768 768 nt.assert_equal(ip.user_ns['error'], 'hello\n')
769 769
770 770 @dec.skip_win32
771 771 def test_script_bg_out():
772 772 ip = get_ipython()
773 773 ip.run_cell_magic("script", "--bg --out output sh", "echo 'hi'")
774 774 nt.assert_equal(ip.user_ns['output'].read(), b'hi\n')
775 775
776 776 @dec.skip_win32
777 777 def test_script_bg_err():
778 778 ip = get_ipython()
779 779 ip.run_cell_magic("script", "--bg --err error sh", "echo 'hello' >&2")
780 780 nt.assert_equal(ip.user_ns['error'].read(), b'hello\n')
781 781
782 782 @dec.skip_win32
783 783 def test_script_bg_out_err():
784 784 ip = get_ipython()
785 785 ip.run_cell_magic("script", "--bg --out output --err error sh", "echo 'hi'\necho 'hello' >&2")
786 786 nt.assert_equal(ip.user_ns['output'].read(), b'hi\n')
787 787 nt.assert_equal(ip.user_ns['error'].read(), b'hello\n')
788 788
789 789 def test_script_defaults():
790 790 ip = get_ipython()
791 791 for cmd in ['sh', 'bash', 'perl', 'ruby']:
792 792 try:
793 793 find_cmd(cmd)
794 794 except Exception:
795 795 pass
796 796 else:
797 797 nt.assert_in(cmd, ip.magics_manager.magics['cell'])
798 798
799 799
800 800 @magics_class
801 801 class FooFoo(Magics):
802 802 """class with both %foo and %%foo magics"""
803 803 @line_magic('foo')
804 804 def line_foo(self, line):
805 805 "I am line foo"
806 806 pass
807 807
808 808 @cell_magic("foo")
809 809 def cell_foo(self, line, cell):
810 810 "I am cell foo, not line foo"
811 811 pass
812 812
813 813 def test_line_cell_info():
814 814 """%%foo and %foo magics are distinguishable to inspect"""
815 815 ip = get_ipython()
816 816 ip.magics_manager.register(FooFoo)
817 817 oinfo = ip.object_inspect('foo')
818 818 nt.assert_true(oinfo['found'])
819 819 nt.assert_true(oinfo['ismagic'])
820 820
821 821 oinfo = ip.object_inspect('%%foo')
822 822 nt.assert_true(oinfo['found'])
823 823 nt.assert_true(oinfo['ismagic'])
824 824 nt.assert_equal(oinfo['docstring'], FooFoo.cell_foo.__doc__)
825 825
826 826 oinfo = ip.object_inspect('%foo')
827 827 nt.assert_true(oinfo['found'])
828 828 nt.assert_true(oinfo['ismagic'])
829 829 nt.assert_equal(oinfo['docstring'], FooFoo.line_foo.__doc__)
830 830
831 831 def test_multiple_magics():
832 832 ip = get_ipython()
833 833 foo1 = FooFoo(ip)
834 834 foo2 = FooFoo(ip)
835 835 mm = ip.magics_manager
836 836 mm.register(foo1)
837 837 nt.assert_true(mm.magics['line']['foo'].__self__ is foo1)
838 838 mm.register(foo2)
839 839 nt.assert_true(mm.magics['line']['foo'].__self__ is foo2)
840 840
841 841 def test_alias_magic():
842 842 """Test %alias_magic."""
843 843 ip = get_ipython()
844 844 mm = ip.magics_manager
845 845
846 846 # Basic operation: both cell and line magics are created, if possible.
847 847 ip.run_line_magic('alias_magic', 'timeit_alias timeit')
848 848 nt.assert_in('timeit_alias', mm.magics['line'])
849 849 nt.assert_in('timeit_alias', mm.magics['cell'])
850 850
851 851 # --cell is specified, line magic not created.
852 852 ip.run_line_magic('alias_magic', '--cell timeit_cell_alias timeit')
853 853 nt.assert_not_in('timeit_cell_alias', mm.magics['line'])
854 854 nt.assert_in('timeit_cell_alias', mm.magics['cell'])
855 855
856 856 # Test that line alias is created successfully.
857 857 ip.run_line_magic('alias_magic', '--line env_alias env')
858 858 nt.assert_equal(ip.run_line_magic('env', ''),
859 859 ip.run_line_magic('env_alias', ''))
860 860
861 861 def test_save():
862 862 """Test %save."""
863 863 ip = get_ipython()
864 864 ip.history_manager.reset() # Clear any existing history.
865 865 cmds = [u"a=1", u"def b():\n return a**2", u"print(a, b())"]
866 866 for i, cmd in enumerate(cmds, start=1):
867 867 ip.history_manager.store_inputs(i, cmd)
868 868 with TemporaryDirectory() as tmpdir:
869 869 file = os.path.join(tmpdir, "testsave.py")
870 870 ip.run_line_magic("save", "%s 1-10" % file)
871 871 with open(file) as f:
872 872 content = f.read()
873 873 nt.assert_equal(content.count(cmds[0]), 1)
874 874 nt.assert_in('coding: utf-8', content)
875 875 ip.run_line_magic("save", "-a %s 1-10" % file)
876 876 with open(file) as f:
877 877 content = f.read()
878 878 nt.assert_equal(content.count(cmds[0]), 2)
879 879 nt.assert_in('coding: utf-8', content)
880 880
881 881
882 882 def test_store():
883 883 """Test %store."""
884 884 ip = get_ipython()
885 885 ip.run_line_magic('load_ext', 'storemagic')
886 886
887 887 # make sure the storage is empty
888 888 ip.run_line_magic('store', '-z')
889 889 ip.user_ns['var'] = 42
890 890 ip.run_line_magic('store', 'var')
891 891 ip.user_ns['var'] = 39
892 892 ip.run_line_magic('store', '-r')
893 893 nt.assert_equal(ip.user_ns['var'], 42)
894 894
895 895 ip.run_line_magic('store', '-d var')
896 896 ip.user_ns['var'] = 39
897 897 ip.run_line_magic('store' , '-r')
898 898 nt.assert_equal(ip.user_ns['var'], 39)
899 899
900 900
901 901 def _run_edit_test(arg_s, exp_filename=None,
902 902 exp_lineno=-1,
903 903 exp_contents=None,
904 904 exp_is_temp=None):
905 905 ip = get_ipython()
906 906 M = code.CodeMagics(ip)
907 907 last_call = ['','']
908 908 opts,args = M.parse_options(arg_s,'prxn:')
909 909 filename, lineno, is_temp = M._find_edit_target(ip, args, opts, last_call)
910 910
911 911 if exp_filename is not None:
912 912 nt.assert_equal(exp_filename, filename)
913 913 if exp_contents is not None:
914 914 with io.open(filename, 'r') as f:
915 915 contents = f.read()
916 916 nt.assert_equal(exp_contents, contents)
917 917 if exp_lineno != -1:
918 918 nt.assert_equal(exp_lineno, lineno)
919 919 if exp_is_temp is not None:
920 920 nt.assert_equal(exp_is_temp, is_temp)
921 921
922 922
923 923 def test_edit_interactive():
924 924 """%edit on interactively defined objects"""
925 925 ip = get_ipython()
926 926 n = ip.execution_count
927 927 ip.run_cell(u"def foo(): return 1", store_history=True)
928 928
929 929 try:
930 930 _run_edit_test("foo")
931 931 except code.InteractivelyDefined as e:
932 932 nt.assert_equal(e.index, n)
933 933 else:
934 934 raise AssertionError("Should have raised InteractivelyDefined")
935 935
936 936
937 937 def test_edit_cell():
938 938 """%edit [cell id]"""
939 939 ip = get_ipython()
940 940
941 941 ip.run_cell(u"def foo(): return 1", store_history=True)
942 942
943 943 # test
944 944 _run_edit_test("1", exp_contents=ip.user_ns['In'][1], exp_is_temp=True)
@@ -1,111 +1,112 b''
1 1 # -*- coding: utf-8
2 2 """Tests for prompt generation."""
3 3
4 4 import unittest
5 5
6 6 import os
7 7
8 8 from IPython.testing import tools as tt, decorators as dec
9 9 from IPython.core.prompts import PromptManager, LazyEvaluate
10 10 from IPython.testing.globalipapp import get_ipython
11 11 from IPython.utils.tempdir import TemporaryDirectory
12 from IPython.utils import py3compat
12 13 from IPython.utils.py3compat import unicode_type
13 14
14 15 ip = get_ipython()
15 16
16 17
17 18 class PromptTests(unittest.TestCase):
18 19 def setUp(self):
19 20 self.pm = PromptManager(shell=ip, config=ip.config)
20 21
21 22 def test_multiline_prompt(self):
22 23 self.pm.in_template = "[In]\n>>>"
23 24 self.pm.render('in')
24 25 self.assertEqual(self.pm.width, 3)
25 26 self.assertEqual(self.pm.txtwidth, 3)
26 27
27 28 self.pm.in_template = '[In]\n'
28 29 self.pm.render('in')
29 30 self.assertEqual(self.pm.width, 0)
30 31 self.assertEqual(self.pm.txtwidth, 0)
31 32
32 33 def test_translate_abbreviations(self):
33 34 def do_translate(template):
34 35 self.pm.in_template = template
35 36 return self.pm.templates['in']
36 37
37 38 pairs = [(r'%n>', '{color.number}{count}{color.prompt}>'),
38 39 (r'\T', '{time}'),
39 40 (r'\n', '\n')
40 41 ]
41 42
42 43 tt.check_pairs(do_translate, pairs)
43 44
44 45 def test_user_ns(self):
45 46 self.pm.color_scheme = 'NoColor'
46 47 ip.ex("foo='bar'")
47 48 self.pm.in_template = "In [{foo}]"
48 49 prompt = self.pm.render('in')
49 50 self.assertEqual(prompt, u'In [bar]')
50 51
51 52 def test_builtins(self):
52 53 self.pm.color_scheme = 'NoColor'
53 54 self.pm.in_template = "In [{int}]"
54 55 prompt = self.pm.render('in')
55 56 self.assertEqual(prompt, u"In [%r]" % int)
56 57
57 58 def test_undefined(self):
58 59 self.pm.color_scheme = 'NoColor'
59 60 self.pm.in_template = "In [{foo_dne}]"
60 61 prompt = self.pm.render('in')
61 62 self.assertEqual(prompt, u"In [<ERROR: 'foo_dne' not found>]")
62 63
63 64 def test_render(self):
64 65 self.pm.in_template = r'\#>'
65 66 self.assertEqual(self.pm.render('in',color=False), '%d>' % ip.execution_count)
66 67
67 68 @dec.onlyif_unicode_paths
68 69 def test_render_unicode_cwd(self):
69 save = os.getcwdu()
70 save = py3compat.getcwd()
70 71 with TemporaryDirectory(u'ünicødé') as td:
71 72 os.chdir(td)
72 73 self.pm.in_template = r'\w [\#]'
73 74 p = self.pm.render('in', color=False)
74 self.assertEqual(p, u"%s [%i]" % (os.getcwdu(), ip.execution_count))
75 self.assertEqual(p, u"%s [%i]" % (py3compat.getcwd(), ip.execution_count))
75 76 os.chdir(save)
76 77
77 78 def test_lazy_eval_unicode(self):
78 79 u = u'ünicødé'
79 80 lz = LazyEvaluate(lambda : u)
80 81 # str(lz) would fail
81 82 self.assertEqual(unicode_type(lz), u)
82 83 self.assertEqual(format(lz), u)
83 84
84 85 def test_lazy_eval_nonascii_bytes(self):
85 86 u = u'ünicødé'
86 87 b = u.encode('utf8')
87 88 lz = LazyEvaluate(lambda : b)
88 89 # unicode(lz) would fail
89 90 self.assertEqual(str(lz), str(b))
90 91 self.assertEqual(format(lz), str(b))
91 92
92 93 def test_lazy_eval_float(self):
93 94 f = 0.503
94 95 lz = LazyEvaluate(lambda : f)
95 96
96 97 self.assertEqual(str(lz), str(f))
97 98 self.assertEqual(unicode_type(lz), unicode_type(f))
98 99 self.assertEqual(format(lz), str(f))
99 100 self.assertEqual(format(lz, '.1'), '0.5')
100 101
101 102 @dec.skip_win32
102 103 def test_cwd_x(self):
103 104 self.pm.in_template = r"\X0"
104 save = os.getcwdu()
105 save = py3compat.getcwd()
105 106 os.chdir(os.path.expanduser('~'))
106 107 p = self.pm.render('in', color=False)
107 108 try:
108 109 self.assertEqual(p, '~')
109 110 finally:
110 111 os.chdir(save)
111 112
@@ -1,458 +1,458 b''
1 1 # encoding: utf-8
2 2 """Tests for code execution (%run and related), which is particularly tricky.
3 3
4 4 Because of how %run manages namespaces, and the fact that we are trying here to
5 5 verify subtle object deletion and reference counting issues, the %run tests
6 6 will be kept in this separate file. This makes it easier to aggregate in one
7 7 place the tricks needed to handle it; most other magics are much easier to test
8 8 and we do so in a common test_magic file.
9 9 """
10 10 from __future__ import absolute_import
11 11
12 12 #-----------------------------------------------------------------------------
13 13 # Imports
14 14 #-----------------------------------------------------------------------------
15 15
16 16 import functools
17 17 import os
18 18 from os.path import join as pjoin
19 19 import random
20 20 import sys
21 21 import tempfile
22 22 import textwrap
23 23 import unittest
24 24
25 25 import nose.tools as nt
26 26 from nose import SkipTest
27 27
28 28 from IPython.testing import decorators as dec
29 29 from IPython.testing import tools as tt
30 30 from IPython.utils import py3compat
31 31 from IPython.utils.tempdir import TemporaryDirectory
32 32 from IPython.core import debugger
33 33
34 34 #-----------------------------------------------------------------------------
35 35 # Test functions begin
36 36 #-----------------------------------------------------------------------------
37 37
38 38 def doctest_refbug():
39 39 """Very nasty problem with references held by multiple runs of a script.
40 40 See: https://github.com/ipython/ipython/issues/141
41 41
42 42 In [1]: _ip.clear_main_mod_cache()
43 43 # random
44 44
45 45 In [2]: %run refbug
46 46
47 47 In [3]: call_f()
48 48 lowercased: hello
49 49
50 50 In [4]: %run refbug
51 51
52 52 In [5]: call_f()
53 53 lowercased: hello
54 54 lowercased: hello
55 55 """
56 56
57 57
58 58 def doctest_run_builtins():
59 59 r"""Check that %run doesn't damage __builtins__.
60 60
61 61 In [1]: import tempfile
62 62
63 63 In [2]: bid1 = id(__builtins__)
64 64
65 65 In [3]: fname = tempfile.mkstemp('.py')[1]
66 66
67 67 In [3]: f = open(fname,'w')
68 68
69 69 In [4]: dummy= f.write('pass\n')
70 70
71 71 In [5]: f.flush()
72 72
73 73 In [6]: t1 = type(__builtins__)
74 74
75 75 In [7]: %run $fname
76 76
77 77 In [7]: f.close()
78 78
79 79 In [8]: bid2 = id(__builtins__)
80 80
81 81 In [9]: t2 = type(__builtins__)
82 82
83 83 In [10]: t1 == t2
84 84 Out[10]: True
85 85
86 86 In [10]: bid1 == bid2
87 87 Out[10]: True
88 88
89 89 In [12]: try:
90 90 ....: os.unlink(fname)
91 91 ....: except:
92 92 ....: pass
93 93 ....:
94 94 """
95 95
96 96
97 97 def doctest_run_option_parser():
98 98 r"""Test option parser in %run.
99 99
100 100 In [1]: %run print_argv.py
101 101 []
102 102
103 103 In [2]: %run print_argv.py print*.py
104 104 ['print_argv.py']
105 105
106 106 In [3]: %run -G print_argv.py print*.py
107 107 ['print*.py']
108 108
109 109 """
110 110
111 111
112 112 @dec.skip_win32
113 113 def doctest_run_option_parser_for_posix():
114 114 r"""Test option parser in %run (Linux/OSX specific).
115 115
116 116 You need double quote to escape glob in POSIX systems:
117 117
118 118 In [1]: %run print_argv.py print\\*.py
119 119 ['print*.py']
120 120
121 121 You can't use quote to escape glob in POSIX systems:
122 122
123 123 In [2]: %run print_argv.py 'print*.py'
124 124 ['print_argv.py']
125 125
126 126 """
127 127
128 128
129 129 @dec.skip_if_not_win32
130 130 def doctest_run_option_parser_for_windows():
131 131 r"""Test option parser in %run (Windows specific).
132 132
133 133 In Windows, you can't escape ``*` `by backslash:
134 134
135 135 In [1]: %run print_argv.py print\\*.py
136 136 ['print\\*.py']
137 137
138 138 You can use quote to escape glob:
139 139
140 140 In [2]: %run print_argv.py 'print*.py'
141 141 ['print*.py']
142 142
143 143 """
144 144
145 145
146 146 @py3compat.doctest_refactor_print
147 147 def doctest_reset_del():
148 148 """Test that resetting doesn't cause errors in __del__ methods.
149 149
150 150 In [2]: class A(object):
151 151 ...: def __del__(self):
152 152 ...: print str("Hi")
153 153 ...:
154 154
155 155 In [3]: a = A()
156 156
157 157 In [4]: get_ipython().reset()
158 158 Hi
159 159
160 160 In [5]: 1+1
161 161 Out[5]: 2
162 162 """
163 163
164 164 # For some tests, it will be handy to organize them in a class with a common
165 165 # setup that makes a temp file
166 166
167 167 class TestMagicRunPass(tt.TempFileMixin):
168 168
169 169 def setup(self):
170 170 """Make a valid python temp file."""
171 171 self.mktmp('pass\n')
172 172
173 173 def run_tmpfile(self):
174 174 _ip = get_ipython()
175 175 # This fails on Windows if self.tmpfile.name has spaces or "~" in it.
176 176 # See below and ticket https://bugs.launchpad.net/bugs/366353
177 177 _ip.magic('run %s' % self.fname)
178 178
179 179 def run_tmpfile_p(self):
180 180 _ip = get_ipython()
181 181 # This fails on Windows if self.tmpfile.name has spaces or "~" in it.
182 182 # See below and ticket https://bugs.launchpad.net/bugs/366353
183 183 _ip.magic('run -p %s' % self.fname)
184 184
185 185 def test_builtins_id(self):
186 186 """Check that %run doesn't damage __builtins__ """
187 187 _ip = get_ipython()
188 188 # Test that the id of __builtins__ is not modified by %run
189 189 bid1 = id(_ip.user_ns['__builtins__'])
190 190 self.run_tmpfile()
191 191 bid2 = id(_ip.user_ns['__builtins__'])
192 192 nt.assert_equal(bid1, bid2)
193 193
194 194 def test_builtins_type(self):
195 195 """Check that the type of __builtins__ doesn't change with %run.
196 196
197 197 However, the above could pass if __builtins__ was already modified to
198 198 be a dict (it should be a module) by a previous use of %run. So we
199 199 also check explicitly that it really is a module:
200 200 """
201 201 _ip = get_ipython()
202 202 self.run_tmpfile()
203 203 nt.assert_equal(type(_ip.user_ns['__builtins__']),type(sys))
204 204
205 205 def test_prompts(self):
206 206 """Test that prompts correctly generate after %run"""
207 207 self.run_tmpfile()
208 208 _ip = get_ipython()
209 209 p2 = _ip.prompt_manager.render('in2').strip()
210 210 nt.assert_equal(p2[:3], '...')
211 211
212 212 def test_run_profile( self ):
213 213 """Test that the option -p, which invokes the profiler, do not
214 214 crash by invoking execfile"""
215 215 _ip = get_ipython()
216 216 self.run_tmpfile_p()
217 217
218 218
219 219 class TestMagicRunSimple(tt.TempFileMixin):
220 220
221 221 def test_simpledef(self):
222 222 """Test that simple class definitions work."""
223 223 src = ("class foo: pass\n"
224 224 "def f(): return foo()")
225 225 self.mktmp(src)
226 226 _ip.magic('run %s' % self.fname)
227 227 _ip.run_cell('t = isinstance(f(), foo)')
228 228 nt.assert_true(_ip.user_ns['t'])
229 229
230 230 def test_obj_del(self):
231 231 """Test that object's __del__ methods are called on exit."""
232 232 if sys.platform == 'win32':
233 233 try:
234 234 import win32api
235 235 except ImportError:
236 236 raise SkipTest("Test requires pywin32")
237 237 src = ("class A(object):\n"
238 238 " def __del__(self):\n"
239 239 " print 'object A deleted'\n"
240 240 "a = A()\n")
241 241 self.mktmp(py3compat.doctest_refactor_print(src))
242 242 if dec.module_not_available('sqlite3'):
243 243 err = 'WARNING: IPython History requires SQLite, your history will not be saved\n'
244 244 else:
245 245 err = None
246 246 tt.ipexec_validate(self.fname, 'object A deleted', err)
247 247
248 248 def test_aggressive_namespace_cleanup(self):
249 249 """Test that namespace cleanup is not too aggressive GH-238
250 250
251 251 Returning from another run magic deletes the namespace"""
252 252 # see ticket https://github.com/ipython/ipython/issues/238
253 253 class secondtmp(tt.TempFileMixin): pass
254 254 empty = secondtmp()
255 255 empty.mktmp('')
256 256 # On Windows, the filename will have \users in it, so we need to use the
257 257 # repr so that the \u becomes \\u.
258 258 src = ("ip = get_ipython()\n"
259 259 "for i in range(5):\n"
260 260 " try:\n"
261 261 " ip.magic(%r)\n"
262 262 " except NameError as e:\n"
263 263 " print(i)\n"
264 264 " break\n" % ('run ' + empty.fname))
265 265 self.mktmp(src)
266 266 _ip.magic('run %s' % self.fname)
267 267 _ip.run_cell('ip == get_ipython()')
268 268 nt.assert_equal(_ip.user_ns['i'], 4)
269 269
270 270 def test_run_second(self):
271 271 """Test that running a second file doesn't clobber the first, gh-3547
272 272 """
273 273 self.mktmp("avar = 1\n"
274 274 "def afunc():\n"
275 275 " return avar\n")
276 276
277 277 empty = tt.TempFileMixin()
278 278 empty.mktmp("")
279 279
280 280 _ip.magic('run %s' % self.fname)
281 281 _ip.magic('run %s' % empty.fname)
282 282 nt.assert_equal(_ip.user_ns['afunc'](), 1)
283 283
284 284 @dec.skip_win32
285 285 def test_tclass(self):
286 286 mydir = os.path.dirname(__file__)
287 287 tc = os.path.join(mydir, 'tclass')
288 288 src = ("%%run '%s' C-first\n"
289 289 "%%run '%s' C-second\n"
290 290 "%%run '%s' C-third\n") % (tc, tc, tc)
291 291 self.mktmp(src, '.ipy')
292 292 out = """\
293 293 ARGV 1-: ['C-first']
294 294 ARGV 1-: ['C-second']
295 295 tclass.py: deleting object: C-first
296 296 ARGV 1-: ['C-third']
297 297 tclass.py: deleting object: C-second
298 298 tclass.py: deleting object: C-third
299 299 """
300 300 if dec.module_not_available('sqlite3'):
301 301 err = 'WARNING: IPython History requires SQLite, your history will not be saved\n'
302 302 else:
303 303 err = None
304 304 tt.ipexec_validate(self.fname, out, err)
305 305
306 306 def test_run_i_after_reset(self):
307 307 """Check that %run -i still works after %reset (gh-693)"""
308 308 src = "yy = zz\n"
309 309 self.mktmp(src)
310 310 _ip.run_cell("zz = 23")
311 311 _ip.magic('run -i %s' % self.fname)
312 312 nt.assert_equal(_ip.user_ns['yy'], 23)
313 313 _ip.magic('reset -f')
314 314 _ip.run_cell("zz = 23")
315 315 _ip.magic('run -i %s' % self.fname)
316 316 nt.assert_equal(_ip.user_ns['yy'], 23)
317 317
318 318 def test_unicode(self):
319 319 """Check that files in odd encodings are accepted."""
320 320 mydir = os.path.dirname(__file__)
321 321 na = os.path.join(mydir, 'nonascii.py')
322 322 _ip.magic('run "%s"' % na)
323 323 nt.assert_equal(_ip.user_ns['u'], u'Ўт№Ф')
324 324
325 325 def test_run_py_file_attribute(self):
326 326 """Test handling of `__file__` attribute in `%run <file>.py`."""
327 327 src = "t = __file__\n"
328 328 self.mktmp(src)
329 329 _missing = object()
330 330 file1 = _ip.user_ns.get('__file__', _missing)
331 331 _ip.magic('run %s' % self.fname)
332 332 file2 = _ip.user_ns.get('__file__', _missing)
333 333
334 334 # Check that __file__ was equal to the filename in the script's
335 335 # namespace.
336 336 nt.assert_equal(_ip.user_ns['t'], self.fname)
337 337
338 338 # Check that __file__ was not leaked back into user_ns.
339 339 nt.assert_equal(file1, file2)
340 340
341 341 def test_run_ipy_file_attribute(self):
342 342 """Test handling of `__file__` attribute in `%run <file.ipy>`."""
343 343 src = "t = __file__\n"
344 344 self.mktmp(src, ext='.ipy')
345 345 _missing = object()
346 346 file1 = _ip.user_ns.get('__file__', _missing)
347 347 _ip.magic('run %s' % self.fname)
348 348 file2 = _ip.user_ns.get('__file__', _missing)
349 349
350 350 # Check that __file__ was equal to the filename in the script's
351 351 # namespace.
352 352 nt.assert_equal(_ip.user_ns['t'], self.fname)
353 353
354 354 # Check that __file__ was not leaked back into user_ns.
355 355 nt.assert_equal(file1, file2)
356 356
357 357 def test_run_formatting(self):
358 358 """ Test that %run -t -N<N> does not raise a TypeError for N > 1."""
359 359 src = "pass"
360 360 self.mktmp(src)
361 361 _ip.magic('run -t -N 1 %s' % self.fname)
362 362 _ip.magic('run -t -N 10 %s' % self.fname)
363 363
364 364 def test_ignore_sys_exit(self):
365 365 """Test the -e option to ignore sys.exit()"""
366 366 src = "import sys; sys.exit(1)"
367 367 self.mktmp(src)
368 368 with tt.AssertPrints('SystemExit'):
369 369 _ip.magic('run %s' % self.fname)
370 370
371 371 with tt.AssertNotPrints('SystemExit'):
372 372 _ip.magic('run -e %s' % self.fname)
373 373
374 374
375 375
376 376 class TestMagicRunWithPackage(unittest.TestCase):
377 377
378 378 def writefile(self, name, content):
379 379 path = os.path.join(self.tempdir.name, name)
380 380 d = os.path.dirname(path)
381 381 if not os.path.isdir(d):
382 382 os.makedirs(d)
383 383 with open(path, 'w') as f:
384 384 f.write(textwrap.dedent(content))
385 385
386 386 def setUp(self):
387 387 self.package = package = 'tmp{0}'.format(repr(random.random())[2:])
388 388 """Temporary valid python package name."""
389 389
390 390 self.value = int(random.random() * 10000)
391 391
392 392 self.tempdir = TemporaryDirectory()
393 self.__orig_cwd = os.getcwdu()
393 self.__orig_cwd = py3compat.getcwd()
394 394 sys.path.insert(0, self.tempdir.name)
395 395
396 396 self.writefile(os.path.join(package, '__init__.py'), '')
397 397 self.writefile(os.path.join(package, 'sub.py'), """
398 398 x = {0!r}
399 399 """.format(self.value))
400 400 self.writefile(os.path.join(package, 'relative.py'), """
401 401 from .sub import x
402 402 """)
403 403 self.writefile(os.path.join(package, 'absolute.py'), """
404 404 from {0}.sub import x
405 405 """.format(package))
406 406
407 407 def tearDown(self):
408 408 os.chdir(self.__orig_cwd)
409 409 sys.path[:] = [p for p in sys.path if p != self.tempdir.name]
410 410 self.tempdir.cleanup()
411 411
412 412 def check_run_submodule(self, submodule, opts=''):
413 413 _ip.user_ns.pop('x', None)
414 414 _ip.magic('run {2} -m {0}.{1}'.format(self.package, submodule, opts))
415 415 self.assertEqual(_ip.user_ns['x'], self.value,
416 416 'Variable `x` is not loaded from module `{0}`.'
417 417 .format(submodule))
418 418
419 419 def test_run_submodule_with_absolute_import(self):
420 420 self.check_run_submodule('absolute')
421 421
422 422 def test_run_submodule_with_relative_import(self):
423 423 """Run submodule that has a relative import statement (#2727)."""
424 424 self.check_run_submodule('relative')
425 425
426 426 def test_prun_submodule_with_absolute_import(self):
427 427 self.check_run_submodule('absolute', '-p')
428 428
429 429 def test_prun_submodule_with_relative_import(self):
430 430 self.check_run_submodule('relative', '-p')
431 431
432 432 def with_fake_debugger(func):
433 433 @functools.wraps(func)
434 434 def wrapper(*args, **kwds):
435 435 with tt.monkeypatch(debugger.Pdb, 'run', staticmethod(eval)):
436 436 return func(*args, **kwds)
437 437 return wrapper
438 438
439 439 @with_fake_debugger
440 440 def test_debug_run_submodule_with_absolute_import(self):
441 441 self.check_run_submodule('absolute', '-d')
442 442
443 443 @with_fake_debugger
444 444 def test_debug_run_submodule_with_relative_import(self):
445 445 self.check_run_submodule('relative', '-d')
446 446
447 447 def test_run__name__():
448 448 with TemporaryDirectory() as td:
449 449 path = pjoin(td, 'foo.py')
450 450 with open(path, 'w') as f:
451 451 f.write("q = __name__")
452 452
453 453 _ip.user_ns.pop('q', None)
454 454 _ip.magic('run {}'.format(path))
455 455 nt.assert_equal(_ip.user_ns.pop('q'), '__main__')
456 456
457 457 _ip.magic('run -n {}'.format(path))
458 458 nt.assert_equal(_ip.user_ns.pop('q'), 'foo')
@@ -1,1267 +1,1267 b''
1 1 #
2 2 # Copyright (c) 2010 Mikhail Gusarov
3 3 #
4 4 # Permission is hereby granted, free of charge, to any person obtaining a copy
5 5 # of this software and associated documentation files (the "Software"), to deal
6 6 # in the Software without restriction, including without limitation the rights
7 7 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 8 # copies of the Software, and to permit persons to whom the Software is
9 9 # furnished to do so, subject to the following conditions:
10 10 #
11 11 # The above copyright notice and this permission notice shall be included in
12 12 # all copies or substantial portions of the Software.
13 13 #
14 14 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 15 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 16 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 17 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 18 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 19 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 20 # SOFTWARE.
21 21 #
22 22
23 23 """ path.py - An object representing a path to a file or directory.
24 24
25 25 Original author:
26 26 Jason Orendorff <jason.orendorff\x40gmail\x2ecom>
27 27
28 28 Current maintainer:
29 29 Jason R. Coombs <jaraco@jaraco.com>
30 30
31 31 Contributors:
32 32 Mikhail Gusarov <dottedmag@dottedmag.net>
33 33 Marc Abramowitz <marc@marc-abramowitz.com>
34 34 Jason R. Coombs <jaraco@jaraco.com>
35 35 Jason Chu <jchu@xentac.net>
36 36 Vojislav Stojkovic <vstojkovic@syntertainment.com>
37 37
38 38 Example::
39 39
40 40 from path import path
41 41 d = path('/home/guido/bin')
42 42 for f in d.files('*.py'):
43 43 f.chmod(0755)
44 44
45 45 path.py requires Python 2.5 or later.
46 46 """
47 47
48 48 from __future__ import with_statement
49 49
50 50 import sys
51 51 import warnings
52 52 import os
53 53 import fnmatch
54 54 import glob
55 55 import shutil
56 56 import codecs
57 57 import hashlib
58 58 import errno
59 59 import tempfile
60 60 import functools
61 61 import operator
62 62 import re
63 63
64 64 try:
65 65 import win32security
66 66 except ImportError:
67 67 pass
68 68
69 69 try:
70 70 import pwd
71 71 except ImportError:
72 72 pass
73 73
74 74 ################################
75 75 # Monkey patchy python 3 support
76 76 try:
77 77 basestring
78 78 except NameError:
79 79 basestring = str
80 80
81 81 try:
82 82 unicode
83 83 except NameError:
84 84 unicode = str
85 85
86 86 try:
87 os.getcwdu
87 getcwdu = os.getcwdu
88 88 except AttributeError:
89 os.getcwdu = os.getcwd
89 getcwdu = os.getcwd
90 90
91 91 if sys.version < '3':
92 92 def u(x):
93 93 return codecs.unicode_escape_decode(x)[0]
94 94 else:
95 95 def u(x):
96 96 return x
97 97
98 98 o777 = 511
99 99 o766 = 502
100 100 o666 = 438
101 101 o554 = 364
102 102 ################################
103 103
104 104 __version__ = '4.3'
105 105 __all__ = ['path']
106 106
107 107
108 108 class TreeWalkWarning(Warning):
109 109 pass
110 110
111 111
112 112 def simple_cache(func):
113 113 """
114 114 Save results for the 'using_module' classmethod.
115 115 When Python 3.2 is available, use functools.lru_cache instead.
116 116 """
117 117 saved_results = {}
118 118
119 119 def wrapper(cls, module):
120 120 if module in saved_results:
121 121 return saved_results[module]
122 122 saved_results[module] = func(cls, module)
123 123 return saved_results[module]
124 124 return wrapper
125 125
126 126
127 127 class ClassProperty(property):
128 128 def __get__(self, cls, owner):
129 129 return self.fget.__get__(None, owner)()
130 130
131 131
132 132 class multimethod(object):
133 133 """
134 134 Acts like a classmethod when invoked from the class and like an
135 135 instancemethod when invoked from the instance.
136 136 """
137 137 def __init__(self, func):
138 138 self.func = func
139 139
140 140 def __get__(self, instance, owner):
141 141 return (
142 142 functools.partial(self.func, owner) if instance is None
143 143 else functools.partial(self.func, owner, instance)
144 144 )
145 145
146 146
147 147 class path(unicode):
148 148 """ Represents a filesystem path.
149 149
150 150 For documentation on individual methods, consult their
151 151 counterparts in os.path.
152 152 """
153 153
154 154 module = os.path
155 155 "The path module to use for path operations."
156 156
157 157 def __init__(self, other=''):
158 158 if other is None:
159 159 raise TypeError("Invalid initial value for path: None")
160 160
161 161 @classmethod
162 162 @simple_cache
163 163 def using_module(cls, module):
164 164 subclass_name = cls.__name__ + '_' + module.__name__
165 165 bases = (cls,)
166 166 ns = {'module': module}
167 167 return type(subclass_name, bases, ns)
168 168
169 169 @ClassProperty
170 170 @classmethod
171 171 def _next_class(cls):
172 172 """
173 173 What class should be used to construct new instances from this class
174 174 """
175 175 return cls
176 176
177 177 # --- Special Python methods.
178 178
179 179 def __repr__(self):
180 180 return '%s(%s)' % (type(self).__name__, super(path, self).__repr__())
181 181
182 182 # Adding a path and a string yields a path.
183 183 def __add__(self, more):
184 184 try:
185 185 return self._next_class(super(path, self).__add__(more))
186 186 except TypeError: # Python bug
187 187 return NotImplemented
188 188
189 189 def __radd__(self, other):
190 190 if not isinstance(other, basestring):
191 191 return NotImplemented
192 192 return self._next_class(other.__add__(self))
193 193
194 194 # The / operator joins paths.
195 195 def __div__(self, rel):
196 196 """ fp.__div__(rel) == fp / rel == fp.joinpath(rel)
197 197
198 198 Join two path components, adding a separator character if
199 199 needed.
200 200 """
201 201 return self._next_class(self.module.join(self, rel))
202 202
203 203 # Make the / operator work even when true division is enabled.
204 204 __truediv__ = __div__
205 205
206 206 def __enter__(self):
207 207 self._old_dir = self.getcwd()
208 208 os.chdir(self)
209 209 return self
210 210
211 211 def __exit__(self, *_):
212 212 os.chdir(self._old_dir)
213 213
214 214 @classmethod
215 215 def getcwd(cls):
216 216 """ Return the current working directory as a path object. """
217 return cls(os.getcwdu())
217 return cls(getcwdu())
218 218
219 219 #
220 220 # --- Operations on path strings.
221 221
222 222 def abspath(self):
223 223 return self._next_class(self.module.abspath(self))
224 224
225 225 def normcase(self):
226 226 return self._next_class(self.module.normcase(self))
227 227
228 228 def normpath(self):
229 229 return self._next_class(self.module.normpath(self))
230 230
231 231 def realpath(self):
232 232 return self._next_class(self.module.realpath(self))
233 233
234 234 def expanduser(self):
235 235 return self._next_class(self.module.expanduser(self))
236 236
237 237 def expandvars(self):
238 238 return self._next_class(self.module.expandvars(self))
239 239
240 240 def dirname(self):
241 241 return self._next_class(self.module.dirname(self))
242 242
243 243 def basename(self):
244 244 return self._next_class(self.module.basename(self))
245 245
246 246 def expand(self):
247 247 """ Clean up a filename by calling expandvars(),
248 248 expanduser(), and normpath() on it.
249 249
250 250 This is commonly everything needed to clean up a filename
251 251 read from a configuration file, for example.
252 252 """
253 253 return self.expandvars().expanduser().normpath()
254 254
255 255 @property
256 256 def namebase(self):
257 257 """ The same as path.name, but with one file extension stripped off.
258 258
259 259 For example, path('/home/guido/python.tar.gz').name == 'python.tar.gz',
260 260 but path('/home/guido/python.tar.gz').namebase == 'python.tar'
261 261 """
262 262 base, ext = self.module.splitext(self.name)
263 263 return base
264 264
265 265 @property
266 266 def ext(self):
267 267 """ The file extension, for example '.py'. """
268 268 f, ext = self.module.splitext(self)
269 269 return ext
270 270
271 271 @property
272 272 def drive(self):
273 273 """ The drive specifier, for example 'C:'.
274 274 This is always empty on systems that don't use drive specifiers.
275 275 """
276 276 drive, r = self.module.splitdrive(self)
277 277 return self._next_class(drive)
278 278
279 279 parent = property(
280 280 dirname, None, None,
281 281 """ This path's parent directory, as a new path object.
282 282
283 283 For example,
284 284 path('/usr/local/lib/libpython.so').parent == path('/usr/local/lib')
285 285 """)
286 286
287 287 name = property(
288 288 basename, None, None,
289 289 """ The name of this file or directory without the full path.
290 290
291 291 For example, path('/usr/local/lib/libpython.so').name == 'libpython.so'
292 292 """)
293 293
294 294 def splitpath(self):
295 295 """ p.splitpath() -> Return (p.parent, p.name). """
296 296 parent, child = self.module.split(self)
297 297 return self._next_class(parent), child
298 298
299 299 def splitdrive(self):
300 300 """ p.splitdrive() -> Return (p.drive, <the rest of p>).
301 301
302 302 Split the drive specifier from this path. If there is
303 303 no drive specifier, p.drive is empty, so the return value
304 304 is simply (path(''), p). This is always the case on Unix.
305 305 """
306 306 drive, rel = self.module.splitdrive(self)
307 307 return self._next_class(drive), rel
308 308
309 309 def splitext(self):
310 310 """ p.splitext() -> Return (p.stripext(), p.ext).
311 311
312 312 Split the filename extension from this path and return
313 313 the two parts. Either part may be empty.
314 314
315 315 The extension is everything from '.' to the end of the
316 316 last path segment. This has the property that if
317 317 (a, b) == p.splitext(), then a + b == p.
318 318 """
319 319 filename, ext = self.module.splitext(self)
320 320 return self._next_class(filename), ext
321 321
322 322 def stripext(self):
323 323 """ p.stripext() -> Remove one file extension from the path.
324 324
325 325 For example, path('/home/guido/python.tar.gz').stripext()
326 326 returns path('/home/guido/python.tar').
327 327 """
328 328 return self.splitext()[0]
329 329
330 330 def splitunc(self):
331 331 unc, rest = self.module.splitunc(self)
332 332 return self._next_class(unc), rest
333 333
334 334 @property
335 335 def uncshare(self):
336 336 """
337 337 The UNC mount point for this path.
338 338 This is empty for paths on local drives.
339 339 """
340 340 unc, r = self.module.splitunc(self)
341 341 return self._next_class(unc)
342 342
343 343 @multimethod
344 344 def joinpath(cls, first, *others):
345 345 """
346 346 Join first to zero or more path components, adding a separator
347 347 character (first.module.sep) if needed. Returns a new instance of
348 348 first._next_class.
349 349 """
350 350 if not isinstance(first, cls):
351 351 first = cls(first)
352 352 return first._next_class(first.module.join(first, *others))
353 353
354 354 def splitall(self):
355 355 r""" Return a list of the path components in this path.
356 356
357 357 The first item in the list will be a path. Its value will be
358 358 either os.curdir, os.pardir, empty, or the root directory of
359 359 this path (for example, ``'/'`` or ``'C:\\'``). The other items in
360 360 the list will be strings.
361 361
362 362 ``path.path.joinpath(*result)`` will yield the original path.
363 363 """
364 364 parts = []
365 365 loc = self
366 366 while loc != os.curdir and loc != os.pardir:
367 367 prev = loc
368 368 loc, child = prev.splitpath()
369 369 if loc == prev:
370 370 break
371 371 parts.append(child)
372 372 parts.append(loc)
373 373 parts.reverse()
374 374 return parts
375 375
376 376 def relpath(self, start='.'):
377 377 """ Return this path as a relative path,
378 378 based from start, which defaults to the current working directory.
379 379 """
380 380 cwd = self._next_class(start)
381 381 return cwd.relpathto(self)
382 382
383 383 def relpathto(self, dest):
384 384 """ Return a relative path from self to dest.
385 385
386 386 If there is no relative path from self to dest, for example if
387 387 they reside on different drives in Windows, then this returns
388 388 dest.abspath().
389 389 """
390 390 origin = self.abspath()
391 391 dest = self._next_class(dest).abspath()
392 392
393 393 orig_list = origin.normcase().splitall()
394 394 # Don't normcase dest! We want to preserve the case.
395 395 dest_list = dest.splitall()
396 396
397 397 if orig_list[0] != self.module.normcase(dest_list[0]):
398 398 # Can't get here from there.
399 399 return dest
400 400
401 401 # Find the location where the two paths start to differ.
402 402 i = 0
403 403 for start_seg, dest_seg in zip(orig_list, dest_list):
404 404 if start_seg != self.module.normcase(dest_seg):
405 405 break
406 406 i += 1
407 407
408 408 # Now i is the point where the two paths diverge.
409 409 # Need a certain number of "os.pardir"s to work up
410 410 # from the origin to the point of divergence.
411 411 segments = [os.pardir] * (len(orig_list) - i)
412 412 # Need to add the diverging part of dest_list.
413 413 segments += dest_list[i:]
414 414 if len(segments) == 0:
415 415 # If they happen to be identical, use os.curdir.
416 416 relpath = os.curdir
417 417 else:
418 418 relpath = self.module.join(*segments)
419 419 return self._next_class(relpath)
420 420
421 421 # --- Listing, searching, walking, and matching
422 422
423 423 def listdir(self, pattern=None):
424 424 """ D.listdir() -> List of items in this directory.
425 425
426 426 Use D.files() or D.dirs() instead if you want a listing
427 427 of just files or just subdirectories.
428 428
429 429 The elements of the list are path objects.
430 430
431 431 With the optional 'pattern' argument, this only lists
432 432 items whose names match the given pattern.
433 433 """
434 434 names = os.listdir(self)
435 435 if pattern is not None:
436 436 names = fnmatch.filter(names, pattern)
437 437 return [self / child for child in names]
438 438
439 439 def dirs(self, pattern=None):
440 440 """ D.dirs() -> List of this directory's subdirectories.
441 441
442 442 The elements of the list are path objects.
443 443 This does not walk recursively into subdirectories
444 444 (but see path.walkdirs).
445 445
446 446 With the optional 'pattern' argument, this only lists
447 447 directories whose names match the given pattern. For
448 448 example, ``d.dirs('build-*')``.
449 449 """
450 450 return [p for p in self.listdir(pattern) if p.isdir()]
451 451
452 452 def files(self, pattern=None):
453 453 """ D.files() -> List of the files in this directory.
454 454
455 455 The elements of the list are path objects.
456 456 This does not walk into subdirectories (see path.walkfiles).
457 457
458 458 With the optional 'pattern' argument, this only lists files
459 459 whose names match the given pattern. For example,
460 460 ``d.files('*.pyc')``.
461 461 """
462 462
463 463 return [p for p in self.listdir(pattern) if p.isfile()]
464 464
465 465 def walk(self, pattern=None, errors='strict'):
466 466 """ D.walk() -> iterator over files and subdirs, recursively.
467 467
468 468 The iterator yields path objects naming each child item of
469 469 this directory and its descendants. This requires that
470 470 D.isdir().
471 471
472 472 This performs a depth-first traversal of the directory tree.
473 473 Each directory is returned just before all its children.
474 474
475 475 The errors= keyword argument controls behavior when an
476 476 error occurs. The default is 'strict', which causes an
477 477 exception. The other allowed values are 'warn', which
478 478 reports the error via warnings.warn(), and 'ignore'.
479 479 """
480 480 if errors not in ('strict', 'warn', 'ignore'):
481 481 raise ValueError("invalid errors parameter")
482 482
483 483 try:
484 484 childList = self.listdir()
485 485 except Exception:
486 486 if errors == 'ignore':
487 487 return
488 488 elif errors == 'warn':
489 489 warnings.warn(
490 490 "Unable to list directory '%s': %s"
491 491 % (self, sys.exc_info()[1]),
492 492 TreeWalkWarning)
493 493 return
494 494 else:
495 495 raise
496 496
497 497 for child in childList:
498 498 if pattern is None or child.fnmatch(pattern):
499 499 yield child
500 500 try:
501 501 isdir = child.isdir()
502 502 except Exception:
503 503 if errors == 'ignore':
504 504 isdir = False
505 505 elif errors == 'warn':
506 506 warnings.warn(
507 507 "Unable to access '%s': %s"
508 508 % (child, sys.exc_info()[1]),
509 509 TreeWalkWarning)
510 510 isdir = False
511 511 else:
512 512 raise
513 513
514 514 if isdir:
515 515 for item in child.walk(pattern, errors):
516 516 yield item
517 517
518 518 def walkdirs(self, pattern=None, errors='strict'):
519 519 """ D.walkdirs() -> iterator over subdirs, recursively.
520 520
521 521 With the optional 'pattern' argument, this yields only
522 522 directories whose names match the given pattern. For
523 523 example, ``mydir.walkdirs('*test')`` yields only directories
524 524 with names ending in 'test'.
525 525
526 526 The errors= keyword argument controls behavior when an
527 527 error occurs. The default is 'strict', which causes an
528 528 exception. The other allowed values are 'warn', which
529 529 reports the error via warnings.warn(), and 'ignore'.
530 530 """
531 531 if errors not in ('strict', 'warn', 'ignore'):
532 532 raise ValueError("invalid errors parameter")
533 533
534 534 try:
535 535 dirs = self.dirs()
536 536 except Exception:
537 537 if errors == 'ignore':
538 538 return
539 539 elif errors == 'warn':
540 540 warnings.warn(
541 541 "Unable to list directory '%s': %s"
542 542 % (self, sys.exc_info()[1]),
543 543 TreeWalkWarning)
544 544 return
545 545 else:
546 546 raise
547 547
548 548 for child in dirs:
549 549 if pattern is None or child.fnmatch(pattern):
550 550 yield child
551 551 for subsubdir in child.walkdirs(pattern, errors):
552 552 yield subsubdir
553 553
554 554 def walkfiles(self, pattern=None, errors='strict'):
555 555 """ D.walkfiles() -> iterator over files in D, recursively.
556 556
557 557 The optional argument, pattern, limits the results to files
558 558 with names that match the pattern. For example,
559 559 ``mydir.walkfiles('*.tmp')`` yields only files with the .tmp
560 560 extension.
561 561 """
562 562 if errors not in ('strict', 'warn', 'ignore'):
563 563 raise ValueError("invalid errors parameter")
564 564
565 565 try:
566 566 childList = self.listdir()
567 567 except Exception:
568 568 if errors == 'ignore':
569 569 return
570 570 elif errors == 'warn':
571 571 warnings.warn(
572 572 "Unable to list directory '%s': %s"
573 573 % (self, sys.exc_info()[1]),
574 574 TreeWalkWarning)
575 575 return
576 576 else:
577 577 raise
578 578
579 579 for child in childList:
580 580 try:
581 581 isfile = child.isfile()
582 582 isdir = not isfile and child.isdir()
583 583 except:
584 584 if errors == 'ignore':
585 585 continue
586 586 elif errors == 'warn':
587 587 warnings.warn(
588 588 "Unable to access '%s': %s"
589 589 % (self, sys.exc_info()[1]),
590 590 TreeWalkWarning)
591 591 continue
592 592 else:
593 593 raise
594 594
595 595 if isfile:
596 596 if pattern is None or child.fnmatch(pattern):
597 597 yield child
598 598 elif isdir:
599 599 for f in child.walkfiles(pattern, errors):
600 600 yield f
601 601
602 602 def fnmatch(self, pattern):
603 603 """ Return True if self.name matches the given pattern.
604 604
605 605 pattern - A filename pattern with wildcards,
606 606 for example ``'*.py'``.
607 607 """
608 608 return fnmatch.fnmatch(self.name, pattern)
609 609
610 610 def glob(self, pattern):
611 611 """ Return a list of path objects that match the pattern.
612 612
613 613 pattern - a path relative to this directory, with wildcards.
614 614
615 615 For example, path('/users').glob('*/bin/*') returns a list
616 616 of all the files users have in their bin directories.
617 617 """
618 618 cls = self._next_class
619 619 return [cls(s) for s in glob.glob(self / pattern)]
620 620
621 621 #
622 622 # --- Reading or writing an entire file at once.
623 623
624 624 def open(self, *args, **kwargs):
625 625 """ Open this file. Return a file object. """
626 626 return open(self, *args, **kwargs)
627 627
628 628 def bytes(self):
629 629 """ Open this file, read all bytes, return them as a string. """
630 630 with self.open('rb') as f:
631 631 return f.read()
632 632
633 633 def chunks(self, size, *args, **kwargs):
634 634 """ Returns a generator yielding chunks of the file, so it can
635 635 be read piece by piece with a simple for loop.
636 636
637 637 Any argument you pass after `size` will be passed to `open()`.
638 638
639 639 :example:
640 640
641 641 >>> for chunk in path("file.txt").chunk(8192):
642 642 ... print(chunk)
643 643
644 644 This will read the file by chunks of 8192 bytes.
645 645 """
646 646 with open(self, *args, **kwargs) as f:
647 647 while True:
648 648 d = f.read(size)
649 649 if not d:
650 650 break
651 651 yield d
652 652
653 653 def write_bytes(self, bytes, append=False):
654 654 """ Open this file and write the given bytes to it.
655 655
656 656 Default behavior is to overwrite any existing file.
657 657 Call p.write_bytes(bytes, append=True) to append instead.
658 658 """
659 659 if append:
660 660 mode = 'ab'
661 661 else:
662 662 mode = 'wb'
663 663 with self.open(mode) as f:
664 664 f.write(bytes)
665 665
666 666 def text(self, encoding=None, errors='strict'):
667 667 r""" Open this file, read it in, return the content as a string.
668 668
669 669 This method uses 'U' mode, so '\r\n' and '\r' are automatically
670 670 translated to '\n'.
671 671
672 672 Optional arguments:
673 673
674 674 encoding - The Unicode encoding (or character set) of
675 675 the file. If present, the content of the file is
676 676 decoded and returned as a unicode object; otherwise
677 677 it is returned as an 8-bit str.
678 678 errors - How to handle Unicode errors; see help(str.decode)
679 679 for the options. Default is 'strict'.
680 680 """
681 681 if encoding is None:
682 682 # 8-bit
683 683 with self.open('U') as f:
684 684 return f.read()
685 685 else:
686 686 # Unicode
687 687 with codecs.open(self, 'r', encoding, errors) as f:
688 688 # (Note - Can't use 'U' mode here, since codecs.open
689 689 # doesn't support 'U' mode.)
690 690 t = f.read()
691 691 return (t.replace(u('\r\n'), u('\n'))
692 692 .replace(u('\r\x85'), u('\n'))
693 693 .replace(u('\r'), u('\n'))
694 694 .replace(u('\x85'), u('\n'))
695 695 .replace(u('\u2028'), u('\n')))
696 696
697 697 def write_text(self, text, encoding=None, errors='strict',
698 698 linesep=os.linesep, append=False):
699 699 r""" Write the given text to this file.
700 700
701 701 The default behavior is to overwrite any existing file;
702 702 to append instead, use the 'append=True' keyword argument.
703 703
704 704 There are two differences between path.write_text() and
705 705 path.write_bytes(): newline handling and Unicode handling.
706 706 See below.
707 707
708 708 Parameters:
709 709
710 710 - text - str/unicode - The text to be written.
711 711
712 712 - encoding - str - The Unicode encoding that will be used.
713 713 This is ignored if 'text' isn't a Unicode string.
714 714
715 715 - errors - str - How to handle Unicode encoding errors.
716 716 Default is 'strict'. See help(unicode.encode) for the
717 717 options. This is ignored if 'text' isn't a Unicode
718 718 string.
719 719
720 720 - linesep - keyword argument - str/unicode - The sequence of
721 721 characters to be used to mark end-of-line. The default is
722 722 os.linesep. You can also specify None; this means to
723 723 leave all newlines as they are in 'text'.
724 724
725 725 - append - keyword argument - bool - Specifies what to do if
726 726 the file already exists (True: append to the end of it;
727 727 False: overwrite it.) The default is False.
728 728
729 729
730 730 --- Newline handling.
731 731
732 732 write_text() converts all standard end-of-line sequences
733 733 ('\n', '\r', and '\r\n') to your platform's default end-of-line
734 734 sequence (see os.linesep; on Windows, for example, the
735 735 end-of-line marker is '\r\n').
736 736
737 737 If you don't like your platform's default, you can override it
738 738 using the 'linesep=' keyword argument. If you specifically want
739 739 write_text() to preserve the newlines as-is, use 'linesep=None'.
740 740
741 741 This applies to Unicode text the same as to 8-bit text, except
742 742 there are three additional standard Unicode end-of-line sequences:
743 743 u'\x85', u'\r\x85', and u'\u2028'.
744 744
745 745 (This is slightly different from when you open a file for
746 746 writing with fopen(filename, "w") in C or open(filename, 'w')
747 747 in Python.)
748 748
749 749
750 750 --- Unicode
751 751
752 752 If 'text' isn't Unicode, then apart from newline handling, the
753 753 bytes are written verbatim to the file. The 'encoding' and
754 754 'errors' arguments are not used and must be omitted.
755 755
756 756 If 'text' is Unicode, it is first converted to bytes using the
757 757 specified 'encoding' (or the default encoding if 'encoding'
758 758 isn't specified). The 'errors' argument applies only to this
759 759 conversion.
760 760
761 761 """
762 762 if isinstance(text, unicode):
763 763 if linesep is not None:
764 764 # Convert all standard end-of-line sequences to
765 765 # ordinary newline characters.
766 766 text = (text.replace(u('\r\n'), u('\n'))
767 767 .replace(u('\r\x85'), u('\n'))
768 768 .replace(u('\r'), u('\n'))
769 769 .replace(u('\x85'), u('\n'))
770 770 .replace(u('\u2028'), u('\n')))
771 771 text = text.replace(u('\n'), linesep)
772 772 if encoding is None:
773 773 encoding = sys.getdefaultencoding()
774 774 bytes = text.encode(encoding, errors)
775 775 else:
776 776 # It is an error to specify an encoding if 'text' is
777 777 # an 8-bit string.
778 778 assert encoding is None
779 779
780 780 if linesep is not None:
781 781 text = (text.replace('\r\n', '\n')
782 782 .replace('\r', '\n'))
783 783 bytes = text.replace('\n', linesep)
784 784
785 785 self.write_bytes(bytes, append)
786 786
787 787 def lines(self, encoding=None, errors='strict', retain=True):
788 788 r""" Open this file, read all lines, return them in a list.
789 789
790 790 Optional arguments:
791 791 encoding - The Unicode encoding (or character set) of
792 792 the file. The default is None, meaning the content
793 793 of the file is read as 8-bit characters and returned
794 794 as a list of (non-Unicode) str objects.
795 795 errors - How to handle Unicode errors; see help(str.decode)
796 796 for the options. Default is 'strict'
797 797 retain - If true, retain newline characters; but all newline
798 798 character combinations ('\r', '\n', '\r\n') are
799 799 translated to '\n'. If false, newline characters are
800 800 stripped off. Default is True.
801 801
802 802 This uses 'U' mode.
803 803 """
804 804 if encoding is None and retain:
805 805 with self.open('U') as f:
806 806 return f.readlines()
807 807 else:
808 808 return self.text(encoding, errors).splitlines(retain)
809 809
810 810 def write_lines(self, lines, encoding=None, errors='strict',
811 811 linesep=os.linesep, append=False):
812 812 r""" Write the given lines of text to this file.
813 813
814 814 By default this overwrites any existing file at this path.
815 815
816 816 This puts a platform-specific newline sequence on every line.
817 817 See 'linesep' below.
818 818
819 819 lines - A list of strings.
820 820
821 821 encoding - A Unicode encoding to use. This applies only if
822 822 'lines' contains any Unicode strings.
823 823
824 824 errors - How to handle errors in Unicode encoding. This
825 825 also applies only to Unicode strings.
826 826
827 827 linesep - The desired line-ending. This line-ending is
828 828 applied to every line. If a line already has any
829 829 standard line ending ('\r', '\n', '\r\n', u'\x85',
830 830 u'\r\x85', u'\u2028'), that will be stripped off and
831 831 this will be used instead. The default is os.linesep,
832 832 which is platform-dependent ('\r\n' on Windows, '\n' on
833 833 Unix, etc.) Specify None to write the lines as-is,
834 834 like file.writelines().
835 835
836 836 Use the keyword argument append=True to append lines to the
837 837 file. The default is to overwrite the file. Warning:
838 838 When you use this with Unicode data, if the encoding of the
839 839 existing data in the file is different from the encoding
840 840 you specify with the encoding= parameter, the result is
841 841 mixed-encoding data, which can really confuse someone trying
842 842 to read the file later.
843 843 """
844 844 if append:
845 845 mode = 'ab'
846 846 else:
847 847 mode = 'wb'
848 848 with self.open(mode) as f:
849 849 for line in lines:
850 850 isUnicode = isinstance(line, unicode)
851 851 if linesep is not None:
852 852 # Strip off any existing line-end and add the
853 853 # specified linesep string.
854 854 if isUnicode:
855 855 if line[-2:] in (u('\r\n'), u('\x0d\x85')):
856 856 line = line[:-2]
857 857 elif line[-1:] in (u('\r'), u('\n'),
858 858 u('\x85'), u('\u2028')):
859 859 line = line[:-1]
860 860 else:
861 861 if line[-2:] == '\r\n':
862 862 line = line[:-2]
863 863 elif line[-1:] in ('\r', '\n'):
864 864 line = line[:-1]
865 865 line += linesep
866 866 if isUnicode:
867 867 if encoding is None:
868 868 encoding = sys.getdefaultencoding()
869 869 line = line.encode(encoding, errors)
870 870 f.write(line)
871 871
872 872 def read_md5(self):
873 873 """ Calculate the md5 hash for this file.
874 874
875 875 This reads through the entire file.
876 876 """
877 877 return self.read_hash('md5')
878 878
879 879 def _hash(self, hash_name):
880 880 """ Returns a hash object for the file at the current path.
881 881
882 882 `hash_name` should be a hash algo name such as 'md5' or 'sha1'
883 883 that's available in the `hashlib` module.
884 884 """
885 885 m = hashlib.new(hash_name)
886 886 for chunk in self.chunks(8192):
887 887 m.update(chunk)
888 888 return m
889 889
890 890 def read_hash(self, hash_name):
891 891 """ Calculate given hash for this file.
892 892
893 893 List of supported hashes can be obtained from hashlib package. This
894 894 reads the entire file.
895 895 """
896 896 return self._hash(hash_name).digest()
897 897
898 898 def read_hexhash(self, hash_name):
899 899 """ Calculate given hash for this file, returning hexdigest.
900 900
901 901 List of supported hashes can be obtained from hashlib package. This
902 902 reads the entire file.
903 903 """
904 904 return self._hash(hash_name).hexdigest()
905 905
906 906 # --- Methods for querying the filesystem.
907 907 # N.B. On some platforms, the os.path functions may be implemented in C
908 908 # (e.g. isdir on Windows, Python 3.2.2), and compiled functions don't get
909 909 # bound. Playing it safe and wrapping them all in method calls.
910 910
911 911 def isabs(self):
912 912 return self.module.isabs(self)
913 913
914 914 def exists(self):
915 915 return self.module.exists(self)
916 916
917 917 def isdir(self):
918 918 return self.module.isdir(self)
919 919
920 920 def isfile(self):
921 921 return self.module.isfile(self)
922 922
923 923 def islink(self):
924 924 return self.module.islink(self)
925 925
926 926 def ismount(self):
927 927 return self.module.ismount(self)
928 928
929 929 def samefile(self, other):
930 930 return self.module.samefile(self, other)
931 931
932 932 def getatime(self):
933 933 return self.module.getatime(self)
934 934
935 935 atime = property(
936 936 getatime, None, None,
937 937 """ Last access time of the file. """)
938 938
939 939 def getmtime(self):
940 940 return self.module.getmtime(self)
941 941
942 942 mtime = property(
943 943 getmtime, None, None,
944 944 """ Last-modified time of the file. """)
945 945
946 946 def getctime(self):
947 947 return self.module.getctime(self)
948 948
949 949 ctime = property(
950 950 getctime, None, None,
951 951 """ Creation time of the file. """)
952 952
953 953 def getsize(self):
954 954 return self.module.getsize(self)
955 955
956 956 size = property(
957 957 getsize, None, None,
958 958 """ Size of the file, in bytes. """)
959 959
960 960 if hasattr(os, 'access'):
961 961 def access(self, mode):
962 962 """ Return true if current user has access to this path.
963 963
964 964 mode - One of the constants os.F_OK, os.R_OK, os.W_OK, os.X_OK
965 965 """
966 966 return os.access(self, mode)
967 967
968 968 def stat(self):
969 969 """ Perform a stat() system call on this path. """
970 970 return os.stat(self)
971 971
972 972 def lstat(self):
973 973 """ Like path.stat(), but do not follow symbolic links. """
974 974 return os.lstat(self)
975 975
976 976 def __get_owner_windows(self):
977 977 r"""
978 978 Return the name of the owner of this file or directory. Follow
979 979 symbolic links.
980 980
981 981 Return a name of the form ur'DOMAIN\User Name'; may be a group.
982 982 """
983 983 desc = win32security.GetFileSecurity(
984 984 self, win32security.OWNER_SECURITY_INFORMATION)
985 985 sid = desc.GetSecurityDescriptorOwner()
986 986 account, domain, typecode = win32security.LookupAccountSid(None, sid)
987 987 return domain + u('\\') + account
988 988
989 989 def __get_owner_unix(self):
990 990 """
991 991 Return the name of the owner of this file or directory. Follow
992 992 symbolic links.
993 993 """
994 994 st = self.stat()
995 995 return pwd.getpwuid(st.st_uid).pw_name
996 996
997 997 def __get_owner_not_implemented(self):
998 998 raise NotImplementedError("Ownership not available on this platform.")
999 999
1000 1000 if 'win32security' in globals():
1001 1001 get_owner = __get_owner_windows
1002 1002 elif 'pwd' in globals():
1003 1003 get_owner = __get_owner_unix
1004 1004 else:
1005 1005 get_owner = __get_owner_not_implemented
1006 1006
1007 1007 owner = property(
1008 1008 get_owner, None, None,
1009 1009 """ Name of the owner of this file or directory. """)
1010 1010
1011 1011 if hasattr(os, 'statvfs'):
1012 1012 def statvfs(self):
1013 1013 """ Perform a statvfs() system call on this path. """
1014 1014 return os.statvfs(self)
1015 1015
1016 1016 if hasattr(os, 'pathconf'):
1017 1017 def pathconf(self, name):
1018 1018 return os.pathconf(self, name)
1019 1019
1020 1020 #
1021 1021 # --- Modifying operations on files and directories
1022 1022
1023 1023 def utime(self, times):
1024 1024 """ Set the access and modified times of this file. """
1025 1025 os.utime(self, times)
1026 1026 return self
1027 1027
1028 1028 def chmod(self, mode):
1029 1029 os.chmod(self, mode)
1030 1030 return self
1031 1031
1032 1032 if hasattr(os, 'chown'):
1033 1033 def chown(self, uid=-1, gid=-1):
1034 1034 os.chown(self, uid, gid)
1035 1035 return self
1036 1036
1037 1037 def rename(self, new):
1038 1038 os.rename(self, new)
1039 1039 return self._next_class(new)
1040 1040
1041 1041 def renames(self, new):
1042 1042 os.renames(self, new)
1043 1043 return self._next_class(new)
1044 1044
1045 1045 #
1046 1046 # --- Create/delete operations on directories
1047 1047
1048 1048 def mkdir(self, mode=o777):
1049 1049 os.mkdir(self, mode)
1050 1050 return self
1051 1051
1052 1052 def mkdir_p(self, mode=o777):
1053 1053 try:
1054 1054 self.mkdir(mode)
1055 1055 except OSError:
1056 1056 _, e, _ = sys.exc_info()
1057 1057 if e.errno != errno.EEXIST:
1058 1058 raise
1059 1059 return self
1060 1060
1061 1061 def makedirs(self, mode=o777):
1062 1062 os.makedirs(self, mode)
1063 1063 return self
1064 1064
1065 1065 def makedirs_p(self, mode=o777):
1066 1066 try:
1067 1067 self.makedirs(mode)
1068 1068 except OSError:
1069 1069 _, e, _ = sys.exc_info()
1070 1070 if e.errno != errno.EEXIST:
1071 1071 raise
1072 1072 return self
1073 1073
1074 1074 def rmdir(self):
1075 1075 os.rmdir(self)
1076 1076 return self
1077 1077
1078 1078 def rmdir_p(self):
1079 1079 try:
1080 1080 self.rmdir()
1081 1081 except OSError:
1082 1082 _, e, _ = sys.exc_info()
1083 1083 if e.errno != errno.ENOTEMPTY and e.errno != errno.EEXIST:
1084 1084 raise
1085 1085 return self
1086 1086
1087 1087 def removedirs(self):
1088 1088 os.removedirs(self)
1089 1089 return self
1090 1090
1091 1091 def removedirs_p(self):
1092 1092 try:
1093 1093 self.removedirs()
1094 1094 except OSError:
1095 1095 _, e, _ = sys.exc_info()
1096 1096 if e.errno != errno.ENOTEMPTY and e.errno != errno.EEXIST:
1097 1097 raise
1098 1098 return self
1099 1099
1100 1100 # --- Modifying operations on files
1101 1101
1102 1102 def touch(self):
1103 1103 """ Set the access/modified times of this file to the current time.
1104 1104 Create the file if it does not exist.
1105 1105 """
1106 1106 fd = os.open(self, os.O_WRONLY | os.O_CREAT, o666)
1107 1107 os.close(fd)
1108 1108 os.utime(self, None)
1109 1109 return self
1110 1110
1111 1111 def remove(self):
1112 1112 os.remove(self)
1113 1113 return self
1114 1114
1115 1115 def remove_p(self):
1116 1116 try:
1117 1117 self.unlink()
1118 1118 except OSError:
1119 1119 _, e, _ = sys.exc_info()
1120 1120 if e.errno != errno.ENOENT:
1121 1121 raise
1122 1122 return self
1123 1123
1124 1124 def unlink(self):
1125 1125 os.unlink(self)
1126 1126 return self
1127 1127
1128 1128 def unlink_p(self):
1129 1129 self.remove_p()
1130 1130 return self
1131 1131
1132 1132 # --- Links
1133 1133
1134 1134 if hasattr(os, 'link'):
1135 1135 def link(self, newpath):
1136 1136 """ Create a hard link at 'newpath', pointing to this file. """
1137 1137 os.link(self, newpath)
1138 1138 return self._next_class(newpath)
1139 1139
1140 1140 if hasattr(os, 'symlink'):
1141 1141 def symlink(self, newlink):
1142 1142 """ Create a symbolic link at 'newlink', pointing here. """
1143 1143 os.symlink(self, newlink)
1144 1144 return self._next_class(newlink)
1145 1145
1146 1146 if hasattr(os, 'readlink'):
1147 1147 def readlink(self):
1148 1148 """ Return the path to which this symbolic link points.
1149 1149
1150 1150 The result may be an absolute or a relative path.
1151 1151 """
1152 1152 return self._next_class(os.readlink(self))
1153 1153
1154 1154 def readlinkabs(self):
1155 1155 """ Return the path to which this symbolic link points.
1156 1156
1157 1157 The result is always an absolute path.
1158 1158 """
1159 1159 p = self.readlink()
1160 1160 if p.isabs():
1161 1161 return p
1162 1162 else:
1163 1163 return (self.parent / p).abspath()
1164 1164
1165 1165 #
1166 1166 # --- High-level functions from shutil
1167 1167
1168 1168 copyfile = shutil.copyfile
1169 1169 copymode = shutil.copymode
1170 1170 copystat = shutil.copystat
1171 1171 copy = shutil.copy
1172 1172 copy2 = shutil.copy2
1173 1173 copytree = shutil.copytree
1174 1174 if hasattr(shutil, 'move'):
1175 1175 move = shutil.move
1176 1176 rmtree = shutil.rmtree
1177 1177
1178 1178 def rmtree_p(self):
1179 1179 try:
1180 1180 self.rmtree()
1181 1181 except OSError:
1182 1182 _, e, _ = sys.exc_info()
1183 1183 if e.errno != errno.ENOENT:
1184 1184 raise
1185 1185 return self
1186 1186
1187 1187 def chdir(self):
1188 1188 os.chdir(self)
1189 1189
1190 1190 cd = chdir
1191 1191
1192 1192 #
1193 1193 # --- Special stuff from os
1194 1194
1195 1195 if hasattr(os, 'chroot'):
1196 1196 def chroot(self):
1197 1197 os.chroot(self)
1198 1198
1199 1199 if hasattr(os, 'startfile'):
1200 1200 def startfile(self):
1201 1201 os.startfile(self)
1202 1202 return self
1203 1203
1204 1204
1205 1205 class tempdir(path):
1206 1206 """
1207 1207 A temporary directory via tempfile.mkdtemp, and constructed with the
1208 1208 same parameters that you can use as a context manager.
1209 1209
1210 1210 Example:
1211 1211
1212 1212 with tempdir() as d:
1213 1213 # do stuff with the path object "d"
1214 1214
1215 1215 # here the directory is deleted automatically
1216 1216 """
1217 1217
1218 1218 @ClassProperty
1219 1219 @classmethod
1220 1220 def _next_class(cls):
1221 1221 return path
1222 1222
1223 1223 def __new__(cls, *args, **kwargs):
1224 1224 dirname = tempfile.mkdtemp(*args, **kwargs)
1225 1225 return super(tempdir, cls).__new__(cls, dirname)
1226 1226
1227 1227 def __init__(self, *args, **kwargs):
1228 1228 pass
1229 1229
1230 1230 def __enter__(self):
1231 1231 return self
1232 1232
1233 1233 def __exit__(self, exc_type, exc_value, traceback):
1234 1234 if not exc_value:
1235 1235 self.rmtree()
1236 1236
1237 1237
1238 1238 def _permission_mask(mode):
1239 1239 """
1240 1240 Convert a Unix chmod symbolic mode like 'ugo+rwx' to a function
1241 1241 suitable for applying to a mask to affect that change.
1242 1242
1243 1243 >>> mask = _permission_mask('ugo+rwx')
1244 1244 >>> oct(mask(o554))
1245 1245 'o777'
1246 1246
1247 1247 >>> oct(_permission_mask('gw-x')(o777))
1248 1248 'o766'
1249 1249 """
1250 1250 parsed = re.match('(?P<who>[ugo]+)(?P<op>[-+])(?P<what>[rwx]+)$', mode)
1251 1251 if not parsed:
1252 1252 raise ValueError("Unrecognized symbolic mode", mode)
1253 1253 spec_map = dict(r=4, w=2, x=1)
1254 1254 spec = reduce(operator.or_, [spec_map[perm]
1255 1255 for perm in parsed.group('what')])
1256 1256 # now apply spec to each in who
1257 1257 shift_map = dict(u=6, g=3, o=0)
1258 1258 mask = reduce(operator.or_, [spec << shift_map[subj]
1259 1259 for subj in parsed.group('who')])
1260 1260
1261 1261 op = parsed.group('op')
1262 1262 # if op is -, invert the mask
1263 1263 if op == '-':
1264 1264 mask ^= o777
1265 1265
1266 1266 op_map = {'+': operator.or_, '-': operator.and_}
1267 1267 return functools.partial(op_map[op], mask)
@@ -1,172 +1,171 b''
1 1 """Manage IPython.parallel clusters in the notebook.
2 2
3 3 Authors:
4 4
5 5 * Brian Granger
6 6 """
7 7
8 8 #-----------------------------------------------------------------------------
9 9 # Copyright (C) 2008-2011 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
19 import os
20
21 19 from tornado import web
22 20 from zmq.eventloop import ioloop
23 21
24 22 from IPython.config.configurable import LoggingConfigurable
25 23 from IPython.utils.traitlets import Dict, Instance, CFloat
26 24 from IPython.parallel.apps.ipclusterapp import IPClusterStart
27 25 from IPython.core.profileapp import list_profiles_in
28 26 from IPython.core.profiledir import ProfileDir
27 from IPython.utils import py3compat
29 28 from IPython.utils.path import get_ipython_dir
30 29
31 30
32 31 #-----------------------------------------------------------------------------
33 32 # Classes
34 33 #-----------------------------------------------------------------------------
35 34
36 35
37 36 class DummyIPClusterStart(IPClusterStart):
38 37 """Dummy subclass to skip init steps that conflict with global app.
39 38
40 39 Instantiating and initializing this class should result in fully configured
41 40 launchers, but no other side effects or state.
42 41 """
43 42
44 43 def init_signal(self):
45 44 pass
46 45 def reinit_logging(self):
47 46 pass
48 47
49 48
50 49 class ClusterManager(LoggingConfigurable):
51 50
52 51 profiles = Dict()
53 52
54 53 delay = CFloat(1., config=True,
55 54 help="delay (in s) between starting the controller and the engines")
56 55
57 56 loop = Instance('zmq.eventloop.ioloop.IOLoop')
58 57 def _loop_default(self):
59 58 from zmq.eventloop.ioloop import IOLoop
60 59 return IOLoop.instance()
61 60
62 61 def build_launchers(self, profile_dir):
63 62 starter = DummyIPClusterStart(log=self.log)
64 63 starter.initialize(['--profile-dir', profile_dir])
65 64 cl = starter.controller_launcher
66 65 esl = starter.engine_launcher
67 66 n = starter.n
68 67 return cl, esl, n
69 68
70 69 def get_profile_dir(self, name, path):
71 70 p = ProfileDir.find_profile_dir_by_name(path,name=name)
72 71 return p.location
73 72
74 73 def update_profiles(self):
75 74 """List all profiles in the ipython_dir and cwd.
76 75 """
77 for path in [get_ipython_dir(), os.getcwdu()]:
76 for path in [get_ipython_dir(), py3compat.getcwd()]:
78 77 for profile in list_profiles_in(path):
79 78 pd = self.get_profile_dir(profile, path)
80 79 if profile not in self.profiles:
81 80 self.log.debug("Adding cluster profile '%s'" % profile)
82 81 self.profiles[profile] = {
83 82 'profile': profile,
84 83 'profile_dir': pd,
85 84 'status': 'stopped'
86 85 }
87 86
88 87 def list_profiles(self):
89 88 self.update_profiles()
90 89 # sorted list, but ensure that 'default' always comes first
91 90 default_first = lambda name: name if name != 'default' else ''
92 91 result = [self.profile_info(p) for p in sorted(self.profiles, key=default_first)]
93 92 return result
94 93
95 94 def check_profile(self, profile):
96 95 if profile not in self.profiles:
97 96 raise web.HTTPError(404, u'profile not found')
98 97
99 98 def profile_info(self, profile):
100 99 self.check_profile(profile)
101 100 result = {}
102 101 data = self.profiles.get(profile)
103 102 result['profile'] = profile
104 103 result['profile_dir'] = data['profile_dir']
105 104 result['status'] = data['status']
106 105 if 'n' in data:
107 106 result['n'] = data['n']
108 107 return result
109 108
110 109 def start_cluster(self, profile, n=None):
111 110 """Start a cluster for a given profile."""
112 111 self.check_profile(profile)
113 112 data = self.profiles[profile]
114 113 if data['status'] == 'running':
115 114 raise web.HTTPError(409, u'cluster already running')
116 115 cl, esl, default_n = self.build_launchers(data['profile_dir'])
117 116 n = n if n is not None else default_n
118 117 def clean_data():
119 118 data.pop('controller_launcher',None)
120 119 data.pop('engine_set_launcher',None)
121 120 data.pop('n',None)
122 121 data['status'] = 'stopped'
123 122 def engines_stopped(r):
124 123 self.log.debug('Engines stopped')
125 124 if cl.running:
126 125 cl.stop()
127 126 clean_data()
128 127 esl.on_stop(engines_stopped)
129 128 def controller_stopped(r):
130 129 self.log.debug('Controller stopped')
131 130 if esl.running:
132 131 esl.stop()
133 132 clean_data()
134 133 cl.on_stop(controller_stopped)
135 134
136 135 dc = ioloop.DelayedCallback(lambda: cl.start(), 0, self.loop)
137 136 dc.start()
138 137 dc = ioloop.DelayedCallback(lambda: esl.start(n), 1000*self.delay, self.loop)
139 138 dc.start()
140 139
141 140 self.log.debug('Cluster started')
142 141 data['controller_launcher'] = cl
143 142 data['engine_set_launcher'] = esl
144 143 data['n'] = n
145 144 data['status'] = 'running'
146 145 return self.profile_info(profile)
147 146
148 147 def stop_cluster(self, profile):
149 148 """Stop a cluster for a given profile."""
150 149 self.check_profile(profile)
151 150 data = self.profiles[profile]
152 151 if data['status'] == 'stopped':
153 152 raise web.HTTPError(409, u'cluster not running')
154 153 data = self.profiles[profile]
155 154 cl = data['controller_launcher']
156 155 esl = data['engine_set_launcher']
157 156 if cl.running:
158 157 cl.stop()
159 158 if esl.running:
160 159 esl.stop()
161 160 # Return a temp info dict, the real one is updated in the on_stop
162 161 # logic above.
163 162 result = {
164 163 'profile': data['profile'],
165 164 'profile_dir': data['profile_dir'],
166 165 'status': 'stopped'
167 166 }
168 167 return result
169 168
170 169 def stop_all_clusters(self):
171 170 for p in self.profiles.keys():
172 171 self.stop_cluster(p)
@@ -1,173 +1,174 b''
1 1 """A base class notebook manager.
2 2
3 3 Authors:
4 4
5 5 * Brian Granger
6 6 * Zach Sailer
7 7 """
8 8
9 9 #-----------------------------------------------------------------------------
10 10 # Copyright (C) 2011 The IPython Development Team
11 11 #
12 12 # Distributed under the terms of the BSD License. The full license is in
13 13 # the file COPYING, distributed as part of this software.
14 14 #-----------------------------------------------------------------------------
15 15
16 16 #-----------------------------------------------------------------------------
17 17 # Imports
18 18 #-----------------------------------------------------------------------------
19 19
20 20 import os
21 21
22 22 from IPython.config.configurable import LoggingConfigurable
23 23 from IPython.nbformat import current
24 from IPython.utils.traitlets import List, Dict, Unicode, TraitError
24 from IPython.utils import py3compat
25 from IPython.utils.traitlets import Unicode, TraitError
25 26
26 27 #-----------------------------------------------------------------------------
27 28 # Classes
28 29 #-----------------------------------------------------------------------------
29 30
30 31 class NotebookManager(LoggingConfigurable):
31 32
32 33 # Todo:
33 34 # The notebook_dir attribute is used to mean a couple of different things:
34 35 # 1. Where the notebooks are stored if FileNotebookManager is used.
35 36 # 2. The cwd of the kernel for a project.
36 37 # Right now we use this attribute in a number of different places and
37 38 # we are going to have to disentangle all of this.
38 notebook_dir = Unicode(os.getcwdu(), config=True, help="""
39 notebook_dir = Unicode(py3compat.getcwd(), config=True, help="""
39 40 The directory to use for notebooks.
40 41 """)
41 42
42 43 filename_ext = Unicode(u'.ipynb')
43 44
44 45 def path_exists(self, path):
45 46 """Does the API-style path (directory) actually exist?
46 47
47 48 Override this method in subclasses.
48 49
49 50 Parameters
50 51 ----------
51 52 path : string
52 53 The
53 54
54 55 Returns
55 56 -------
56 57 exists : bool
57 58 Whether the path does indeed exist.
58 59 """
59 60 raise NotImplementedError
60 61
61 62 def _notebook_dir_changed(self, name, old, new):
62 63 """Do a bit of validation of the notebook dir."""
63 64 if not os.path.isabs(new):
64 65 # If we receive a non-absolute path, make it absolute.
65 66 self.notebook_dir = os.path.abspath(new)
66 67 return
67 68 if os.path.exists(new) and not os.path.isdir(new):
68 69 raise TraitError("notebook dir %r is not a directory" % new)
69 70 if not os.path.exists(new):
70 71 self.log.info("Creating notebook dir %s", new)
71 72 try:
72 73 os.mkdir(new)
73 74 except:
74 75 raise TraitError("Couldn't create notebook dir %r" % new)
75 76
76 77 # Main notebook API
77 78
78 79 def increment_filename(self, basename, path=''):
79 80 """Increment a notebook filename without the .ipynb to make it unique.
80 81
81 82 Parameters
82 83 ----------
83 84 basename : unicode
84 85 The name of a notebook without the ``.ipynb`` file extension.
85 86 path : unicode
86 87 The URL path of the notebooks directory
87 88 """
88 89 return basename
89 90
90 91 def list_notebooks(self, path=''):
91 92 """Return a list of notebook dicts without content.
92 93
93 94 This returns a list of dicts, each of the form::
94 95
95 96 dict(notebook_id=notebook,name=name)
96 97
97 98 This list of dicts should be sorted by name::
98 99
99 100 data = sorted(data, key=lambda item: item['name'])
100 101 """
101 102 raise NotImplementedError('must be implemented in a subclass')
102 103
103 104 def get_notebook_model(self, name, path='', content=True):
104 105 """Get the notebook model with or without content."""
105 106 raise NotImplementedError('must be implemented in a subclass')
106 107
107 108 def save_notebook_model(self, model, name, path=''):
108 109 """Save the notebook model and return the model with no content."""
109 110 raise NotImplementedError('must be implemented in a subclass')
110 111
111 112 def update_notebook_model(self, model, name, path=''):
112 113 """Update the notebook model and return the model with no content."""
113 114 raise NotImplementedError('must be implemented in a subclass')
114 115
115 116 def delete_notebook_model(self, name, path=''):
116 117 """Delete notebook by name and path."""
117 118 raise NotImplementedError('must be implemented in a subclass')
118 119
119 120 def create_notebook_model(self, model=None, path=''):
120 121 """Create a new notebook and return its model with no content."""
121 122 path = path.strip('/')
122 123 if model is None:
123 124 model = {}
124 125 if 'content' not in model:
125 126 metadata = current.new_metadata(name=u'')
126 127 model['content'] = current.new_notebook(metadata=metadata)
127 128 if 'name' not in model:
128 129 model['name'] = self.increment_filename('Untitled', path)
129 130
130 131 model['path'] = path
131 132 model = self.save_notebook_model(model, model['name'], model['path'])
132 133 return model
133 134
134 135 def copy_notebook(self, from_name, to_name=None, path=''):
135 136 """Copy an existing notebook and return its new model.
136 137
137 138 If to_name not specified, increment `from_name-Copy#.ipynb`.
138 139 """
139 140 path = path.strip('/')
140 141 model = self.get_notebook_model(from_name, path)
141 142 if not to_name:
142 143 base = os.path.splitext(from_name)[0] + '-Copy'
143 144 to_name = self.increment_filename(base, path)
144 145 model['name'] = to_name
145 146 model = self.save_notebook_model(model, to_name, path)
146 147 return model
147 148
148 149 # Checkpoint-related
149 150
150 151 def create_checkpoint(self, name, path=''):
151 152 """Create a checkpoint of the current state of a notebook
152 153
153 154 Returns a checkpoint_id for the new checkpoint.
154 155 """
155 156 raise NotImplementedError("must be implemented in a subclass")
156 157
157 158 def list_checkpoints(self, name, path=''):
158 159 """Return a list of checkpoints for a given notebook"""
159 160 return []
160 161
161 162 def restore_checkpoint(self, checkpoint_id, name, path=''):
162 163 """Restore a notebook from one of its checkpoints"""
163 164 raise NotImplementedError("must be implemented in a subclass")
164 165
165 166 def delete_checkpoint(self, checkpoint_id, name, path=''):
166 167 """delete a checkpoint for a notebook"""
167 168 raise NotImplementedError("must be implemented in a subclass")
168 169
169 170 def log_info(self):
170 171 self.log.info(self.info_string())
171 172
172 173 def info_string(self):
173 174 return "Serving notebooks"
@@ -1,275 +1,276 b''
1 1 # encoding: utf-8
2 2 """
3 3 The Base Application class for IPython.parallel apps
4 4
5 5 Authors:
6 6
7 7 * Brian Granger
8 8 * Min RK
9 9
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 import os
24 24 import logging
25 25 import re
26 26 import sys
27 27
28 28 from subprocess import Popen, PIPE
29 29
30 30 from IPython.config.application import catch_config_error, LevelFormatter
31 31 from IPython.core import release
32 32 from IPython.core.crashhandler import CrashHandler
33 33 from IPython.core.application import (
34 34 BaseIPythonApplication,
35 35 base_aliases as base_ip_aliases,
36 36 base_flags as base_ip_flags
37 37 )
38 38 from IPython.utils.path import expand_path
39 from IPython.utils import py3compat
39 40 from IPython.utils.py3compat import unicode_type
40 41
41 42 from IPython.utils.traitlets import Unicode, Bool, Instance, Dict
42 43
43 44 #-----------------------------------------------------------------------------
44 45 # Module errors
45 46 #-----------------------------------------------------------------------------
46 47
47 48 class PIDFileError(Exception):
48 49 pass
49 50
50 51
51 52 #-----------------------------------------------------------------------------
52 53 # Crash handler for this application
53 54 #-----------------------------------------------------------------------------
54 55
55 56 class ParallelCrashHandler(CrashHandler):
56 57 """sys.excepthook for IPython itself, leaves a detailed report on disk."""
57 58
58 59 def __init__(self, app):
59 60 contact_name = release.authors['Min'][0]
60 61 contact_email = release.author_email
61 62 bug_tracker = 'https://github.com/ipython/ipython/issues'
62 63 super(ParallelCrashHandler,self).__init__(
63 64 app, contact_name, contact_email, bug_tracker
64 65 )
65 66
66 67
67 68 #-----------------------------------------------------------------------------
68 69 # Main application
69 70 #-----------------------------------------------------------------------------
70 71 base_aliases = {}
71 72 base_aliases.update(base_ip_aliases)
72 73 base_aliases.update({
73 74 'work-dir' : 'BaseParallelApplication.work_dir',
74 75 'log-to-file' : 'BaseParallelApplication.log_to_file',
75 76 'clean-logs' : 'BaseParallelApplication.clean_logs',
76 77 'log-url' : 'BaseParallelApplication.log_url',
77 78 'cluster-id' : 'BaseParallelApplication.cluster_id',
78 79 })
79 80
80 81 base_flags = {
81 82 'log-to-file' : (
82 83 {'BaseParallelApplication' : {'log_to_file' : True}},
83 84 "send log output to a file"
84 85 )
85 86 }
86 87 base_flags.update(base_ip_flags)
87 88
88 89 class BaseParallelApplication(BaseIPythonApplication):
89 90 """The base Application for IPython.parallel apps
90 91
91 92 Principle extensions to BaseIPyythonApplication:
92 93
93 94 * work_dir
94 95 * remote logging via pyzmq
95 96 * IOLoop instance
96 97 """
97 98
98 99 crash_handler_class = ParallelCrashHandler
99 100
100 101 def _log_level_default(self):
101 102 # temporarily override default_log_level to INFO
102 103 return logging.INFO
103 104
104 105 def _log_format_default(self):
105 106 """override default log format to include time"""
106 107 return u"%(asctime)s.%(msecs).03d [%(name)s]%(highlevel)s %(message)s"
107 108
108 work_dir = Unicode(os.getcwdu(), config=True,
109 work_dir = Unicode(py3compat.getcwd(), config=True,
109 110 help='Set the working dir for the process.'
110 111 )
111 112 def _work_dir_changed(self, name, old, new):
112 113 self.work_dir = unicode_type(expand_path(new))
113 114
114 115 log_to_file = Bool(config=True,
115 116 help="whether to log to a file")
116 117
117 118 clean_logs = Bool(False, config=True,
118 119 help="whether to cleanup old logfiles before starting")
119 120
120 121 log_url = Unicode('', config=True,
121 122 help="The ZMQ URL of the iplogger to aggregate logging.")
122 123
123 124 cluster_id = Unicode('', config=True,
124 125 help="""String id to add to runtime files, to prevent name collisions when
125 126 using multiple clusters with a single profile simultaneously.
126 127
127 128 When set, files will be named like: 'ipcontroller-<cluster_id>-engine.json'
128 129
129 130 Since this is text inserted into filenames, typical recommendations apply:
130 131 Simple character strings are ideal, and spaces are not recommended (but should
131 132 generally work).
132 133 """
133 134 )
134 135 def _cluster_id_changed(self, name, old, new):
135 136 self.name = self.__class__.name
136 137 if new:
137 138 self.name += '-%s'%new
138 139
139 140 def _config_files_default(self):
140 141 return ['ipcontroller_config.py', 'ipengine_config.py', 'ipcluster_config.py']
141 142
142 143 loop = Instance('zmq.eventloop.ioloop.IOLoop')
143 144 def _loop_default(self):
144 145 from zmq.eventloop.ioloop import IOLoop
145 146 return IOLoop.instance()
146 147
147 148 aliases = Dict(base_aliases)
148 149 flags = Dict(base_flags)
149 150
150 151 @catch_config_error
151 152 def initialize(self, argv=None):
152 153 """initialize the app"""
153 154 super(BaseParallelApplication, self).initialize(argv)
154 155 self.to_work_dir()
155 156 self.reinit_logging()
156 157
157 158 def to_work_dir(self):
158 159 wd = self.work_dir
159 if unicode_type(wd) != os.getcwdu():
160 if unicode_type(wd) != py3compat.getcwd():
160 161 os.chdir(wd)
161 162 self.log.info("Changing to working dir: %s" % wd)
162 163 # This is the working dir by now.
163 164 sys.path.insert(0, '')
164 165
165 166 def reinit_logging(self):
166 167 # Remove old log files
167 168 log_dir = self.profile_dir.log_dir
168 169 if self.clean_logs:
169 170 for f in os.listdir(log_dir):
170 171 if re.match(r'%s-\d+\.(log|err|out)' % self.name, f):
171 172 try:
172 173 os.remove(os.path.join(log_dir, f))
173 174 except (OSError, IOError):
174 175 # probably just conflict from sibling process
175 176 # already removing it
176 177 pass
177 178 if self.log_to_file:
178 179 # Start logging to the new log file
179 180 log_filename = self.name + u'-' + str(os.getpid()) + u'.log'
180 181 logfile = os.path.join(log_dir, log_filename)
181 182 open_log_file = open(logfile, 'w')
182 183 else:
183 184 open_log_file = None
184 185 if open_log_file is not None:
185 186 while self.log.handlers:
186 187 self.log.removeHandler(self.log.handlers[0])
187 188 self._log_handler = logging.StreamHandler(open_log_file)
188 189 self.log.addHandler(self._log_handler)
189 190 else:
190 191 self._log_handler = self.log.handlers[0]
191 192 # Add timestamps to log format:
192 193 self._log_formatter = LevelFormatter(self.log_format,
193 194 datefmt=self.log_datefmt)
194 195 self._log_handler.setFormatter(self._log_formatter)
195 196 # do not propagate log messages to root logger
196 197 # ipcluster app will sometimes print duplicate messages during shutdown
197 198 # if this is 1 (default):
198 199 self.log.propagate = False
199 200
200 201 def write_pid_file(self, overwrite=False):
201 202 """Create a .pid file in the pid_dir with my pid.
202 203
203 204 This must be called after pre_construct, which sets `self.pid_dir`.
204 205 This raises :exc:`PIDFileError` if the pid file exists already.
205 206 """
206 207 pid_file = os.path.join(self.profile_dir.pid_dir, self.name + u'.pid')
207 208 if os.path.isfile(pid_file):
208 209 pid = self.get_pid_from_file()
209 210 if not overwrite:
210 211 raise PIDFileError(
211 212 'The pid file [%s] already exists. \nThis could mean that this '
212 213 'server is already running with [pid=%s].' % (pid_file, pid)
213 214 )
214 215 with open(pid_file, 'w') as f:
215 216 self.log.info("Creating pid file: %s" % pid_file)
216 217 f.write(repr(os.getpid())+'\n')
217 218
218 219 def remove_pid_file(self):
219 220 """Remove the pid file.
220 221
221 222 This should be called at shutdown by registering a callback with
222 223 :func:`reactor.addSystemEventTrigger`. This needs to return
223 224 ``None``.
224 225 """
225 226 pid_file = os.path.join(self.profile_dir.pid_dir, self.name + u'.pid')
226 227 if os.path.isfile(pid_file):
227 228 try:
228 229 self.log.info("Removing pid file: %s" % pid_file)
229 230 os.remove(pid_file)
230 231 except:
231 232 self.log.warn("Error removing the pid file: %s" % pid_file)
232 233
233 234 def get_pid_from_file(self):
234 235 """Get the pid from the pid file.
235 236
236 237 If the pid file doesn't exist a :exc:`PIDFileError` is raised.
237 238 """
238 239 pid_file = os.path.join(self.profile_dir.pid_dir, self.name + u'.pid')
239 240 if os.path.isfile(pid_file):
240 241 with open(pid_file, 'r') as f:
241 242 s = f.read().strip()
242 243 try:
243 244 pid = int(s)
244 245 except:
245 246 raise PIDFileError("invalid pid file: %s (contents: %r)"%(pid_file, s))
246 247 return pid
247 248 else:
248 249 raise PIDFileError('pid file not found: %s' % pid_file)
249 250
250 251 def check_pid(self, pid):
251 252 if os.name == 'nt':
252 253 try:
253 254 import ctypes
254 255 # returns 0 if no such process (of ours) exists
255 256 # positive int otherwise
256 257 p = ctypes.windll.kernel32.OpenProcess(1,0,pid)
257 258 except Exception:
258 259 self.log.warn(
259 260 "Could not determine whether pid %i is running via `OpenProcess`. "
260 261 " Making the likely assumption that it is."%pid
261 262 )
262 263 return True
263 264 return bool(p)
264 265 else:
265 266 try:
266 267 p = Popen(['ps','x'], stdout=PIPE, stderr=PIPE)
267 268 output,_ = p.communicate()
268 269 except OSError:
269 270 self.log.warn(
270 271 "Could not determine whether pid %i is running via `ps x`. "
271 272 " Making the likely assumption that it is."%pid
272 273 )
273 274 return True
274 275 pids = list(map(int, re.findall(r'^\W*\d+', output, re.MULTILINE)))
275 276 return pid in pids
@@ -1,764 +1,764 b''
1 1 """Nose Plugin that supports IPython doctests.
2 2
3 3 Limitations:
4 4
5 5 - When generating examples for use as doctests, make sure that you have
6 6 pretty-printing OFF. This can be done either by setting the
7 7 ``PlainTextFormatter.pprint`` option in your configuration file to False, or
8 8 by interactively disabling it with %Pprint. This is required so that IPython
9 9 output matches that of normal Python, which is used by doctest for internal
10 10 execution.
11 11
12 12 - Do not rely on specific prompt numbers for results (such as using
13 13 '_34==True', for example). For IPython tests run via an external process the
14 14 prompt numbers may be different, and IPython tests run as normal python code
15 15 won't even have these special _NN variables set at all.
16 16 """
17 17
18 18 #-----------------------------------------------------------------------------
19 19 # Module imports
20 20
21 21 # From the standard library
22 22 import doctest
23 23 import inspect
24 24 import logging
25 25 import os
26 26 import re
27 27 import sys
28 28 import traceback
29 29 import unittest
30 30
31 31 from inspect import getmodule
32 32
33 33 # We are overriding the default doctest runner, so we need to import a few
34 34 # things from doctest directly
35 35 from doctest import (REPORTING_FLAGS, REPORT_ONLY_FIRST_FAILURE,
36 36 _unittest_reportflags, DocTestRunner,
37 37 _extract_future_flags, pdb, _OutputRedirectingPdb,
38 38 _exception_traceback,
39 39 linecache)
40 40
41 41 # Third-party modules
42 42 import nose.core
43 43
44 44 from nose.plugins import doctests, Plugin
45 45 from nose.util import anyp, getpackage, test_address, resolve_name, tolist
46 46
47 47 # Our own imports
48 from IPython.utils.py3compat import builtin_mod, PY3
48 from IPython.utils.py3compat import builtin_mod, PY3, getcwd
49 49
50 50 if PY3:
51 51 from io import StringIO
52 52 else:
53 53 from StringIO import StringIO
54 54
55 55 #-----------------------------------------------------------------------------
56 56 # Module globals and other constants
57 57 #-----------------------------------------------------------------------------
58 58
59 59 log = logging.getLogger(__name__)
60 60
61 61
62 62 #-----------------------------------------------------------------------------
63 63 # Classes and functions
64 64 #-----------------------------------------------------------------------------
65 65
66 66 def is_extension_module(filename):
67 67 """Return whether the given filename is an extension module.
68 68
69 69 This simply checks that the extension is either .so or .pyd.
70 70 """
71 71 return os.path.splitext(filename)[1].lower() in ('.so','.pyd')
72 72
73 73
74 74 class DocTestSkip(object):
75 75 """Object wrapper for doctests to be skipped."""
76 76
77 77 ds_skip = """Doctest to skip.
78 78 >>> 1 #doctest: +SKIP
79 79 """
80 80
81 81 def __init__(self,obj):
82 82 self.obj = obj
83 83
84 84 def __getattribute__(self,key):
85 85 if key == '__doc__':
86 86 return DocTestSkip.ds_skip
87 87 else:
88 88 return getattr(object.__getattribute__(self,'obj'),key)
89 89
90 90 # Modified version of the one in the stdlib, that fixes a python bug (doctests
91 91 # not found in extension modules, http://bugs.python.org/issue3158)
92 92 class DocTestFinder(doctest.DocTestFinder):
93 93
94 94 def _from_module(self, module, object):
95 95 """
96 96 Return true if the given object is defined in the given
97 97 module.
98 98 """
99 99 if module is None:
100 100 return True
101 101 elif inspect.isfunction(object):
102 102 return module.__dict__ is object.__globals__
103 103 elif inspect.isbuiltin(object):
104 104 return module.__name__ == object.__module__
105 105 elif inspect.isclass(object):
106 106 return module.__name__ == object.__module__
107 107 elif inspect.ismethod(object):
108 108 # This one may be a bug in cython that fails to correctly set the
109 109 # __module__ attribute of methods, but since the same error is easy
110 110 # to make by extension code writers, having this safety in place
111 111 # isn't such a bad idea
112 112 return module.__name__ == object.__self__.__class__.__module__
113 113 elif inspect.getmodule(object) is not None:
114 114 return module is inspect.getmodule(object)
115 115 elif hasattr(object, '__module__'):
116 116 return module.__name__ == object.__module__
117 117 elif isinstance(object, property):
118 118 return True # [XX] no way not be sure.
119 119 else:
120 120 raise ValueError("object must be a class or function, got %r" % object)
121 121
122 122 def _find(self, tests, obj, name, module, source_lines, globs, seen):
123 123 """
124 124 Find tests for the given object and any contained objects, and
125 125 add them to `tests`.
126 126 """
127 127 #print '_find for:', obj, name, module # dbg
128 128 if hasattr(obj,"skip_doctest"):
129 129 #print 'SKIPPING DOCTEST FOR:',obj # dbg
130 130 obj = DocTestSkip(obj)
131 131
132 132 doctest.DocTestFinder._find(self,tests, obj, name, module,
133 133 source_lines, globs, seen)
134 134
135 135 # Below we re-run pieces of the above method with manual modifications,
136 136 # because the original code is buggy and fails to correctly identify
137 137 # doctests in extension modules.
138 138
139 139 # Local shorthands
140 140 from inspect import isroutine, isclass, ismodule
141 141
142 142 # Look for tests in a module's contained objects.
143 143 if inspect.ismodule(obj) and self._recurse:
144 144 for valname, val in obj.__dict__.items():
145 145 valname1 = '%s.%s' % (name, valname)
146 146 if ( (isroutine(val) or isclass(val))
147 147 and self._from_module(module, val) ):
148 148
149 149 self._find(tests, val, valname1, module, source_lines,
150 150 globs, seen)
151 151
152 152 # Look for tests in a class's contained objects.
153 153 if inspect.isclass(obj) and self._recurse:
154 154 #print 'RECURSE into class:',obj # dbg
155 155 for valname, val in obj.__dict__.items():
156 156 # Special handling for staticmethod/classmethod.
157 157 if isinstance(val, staticmethod):
158 158 val = getattr(obj, valname)
159 159 if isinstance(val, classmethod):
160 160 val = getattr(obj, valname).__func__
161 161
162 162 # Recurse to methods, properties, and nested classes.
163 163 if ((inspect.isfunction(val) or inspect.isclass(val) or
164 164 inspect.ismethod(val) or
165 165 isinstance(val, property)) and
166 166 self._from_module(module, val)):
167 167 valname = '%s.%s' % (name, valname)
168 168 self._find(tests, val, valname, module, source_lines,
169 169 globs, seen)
170 170
171 171
172 172 class IPDoctestOutputChecker(doctest.OutputChecker):
173 173 """Second-chance checker with support for random tests.
174 174
175 175 If the default comparison doesn't pass, this checker looks in the expected
176 176 output string for flags that tell us to ignore the output.
177 177 """
178 178
179 179 random_re = re.compile(r'#\s*random\s+')
180 180
181 181 def check_output(self, want, got, optionflags):
182 182 """Check output, accepting special markers embedded in the output.
183 183
184 184 If the output didn't pass the default validation but the special string
185 185 '#random' is included, we accept it."""
186 186
187 187 # Let the original tester verify first, in case people have valid tests
188 188 # that happen to have a comment saying '#random' embedded in.
189 189 ret = doctest.OutputChecker.check_output(self, want, got,
190 190 optionflags)
191 191 if not ret and self.random_re.search(want):
192 192 #print >> sys.stderr, 'RANDOM OK:',want # dbg
193 193 return True
194 194
195 195 return ret
196 196
197 197
198 198 class DocTestCase(doctests.DocTestCase):
199 199 """Proxy for DocTestCase: provides an address() method that
200 200 returns the correct address for the doctest case. Otherwise
201 201 acts as a proxy to the test case. To provide hints for address(),
202 202 an obj may also be passed -- this will be used as the test object
203 203 for purposes of determining the test address, if it is provided.
204 204 """
205 205
206 206 # Note: this method was taken from numpy's nosetester module.
207 207
208 208 # Subclass nose.plugins.doctests.DocTestCase to work around a bug in
209 209 # its constructor that blocks non-default arguments from being passed
210 210 # down into doctest.DocTestCase
211 211
212 212 def __init__(self, test, optionflags=0, setUp=None, tearDown=None,
213 213 checker=None, obj=None, result_var='_'):
214 214 self._result_var = result_var
215 215 doctests.DocTestCase.__init__(self, test,
216 216 optionflags=optionflags,
217 217 setUp=setUp, tearDown=tearDown,
218 218 checker=checker)
219 219 # Now we must actually copy the original constructor from the stdlib
220 220 # doctest class, because we can't call it directly and a bug in nose
221 221 # means it never gets passed the right arguments.
222 222
223 223 self._dt_optionflags = optionflags
224 224 self._dt_checker = checker
225 225 self._dt_test = test
226 226 self._dt_test_globs_ori = test.globs
227 227 self._dt_setUp = setUp
228 228 self._dt_tearDown = tearDown
229 229
230 230 # XXX - store this runner once in the object!
231 231 runner = IPDocTestRunner(optionflags=optionflags,
232 232 checker=checker, verbose=False)
233 233 self._dt_runner = runner
234 234
235 235
236 236 # Each doctest should remember the directory it was loaded from, so
237 237 # things like %run work without too many contortions
238 238 self._ori_dir = os.path.dirname(test.filename)
239 239
240 240 # Modified runTest from the default stdlib
241 241 def runTest(self):
242 242 test = self._dt_test
243 243 runner = self._dt_runner
244 244
245 245 old = sys.stdout
246 246 new = StringIO()
247 247 optionflags = self._dt_optionflags
248 248
249 249 if not (optionflags & REPORTING_FLAGS):
250 250 # The option flags don't include any reporting flags,
251 251 # so add the default reporting flags
252 252 optionflags |= _unittest_reportflags
253 253
254 254 try:
255 255 # Save our current directory and switch out to the one where the
256 256 # test was originally created, in case another doctest did a
257 257 # directory change. We'll restore this in the finally clause.
258 curdir = os.getcwdu()
258 curdir = getcwd()
259 259 #print 'runTest in dir:', self._ori_dir # dbg
260 260 os.chdir(self._ori_dir)
261 261
262 262 runner.DIVIDER = "-"*70
263 263 failures, tries = runner.run(test,out=new.write,
264 264 clear_globs=False)
265 265 finally:
266 266 sys.stdout = old
267 267 os.chdir(curdir)
268 268
269 269 if failures:
270 270 raise self.failureException(self.format_failure(new.getvalue()))
271 271
272 272 def setUp(self):
273 273 """Modified test setup that syncs with ipython namespace"""
274 274 #print "setUp test", self._dt_test.examples # dbg
275 275 if isinstance(self._dt_test.examples[0], IPExample):
276 276 # for IPython examples *only*, we swap the globals with the ipython
277 277 # namespace, after updating it with the globals (which doctest
278 278 # fills with the necessary info from the module being tested).
279 279 self.user_ns_orig = {}
280 280 self.user_ns_orig.update(_ip.user_ns)
281 281 _ip.user_ns.update(self._dt_test.globs)
282 282 # We must remove the _ key in the namespace, so that Python's
283 283 # doctest code sets it naturally
284 284 _ip.user_ns.pop('_', None)
285 285 _ip.user_ns['__builtins__'] = builtin_mod
286 286 self._dt_test.globs = _ip.user_ns
287 287
288 288 super(DocTestCase, self).setUp()
289 289
290 290 def tearDown(self):
291 291
292 292 # Undo the test.globs reassignment we made, so that the parent class
293 293 # teardown doesn't destroy the ipython namespace
294 294 if isinstance(self._dt_test.examples[0], IPExample):
295 295 self._dt_test.globs = self._dt_test_globs_ori
296 296 _ip.user_ns.clear()
297 297 _ip.user_ns.update(self.user_ns_orig)
298 298
299 299 # XXX - fperez: I am not sure if this is truly a bug in nose 0.11, but
300 300 # it does look like one to me: its tearDown method tries to run
301 301 #
302 302 # delattr(builtin_mod, self._result_var)
303 303 #
304 304 # without checking that the attribute really is there; it implicitly
305 305 # assumes it should have been set via displayhook. But if the
306 306 # displayhook was never called, this doesn't necessarily happen. I
307 307 # haven't been able to find a little self-contained example outside of
308 308 # ipython that would show the problem so I can report it to the nose
309 309 # team, but it does happen a lot in our code.
310 310 #
311 311 # So here, we just protect as narrowly as possible by trapping an
312 312 # attribute error whose message would be the name of self._result_var,
313 313 # and letting any other error propagate.
314 314 try:
315 315 super(DocTestCase, self).tearDown()
316 316 except AttributeError as exc:
317 317 if exc.args[0] != self._result_var:
318 318 raise
319 319
320 320
321 321 # A simple subclassing of the original with a different class name, so we can
322 322 # distinguish and treat differently IPython examples from pure python ones.
323 323 class IPExample(doctest.Example): pass
324 324
325 325
326 326 class IPExternalExample(doctest.Example):
327 327 """Doctest examples to be run in an external process."""
328 328
329 329 def __init__(self, source, want, exc_msg=None, lineno=0, indent=0,
330 330 options=None):
331 331 # Parent constructor
332 332 doctest.Example.__init__(self,source,want,exc_msg,lineno,indent,options)
333 333
334 334 # An EXTRA newline is needed to prevent pexpect hangs
335 335 self.source += '\n'
336 336
337 337
338 338 class IPDocTestParser(doctest.DocTestParser):
339 339 """
340 340 A class used to parse strings containing doctest examples.
341 341
342 342 Note: This is a version modified to properly recognize IPython input and
343 343 convert any IPython examples into valid Python ones.
344 344 """
345 345 # This regular expression is used to find doctest examples in a
346 346 # string. It defines three groups: `source` is the source code
347 347 # (including leading indentation and prompts); `indent` is the
348 348 # indentation of the first (PS1) line of the source code; and
349 349 # `want` is the expected output (including leading indentation).
350 350
351 351 # Classic Python prompts or default IPython ones
352 352 _PS1_PY = r'>>>'
353 353 _PS2_PY = r'\.\.\.'
354 354
355 355 _PS1_IP = r'In\ \[\d+\]:'
356 356 _PS2_IP = r'\ \ \ \.\.\.+:'
357 357
358 358 _RE_TPL = r'''
359 359 # Source consists of a PS1 line followed by zero or more PS2 lines.
360 360 (?P<source>
361 361 (?:^(?P<indent> [ ]*) (?P<ps1> %s) .*) # PS1 line
362 362 (?:\n [ ]* (?P<ps2> %s) .*)*) # PS2 lines
363 363 \n? # a newline
364 364 # Want consists of any non-blank lines that do not start with PS1.
365 365 (?P<want> (?:(?![ ]*$) # Not a blank line
366 366 (?![ ]*%s) # Not a line starting with PS1
367 367 (?![ ]*%s) # Not a line starting with PS2
368 368 .*$\n? # But any other line
369 369 )*)
370 370 '''
371 371
372 372 _EXAMPLE_RE_PY = re.compile( _RE_TPL % (_PS1_PY,_PS2_PY,_PS1_PY,_PS2_PY),
373 373 re.MULTILINE | re.VERBOSE)
374 374
375 375 _EXAMPLE_RE_IP = re.compile( _RE_TPL % (_PS1_IP,_PS2_IP,_PS1_IP,_PS2_IP),
376 376 re.MULTILINE | re.VERBOSE)
377 377
378 378 # Mark a test as being fully random. In this case, we simply append the
379 379 # random marker ('#random') to each individual example's output. This way
380 380 # we don't need to modify any other code.
381 381 _RANDOM_TEST = re.compile(r'#\s*all-random\s+')
382 382
383 383 # Mark tests to be executed in an external process - currently unsupported.
384 384 _EXTERNAL_IP = re.compile(r'#\s*ipdoctest:\s*EXTERNAL')
385 385
386 386 def ip2py(self,source):
387 387 """Convert input IPython source into valid Python."""
388 388 block = _ip.input_transformer_manager.transform_cell(source)
389 389 if len(block.splitlines()) == 1:
390 390 return _ip.prefilter(block)
391 391 else:
392 392 return block
393 393
394 394 def parse(self, string, name='<string>'):
395 395 """
396 396 Divide the given string into examples and intervening text,
397 397 and return them as a list of alternating Examples and strings.
398 398 Line numbers for the Examples are 0-based. The optional
399 399 argument `name` is a name identifying this string, and is only
400 400 used for error messages.
401 401 """
402 402
403 403 #print 'Parse string:\n',string # dbg
404 404
405 405 string = string.expandtabs()
406 406 # If all lines begin with the same indentation, then strip it.
407 407 min_indent = self._min_indent(string)
408 408 if min_indent > 0:
409 409 string = '\n'.join([l[min_indent:] for l in string.split('\n')])
410 410
411 411 output = []
412 412 charno, lineno = 0, 0
413 413
414 414 # We make 'all random' tests by adding the '# random' mark to every
415 415 # block of output in the test.
416 416 if self._RANDOM_TEST.search(string):
417 417 random_marker = '\n# random'
418 418 else:
419 419 random_marker = ''
420 420
421 421 # Whether to convert the input from ipython to python syntax
422 422 ip2py = False
423 423 # Find all doctest examples in the string. First, try them as Python
424 424 # examples, then as IPython ones
425 425 terms = list(self._EXAMPLE_RE_PY.finditer(string))
426 426 if terms:
427 427 # Normal Python example
428 428 #print '-'*70 # dbg
429 429 #print 'PyExample, Source:\n',string # dbg
430 430 #print '-'*70 # dbg
431 431 Example = doctest.Example
432 432 else:
433 433 # It's an ipython example. Note that IPExamples are run
434 434 # in-process, so their syntax must be turned into valid python.
435 435 # IPExternalExamples are run out-of-process (via pexpect) so they
436 436 # don't need any filtering (a real ipython will be executing them).
437 437 terms = list(self._EXAMPLE_RE_IP.finditer(string))
438 438 if self._EXTERNAL_IP.search(string):
439 439 #print '-'*70 # dbg
440 440 #print 'IPExternalExample, Source:\n',string # dbg
441 441 #print '-'*70 # dbg
442 442 Example = IPExternalExample
443 443 else:
444 444 #print '-'*70 # dbg
445 445 #print 'IPExample, Source:\n',string # dbg
446 446 #print '-'*70 # dbg
447 447 Example = IPExample
448 448 ip2py = True
449 449
450 450 for m in terms:
451 451 # Add the pre-example text to `output`.
452 452 output.append(string[charno:m.start()])
453 453 # Update lineno (lines before this example)
454 454 lineno += string.count('\n', charno, m.start())
455 455 # Extract info from the regexp match.
456 456 (source, options, want, exc_msg) = \
457 457 self._parse_example(m, name, lineno,ip2py)
458 458
459 459 # Append the random-output marker (it defaults to empty in most
460 460 # cases, it's only non-empty for 'all-random' tests):
461 461 want += random_marker
462 462
463 463 if Example is IPExternalExample:
464 464 options[doctest.NORMALIZE_WHITESPACE] = True
465 465 want += '\n'
466 466
467 467 # Create an Example, and add it to the list.
468 468 if not self._IS_BLANK_OR_COMMENT(source):
469 469 output.append(Example(source, want, exc_msg,
470 470 lineno=lineno,
471 471 indent=min_indent+len(m.group('indent')),
472 472 options=options))
473 473 # Update lineno (lines inside this example)
474 474 lineno += string.count('\n', m.start(), m.end())
475 475 # Update charno.
476 476 charno = m.end()
477 477 # Add any remaining post-example text to `output`.
478 478 output.append(string[charno:])
479 479 return output
480 480
481 481 def _parse_example(self, m, name, lineno,ip2py=False):
482 482 """
483 483 Given a regular expression match from `_EXAMPLE_RE` (`m`),
484 484 return a pair `(source, want)`, where `source` is the matched
485 485 example's source code (with prompts and indentation stripped);
486 486 and `want` is the example's expected output (with indentation
487 487 stripped).
488 488
489 489 `name` is the string's name, and `lineno` is the line number
490 490 where the example starts; both are used for error messages.
491 491
492 492 Optional:
493 493 `ip2py`: if true, filter the input via IPython to convert the syntax
494 494 into valid python.
495 495 """
496 496
497 497 # Get the example's indentation level.
498 498 indent = len(m.group('indent'))
499 499
500 500 # Divide source into lines; check that they're properly
501 501 # indented; and then strip their indentation & prompts.
502 502 source_lines = m.group('source').split('\n')
503 503
504 504 # We're using variable-length input prompts
505 505 ps1 = m.group('ps1')
506 506 ps2 = m.group('ps2')
507 507 ps1_len = len(ps1)
508 508
509 509 self._check_prompt_blank(source_lines, indent, name, lineno,ps1_len)
510 510 if ps2:
511 511 self._check_prefix(source_lines[1:], ' '*indent + ps2, name, lineno)
512 512
513 513 source = '\n'.join([sl[indent+ps1_len+1:] for sl in source_lines])
514 514
515 515 if ip2py:
516 516 # Convert source input from IPython into valid Python syntax
517 517 source = self.ip2py(source)
518 518
519 519 # Divide want into lines; check that it's properly indented; and
520 520 # then strip the indentation. Spaces before the last newline should
521 521 # be preserved, so plain rstrip() isn't good enough.
522 522 want = m.group('want')
523 523 want_lines = want.split('\n')
524 524 if len(want_lines) > 1 and re.match(r' *$', want_lines[-1]):
525 525 del want_lines[-1] # forget final newline & spaces after it
526 526 self._check_prefix(want_lines, ' '*indent, name,
527 527 lineno + len(source_lines))
528 528
529 529 # Remove ipython output prompt that might be present in the first line
530 530 want_lines[0] = re.sub(r'Out\[\d+\]: \s*?\n?','',want_lines[0])
531 531
532 532 want = '\n'.join([wl[indent:] for wl in want_lines])
533 533
534 534 # If `want` contains a traceback message, then extract it.
535 535 m = self._EXCEPTION_RE.match(want)
536 536 if m:
537 537 exc_msg = m.group('msg')
538 538 else:
539 539 exc_msg = None
540 540
541 541 # Extract options from the source.
542 542 options = self._find_options(source, name, lineno)
543 543
544 544 return source, options, want, exc_msg
545 545
546 546 def _check_prompt_blank(self, lines, indent, name, lineno, ps1_len):
547 547 """
548 548 Given the lines of a source string (including prompts and
549 549 leading indentation), check to make sure that every prompt is
550 550 followed by a space character. If any line is not followed by
551 551 a space character, then raise ValueError.
552 552
553 553 Note: IPython-modified version which takes the input prompt length as a
554 554 parameter, so that prompts of variable length can be dealt with.
555 555 """
556 556 space_idx = indent+ps1_len
557 557 min_len = space_idx+1
558 558 for i, line in enumerate(lines):
559 559 if len(line) >= min_len and line[space_idx] != ' ':
560 560 raise ValueError('line %r of the docstring for %s '
561 561 'lacks blank after %s: %r' %
562 562 (lineno+i+1, name,
563 563 line[indent:space_idx], line))
564 564
565 565
566 566 SKIP = doctest.register_optionflag('SKIP')
567 567
568 568
569 569 class IPDocTestRunner(doctest.DocTestRunner,object):
570 570 """Test runner that synchronizes the IPython namespace with test globals.
571 571 """
572 572
573 573 def run(self, test, compileflags=None, out=None, clear_globs=True):
574 574
575 575 # Hack: ipython needs access to the execution context of the example,
576 576 # so that it can propagate user variables loaded by %run into
577 577 # test.globs. We put them here into our modified %run as a function
578 578 # attribute. Our new %run will then only make the namespace update
579 579 # when called (rather than unconconditionally updating test.globs here
580 580 # for all examples, most of which won't be calling %run anyway).
581 581 #_ip._ipdoctest_test_globs = test.globs
582 582 #_ip._ipdoctest_test_filename = test.filename
583 583
584 584 test.globs.update(_ip.user_ns)
585 585
586 586 return super(IPDocTestRunner,self).run(test,
587 587 compileflags,out,clear_globs)
588 588
589 589
590 590 class DocFileCase(doctest.DocFileCase):
591 591 """Overrides to provide filename
592 592 """
593 593 def address(self):
594 594 return (self._dt_test.filename, None, None)
595 595
596 596
597 597 class ExtensionDoctest(doctests.Doctest):
598 598 """Nose Plugin that supports doctests in extension modules.
599 599 """
600 600 name = 'extdoctest' # call nosetests with --with-extdoctest
601 601 enabled = True
602 602
603 603 def options(self, parser, env=os.environ):
604 604 Plugin.options(self, parser, env)
605 605 parser.add_option('--doctest-tests', action='store_true',
606 606 dest='doctest_tests',
607 607 default=env.get('NOSE_DOCTEST_TESTS',True),
608 608 help="Also look for doctests in test modules. "
609 609 "Note that classes, methods and functions should "
610 610 "have either doctests or non-doctest tests, "
611 611 "not both. [NOSE_DOCTEST_TESTS]")
612 612 parser.add_option('--doctest-extension', action="append",
613 613 dest="doctestExtension",
614 614 help="Also look for doctests in files with "
615 615 "this extension [NOSE_DOCTEST_EXTENSION]")
616 616 # Set the default as a list, if given in env; otherwise
617 617 # an additional value set on the command line will cause
618 618 # an error.
619 619 env_setting = env.get('NOSE_DOCTEST_EXTENSION')
620 620 if env_setting is not None:
621 621 parser.set_defaults(doctestExtension=tolist(env_setting))
622 622
623 623
624 624 def configure(self, options, config):
625 625 Plugin.configure(self, options, config)
626 626 # Pull standard doctest plugin out of config; we will do doctesting
627 627 config.plugins.plugins = [p for p in config.plugins.plugins
628 628 if p.name != 'doctest']
629 629 self.doctest_tests = options.doctest_tests
630 630 self.extension = tolist(options.doctestExtension)
631 631
632 632 self.parser = doctest.DocTestParser()
633 633 self.finder = DocTestFinder()
634 634 self.checker = IPDoctestOutputChecker()
635 635 self.globs = None
636 636 self.extraglobs = None
637 637
638 638
639 639 def loadTestsFromExtensionModule(self,filename):
640 640 bpath,mod = os.path.split(filename)
641 641 modname = os.path.splitext(mod)[0]
642 642 try:
643 643 sys.path.append(bpath)
644 644 module = __import__(modname)
645 645 tests = list(self.loadTestsFromModule(module))
646 646 finally:
647 647 sys.path.pop()
648 648 return tests
649 649
650 650 # NOTE: the method below is almost a copy of the original one in nose, with
651 651 # a few modifications to control output checking.
652 652
653 653 def loadTestsFromModule(self, module):
654 654 #print '*** ipdoctest - lTM',module # dbg
655 655
656 656 if not self.matches(module.__name__):
657 657 log.debug("Doctest doesn't want module %s", module)
658 658 return
659 659
660 660 tests = self.finder.find(module,globs=self.globs,
661 661 extraglobs=self.extraglobs)
662 662 if not tests:
663 663 return
664 664
665 665 # always use whitespace and ellipsis options
666 666 optionflags = doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS
667 667
668 668 tests.sort()
669 669 module_file = module.__file__
670 670 if module_file[-4:] in ('.pyc', '.pyo'):
671 671 module_file = module_file[:-1]
672 672 for test in tests:
673 673 if not test.examples:
674 674 continue
675 675 if not test.filename:
676 676 test.filename = module_file
677 677
678 678 yield DocTestCase(test,
679 679 optionflags=optionflags,
680 680 checker=self.checker)
681 681
682 682
683 683 def loadTestsFromFile(self, filename):
684 684 #print "ipdoctest - from file", filename # dbg
685 685 if is_extension_module(filename):
686 686 for t in self.loadTestsFromExtensionModule(filename):
687 687 yield t
688 688 else:
689 689 if self.extension and anyp(filename.endswith, self.extension):
690 690 name = os.path.basename(filename)
691 691 dh = open(filename)
692 692 try:
693 693 doc = dh.read()
694 694 finally:
695 695 dh.close()
696 696 test = self.parser.get_doctest(
697 697 doc, globs={'__file__': filename}, name=name,
698 698 filename=filename, lineno=0)
699 699 if test.examples:
700 700 #print 'FileCase:',test.examples # dbg
701 701 yield DocFileCase(test)
702 702 else:
703 703 yield False # no tests to load
704 704
705 705
706 706 class IPythonDoctest(ExtensionDoctest):
707 707 """Nose Plugin that supports doctests in extension modules.
708 708 """
709 709 name = 'ipdoctest' # call nosetests with --with-ipdoctest
710 710 enabled = True
711 711
712 712 def makeTest(self, obj, parent):
713 713 """Look for doctests in the given object, which will be a
714 714 function, method or class.
715 715 """
716 716 #print 'Plugin analyzing:', obj, parent # dbg
717 717 # always use whitespace and ellipsis options
718 718 optionflags = doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS
719 719
720 720 doctests = self.finder.find(obj, module=getmodule(parent))
721 721 if doctests:
722 722 for test in doctests:
723 723 if len(test.examples) == 0:
724 724 continue
725 725
726 726 yield DocTestCase(test, obj=obj,
727 727 optionflags=optionflags,
728 728 checker=self.checker)
729 729
730 730 def options(self, parser, env=os.environ):
731 731 #print "Options for nose plugin:", self.name # dbg
732 732 Plugin.options(self, parser, env)
733 733 parser.add_option('--ipdoctest-tests', action='store_true',
734 734 dest='ipdoctest_tests',
735 735 default=env.get('NOSE_IPDOCTEST_TESTS',True),
736 736 help="Also look for doctests in test modules. "
737 737 "Note that classes, methods and functions should "
738 738 "have either doctests or non-doctest tests, "
739 739 "not both. [NOSE_IPDOCTEST_TESTS]")
740 740 parser.add_option('--ipdoctest-extension', action="append",
741 741 dest="ipdoctest_extension",
742 742 help="Also look for doctests in files with "
743 743 "this extension [NOSE_IPDOCTEST_EXTENSION]")
744 744 # Set the default as a list, if given in env; otherwise
745 745 # an additional value set on the command line will cause
746 746 # an error.
747 747 env_setting = env.get('NOSE_IPDOCTEST_EXTENSION')
748 748 if env_setting is not None:
749 749 parser.set_defaults(ipdoctest_extension=tolist(env_setting))
750 750
751 751 def configure(self, options, config):
752 752 #print "Configuring nose plugin:", self.name # dbg
753 753 Plugin.configure(self, options, config)
754 754 # Pull standard doctest plugin out of config; we will do doctesting
755 755 config.plugins.plugins = [p for p in config.plugins.plugins
756 756 if p.name != 'doctest']
757 757 self.doctest_tests = options.ipdoctest_tests
758 758 self.extension = tolist(options.ipdoctest_extension)
759 759
760 760 self.parser = IPDocTestParser()
761 761 self.finder = DocTestFinder(parser=self.parser)
762 762 self.checker = IPDoctestOutputChecker()
763 763 self.globs = None
764 764 self.extraglobs = None
@@ -1,187 +1,187 b''
1 1 """Windows-specific implementation of process utilities.
2 2
3 3 This file is only meant to be imported by process.py, not by end-users.
4 4 """
5 5
6 6 #-----------------------------------------------------------------------------
7 7 # Copyright (C) 2010-2011 The IPython Development Team
8 8 #
9 9 # Distributed under the terms of the BSD License. The full license is in
10 10 # the file COPYING, distributed as part of this software.
11 11 #-----------------------------------------------------------------------------
12 12
13 13 #-----------------------------------------------------------------------------
14 14 # Imports
15 15 #-----------------------------------------------------------------------------
16 16 from __future__ import print_function
17 17
18 18 # stdlib
19 19 import os
20 20 import sys
21 21 import ctypes
22 22
23 23 from ctypes import c_int, POINTER
24 24 from ctypes.wintypes import LPCWSTR, HLOCAL
25 25 from subprocess import STDOUT
26 26
27 27 # our own imports
28 28 from ._process_common import read_no_interrupt, process_handler, arg_split as py_arg_split
29 29 from . import py3compat
30 30 from .encoding import DEFAULT_ENCODING
31 31
32 32 #-----------------------------------------------------------------------------
33 33 # Function definitions
34 34 #-----------------------------------------------------------------------------
35 35
36 36 class AvoidUNCPath(object):
37 37 """A context manager to protect command execution from UNC paths.
38 38
39 39 In the Win32 API, commands can't be invoked with the cwd being a UNC path.
40 40 This context manager temporarily changes directory to the 'C:' drive on
41 41 entering, and restores the original working directory on exit.
42 42
43 43 The context manager returns the starting working directory *if* it made a
44 44 change and None otherwise, so that users can apply the necessary adjustment
45 45 to their system calls in the event of a change.
46 46
47 47 Examples
48 48 --------
49 49 ::
50 50 cmd = 'dir'
51 51 with AvoidUNCPath() as path:
52 52 if path is not None:
53 53 cmd = '"pushd %s &&"%s' % (path, cmd)
54 54 os.system(cmd)
55 55 """
56 56 def __enter__(self):
57 self.path = os.getcwdu()
57 self.path = py3compat.getcwd()
58 58 self.is_unc_path = self.path.startswith(r"\\")
59 59 if self.is_unc_path:
60 60 # change to c drive (as cmd.exe cannot handle UNC addresses)
61 61 os.chdir("C:")
62 62 return self.path
63 63 else:
64 64 # We return None to signal that there was no change in the working
65 65 # directory
66 66 return None
67 67
68 68 def __exit__(self, exc_type, exc_value, traceback):
69 69 if self.is_unc_path:
70 70 os.chdir(self.path)
71 71
72 72
73 73 def _find_cmd(cmd):
74 74 """Find the full path to a .bat or .exe using the win32api module."""
75 75 try:
76 76 from win32api import SearchPath
77 77 except ImportError:
78 78 raise ImportError('you need to have pywin32 installed for this to work')
79 79 else:
80 80 PATH = os.environ['PATH']
81 81 extensions = ['.exe', '.com', '.bat', '.py']
82 82 path = None
83 83 for ext in extensions:
84 84 try:
85 85 path = SearchPath(PATH, cmd, ext)[0]
86 86 except:
87 87 pass
88 88 if path is None:
89 89 raise OSError("command %r not found" % cmd)
90 90 else:
91 91 return path
92 92
93 93
94 94 def _system_body(p):
95 95 """Callback for _system."""
96 96 enc = DEFAULT_ENCODING
97 97 for line in read_no_interrupt(p.stdout).splitlines():
98 98 line = line.decode(enc, 'replace')
99 99 print(line, file=sys.stdout)
100 100 for line in read_no_interrupt(p.stderr).splitlines():
101 101 line = line.decode(enc, 'replace')
102 102 print(line, file=sys.stderr)
103 103
104 104 # Wait to finish for returncode
105 105 return p.wait()
106 106
107 107
108 108 def system(cmd):
109 109 """Win32 version of os.system() that works with network shares.
110 110
111 111 Note that this implementation returns None, as meant for use in IPython.
112 112
113 113 Parameters
114 114 ----------
115 115 cmd : str
116 116 A command to be executed in the system shell.
117 117
118 118 Returns
119 119 -------
120 120 None : we explicitly do NOT return the subprocess status code, as this
121 121 utility is meant to be used extensively in IPython, where any return value
122 122 would trigger :func:`sys.displayhook` calls.
123 123 """
124 124 # The controller provides interactivity with both
125 125 # stdin and stdout
126 126 #import _process_win32_controller
127 127 #_process_win32_controller.system(cmd)
128 128
129 129 with AvoidUNCPath() as path:
130 130 if path is not None:
131 131 cmd = '"pushd %s &&"%s' % (path, cmd)
132 132 return process_handler(cmd, _system_body)
133 133
134 134 def getoutput(cmd):
135 135 """Return standard output of executing cmd in a shell.
136 136
137 137 Accepts the same arguments as os.system().
138 138
139 139 Parameters
140 140 ----------
141 141 cmd : str
142 142 A command to be executed in the system shell.
143 143
144 144 Returns
145 145 -------
146 146 stdout : str
147 147 """
148 148
149 149 with AvoidUNCPath() as path:
150 150 if path is not None:
151 151 cmd = '"pushd %s &&"%s' % (path, cmd)
152 152 out = process_handler(cmd, lambda p: p.communicate()[0], STDOUT)
153 153
154 154 if out is None:
155 155 out = b''
156 156 return py3compat.bytes_to_str(out)
157 157
158 158 try:
159 159 CommandLineToArgvW = ctypes.windll.shell32.CommandLineToArgvW
160 160 CommandLineToArgvW.arg_types = [LPCWSTR, POINTER(c_int)]
161 161 CommandLineToArgvW.restype = POINTER(LPCWSTR)
162 162 LocalFree = ctypes.windll.kernel32.LocalFree
163 163 LocalFree.res_type = HLOCAL
164 164 LocalFree.arg_types = [HLOCAL]
165 165
166 166 def arg_split(commandline, posix=False, strict=True):
167 167 """Split a command line's arguments in a shell-like manner.
168 168
169 169 This is a special version for windows that use a ctypes call to CommandLineToArgvW
170 170 to do the argv splitting. The posix paramter is ignored.
171 171
172 172 If strict=False, process_common.arg_split(...strict=False) is used instead.
173 173 """
174 174 #CommandLineToArgvW returns path to executable if called with empty string.
175 175 if commandline.strip() == "":
176 176 return []
177 177 if not strict:
178 178 # not really a cl-arg, fallback on _process_common
179 179 return py_arg_split(commandline, posix=posix, strict=strict)
180 180 argvn = c_int()
181 181 result_pointer = CommandLineToArgvW(py3compat.cast_unicode(commandline.lstrip()), ctypes.byref(argvn))
182 182 result_array_type = LPCWSTR * argvn.value
183 183 result = [arg for arg in result_array_type.from_address(ctypes.addressof(result_pointer.contents))]
184 184 retval = LocalFree(result_pointer)
185 185 return result
186 186 except AttributeError:
187 187 arg_split = py_arg_split
@@ -1,577 +1,577 b''
1 1 """Windows-specific implementation of process utilities with direct WinAPI.
2 2
3 3 This file is meant to be used by process.py
4 4 """
5 5
6 6 #-----------------------------------------------------------------------------
7 7 # Copyright (C) 2010-2011 The IPython Development Team
8 8 #
9 9 # Distributed under the terms of the BSD License. The full license is in
10 10 # the file COPYING, distributed as part of this software.
11 11 #-----------------------------------------------------------------------------
12 12
13 13 from __future__ import print_function
14 14
15 15 # stdlib
16 16 import os, sys, threading
17 17 import ctypes, msvcrt
18 18
19 19 # local imports
20 from .py3compat import unicode_type
20 from . import py3compat
21 21
22 22 # Win32 API types needed for the API calls
23 23 from ctypes import POINTER
24 24 from ctypes.wintypes import HANDLE, HLOCAL, LPVOID, WORD, DWORD, BOOL, \
25 25 ULONG, LPCWSTR
26 26 LPDWORD = POINTER(DWORD)
27 27 LPHANDLE = POINTER(HANDLE)
28 28 ULONG_PTR = POINTER(ULONG)
29 29 class SECURITY_ATTRIBUTES(ctypes.Structure):
30 30 _fields_ = [("nLength", DWORD),
31 31 ("lpSecurityDescriptor", LPVOID),
32 32 ("bInheritHandle", BOOL)]
33 33 LPSECURITY_ATTRIBUTES = POINTER(SECURITY_ATTRIBUTES)
34 34 class STARTUPINFO(ctypes.Structure):
35 35 _fields_ = [("cb", DWORD),
36 36 ("lpReserved", LPCWSTR),
37 37 ("lpDesktop", LPCWSTR),
38 38 ("lpTitle", LPCWSTR),
39 39 ("dwX", DWORD),
40 40 ("dwY", DWORD),
41 41 ("dwXSize", DWORD),
42 42 ("dwYSize", DWORD),
43 43 ("dwXCountChars", DWORD),
44 44 ("dwYCountChars", DWORD),
45 45 ("dwFillAttribute", DWORD),
46 46 ("dwFlags", DWORD),
47 47 ("wShowWindow", WORD),
48 48 ("cbReserved2", WORD),
49 49 ("lpReserved2", LPVOID),
50 50 ("hStdInput", HANDLE),
51 51 ("hStdOutput", HANDLE),
52 52 ("hStdError", HANDLE)]
53 53 LPSTARTUPINFO = POINTER(STARTUPINFO)
54 54 class PROCESS_INFORMATION(ctypes.Structure):
55 55 _fields_ = [("hProcess", HANDLE),
56 56 ("hThread", HANDLE),
57 57 ("dwProcessId", DWORD),
58 58 ("dwThreadId", DWORD)]
59 59 LPPROCESS_INFORMATION = POINTER(PROCESS_INFORMATION)
60 60
61 61 # Win32 API constants needed
62 62 ERROR_HANDLE_EOF = 38
63 63 ERROR_BROKEN_PIPE = 109
64 64 ERROR_NO_DATA = 232
65 65 HANDLE_FLAG_INHERIT = 0x0001
66 66 STARTF_USESTDHANDLES = 0x0100
67 67 CREATE_SUSPENDED = 0x0004
68 68 CREATE_NEW_CONSOLE = 0x0010
69 69 CREATE_NO_WINDOW = 0x08000000
70 70 STILL_ACTIVE = 259
71 71 WAIT_TIMEOUT = 0x0102
72 72 WAIT_FAILED = 0xFFFFFFFF
73 73 INFINITE = 0xFFFFFFFF
74 74 DUPLICATE_SAME_ACCESS = 0x00000002
75 75 ENABLE_ECHO_INPUT = 0x0004
76 76 ENABLE_LINE_INPUT = 0x0002
77 77 ENABLE_PROCESSED_INPUT = 0x0001
78 78
79 79 # Win32 API functions needed
80 80 GetLastError = ctypes.windll.kernel32.GetLastError
81 81 GetLastError.argtypes = []
82 82 GetLastError.restype = DWORD
83 83
84 84 CreateFile = ctypes.windll.kernel32.CreateFileW
85 85 CreateFile.argtypes = [LPCWSTR, DWORD, DWORD, LPVOID, DWORD, DWORD, HANDLE]
86 86 CreateFile.restype = HANDLE
87 87
88 88 CreatePipe = ctypes.windll.kernel32.CreatePipe
89 89 CreatePipe.argtypes = [POINTER(HANDLE), POINTER(HANDLE),
90 90 LPSECURITY_ATTRIBUTES, DWORD]
91 91 CreatePipe.restype = BOOL
92 92
93 93 CreateProcess = ctypes.windll.kernel32.CreateProcessW
94 94 CreateProcess.argtypes = [LPCWSTR, LPCWSTR, LPSECURITY_ATTRIBUTES,
95 95 LPSECURITY_ATTRIBUTES, BOOL, DWORD, LPVOID, LPCWSTR, LPSTARTUPINFO,
96 96 LPPROCESS_INFORMATION]
97 97 CreateProcess.restype = BOOL
98 98
99 99 GetExitCodeProcess = ctypes.windll.kernel32.GetExitCodeProcess
100 100 GetExitCodeProcess.argtypes = [HANDLE, LPDWORD]
101 101 GetExitCodeProcess.restype = BOOL
102 102
103 103 GetCurrentProcess = ctypes.windll.kernel32.GetCurrentProcess
104 104 GetCurrentProcess.argtypes = []
105 105 GetCurrentProcess.restype = HANDLE
106 106
107 107 ResumeThread = ctypes.windll.kernel32.ResumeThread
108 108 ResumeThread.argtypes = [HANDLE]
109 109 ResumeThread.restype = DWORD
110 110
111 111 ReadFile = ctypes.windll.kernel32.ReadFile
112 112 ReadFile.argtypes = [HANDLE, LPVOID, DWORD, LPDWORD, LPVOID]
113 113 ReadFile.restype = BOOL
114 114
115 115 WriteFile = ctypes.windll.kernel32.WriteFile
116 116 WriteFile.argtypes = [HANDLE, LPVOID, DWORD, LPDWORD, LPVOID]
117 117 WriteFile.restype = BOOL
118 118
119 119 GetConsoleMode = ctypes.windll.kernel32.GetConsoleMode
120 120 GetConsoleMode.argtypes = [HANDLE, LPDWORD]
121 121 GetConsoleMode.restype = BOOL
122 122
123 123 SetConsoleMode = ctypes.windll.kernel32.SetConsoleMode
124 124 SetConsoleMode.argtypes = [HANDLE, DWORD]
125 125 SetConsoleMode.restype = BOOL
126 126
127 127 FlushConsoleInputBuffer = ctypes.windll.kernel32.FlushConsoleInputBuffer
128 128 FlushConsoleInputBuffer.argtypes = [HANDLE]
129 129 FlushConsoleInputBuffer.restype = BOOL
130 130
131 131 WaitForSingleObject = ctypes.windll.kernel32.WaitForSingleObject
132 132 WaitForSingleObject.argtypes = [HANDLE, DWORD]
133 133 WaitForSingleObject.restype = DWORD
134 134
135 135 DuplicateHandle = ctypes.windll.kernel32.DuplicateHandle
136 136 DuplicateHandle.argtypes = [HANDLE, HANDLE, HANDLE, LPHANDLE,
137 137 DWORD, BOOL, DWORD]
138 138 DuplicateHandle.restype = BOOL
139 139
140 140 SetHandleInformation = ctypes.windll.kernel32.SetHandleInformation
141 141 SetHandleInformation.argtypes = [HANDLE, DWORD, DWORD]
142 142 SetHandleInformation.restype = BOOL
143 143
144 144 CloseHandle = ctypes.windll.kernel32.CloseHandle
145 145 CloseHandle.argtypes = [HANDLE]
146 146 CloseHandle.restype = BOOL
147 147
148 148 CommandLineToArgvW = ctypes.windll.shell32.CommandLineToArgvW
149 149 CommandLineToArgvW.argtypes = [LPCWSTR, POINTER(ctypes.c_int)]
150 150 CommandLineToArgvW.restype = POINTER(LPCWSTR)
151 151
152 152 LocalFree = ctypes.windll.kernel32.LocalFree
153 153 LocalFree.argtypes = [HLOCAL]
154 154 LocalFree.restype = HLOCAL
155 155
156 156 class AvoidUNCPath(object):
157 157 """A context manager to protect command execution from UNC paths.
158 158
159 159 In the Win32 API, commands can't be invoked with the cwd being a UNC path.
160 160 This context manager temporarily changes directory to the 'C:' drive on
161 161 entering, and restores the original working directory on exit.
162 162
163 163 The context manager returns the starting working directory *if* it made a
164 164 change and None otherwise, so that users can apply the necessary adjustment
165 165 to their system calls in the event of a change.
166 166
167 167 Examples
168 168 --------
169 169 ::
170 170 cmd = 'dir'
171 171 with AvoidUNCPath() as path:
172 172 if path is not None:
173 173 cmd = '"pushd %s &&"%s' % (path, cmd)
174 174 os.system(cmd)
175 175 """
176 176 def __enter__(self):
177 self.path = os.getcwdu()
177 self.path = py3compat.getcwd()
178 178 self.is_unc_path = self.path.startswith(r"\\")
179 179 if self.is_unc_path:
180 180 # change to c drive (as cmd.exe cannot handle UNC addresses)
181 181 os.chdir("C:")
182 182 return self.path
183 183 else:
184 184 # We return None to signal that there was no change in the working
185 185 # directory
186 186 return None
187 187
188 188 def __exit__(self, exc_type, exc_value, traceback):
189 189 if self.is_unc_path:
190 190 os.chdir(self.path)
191 191
192 192
193 193 class Win32ShellCommandController(object):
194 194 """Runs a shell command in a 'with' context.
195 195
196 196 This implementation is Win32-specific.
197 197
198 198 Example:
199 199 # Runs the command interactively with default console stdin/stdout
200 200 with ShellCommandController('python -i') as scc:
201 201 scc.run()
202 202
203 203 # Runs the command using the provided functions for stdin/stdout
204 204 def my_stdout_func(s):
205 205 # print or save the string 's'
206 206 write_to_stdout(s)
207 207 def my_stdin_func():
208 208 # If input is available, return it as a string.
209 209 if input_available():
210 210 return get_input()
211 211 # If no input available, return None after a short delay to
212 212 # keep from blocking.
213 213 else:
214 214 time.sleep(0.01)
215 215 return None
216 216
217 217 with ShellCommandController('python -i') as scc:
218 218 scc.run(my_stdout_func, my_stdin_func)
219 219 """
220 220
221 221 def __init__(self, cmd, mergeout = True):
222 222 """Initializes the shell command controller.
223 223
224 224 The cmd is the program to execute, and mergeout is
225 225 whether to blend stdout and stderr into one output
226 226 in stdout. Merging them together in this fashion more
227 227 reliably keeps stdout and stderr in the correct order
228 228 especially for interactive shell usage.
229 229 """
230 230 self.cmd = cmd
231 231 self.mergeout = mergeout
232 232
233 233 def __enter__(self):
234 234 cmd = self.cmd
235 235 mergeout = self.mergeout
236 236
237 237 self.hstdout, self.hstdin, self.hstderr = None, None, None
238 238 self.piProcInfo = None
239 239 try:
240 240 p_hstdout, c_hstdout, p_hstderr, \
241 241 c_hstderr, p_hstdin, c_hstdin = [None]*6
242 242
243 243 # SECURITY_ATTRIBUTES with inherit handle set to True
244 244 saAttr = SECURITY_ATTRIBUTES()
245 245 saAttr.nLength = ctypes.sizeof(saAttr)
246 246 saAttr.bInheritHandle = True
247 247 saAttr.lpSecurityDescriptor = None
248 248
249 249 def create_pipe(uninherit):
250 250 """Creates a Windows pipe, which consists of two handles.
251 251
252 252 The 'uninherit' parameter controls which handle is not
253 253 inherited by the child process.
254 254 """
255 255 handles = HANDLE(), HANDLE()
256 256 if not CreatePipe(ctypes.byref(handles[0]),
257 257 ctypes.byref(handles[1]), ctypes.byref(saAttr), 0):
258 258 raise ctypes.WinError()
259 259 if not SetHandleInformation(handles[uninherit],
260 260 HANDLE_FLAG_INHERIT, 0):
261 261 raise ctypes.WinError()
262 262 return handles[0].value, handles[1].value
263 263
264 264 p_hstdout, c_hstdout = create_pipe(uninherit=0)
265 265 # 'mergeout' signals that stdout and stderr should be merged.
266 266 # We do that by using one pipe for both of them.
267 267 if mergeout:
268 268 c_hstderr = HANDLE()
269 269 if not DuplicateHandle(GetCurrentProcess(), c_hstdout,
270 270 GetCurrentProcess(), ctypes.byref(c_hstderr),
271 271 0, True, DUPLICATE_SAME_ACCESS):
272 272 raise ctypes.WinError()
273 273 else:
274 274 p_hstderr, c_hstderr = create_pipe(uninherit=0)
275 275 c_hstdin, p_hstdin = create_pipe(uninherit=1)
276 276
277 277 # Create the process object
278 278 piProcInfo = PROCESS_INFORMATION()
279 279 siStartInfo = STARTUPINFO()
280 280 siStartInfo.cb = ctypes.sizeof(siStartInfo)
281 281 siStartInfo.hStdInput = c_hstdin
282 282 siStartInfo.hStdOutput = c_hstdout
283 283 siStartInfo.hStdError = c_hstderr
284 284 siStartInfo.dwFlags = STARTF_USESTDHANDLES
285 285 dwCreationFlags = CREATE_SUSPENDED | CREATE_NO_WINDOW # | CREATE_NEW_CONSOLE
286 286
287 287 if not CreateProcess(None,
288 288 u"cmd.exe /c " + cmd,
289 289 None, None, True, dwCreationFlags,
290 290 None, None, ctypes.byref(siStartInfo),
291 291 ctypes.byref(piProcInfo)):
292 292 raise ctypes.WinError()
293 293
294 294 # Close this process's versions of the child handles
295 295 CloseHandle(c_hstdin)
296 296 c_hstdin = None
297 297 CloseHandle(c_hstdout)
298 298 c_hstdout = None
299 299 if c_hstderr != None:
300 300 CloseHandle(c_hstderr)
301 301 c_hstderr = None
302 302
303 303 # Transfer ownership of the parent handles to the object
304 304 self.hstdin = p_hstdin
305 305 p_hstdin = None
306 306 self.hstdout = p_hstdout
307 307 p_hstdout = None
308 308 if not mergeout:
309 309 self.hstderr = p_hstderr
310 310 p_hstderr = None
311 311 self.piProcInfo = piProcInfo
312 312
313 313 finally:
314 314 if p_hstdin:
315 315 CloseHandle(p_hstdin)
316 316 if c_hstdin:
317 317 CloseHandle(c_hstdin)
318 318 if p_hstdout:
319 319 CloseHandle(p_hstdout)
320 320 if c_hstdout:
321 321 CloseHandle(c_hstdout)
322 322 if p_hstderr:
323 323 CloseHandle(p_hstderr)
324 324 if c_hstderr:
325 325 CloseHandle(c_hstderr)
326 326
327 327 return self
328 328
329 329 def _stdin_thread(self, handle, hprocess, func, stdout_func):
330 330 exitCode = DWORD()
331 331 bytesWritten = DWORD(0)
332 332 while True:
333 333 #print("stdin thread loop start")
334 334 # Get the input string (may be bytes or unicode)
335 335 data = func()
336 336
337 337 # None signals to poll whether the process has exited
338 338 if data is None:
339 339 #print("checking for process completion")
340 340 if not GetExitCodeProcess(hprocess, ctypes.byref(exitCode)):
341 341 raise ctypes.WinError()
342 342 if exitCode.value != STILL_ACTIVE:
343 343 return
344 344 # TESTING: Does zero-sized writefile help?
345 345 if not WriteFile(handle, "", 0,
346 346 ctypes.byref(bytesWritten), None):
347 347 raise ctypes.WinError()
348 348 continue
349 349 #print("\nGot str %s\n" % repr(data), file=sys.stderr)
350 350
351 351 # Encode the string to the console encoding
352 352 if isinstance(data, unicode): #FIXME: Python3
353 353 data = data.encode('utf_8')
354 354
355 355 # What we have now must be a string of bytes
356 356 if not isinstance(data, str): #FIXME: Python3
357 357 raise RuntimeError("internal stdin function string error")
358 358
359 359 # An empty string signals EOF
360 360 if len(data) == 0:
361 361 return
362 362
363 363 # In a windows console, sometimes the input is echoed,
364 364 # but sometimes not. How do we determine when to do this?
365 365 stdout_func(data)
366 366 # WriteFile may not accept all the data at once.
367 367 # Loop until everything is processed
368 368 while len(data) != 0:
369 369 #print("Calling writefile")
370 370 if not WriteFile(handle, data, len(data),
371 371 ctypes.byref(bytesWritten), None):
372 372 # This occurs at exit
373 373 if GetLastError() == ERROR_NO_DATA:
374 374 return
375 375 raise ctypes.WinError()
376 376 #print("Called writefile")
377 377 data = data[bytesWritten.value:]
378 378
379 379 def _stdout_thread(self, handle, func):
380 380 # Allocate the output buffer
381 381 data = ctypes.create_string_buffer(4096)
382 382 while True:
383 383 bytesRead = DWORD(0)
384 384 if not ReadFile(handle, data, 4096,
385 385 ctypes.byref(bytesRead), None):
386 386 le = GetLastError()
387 387 if le == ERROR_BROKEN_PIPE:
388 388 return
389 389 else:
390 390 raise ctypes.WinError()
391 391 # FIXME: Python3
392 392 s = data.value[0:bytesRead.value]
393 393 #print("\nv: %s" % repr(s), file=sys.stderr)
394 394 func(s.decode('utf_8', 'replace'))
395 395
396 396 def run(self, stdout_func = None, stdin_func = None, stderr_func = None):
397 397 """Runs the process, using the provided functions for I/O.
398 398
399 399 The function stdin_func should return strings whenever a
400 400 character or characters become available.
401 401 The functions stdout_func and stderr_func are called whenever
402 402 something is printed to stdout or stderr, respectively.
403 403 These functions are called from different threads (but not
404 404 concurrently, because of the GIL).
405 405 """
406 406 if stdout_func == None and stdin_func == None and stderr_func == None:
407 407 return self._run_stdio()
408 408
409 409 if stderr_func != None and self.mergeout:
410 410 raise RuntimeError("Shell command was initiated with "
411 411 "merged stdin/stdout, but a separate stderr_func "
412 412 "was provided to the run() method")
413 413
414 414 # Create a thread for each input/output handle
415 415 stdin_thread = None
416 416 threads = []
417 417 if stdin_func:
418 418 stdin_thread = threading.Thread(target=self._stdin_thread,
419 419 args=(self.hstdin, self.piProcInfo.hProcess,
420 420 stdin_func, stdout_func))
421 421 threads.append(threading.Thread(target=self._stdout_thread,
422 422 args=(self.hstdout, stdout_func)))
423 423 if not self.mergeout:
424 424 if stderr_func == None:
425 425 stderr_func = stdout_func
426 426 threads.append(threading.Thread(target=self._stdout_thread,
427 427 args=(self.hstderr, stderr_func)))
428 428 # Start the I/O threads and the process
429 429 if ResumeThread(self.piProcInfo.hThread) == 0xFFFFFFFF:
430 430 raise ctypes.WinError()
431 431 if stdin_thread is not None:
432 432 stdin_thread.start()
433 433 for thread in threads:
434 434 thread.start()
435 435 # Wait for the process to complete
436 436 if WaitForSingleObject(self.piProcInfo.hProcess, INFINITE) == \
437 437 WAIT_FAILED:
438 438 raise ctypes.WinError()
439 439 # Wait for the I/O threads to complete
440 440 for thread in threads:
441 441 thread.join()
442 442
443 443 # Wait for the stdin thread to complete
444 444 if stdin_thread is not None:
445 445 stdin_thread.join()
446 446
447 447 def _stdin_raw_nonblock(self):
448 448 """Use the raw Win32 handle of sys.stdin to do non-blocking reads"""
449 449 # WARNING: This is experimental, and produces inconsistent results.
450 450 # It's possible for the handle not to be appropriate for use
451 451 # with WaitForSingleObject, among other things.
452 452 handle = msvcrt.get_osfhandle(sys.stdin.fileno())
453 453 result = WaitForSingleObject(handle, 100)
454 454 if result == WAIT_FAILED:
455 455 raise ctypes.WinError()
456 456 elif result == WAIT_TIMEOUT:
457 457 print(".", end='')
458 458 return None
459 459 else:
460 460 data = ctypes.create_string_buffer(256)
461 461 bytesRead = DWORD(0)
462 462 print('?', end='')
463 463
464 464 if not ReadFile(handle, data, 256,
465 465 ctypes.byref(bytesRead), None):
466 466 raise ctypes.WinError()
467 467 # This ensures the non-blocking works with an actual console
468 468 # Not checking the error, so the processing will still work with
469 469 # other handle types
470 470 FlushConsoleInputBuffer(handle)
471 471
472 472 data = data.value
473 473 data = data.replace('\r\n', '\n')
474 474 data = data.replace('\r', '\n')
475 475 print(repr(data) + " ", end='')
476 476 return data
477 477
478 478 def _stdin_raw_block(self):
479 479 """Use a blocking stdin read"""
480 480 # The big problem with the blocking read is that it doesn't
481 481 # exit when it's supposed to in all contexts. An extra
482 482 # key-press may be required to trigger the exit.
483 483 try:
484 484 data = sys.stdin.read(1)
485 485 data = data.replace('\r', '\n')
486 486 return data
487 487 except WindowsError as we:
488 488 if we.winerror == ERROR_NO_DATA:
489 489 # This error occurs when the pipe is closed
490 490 return None
491 491 else:
492 492 # Otherwise let the error propagate
493 493 raise we
494 494
495 495 def _stdout_raw(self, s):
496 496 """Writes the string to stdout"""
497 497 print(s, end='', file=sys.stdout)
498 498 sys.stdout.flush()
499 499
500 500 def _stderr_raw(self, s):
501 501 """Writes the string to stdout"""
502 502 print(s, end='', file=sys.stderr)
503 503 sys.stderr.flush()
504 504
505 505 def _run_stdio(self):
506 506 """Runs the process using the system standard I/O.
507 507
508 508 IMPORTANT: stdin needs to be asynchronous, so the Python
509 509 sys.stdin object is not used. Instead,
510 510 msvcrt.kbhit/getwch are used asynchronously.
511 511 """
512 512 # Disable Line and Echo mode
513 513 #lpMode = DWORD()
514 514 #handle = msvcrt.get_osfhandle(sys.stdin.fileno())
515 515 #if GetConsoleMode(handle, ctypes.byref(lpMode)):
516 516 # set_console_mode = True
517 517 # if not SetConsoleMode(handle, lpMode.value &
518 518 # ~(ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT)):
519 519 # raise ctypes.WinError()
520 520
521 521 if self.mergeout:
522 522 return self.run(stdout_func = self._stdout_raw,
523 523 stdin_func = self._stdin_raw_block)
524 524 else:
525 525 return self.run(stdout_func = self._stdout_raw,
526 526 stdin_func = self._stdin_raw_block,
527 527 stderr_func = self._stderr_raw)
528 528
529 529 # Restore the previous console mode
530 530 #if set_console_mode:
531 531 # if not SetConsoleMode(handle, lpMode.value):
532 532 # raise ctypes.WinError()
533 533
534 534 def __exit__(self, exc_type, exc_value, traceback):
535 535 if self.hstdin:
536 536 CloseHandle(self.hstdin)
537 537 self.hstdin = None
538 538 if self.hstdout:
539 539 CloseHandle(self.hstdout)
540 540 self.hstdout = None
541 541 if self.hstderr:
542 542 CloseHandle(self.hstderr)
543 543 self.hstderr = None
544 544 if self.piProcInfo != None:
545 545 CloseHandle(self.piProcInfo.hProcess)
546 546 CloseHandle(self.piProcInfo.hThread)
547 547 self.piProcInfo = None
548 548
549 549
550 550 def system(cmd):
551 551 """Win32 version of os.system() that works with network shares.
552 552
553 553 Note that this implementation returns None, as meant for use in IPython.
554 554
555 555 Parameters
556 556 ----------
557 557 cmd : str
558 558 A command to be executed in the system shell.
559 559
560 560 Returns
561 561 -------
562 562 None : we explicitly do NOT return the subprocess status code, as this
563 563 utility is meant to be used extensively in IPython, where any return value
564 564 would trigger :func:`sys.displayhook` calls.
565 565 """
566 566 with AvoidUNCPath() as path:
567 567 if path is not None:
568 568 cmd = '"pushd %s &&"%s' % (path, cmd)
569 569 with Win32ShellCommandController(cmd) as scc:
570 570 scc.run()
571 571
572 572
573 573 if __name__ == "__main__":
574 574 print("Test starting!")
575 575 #system("cmd")
576 576 system("python -i")
577 577 print("Test finished!")
@@ -1,574 +1,574 b''
1 1 # encoding: utf-8
2 2 """
3 3 Utilities for path handling.
4 4 """
5 5
6 6 #-----------------------------------------------------------------------------
7 7 # Copyright (C) 2008-2011 The IPython Development Team
8 8 #
9 9 # Distributed under the terms of the BSD License. The full license is in
10 10 # the file COPYING, distributed as part of this software.
11 11 #-----------------------------------------------------------------------------
12 12
13 13 #-----------------------------------------------------------------------------
14 14 # Imports
15 15 #-----------------------------------------------------------------------------
16 16
17 17 import os
18 18 import sys
19 19 import errno
20 20 import shutil
21 21 import random
22 22 import tempfile
23 23 import warnings
24 24 from hashlib import md5
25 25 import glob
26 26
27 27 import IPython
28 28 from IPython.testing.skipdoctest import skip_doctest
29 29 from IPython.utils.process import system
30 30 from IPython.utils.importstring import import_item
31 31 from IPython.utils import py3compat
32 32 #-----------------------------------------------------------------------------
33 33 # Code
34 34 #-----------------------------------------------------------------------------
35 35
36 36 fs_encoding = sys.getfilesystemencoding()
37 37
38 38 def _get_long_path_name(path):
39 39 """Dummy no-op."""
40 40 return path
41 41
42 42 def _writable_dir(path):
43 43 """Whether `path` is a directory, to which the user has write access."""
44 44 return os.path.isdir(path) and os.access(path, os.W_OK)
45 45
46 46 if sys.platform == 'win32':
47 47 @skip_doctest
48 48 def _get_long_path_name(path):
49 49 """Get a long path name (expand ~) on Windows using ctypes.
50 50
51 51 Examples
52 52 --------
53 53
54 54 >>> get_long_path_name('c:\\docume~1')
55 55 u'c:\\\\Documents and Settings'
56 56
57 57 """
58 58 try:
59 59 import ctypes
60 60 except ImportError:
61 61 raise ImportError('you need to have ctypes installed for this to work')
62 62 _GetLongPathName = ctypes.windll.kernel32.GetLongPathNameW
63 63 _GetLongPathName.argtypes = [ctypes.c_wchar_p, ctypes.c_wchar_p,
64 64 ctypes.c_uint ]
65 65
66 66 buf = ctypes.create_unicode_buffer(260)
67 67 rv = _GetLongPathName(path, buf, 260)
68 68 if rv == 0 or rv > 260:
69 69 return path
70 70 else:
71 71 return buf.value
72 72
73 73
74 74 def get_long_path_name(path):
75 75 """Expand a path into its long form.
76 76
77 77 On Windows this expands any ~ in the paths. On other platforms, it is
78 78 a null operation.
79 79 """
80 80 return _get_long_path_name(path)
81 81
82 82
83 83 def unquote_filename(name, win32=(sys.platform=='win32')):
84 84 """ On Windows, remove leading and trailing quotes from filenames.
85 85 """
86 86 if win32:
87 87 if name.startswith(("'", '"')) and name.endswith(("'", '"')):
88 88 name = name[1:-1]
89 89 return name
90 90
91 91 def compress_user(path):
92 92 """Reverse of :func:`os.path.expanduser`
93 93 """
94 94 home = os.path.expanduser('~')
95 95 if path.startswith(home):
96 96 path = "~" + path[len(home):]
97 97 return path
98 98
99 99 def get_py_filename(name, force_win32=None):
100 100 """Return a valid python filename in the current directory.
101 101
102 102 If the given name is not a file, it adds '.py' and searches again.
103 103 Raises IOError with an informative message if the file isn't found.
104 104
105 105 On Windows, apply Windows semantics to the filename. In particular, remove
106 106 any quoting that has been applied to it. This option can be forced for
107 107 testing purposes.
108 108 """
109 109
110 110 name = os.path.expanduser(name)
111 111 if force_win32 is None:
112 112 win32 = (sys.platform == 'win32')
113 113 else:
114 114 win32 = force_win32
115 115 name = unquote_filename(name, win32=win32)
116 116 if not os.path.isfile(name) and not name.endswith('.py'):
117 117 name += '.py'
118 118 if os.path.isfile(name):
119 119 return name
120 120 else:
121 121 raise IOError('File `%r` not found.' % name)
122 122
123 123
124 124 def filefind(filename, path_dirs=None):
125 125 """Find a file by looking through a sequence of paths.
126 126
127 127 This iterates through a sequence of paths looking for a file and returns
128 128 the full, absolute path of the first occurence of the file. If no set of
129 129 path dirs is given, the filename is tested as is, after running through
130 130 :func:`expandvars` and :func:`expanduser`. Thus a simple call::
131 131
132 132 filefind('myfile.txt')
133 133
134 134 will find the file in the current working dir, but::
135 135
136 136 filefind('~/myfile.txt')
137 137
138 138 Will find the file in the users home directory. This function does not
139 139 automatically try any paths, such as the cwd or the user's home directory.
140 140
141 141 Parameters
142 142 ----------
143 143 filename : str
144 144 The filename to look for.
145 145 path_dirs : str, None or sequence of str
146 146 The sequence of paths to look for the file in. If None, the filename
147 147 need to be absolute or be in the cwd. If a string, the string is
148 148 put into a sequence and the searched. If a sequence, walk through
149 149 each element and join with ``filename``, calling :func:`expandvars`
150 150 and :func:`expanduser` before testing for existence.
151 151
152 152 Returns
153 153 -------
154 154 Raises :exc:`IOError` or returns absolute path to file.
155 155 """
156 156
157 157 # If paths are quoted, abspath gets confused, strip them...
158 158 filename = filename.strip('"').strip("'")
159 159 # If the input is an absolute path, just check it exists
160 160 if os.path.isabs(filename) and os.path.isfile(filename):
161 161 return filename
162 162
163 163 if path_dirs is None:
164 164 path_dirs = ("",)
165 165 elif isinstance(path_dirs, py3compat.string_types):
166 166 path_dirs = (path_dirs,)
167 167
168 168 for path in path_dirs:
169 if path == '.': path = os.getcwdu()
169 if path == '.': path = py3compat.getcwd()
170 170 testname = expand_path(os.path.join(path, filename))
171 171 if os.path.isfile(testname):
172 172 return os.path.abspath(testname)
173 173
174 174 raise IOError("File %r does not exist in any of the search paths: %r" %
175 175 (filename, path_dirs) )
176 176
177 177
178 178 class HomeDirError(Exception):
179 179 pass
180 180
181 181
182 182 def get_home_dir(require_writable=False):
183 183 """Return the 'home' directory, as a unicode string.
184 184
185 185 Uses os.path.expanduser('~'), and checks for writability.
186 186
187 187 See stdlib docs for how this is determined.
188 188 $HOME is first priority on *ALL* platforms.
189 189
190 190 Parameters
191 191 ----------
192 192
193 193 require_writable : bool [default: False]
194 194 if True:
195 195 guarantees the return value is a writable directory, otherwise
196 196 raises HomeDirError
197 197 if False:
198 198 The path is resolved, but it is not guaranteed to exist or be writable.
199 199 """
200 200
201 201 homedir = os.path.expanduser('~')
202 202 # Next line will make things work even when /home/ is a symlink to
203 203 # /usr/home as it is on FreeBSD, for example
204 204 homedir = os.path.realpath(homedir)
205 205
206 206 if not _writable_dir(homedir) and os.name == 'nt':
207 207 # expanduser failed, use the registry to get the 'My Documents' folder.
208 208 try:
209 209 try:
210 210 import winreg as wreg # Py 3
211 211 except ImportError:
212 212 import _winreg as wreg # Py 2
213 213 key = wreg.OpenKey(
214 214 wreg.HKEY_CURRENT_USER,
215 215 "Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders"
216 216 )
217 217 homedir = wreg.QueryValueEx(key,'Personal')[0]
218 218 key.Close()
219 219 except:
220 220 pass
221 221
222 222 if (not require_writable) or _writable_dir(homedir):
223 223 return py3compat.cast_unicode(homedir, fs_encoding)
224 224 else:
225 225 raise HomeDirError('%s is not a writable dir, '
226 226 'set $HOME environment variable to override' % homedir)
227 227
228 228 def get_xdg_dir():
229 229 """Return the XDG_CONFIG_HOME, if it is defined and exists, else None.
230 230
231 231 This is only for non-OS X posix (Linux,Unix,etc.) systems.
232 232 """
233 233
234 234 env = os.environ
235 235
236 236 if os.name == 'posix' and sys.platform != 'darwin':
237 237 # Linux, Unix, AIX, etc.
238 238 # use ~/.config if empty OR not set
239 239 xdg = env.get("XDG_CONFIG_HOME", None) or os.path.join(get_home_dir(), '.config')
240 240 if xdg and _writable_dir(xdg):
241 241 return py3compat.cast_unicode(xdg, fs_encoding)
242 242
243 243 return None
244 244
245 245
246 246 def get_xdg_cache_dir():
247 247 """Return the XDG_CACHE_HOME, if it is defined and exists, else None.
248 248
249 249 This is only for non-OS X posix (Linux,Unix,etc.) systems.
250 250 """
251 251
252 252 env = os.environ
253 253
254 254 if os.name == 'posix' and sys.platform != 'darwin':
255 255 # Linux, Unix, AIX, etc.
256 256 # use ~/.cache if empty OR not set
257 257 xdg = env.get("XDG_CACHE_HOME", None) or os.path.join(get_home_dir(), '.cache')
258 258 if xdg and _writable_dir(xdg):
259 259 return py3compat.cast_unicode(xdg, fs_encoding)
260 260
261 261 return None
262 262
263 263
264 264 def get_ipython_dir():
265 265 """Get the IPython directory for this platform and user.
266 266
267 267 This uses the logic in `get_home_dir` to find the home directory
268 268 and then adds .ipython to the end of the path.
269 269 """
270 270
271 271 env = os.environ
272 272 pjoin = os.path.join
273 273
274 274
275 275 ipdir_def = '.ipython'
276 276 xdg_def = 'ipython'
277 277
278 278 home_dir = get_home_dir()
279 279 xdg_dir = get_xdg_dir()
280 280
281 281 # import pdb; pdb.set_trace() # dbg
282 282 if 'IPYTHON_DIR' in env:
283 283 warnings.warn('The environment variable IPYTHON_DIR is deprecated. '
284 284 'Please use IPYTHONDIR instead.')
285 285 ipdir = env.get('IPYTHONDIR', env.get('IPYTHON_DIR', None))
286 286 if ipdir is None:
287 287 # not set explicitly, use XDG_CONFIG_HOME or HOME
288 288 home_ipdir = pjoin(home_dir, ipdir_def)
289 289 if xdg_dir:
290 290 # use XDG, as long as the user isn't already
291 291 # using $HOME/.ipython and *not* XDG/ipython
292 292
293 293 xdg_ipdir = pjoin(xdg_dir, xdg_def)
294 294
295 295 if _writable_dir(xdg_ipdir) or not _writable_dir(home_ipdir):
296 296 ipdir = xdg_ipdir
297 297
298 298 if ipdir is None:
299 299 # not using XDG
300 300 ipdir = home_ipdir
301 301
302 302 ipdir = os.path.normpath(os.path.expanduser(ipdir))
303 303
304 304 if os.path.exists(ipdir) and not _writable_dir(ipdir):
305 305 # ipdir exists, but is not writable
306 306 warnings.warn("IPython dir '%s' is not a writable location,"
307 307 " using a temp directory."%ipdir)
308 308 ipdir = tempfile.mkdtemp()
309 309 elif not os.path.exists(ipdir):
310 310 parent = os.path.dirname(ipdir)
311 311 if not _writable_dir(parent):
312 312 # ipdir does not exist and parent isn't writable
313 313 warnings.warn("IPython parent '%s' is not a writable location,"
314 314 " using a temp directory."%parent)
315 315 ipdir = tempfile.mkdtemp()
316 316
317 317 return py3compat.cast_unicode(ipdir, fs_encoding)
318 318
319 319
320 320 def get_ipython_cache_dir():
321 321 """Get the cache directory it is created if it does not exist."""
322 322 xdgdir = get_xdg_cache_dir()
323 323 if xdgdir is None:
324 324 return get_ipython_dir()
325 325 ipdir = os.path.join(xdgdir, "ipython")
326 326 if not os.path.exists(ipdir) and _writable_dir(xdgdir):
327 327 os.makedirs(ipdir)
328 328 elif not _writable_dir(xdgdir):
329 329 return get_ipython_dir()
330 330
331 331 return py3compat.cast_unicode(ipdir, fs_encoding)
332 332
333 333
334 334 def get_ipython_package_dir():
335 335 """Get the base directory where IPython itself is installed."""
336 336 ipdir = os.path.dirname(IPython.__file__)
337 337 return py3compat.cast_unicode(ipdir, fs_encoding)
338 338
339 339
340 340 def get_ipython_module_path(module_str):
341 341 """Find the path to an IPython module in this version of IPython.
342 342
343 343 This will always find the version of the module that is in this importable
344 344 IPython package. This will always return the path to the ``.py``
345 345 version of the module.
346 346 """
347 347 if module_str == 'IPython':
348 348 return os.path.join(get_ipython_package_dir(), '__init__.py')
349 349 mod = import_item(module_str)
350 350 the_path = mod.__file__.replace('.pyc', '.py')
351 351 the_path = the_path.replace('.pyo', '.py')
352 352 return py3compat.cast_unicode(the_path, fs_encoding)
353 353
354 354 def locate_profile(profile='default'):
355 355 """Find the path to the folder associated with a given profile.
356 356
357 357 I.e. find $IPYTHONDIR/profile_whatever.
358 358 """
359 359 from IPython.core.profiledir import ProfileDir, ProfileDirError
360 360 try:
361 361 pd = ProfileDir.find_profile_dir_by_name(get_ipython_dir(), profile)
362 362 except ProfileDirError:
363 363 # IOError makes more sense when people are expecting a path
364 364 raise IOError("Couldn't find profile %r" % profile)
365 365 return pd.location
366 366
367 367 def expand_path(s):
368 368 """Expand $VARS and ~names in a string, like a shell
369 369
370 370 :Examples:
371 371
372 372 In [2]: os.environ['FOO']='test'
373 373
374 374 In [3]: expand_path('variable FOO is $FOO')
375 375 Out[3]: 'variable FOO is test'
376 376 """
377 377 # This is a pretty subtle hack. When expand user is given a UNC path
378 378 # on Windows (\\server\share$\%username%), os.path.expandvars, removes
379 379 # the $ to get (\\server\share\%username%). I think it considered $
380 380 # alone an empty var. But, we need the $ to remains there (it indicates
381 381 # a hidden share).
382 382 if os.name=='nt':
383 383 s = s.replace('$\\', 'IPYTHON_TEMP')
384 384 s = os.path.expandvars(os.path.expanduser(s))
385 385 if os.name=='nt':
386 386 s = s.replace('IPYTHON_TEMP', '$\\')
387 387 return s
388 388
389 389
390 390 def unescape_glob(string):
391 391 """Unescape glob pattern in `string`."""
392 392 def unescape(s):
393 393 for pattern in '*[]!?':
394 394 s = s.replace(r'\{0}'.format(pattern), pattern)
395 395 return s
396 396 return '\\'.join(map(unescape, string.split('\\\\')))
397 397
398 398
399 399 def shellglob(args):
400 400 """
401 401 Do glob expansion for each element in `args` and return a flattened list.
402 402
403 403 Unmatched glob pattern will remain as-is in the returned list.
404 404
405 405 """
406 406 expanded = []
407 407 # Do not unescape backslash in Windows as it is interpreted as
408 408 # path separator:
409 409 unescape = unescape_glob if sys.platform != 'win32' else lambda x: x
410 410 for a in args:
411 411 expanded.extend(glob.glob(a) or [unescape(a)])
412 412 return expanded
413 413
414 414
415 415 def target_outdated(target,deps):
416 416 """Determine whether a target is out of date.
417 417
418 418 target_outdated(target,deps) -> 1/0
419 419
420 420 deps: list of filenames which MUST exist.
421 421 target: single filename which may or may not exist.
422 422
423 423 If target doesn't exist or is older than any file listed in deps, return
424 424 true, otherwise return false.
425 425 """
426 426 try:
427 427 target_time = os.path.getmtime(target)
428 428 except os.error:
429 429 return 1
430 430 for dep in deps:
431 431 dep_time = os.path.getmtime(dep)
432 432 if dep_time > target_time:
433 433 #print "For target",target,"Dep failed:",dep # dbg
434 434 #print "times (dep,tar):",dep_time,target_time # dbg
435 435 return 1
436 436 return 0
437 437
438 438
439 439 def target_update(target,deps,cmd):
440 440 """Update a target with a given command given a list of dependencies.
441 441
442 442 target_update(target,deps,cmd) -> runs cmd if target is outdated.
443 443
444 444 This is just a wrapper around target_outdated() which calls the given
445 445 command if target is outdated."""
446 446
447 447 if target_outdated(target,deps):
448 448 system(cmd)
449 449
450 450 def filehash(path):
451 451 """Make an MD5 hash of a file, ignoring any differences in line
452 452 ending characters."""
453 453 with open(path, "rU") as f:
454 454 return md5(py3compat.str_to_bytes(f.read())).hexdigest()
455 455
456 456 # If the config is unmodified from the default, we'll just delete it.
457 457 # These are consistent for 0.10.x, thankfully. We're not going to worry about
458 458 # older versions.
459 459 old_config_md5 = {'ipy_user_conf.py': 'fc108bedff4b9a00f91fa0a5999140d3',
460 460 'ipythonrc': '12a68954f3403eea2eec09dc8fe5a9b5'}
461 461
462 462 def check_for_old_config(ipython_dir=None):
463 463 """Check for old config files, and present a warning if they exist.
464 464
465 465 A link to the docs of the new config is included in the message.
466 466
467 467 This should mitigate confusion with the transition to the new
468 468 config system in 0.11.
469 469 """
470 470 if ipython_dir is None:
471 471 ipython_dir = get_ipython_dir()
472 472
473 473 old_configs = ['ipy_user_conf.py', 'ipythonrc', 'ipython_config.py']
474 474 warned = False
475 475 for cfg in old_configs:
476 476 f = os.path.join(ipython_dir, cfg)
477 477 if os.path.exists(f):
478 478 if filehash(f) == old_config_md5.get(cfg, ''):
479 479 os.unlink(f)
480 480 else:
481 481 warnings.warn("Found old IPython config file %r (modified by user)"%f)
482 482 warned = True
483 483
484 484 if warned:
485 485 warnings.warn("""
486 486 The IPython configuration system has changed as of 0.11, and these files will
487 487 be ignored. See http://ipython.github.com/ipython-doc/dev/config for details
488 488 of the new config system.
489 489 To start configuring IPython, do `ipython profile create`, and edit
490 490 `ipython_config.py` in <ipython_dir>/profile_default.
491 491 If you need to leave the old config files in place for an older version of
492 492 IPython and want to suppress this warning message, set
493 493 `c.InteractiveShellApp.ignore_old_config=True` in the new config.""")
494 494
495 495 def get_security_file(filename, profile='default'):
496 496 """Return the absolute path of a security file given by filename and profile
497 497
498 498 This allows users and developers to find security files without
499 499 knowledge of the IPython directory structure. The search path
500 500 will be ['.', profile.security_dir]
501 501
502 502 Parameters
503 503 ----------
504 504
505 505 filename : str
506 506 The file to be found. If it is passed as an absolute path, it will
507 507 simply be returned.
508 508 profile : str [default: 'default']
509 509 The name of the profile to search. Leaving this unspecified
510 510 The file to be found. If it is passed as an absolute path, fname will
511 511 simply be returned.
512 512
513 513 Returns
514 514 -------
515 515 Raises :exc:`IOError` if file not found or returns absolute path to file.
516 516 """
517 517 # import here, because profiledir also imports from utils.path
518 518 from IPython.core.profiledir import ProfileDir
519 519 try:
520 520 pd = ProfileDir.find_profile_dir_by_name(get_ipython_dir(), profile)
521 521 except Exception:
522 522 # will raise ProfileDirError if no such profile
523 523 raise IOError("Profile %r not found")
524 524 return filefind(filename, ['.', pd.security_dir])
525 525
526 526
527 527 ENOLINK = 1998
528 528
529 529 def link(src, dst):
530 530 """Hard links ``src`` to ``dst``, returning 0 or errno.
531 531
532 532 Note that the special errno ``ENOLINK`` will be returned if ``os.link`` isn't
533 533 supported by the operating system.
534 534 """
535 535
536 536 if not hasattr(os, "link"):
537 537 return ENOLINK
538 538 link_errno = 0
539 539 try:
540 540 os.link(src, dst)
541 541 except OSError as e:
542 542 link_errno = e.errno
543 543 return link_errno
544 544
545 545
546 546 def link_or_copy(src, dst):
547 547 """Attempts to hardlink ``src`` to ``dst``, copying if the link fails.
548 548
549 549 Attempts to maintain the semantics of ``shutil.copy``.
550 550
551 551 Because ``os.link`` does not overwrite files, a unique temporary file
552 552 will be used if the target already exists, then that file will be moved
553 553 into place.
554 554 """
555 555
556 556 if os.path.isdir(dst):
557 557 dst = os.path.join(dst, os.path.basename(src))
558 558
559 559 link_errno = link(src, dst)
560 560 if link_errno == errno.EEXIST:
561 561 new_dst = dst + "-temp-%04X" %(random.randint(1, 16**4), )
562 562 try:
563 563 link_or_copy(src, new_dst)
564 564 except:
565 565 try:
566 566 os.remove(new_dst)
567 567 except OSError:
568 568 pass
569 569 raise
570 570 os.rename(new_dst, dst)
571 571 elif link_errno != 0:
572 572 # Either link isn't supported, or the filesystem doesn't support
573 573 # linking, or 'src' and 'dst' are on different filesystems.
574 574 shutil.copy(src, dst)
@@ -1,122 +1,123 b''
1 1 # encoding: utf-8
2 2 """
3 3 Utilities for working with external processes.
4 4 """
5 5
6 6 #-----------------------------------------------------------------------------
7 7 # Copyright (C) 2008-2011 The IPython Development Team
8 8 #
9 9 # Distributed under the terms of the BSD License. The full license is in
10 10 # the file COPYING, distributed as part of this software.
11 11 #-----------------------------------------------------------------------------
12 12
13 13 #-----------------------------------------------------------------------------
14 14 # Imports
15 15 #-----------------------------------------------------------------------------
16 16 from __future__ import print_function
17 17
18 18 # Stdlib
19 19 import os
20 20 import sys
21 21 import shlex
22 22
23 23 # Our own
24 24 if sys.platform == 'win32':
25 25 from ._process_win32 import _find_cmd, system, getoutput, AvoidUNCPath, arg_split
26 26 else:
27 27 from ._process_posix import _find_cmd, system, getoutput, arg_split
28 28
29 29
30 30 from ._process_common import getoutputerror, get_output_error_code
31 from . import py3compat
31 32
32 33 #-----------------------------------------------------------------------------
33 34 # Code
34 35 #-----------------------------------------------------------------------------
35 36
36 37
37 38 class FindCmdError(Exception):
38 39 pass
39 40
40 41
41 42 def find_cmd(cmd):
42 43 """Find absolute path to executable cmd in a cross platform manner.
43 44
44 45 This function tries to determine the full path to a command line program
45 46 using `which` on Unix/Linux/OS X and `win32api` on Windows. Most of the
46 47 time it will use the version that is first on the users `PATH`.
47 48
48 49 Warning, don't use this to find IPython command line programs as there
49 50 is a risk you will find the wrong one. Instead find those using the
50 51 following code and looking for the application itself::
51 52
52 53 from IPython.utils.path import get_ipython_module_path
53 54 from IPython.utils.process import pycmd2argv
54 55 argv = pycmd2argv(get_ipython_module_path('IPython.terminal.ipapp'))
55 56
56 57 Parameters
57 58 ----------
58 59 cmd : str
59 60 The command line program to look for.
60 61 """
61 62 try:
62 63 path = _find_cmd(cmd).rstrip()
63 64 except OSError:
64 65 raise FindCmdError('command could not be found: %s' % cmd)
65 66 # which returns empty if not found
66 67 if path == '':
67 68 raise FindCmdError('command could not be found: %s' % cmd)
68 69 return os.path.abspath(path)
69 70
70 71
71 72 def is_cmd_found(cmd):
72 73 """Check whether executable `cmd` exists or not and return a bool."""
73 74 try:
74 75 find_cmd(cmd)
75 76 return True
76 77 except FindCmdError:
77 78 return False
78 79
79 80
80 81 def pycmd2argv(cmd):
81 82 r"""Take the path of a python command and return a list (argv-style).
82 83
83 84 This only works on Python based command line programs and will find the
84 85 location of the ``python`` executable using ``sys.executable`` to make
85 86 sure the right version is used.
86 87
87 88 For a given path ``cmd``, this returns [cmd] if cmd's extension is .exe,
88 89 .com or .bat, and [, cmd] otherwise.
89 90
90 91 Parameters
91 92 ----------
92 93 cmd : string
93 94 The path of the command.
94 95
95 96 Returns
96 97 -------
97 98 argv-style list.
98 99 """
99 100 ext = os.path.splitext(cmd)[1]
100 101 if ext in ['.exe', '.com', '.bat']:
101 102 return [cmd]
102 103 else:
103 104 return [sys.executable, cmd]
104 105
105 106
106 107 def abbrev_cwd():
107 108 """ Return abbreviated version of cwd, e.g. d:mydir """
108 cwd = os.getcwdu().replace('\\','/')
109 cwd = py3compat.getcwd().replace('\\','/')
109 110 drivepart = ''
110 111 tail = cwd
111 112 if sys.platform == 'win32':
112 113 if len(cwd) < 4:
113 114 return cwd
114 115 drivepart,tail = os.path.splitdrive(cwd)
115 116
116 117
117 118 parts = tail.split('/')
118 119 if len(parts) > 2:
119 120 tail = '/'.join(parts[-2:])
120 121
121 122 return (drivepart + (
122 123 cwd == '/' and '/' or tail))
@@ -1,239 +1,242 b''
1 1 # coding: utf-8
2 2 """Compatibility tricks for Python 3. Mainly to do with unicode."""
3 3 import functools
4 import os
4 5 import sys
5 6 import re
6 7 import types
7 8
8 9 from .encoding import DEFAULT_ENCODING
9 10
10 11 orig_open = open
11 12
12 13 def no_code(x, encoding=None):
13 14 return x
14 15
15 16 def decode(s, encoding=None):
16 17 encoding = encoding or DEFAULT_ENCODING
17 18 return s.decode(encoding, "replace")
18 19
19 20 def encode(u, encoding=None):
20 21 encoding = encoding or DEFAULT_ENCODING
21 22 return u.encode(encoding, "replace")
22 23
23 24
24 25 def cast_unicode(s, encoding=None):
25 26 if isinstance(s, bytes):
26 27 return decode(s, encoding)
27 28 return s
28 29
29 30 def cast_bytes(s, encoding=None):
30 31 if not isinstance(s, bytes):
31 32 return encode(s, encoding)
32 33 return s
33 34
34 35 def _modify_str_or_docstring(str_change_func):
35 36 @functools.wraps(str_change_func)
36 37 def wrapper(func_or_str):
37 38 if isinstance(func_or_str, string_types):
38 39 func = None
39 40 doc = func_or_str
40 41 else:
41 42 func = func_or_str
42 43 doc = func.__doc__
43 44
44 45 doc = str_change_func(doc)
45 46
46 47 if func:
47 48 func.__doc__ = doc
48 49 return func
49 50 return doc
50 51 return wrapper
51 52
52 53 def safe_unicode(e):
53 54 """unicode(e) with various fallbacks. Used for exceptions, which may not be
54 55 safe to call unicode() on.
55 56 """
56 57 try:
57 58 return unicode_type(e)
58 59 except UnicodeError:
59 60 pass
60 61
61 62 try:
62 63 return str_to_unicode(str(e))
63 64 except UnicodeError:
64 65 pass
65 66
66 67 try:
67 68 return str_to_unicode(repr(e))
68 69 except UnicodeError:
69 70 pass
70 71
71 72 return u'Unrecoverably corrupt evalue'
72 73
73 74 if sys.version_info[0] >= 3:
74 75 PY3 = True
75 76
76 77 input = input
77 78 builtin_mod_name = "builtins"
78 79 import builtins as builtin_mod
79 80
80 81 str_to_unicode = no_code
81 82 unicode_to_str = no_code
82 83 str_to_bytes = encode
83 84 bytes_to_str = decode
84 85 cast_bytes_py2 = no_code
85 86
86 87 string_types = (str,)
87 88 unicode_type = str
88 89
89 90 def isidentifier(s, dotted=False):
90 91 if dotted:
91 92 return all(isidentifier(a) for a in s.split("."))
92 93 return s.isidentifier()
93 94
94 95 open = orig_open
95 96 xrange = range
96 97 def iteritems(d): return iter(d.items())
97 98 def itervalues(d): return iter(d.values())
99 getcwd = os.getcwd
98 100
99 101 MethodType = types.MethodType
100 102
101 103 def execfile(fname, glob, loc=None):
102 104 loc = loc if (loc is not None) else glob
103 105 with open(fname, 'rb') as f:
104 106 exec(compile(f.read(), fname, 'exec'), glob, loc)
105 107
106 108 # Refactor print statements in doctests.
107 109 _print_statement_re = re.compile(r"\bprint (?P<expr>.*)$", re.MULTILINE)
108 110 def _print_statement_sub(match):
109 111 expr = match.groups('expr')
110 112 return "print(%s)" % expr
111 113
112 114 @_modify_str_or_docstring
113 115 def doctest_refactor_print(doc):
114 116 """Refactor 'print x' statements in a doctest to print(x) style. 2to3
115 117 unfortunately doesn't pick up on our doctests.
116 118
117 119 Can accept a string or a function, so it can be used as a decorator."""
118 120 return _print_statement_re.sub(_print_statement_sub, doc)
119 121
120 122 # Abstract u'abc' syntax:
121 123 @_modify_str_or_docstring
122 124 def u_format(s):
123 125 """"{u}'abc'" --> "'abc'" (Python 3)
124 126
125 127 Accepts a string or a function, so it can be used as a decorator."""
126 128 return s.format(u='')
127 129
128 130 else:
129 131 PY3 = False
130 132
131 133 input = raw_input
132 134 builtin_mod_name = "__builtin__"
133 135 import __builtin__ as builtin_mod
134 136
135 137 str_to_unicode = decode
136 138 unicode_to_str = encode
137 139 str_to_bytes = no_code
138 140 bytes_to_str = no_code
139 141 cast_bytes_py2 = cast_bytes
140 142
141 143 string_types = (str, unicode)
142 144 unicode_type = unicode
143 145
144 146 import re
145 147 _name_re = re.compile(r"[a-zA-Z_][a-zA-Z0-9_]*$")
146 148 def isidentifier(s, dotted=False):
147 149 if dotted:
148 150 return all(isidentifier(a) for a in s.split("."))
149 151 return bool(_name_re.match(s))
150 152
151 153 class open(object):
152 154 """Wrapper providing key part of Python 3 open() interface."""
153 155 def __init__(self, fname, mode="r", encoding="utf-8"):
154 156 self.f = orig_open(fname, mode)
155 157 self.enc = encoding
156 158
157 159 def write(self, s):
158 160 return self.f.write(s.encode(self.enc))
159 161
160 162 def read(self, size=-1):
161 163 return self.f.read(size).decode(self.enc)
162 164
163 165 def close(self):
164 166 return self.f.close()
165 167
166 168 def __enter__(self):
167 169 return self
168 170
169 171 def __exit__(self, etype, value, traceback):
170 172 self.f.close()
171 173
172 174 xrange = xrange
173 175 def iteritems(d): return d.iteritems()
174 176 def itervalues(d): return d.itervalues()
177 getcwd = os.getcwdu
175 178
176 179 def MethodType(func, instance):
177 180 return types.MethodType(func, instance, type(instance))
178 181
179 182 # don't override system execfile on 2.x:
180 183 execfile = execfile
181 184
182 185 def doctest_refactor_print(func_or_str):
183 186 return func_or_str
184 187
185 188
186 189 # Abstract u'abc' syntax:
187 190 @_modify_str_or_docstring
188 191 def u_format(s):
189 192 """"{u}'abc'" --> "u'abc'" (Python 2)
190 193
191 194 Accepts a string or a function, so it can be used as a decorator."""
192 195 return s.format(u='u')
193 196
194 197 if sys.platform == 'win32':
195 198 def execfile(fname, glob=None, loc=None):
196 199 loc = loc if (loc is not None) else glob
197 200 # The rstrip() is necessary b/c trailing whitespace in files will
198 201 # cause an IndentationError in Python 2.6 (this was fixed in 2.7,
199 202 # but we still support 2.6). See issue 1027.
200 203 scripttext = builtin_mod.open(fname).read().rstrip() + '\n'
201 204 # compile converts unicode filename to str assuming
202 205 # ascii. Let's do the conversion before calling compile
203 206 if isinstance(fname, unicode):
204 207 filename = unicode_to_str(fname)
205 208 else:
206 209 filename = fname
207 210 exec(compile(scripttext, filename, 'exec'), glob, loc)
208 211 else:
209 212 def execfile(fname, *where):
210 213 if isinstance(fname, unicode):
211 214 filename = fname.encode(sys.getfilesystemencoding())
212 215 else:
213 216 filename = fname
214 217 builtin_mod.execfile(filename, *where)
215 218
216 219 # Parts below taken from six:
217 220 # Copyright (c) 2010-2013 Benjamin Peterson
218 221 #
219 222 # Permission is hereby granted, free of charge, to any person obtaining a copy
220 223 # of this software and associated documentation files (the "Software"), to deal
221 224 # in the Software without restriction, including without limitation the rights
222 225 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
223 226 # copies of the Software, and to permit persons to whom the Software is
224 227 # furnished to do so, subject to the following conditions:
225 228 #
226 229 # The above copyright notice and this permission notice shall be included in all
227 230 # copies or substantial portions of the Software.
228 231 #
229 232 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
230 233 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
231 234 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
232 235 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
233 236 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
234 237 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
235 238 # SOFTWARE.
236 239
237 240 def with_metaclass(meta, *bases):
238 241 """Create a base class with a metaclass."""
239 242 return meta("NewBase", bases, {})
@@ -1,162 +1,164 b''
1 1 # encoding: utf-8
2 2 """
3 3 Utilities for working with terminals.
4 4
5 5 Authors:
6 6
7 7 * Brian E. Granger
8 8 * Fernando Perez
9 9 * Alexander Belchenko (e-mail: bialix AT ukr.net)
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 import os
24 24 import struct
25 25 import sys
26 26 import warnings
27 27
28 from . import py3compat
29
28 30 #-----------------------------------------------------------------------------
29 31 # Code
30 32 #-----------------------------------------------------------------------------
31 33
32 34 # This variable is part of the expected API of the module:
33 35 ignore_termtitle = True
34 36
35 37
36 38 def _term_clear():
37 39 pass
38 40
39 41
40 42 if os.name == 'posix':
41 43 def _term_clear():
42 44 os.system('clear')
43 45
44 46
45 47 if sys.platform == 'win32':
46 48 def _term_clear():
47 49 os.system('cls')
48 50
49 51
50 52 def term_clear():
51 53 _term_clear()
52 54
53 55
54 56 def toggle_set_term_title(val):
55 57 """Control whether set_term_title is active or not.
56 58
57 59 set_term_title() allows writing to the console titlebar. In embedded
58 60 widgets this can cause problems, so this call can be used to toggle it on
59 61 or off as needed.
60 62
61 63 The default state of the module is for the function to be disabled.
62 64
63 65 Parameters
64 66 ----------
65 67 val : bool
66 68 If True, set_term_title() actually writes to the terminal (using the
67 69 appropriate platform-specific module). If False, it is a no-op.
68 70 """
69 71 global ignore_termtitle
70 72 ignore_termtitle = not(val)
71 73
72 74
73 75 def _set_term_title(*args,**kw):
74 76 """Dummy no-op."""
75 77 pass
76 78
77 79
78 80 def _set_term_title_xterm(title):
79 81 """ Change virtual terminal title in xterm-workalikes """
80 82 sys.stdout.write('\033]0;%s\007' % title)
81 83
82 84 if os.name == 'posix':
83 85 TERM = os.environ.get('TERM','')
84 86 if TERM.startswith('xterm'):
85 87 _set_term_title = _set_term_title_xterm
86 88
87 89
88 90 if sys.platform == 'win32':
89 91 try:
90 92 import ctypes
91 93
92 94 SetConsoleTitleW = ctypes.windll.kernel32.SetConsoleTitleW
93 95 SetConsoleTitleW.argtypes = [ctypes.c_wchar_p]
94 96
95 97 def _set_term_title(title):
96 98 """Set terminal title using ctypes to access the Win32 APIs."""
97 99 SetConsoleTitleW(title)
98 100 except ImportError:
99 101 def _set_term_title(title):
100 102 """Set terminal title using the 'title' command."""
101 103 global ignore_termtitle
102 104
103 105 try:
104 106 # Cannot be on network share when issuing system commands
105 curr = os.getcwdu()
107 curr = py3compat.getcwd()
106 108 os.chdir("C:")
107 109 ret = os.system("title " + title)
108 110 finally:
109 111 os.chdir(curr)
110 112 if ret:
111 113 # non-zero return code signals error, don't try again
112 114 ignore_termtitle = True
113 115
114 116
115 117 def set_term_title(title):
116 118 """Set terminal title using the necessary platform-dependent calls."""
117 119 if ignore_termtitle:
118 120 return
119 121 _set_term_title(title)
120 122
121 123
122 124 def freeze_term_title():
123 125 warnings.warn("This function is deprecated, use toggle_set_term_title()")
124 126 global ignore_termtitle
125 127 ignore_termtitle = True
126 128
127 129
128 130 def get_terminal_size(defaultx=80, defaulty=25):
129 131 return defaultx, defaulty
130 132
131 133
132 134 if sys.platform == 'win32':
133 135 def get_terminal_size(defaultx=80, defaulty=25):
134 136 """Return size of current terminal console.
135 137
136 138 This function try to determine actual size of current working
137 139 console window and return tuple (sizex, sizey) if success,
138 140 or default size (defaultx, defaulty) otherwise.
139 141
140 142 Dependencies: ctypes should be installed.
141 143
142 144 Author: Alexander Belchenko (e-mail: bialix AT ukr.net)
143 145 """
144 146 try:
145 147 import ctypes
146 148 except ImportError:
147 149 return defaultx, defaulty
148 150
149 151 h = ctypes.windll.kernel32.GetStdHandle(-11)
150 152 csbi = ctypes.create_string_buffer(22)
151 153 res = ctypes.windll.kernel32.GetConsoleScreenBufferInfo(h, csbi)
152 154
153 155 if res:
154 156 (bufx, bufy, curx, cury, wattr,
155 157 left, top, right, bottom, maxx, maxy) = struct.unpack(
156 158 "hhhhHhhhhhh", csbi.raw)
157 159 sizex = right - left + 1
158 160 sizey = bottom - top + 1
159 161 return (sizex, sizey)
160 162 else:
161 163 return (defaultx, defaulty)
162 164
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
General Comments 0
You need to be logged in to leave comments. Login now