##// END OF EJS Templates
Convert print statements to print function calls...
Thomas Kluyver -
Show More

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

@@ -1,580 +1,581 b''
1 1 # encoding: utf-8
2 2 """
3 3 A base class for a configurable application.
4 4
5 5 Authors:
6 6
7 7 * Brian Granger
8 8 * Min RK
9 9 """
10 from __future__ import print_function
10 11
11 12 #-----------------------------------------------------------------------------
12 13 # Copyright (C) 2008-2011 The IPython Development Team
13 14 #
14 15 # Distributed under the terms of the BSD License. The full license is in
15 16 # the file COPYING, distributed as part of this software.
16 17 #-----------------------------------------------------------------------------
17 18
18 19 #-----------------------------------------------------------------------------
19 20 # Imports
20 21 #-----------------------------------------------------------------------------
21 22
22 23 import logging
23 24 import os
24 25 import re
25 26 import sys
26 27 from copy import deepcopy
27 28 from collections import defaultdict
28 29
29 30 from IPython.external.decorator import decorator
30 31
31 32 from IPython.config.configurable import SingletonConfigurable
32 33 from IPython.config.loader import (
33 34 KVArgParseConfigLoader, PyFileConfigLoader, Config, ArgumentError, ConfigFileNotFound,
34 35 )
35 36
36 37 from IPython.utils.traitlets import (
37 38 Unicode, List, Enum, Dict, Instance, TraitError
38 39 )
39 40 from IPython.utils.importstring import import_item
40 41 from IPython.utils.text import indent, wrap_paragraphs, dedent
41 42 from IPython.utils import py3compat
42 43
43 44 #-----------------------------------------------------------------------------
44 45 # function for re-wrapping a helpstring
45 46 #-----------------------------------------------------------------------------
46 47
47 48 #-----------------------------------------------------------------------------
48 49 # Descriptions for the various sections
49 50 #-----------------------------------------------------------------------------
50 51
51 52 # merge flags&aliases into options
52 53 option_description = """
53 54 Arguments that take values are actually convenience aliases to full
54 55 Configurables, whose aliases are listed on the help line. For more information
55 56 on full configurables, see '--help-all'.
56 57 """.strip() # trim newlines of front and back
57 58
58 59 keyvalue_description = """
59 60 Parameters are set from command-line arguments of the form:
60 61 `--Class.trait=value`.
61 62 This line is evaluated in Python, so simple expressions are allowed, e.g.::
62 63 `--C.a='range(3)'` For setting C.a=[0,1,2].
63 64 """.strip() # trim newlines of front and back
64 65
65 66 # sys.argv can be missing, for example when python is embedded. See the docs
66 67 # for details: http://docs.python.org/2/c-api/intro.html#embedding-python
67 68 if not hasattr(sys, "argv"):
68 69 sys.argv = [""]
69 70
70 71 subcommand_description = """
71 72 Subcommands are launched as `{app} cmd [args]`. For information on using
72 73 subcommand 'cmd', do: `{app} cmd -h`.
73 74 """.strip().format(app=os.path.basename(sys.argv[0]))
74 75 # get running program name
75 76
76 77 #-----------------------------------------------------------------------------
77 78 # Application class
78 79 #-----------------------------------------------------------------------------
79 80
80 81 @decorator
81 82 def catch_config_error(method, app, *args, **kwargs):
82 83 """Method decorator for catching invalid config (Trait/ArgumentErrors) during init.
83 84
84 85 On a TraitError (generally caused by bad config), this will print the trait's
85 86 message, and exit the app.
86 87
87 88 For use on init methods, to prevent invoking excepthook on invalid input.
88 89 """
89 90 try:
90 91 return method(app, *args, **kwargs)
91 92 except (TraitError, ArgumentError) as e:
92 93 app.print_help()
93 94 app.log.fatal("Bad config encountered during initialization:")
94 95 app.log.fatal(str(e))
95 96 app.log.debug("Config at the time: %s", app.config)
96 97 app.exit(1)
97 98
98 99
99 100 class ApplicationError(Exception):
100 101 pass
101 102
102 103 class LevelFormatter(logging.Formatter):
103 104 """Formatter with additional `highlevel` record
104 105
105 106 This field is empty if log level is less than highlevel_limit,
106 107 otherwise it is formatted with self.highlevel_format.
107 108
108 109 Useful for adding 'WARNING' to warning messages,
109 110 without adding 'INFO' to info, etc.
110 111 """
111 112 highlevel_limit = logging.WARN
112 113 highlevel_format = " %(levelname)s |"
113 114
114 115 def format(self, record):
115 116 if record.levelno >= self.highlevel_limit:
116 117 record.highlevel = self.highlevel_format % record.__dict__
117 118 else:
118 119 record.highlevel = ""
119 120 return super(LevelFormatter, self).format(record)
120 121
121 122
122 123 class Application(SingletonConfigurable):
123 124 """A singleton application with full configuration support."""
124 125
125 126 # The name of the application, will usually match the name of the command
126 127 # line application
127 128 name = Unicode(u'application')
128 129
129 130 # The description of the application that is printed at the beginning
130 131 # of the help.
131 132 description = Unicode(u'This is an application.')
132 133 # default section descriptions
133 134 option_description = Unicode(option_description)
134 135 keyvalue_description = Unicode(keyvalue_description)
135 136 subcommand_description = Unicode(subcommand_description)
136 137
137 138 # The usage and example string that goes at the end of the help string.
138 139 examples = Unicode()
139 140
140 141 # A sequence of Configurable subclasses whose config=True attributes will
141 142 # be exposed at the command line.
142 143 classes = List([])
143 144
144 145 # The version string of this application.
145 146 version = Unicode(u'0.0')
146 147
147 148 # the argv used to initialize the application
148 149 argv = List()
149 150
150 151 # The log level for the application
151 152 log_level = Enum((0,10,20,30,40,50,'DEBUG','INFO','WARN','ERROR','CRITICAL'),
152 153 default_value=logging.WARN,
153 154 config=True,
154 155 help="Set the log level by value or name.")
155 156 def _log_level_changed(self, name, old, new):
156 157 """Adjust the log level when log_level is set."""
157 158 if isinstance(new, basestring):
158 159 new = getattr(logging, new)
159 160 self.log_level = new
160 161 self.log.setLevel(new)
161 162
162 163 log_datefmt = Unicode("%Y-%m-%d %H:%M:%S", config=True,
163 164 help="The date format used by logging formatters for %(asctime)s"
164 165 )
165 166 def _log_datefmt_changed(self, name, old, new):
166 167 self._log_format_changed()
167 168
168 169 log_format = Unicode("[%(name)s]%(highlevel)s %(message)s", config=True,
169 170 help="The Logging format template",
170 171 )
171 172 def _log_format_changed(self, name, old, new):
172 173 """Change the log formatter when log_format is set."""
173 174 _log_handler = self.log.handlers[0]
174 175 _log_formatter = LevelFormatter(new, datefmt=self.log_datefmt)
175 176 _log_handler.setFormatter(_log_formatter)
176 177
177 178 log = Instance(logging.Logger)
178 179 def _log_default(self):
179 180 """Start logging for this application.
180 181
181 182 The default is to log to stderr using a StreamHandler, if no default
182 183 handler already exists. The log level starts at logging.WARN, but this
183 184 can be adjusted by setting the ``log_level`` attribute.
184 185 """
185 186 log = logging.getLogger(self.__class__.__name__)
186 187 log.setLevel(self.log_level)
187 188 log.propagate = False
188 189 _log = log # copied from Logger.hasHandlers() (new in Python 3.2)
189 190 while _log:
190 191 if _log.handlers:
191 192 return log
192 193 if not _log.propagate:
193 194 break
194 195 else:
195 196 _log = _log.parent
196 197 if sys.executable.endswith('pythonw.exe'):
197 198 # this should really go to a file, but file-logging is only
198 199 # hooked up in parallel applications
199 200 _log_handler = logging.StreamHandler(open(os.devnull, 'w'))
200 201 else:
201 202 _log_handler = logging.StreamHandler()
202 203 _log_formatter = LevelFormatter(self.log_format, datefmt=self.log_datefmt)
203 204 _log_handler.setFormatter(_log_formatter)
204 205 log.addHandler(_log_handler)
205 206 return log
206 207
207 208 # the alias map for configurables
208 209 aliases = Dict({'log-level' : 'Application.log_level'})
209 210
210 211 # flags for loading Configurables or store_const style flags
211 212 # flags are loaded from this dict by '--key' flags
212 213 # this must be a dict of two-tuples, the first element being the Config/dict
213 214 # and the second being the help string for the flag
214 215 flags = Dict()
215 216 def _flags_changed(self, name, old, new):
216 217 """ensure flags dict is valid"""
217 218 for key,value in new.iteritems():
218 219 assert len(value) == 2, "Bad flag: %r:%s"%(key,value)
219 220 assert isinstance(value[0], (dict, Config)), "Bad flag: %r:%s"%(key,value)
220 221 assert isinstance(value[1], basestring), "Bad flag: %r:%s"%(key,value)
221 222
222 223
223 224 # subcommands for launching other applications
224 225 # if this is not empty, this will be a parent Application
225 226 # this must be a dict of two-tuples,
226 227 # the first element being the application class/import string
227 228 # and the second being the help string for the subcommand
228 229 subcommands = Dict()
229 230 # parse_command_line will initialize a subapp, if requested
230 231 subapp = Instance('IPython.config.application.Application', allow_none=True)
231 232
232 233 # extra command-line arguments that don't set config values
233 234 extra_args = List(Unicode)
234 235
235 236
236 237 def __init__(self, **kwargs):
237 238 SingletonConfigurable.__init__(self, **kwargs)
238 239 # Ensure my class is in self.classes, so my attributes appear in command line
239 240 # options and config files.
240 241 if self.__class__ not in self.classes:
241 242 self.classes.insert(0, self.__class__)
242 243
243 244 def _config_changed(self, name, old, new):
244 245 SingletonConfigurable._config_changed(self, name, old, new)
245 246 self.log.debug('Config changed:')
246 247 self.log.debug(repr(new))
247 248
248 249 @catch_config_error
249 250 def initialize(self, argv=None):
250 251 """Do the basic steps to configure me.
251 252
252 253 Override in subclasses.
253 254 """
254 255 self.parse_command_line(argv)
255 256
256 257
257 258 def start(self):
258 259 """Start the app mainloop.
259 260
260 261 Override in subclasses.
261 262 """
262 263 if self.subapp is not None:
263 264 return self.subapp.start()
264 265
265 266 def print_alias_help(self):
266 267 """Print the alias part of the help."""
267 268 if not self.aliases:
268 269 return
269 270
270 271 lines = []
271 272 classdict = {}
272 273 for cls in self.classes:
273 274 # include all parents (up to, but excluding Configurable) in available names
274 275 for c in cls.mro()[:-3]:
275 276 classdict[c.__name__] = c
276 277
277 278 for alias, longname in self.aliases.iteritems():
278 279 classname, traitname = longname.split('.',1)
279 280 cls = classdict[classname]
280 281
281 282 trait = cls.class_traits(config=True)[traitname]
282 283 help = cls.class_get_trait_help(trait).splitlines()
283 284 # reformat first line
284 285 help[0] = help[0].replace(longname, alias) + ' (%s)'%longname
285 286 if len(alias) == 1:
286 287 help[0] = help[0].replace('--%s='%alias, '-%s '%alias)
287 288 lines.extend(help)
288 289 # lines.append('')
289 print os.linesep.join(lines)
290 print(os.linesep.join(lines))
290 291
291 292 def print_flag_help(self):
292 293 """Print the flag part of the help."""
293 294 if not self.flags:
294 295 return
295 296
296 297 lines = []
297 298 for m, (cfg,help) in self.flags.iteritems():
298 299 prefix = '--' if len(m) > 1 else '-'
299 300 lines.append(prefix+m)
300 301 lines.append(indent(dedent(help.strip())))
301 302 # lines.append('')
302 print os.linesep.join(lines)
303 print(os.linesep.join(lines))
303 304
304 305 def print_options(self):
305 306 if not self.flags and not self.aliases:
306 307 return
307 308 lines = ['Options']
308 309 lines.append('-'*len(lines[0]))
309 310 lines.append('')
310 311 for p in wrap_paragraphs(self.option_description):
311 312 lines.append(p)
312 313 lines.append('')
313 print os.linesep.join(lines)
314 print(os.linesep.join(lines))
314 315 self.print_flag_help()
315 316 self.print_alias_help()
316 print
317 print()
317 318
318 319 def print_subcommands(self):
319 320 """Print the subcommand part of the help."""
320 321 if not self.subcommands:
321 322 return
322 323
323 324 lines = ["Subcommands"]
324 325 lines.append('-'*len(lines[0]))
325 326 lines.append('')
326 327 for p in wrap_paragraphs(self.subcommand_description):
327 328 lines.append(p)
328 329 lines.append('')
329 330 for subc, (cls, help) in self.subcommands.iteritems():
330 331 lines.append(subc)
331 332 if help:
332 333 lines.append(indent(dedent(help.strip())))
333 334 lines.append('')
334 print os.linesep.join(lines)
335 print(os.linesep.join(lines))
335 336
336 337 def print_help(self, classes=False):
337 338 """Print the help for each Configurable class in self.classes.
338 339
339 340 If classes=False (the default), only flags and aliases are printed.
340 341 """
341 342 self.print_description()
342 343 self.print_subcommands()
343 344 self.print_options()
344 345
345 346 if classes:
346 347 if self.classes:
347 print "Class parameters"
348 print "----------------"
349 print
348 print("Class parameters")
349 print("----------------")
350 print()
350 351 for p in wrap_paragraphs(self.keyvalue_description):
351 print p
352 print
352 print(p)
353 print()
353 354
354 355 for cls in self.classes:
355 356 cls.class_print_help()
356 print
357 print()
357 358 else:
358 print "To see all available configurables, use `--help-all`"
359 print
359 print("To see all available configurables, use `--help-all`")
360 print()
360 361
361 362 self.print_examples()
362 363
363 364
364 365 def print_description(self):
365 366 """Print the application description."""
366 367 for p in wrap_paragraphs(self.description):
367 print p
368 print
368 print(p)
369 print()
369 370
370 371 def print_examples(self):
371 372 """Print usage and examples.
372 373
373 374 This usage string goes at the end of the command line help string
374 375 and should contain examples of the application's usage.
375 376 """
376 377 if self.examples:
377 print "Examples"
378 print "--------"
379 print
380 print indent(dedent(self.examples.strip()))
381 print
378 print("Examples")
379 print("--------")
380 print()
381 print(indent(dedent(self.examples.strip())))
382 print()
382 383
383 384 def print_version(self):
384 385 """Print the version string."""
385 print self.version
386 print(self.version)
386 387
387 388 def update_config(self, config):
388 389 """Fire the traits events when the config is updated."""
389 390 # Save a copy of the current config.
390 391 newconfig = deepcopy(self.config)
391 392 # Merge the new config into the current one.
392 393 newconfig.merge(config)
393 394 # Save the combined config as self.config, which triggers the traits
394 395 # events.
395 396 self.config = newconfig
396 397
397 398 @catch_config_error
398 399 def initialize_subcommand(self, subc, argv=None):
399 400 """Initialize a subcommand with argv."""
400 401 subapp,help = self.subcommands.get(subc)
401 402
402 403 if isinstance(subapp, basestring):
403 404 subapp = import_item(subapp)
404 405
405 406 # clear existing instances
406 407 self.__class__.clear_instance()
407 408 # instantiate
408 409 self.subapp = subapp.instance(config=self.config)
409 410 # and initialize subapp
410 411 self.subapp.initialize(argv)
411 412
412 413 def flatten_flags(self):
413 414 """flatten flags and aliases, so cl-args override as expected.
414 415
415 416 This prevents issues such as an alias pointing to InteractiveShell,
416 417 but a config file setting the same trait in TerminalInteraciveShell
417 418 getting inappropriate priority over the command-line arg.
418 419
419 420 Only aliases with exactly one descendent in the class list
420 421 will be promoted.
421 422
422 423 """
423 424 # build a tree of classes in our list that inherit from a particular
424 425 # it will be a dict by parent classname of classes in our list
425 426 # that are descendents
426 427 mro_tree = defaultdict(list)
427 428 for cls in self.classes:
428 429 clsname = cls.__name__
429 430 for parent in cls.mro()[1:-3]:
430 431 # exclude cls itself and Configurable,HasTraits,object
431 432 mro_tree[parent.__name__].append(clsname)
432 433 # flatten aliases, which have the form:
433 434 # { 'alias' : 'Class.trait' }
434 435 aliases = {}
435 436 for alias, cls_trait in self.aliases.iteritems():
436 437 cls,trait = cls_trait.split('.',1)
437 438 children = mro_tree[cls]
438 439 if len(children) == 1:
439 440 # exactly one descendent, promote alias
440 441 cls = children[0]
441 442 aliases[alias] = '.'.join([cls,trait])
442 443
443 444 # flatten flags, which are of the form:
444 445 # { 'key' : ({'Cls' : {'trait' : value}}, 'help')}
445 446 flags = {}
446 447 for key, (flagdict, help) in self.flags.iteritems():
447 448 newflag = {}
448 449 for cls, subdict in flagdict.iteritems():
449 450 children = mro_tree[cls]
450 451 # exactly one descendent, promote flag section
451 452 if len(children) == 1:
452 453 cls = children[0]
453 454 newflag[cls] = subdict
454 455 flags[key] = (newflag, help)
455 456 return flags, aliases
456 457
457 458 @catch_config_error
458 459 def parse_command_line(self, argv=None):
459 460 """Parse the command line arguments."""
460 461 argv = sys.argv[1:] if argv is None else argv
461 462 self.argv = [ py3compat.cast_unicode(arg) for arg in argv ]
462 463
463 464 if argv and argv[0] == 'help':
464 465 # turn `ipython help notebook` into `ipython notebook -h`
465 466 argv = argv[1:] + ['-h']
466 467
467 468 if self.subcommands and len(argv) > 0:
468 469 # we have subcommands, and one may have been specified
469 470 subc, subargv = argv[0], argv[1:]
470 471 if re.match(r'^\w(\-?\w)*$', subc) and subc in self.subcommands:
471 472 # it's a subcommand, and *not* a flag or class parameter
472 473 return self.initialize_subcommand(subc, subargv)
473 474
474 475 # Arguments after a '--' argument are for the script IPython may be
475 476 # about to run, not IPython iteslf. For arguments parsed here (help and
476 477 # version), we want to only search the arguments up to the first
477 478 # occurrence of '--', which we're calling interpreted_argv.
478 479 try:
479 480 interpreted_argv = argv[:argv.index('--')]
480 481 except ValueError:
481 482 interpreted_argv = argv
482 483
483 484 if any(x in interpreted_argv for x in ('-h', '--help-all', '--help')):
484 485 self.print_help('--help-all' in interpreted_argv)
485 486 self.exit(0)
486 487
487 488 if '--version' in interpreted_argv or '-V' in interpreted_argv:
488 489 self.print_version()
489 490 self.exit(0)
490 491
491 492 # flatten flags&aliases, so cl-args get appropriate priority:
492 493 flags,aliases = self.flatten_flags()
493 494
494 495 loader = KVArgParseConfigLoader(argv=argv, aliases=aliases,
495 496 flags=flags)
496 497 config = loader.load_config()
497 498 self.update_config(config)
498 499 # store unparsed args in extra_args
499 500 self.extra_args = loader.extra_args
500 501
501 502 @catch_config_error
502 503 def load_config_file(self, filename, path=None):
503 504 """Load a .py based config file by filename and path."""
504 505 loader = PyFileConfigLoader(filename, path=path)
505 506 try:
506 507 config = loader.load_config()
507 508 except ConfigFileNotFound:
508 509 # problem finding the file, raise
509 510 raise
510 511 except Exception:
511 512 # try to get the full filename, but it will be empty in the
512 513 # unlikely event that the error raised before filefind finished
513 514 filename = loader.full_filename or filename
514 515 # problem while running the file
515 516 self.log.error("Exception while loading config file %s",
516 517 filename, exc_info=True)
517 518 else:
518 519 self.log.debug("Loaded config file: %s", loader.full_filename)
519 520 self.update_config(config)
520 521
521 522 def generate_config_file(self):
522 523 """generate default config file from Configurables"""
523 524 lines = ["# Configuration file for %s."%self.name]
524 525 lines.append('')
525 526 lines.append('c = get_config()')
526 527 lines.append('')
527 528 for cls in self.classes:
528 529 lines.append(cls.class_config_section())
529 530 return '\n'.join(lines)
530 531
531 532 def exit(self, exit_status=0):
532 533 self.log.debug("Exiting application: %s" % self.name)
533 534 sys.exit(exit_status)
534 535
535 536 @classmethod
536 537 def launch_instance(cls, argv=None, **kwargs):
537 538 """Launch a global instance of this Application
538 539
539 540 If a global instance already exists, this reinitializes and starts it
540 541 """
541 542 app = cls.instance(**kwargs)
542 543 app.initialize(argv)
543 544 app.start()
544 545
545 546 #-----------------------------------------------------------------------------
546 547 # utility functions, for convenience
547 548 #-----------------------------------------------------------------------------
548 549
549 550 def boolean_flag(name, configurable, set_help='', unset_help=''):
550 551 """Helper for building basic --trait, --no-trait flags.
551 552
552 553 Parameters
553 554 ----------
554 555
555 556 name : str
556 557 The name of the flag.
557 558 configurable : str
558 559 The 'Class.trait' string of the trait to be set/unset with the flag
559 560 set_help : unicode
560 561 help string for --name flag
561 562 unset_help : unicode
562 563 help string for --no-name flag
563 564
564 565 Returns
565 566 -------
566 567
567 568 cfg : dict
568 569 A dict with two keys: 'name', and 'no-name', for setting and unsetting
569 570 the trait, respectively.
570 571 """
571 572 # default helpstrings
572 573 set_help = set_help or "set %s=True"%configurable
573 574 unset_help = unset_help or "set %s=False"%configurable
574 575
575 576 cls,trait = configurable.split('.')
576 577
577 578 setter = {cls : {trait : True}}
578 579 unsetter = {cls : {trait : False}}
579 580 return {name : (setter, set_help), 'no-'+name : (unsetter, unset_help)}
580 581
@@ -1,387 +1,388 b''
1 1 # encoding: utf-8
2 2 """
3 3 A base class for objects that are configurable.
4 4
5 5 Inheritance diagram:
6 6
7 7 .. inheritance-diagram:: IPython.config.configurable
8 8 :parts: 3
9 9
10 10 Authors:
11 11
12 12 * Brian Granger
13 13 * Fernando Perez
14 14 * Min RK
15 15 """
16 from __future__ import print_function
16 17
17 18 #-----------------------------------------------------------------------------
18 19 # Copyright (C) 2008-2011 The IPython Development Team
19 20 #
20 21 # Distributed under the terms of the BSD License. The full license is in
21 22 # the file COPYING, distributed as part of this software.
22 23 #-----------------------------------------------------------------------------
23 24
24 25 #-----------------------------------------------------------------------------
25 26 # Imports
26 27 #-----------------------------------------------------------------------------
27 28
28 29 import datetime
29 30 from copy import deepcopy
30 31
31 32 from .loader import Config, LazyConfigValue
32 33 from IPython.utils.traitlets import HasTraits, Instance
33 34 from IPython.utils.text import indent, wrap_paragraphs
34 35
35 36
36 37 #-----------------------------------------------------------------------------
37 38 # Helper classes for Configurables
38 39 #-----------------------------------------------------------------------------
39 40
40 41
41 42 class ConfigurableError(Exception):
42 43 pass
43 44
44 45
45 46 class MultipleInstanceError(ConfigurableError):
46 47 pass
47 48
48 49 #-----------------------------------------------------------------------------
49 50 # Configurable implementation
50 51 #-----------------------------------------------------------------------------
51 52
52 53 class Configurable(HasTraits):
53 54
54 55 config = Instance(Config, (), {})
55 56 parent = Instance('IPython.config.configurable.Configurable')
56 57 created = None
57 58
58 59 def __init__(self, **kwargs):
59 60 """Create a configurable given a config config.
60 61
61 62 Parameters
62 63 ----------
63 64 config : Config
64 65 If this is empty, default values are used. If config is a
65 66 :class:`Config` instance, it will be used to configure the
66 67 instance.
67 68 parent : Configurable instance, optional
68 69 The parent Configurable instance of this object.
69 70
70 71 Notes
71 72 -----
72 73 Subclasses of Configurable must call the :meth:`__init__` method of
73 74 :class:`Configurable` *before* doing anything else and using
74 75 :func:`super`::
75 76
76 77 class MyConfigurable(Configurable):
77 78 def __init__(self, config=None):
78 79 super(MyConfigurable, self).__init__(config=config)
79 80 # Then any other code you need to finish initialization.
80 81
81 82 This ensures that instances will be configured properly.
82 83 """
83 84 parent = kwargs.pop('parent', None)
84 85 if parent is not None:
85 86 # config is implied from parent
86 87 if kwargs.get('config', None) is None:
87 88 kwargs['config'] = parent.config
88 89 self.parent = parent
89 90
90 91 config = kwargs.pop('config', None)
91 92 if config is not None:
92 93 # We used to deepcopy, but for now we are trying to just save
93 94 # by reference. This *could* have side effects as all components
94 95 # will share config. In fact, I did find such a side effect in
95 96 # _config_changed below. If a config attribute value was a mutable type
96 97 # all instances of a component were getting the same copy, effectively
97 98 # making that a class attribute.
98 99 # self.config = deepcopy(config)
99 100 self.config = config
100 101 # This should go second so individual keyword arguments override
101 102 # the values in config.
102 103 super(Configurable, self).__init__(**kwargs)
103 104 self.created = datetime.datetime.now()
104 105
105 106 #-------------------------------------------------------------------------
106 107 # Static trait notifiations
107 108 #-------------------------------------------------------------------------
108 109
109 110 @classmethod
110 111 def section_names(cls):
111 112 """return section names as a list"""
112 113 return [c.__name__ for c in reversed(cls.__mro__) if
113 114 issubclass(c, Configurable) and issubclass(cls, c)
114 115 ]
115 116
116 117 def _find_my_config(self, cfg):
117 118 """extract my config from a global Config object
118 119
119 120 will construct a Config object of only the config values that apply to me
120 121 based on my mro(), as well as those of my parent(s) if they exist.
121 122
122 123 If I am Bar and my parent is Foo, and their parent is Tim,
123 124 this will return merge following config sections, in this order::
124 125
125 126 [Bar, Foo.bar, Tim.Foo.Bar]
126 127
127 128 With the last item being the highest priority.
128 129 """
129 130 cfgs = [cfg]
130 131 if self.parent:
131 132 cfgs.append(self.parent._find_my_config(cfg))
132 133 my_config = Config()
133 134 for c in cfgs:
134 135 for sname in self.section_names():
135 136 # Don't do a blind getattr as that would cause the config to
136 137 # dynamically create the section with name Class.__name__.
137 138 if c._has_section(sname):
138 139 my_config.merge(c[sname])
139 140 return my_config
140 141
141 142 def _load_config(self, cfg, section_names=None, traits=None):
142 143 """load traits from a Config object"""
143 144
144 145 if traits is None:
145 146 traits = self.traits(config=True)
146 147 if section_names is None:
147 148 section_names = self.section_names()
148 149
149 150 my_config = self._find_my_config(cfg)
150 151 for name, config_value in my_config.iteritems():
151 152 if name in traits:
152 153 if isinstance(config_value, LazyConfigValue):
153 154 # ConfigValue is a wrapper for using append / update on containers
154 155 # without having to copy the
155 156 initial = getattr(self, name)
156 157 config_value = config_value.get_value(initial)
157 158 # We have to do a deepcopy here if we don't deepcopy the entire
158 159 # config object. If we don't, a mutable config_value will be
159 160 # shared by all instances, effectively making it a class attribute.
160 161 setattr(self, name, deepcopy(config_value))
161 162
162 163 def _config_changed(self, name, old, new):
163 164 """Update all the class traits having ``config=True`` as metadata.
164 165
165 166 For any class trait with a ``config`` metadata attribute that is
166 167 ``True``, we update the trait with the value of the corresponding
167 168 config entry.
168 169 """
169 170 # Get all traits with a config metadata entry that is True
170 171 traits = self.traits(config=True)
171 172
172 173 # We auto-load config section for this class as well as any parent
173 174 # classes that are Configurable subclasses. This starts with Configurable
174 175 # and works down the mro loading the config for each section.
175 176 section_names = self.section_names()
176 177 self._load_config(new, traits=traits, section_names=section_names)
177 178
178 179 def update_config(self, config):
179 180 """Fire the traits events when the config is updated."""
180 181 # Save a copy of the current config.
181 182 newconfig = deepcopy(self.config)
182 183 # Merge the new config into the current one.
183 184 newconfig.merge(config)
184 185 # Save the combined config as self.config, which triggers the traits
185 186 # events.
186 187 self.config = newconfig
187 188
188 189 @classmethod
189 190 def class_get_help(cls, inst=None):
190 191 """Get the help string for this class in ReST format.
191 192
192 193 If `inst` is given, it's current trait values will be used in place of
193 194 class defaults.
194 195 """
195 196 assert inst is None or isinstance(inst, cls)
196 197 final_help = []
197 198 final_help.append(u'%s options' % cls.__name__)
198 199 final_help.append(len(final_help[0])*u'-')
199 200 for k, v in sorted(cls.class_traits(config=True).iteritems()):
200 201 help = cls.class_get_trait_help(v, inst)
201 202 final_help.append(help)
202 203 return '\n'.join(final_help)
203 204
204 205 @classmethod
205 206 def class_get_trait_help(cls, trait, inst=None):
206 207 """Get the help string for a single trait.
207 208
208 209 If `inst` is given, it's current trait values will be used in place of
209 210 the class default.
210 211 """
211 212 assert inst is None or isinstance(inst, cls)
212 213 lines = []
213 214 header = "--%s.%s=<%s>" % (cls.__name__, trait.name, trait.__class__.__name__)
214 215 lines.append(header)
215 216 if inst is not None:
216 217 lines.append(indent('Current: %r' % getattr(inst, trait.name), 4))
217 218 else:
218 219 try:
219 220 dvr = repr(trait.get_default_value())
220 221 except Exception:
221 222 dvr = None # ignore defaults we can't construct
222 223 if dvr is not None:
223 224 if len(dvr) > 64:
224 225 dvr = dvr[:61]+'...'
225 226 lines.append(indent('Default: %s' % dvr, 4))
226 227 if 'Enum' in trait.__class__.__name__:
227 228 # include Enum choices
228 229 lines.append(indent('Choices: %r' % (trait.values,)))
229 230
230 231 help = trait.get_metadata('help')
231 232 if help is not None:
232 233 help = '\n'.join(wrap_paragraphs(help, 76))
233 234 lines.append(indent(help, 4))
234 235 return '\n'.join(lines)
235 236
236 237 @classmethod
237 238 def class_print_help(cls, inst=None):
238 239 """Get the help string for a single trait and print it."""
239 print cls.class_get_help(inst)
240 print(cls.class_get_help(inst))
240 241
241 242 @classmethod
242 243 def class_config_section(cls):
243 244 """Get the config class config section"""
244 245 def c(s):
245 246 """return a commented, wrapped block."""
246 247 s = '\n\n'.join(wrap_paragraphs(s, 78))
247 248
248 249 return '# ' + s.replace('\n', '\n# ')
249 250
250 251 # section header
251 252 breaker = '#' + '-'*78
252 253 s = "# %s configuration" % cls.__name__
253 254 lines = [breaker, s, breaker, '']
254 255 # get the description trait
255 256 desc = cls.class_traits().get('description')
256 257 if desc:
257 258 desc = desc.default_value
258 259 else:
259 260 # no description trait, use __doc__
260 261 desc = getattr(cls, '__doc__', '')
261 262 if desc:
262 263 lines.append(c(desc))
263 264 lines.append('')
264 265
265 266 parents = []
266 267 for parent in cls.mro():
267 268 # only include parents that are not base classes
268 269 # and are not the class itself
269 270 # and have some configurable traits to inherit
270 271 if parent is not cls and issubclass(parent, Configurable) and \
271 272 parent.class_traits(config=True):
272 273 parents.append(parent)
273 274
274 275 if parents:
275 276 pstr = ', '.join([ p.__name__ for p in parents ])
276 277 lines.append(c('%s will inherit config from: %s'%(cls.__name__, pstr)))
277 278 lines.append('')
278 279
279 280 for name, trait in cls.class_traits(config=True).iteritems():
280 281 help = trait.get_metadata('help') or ''
281 282 lines.append(c(help))
282 283 lines.append('# c.%s.%s = %r'%(cls.__name__, name, trait.get_default_value()))
283 284 lines.append('')
284 285 return '\n'.join(lines)
285 286
286 287
287 288
288 289 class SingletonConfigurable(Configurable):
289 290 """A configurable that only allows one instance.
290 291
291 292 This class is for classes that should only have one instance of itself
292 293 or *any* subclass. To create and retrieve such a class use the
293 294 :meth:`SingletonConfigurable.instance` method.
294 295 """
295 296
296 297 _instance = None
297 298
298 299 @classmethod
299 300 def _walk_mro(cls):
300 301 """Walk the cls.mro() for parent classes that are also singletons
301 302
302 303 For use in instance()
303 304 """
304 305
305 306 for subclass in cls.mro():
306 307 if issubclass(cls, subclass) and \
307 308 issubclass(subclass, SingletonConfigurable) and \
308 309 subclass != SingletonConfigurable:
309 310 yield subclass
310 311
311 312 @classmethod
312 313 def clear_instance(cls):
313 314 """unset _instance for this class and singleton parents.
314 315 """
315 316 if not cls.initialized():
316 317 return
317 318 for subclass in cls._walk_mro():
318 319 if isinstance(subclass._instance, cls):
319 320 # only clear instances that are instances
320 321 # of the calling class
321 322 subclass._instance = None
322 323
323 324 @classmethod
324 325 def instance(cls, *args, **kwargs):
325 326 """Returns a global instance of this class.
326 327
327 328 This method create a new instance if none have previously been created
328 329 and returns a previously created instance is one already exists.
329 330
330 331 The arguments and keyword arguments passed to this method are passed
331 332 on to the :meth:`__init__` method of the class upon instantiation.
332 333
333 334 Examples
334 335 --------
335 336
336 337 Create a singleton class using instance, and retrieve it::
337 338
338 339 >>> from IPython.config.configurable import SingletonConfigurable
339 340 >>> class Foo(SingletonConfigurable): pass
340 341 >>> foo = Foo.instance()
341 342 >>> foo == Foo.instance()
342 343 True
343 344
344 345 Create a subclass that is retrived using the base class instance::
345 346
346 347 >>> class Bar(SingletonConfigurable): pass
347 348 >>> class Bam(Bar): pass
348 349 >>> bam = Bam.instance()
349 350 >>> bam == Bar.instance()
350 351 True
351 352 """
352 353 # Create and save the instance
353 354 if cls._instance is None:
354 355 inst = cls(*args, **kwargs)
355 356 # Now make sure that the instance will also be returned by
356 357 # parent classes' _instance attribute.
357 358 for subclass in cls._walk_mro():
358 359 subclass._instance = inst
359 360
360 361 if isinstance(cls._instance, cls):
361 362 return cls._instance
362 363 else:
363 364 raise MultipleInstanceError(
364 365 'Multiple incompatible subclass instances of '
365 366 '%s are being created.' % cls.__name__
366 367 )
367 368
368 369 @classmethod
369 370 def initialized(cls):
370 371 """Has an instance been created?"""
371 372 return hasattr(cls, "_instance") and cls._instance is not None
372 373
373 374
374 375 class LoggingConfigurable(Configurable):
375 376 """A parent class for Configurables that log.
376 377
377 378 Subclasses have a log trait, and the default behavior
378 379 is to get the logger from the currently running Application
379 380 via Application.instance().log.
380 381 """
381 382
382 383 log = Instance('logging.Logger')
383 384 def _log_default(self):
384 385 from IPython.config.application import Application
385 386 return Application.instance().log
386 387
387 388
@@ -1,220 +1,221 b''
1 1 """Logger class for IPython's logging facilities.
2 2 """
3 from __future__ import print_function
3 4
4 5 #*****************************************************************************
5 6 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de> and
6 7 # Copyright (C) 2001-2006 Fernando Perez <fperez@colorado.edu>
7 8 #
8 9 # Distributed under the terms of the BSD License. The full license is in
9 10 # the file COPYING, distributed as part of this software.
10 11 #*****************************************************************************
11 12
12 13 #****************************************************************************
13 14 # Modules and globals
14 15
15 16 # Python standard modules
16 17 import glob
17 18 import io
18 19 import os
19 20 import time
20 21
21 22 from IPython.utils.py3compat import str_to_unicode
22 23
23 24 #****************************************************************************
24 25 # FIXME: This class isn't a mixin anymore, but it still needs attributes from
25 26 # ipython and does input cache management. Finish cleanup later...
26 27
27 28 class Logger(object):
28 29 """A Logfile class with different policies for file creation"""
29 30
30 31 def __init__(self, home_dir, logfname='Logger.log', loghead=u'',
31 32 logmode='over'):
32 33
33 34 # this is the full ipython instance, we need some attributes from it
34 35 # which won't exist until later. What a mess, clean up later...
35 36 self.home_dir = home_dir
36 37
37 38 self.logfname = logfname
38 39 self.loghead = loghead
39 40 self.logmode = logmode
40 41 self.logfile = None
41 42
42 43 # Whether to log raw or processed input
43 44 self.log_raw_input = False
44 45
45 46 # whether to also log output
46 47 self.log_output = False
47 48
48 49 # whether to put timestamps before each log entry
49 50 self.timestamp = False
50 51
51 52 # activity control flags
52 53 self.log_active = False
53 54
54 55 # logmode is a validated property
55 56 def _set_mode(self,mode):
56 57 if mode not in ['append','backup','global','over','rotate']:
57 58 raise ValueError('invalid log mode %s given' % mode)
58 59 self._logmode = mode
59 60
60 61 def _get_mode(self):
61 62 return self._logmode
62 63
63 64 logmode = property(_get_mode,_set_mode)
64 65
65 66 def logstart(self, logfname=None, loghead=None, logmode=None,
66 67 log_output=False, timestamp=False, log_raw_input=False):
67 68 """Generate a new log-file with a default header.
68 69
69 70 Raises RuntimeError if the log has already been started"""
70 71
71 72 if self.logfile is not None:
72 73 raise RuntimeError('Log file is already active: %s' %
73 74 self.logfname)
74 75
75 76 # The parameters can override constructor defaults
76 77 if logfname is not None: self.logfname = logfname
77 78 if loghead is not None: self.loghead = loghead
78 79 if logmode is not None: self.logmode = logmode
79 80
80 81 # Parameters not part of the constructor
81 82 self.timestamp = timestamp
82 83 self.log_output = log_output
83 84 self.log_raw_input = log_raw_input
84 85
85 86 # init depending on the log mode requested
86 87 isfile = os.path.isfile
87 88 logmode = self.logmode
88 89
89 90 if logmode == 'append':
90 91 self.logfile = io.open(self.logfname, 'a', encoding='utf-8')
91 92
92 93 elif logmode == 'backup':
93 94 if isfile(self.logfname):
94 95 backup_logname = self.logfname+'~'
95 96 # Manually remove any old backup, since os.rename may fail
96 97 # under Windows.
97 98 if isfile(backup_logname):
98 99 os.remove(backup_logname)
99 100 os.rename(self.logfname,backup_logname)
100 101 self.logfile = io.open(self.logfname, 'w', encoding='utf-8')
101 102
102 103 elif logmode == 'global':
103 104 self.logfname = os.path.join(self.home_dir,self.logfname)
104 105 self.logfile = io.open(self.logfname, 'a', encoding='utf-8')
105 106
106 107 elif logmode == 'over':
107 108 if isfile(self.logfname):
108 109 os.remove(self.logfname)
109 110 self.logfile = io.open(self.logfname,'w', encoding='utf-8')
110 111
111 112 elif logmode == 'rotate':
112 113 if isfile(self.logfname):
113 114 if isfile(self.logfname+'.001~'):
114 115 old = glob.glob(self.logfname+'.*~')
115 116 old.sort()
116 117 old.reverse()
117 118 for f in old:
118 119 root, ext = os.path.splitext(f)
119 120 num = int(ext[1:-1])+1
120 121 os.rename(f, root+'.'+repr(num).zfill(3)+'~')
121 122 os.rename(self.logfname, self.logfname+'.001~')
122 123 self.logfile = io.open(self.logfname, 'w', encoding='utf-8')
123 124
124 125 if logmode != 'append':
125 126 self.logfile.write(self.loghead)
126 127
127 128 self.logfile.flush()
128 129 self.log_active = True
129 130
130 131 def switch_log(self,val):
131 132 """Switch logging on/off. val should be ONLY a boolean."""
132 133
133 134 if val not in [False,True,0,1]:
134 135 raise ValueError('Call switch_log ONLY with a boolean argument, '
135 136 'not with: %s' % val)
136 137
137 138 label = {0:'OFF',1:'ON',False:'OFF',True:'ON'}
138 139
139 140 if self.logfile is None:
140 print """
141 print("""
141 142 Logging hasn't been started yet (use logstart for that).
142 143
143 144 %logon/%logoff are for temporarily starting and stopping logging for a logfile
144 145 which already exists. But you must first start the logging process with
145 %logstart (optionally giving a logfile name)."""
146 %logstart (optionally giving a logfile name).""")
146 147
147 148 else:
148 149 if self.log_active == val:
149 print 'Logging is already',label[val]
150 print('Logging is already',label[val])
150 151 else:
151 print 'Switching logging',label[val]
152 print('Switching logging',label[val])
152 153 self.log_active = not self.log_active
153 154 self.log_active_out = self.log_active
154 155
155 156 def logstate(self):
156 157 """Print a status message about the logger."""
157 158 if self.logfile is None:
158 print 'Logging has not been activated.'
159 print('Logging has not been activated.')
159 160 else:
160 161 state = self.log_active and 'active' or 'temporarily suspended'
161 print 'Filename :',self.logfname
162 print 'Mode :',self.logmode
163 print 'Output logging :',self.log_output
164 print 'Raw input log :',self.log_raw_input
165 print 'Timestamping :',self.timestamp
166 print 'State :',state
162 print('Filename :',self.logfname)
163 print('Mode :',self.logmode)
164 print('Output logging :',self.log_output)
165 print('Raw input log :',self.log_raw_input)
166 print('Timestamping :',self.timestamp)
167 print('State :',state)
167 168
168 169 def log(self, line_mod, line_ori):
169 170 """Write the sources to a log.
170 171
171 172 Inputs:
172 173
173 174 - line_mod: possibly modified input, such as the transformations made
174 175 by input prefilters or input handlers of various kinds. This should
175 176 always be valid Python.
176 177
177 178 - line_ori: unmodified input line from the user. This is not
178 179 necessarily valid Python.
179 180 """
180 181
181 182 # Write the log line, but decide which one according to the
182 183 # log_raw_input flag, set when the log is started.
183 184 if self.log_raw_input:
184 185 self.log_write(line_ori)
185 186 else:
186 187 self.log_write(line_mod)
187 188
188 189 def log_write(self, data, kind='input'):
189 190 """Write data to the log file, if active"""
190 191
191 192 #print 'data: %r' % data # dbg
192 193 if self.log_active and data:
193 194 write = self.logfile.write
194 195 if kind=='input':
195 196 if self.timestamp:
196 197 write(str_to_unicode(time.strftime('# %a, %d %b %Y %H:%M:%S\n',
197 198 time.localtime())))
198 199 write(data)
199 200 elif kind=='output' and self.log_output:
200 201 odata = u'\n'.join([u'#[Out]# %s' % s
201 202 for s in data.splitlines()])
202 203 write(u'%s\n' % odata)
203 204 self.logfile.flush()
204 205
205 206 def logstop(self):
206 207 """Fully stop logging and close log file.
207 208
208 209 In order to start logging again, a new logstart() call needs to be
209 210 made, possibly (though not necessarily) with a new filename, mode and
210 211 other options."""
211 212
212 213 if self.logfile is not None:
213 214 self.logfile.close()
214 215 self.logfile = None
215 216 else:
216 print "Logging hadn't been started."
217 print("Logging hadn't been started.")
217 218 self.log_active = False
218 219
219 220 # For backwards compatibility, in case anyone was using this.
220 221 close_log = logstop
@@ -1,688 +1,689 b''
1 1 # encoding: utf-8
2 2 """Magic functions for InteractiveShell.
3 3 """
4 from __future__ import print_function
4 5
5 6 #-----------------------------------------------------------------------------
6 7 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de> and
7 8 # Copyright (C) 2001 Fernando Perez <fperez@colorado.edu>
8 9 # Copyright (C) 2008 The IPython Development Team
9 10
10 11 # Distributed under the terms of the BSD License. The full license is in
11 12 # the file COPYING, distributed as part of this software.
12 13 #-----------------------------------------------------------------------------
13 14
14 15 #-----------------------------------------------------------------------------
15 16 # Imports
16 17 #-----------------------------------------------------------------------------
17 18 # Stdlib
18 19 import os
19 20 import re
20 21 import sys
21 22 import types
22 23 from getopt import getopt, GetoptError
23 24
24 25 # Our own
25 26 from IPython.config.configurable import Configurable
26 27 from IPython.core import oinspect
27 28 from IPython.core.error import UsageError
28 29 from IPython.core.inputsplitter import ESC_MAGIC, ESC_MAGIC2
29 30 from IPython.external.decorator import decorator
30 31 from IPython.utils.ipstruct import Struct
31 32 from IPython.utils.process import arg_split
32 33 from IPython.utils.text import dedent
33 34 from IPython.utils.traitlets import Bool, Dict, Instance, MetaHasTraits
34 35 from IPython.utils.warn import error
35 36
36 37 #-----------------------------------------------------------------------------
37 38 # Globals
38 39 #-----------------------------------------------------------------------------
39 40
40 41 # A dict we'll use for each class that has magics, used as temporary storage to
41 42 # pass information between the @line/cell_magic method decorators and the
42 43 # @magics_class class decorator, because the method decorators have no
43 44 # access to the class when they run. See for more details:
44 45 # http://stackoverflow.com/questions/2366713/can-a-python-decorator-of-an-instance-method-access-the-class
45 46
46 47 magics = dict(line={}, cell={})
47 48
48 49 magic_kinds = ('line', 'cell')
49 50 magic_spec = ('line', 'cell', 'line_cell')
50 51 magic_escapes = dict(line=ESC_MAGIC, cell=ESC_MAGIC2)
51 52
52 53 #-----------------------------------------------------------------------------
53 54 # Utility classes and functions
54 55 #-----------------------------------------------------------------------------
55 56
56 57 class Bunch: pass
57 58
58 59
59 60 def on_off(tag):
60 61 """Return an ON/OFF string for a 1/0 input. Simple utility function."""
61 62 return ['OFF','ON'][tag]
62 63
63 64
64 65 def compress_dhist(dh):
65 66 """Compress a directory history into a new one with at most 20 entries.
66 67
67 68 Return a new list made from the first and last 10 elements of dhist after
68 69 removal of duplicates.
69 70 """
70 71 head, tail = dh[:-10], dh[-10:]
71 72
72 73 newhead = []
73 74 done = set()
74 75 for h in head:
75 76 if h in done:
76 77 continue
77 78 newhead.append(h)
78 79 done.add(h)
79 80
80 81 return newhead + tail
81 82
82 83
83 84 def needs_local_scope(func):
84 85 """Decorator to mark magic functions which need to local scope to run."""
85 86 func.needs_local_scope = True
86 87 return func
87 88
88 89 #-----------------------------------------------------------------------------
89 90 # Class and method decorators for registering magics
90 91 #-----------------------------------------------------------------------------
91 92
92 93 def magics_class(cls):
93 94 """Class decorator for all subclasses of the main Magics class.
94 95
95 96 Any class that subclasses Magics *must* also apply this decorator, to
96 97 ensure that all the methods that have been decorated as line/cell magics
97 98 get correctly registered in the class instance. This is necessary because
98 99 when method decorators run, the class does not exist yet, so they
99 100 temporarily store their information into a module global. Application of
100 101 this class decorator copies that global data to the class instance and
101 102 clears the global.
102 103
103 104 Obviously, this mechanism is not thread-safe, which means that the
104 105 *creation* of subclasses of Magic should only be done in a single-thread
105 106 context. Instantiation of the classes has no restrictions. Given that
106 107 these classes are typically created at IPython startup time and before user
107 108 application code becomes active, in practice this should not pose any
108 109 problems.
109 110 """
110 111 cls.registered = True
111 112 cls.magics = dict(line = magics['line'],
112 113 cell = magics['cell'])
113 114 magics['line'] = {}
114 115 magics['cell'] = {}
115 116 return cls
116 117
117 118
118 119 def record_magic(dct, magic_kind, magic_name, func):
119 120 """Utility function to store a function as a magic of a specific kind.
120 121
121 122 Parameters
122 123 ----------
123 124 dct : dict
124 125 A dictionary with 'line' and 'cell' subdicts.
125 126
126 127 magic_kind : str
127 128 Kind of magic to be stored.
128 129
129 130 magic_name : str
130 131 Key to store the magic as.
131 132
132 133 func : function
133 134 Callable object to store.
134 135 """
135 136 if magic_kind == 'line_cell':
136 137 dct['line'][magic_name] = dct['cell'][magic_name] = func
137 138 else:
138 139 dct[magic_kind][magic_name] = func
139 140
140 141
141 142 def validate_type(magic_kind):
142 143 """Ensure that the given magic_kind is valid.
143 144
144 145 Check that the given magic_kind is one of the accepted spec types (stored
145 146 in the global `magic_spec`), raise ValueError otherwise.
146 147 """
147 148 if magic_kind not in magic_spec:
148 149 raise ValueError('magic_kind must be one of %s, %s given' %
149 150 magic_kinds, magic_kind)
150 151
151 152
152 153 # The docstrings for the decorator below will be fairly similar for the two
153 154 # types (method and function), so we generate them here once and reuse the
154 155 # templates below.
155 156 _docstring_template = \
156 157 """Decorate the given {0} as {1} magic.
157 158
158 159 The decorator can be used with or without arguments, as follows.
159 160
160 161 i) without arguments: it will create a {1} magic named as the {0} being
161 162 decorated::
162 163
163 164 @deco
164 165 def foo(...)
165 166
166 167 will create a {1} magic named `foo`.
167 168
168 169 ii) with one string argument: which will be used as the actual name of the
169 170 resulting magic::
170 171
171 172 @deco('bar')
172 173 def foo(...)
173 174
174 175 will create a {1} magic named `bar`.
175 176 """
176 177
177 178 # These two are decorator factories. While they are conceptually very similar,
178 179 # there are enough differences in the details that it's simpler to have them
179 180 # written as completely standalone functions rather than trying to share code
180 181 # and make a single one with convoluted logic.
181 182
182 183 def _method_magic_marker(magic_kind):
183 184 """Decorator factory for methods in Magics subclasses.
184 185 """
185 186
186 187 validate_type(magic_kind)
187 188
188 189 # This is a closure to capture the magic_kind. We could also use a class,
189 190 # but it's overkill for just that one bit of state.
190 191 def magic_deco(arg):
191 192 call = lambda f, *a, **k: f(*a, **k)
192 193
193 194 if callable(arg):
194 195 # "Naked" decorator call (just @foo, no args)
195 196 func = arg
196 197 name = func.func_name
197 198 retval = decorator(call, func)
198 199 record_magic(magics, magic_kind, name, name)
199 200 elif isinstance(arg, basestring):
200 201 # Decorator called with arguments (@foo('bar'))
201 202 name = arg
202 203 def mark(func, *a, **kw):
203 204 record_magic(magics, magic_kind, name, func.func_name)
204 205 return decorator(call, func)
205 206 retval = mark
206 207 else:
207 208 raise TypeError("Decorator can only be called with "
208 209 "string or function")
209 210 return retval
210 211
211 212 # Ensure the resulting decorator has a usable docstring
212 213 magic_deco.__doc__ = _docstring_template.format('method', magic_kind)
213 214 return magic_deco
214 215
215 216
216 217 def _function_magic_marker(magic_kind):
217 218 """Decorator factory for standalone functions.
218 219 """
219 220 validate_type(magic_kind)
220 221
221 222 # This is a closure to capture the magic_kind. We could also use a class,
222 223 # but it's overkill for just that one bit of state.
223 224 def magic_deco(arg):
224 225 call = lambda f, *a, **k: f(*a, **k)
225 226
226 227 # Find get_ipython() in the caller's namespace
227 228 caller = sys._getframe(1)
228 229 for ns in ['f_locals', 'f_globals', 'f_builtins']:
229 230 get_ipython = getattr(caller, ns).get('get_ipython')
230 231 if get_ipython is not None:
231 232 break
232 233 else:
233 234 raise NameError('Decorator can only run in context where '
234 235 '`get_ipython` exists')
235 236
236 237 ip = get_ipython()
237 238
238 239 if callable(arg):
239 240 # "Naked" decorator call (just @foo, no args)
240 241 func = arg
241 242 name = func.func_name
242 243 ip.register_magic_function(func, magic_kind, name)
243 244 retval = decorator(call, func)
244 245 elif isinstance(arg, basestring):
245 246 # Decorator called with arguments (@foo('bar'))
246 247 name = arg
247 248 def mark(func, *a, **kw):
248 249 ip.register_magic_function(func, magic_kind, name)
249 250 return decorator(call, func)
250 251 retval = mark
251 252 else:
252 253 raise TypeError("Decorator can only be called with "
253 254 "string or function")
254 255 return retval
255 256
256 257 # Ensure the resulting decorator has a usable docstring
257 258 ds = _docstring_template.format('function', magic_kind)
258 259
259 260 ds += dedent("""
260 261 Note: this decorator can only be used in a context where IPython is already
261 262 active, so that the `get_ipython()` call succeeds. You can therefore use
262 263 it in your startup files loaded after IPython initializes, but *not* in the
263 264 IPython configuration file itself, which is executed before IPython is
264 265 fully up and running. Any file located in the `startup` subdirectory of
265 266 your configuration profile will be OK in this sense.
266 267 """)
267 268
268 269 magic_deco.__doc__ = ds
269 270 return magic_deco
270 271
271 272
272 273 # Create the actual decorators for public use
273 274
274 275 # These three are used to decorate methods in class definitions
275 276 line_magic = _method_magic_marker('line')
276 277 cell_magic = _method_magic_marker('cell')
277 278 line_cell_magic = _method_magic_marker('line_cell')
278 279
279 280 # These three decorate standalone functions and perform the decoration
280 281 # immediately. They can only run where get_ipython() works
281 282 register_line_magic = _function_magic_marker('line')
282 283 register_cell_magic = _function_magic_marker('cell')
283 284 register_line_cell_magic = _function_magic_marker('line_cell')
284 285
285 286 #-----------------------------------------------------------------------------
286 287 # Core Magic classes
287 288 #-----------------------------------------------------------------------------
288 289
289 290 class MagicsManager(Configurable):
290 291 """Object that handles all magic-related functionality for IPython.
291 292 """
292 293 # Non-configurable class attributes
293 294
294 295 # A two-level dict, first keyed by magic type, then by magic function, and
295 296 # holding the actual callable object as value. This is the dict used for
296 297 # magic function dispatch
297 298 magics = Dict
298 299
299 300 # A registry of the original objects that we've been given holding magics.
300 301 registry = Dict
301 302
302 303 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
303 304
304 305 auto_magic = Bool(True, config=True, help=
305 306 "Automatically call line magics without requiring explicit % prefix")
306 307
307 308 def _auto_magic_changed(self, name, value):
308 309 self.shell.automagic = value
309 310
310 311 _auto_status = [
311 312 'Automagic is OFF, % prefix IS needed for line magics.',
312 313 'Automagic is ON, % prefix IS NOT needed for line magics.']
313 314
314 315 user_magics = Instance('IPython.core.magics.UserMagics')
315 316
316 317 def __init__(self, shell=None, config=None, user_magics=None, **traits):
317 318
318 319 super(MagicsManager, self).__init__(shell=shell, config=config,
319 320 user_magics=user_magics, **traits)
320 321 self.magics = dict(line={}, cell={})
321 322 # Let's add the user_magics to the registry for uniformity, so *all*
322 323 # registered magic containers can be found there.
323 324 self.registry[user_magics.__class__.__name__] = user_magics
324 325
325 326 def auto_status(self):
326 327 """Return descriptive string with automagic status."""
327 328 return self._auto_status[self.auto_magic]
328 329
329 330 def lsmagic(self):
330 331 """Return a dict of currently available magic functions.
331 332
332 333 The return dict has the keys 'line' and 'cell', corresponding to the
333 334 two types of magics we support. Each value is a list of names.
334 335 """
335 336 return self.magics
336 337
337 338 def lsmagic_docs(self, brief=False, missing=''):
338 339 """Return dict of documentation of magic functions.
339 340
340 341 The return dict has the keys 'line' and 'cell', corresponding to the
341 342 two types of magics we support. Each value is a dict keyed by magic
342 343 name whose value is the function docstring. If a docstring is
343 344 unavailable, the value of `missing` is used instead.
344 345
345 346 If brief is True, only the first line of each docstring will be returned.
346 347 """
347 348 docs = {}
348 349 for m_type in self.magics:
349 350 m_docs = {}
350 351 for m_name, m_func in self.magics[m_type].iteritems():
351 352 if m_func.__doc__:
352 353 if brief:
353 354 m_docs[m_name] = m_func.__doc__.split('\n', 1)[0]
354 355 else:
355 356 m_docs[m_name] = m_func.__doc__.rstrip()
356 357 else:
357 358 m_docs[m_name] = missing
358 359 docs[m_type] = m_docs
359 360 return docs
360 361
361 362 def register(self, *magic_objects):
362 363 """Register one or more instances of Magics.
363 364
364 365 Take one or more classes or instances of classes that subclass the main
365 366 `core.Magic` class, and register them with IPython to use the magic
366 367 functions they provide. The registration process will then ensure that
367 368 any methods that have decorated to provide line and/or cell magics will
368 369 be recognized with the `%x`/`%%x` syntax as a line/cell magic
369 370 respectively.
370 371
371 372 If classes are given, they will be instantiated with the default
372 373 constructor. If your classes need a custom constructor, you should
373 374 instanitate them first and pass the instance.
374 375
375 376 The provided arguments can be an arbitrary mix of classes and instances.
376 377
377 378 Parameters
378 379 ----------
379 380 magic_objects : one or more classes or instances
380 381 """
381 382 # Start by validating them to ensure they have all had their magic
382 383 # methods registered at the instance level
383 384 for m in magic_objects:
384 385 if not m.registered:
385 386 raise ValueError("Class of magics %r was constructed without "
386 387 "the @register_magics class decorator")
387 388 if type(m) in (type, MetaHasTraits):
388 389 # If we're given an uninstantiated class
389 390 m = m(shell=self.shell)
390 391
391 392 # Now that we have an instance, we can register it and update the
392 393 # table of callables
393 394 self.registry[m.__class__.__name__] = m
394 395 for mtype in magic_kinds:
395 396 self.magics[mtype].update(m.magics[mtype])
396 397
397 398 def register_function(self, func, magic_kind='line', magic_name=None):
398 399 """Expose a standalone function as magic function for IPython.
399 400
400 401 This will create an IPython magic (line, cell or both) from a
401 402 standalone function. The functions should have the following
402 403 signatures:
403 404
404 405 * For line magics: `def f(line)`
405 406 * For cell magics: `def f(line, cell)`
406 407 * For a function that does both: `def f(line, cell=None)`
407 408
408 409 In the latter case, the function will be called with `cell==None` when
409 410 invoked as `%f`, and with cell as a string when invoked as `%%f`.
410 411
411 412 Parameters
412 413 ----------
413 414 func : callable
414 415 Function to be registered as a magic.
415 416
416 417 magic_kind : str
417 418 Kind of magic, one of 'line', 'cell' or 'line_cell'
418 419
419 420 magic_name : optional str
420 421 If given, the name the magic will have in the IPython namespace. By
421 422 default, the name of the function itself is used.
422 423 """
423 424
424 425 # Create the new method in the user_magics and register it in the
425 426 # global table
426 427 validate_type(magic_kind)
427 428 magic_name = func.func_name if magic_name is None else magic_name
428 429 setattr(self.user_magics, magic_name, func)
429 430 record_magic(self.magics, magic_kind, magic_name, func)
430 431
431 432 def define_magic(self, name, func):
432 433 """[Deprecated] Expose own function as magic function for IPython.
433 434
434 435 Example::
435 436
436 437 def foo_impl(self, parameter_s=''):
437 438 'My very own magic!. (Use docstrings, IPython reads them).'
438 439 print 'Magic function. Passed parameter is between < >:'
439 440 print '<%s>' % parameter_s
440 441 print 'The self object is:', self
441 442
442 443 ip.define_magic('foo',foo_impl)
443 444 """
444 445 meth = types.MethodType(func, self.user_magics)
445 446 setattr(self.user_magics, name, meth)
446 447 record_magic(self.magics, 'line', name, meth)
447 448
448 449 def register_alias(self, alias_name, magic_name, magic_kind='line'):
449 450 """Register an alias to a magic function.
450 451
451 452 The alias is an instance of :class:`MagicAlias`, which holds the
452 453 name and kind of the magic it should call. Binding is done at
453 454 call time, so if the underlying magic function is changed the alias
454 455 will call the new function.
455 456
456 457 Parameters
457 458 ----------
458 459 alias_name : str
459 460 The name of the magic to be registered.
460 461
461 462 magic_name : str
462 463 The name of an existing magic.
463 464
464 465 magic_kind : str
465 466 Kind of magic, one of 'line' or 'cell'
466 467 """
467 468
468 469 # `validate_type` is too permissive, as it allows 'line_cell'
469 470 # which we do not handle.
470 471 if magic_kind not in magic_kinds:
471 472 raise ValueError('magic_kind must be one of %s, %s given' %
472 473 magic_kinds, magic_kind)
473 474
474 475 alias = MagicAlias(self.shell, magic_name, magic_kind)
475 476 setattr(self.user_magics, alias_name, alias)
476 477 record_magic(self.magics, magic_kind, alias_name, alias)
477 478
478 479 # Key base class that provides the central functionality for magics.
479 480
480 481
481 482 class Magics(Configurable):
482 483 """Base class for implementing magic functions.
483 484
484 485 Shell functions which can be reached as %function_name. All magic
485 486 functions should accept a string, which they can parse for their own
486 487 needs. This can make some functions easier to type, eg `%cd ../`
487 488 vs. `%cd("../")`
488 489
489 490 Classes providing magic functions need to subclass this class, and they
490 491 MUST:
491 492
492 493 - Use the method decorators `@line_magic` and `@cell_magic` to decorate
493 494 individual methods as magic functions, AND
494 495
495 496 - Use the class decorator `@magics_class` to ensure that the magic
496 497 methods are properly registered at the instance level upon instance
497 498 initialization.
498 499
499 500 See :mod:`magic_functions` for examples of actual implementation classes.
500 501 """
501 502 # Dict holding all command-line options for each magic.
502 503 options_table = None
503 504 # Dict for the mapping of magic names to methods, set by class decorator
504 505 magics = None
505 506 # Flag to check that the class decorator was properly applied
506 507 registered = False
507 508 # Instance of IPython shell
508 509 shell = None
509 510
510 511 def __init__(self, shell=None, **kwargs):
511 512 if not(self.__class__.registered):
512 513 raise ValueError('Magics subclass without registration - '
513 514 'did you forget to apply @magics_class?')
514 515 if shell is not None:
515 516 if hasattr(shell, 'configurables'):
516 517 shell.configurables.append(self)
517 518 if hasattr(shell, 'config'):
518 519 kwargs.setdefault('parent', shell)
519 520 kwargs['shell'] = shell
520 521
521 522 self.shell = shell
522 523 self.options_table = {}
523 524 # The method decorators are run when the instance doesn't exist yet, so
524 525 # they can only record the names of the methods they are supposed to
525 526 # grab. Only now, that the instance exists, can we create the proper
526 527 # mapping to bound methods. So we read the info off the original names
527 528 # table and replace each method name by the actual bound method.
528 529 # But we mustn't clobber the *class* mapping, in case of multiple instances.
529 530 class_magics = self.magics
530 531 self.magics = {}
531 532 for mtype in magic_kinds:
532 533 tab = self.magics[mtype] = {}
533 534 cls_tab = class_magics[mtype]
534 535 for magic_name, meth_name in cls_tab.iteritems():
535 536 if isinstance(meth_name, basestring):
536 537 # it's a method name, grab it
537 538 tab[magic_name] = getattr(self, meth_name)
538 539 else:
539 540 # it's the real thing
540 541 tab[magic_name] = meth_name
541 542 # Configurable **needs** to be initiated at the end or the config
542 543 # magics get screwed up.
543 544 super(Magics, self).__init__(**kwargs)
544 545
545 546 def arg_err(self,func):
546 547 """Print docstring if incorrect arguments were passed"""
547 print 'Error in arguments:'
548 print oinspect.getdoc(func)
548 print('Error in arguments:')
549 print(oinspect.getdoc(func))
549 550
550 551 def format_latex(self, strng):
551 552 """Format a string for latex inclusion."""
552 553
553 554 # Characters that need to be escaped for latex:
554 555 escape_re = re.compile(r'(%|_|\$|#|&)',re.MULTILINE)
555 556 # Magic command names as headers:
556 557 cmd_name_re = re.compile(r'^(%s.*?):' % ESC_MAGIC,
557 558 re.MULTILINE)
558 559 # Magic commands
559 560 cmd_re = re.compile(r'(?P<cmd>%s.+?\b)(?!\}\}:)' % ESC_MAGIC,
560 561 re.MULTILINE)
561 562 # Paragraph continue
562 563 par_re = re.compile(r'\\$',re.MULTILINE)
563 564
564 565 # The "\n" symbol
565 566 newline_re = re.compile(r'\\n')
566 567
567 568 # Now build the string for output:
568 569 #strng = cmd_name_re.sub(r'\n\\texttt{\\textsl{\\large \1}}:',strng)
569 570 strng = cmd_name_re.sub(r'\n\\bigskip\n\\texttt{\\textbf{ \1}}:',
570 571 strng)
571 572 strng = cmd_re.sub(r'\\texttt{\g<cmd>}',strng)
572 573 strng = par_re.sub(r'\\\\',strng)
573 574 strng = escape_re.sub(r'\\\1',strng)
574 575 strng = newline_re.sub(r'\\textbackslash{}n',strng)
575 576 return strng
576 577
577 578 def parse_options(self, arg_str, opt_str, *long_opts, **kw):
578 579 """Parse options passed to an argument string.
579 580
580 581 The interface is similar to that of getopt(), but it returns back a
581 582 Struct with the options as keys and the stripped argument string still
582 583 as a string.
583 584
584 585 arg_str is quoted as a true sys.argv vector by using shlex.split.
585 586 This allows us to easily expand variables, glob files, quote
586 587 arguments, etc.
587 588
588 589 Options:
589 590 -mode: default 'string'. If given as 'list', the argument string is
590 591 returned as a list (split on whitespace) instead of a string.
591 592
592 593 -list_all: put all option values in lists. Normally only options
593 594 appearing more than once are put in a list.
594 595
595 596 -posix (True): whether to split the input line in POSIX mode or not,
596 597 as per the conventions outlined in the shlex module from the
597 598 standard library."""
598 599
599 600 # inject default options at the beginning of the input line
600 601 caller = sys._getframe(1).f_code.co_name
601 602 arg_str = '%s %s' % (self.options_table.get(caller,''),arg_str)
602 603
603 604 mode = kw.get('mode','string')
604 605 if mode not in ['string','list']:
605 606 raise ValueError('incorrect mode given: %s' % mode)
606 607 # Get options
607 608 list_all = kw.get('list_all',0)
608 609 posix = kw.get('posix', os.name == 'posix')
609 610 strict = kw.get('strict', True)
610 611
611 612 # Check if we have more than one argument to warrant extra processing:
612 613 odict = {} # Dictionary with options
613 614 args = arg_str.split()
614 615 if len(args) >= 1:
615 616 # If the list of inputs only has 0 or 1 thing in it, there's no
616 617 # need to look for options
617 618 argv = arg_split(arg_str, posix, strict)
618 619 # Do regular option processing
619 620 try:
620 621 opts,args = getopt(argv, opt_str, long_opts)
621 622 except GetoptError as e:
622 623 raise UsageError('%s ( allowed: "%s" %s)' % (e.msg,opt_str,
623 624 " ".join(long_opts)))
624 625 for o,a in opts:
625 626 if o.startswith('--'):
626 627 o = o[2:]
627 628 else:
628 629 o = o[1:]
629 630 try:
630 631 odict[o].append(a)
631 632 except AttributeError:
632 633 odict[o] = [odict[o],a]
633 634 except KeyError:
634 635 if list_all:
635 636 odict[o] = [a]
636 637 else:
637 638 odict[o] = a
638 639
639 640 # Prepare opts,args for return
640 641 opts = Struct(odict)
641 642 if mode == 'string':
642 643 args = ' '.join(args)
643 644
644 645 return opts,args
645 646
646 647 def default_option(self, fn, optstr):
647 648 """Make an entry in the options_table for fn, with value optstr"""
648 649
649 650 if fn not in self.lsmagic():
650 651 error("%s is not a magic function" % fn)
651 652 self.options_table[fn] = optstr
652 653
653 654
654 655 class MagicAlias(object):
655 656 """An alias to another magic function.
656 657
657 658 An alias is determined by its magic name and magic kind. Lookup
658 659 is done at call time, so if the underlying magic changes the alias
659 660 will call the new function.
660 661
661 662 Use the :meth:`MagicsManager.register_alias` method or the
662 663 `%alias_magic` magic function to create and register a new alias.
663 664 """
664 665 def __init__(self, shell, magic_name, magic_kind):
665 666 self.shell = shell
666 667 self.magic_name = magic_name
667 668 self.magic_kind = magic_kind
668 669
669 670 self.pretty_target = '%s%s' % (magic_escapes[self.magic_kind], self.magic_name)
670 671 self.__doc__ = "Alias for `%s`." % self.pretty_target
671 672
672 673 self._in_call = False
673 674
674 675 def __call__(self, *args, **kwargs):
675 676 """Call the magic alias."""
676 677 fn = self.shell.find_magic(self.magic_name, self.magic_kind)
677 678 if fn is None:
678 679 raise UsageError("Magic `%s` not found." % self.pretty_target)
679 680
680 681 # Protect against infinite recursion.
681 682 if self._in_call:
682 683 raise UsageError("Infinite recursion detected; "
683 684 "magic aliases cannot call themselves.")
684 685 self._in_call = True
685 686 try:
686 687 return fn(*args, **kwargs)
687 688 finally:
688 689 self._in_call = False
@@ -1,128 +1,129 b''
1 1 """Implementation of magic functions that control various automatic behaviors.
2 2 """
3 from __future__ import print_function
3 4 #-----------------------------------------------------------------------------
4 5 # Copyright (c) 2012 The IPython Development Team.
5 6 #
6 7 # Distributed under the terms of the Modified BSD License.
7 8 #
8 9 # The full license is in the file COPYING.txt, distributed with this software.
9 10 #-----------------------------------------------------------------------------
10 11
11 12 #-----------------------------------------------------------------------------
12 13 # Imports
13 14 #-----------------------------------------------------------------------------
14 15
15 16 # Our own packages
16 17 from IPython.core.magic import Bunch, Magics, magics_class, line_magic
17 18 from IPython.testing.skipdoctest import skip_doctest
18 19 from IPython.utils.warn import error
19 20
20 21 #-----------------------------------------------------------------------------
21 22 # Magic implementation classes
22 23 #-----------------------------------------------------------------------------
23 24
24 25 @magics_class
25 26 class AutoMagics(Magics):
26 27 """Magics that control various autoX behaviors."""
27 28
28 29 def __init__(self, shell):
29 30 super(AutoMagics, self).__init__(shell)
30 31 # namespace for holding state we may need
31 32 self._magic_state = Bunch()
32 33
33 34 @line_magic
34 35 def automagic(self, parameter_s=''):
35 36 """Make magic functions callable without having to type the initial %.
36 37
37 38 Without argumentsl toggles on/off (when off, you must call it as
38 39 %automagic, of course). With arguments it sets the value, and you can
39 40 use any of (case insensitive):
40 41
41 42 - on, 1, True: to activate
42 43
43 44 - off, 0, False: to deactivate.
44 45
45 46 Note that magic functions have lowest priority, so if there's a
46 47 variable whose name collides with that of a magic fn, automagic won't
47 48 work for that function (you get the variable instead). However, if you
48 49 delete the variable (del var), the previously shadowed magic function
49 50 becomes visible to automagic again."""
50 51
51 52 arg = parameter_s.lower()
52 53 mman = self.shell.magics_manager
53 54 if arg in ('on', '1', 'true'):
54 55 val = True
55 56 elif arg in ('off', '0', 'false'):
56 57 val = False
57 58 else:
58 59 val = not mman.auto_magic
59 60 mman.auto_magic = val
60 print '\n' + self.shell.magics_manager.auto_status()
61 print('\n' + self.shell.magics_manager.auto_status())
61 62
62 63 @skip_doctest
63 64 @line_magic
64 65 def autocall(self, parameter_s=''):
65 66 """Make functions callable without having to type parentheses.
66 67
67 68 Usage:
68 69
69 70 %autocall [mode]
70 71
71 72 The mode can be one of: 0->Off, 1->Smart, 2->Full. If not given, the
72 73 value is toggled on and off (remembering the previous state).
73 74
74 75 In more detail, these values mean:
75 76
76 77 0 -> fully disabled
77 78
78 79 1 -> active, but do not apply if there are no arguments on the line.
79 80
80 81 In this mode, you get::
81 82
82 83 In [1]: callable
83 84 Out[1]: <built-in function callable>
84 85
85 86 In [2]: callable 'hello'
86 87 ------> callable('hello')
87 88 Out[2]: False
88 89
89 90 2 -> Active always. Even if no arguments are present, the callable
90 91 object is called::
91 92
92 93 In [2]: float
93 94 ------> float()
94 95 Out[2]: 0.0
95 96
96 97 Note that even with autocall off, you can still use '/' at the start of
97 98 a line to treat the first argument on the command line as a function
98 99 and add parentheses to it::
99 100
100 101 In [8]: /str 43
101 102 ------> str(43)
102 103 Out[8]: '43'
103 104
104 105 # all-random (note for auto-testing)
105 106 """
106 107
107 108 if parameter_s:
108 109 arg = int(parameter_s)
109 110 else:
110 111 arg = 'toggle'
111 112
112 113 if not arg in (0, 1, 2, 'toggle'):
113 114 error('Valid modes: (0->Off, 1->Smart, 2->Full')
114 115 return
115 116
116 117 if arg in (0, 1, 2):
117 118 self.shell.autocall = arg
118 119 else: # toggle
119 120 if self.shell.autocall:
120 121 self._magic_state.autocall_save = self.shell.autocall
121 122 self.shell.autocall = 0
122 123 else:
123 124 try:
124 125 self.shell.autocall = self._magic_state.autocall_save
125 126 except AttributeError:
126 127 self.shell.autocall = self._magic_state.autocall_save = 1
127 128
128 print "Automatic calling is:",['OFF','Smart','Full'][self.shell.autocall]
129 print("Automatic calling is:",['OFF','Smart','Full'][self.shell.autocall])
@@ -1,690 +1,691 b''
1 1 """Implementation of code management magic functions.
2 2 """
3 from __future__ import print_function
3 4 #-----------------------------------------------------------------------------
4 5 # Copyright (c) 2012 The IPython Development Team.
5 6 #
6 7 # Distributed under the terms of the Modified BSD License.
7 8 #
8 9 # The full license is in the file COPYING.txt, distributed with this software.
9 10 #-----------------------------------------------------------------------------
10 11
11 12 #-----------------------------------------------------------------------------
12 13 # Imports
13 14 #-----------------------------------------------------------------------------
14 15
15 16 # Stdlib
16 17 import inspect
17 18 import io
18 19 import os
19 20 import re
20 21 import sys
21 22 import ast
22 23 from itertools import chain
23 24
24 25 # Our own packages
25 26 from IPython.core.error import TryNext, StdinNotImplementedError, UsageError
26 27 from IPython.core.macro import Macro
27 28 from IPython.core.magic import Magics, magics_class, line_magic
28 29 from IPython.core.oinspect import find_file, find_source_lines
29 30 from IPython.testing.skipdoctest import skip_doctest
30 31 from IPython.utils import py3compat
31 32 from IPython.utils.contexts import preserve_keys
32 33 from IPython.utils.path import get_py_filename, unquote_filename
33 34 from IPython.utils.warn import warn, error
34 35 from IPython.utils.text import get_text_list
35 36
36 37 #-----------------------------------------------------------------------------
37 38 # Magic implementation classes
38 39 #-----------------------------------------------------------------------------
39 40
40 41 # Used for exception handling in magic_edit
41 42 class MacroToEdit(ValueError): pass
42 43
43 44 ipython_input_pat = re.compile(r"<ipython\-input\-(\d+)-[a-z\d]+>$")
44 45
45 46 # To match, e.g. 8-10 1:5 :10 3-
46 47 range_re = re.compile(r"""
47 48 (?P<start>\d+)?
48 49 ((?P<sep>[\-:])
49 50 (?P<end>\d+)?)?
50 51 $""", re.VERBOSE)
51 52
52 53
53 54 def extract_code_ranges(ranges_str):
54 55 """Turn a string of range for %%load into 2-tuples of (start, stop)
55 56 ready to use as a slice of the content splitted by lines.
56 57
57 58 Examples
58 59 --------
59 60 list(extract_input_ranges("5-10 2"))
60 61 [(4, 10), (1, 2)]
61 62 """
62 63 for range_str in ranges_str.split():
63 64 rmatch = range_re.match(range_str)
64 65 if not rmatch:
65 66 continue
66 67 sep = rmatch.group("sep")
67 68 start = rmatch.group("start")
68 69 end = rmatch.group("end")
69 70
70 71 if sep == '-':
71 72 start = int(start) - 1 if start else None
72 73 end = int(end) if end else None
73 74 elif sep == ':':
74 75 start = int(start) - 1 if start else None
75 76 end = int(end) - 1 if end else None
76 77 else:
77 78 end = int(start)
78 79 start = int(start) - 1
79 80 yield (start, end)
80 81
81 82
82 83 @skip_doctest
83 84 def extract_symbols(code, symbols):
84 85 """
85 86 Return a tuple (blocks, not_found)
86 87 where ``blocks`` is a list of code fragments
87 88 for each symbol parsed from code, and ``not_found`` are
88 89 symbols not found in the code.
89 90
90 91 For example::
91 92
92 93 >>> code = '''a = 10
93 94
94 95 def b(): return 42
95 96
96 97 class A: pass'''
97 98
98 99 >>> extract_symbols(code, 'A,b,z')
99 100 (["class A: pass", "def b(): return 42"], ['z'])
100 101 """
101 102 symbols = symbols.split(',')
102 103
103 104 # this will raise SyntaxError if code isn't valid Python
104 105 py_code = ast.parse(code)
105 106
106 107 marks = [(getattr(s, 'name', None), s.lineno) for s in py_code.body]
107 108 code = code.split('\n')
108 109
109 110 symbols_lines = {}
110 111
111 112 # we already know the start_lineno of each symbol (marks).
112 113 # To find each end_lineno, we traverse in reverse order until each
113 114 # non-blank line
114 115 end = len(code)
115 116 for name, start in reversed(marks):
116 117 while not code[end - 1].strip():
117 118 end -= 1
118 119 if name:
119 120 symbols_lines[name] = (start - 1, end)
120 121 end = start - 1
121 122
122 123 # Now symbols_lines is a map
123 124 # {'symbol_name': (start_lineno, end_lineno), ...}
124 125
125 126 # fill a list with chunks of codes for each requested symbol
126 127 blocks = []
127 128 not_found = []
128 129 for symbol in symbols:
129 130 if symbol in symbols_lines:
130 131 start, end = symbols_lines[symbol]
131 132 blocks.append('\n'.join(code[start:end]) + '\n')
132 133 else:
133 134 not_found.append(symbol)
134 135
135 136 return blocks, not_found
136 137
137 138
138 139 class InteractivelyDefined(Exception):
139 140 """Exception for interactively defined variable in magic_edit"""
140 141 def __init__(self, index):
141 142 self.index = index
142 143
143 144
144 145 @magics_class
145 146 class CodeMagics(Magics):
146 147 """Magics related to code management (loading, saving, editing, ...)."""
147 148
148 149 @line_magic
149 150 def save(self, parameter_s=''):
150 151 """Save a set of lines or a macro to a given filename.
151 152
152 153 Usage:\\
153 154 %save [options] filename n1-n2 n3-n4 ... n5 .. n6 ...
154 155
155 156 Options:
156 157
157 158 -r: use 'raw' input. By default, the 'processed' history is used,
158 159 so that magics are loaded in their transformed version to valid
159 160 Python. If this option is given, the raw input as typed as the
160 161 command line is used instead.
161 162
162 163 -f: force overwrite. If file exists, %save will prompt for overwrite
163 164 unless -f is given.
164 165
165 166 -a: append to the file instead of overwriting it.
166 167
167 168 This function uses the same syntax as %history for input ranges,
168 169 then saves the lines to the filename you specify.
169 170
170 171 It adds a '.py' extension to the file if you don't do so yourself, and
171 172 it asks for confirmation before overwriting existing files.
172 173
173 174 If `-r` option is used, the default extension is `.ipy`.
174 175 """
175 176
176 177 opts,args = self.parse_options(parameter_s,'fra',mode='list')
177 178 if not args:
178 179 raise UsageError('Missing filename.')
179 180 raw = 'r' in opts
180 181 force = 'f' in opts
181 182 append = 'a' in opts
182 183 mode = 'a' if append else 'w'
183 184 ext = u'.ipy' if raw else u'.py'
184 185 fname, codefrom = unquote_filename(args[0]), " ".join(args[1:])
185 186 if not fname.endswith((u'.py',u'.ipy')):
186 187 fname += ext
187 188 file_exists = os.path.isfile(fname)
188 189 if file_exists and not force and not append:
189 190 try:
190 191 overwrite = self.shell.ask_yes_no('File `%s` exists. Overwrite (y/[N])? ' % fname, default='n')
191 192 except StdinNotImplementedError:
192 print "File `%s` exists. Use `%%save -f %s` to force overwrite" % (fname, parameter_s)
193 print("File `%s` exists. Use `%%save -f %s` to force overwrite" % (fname, parameter_s))
193 194 return
194 195 if not overwrite :
195 print 'Operation cancelled.'
196 print('Operation cancelled.')
196 197 return
197 198 try:
198 199 cmds = self.shell.find_user_code(codefrom,raw)
199 200 except (TypeError, ValueError) as e:
200 print e.args[0]
201 print(e.args[0])
201 202 return
202 203 out = py3compat.cast_unicode(cmds)
203 204 with io.open(fname, mode, encoding="utf-8") as f:
204 205 if not file_exists or not append:
205 206 f.write(u"# coding: utf-8\n")
206 207 f.write(out)
207 208 # make sure we end on a newline
208 209 if not out.endswith(u'\n'):
209 210 f.write(u'\n')
210 print 'The following commands were written to file `%s`:' % fname
211 print cmds
211 print('The following commands were written to file `%s`:' % fname)
212 print(cmds)
212 213
213 214 @line_magic
214 215 def pastebin(self, parameter_s=''):
215 216 """Upload code to Github's Gist paste bin, returning the URL.
216 217
217 218 Usage:\\
218 219 %pastebin [-d "Custom description"] 1-7
219 220
220 221 The argument can be an input history range, a filename, or the name of a
221 222 string or macro.
222 223
223 224 Options:
224 225
225 226 -d: Pass a custom description for the gist. The default will say
226 227 "Pasted from IPython".
227 228 """
228 229 opts, args = self.parse_options(parameter_s, 'd:')
229 230
230 231 try:
231 232 code = self.shell.find_user_code(args)
232 233 except (ValueError, TypeError) as e:
233 print e.args[0]
234 print(e.args[0])
234 235 return
235 236
236 237 from urllib2 import urlopen # Deferred import
237 238 import json
238 239 post_data = json.dumps({
239 240 "description": opts.get('d', "Pasted from IPython"),
240 241 "public": True,
241 242 "files": {
242 243 "file1.py": {
243 244 "content": code
244 245 }
245 246 }
246 247 }).encode('utf-8')
247 248
248 249 response = urlopen("https://api.github.com/gists", post_data)
249 250 response_data = json.loads(response.read().decode('utf-8'))
250 251 return response_data['html_url']
251 252
252 253 @line_magic
253 254 def loadpy(self, arg_s):
254 255 """Alias of `%load`
255 256
256 257 `%loadpy` has gained some flexibility and dropped the requirement of a `.py`
257 258 extension. So it has been renamed simply into %load. You can look at
258 259 `%load`'s docstring for more info.
259 260 """
260 261 self.load(arg_s)
261 262
262 263 @line_magic
263 264 def load(self, arg_s):
264 265 """Load code into the current frontend.
265 266
266 267 Usage:\\
267 268 %load [options] source
268 269
269 270 where source can be a filename, URL, input history range or macro
270 271
271 272 Options:
272 273 --------
273 274 -r <lines>: Specify lines or ranges of lines to load from the source.
274 275 Ranges could be specified as x-y (x..y) or in python-style x:y
275 276 (x..(y-1)). Both limits x and y can be left blank (meaning the
276 277 beginning and end of the file, respectively).
277 278
278 279 -s <symbols>: Specify function or classes to load from python source.
279 280
280 281 -y : Don't ask confirmation for loading source above 200 000 characters.
281 282
282 283 This magic command can either take a local filename, a URL, an history
283 284 range (see %history) or a macro as argument, it will prompt for
284 285 confirmation before loading source with more than 200 000 characters, unless
285 286 -y flag is passed or if the frontend does not support raw_input::
286 287
287 288 %load myscript.py
288 289 %load 7-27
289 290 %load myMacro
290 291 %load http://www.example.com/myscript.py
291 292 %load -r 5-10 myscript.py
292 293 %load -r 10-20,30,40: foo.py
293 294 %load -s MyClass,wonder_function myscript.py
294 295 """
295 296 opts,args = self.parse_options(arg_s,'ys:r:')
296 297
297 298 if not args:
298 299 raise UsageError('Missing filename, URL, input history range, '
299 300 'or macro.')
300 301
301 302 contents = self.shell.find_user_code(args)
302 303
303 304 if 's' in opts:
304 305 try:
305 306 blocks, not_found = extract_symbols(contents, opts['s'])
306 307 except SyntaxError:
307 308 # non python code
308 309 error("Unable to parse the input as valid Python code")
309 310 return
310 311
311 312 if len(not_found) == 1:
312 313 warn('The symbol `%s` was not found' % not_found[0])
313 314 elif len(not_found) > 1:
314 315 warn('The symbols %s were not found' % get_text_list(not_found,
315 316 wrap_item_with='`')
316 317 )
317 318
318 319 contents = '\n'.join(blocks)
319 320
320 321 if 'r' in opts:
321 322 ranges = opts['r'].replace(',', ' ')
322 323 lines = contents.split('\n')
323 324 slices = extract_code_ranges(ranges)
324 325 contents = [lines[slice(*slc)] for slc in slices]
325 326 contents = '\n'.join(chain.from_iterable(contents))
326 327
327 328 l = len(contents)
328 329
329 330 # 200 000 is ~ 2500 full 80 caracter lines
330 331 # so in average, more than 5000 lines
331 332 if l > 200000 and 'y' not in opts:
332 333 try:
333 334 ans = self.shell.ask_yes_no(("The text you're trying to load seems pretty big"\
334 335 " (%d characters). Continue (y/[N]) ?" % l), default='n' )
335 336 except StdinNotImplementedError:
336 337 #asume yes if raw input not implemented
337 338 ans = True
338 339
339 340 if ans is False :
340 print 'Operation cancelled.'
341 print('Operation cancelled.')
341 342 return
342 343
343 344 self.shell.set_next_input(contents)
344 345
345 346 @staticmethod
346 347 def _find_edit_target(shell, args, opts, last_call):
347 348 """Utility method used by magic_edit to find what to edit."""
348 349
349 350 def make_filename(arg):
350 351 "Make a filename from the given args"
351 352 arg = unquote_filename(arg)
352 353 try:
353 354 filename = get_py_filename(arg)
354 355 except IOError:
355 356 # If it ends with .py but doesn't already exist, assume we want
356 357 # a new file.
357 358 if arg.endswith('.py'):
358 359 filename = arg
359 360 else:
360 361 filename = None
361 362 return filename
362 363
363 364 # Set a few locals from the options for convenience:
364 365 opts_prev = 'p' in opts
365 366 opts_raw = 'r' in opts
366 367
367 368 # custom exceptions
368 369 class DataIsObject(Exception): pass
369 370
370 371 # Default line number value
371 372 lineno = opts.get('n',None)
372 373
373 374 if opts_prev:
374 375 args = '_%s' % last_call[0]
375 376 if args not in shell.user_ns:
376 377 args = last_call[1]
377 378
378 379 # by default this is done with temp files, except when the given
379 380 # arg is a filename
380 381 use_temp = True
381 382
382 383 data = ''
383 384
384 385 # First, see if the arguments should be a filename.
385 386 filename = make_filename(args)
386 387 if filename:
387 388 use_temp = False
388 389 elif args:
389 390 # Mode where user specifies ranges of lines, like in %macro.
390 391 data = shell.extract_input_lines(args, opts_raw)
391 392 if not data:
392 393 try:
393 394 # Load the parameter given as a variable. If not a string,
394 395 # process it as an object instead (below)
395 396
396 397 #print '*** args',args,'type',type(args) # dbg
397 398 data = eval(args, shell.user_ns)
398 399 if not isinstance(data, basestring):
399 400 raise DataIsObject
400 401
401 402 except (NameError,SyntaxError):
402 403 # given argument is not a variable, try as a filename
403 404 filename = make_filename(args)
404 405 if filename is None:
405 406 warn("Argument given (%s) can't be found as a variable "
406 407 "or as a filename." % args)
407 408 return (None, None, None)
408 409 use_temp = False
409 410
410 411 except DataIsObject:
411 412 # macros have a special edit function
412 413 if isinstance(data, Macro):
413 414 raise MacroToEdit(data)
414 415
415 416 # For objects, try to edit the file where they are defined
416 417 filename = find_file(data)
417 418 if filename:
418 419 if 'fakemodule' in filename.lower() and \
419 420 inspect.isclass(data):
420 421 # class created by %edit? Try to find source
421 422 # by looking for method definitions instead, the
422 423 # __module__ in those classes is FakeModule.
423 424 attrs = [getattr(data, aname) for aname in dir(data)]
424 425 for attr in attrs:
425 426 if not inspect.ismethod(attr):
426 427 continue
427 428 filename = find_file(attr)
428 429 if filename and \
429 430 'fakemodule' not in filename.lower():
430 431 # change the attribute to be the edit
431 432 # target instead
432 433 data = attr
433 434 break
434 435
435 436 m = ipython_input_pat.match(os.path.basename(filename))
436 437 if m:
437 438 raise InteractivelyDefined(int(m.groups()[0]))
438 439
439 440 datafile = 1
440 441 if filename is None:
441 442 filename = make_filename(args)
442 443 datafile = 1
443 444 if filename is not None:
444 445 # only warn about this if we get a real name
445 446 warn('Could not find file where `%s` is defined.\n'
446 447 'Opening a file named `%s`' % (args, filename))
447 448 # Now, make sure we can actually read the source (if it was
448 449 # in a temp file it's gone by now).
449 450 if datafile:
450 451 if lineno is None:
451 452 lineno = find_source_lines(data)
452 453 if lineno is None:
453 454 filename = make_filename(args)
454 455 if filename is None:
455 456 warn('The file where `%s` was defined '
456 457 'cannot be read or found.' % data)
457 458 return (None, None, None)
458 459 use_temp = False
459 460
460 461 if use_temp:
461 462 filename = shell.mktempfile(data)
462 print 'IPython will make a temporary file named:',filename
463 print('IPython will make a temporary file named:',filename)
463 464
464 465 # use last_call to remember the state of the previous call, but don't
465 466 # let it be clobbered by successive '-p' calls.
466 467 try:
467 468 last_call[0] = shell.displayhook.prompt_count
468 469 if not opts_prev:
469 470 last_call[1] = args
470 471 except:
471 472 pass
472 473
473 474
474 475 return filename, lineno, use_temp
475 476
476 477 def _edit_macro(self,mname,macro):
477 478 """open an editor with the macro data in a file"""
478 479 filename = self.shell.mktempfile(macro.value)
479 480 self.shell.hooks.editor(filename)
480 481
481 482 # and make a new macro object, to replace the old one
482 483 with open(filename) as mfile:
483 484 mvalue = mfile.read()
484 485 self.shell.user_ns[mname] = Macro(mvalue)
485 486
486 487 @skip_doctest
487 488 @line_magic
488 489 def edit(self, parameter_s='',last_call=['','']):
489 490 """Bring up an editor and execute the resulting code.
490 491
491 492 Usage:
492 493 %edit [options] [args]
493 494
494 495 %edit runs IPython's editor hook. The default version of this hook is
495 496 set to call the editor specified by your $EDITOR environment variable.
496 497 If this isn't found, it will default to vi under Linux/Unix and to
497 498 notepad under Windows. See the end of this docstring for how to change
498 499 the editor hook.
499 500
500 501 You can also set the value of this editor via the
501 502 ``TerminalInteractiveShell.editor`` option in your configuration file.
502 503 This is useful if you wish to use a different editor from your typical
503 504 default with IPython (and for Windows users who typically don't set
504 505 environment variables).
505 506
506 507 This command allows you to conveniently edit multi-line code right in
507 508 your IPython session.
508 509
509 510 If called without arguments, %edit opens up an empty editor with a
510 511 temporary file and will execute the contents of this file when you
511 512 close it (don't forget to save it!).
512 513
513 514
514 515 Options:
515 516
516 517 -n <number>: open the editor at a specified line number. By default,
517 518 the IPython editor hook uses the unix syntax 'editor +N filename', but
518 519 you can configure this by providing your own modified hook if your
519 520 favorite editor supports line-number specifications with a different
520 521 syntax.
521 522
522 523 -p: this will call the editor with the same data as the previous time
523 524 it was used, regardless of how long ago (in your current session) it
524 525 was.
525 526
526 527 -r: use 'raw' input. This option only applies to input taken from the
527 528 user's history. By default, the 'processed' history is used, so that
528 529 magics are loaded in their transformed version to valid Python. If
529 530 this option is given, the raw input as typed as the command line is
530 531 used instead. When you exit the editor, it will be executed by
531 532 IPython's own processor.
532 533
533 534 -x: do not execute the edited code immediately upon exit. This is
534 535 mainly useful if you are editing programs which need to be called with
535 536 command line arguments, which you can then do using %run.
536 537
537 538
538 539 Arguments:
539 540
540 541 If arguments are given, the following possibilities exist:
541 542
542 543 - If the argument is a filename, IPython will load that into the
543 544 editor. It will execute its contents with execfile() when you exit,
544 545 loading any code in the file into your interactive namespace.
545 546
546 547 - The arguments are ranges of input history, e.g. "7 ~1/4-6".
547 548 The syntax is the same as in the %history magic.
548 549
549 550 - If the argument is a string variable, its contents are loaded
550 551 into the editor. You can thus edit any string which contains
551 552 python code (including the result of previous edits).
552 553
553 554 - If the argument is the name of an object (other than a string),
554 555 IPython will try to locate the file where it was defined and open the
555 556 editor at the point where it is defined. You can use `%edit function`
556 557 to load an editor exactly at the point where 'function' is defined,
557 558 edit it and have the file be executed automatically.
558 559
559 560 - If the object is a macro (see %macro for details), this opens up your
560 561 specified editor with a temporary file containing the macro's data.
561 562 Upon exit, the macro is reloaded with the contents of the file.
562 563
563 564 Note: opening at an exact line is only supported under Unix, and some
564 565 editors (like kedit and gedit up to Gnome 2.8) do not understand the
565 566 '+NUMBER' parameter necessary for this feature. Good editors like
566 567 (X)Emacs, vi, jed, pico and joe all do.
567 568
568 569 After executing your code, %edit will return as output the code you
569 570 typed in the editor (except when it was an existing file). This way
570 571 you can reload the code in further invocations of %edit as a variable,
571 572 via _<NUMBER> or Out[<NUMBER>], where <NUMBER> is the prompt number of
572 573 the output.
573 574
574 575 Note that %edit is also available through the alias %ed.
575 576
576 577 This is an example of creating a simple function inside the editor and
577 578 then modifying it. First, start up the editor::
578 579
579 580 In [1]: edit
580 581 Editing... done. Executing edited code...
581 582 Out[1]: 'def foo():\\n print "foo() was defined in an editing
582 583 session"\\n'
583 584
584 585 We can then call the function foo()::
585 586
586 587 In [2]: foo()
587 588 foo() was defined in an editing session
588 589
589 590 Now we edit foo. IPython automatically loads the editor with the
590 591 (temporary) file where foo() was previously defined::
591 592
592 593 In [3]: edit foo
593 594 Editing... done. Executing edited code...
594 595
595 596 And if we call foo() again we get the modified version::
596 597
597 598 In [4]: foo()
598 599 foo() has now been changed!
599 600
600 601 Here is an example of how to edit a code snippet successive
601 602 times. First we call the editor::
602 603
603 604 In [5]: edit
604 605 Editing... done. Executing edited code...
605 606 hello
606 607 Out[5]: "print 'hello'\\n"
607 608
608 609 Now we call it again with the previous output (stored in _)::
609 610
610 611 In [6]: edit _
611 612 Editing... done. Executing edited code...
612 613 hello world
613 614 Out[6]: "print 'hello world'\\n"
614 615
615 616 Now we call it with the output #8 (stored in _8, also as Out[8])::
616 617
617 618 In [7]: edit _8
618 619 Editing... done. Executing edited code...
619 620 hello again
620 621 Out[7]: "print 'hello again'\\n"
621 622
622 623
623 624 Changing the default editor hook:
624 625
625 626 If you wish to write your own editor hook, you can put it in a
626 627 configuration file which you load at startup time. The default hook
627 628 is defined in the IPython.core.hooks module, and you can use that as a
628 629 starting example for further modifications. That file also has
629 630 general instructions on how to set a new hook for use once you've
630 631 defined it."""
631 632 opts,args = self.parse_options(parameter_s,'prxn:')
632 633
633 634 try:
634 635 filename, lineno, is_temp = self._find_edit_target(self.shell,
635 636 args, opts, last_call)
636 637 except MacroToEdit as e:
637 638 self._edit_macro(args, e.args[0])
638 639 return
639 640 except InteractivelyDefined as e:
640 print "Editing In[%i]" % e.index
641 print("Editing In[%i]" % e.index)
641 642 args = str(e.index)
642 643 filename, lineno, is_temp = self._find_edit_target(self.shell,
643 644 args, opts, last_call)
644 645 if filename is None:
645 646 # nothing was found, warnings have already been issued,
646 647 # just give up.
647 648 return
648 649
649 650 # do actual editing here
650 print 'Editing...',
651 print('Editing...', end=' ')
651 652 sys.stdout.flush()
652 653 try:
653 654 # Quote filenames that may have spaces in them
654 655 if ' ' in filename:
655 656 filename = "'%s'" % filename
656 657 self.shell.hooks.editor(filename,lineno)
657 658 except TryNext:
658 659 warn('Could not open editor')
659 660 return
660 661
661 662 # XXX TODO: should this be generalized for all string vars?
662 663 # For now, this is special-cased to blocks created by cpaste
663 664 if args.strip() == 'pasted_block':
664 665 with open(filename, 'r') as f:
665 666 self.shell.user_ns['pasted_block'] = f.read()
666 667
667 668 if 'x' in opts: # -x prevents actual execution
668 print
669 print()
669 670 else:
670 print 'done. Executing edited code...'
671 print('done. Executing edited code...')
671 672 with preserve_keys(self.shell.user_ns, '__file__'):
672 673 if not is_temp:
673 674 self.shell.user_ns['__file__'] = filename
674 675 if 'r' in opts: # Untranslated IPython code
675 676 with open(filename, 'r') as f:
676 677 source = f.read()
677 678 self.shell.run_cell(source, store_history=False)
678 679 else:
679 680 self.shell.safe_execfile(filename, self.shell.user_ns,
680 681 self.shell.user_ns)
681 682
682 683 if is_temp:
683 684 try:
684 685 return open(filename).read()
685 686 except IOError as msg:
686 687 if msg.filename == filename:
687 688 warn('File not found. Did you forget to save?')
688 689 return
689 690 else:
690 691 self.shell.showtraceback()
@@ -1,158 +1,159 b''
1 1 """Implementation of configuration-related magic functions.
2 2 """
3 from __future__ import print_function
3 4 #-----------------------------------------------------------------------------
4 5 # Copyright (c) 2012 The IPython Development Team.
5 6 #
6 7 # Distributed under the terms of the Modified BSD License.
7 8 #
8 9 # The full license is in the file COPYING.txt, distributed with this software.
9 10 #-----------------------------------------------------------------------------
10 11
11 12 #-----------------------------------------------------------------------------
12 13 # Imports
13 14 #-----------------------------------------------------------------------------
14 15
15 16 # Stdlib
16 17 import re
17 18
18 19 # Our own packages
19 20 from IPython.core.error import UsageError
20 21 from IPython.core.magic import Magics, magics_class, line_magic
21 22 from IPython.utils.warn import error
22 23
23 24 #-----------------------------------------------------------------------------
24 25 # Magic implementation classes
25 26 #-----------------------------------------------------------------------------
26 27
27 28 reg = re.compile('^\w+\.\w+$')
28 29 @magics_class
29 30 class ConfigMagics(Magics):
30 31
31 32 def __init__(self, shell):
32 33 super(ConfigMagics, self).__init__(shell)
33 34 self.configurables = []
34 35
35 36 @line_magic
36 37 def config(self, s):
37 38 """configure IPython
38 39
39 40 %config Class[.trait=value]
40 41
41 42 This magic exposes most of the IPython config system. Any
42 43 Configurable class should be able to be configured with the simple
43 44 line::
44 45
45 46 %config Class.trait=value
46 47
47 48 Where `value` will be resolved in the user's namespace, if it is an
48 49 expression or variable name.
49 50
50 51 Examples
51 52 --------
52 53
53 54 To see what classes are available for config, pass no arguments::
54 55
55 56 In [1]: %config
56 57 Available objects for config:
57 58 TerminalInteractiveShell
58 59 HistoryManager
59 60 PrefilterManager
60 61 AliasManager
61 62 IPCompleter
62 63 PromptManager
63 64 DisplayFormatter
64 65
65 66 To view what is configurable on a given class, just pass the class
66 67 name::
67 68
68 69 In [2]: %config IPCompleter
69 70 IPCompleter options
70 71 -----------------
71 72 IPCompleter.omit__names=<Enum>
72 73 Current: 2
73 74 Choices: (0, 1, 2)
74 75 Instruct the completer to omit private method names
75 76 Specifically, when completing on ``object.<tab>``.
76 77 When 2 [default]: all names that start with '_' will be excluded.
77 78 When 1: all 'magic' names (``__foo__``) will be excluded.
78 79 When 0: nothing will be excluded.
79 80 IPCompleter.merge_completions=<CBool>
80 81 Current: True
81 82 Whether to merge completion results into a single list
82 83 If False, only the completion results from the first non-empty
83 84 completer will be returned.
84 85 IPCompleter.limit_to__all__=<CBool>
85 86 Current: False
86 87 Instruct the completer to use __all__ for the completion
87 88 Specifically, when completing on ``object.<tab>``.
88 89 When True: only those names in obj.__all__ will be included.
89 90 When False [default]: the __all__ attribute is ignored
90 91 IPCompleter.greedy=<CBool>
91 92 Current: False
92 93 Activate greedy completion
93 94 This will enable completion on elements of lists, results of
94 95 function calls, etc., but can be unsafe because the code is
95 96 actually evaluated on TAB.
96 97
97 98 but the real use is in setting values::
98 99
99 100 In [3]: %config IPCompleter.greedy = True
100 101
101 102 and these values are read from the user_ns if they are variables::
102 103
103 104 In [4]: feeling_greedy=False
104 105
105 106 In [5]: %config IPCompleter.greedy = feeling_greedy
106 107
107 108 """
108 109 from IPython.config.loader import Config
109 110 # some IPython objects are Configurable, but do not yet have
110 111 # any configurable traits. Exclude them from the effects of
111 112 # this magic, as their presence is just noise:
112 113 configurables = [ c for c in self.shell.configurables
113 114 if c.__class__.class_traits(config=True) ]
114 115 classnames = [ c.__class__.__name__ for c in configurables ]
115 116
116 117 line = s.strip()
117 118 if not line:
118 119 # print available configurable names
119 print "Available objects for config:"
120 print("Available objects for config:")
120 121 for name in classnames:
121 print " ", name
122 print(" ", name)
122 123 return
123 124 elif line in classnames:
124 125 # `%config TerminalInteractiveShell` will print trait info for
125 126 # TerminalInteractiveShell
126 127 c = configurables[classnames.index(line)]
127 128 cls = c.__class__
128 129 help = cls.class_get_help(c)
129 130 # strip leading '--' from cl-args:
130 131 help = re.sub(re.compile(r'^--', re.MULTILINE), '', help)
131 print help
132 print(help)
132 133 return
133 134 elif reg.match(line):
134 135 cls, attr = line.split('.')
135 136 return getattr(configurables[classnames.index(cls)],attr)
136 137 elif '=' not in line:
137 138 msg = "Invalid config statement: %r, "\
138 139 "should be `Class.trait = value`."
139 140
140 141 ll = line.lower()
141 142 for classname in classnames:
142 143 if ll == classname.lower():
143 144 msg = msg + '\nDid you mean %s (note the case)?' % classname
144 145 break
145 146
146 147 raise UsageError( msg % line)
147 148
148 149 # otherwise, assume we are setting configurables.
149 150 # leave quotes on args when splitting, because we want
150 151 # unquoted args to eval in user_ns
151 152 cfg = Config()
152 153 exec "cfg."+line in locals(), self.shell.user_ns
153 154
154 155 for configurable in configurables:
155 156 try:
156 157 configurable.update_config(cfg)
157 158 except Exception as e:
158 159 error(e)
@@ -1,45 +1,46 b''
1 1 """Deprecated Magic functions.
2 2 """
3 from __future__ import print_function
3 4 #-----------------------------------------------------------------------------
4 5 # Copyright (c) 2012 The IPython Development Team.
5 6 #
6 7 # Distributed under the terms of the Modified BSD License.
7 8 #
8 9 # The full license is in the file COPYING.txt, distributed with this software.
9 10 #-----------------------------------------------------------------------------
10 11
11 12 #-----------------------------------------------------------------------------
12 13 # Imports
13 14 #-----------------------------------------------------------------------------
14 15
15 16 # Our own packages
16 17 from IPython.core.magic import Magics, magics_class, line_magic
17 18
18 19 #-----------------------------------------------------------------------------
19 20 # Magic implementation classes
20 21 #-----------------------------------------------------------------------------
21 22
22 23 @magics_class
23 24 class DeprecatedMagics(Magics):
24 25 """Magics slated for later removal."""
25 26
26 27 @line_magic
27 28 def install_profiles(self, parameter_s=''):
28 29 """%install_profiles has been deprecated."""
29 print '\n'.join([
30 print('\n'.join([
30 31 "%install_profiles has been deprecated.",
31 32 "Use `ipython profile list` to view available profiles.",
32 33 "Requesting a profile with `ipython profile create <name>`",
33 34 "or `ipython --profile=<name>` will start with the bundled",
34 35 "profile of that name if it exists."
35 ])
36 ]))
36 37
37 38 @line_magic
38 39 def install_default_config(self, parameter_s=''):
39 40 """%install_default_config has been deprecated."""
40 print '\n'.join([
41 print('\n'.join([
41 42 "%install_default_config has been deprecated.",
42 43 "Use `ipython profile create <name>` to initialize a profile",
43 44 "with the default config files.",
44 45 "Add `--reset` to overwrite already existing config files with defaults."
45 ])
46 ]))
@@ -1,1287 +1,1288 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Implementation of execution-related magic functions.
3 3 """
4 from __future__ import print_function
4 5 #-----------------------------------------------------------------------------
5 6 # Copyright (c) 2012 The IPython Development Team.
6 7 #
7 8 # Distributed under the terms of the Modified BSD License.
8 9 #
9 10 # The full license is in the file COPYING.txt, distributed with this software.
10 11 #-----------------------------------------------------------------------------
11 12
12 13 #-----------------------------------------------------------------------------
13 14 # Imports
14 15 #-----------------------------------------------------------------------------
15 16
16 17 # Stdlib
17 18 import __builtin__ as builtin_mod
18 19 import ast
19 20 import bdb
20 21 import os
21 22 import sys
22 23 import time
23 24 from StringIO import StringIO
24 25
25 26 # cProfile was added in Python2.5
26 27 try:
27 28 import cProfile as profile
28 29 import pstats
29 30 except ImportError:
30 31 # profile isn't bundled by default in Debian for license reasons
31 32 try:
32 33 import profile, pstats
33 34 except ImportError:
34 35 profile = pstats = None
35 36
36 37 # Our own packages
37 38 from IPython.core import debugger, oinspect
38 39 from IPython.core import magic_arguments
39 40 from IPython.core import page
40 41 from IPython.core.error import UsageError
41 42 from IPython.core.macro import Macro
42 43 from IPython.core.magic import (Magics, magics_class, line_magic, cell_magic,
43 44 line_cell_magic, on_off, needs_local_scope)
44 45 from IPython.testing.skipdoctest import skip_doctest
45 46 from IPython.utils import py3compat
46 47 from IPython.utils.contexts import preserve_keys
47 48 from IPython.utils.io import capture_output
48 49 from IPython.utils.ipstruct import Struct
49 50 from IPython.utils.module_paths import find_mod
50 51 from IPython.utils.path import get_py_filename, unquote_filename, shellglob
51 52 from IPython.utils.timing import clock, clock2
52 53 from IPython.utils.warn import warn, error
53 54
54 55
55 56 #-----------------------------------------------------------------------------
56 57 # Magic implementation classes
57 58 #-----------------------------------------------------------------------------
58 59
59 60
60 61 class TimeitResult(object):
61 62 """
62 63 Object returned by the timeit magic with info about the run.
63 64
64 65 Contain the following attributes :
65 66
66 67 loops: (int) number of loop done per measurement
67 68 repeat: (int) number of time the mesurement has been repeated
68 69 best: (float) best execusion time / number
69 70 all_runs: (list of float) execusion time of each run (in s)
70 71 compile_time: (float) time of statement compilation (s)
71 72
72 73 """
73 74
74 75 def __init__(self, loops, repeat, best, all_runs, compile_time, precision):
75 76 self.loops = loops
76 77 self.repeat = repeat
77 78 self.best = best
78 79 self.all_runs = all_runs
79 80 self.compile_time = compile_time
80 81 self._precision = precision
81 82
82 83 def _repr_pretty_(self, p , cycle):
83 84 unic = u"%d loops, best of %d: %s per loop" % (self.loops, self.repeat,
84 85 _format_time(self.best, self._precision))
85 86 p.text(u'<TimeitResult : '+unic+u'>')
86 87
87 88
88 89
89 90
90 91 @magics_class
91 92 class ExecutionMagics(Magics):
92 93 """Magics related to code execution, debugging, profiling, etc.
93 94
94 95 """
95 96
96 97 def __init__(self, shell):
97 98 super(ExecutionMagics, self).__init__(shell)
98 99 if profile is None:
99 100 self.prun = self.profile_missing_notice
100 101 # Default execution function used to actually run user code.
101 102 self.default_runner = None
102 103
103 104 def profile_missing_notice(self, *args, **kwargs):
104 105 error("""\
105 106 The profile module could not be found. It has been removed from the standard
106 107 python packages because of its non-free license. To use profiling, install the
107 108 python-profiler package from non-free.""")
108 109
109 110 @skip_doctest
110 111 @line_cell_magic
111 112 def prun(self, parameter_s='', cell=None):
112 113
113 114 """Run a statement through the python code profiler.
114 115
115 116 Usage, in line mode:
116 117 %prun [options] statement
117 118
118 119 Usage, in cell mode:
119 120 %%prun [options] [statement]
120 121 code...
121 122 code...
122 123
123 124 In cell mode, the additional code lines are appended to the (possibly
124 125 empty) statement in the first line. Cell mode allows you to easily
125 126 profile multiline blocks without having to put them in a separate
126 127 function.
127 128
128 129 The given statement (which doesn't require quote marks) is run via the
129 130 python profiler in a manner similar to the profile.run() function.
130 131 Namespaces are internally managed to work correctly; profile.run
131 132 cannot be used in IPython because it makes certain assumptions about
132 133 namespaces which do not hold under IPython.
133 134
134 135 Options:
135 136
136 137 -l <limit>
137 138 you can place restrictions on what or how much of the
138 139 profile gets printed. The limit value can be:
139 140
140 141 * A string: only information for function names containing this string
141 142 is printed.
142 143
143 144 * An integer: only these many lines are printed.
144 145
145 146 * A float (between 0 and 1): this fraction of the report is printed
146 147 (for example, use a limit of 0.4 to see the topmost 40% only).
147 148
148 149 You can combine several limits with repeated use of the option. For
149 150 example, ``-l __init__ -l 5`` will print only the topmost 5 lines of
150 151 information about class constructors.
151 152
152 153 -r
153 154 return the pstats.Stats object generated by the profiling. This
154 155 object has all the information about the profile in it, and you can
155 156 later use it for further analysis or in other functions.
156 157
157 158 -s <key>
158 159 sort profile by given key. You can provide more than one key
159 160 by using the option several times: '-s key1 -s key2 -s key3...'. The
160 161 default sorting key is 'time'.
161 162
162 163 The following is copied verbatim from the profile documentation
163 164 referenced below:
164 165
165 166 When more than one key is provided, additional keys are used as
166 167 secondary criteria when the there is equality in all keys selected
167 168 before them.
168 169
169 170 Abbreviations can be used for any key names, as long as the
170 171 abbreviation is unambiguous. The following are the keys currently
171 172 defined:
172 173
173 174 ============ =====================
174 175 Valid Arg Meaning
175 176 ============ =====================
176 177 "calls" call count
177 178 "cumulative" cumulative time
178 179 "file" file name
179 180 "module" file name
180 181 "pcalls" primitive call count
181 182 "line" line number
182 183 "name" function name
183 184 "nfl" name/file/line
184 185 "stdname" standard name
185 186 "time" internal time
186 187 ============ =====================
187 188
188 189 Note that all sorts on statistics are in descending order (placing
189 190 most time consuming items first), where as name, file, and line number
190 191 searches are in ascending order (i.e., alphabetical). The subtle
191 192 distinction between "nfl" and "stdname" is that the standard name is a
192 193 sort of the name as printed, which means that the embedded line
193 194 numbers get compared in an odd way. For example, lines 3, 20, and 40
194 195 would (if the file names were the same) appear in the string order
195 196 "20" "3" and "40". In contrast, "nfl" does a numeric compare of the
196 197 line numbers. In fact, sort_stats("nfl") is the same as
197 198 sort_stats("name", "file", "line").
198 199
199 200 -T <filename>
200 201 save profile results as shown on screen to a text
201 202 file. The profile is still shown on screen.
202 203
203 204 -D <filename>
204 205 save (via dump_stats) profile statistics to given
205 206 filename. This data is in a format understood by the pstats module, and
206 207 is generated by a call to the dump_stats() method of profile
207 208 objects. The profile is still shown on screen.
208 209
209 210 -q
210 211 suppress output to the pager. Best used with -T and/or -D above.
211 212
212 213 If you want to run complete programs under the profiler's control, use
213 214 ``%run -p [prof_opts] filename.py [args to program]`` where prof_opts
214 215 contains profiler specific options as described here.
215 216
216 217 You can read the complete documentation for the profile module with::
217 218
218 219 In [1]: import profile; profile.help()
219 220 """
220 221 opts, arg_str = self.parse_options(parameter_s, 'D:l:rs:T:q',
221 222 list_all=True, posix=False)
222 223 if cell is not None:
223 224 arg_str += '\n' + cell
224 225 arg_str = self.shell.input_splitter.transform_cell(arg_str)
225 226 return self._run_with_profiler(arg_str, opts, self.shell.user_ns)
226 227
227 228 def _run_with_profiler(self, code, opts, namespace):
228 229 """
229 230 Run `code` with profiler. Used by ``%prun`` and ``%run -p``.
230 231
231 232 Parameters
232 233 ----------
233 234 code : str
234 235 Code to be executed.
235 236 opts : Struct
236 237 Options parsed by `self.parse_options`.
237 238 namespace : dict
238 239 A dictionary for Python namespace (e.g., `self.shell.user_ns`).
239 240
240 241 """
241 242
242 243 # Fill default values for unspecified options:
243 244 opts.merge(Struct(D=[''], l=[], s=['time'], T=['']))
244 245
245 246 prof = profile.Profile()
246 247 try:
247 248 prof = prof.runctx(code, namespace, namespace)
248 249 sys_exit = ''
249 250 except SystemExit:
250 251 sys_exit = """*** SystemExit exception caught in code being profiled."""
251 252
252 253 stats = pstats.Stats(prof).strip_dirs().sort_stats(*opts.s)
253 254
254 255 lims = opts.l
255 256 if lims:
256 257 lims = [] # rebuild lims with ints/floats/strings
257 258 for lim in opts.l:
258 259 try:
259 260 lims.append(int(lim))
260 261 except ValueError:
261 262 try:
262 263 lims.append(float(lim))
263 264 except ValueError:
264 265 lims.append(lim)
265 266
266 267 # Trap output.
267 268 stdout_trap = StringIO()
268 269 stats_stream = stats.stream
269 270 try:
270 271 stats.stream = stdout_trap
271 272 stats.print_stats(*lims)
272 273 finally:
273 274 stats.stream = stats_stream
274 275
275 276 output = stdout_trap.getvalue()
276 277 output = output.rstrip()
277 278
278 279 if 'q' not in opts:
279 280 page.page(output)
280 print sys_exit,
281 print(sys_exit, end=' ')
281 282
282 283 dump_file = opts.D[0]
283 284 text_file = opts.T[0]
284 285 if dump_file:
285 286 dump_file = unquote_filename(dump_file)
286 287 prof.dump_stats(dump_file)
287 print '\n*** Profile stats marshalled to file',\
288 repr(dump_file)+'.',sys_exit
288 print('\n*** Profile stats marshalled to file',\
289 repr(dump_file)+'.',sys_exit)
289 290 if text_file:
290 291 text_file = unquote_filename(text_file)
291 292 pfile = open(text_file,'w')
292 293 pfile.write(output)
293 294 pfile.close()
294 print '\n*** Profile printout saved to text file',\
295 repr(text_file)+'.',sys_exit
295 print('\n*** Profile printout saved to text file',\
296 repr(text_file)+'.',sys_exit)
296 297
297 298 if 'r' in opts:
298 299 return stats
299 300 else:
300 301 return None
301 302
302 303 @line_magic
303 304 def pdb(self, parameter_s=''):
304 305 """Control the automatic calling of the pdb interactive debugger.
305 306
306 307 Call as '%pdb on', '%pdb 1', '%pdb off' or '%pdb 0'. If called without
307 308 argument it works as a toggle.
308 309
309 310 When an exception is triggered, IPython can optionally call the
310 311 interactive pdb debugger after the traceback printout. %pdb toggles
311 312 this feature on and off.
312 313
313 314 The initial state of this feature is set in your configuration
314 315 file (the option is ``InteractiveShell.pdb``).
315 316
316 317 If you want to just activate the debugger AFTER an exception has fired,
317 318 without having to type '%pdb on' and rerunning your code, you can use
318 319 the %debug magic."""
319 320
320 321 par = parameter_s.strip().lower()
321 322
322 323 if par:
323 324 try:
324 325 new_pdb = {'off':0,'0':0,'on':1,'1':1}[par]
325 326 except KeyError:
326 327 print ('Incorrect argument. Use on/1, off/0, '
327 328 'or nothing for a toggle.')
328 329 return
329 330 else:
330 331 # toggle
331 332 new_pdb = not self.shell.call_pdb
332 333
333 334 # set on the shell
334 335 self.shell.call_pdb = new_pdb
335 print 'Automatic pdb calling has been turned',on_off(new_pdb)
336 print('Automatic pdb calling has been turned',on_off(new_pdb))
336 337
337 338 @skip_doctest
338 339 @magic_arguments.magic_arguments()
339 340 @magic_arguments.argument('--breakpoint', '-b', metavar='FILE:LINE',
340 341 help="""
341 342 Set break point at LINE in FILE.
342 343 """
343 344 )
344 345 @magic_arguments.argument('statement', nargs='*',
345 346 help="""
346 347 Code to run in debugger.
347 348 You can omit this in cell magic mode.
348 349 """
349 350 )
350 351 @line_cell_magic
351 352 def debug(self, line='', cell=None):
352 353 """Activate the interactive debugger.
353 354
354 355 This magic command support two ways of activating debugger.
355 356 One is to activate debugger before executing code. This way, you
356 357 can set a break point, to step through the code from the point.
357 358 You can use this mode by giving statements to execute and optionally
358 359 a breakpoint.
359 360
360 361 The other one is to activate debugger in post-mortem mode. You can
361 362 activate this mode simply running %debug without any argument.
362 363 If an exception has just occurred, this lets you inspect its stack
363 364 frames interactively. Note that this will always work only on the last
364 365 traceback that occurred, so you must call this quickly after an
365 366 exception that you wish to inspect has fired, because if another one
366 367 occurs, it clobbers the previous one.
367 368
368 369 If you want IPython to automatically do this on every exception, see
369 370 the %pdb magic for more details.
370 371 """
371 372 args = magic_arguments.parse_argstring(self.debug, line)
372 373
373 374 if not (args.breakpoint or args.statement or cell):
374 375 self._debug_post_mortem()
375 376 else:
376 377 code = "\n".join(args.statement)
377 378 if cell:
378 379 code += "\n" + cell
379 380 self._debug_exec(code, args.breakpoint)
380 381
381 382 def _debug_post_mortem(self):
382 383 self.shell.debugger(force=True)
383 384
384 385 def _debug_exec(self, code, breakpoint):
385 386 if breakpoint:
386 387 (filename, bp_line) = breakpoint.split(':', 1)
387 388 bp_line = int(bp_line)
388 389 else:
389 390 (filename, bp_line) = (None, None)
390 391 self._run_with_debugger(code, self.shell.user_ns, filename, bp_line)
391 392
392 393 @line_magic
393 394 def tb(self, s):
394 395 """Print the last traceback with the currently active exception mode.
395 396
396 397 See %xmode for changing exception reporting modes."""
397 398 self.shell.showtraceback()
398 399
399 400 @skip_doctest
400 401 @line_magic
401 402 def run(self, parameter_s='', runner=None,
402 403 file_finder=get_py_filename):
403 404 """Run the named file inside IPython as a program.
404 405
405 406 Usage::
406 407
407 408 %run [-n -i -e -G]
408 409 [( -t [-N<N>] | -d [-b<N>] | -p [profile options] )]
409 410 ( -m mod | file ) [args]
410 411
411 412 Parameters after the filename are passed as command-line arguments to
412 413 the program (put in sys.argv). Then, control returns to IPython's
413 414 prompt.
414 415
415 416 This is similar to running at a system prompt ``python file args``,
416 417 but with the advantage of giving you IPython's tracebacks, and of
417 418 loading all variables into your interactive namespace for further use
418 419 (unless -p is used, see below).
419 420
420 421 The file is executed in a namespace initially consisting only of
421 422 ``__name__=='__main__'`` and sys.argv constructed as indicated. It thus
422 423 sees its environment as if it were being run as a stand-alone program
423 424 (except for sharing global objects such as previously imported
424 425 modules). But after execution, the IPython interactive namespace gets
425 426 updated with all variables defined in the program (except for __name__
426 427 and sys.argv). This allows for very convenient loading of code for
427 428 interactive work, while giving each program a 'clean sheet' to run in.
428 429
429 430 Arguments are expanded using shell-like glob match. Patterns
430 431 '*', '?', '[seq]' and '[!seq]' can be used. Additionally,
431 432 tilde '~' will be expanded into user's home directory. Unlike
432 433 real shells, quotation does not suppress expansions. Use
433 434 *two* back slashes (e.g. ``\\\\*``) to suppress expansions.
434 435 To completely disable these expansions, you can use -G flag.
435 436
436 437 Options:
437 438
438 439 -n
439 440 __name__ is NOT set to '__main__', but to the running file's name
440 441 without extension (as python does under import). This allows running
441 442 scripts and reloading the definitions in them without calling code
442 443 protected by an ``if __name__ == "__main__"`` clause.
443 444
444 445 -i
445 446 run the file in IPython's namespace instead of an empty one. This
446 447 is useful if you are experimenting with code written in a text editor
447 448 which depends on variables defined interactively.
448 449
449 450 -e
450 451 ignore sys.exit() calls or SystemExit exceptions in the script
451 452 being run. This is particularly useful if IPython is being used to
452 453 run unittests, which always exit with a sys.exit() call. In such
453 454 cases you are interested in the output of the test results, not in
454 455 seeing a traceback of the unittest module.
455 456
456 457 -t
457 458 print timing information at the end of the run. IPython will give
458 459 you an estimated CPU time consumption for your script, which under
459 460 Unix uses the resource module to avoid the wraparound problems of
460 461 time.clock(). Under Unix, an estimate of time spent on system tasks
461 462 is also given (for Windows platforms this is reported as 0.0).
462 463
463 464 If -t is given, an additional ``-N<N>`` option can be given, where <N>
464 465 must be an integer indicating how many times you want the script to
465 466 run. The final timing report will include total and per run results.
466 467
467 468 For example (testing the script uniq_stable.py)::
468 469
469 470 In [1]: run -t uniq_stable
470 471
471 472 IPython CPU timings (estimated):
472 473 User : 0.19597 s.
473 474 System: 0.0 s.
474 475
475 476 In [2]: run -t -N5 uniq_stable
476 477
477 478 IPython CPU timings (estimated):
478 479 Total runs performed: 5
479 480 Times : Total Per run
480 481 User : 0.910862 s, 0.1821724 s.
481 482 System: 0.0 s, 0.0 s.
482 483
483 484 -d
484 485 run your program under the control of pdb, the Python debugger.
485 486 This allows you to execute your program step by step, watch variables,
486 487 etc. Internally, what IPython does is similar to calling::
487 488
488 489 pdb.run('execfile("YOURFILENAME")')
489 490
490 491 with a breakpoint set on line 1 of your file. You can change the line
491 492 number for this automatic breakpoint to be <N> by using the -bN option
492 493 (where N must be an integer). For example::
493 494
494 495 %run -d -b40 myscript
495 496
496 497 will set the first breakpoint at line 40 in myscript.py. Note that
497 498 the first breakpoint must be set on a line which actually does
498 499 something (not a comment or docstring) for it to stop execution.
499 500
500 501 Or you can specify a breakpoint in a different file::
501 502
502 503 %run -d -b myotherfile.py:20 myscript
503 504
504 505 When the pdb debugger starts, you will see a (Pdb) prompt. You must
505 506 first enter 'c' (without quotes) to start execution up to the first
506 507 breakpoint.
507 508
508 509 Entering 'help' gives information about the use of the debugger. You
509 510 can easily see pdb's full documentation with "import pdb;pdb.help()"
510 511 at a prompt.
511 512
512 513 -p
513 514 run program under the control of the Python profiler module (which
514 515 prints a detailed report of execution times, function calls, etc).
515 516
516 517 You can pass other options after -p which affect the behavior of the
517 518 profiler itself. See the docs for %prun for details.
518 519
519 520 In this mode, the program's variables do NOT propagate back to the
520 521 IPython interactive namespace (because they remain in the namespace
521 522 where the profiler executes them).
522 523
523 524 Internally this triggers a call to %prun, see its documentation for
524 525 details on the options available specifically for profiling.
525 526
526 527 There is one special usage for which the text above doesn't apply:
527 528 if the filename ends with .ipy, the file is run as ipython script,
528 529 just as if the commands were written on IPython prompt.
529 530
530 531 -m
531 532 specify module name to load instead of script path. Similar to
532 533 the -m option for the python interpreter. Use this option last if you
533 534 want to combine with other %run options. Unlike the python interpreter
534 535 only source modules are allowed no .pyc or .pyo files.
535 536 For example::
536 537
537 538 %run -m example
538 539
539 540 will run the example module.
540 541
541 542 -G
542 543 disable shell-like glob expansion of arguments.
543 544
544 545 """
545 546
546 547 # get arguments and set sys.argv for program to be run.
547 548 opts, arg_lst = self.parse_options(parameter_s,
548 549 'nidtN:b:pD:l:rs:T:em:G',
549 550 mode='list', list_all=1)
550 551 if "m" in opts:
551 552 modulename = opts["m"][0]
552 553 modpath = find_mod(modulename)
553 554 if modpath is None:
554 555 warn('%r is not a valid modulename on sys.path'%modulename)
555 556 return
556 557 arg_lst = [modpath] + arg_lst
557 558 try:
558 559 filename = file_finder(arg_lst[0])
559 560 except IndexError:
560 561 warn('you must provide at least a filename.')
561 print '\n%run:\n', oinspect.getdoc(self.run)
562 print('\n%run:\n', oinspect.getdoc(self.run))
562 563 return
563 564 except IOError as e:
564 565 try:
565 566 msg = str(e)
566 567 except UnicodeError:
567 568 msg = e.message
568 569 error(msg)
569 570 return
570 571
571 572 if filename.lower().endswith('.ipy'):
572 573 with preserve_keys(self.shell.user_ns, '__file__'):
573 574 self.shell.user_ns['__file__'] = filename
574 575 self.shell.safe_execfile_ipy(filename)
575 576 return
576 577
577 578 # Control the response to exit() calls made by the script being run
578 579 exit_ignore = 'e' in opts
579 580
580 581 # Make sure that the running script gets a proper sys.argv as if it
581 582 # were run from a system shell.
582 583 save_argv = sys.argv # save it for later restoring
583 584
584 585 if 'G' in opts:
585 586 args = arg_lst[1:]
586 587 else:
587 588 # tilde and glob expansion
588 589 args = shellglob(map(os.path.expanduser, arg_lst[1:]))
589 590
590 591 sys.argv = [filename] + args # put in the proper filename
591 592 # protect sys.argv from potential unicode strings on Python 2:
592 593 if not py3compat.PY3:
593 594 sys.argv = [ py3compat.cast_bytes(a) for a in sys.argv ]
594 595
595 596 if 'i' in opts:
596 597 # Run in user's interactive namespace
597 598 prog_ns = self.shell.user_ns
598 599 __name__save = self.shell.user_ns['__name__']
599 600 prog_ns['__name__'] = '__main__'
600 601 main_mod = self.shell.user_module
601 602
602 603 # Since '%run foo' emulates 'python foo.py' at the cmd line, we must
603 604 # set the __file__ global in the script's namespace
604 605 # TK: Is this necessary in interactive mode?
605 606 prog_ns['__file__'] = filename
606 607 else:
607 608 # Run in a fresh, empty namespace
608 609 if 'n' in opts:
609 610 name = os.path.splitext(os.path.basename(filename))[0]
610 611 else:
611 612 name = '__main__'
612 613
613 614 # The shell MUST hold a reference to prog_ns so after %run
614 615 # exits, the python deletion mechanism doesn't zero it out
615 616 # (leaving dangling references). See interactiveshell for details
616 617 main_mod = self.shell.new_main_mod(filename, name)
617 618 prog_ns = main_mod.__dict__
618 619
619 620 # pickle fix. See interactiveshell for an explanation. But we need to
620 621 # make sure that, if we overwrite __main__, we replace it at the end
621 622 main_mod_name = prog_ns['__name__']
622 623
623 624 if main_mod_name == '__main__':
624 625 restore_main = sys.modules['__main__']
625 626 else:
626 627 restore_main = False
627 628
628 629 # This needs to be undone at the end to prevent holding references to
629 630 # every single object ever created.
630 631 sys.modules[main_mod_name] = main_mod
631 632
632 633 if 'p' in opts or 'd' in opts:
633 634 if 'm' in opts:
634 635 code = 'run_module(modulename, prog_ns)'
635 636 code_ns = {
636 637 'run_module': self.shell.safe_run_module,
637 638 'prog_ns': prog_ns,
638 639 'modulename': modulename,
639 640 }
640 641 else:
641 642 code = 'execfile(filename, prog_ns)'
642 643 code_ns = {
643 644 'execfile': self.shell.safe_execfile,
644 645 'prog_ns': prog_ns,
645 646 'filename': get_py_filename(filename),
646 647 }
647 648
648 649 try:
649 650 stats = None
650 651 with self.shell.readline_no_record:
651 652 if 'p' in opts:
652 653 stats = self._run_with_profiler(code, opts, code_ns)
653 654 else:
654 655 if 'd' in opts:
655 656 bp_file, bp_line = parse_breakpoint(
656 657 opts.get('b', ['1'])[0], filename)
657 658 self._run_with_debugger(
658 659 code, code_ns, filename, bp_line, bp_file)
659 660 else:
660 661 if 'm' in opts:
661 662 def run():
662 663 self.shell.safe_run_module(modulename, prog_ns)
663 664 else:
664 665 if runner is None:
665 666 runner = self.default_runner
666 667 if runner is None:
667 668 runner = self.shell.safe_execfile
668 669
669 670 def run():
670 671 runner(filename, prog_ns, prog_ns,
671 672 exit_ignore=exit_ignore)
672 673
673 674 if 't' in opts:
674 675 # timed execution
675 676 try:
676 677 nruns = int(opts['N'][0])
677 678 if nruns < 1:
678 679 error('Number of runs must be >=1')
679 680 return
680 681 except (KeyError):
681 682 nruns = 1
682 683 self._run_with_timing(run, nruns)
683 684 else:
684 685 # regular execution
685 686 run()
686 687
687 688 if 'i' in opts:
688 689 self.shell.user_ns['__name__'] = __name__save
689 690 else:
690 691 # update IPython interactive namespace
691 692
692 693 # Some forms of read errors on the file may mean the
693 694 # __name__ key was never set; using pop we don't have to
694 695 # worry about a possible KeyError.
695 696 prog_ns.pop('__name__', None)
696 697
697 698 with preserve_keys(self.shell.user_ns, '__file__'):
698 699 self.shell.user_ns.update(prog_ns)
699 700 finally:
700 701 # It's a bit of a mystery why, but __builtins__ can change from
701 702 # being a module to becoming a dict missing some key data after
702 703 # %run. As best I can see, this is NOT something IPython is doing
703 704 # at all, and similar problems have been reported before:
704 705 # http://coding.derkeiler.com/Archive/Python/comp.lang.python/2004-10/0188.html
705 706 # Since this seems to be done by the interpreter itself, the best
706 707 # we can do is to at least restore __builtins__ for the user on
707 708 # exit.
708 709 self.shell.user_ns['__builtins__'] = builtin_mod
709 710
710 711 # Ensure key global structures are restored
711 712 sys.argv = save_argv
712 713 if restore_main:
713 714 sys.modules['__main__'] = restore_main
714 715 else:
715 716 # Remove from sys.modules the reference to main_mod we'd
716 717 # added. Otherwise it will trap references to objects
717 718 # contained therein.
718 719 del sys.modules[main_mod_name]
719 720
720 721 return stats
721 722
722 723 def _run_with_debugger(self, code, code_ns, filename=None,
723 724 bp_line=None, bp_file=None):
724 725 """
725 726 Run `code` in debugger with a break point.
726 727
727 728 Parameters
728 729 ----------
729 730 code : str
730 731 Code to execute.
731 732 code_ns : dict
732 733 A namespace in which `code` is executed.
733 734 filename : str
734 735 `code` is ran as if it is in `filename`.
735 736 bp_line : int, optional
736 737 Line number of the break point.
737 738 bp_file : str, optional
738 739 Path to the file in which break point is specified.
739 740 `filename` is used if not given.
740 741
741 742 Raises
742 743 ------
743 744 UsageError
744 745 If the break point given by `bp_line` is not valid.
745 746
746 747 """
747 748 deb = debugger.Pdb(self.shell.colors)
748 749 # reset Breakpoint state, which is moronically kept
749 750 # in a class
750 751 bdb.Breakpoint.next = 1
751 752 bdb.Breakpoint.bplist = {}
752 753 bdb.Breakpoint.bpbynumber = [None]
753 754 if bp_line is not None:
754 755 # Set an initial breakpoint to stop execution
755 756 maxtries = 10
756 757 bp_file = bp_file or filename
757 758 checkline = deb.checkline(bp_file, bp_line)
758 759 if not checkline:
759 760 for bp in range(bp_line + 1, bp_line + maxtries + 1):
760 761 if deb.checkline(bp_file, bp):
761 762 break
762 763 else:
763 764 msg = ("\nI failed to find a valid line to set "
764 765 "a breakpoint\n"
765 766 "after trying up to line: %s.\n"
766 767 "Please set a valid breakpoint manually "
767 768 "with the -b option." % bp)
768 769 raise UsageError(msg)
769 770 # if we find a good linenumber, set the breakpoint
770 771 deb.do_break('%s:%s' % (bp_file, bp_line))
771 772
772 773 if filename:
773 774 # Mimic Pdb._runscript(...)
774 775 deb._wait_for_mainpyfile = True
775 776 deb.mainpyfile = deb.canonic(filename)
776 777
777 778 # Start file run
778 print "NOTE: Enter 'c' at the %s prompt to continue execution." % deb.prompt
779 print("NOTE: Enter 'c' at the %s prompt to continue execution." % deb.prompt)
779 780 try:
780 781 if filename:
781 782 # save filename so it can be used by methods on the deb object
782 783 deb._exec_filename = filename
783 784 deb.run(code, code_ns)
784 785
785 786 except:
786 787 etype, value, tb = sys.exc_info()
787 788 # Skip three frames in the traceback: the %run one,
788 789 # one inside bdb.py, and the command-line typed by the
789 790 # user (run by exec in pdb itself).
790 791 self.shell.InteractiveTB(etype, value, tb, tb_offset=3)
791 792
792 793 @staticmethod
793 794 def _run_with_timing(run, nruns):
794 795 """
795 796 Run function `run` and print timing information.
796 797
797 798 Parameters
798 799 ----------
799 800 run : callable
800 801 Any callable object which takes no argument.
801 802 nruns : int
802 803 Number of times to execute `run`.
803 804
804 805 """
805 806 twall0 = time.time()
806 807 if nruns == 1:
807 808 t0 = clock2()
808 809 run()
809 810 t1 = clock2()
810 811 t_usr = t1[0] - t0[0]
811 812 t_sys = t1[1] - t0[1]
812 print "\nIPython CPU timings (estimated):"
813 print " User : %10.2f s." % t_usr
814 print " System : %10.2f s." % t_sys
813 print("\nIPython CPU timings (estimated):")
814 print(" User : %10.2f s." % t_usr)
815 print(" System : %10.2f s." % t_sys)
815 816 else:
816 817 runs = range(nruns)
817 818 t0 = clock2()
818 819 for nr in runs:
819 820 run()
820 821 t1 = clock2()
821 822 t_usr = t1[0] - t0[0]
822 823 t_sys = t1[1] - t0[1]
823 print "\nIPython CPU timings (estimated):"
824 print "Total runs performed:", nruns
825 print " Times : %10s %10s" % ('Total', 'Per run')
826 print " User : %10.2f s, %10.2f s." % (t_usr, t_usr / nruns)
827 print " System : %10.2f s, %10.2f s." % (t_sys, t_sys / nruns)
824 print("\nIPython CPU timings (estimated):")
825 print("Total runs performed:", nruns)
826 print(" Times : %10s %10s" % ('Total', 'Per run'))
827 print(" User : %10.2f s, %10.2f s." % (t_usr, t_usr / nruns))
828 print(" System : %10.2f s, %10.2f s." % (t_sys, t_sys / nruns))
828 829 twall1 = time.time()
829 print "Wall time: %10.2f s." % (twall1 - twall0)
830 print("Wall time: %10.2f s." % (twall1 - twall0))
830 831
831 832 @skip_doctest
832 833 @line_cell_magic
833 834 def timeit(self, line='', cell=None):
834 835 """Time execution of a Python statement or expression
835 836
836 837 Usage, in line mode:
837 838 %timeit [-n<N> -r<R> [-t|-c] -q -p<P> -o] statement
838 839 or in cell mode:
839 840 %%timeit [-n<N> -r<R> [-t|-c] -q -p<P> -o] setup_code
840 841 code
841 842 code...
842 843
843 844 Time execution of a Python statement or expression using the timeit
844 845 module. This function can be used both as a line and cell magic:
845 846
846 847 - In line mode you can time a single-line statement (though multiple
847 848 ones can be chained with using semicolons).
848 849
849 850 - In cell mode, the statement in the first line is used as setup code
850 851 (executed but not timed) and the body of the cell is timed. The cell
851 852 body has access to any variables created in the setup code.
852 853
853 854 Options:
854 855 -n<N>: execute the given statement <N> times in a loop. If this value
855 856 is not given, a fitting value is chosen.
856 857
857 858 -r<R>: repeat the loop iteration <R> times and take the best result.
858 859 Default: 3
859 860
860 861 -t: use time.time to measure the time, which is the default on Unix.
861 862 This function measures wall time.
862 863
863 864 -c: use time.clock to measure the time, which is the default on
864 865 Windows and measures wall time. On Unix, resource.getrusage is used
865 866 instead and returns the CPU user time.
866 867
867 868 -p<P>: use a precision of <P> digits to display the timing result.
868 869 Default: 3
869 870
870 871 -q: Quiet, do not print result.
871 872
872 873 -o: return a TimeitResult that can be stored in a variable to inspect
873 874 the result in more details.
874 875
875 876
876 877 Examples
877 878 --------
878 879 ::
879 880
880 881 In [1]: %timeit pass
881 882 10000000 loops, best of 3: 53.3 ns per loop
882 883
883 884 In [2]: u = None
884 885
885 886 In [3]: %timeit u is None
886 887 10000000 loops, best of 3: 184 ns per loop
887 888
888 889 In [4]: %timeit -r 4 u == None
889 890 1000000 loops, best of 4: 242 ns per loop
890 891
891 892 In [5]: import time
892 893
893 894 In [6]: %timeit -n1 time.sleep(2)
894 895 1 loops, best of 3: 2 s per loop
895 896
896 897
897 898 The times reported by %timeit will be slightly higher than those
898 899 reported by the timeit.py script when variables are accessed. This is
899 900 due to the fact that %timeit executes the statement in the namespace
900 901 of the shell, compared with timeit.py, which uses a single setup
901 902 statement to import function or create variables. Generally, the bias
902 903 does not matter as long as results from timeit.py are not mixed with
903 904 those from %timeit."""
904 905
905 906 import timeit
906 907
907 908 opts, stmt = self.parse_options(line,'n:r:tcp:qo',
908 909 posix=False, strict=False)
909 910 if stmt == "" and cell is None:
910 911 return
911 912
912 913 timefunc = timeit.default_timer
913 914 number = int(getattr(opts, "n", 0))
914 915 repeat = int(getattr(opts, "r", timeit.default_repeat))
915 916 precision = int(getattr(opts, "p", 3))
916 917 quiet = 'q' in opts
917 918 return_result = 'o' in opts
918 919 if hasattr(opts, "t"):
919 920 timefunc = time.time
920 921 if hasattr(opts, "c"):
921 922 timefunc = clock
922 923
923 924 timer = timeit.Timer(timer=timefunc)
924 925 # this code has tight coupling to the inner workings of timeit.Timer,
925 926 # but is there a better way to achieve that the code stmt has access
926 927 # to the shell namespace?
927 928 transform = self.shell.input_splitter.transform_cell
928 929
929 930 if cell is None:
930 931 # called as line magic
931 932 ast_setup = ast.parse("pass")
932 933 ast_stmt = ast.parse(transform(stmt))
933 934 else:
934 935 ast_setup = ast.parse(transform(stmt))
935 936 ast_stmt = ast.parse(transform(cell))
936 937
937 938 ast_setup = self.shell.transform_ast(ast_setup)
938 939 ast_stmt = self.shell.transform_ast(ast_stmt)
939 940
940 941 # This codestring is taken from timeit.template - we fill it in as an
941 942 # AST, so that we can apply our AST transformations to the user code
942 943 # without affecting the timing code.
943 944 timeit_ast_template = ast.parse('def inner(_it, _timer):\n'
944 945 ' setup\n'
945 946 ' _t0 = _timer()\n'
946 947 ' for _i in _it:\n'
947 948 ' stmt\n'
948 949 ' _t1 = _timer()\n'
949 950 ' return _t1 - _t0\n')
950 951
951 952 class TimeitTemplateFiller(ast.NodeTransformer):
952 953 "This is quite tightly tied to the template definition above."
953 954 def visit_FunctionDef(self, node):
954 955 "Fill in the setup statement"
955 956 self.generic_visit(node)
956 957 if node.name == "inner":
957 958 node.body[:1] = ast_setup.body
958 959
959 960 return node
960 961
961 962 def visit_For(self, node):
962 963 "Fill in the statement to be timed"
963 964 if getattr(getattr(node.body[0], 'value', None), 'id', None) == 'stmt':
964 965 node.body = ast_stmt.body
965 966 return node
966 967
967 968 timeit_ast = TimeitTemplateFiller().visit(timeit_ast_template)
968 969 timeit_ast = ast.fix_missing_locations(timeit_ast)
969 970
970 971 # Track compilation time so it can be reported if too long
971 972 # Minimum time above which compilation time will be reported
972 973 tc_min = 0.1
973 974
974 975 t0 = clock()
975 976 code = compile(timeit_ast, "<magic-timeit>", "exec")
976 977 tc = clock()-t0
977 978
978 979 ns = {}
979 980 exec code in self.shell.user_ns, ns
980 981 timer.inner = ns["inner"]
981 982
982 983 if number == 0:
983 984 # determine number so that 0.2 <= total time < 2.0
984 985 number = 1
985 986 for _ in range(1, 10):
986 987 if timer.timeit(number) >= 0.2:
987 988 break
988 989 number *= 10
989 990 all_runs = timer.repeat(repeat, number)
990 991 best = min(all_runs) / number
991 992 if not quiet :
992 print u"%d loops, best of %d: %s per loop" % (number, repeat,
993 _format_time(best, precision))
993 print(u"%d loops, best of %d: %s per loop" % (number, repeat,
994 _format_time(best, precision)))
994 995 if tc > tc_min:
995 print "Compiler time: %.2f s" % tc
996 print("Compiler time: %.2f s" % tc)
996 997 if return_result:
997 998 return TimeitResult(number, repeat, best, all_runs, tc, precision)
998 999
999 1000 @skip_doctest
1000 1001 @needs_local_scope
1001 1002 @line_cell_magic
1002 1003 def time(self,line='', cell=None, local_ns=None):
1003 1004 """Time execution of a Python statement or expression.
1004 1005
1005 1006 The CPU and wall clock times are printed, and the value of the
1006 1007 expression (if any) is returned. Note that under Win32, system time
1007 1008 is always reported as 0, since it can not be measured.
1008 1009
1009 1010 This function can be used both as a line and cell magic:
1010 1011
1011 1012 - In line mode you can time a single-line statement (though multiple
1012 1013 ones can be chained with using semicolons).
1013 1014
1014 1015 - In cell mode, you can time the cell body (a directly
1015 1016 following statement raises an error).
1016 1017
1017 1018 This function provides very basic timing functionality. Use the timeit
1018 1019 magic for more controll over the measurement.
1019 1020
1020 1021 Examples
1021 1022 --------
1022 1023 ::
1023 1024
1024 1025 In [1]: %time 2**128
1025 1026 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1026 1027 Wall time: 0.00
1027 1028 Out[1]: 340282366920938463463374607431768211456L
1028 1029
1029 1030 In [2]: n = 1000000
1030 1031
1031 1032 In [3]: %time sum(range(n))
1032 1033 CPU times: user 1.20 s, sys: 0.05 s, total: 1.25 s
1033 1034 Wall time: 1.37
1034 1035 Out[3]: 499999500000L
1035 1036
1036 1037 In [4]: %time print 'hello world'
1037 1038 hello world
1038 1039 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1039 1040 Wall time: 0.00
1040 1041
1041 1042 Note that the time needed by Python to compile the given expression
1042 1043 will be reported if it is more than 0.1s. In this example, the
1043 1044 actual exponentiation is done by Python at compilation time, so while
1044 1045 the expression can take a noticeable amount of time to compute, that
1045 1046 time is purely due to the compilation:
1046 1047
1047 1048 In [5]: %time 3**9999;
1048 1049 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1049 1050 Wall time: 0.00 s
1050 1051
1051 1052 In [6]: %time 3**999999;
1052 1053 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1053 1054 Wall time: 0.00 s
1054 1055 Compiler : 0.78 s
1055 1056 """
1056 1057
1057 1058 # fail immediately if the given expression can't be compiled
1058 1059
1059 1060 if line and cell:
1060 1061 raise UsageError("Can't use statement directly after '%%time'!")
1061 1062
1062 1063 if cell:
1063 1064 expr = self.shell.input_transformer_manager.transform_cell(cell)
1064 1065 else:
1065 1066 expr = self.shell.input_transformer_manager.transform_cell(line)
1066 1067
1067 1068 # Minimum time above which parse time will be reported
1068 1069 tp_min = 0.1
1069 1070
1070 1071 t0 = clock()
1071 1072 expr_ast = ast.parse(expr)
1072 1073 tp = clock()-t0
1073 1074
1074 1075 # Apply AST transformations
1075 1076 expr_ast = self.shell.transform_ast(expr_ast)
1076 1077
1077 1078 # Minimum time above which compilation time will be reported
1078 1079 tc_min = 0.1
1079 1080
1080 1081 if len(expr_ast.body)==1 and isinstance(expr_ast.body[0], ast.Expr):
1081 1082 mode = 'eval'
1082 1083 source = '<timed eval>'
1083 1084 expr_ast = ast.Expression(expr_ast.body[0].value)
1084 1085 else:
1085 1086 mode = 'exec'
1086 1087 source = '<timed exec>'
1087 1088 t0 = clock()
1088 1089 code = compile(expr_ast, source, mode)
1089 1090 tc = clock()-t0
1090 1091
1091 1092 # skew measurement as little as possible
1092 1093 glob = self.shell.user_ns
1093 1094 wtime = time.time
1094 1095 # time execution
1095 1096 wall_st = wtime()
1096 1097 if mode=='eval':
1097 1098 st = clock2()
1098 1099 out = eval(code, glob, local_ns)
1099 1100 end = clock2()
1100 1101 else:
1101 1102 st = clock2()
1102 1103 exec code in glob, local_ns
1103 1104 end = clock2()
1104 1105 out = None
1105 1106 wall_end = wtime()
1106 1107 # Compute actual times and report
1107 1108 wall_time = wall_end-wall_st
1108 1109 cpu_user = end[0]-st[0]
1109 1110 cpu_sys = end[1]-st[1]
1110 1111 cpu_tot = cpu_user+cpu_sys
1111 1112 # On windows cpu_sys is always zero, so no new information to the next print
1112 1113 if sys.platform != 'win32':
1113 print "CPU times: user %s, sys: %s, total: %s" % \
1114 (_format_time(cpu_user),_format_time(cpu_sys),_format_time(cpu_tot))
1115 print "Wall time: %s" % _format_time(wall_time)
1114 print("CPU times: user %s, sys: %s, total: %s" % \
1115 (_format_time(cpu_user),_format_time(cpu_sys),_format_time(cpu_tot)))
1116 print("Wall time: %s" % _format_time(wall_time))
1116 1117 if tc > tc_min:
1117 print "Compiler : %s" % _format_time(tc)
1118 print("Compiler : %s" % _format_time(tc))
1118 1119 if tp > tp_min:
1119 print "Parser : %s" % _format_time(tp)
1120 print("Parser : %s" % _format_time(tp))
1120 1121 return out
1121 1122
1122 1123 @skip_doctest
1123 1124 @line_magic
1124 1125 def macro(self, parameter_s=''):
1125 1126 """Define a macro for future re-execution. It accepts ranges of history,
1126 1127 filenames or string objects.
1127 1128
1128 1129 Usage:\\
1129 1130 %macro [options] name n1-n2 n3-n4 ... n5 .. n6 ...
1130 1131
1131 1132 Options:
1132 1133
1133 1134 -r: use 'raw' input. By default, the 'processed' history is used,
1134 1135 so that magics are loaded in their transformed version to valid
1135 1136 Python. If this option is given, the raw input as typed at the
1136 1137 command line is used instead.
1137 1138
1138 1139 -q: quiet macro definition. By default, a tag line is printed
1139 1140 to indicate the macro has been created, and then the contents of
1140 1141 the macro are printed. If this option is given, then no printout
1141 1142 is produced once the macro is created.
1142 1143
1143 1144 This will define a global variable called `name` which is a string
1144 1145 made of joining the slices and lines you specify (n1,n2,... numbers
1145 1146 above) from your input history into a single string. This variable
1146 1147 acts like an automatic function which re-executes those lines as if
1147 1148 you had typed them. You just type 'name' at the prompt and the code
1148 1149 executes.
1149 1150
1150 1151 The syntax for indicating input ranges is described in %history.
1151 1152
1152 1153 Note: as a 'hidden' feature, you can also use traditional python slice
1153 1154 notation, where N:M means numbers N through M-1.
1154 1155
1155 1156 For example, if your history contains (print using %hist -n )::
1156 1157
1157 1158 44: x=1
1158 1159 45: y=3
1159 1160 46: z=x+y
1160 1161 47: print x
1161 1162 48: a=5
1162 1163 49: print 'x',x,'y',y
1163 1164
1164 1165 you can create a macro with lines 44 through 47 (included) and line 49
1165 1166 called my_macro with::
1166 1167
1167 1168 In [55]: %macro my_macro 44-47 49
1168 1169
1169 1170 Now, typing `my_macro` (without quotes) will re-execute all this code
1170 1171 in one pass.
1171 1172
1172 1173 You don't need to give the line-numbers in order, and any given line
1173 1174 number can appear multiple times. You can assemble macros with any
1174 1175 lines from your input history in any order.
1175 1176
1176 1177 The macro is a simple object which holds its value in an attribute,
1177 1178 but IPython's display system checks for macros and executes them as
1178 1179 code instead of printing them when you type their name.
1179 1180
1180 1181 You can view a macro's contents by explicitly printing it with::
1181 1182
1182 1183 print macro_name
1183 1184
1184 1185 """
1185 1186 opts,args = self.parse_options(parameter_s,'rq',mode='list')
1186 1187 if not args: # List existing macros
1187 1188 return sorted(k for k,v in self.shell.user_ns.iteritems() if\
1188 1189 isinstance(v, Macro))
1189 1190 if len(args) == 1:
1190 1191 raise UsageError(
1191 1192 "%macro insufficient args; usage '%macro name n1-n2 n3-4...")
1192 1193 name, codefrom = args[0], " ".join(args[1:])
1193 1194
1194 1195 #print 'rng',ranges # dbg
1195 1196 try:
1196 1197 lines = self.shell.find_user_code(codefrom, 'r' in opts)
1197 1198 except (ValueError, TypeError) as e:
1198 print e.args[0]
1199 print(e.args[0])
1199 1200 return
1200 1201 macro = Macro(lines)
1201 1202 self.shell.define_macro(name, macro)
1202 1203 if not ( 'q' in opts) :
1203 print 'Macro `%s` created. To execute, type its name (without quotes).' % name
1204 print '=== Macro contents: ==='
1205 print macro,
1204 print('Macro `%s` created. To execute, type its name (without quotes).' % name)
1205 print('=== Macro contents: ===')
1206 print(macro, end=' ')
1206 1207
1207 1208 @magic_arguments.magic_arguments()
1208 1209 @magic_arguments.argument('output', type=str, default='', nargs='?',
1209 1210 help="""The name of the variable in which to store output.
1210 1211 This is a utils.io.CapturedIO object with stdout/err attributes
1211 1212 for the text of the captured output.
1212 1213
1213 1214 CapturedOutput also has a show() method for displaying the output,
1214 1215 and __call__ as well, so you can use that to quickly display the
1215 1216 output.
1216 1217
1217 1218 If unspecified, captured output is discarded.
1218 1219 """
1219 1220 )
1220 1221 @magic_arguments.argument('--no-stderr', action="store_true",
1221 1222 help="""Don't capture stderr."""
1222 1223 )
1223 1224 @magic_arguments.argument('--no-stdout', action="store_true",
1224 1225 help="""Don't capture stdout."""
1225 1226 )
1226 1227 @magic_arguments.argument('--no-display', action="store_true",
1227 1228 help="""Don't capture IPython's rich display."""
1228 1229 )
1229 1230 @cell_magic
1230 1231 def capture(self, line, cell):
1231 1232 """run the cell, capturing stdout, stderr, and IPython's rich display() calls."""
1232 1233 args = magic_arguments.parse_argstring(self.capture, line)
1233 1234 out = not args.no_stdout
1234 1235 err = not args.no_stderr
1235 1236 disp = not args.no_display
1236 1237 with capture_output(out, err, disp) as io:
1237 1238 self.shell.run_cell(cell)
1238 1239 if args.output:
1239 1240 self.shell.user_ns[args.output] = io
1240 1241
1241 1242 def parse_breakpoint(text, current_file):
1242 1243 '''Returns (file, line) for file:line and (current_file, line) for line'''
1243 1244 colon = text.find(':')
1244 1245 if colon == -1:
1245 1246 return current_file, int(text)
1246 1247 else:
1247 1248 return text[:colon], int(text[colon+1:])
1248 1249
1249 1250 def _format_time(timespan, precision=3):
1250 1251 """Formats the timespan in a human readable form"""
1251 1252 import math
1252 1253
1253 1254 if timespan >= 60.0:
1254 1255 # we have more than a minute, format that in a human readable form
1255 1256 # Idea from http://snipplr.com/view/5713/
1256 1257 parts = [("d", 60*60*24),("h", 60*60),("min", 60), ("s", 1)]
1257 1258 time = []
1258 1259 leftover = timespan
1259 1260 for suffix, length in parts:
1260 1261 value = int(leftover / length)
1261 1262 if value > 0:
1262 1263 leftover = leftover % length
1263 1264 time.append(u'%s%s' % (str(value), suffix))
1264 1265 if leftover < 1:
1265 1266 break
1266 1267 return " ".join(time)
1267 1268
1268 1269
1269 1270 # Unfortunately the unicode 'micro' symbol can cause problems in
1270 1271 # certain terminals.
1271 1272 # See bug: https://bugs.launchpad.net/ipython/+bug/348466
1272 1273 # Try to prevent crashes by being more secure than it needs to
1273 1274 # E.g. eclipse is able to print a µ, but has no sys.stdout.encoding set.
1274 1275 units = [u"s", u"ms",u'us',"ns"] # the save value
1275 1276 if hasattr(sys.stdout, 'encoding') and sys.stdout.encoding:
1276 1277 try:
1277 1278 u'\xb5'.encode(sys.stdout.encoding)
1278 1279 units = [u"s", u"ms",u'\xb5s',"ns"]
1279 1280 except:
1280 1281 pass
1281 1282 scaling = [1, 1e3, 1e6, 1e9]
1282 1283
1283 1284 if timespan > 0.0:
1284 1285 order = min(-int(math.floor(math.log10(timespan)) // 3), 3)
1285 1286 else:
1286 1287 order = 3
1287 1288 return u"%.*g %s" % (precision, timespan * scaling[order], units[order])
@@ -1,92 +1,93 b''
1 1 """Implementation of magic functions for the extension machinery.
2 2 """
3 from __future__ import print_function
3 4 #-----------------------------------------------------------------------------
4 5 # Copyright (c) 2012 The IPython Development Team.
5 6 #
6 7 # Distributed under the terms of the Modified BSD License.
7 8 #
8 9 # The full license is in the file COPYING.txt, distributed with this software.
9 10 #-----------------------------------------------------------------------------
10 11
11 12 #-----------------------------------------------------------------------------
12 13 # Imports
13 14 #-----------------------------------------------------------------------------
14 15
15 16 # Stdlib
16 17 import os
17 18
18 19 # Our own packages
19 20 from IPython.core.error import UsageError
20 21 from IPython.core.magic import Magics, magics_class, line_magic
21 22
22 23 #-----------------------------------------------------------------------------
23 24 # Magic implementation classes
24 25 #-----------------------------------------------------------------------------
25 26
26 27 @magics_class
27 28 class ExtensionMagics(Magics):
28 29 """Magics to manage the IPython extensions system."""
29 30
30 31 @line_magic
31 32 def install_ext(self, parameter_s=''):
32 33 """Download and install an extension from a URL, e.g.::
33 34
34 35 %install_ext https://bitbucket.org/birkenfeld/ipython-physics/raw/d1310a2ab15d/physics.py
35 36
36 37 The URL should point to an importable Python module - either a .py file
37 38 or a .zip file.
38 39
39 40 Parameters:
40 41
41 42 -n filename : Specify a name for the file, rather than taking it from
42 43 the URL.
43 44 """
44 45 opts, args = self.parse_options(parameter_s, 'n:')
45 46 try:
46 47 filename = self.shell.extension_manager.install_extension(args,
47 48 opts.get('n'))
48 49 except ValueError as e:
49 print e
50 print(e)
50 51 return
51 52
52 53 filename = os.path.basename(filename)
53 print "Installed %s. To use it, type:" % filename
54 print " %%load_ext %s" % os.path.splitext(filename)[0]
54 print("Installed %s. To use it, type:" % filename)
55 print(" %%load_ext %s" % os.path.splitext(filename)[0])
55 56
56 57
57 58 @line_magic
58 59 def load_ext(self, module_str):
59 60 """Load an IPython extension by its module name."""
60 61 if not module_str:
61 62 raise UsageError('Missing module name.')
62 63 res = self.shell.extension_manager.load_extension(module_str)
63 64
64 65 if res == 'already loaded':
65 print "The %s extension is already loaded. To reload it, use:" % module_str
66 print " %reload_ext", module_str
66 print("The %s extension is already loaded. To reload it, use:" % module_str)
67 print(" %reload_ext", module_str)
67 68 elif res == 'no load function':
68 print "The %s module is not an IPython extension." % module_str
69 print("The %s module is not an IPython extension." % module_str)
69 70
70 71 @line_magic
71 72 def unload_ext(self, module_str):
72 73 """Unload an IPython extension by its module name.
73 74
74 75 Not all extensions can be unloaded, only those which define an
75 76 ``unload_ipython_extension`` function.
76 77 """
77 78 if not module_str:
78 79 raise UsageError('Missing module name.')
79 80
80 81 res = self.shell.extension_manager.unload_extension(module_str)
81 82
82 83 if res == 'no unload function':
83 print "The %s extension doesn't define how to unload it." % module_str
84 print("The %s extension doesn't define how to unload it." % module_str)
84 85 elif res == "not loaded":
85 print "The %s extension is not loaded." % module_str
86 print("The %s extension is not loaded." % module_str)
86 87
87 88 @line_magic
88 89 def reload_ext(self, module_str):
89 90 """Reload an IPython extension by its module name."""
90 91 if not module_str:
91 92 raise UsageError('Missing module name.')
92 93 self.shell.extension_manager.reload_extension(module_str)
@@ -1,704 +1,705 b''
1 1 """Implementation of namespace-related magic functions.
2 2 """
3 from __future__ import print_function
3 4 #-----------------------------------------------------------------------------
4 5 # Copyright (c) 2012 The IPython Development Team.
5 6 #
6 7 # Distributed under the terms of the Modified BSD License.
7 8 #
8 9 # The full license is in the file COPYING.txt, distributed with this software.
9 10 #-----------------------------------------------------------------------------
10 11
11 12 #-----------------------------------------------------------------------------
12 13 # Imports
13 14 #-----------------------------------------------------------------------------
14 15
15 16 # Stdlib
16 17 import gc
17 18 import re
18 19 import sys
19 20
20 21 # Our own packages
21 22 from IPython.core import page
22 23 from IPython.core.error import StdinNotImplementedError, UsageError
23 24 from IPython.core.magic import Magics, magics_class, line_magic
24 25 from IPython.testing.skipdoctest import skip_doctest
25 26 from IPython.utils.encoding import DEFAULT_ENCODING
26 27 from IPython.utils.openpy import read_py_file
27 28 from IPython.utils.path import get_py_filename
28 29
29 30 #-----------------------------------------------------------------------------
30 31 # Magic implementation classes
31 32 #-----------------------------------------------------------------------------
32 33
33 34 @magics_class
34 35 class NamespaceMagics(Magics):
35 36 """Magics to manage various aspects of the user's namespace.
36 37
37 38 These include listing variables, introspecting into them, etc.
38 39 """
39 40
40 41 @line_magic
41 42 def pinfo(self, parameter_s='', namespaces=None):
42 43 """Provide detailed information about an object.
43 44
44 45 '%pinfo object' is just a synonym for object? or ?object."""
45 46
46 47 #print 'pinfo par: <%s>' % parameter_s # dbg
47 48 # detail_level: 0 -> obj? , 1 -> obj??
48 49 detail_level = 0
49 50 # We need to detect if we got called as 'pinfo pinfo foo', which can
50 51 # happen if the user types 'pinfo foo?' at the cmd line.
51 52 pinfo,qmark1,oname,qmark2 = \
52 53 re.match('(pinfo )?(\?*)(.*?)(\??$)',parameter_s).groups()
53 54 if pinfo or qmark1 or qmark2:
54 55 detail_level = 1
55 56 if "*" in oname:
56 57 self.psearch(oname)
57 58 else:
58 59 self.shell._inspect('pinfo', oname, detail_level=detail_level,
59 60 namespaces=namespaces)
60 61
61 62 @line_magic
62 63 def pinfo2(self, parameter_s='', namespaces=None):
63 64 """Provide extra detailed information about an object.
64 65
65 66 '%pinfo2 object' is just a synonym for object?? or ??object."""
66 67 self.shell._inspect('pinfo', parameter_s, detail_level=1,
67 68 namespaces=namespaces)
68 69
69 70 @skip_doctest
70 71 @line_magic
71 72 def pdef(self, parameter_s='', namespaces=None):
72 73 """Print the call signature for any callable object.
73 74
74 75 If the object is a class, print the constructor information.
75 76
76 77 Examples
77 78 --------
78 79 ::
79 80
80 81 In [3]: %pdef urllib.urlopen
81 82 urllib.urlopen(url, data=None, proxies=None)
82 83 """
83 84 self.shell._inspect('pdef',parameter_s, namespaces)
84 85
85 86 @line_magic
86 87 def pdoc(self, parameter_s='', namespaces=None):
87 88 """Print the docstring for an object.
88 89
89 90 If the given object is a class, it will print both the class and the
90 91 constructor docstrings."""
91 92 self.shell._inspect('pdoc',parameter_s, namespaces)
92 93
93 94 @line_magic
94 95 def psource(self, parameter_s='', namespaces=None):
95 96 """Print (or run through pager) the source code for an object."""
96 97 if not parameter_s:
97 98 raise UsageError('Missing object name.')
98 99 self.shell._inspect('psource',parameter_s, namespaces)
99 100
100 101 @line_magic
101 102 def pfile(self, parameter_s='', namespaces=None):
102 103 """Print (or run through pager) the file where an object is defined.
103 104
104 105 The file opens at the line where the object definition begins. IPython
105 106 will honor the environment variable PAGER if set, and otherwise will
106 107 do its best to print the file in a convenient form.
107 108
108 109 If the given argument is not an object currently defined, IPython will
109 110 try to interpret it as a filename (automatically adding a .py extension
110 111 if needed). You can thus use %pfile as a syntax highlighting code
111 112 viewer."""
112 113
113 114 # first interpret argument as an object name
114 115 out = self.shell._inspect('pfile',parameter_s, namespaces)
115 116 # if not, try the input as a filename
116 117 if out == 'not found':
117 118 try:
118 119 filename = get_py_filename(parameter_s)
119 120 except IOError as msg:
120 print msg
121 print(msg)
121 122 return
122 123 page.page(self.shell.pycolorize(read_py_file(filename, skip_encoding_cookie=False)))
123 124
124 125 @line_magic
125 126 def psearch(self, parameter_s=''):
126 127 """Search for object in namespaces by wildcard.
127 128
128 129 %psearch [options] PATTERN [OBJECT TYPE]
129 130
130 131 Note: ? can be used as a synonym for %psearch, at the beginning or at
131 132 the end: both a*? and ?a* are equivalent to '%psearch a*'. Still, the
132 133 rest of the command line must be unchanged (options come first), so
133 134 for example the following forms are equivalent
134 135
135 136 %psearch -i a* function
136 137 -i a* function?
137 138 ?-i a* function
138 139
139 140 Arguments:
140 141
141 142 PATTERN
142 143
143 144 where PATTERN is a string containing * as a wildcard similar to its
144 145 use in a shell. The pattern is matched in all namespaces on the
145 146 search path. By default objects starting with a single _ are not
146 147 matched, many IPython generated objects have a single
147 148 underscore. The default is case insensitive matching. Matching is
148 149 also done on the attributes of objects and not only on the objects
149 150 in a module.
150 151
151 152 [OBJECT TYPE]
152 153
153 154 Is the name of a python type from the types module. The name is
154 155 given in lowercase without the ending type, ex. StringType is
155 156 written string. By adding a type here only objects matching the
156 157 given type are matched. Using all here makes the pattern match all
157 158 types (this is the default).
158 159
159 160 Options:
160 161
161 162 -a: makes the pattern match even objects whose names start with a
162 163 single underscore. These names are normally omitted from the
163 164 search.
164 165
165 166 -i/-c: make the pattern case insensitive/sensitive. If neither of
166 167 these options are given, the default is read from your configuration
167 168 file, with the option ``InteractiveShell.wildcards_case_sensitive``.
168 169 If this option is not specified in your configuration file, IPython's
169 170 internal default is to do a case sensitive search.
170 171
171 172 -e/-s NAMESPACE: exclude/search a given namespace. The pattern you
172 173 specify can be searched in any of the following namespaces:
173 174 'builtin', 'user', 'user_global','internal', 'alias', where
174 175 'builtin' and 'user' are the search defaults. Note that you should
175 176 not use quotes when specifying namespaces.
176 177
177 178 'Builtin' contains the python module builtin, 'user' contains all
178 179 user data, 'alias' only contain the shell aliases and no python
179 180 objects, 'internal' contains objects used by IPython. The
180 181 'user_global' namespace is only used by embedded IPython instances,
181 182 and it contains module-level globals. You can add namespaces to the
182 183 search with -s or exclude them with -e (these options can be given
183 184 more than once).
184 185
185 186 Examples
186 187 --------
187 188 ::
188 189
189 190 %psearch a* -> objects beginning with an a
190 191 %psearch -e builtin a* -> objects NOT in the builtin space starting in a
191 192 %psearch a* function -> all functions beginning with an a
192 193 %psearch re.e* -> objects beginning with an e in module re
193 194 %psearch r*.e* -> objects that start with e in modules starting in r
194 195 %psearch r*.* string -> all strings in modules beginning with r
195 196
196 197 Case sensitive search::
197 198
198 199 %psearch -c a* list all object beginning with lower case a
199 200
200 201 Show objects beginning with a single _::
201 202
202 203 %psearch -a _* list objects beginning with a single underscore
203 204 """
204 205 try:
205 206 parameter_s.encode('ascii')
206 207 except UnicodeEncodeError:
207 print 'Python identifiers can only contain ascii characters.'
208 print('Python identifiers can only contain ascii characters.')
208 209 return
209 210
210 211 # default namespaces to be searched
211 212 def_search = ['user_local', 'user_global', 'builtin']
212 213
213 214 # Process options/args
214 215 opts,args = self.parse_options(parameter_s,'cias:e:',list_all=True)
215 216 opt = opts.get
216 217 shell = self.shell
217 218 psearch = shell.inspector.psearch
218 219
219 220 # select case options
220 221 if 'i' in opts:
221 222 ignore_case = True
222 223 elif 'c' in opts:
223 224 ignore_case = False
224 225 else:
225 226 ignore_case = not shell.wildcards_case_sensitive
226 227
227 228 # Build list of namespaces to search from user options
228 229 def_search.extend(opt('s',[]))
229 230 ns_exclude = ns_exclude=opt('e',[])
230 231 ns_search = [nm for nm in def_search if nm not in ns_exclude]
231 232
232 233 # Call the actual search
233 234 try:
234 235 psearch(args,shell.ns_table,ns_search,
235 236 show_all=opt('a'),ignore_case=ignore_case)
236 237 except:
237 238 shell.showtraceback()
238 239
239 240 @skip_doctest
240 241 @line_magic
241 242 def who_ls(self, parameter_s=''):
242 243 """Return a sorted list of all interactive variables.
243 244
244 245 If arguments are given, only variables of types matching these
245 246 arguments are returned.
246 247
247 248 Examples
248 249 --------
249 250
250 251 Define two variables and list them with who_ls::
251 252
252 253 In [1]: alpha = 123
253 254
254 255 In [2]: beta = 'test'
255 256
256 257 In [3]: %who_ls
257 258 Out[3]: ['alpha', 'beta']
258 259
259 260 In [4]: %who_ls int
260 261 Out[4]: ['alpha']
261 262
262 263 In [5]: %who_ls str
263 264 Out[5]: ['beta']
264 265 """
265 266
266 267 user_ns = self.shell.user_ns
267 268 user_ns_hidden = self.shell.user_ns_hidden
268 269 nonmatching = object() # This can never be in user_ns
269 270 out = [ i for i in user_ns
270 271 if not i.startswith('_') \
271 272 and (user_ns[i] is not user_ns_hidden.get(i, nonmatching)) ]
272 273
273 274 typelist = parameter_s.split()
274 275 if typelist:
275 276 typeset = set(typelist)
276 277 out = [i for i in out if type(user_ns[i]).__name__ in typeset]
277 278
278 279 out.sort()
279 280 return out
280 281
281 282 @skip_doctest
282 283 @line_magic
283 284 def who(self, parameter_s=''):
284 285 """Print all interactive variables, with some minimal formatting.
285 286
286 287 If any arguments are given, only variables whose type matches one of
287 288 these are printed. For example::
288 289
289 290 %who function str
290 291
291 292 will only list functions and strings, excluding all other types of
292 293 variables. To find the proper type names, simply use type(var) at a
293 294 command line to see how python prints type names. For example:
294 295
295 296 ::
296 297
297 298 In [1]: type('hello')\\
298 299 Out[1]: <type 'str'>
299 300
300 301 indicates that the type name for strings is 'str'.
301 302
302 303 ``%who`` always excludes executed names loaded through your configuration
303 304 file and things which are internal to IPython.
304 305
305 306 This is deliberate, as typically you may load many modules and the
306 307 purpose of %who is to show you only what you've manually defined.
307 308
308 309 Examples
309 310 --------
310 311
311 312 Define two variables and list them with who::
312 313
313 314 In [1]: alpha = 123
314 315
315 316 In [2]: beta = 'test'
316 317
317 318 In [3]: %who
318 319 alpha beta
319 320
320 321 In [4]: %who int
321 322 alpha
322 323
323 324 In [5]: %who str
324 325 beta
325 326 """
326 327
327 328 varlist = self.who_ls(parameter_s)
328 329 if not varlist:
329 330 if parameter_s:
330 print 'No variables match your requested type.'
331 print('No variables match your requested type.')
331 332 else:
332 print 'Interactive namespace is empty.'
333 print('Interactive namespace is empty.')
333 334 return
334 335
335 336 # if we have variables, move on...
336 337 count = 0
337 338 for i in varlist:
338 print i+'\t',
339 print(i+'\t', end=' ')
339 340 count += 1
340 341 if count > 8:
341 342 count = 0
342 print
343 print
343 print()
344 print()
344 345
345 346 @skip_doctest
346 347 @line_magic
347 348 def whos(self, parameter_s=''):
348 349 """Like %who, but gives some extra information about each variable.
349 350
350 351 The same type filtering of %who can be applied here.
351 352
352 353 For all variables, the type is printed. Additionally it prints:
353 354
354 355 - For {},[],(): their length.
355 356
356 357 - For numpy arrays, a summary with shape, number of
357 358 elements, typecode and size in memory.
358 359
359 360 - Everything else: a string representation, snipping their middle if
360 361 too long.
361 362
362 363 Examples
363 364 --------
364 365
365 366 Define two variables and list them with whos::
366 367
367 368 In [1]: alpha = 123
368 369
369 370 In [2]: beta = 'test'
370 371
371 372 In [3]: %whos
372 373 Variable Type Data/Info
373 374 --------------------------------
374 375 alpha int 123
375 376 beta str test
376 377 """
377 378
378 379 varnames = self.who_ls(parameter_s)
379 380 if not varnames:
380 381 if parameter_s:
381 print 'No variables match your requested type.'
382 print('No variables match your requested type.')
382 383 else:
383 print 'Interactive namespace is empty.'
384 print('Interactive namespace is empty.')
384 385 return
385 386
386 387 # if we have variables, move on...
387 388
388 389 # for these types, show len() instead of data:
389 390 seq_types = ['dict', 'list', 'tuple']
390 391
391 392 # for numpy arrays, display summary info
392 393 ndarray_type = None
393 394 if 'numpy' in sys.modules:
394 395 try:
395 396 from numpy import ndarray
396 397 except ImportError:
397 398 pass
398 399 else:
399 400 ndarray_type = ndarray.__name__
400 401
401 402 # Find all variable names and types so we can figure out column sizes
402 403 def get_vars(i):
403 404 return self.shell.user_ns[i]
404 405
405 406 # some types are well known and can be shorter
406 407 abbrevs = {'IPython.core.macro.Macro' : 'Macro'}
407 408 def type_name(v):
408 409 tn = type(v).__name__
409 410 return abbrevs.get(tn,tn)
410 411
411 412 varlist = map(get_vars,varnames)
412 413
413 414 typelist = []
414 415 for vv in varlist:
415 416 tt = type_name(vv)
416 417
417 418 if tt=='instance':
418 419 typelist.append( abbrevs.get(str(vv.__class__),
419 420 str(vv.__class__)))
420 421 else:
421 422 typelist.append(tt)
422 423
423 424 # column labels and # of spaces as separator
424 425 varlabel = 'Variable'
425 426 typelabel = 'Type'
426 427 datalabel = 'Data/Info'
427 428 colsep = 3
428 429 # variable format strings
429 430 vformat = "{0:<{varwidth}}{1:<{typewidth}}"
430 431 aformat = "%s: %s elems, type `%s`, %s bytes"
431 432 # find the size of the columns to format the output nicely
432 433 varwidth = max(max(map(len,varnames)), len(varlabel)) + colsep
433 434 typewidth = max(max(map(len,typelist)), len(typelabel)) + colsep
434 435 # table header
435 print varlabel.ljust(varwidth) + typelabel.ljust(typewidth) + \
436 ' '+datalabel+'\n' + '-'*(varwidth+typewidth+len(datalabel)+1)
436 print(varlabel.ljust(varwidth) + typelabel.ljust(typewidth) + \
437 ' '+datalabel+'\n' + '-'*(varwidth+typewidth+len(datalabel)+1))
437 438 # and the table itself
438 439 kb = 1024
439 440 Mb = 1048576 # kb**2
440 441 for vname,var,vtype in zip(varnames,varlist,typelist):
441 print vformat.format(vname, vtype, varwidth=varwidth, typewidth=typewidth),
442 print(vformat.format(vname, vtype, varwidth=varwidth, typewidth=typewidth), end=' ')
442 443 if vtype in seq_types:
443 print "n="+str(len(var))
444 print("n="+str(len(var)))
444 445 elif vtype == ndarray_type:
445 446 vshape = str(var.shape).replace(',','').replace(' ','x')[1:-1]
446 447 if vtype==ndarray_type:
447 448 # numpy
448 449 vsize = var.size
449 450 vbytes = vsize*var.itemsize
450 451 vdtype = var.dtype
451 452
452 453 if vbytes < 100000:
453 print aformat % (vshape, vsize, vdtype, vbytes)
454 print(aformat % (vshape, vsize, vdtype, vbytes))
454 455 else:
455 print aformat % (vshape, vsize, vdtype, vbytes),
456 print(aformat % (vshape, vsize, vdtype, vbytes), end=' ')
456 457 if vbytes < Mb:
457 print '(%s kb)' % (vbytes/kb,)
458 print('(%s kb)' % (vbytes/kb,))
458 459 else:
459 print '(%s Mb)' % (vbytes/Mb,)
460 print('(%s Mb)' % (vbytes/Mb,))
460 461 else:
461 462 try:
462 463 vstr = str(var)
463 464 except UnicodeEncodeError:
464 465 vstr = unicode(var).encode(DEFAULT_ENCODING,
465 466 'backslashreplace')
466 467 except:
467 468 vstr = "<object with id %d (str() failed)>" % id(var)
468 469 vstr = vstr.replace('\n', '\\n')
469 470 if len(vstr) < 50:
470 print vstr
471 print(vstr)
471 472 else:
472 print vstr[:25] + "<...>" + vstr[-25:]
473 print(vstr[:25] + "<...>" + vstr[-25:])
473 474
474 475 @line_magic
475 476 def reset(self, parameter_s=''):
476 477 """Resets the namespace by removing all names defined by the user, if
477 478 called without arguments, or by removing some types of objects, such
478 479 as everything currently in IPython's In[] and Out[] containers (see
479 480 the parameters for details).
480 481
481 482 Parameters
482 483 ----------
483 484 -f : force reset without asking for confirmation.
484 485
485 486 -s : 'Soft' reset: Only clears your namespace, leaving history intact.
486 487 References to objects may be kept. By default (without this option),
487 488 we do a 'hard' reset, giving you a new session and removing all
488 489 references to objects from the current session.
489 490
490 491 in : reset input history
491 492
492 493 out : reset output history
493 494
494 495 dhist : reset directory history
495 496
496 497 array : reset only variables that are NumPy arrays
497 498
498 499 See Also
499 500 --------
500 501 magic_reset_selective : invoked as ``%reset_selective``
501 502
502 503 Examples
503 504 --------
504 505 ::
505 506
506 507 In [6]: a = 1
507 508
508 509 In [7]: a
509 510 Out[7]: 1
510 511
511 512 In [8]: 'a' in _ip.user_ns
512 513 Out[8]: True
513 514
514 515 In [9]: %reset -f
515 516
516 517 In [1]: 'a' in _ip.user_ns
517 518 Out[1]: False
518 519
519 520 In [2]: %reset -f in
520 521 Flushing input history
521 522
522 523 In [3]: %reset -f dhist in
523 524 Flushing directory history
524 525 Flushing input history
525 526
526 527 Notes
527 528 -----
528 529 Calling this magic from clients that do not implement standard input,
529 530 such as the ipython notebook interface, will reset the namespace
530 531 without confirmation.
531 532 """
532 533 opts, args = self.parse_options(parameter_s,'sf', mode='list')
533 534 if 'f' in opts:
534 535 ans = True
535 536 else:
536 537 try:
537 538 ans = self.shell.ask_yes_no(
538 539 "Once deleted, variables cannot be recovered. Proceed (y/[n])?",
539 540 default='n')
540 541 except StdinNotImplementedError:
541 542 ans = True
542 543 if not ans:
543 print 'Nothing done.'
544 print('Nothing done.')
544 545 return
545 546
546 547 if 's' in opts: # Soft reset
547 548 user_ns = self.shell.user_ns
548 549 for i in self.who_ls():
549 550 del(user_ns[i])
550 551 elif len(args) == 0: # Hard reset
551 552 self.shell.reset(new_session = False)
552 553
553 554 # reset in/out/dhist/array: previously extensinions/clearcmd.py
554 555 ip = self.shell
555 556 user_ns = self.shell.user_ns # local lookup, heavily used
556 557
557 558 for target in args:
558 559 target = target.lower() # make matches case insensitive
559 560 if target == 'out':
560 print "Flushing output cache (%d entries)" % len(user_ns['_oh'])
561 print("Flushing output cache (%d entries)" % len(user_ns['_oh']))
561 562 self.shell.displayhook.flush()
562 563
563 564 elif target == 'in':
564 print "Flushing input history"
565 print("Flushing input history")
565 566 pc = self.shell.displayhook.prompt_count + 1
566 567 for n in range(1, pc):
567 568 key = '_i'+repr(n)
568 569 user_ns.pop(key,None)
569 570 user_ns.update(dict(_i=u'',_ii=u'',_iii=u''))
570 571 hm = ip.history_manager
571 572 # don't delete these, as %save and %macro depending on the
572 573 # length of these lists to be preserved
573 574 hm.input_hist_parsed[:] = [''] * pc
574 575 hm.input_hist_raw[:] = [''] * pc
575 576 # hm has internal machinery for _i,_ii,_iii, clear it out
576 577 hm._i = hm._ii = hm._iii = hm._i00 = u''
577 578
578 579 elif target == 'array':
579 580 # Support cleaning up numpy arrays
580 581 try:
581 582 from numpy import ndarray
582 583 # This must be done with items and not iteritems because
583 584 # we're going to modify the dict in-place.
584 585 for x,val in user_ns.items():
585 586 if isinstance(val,ndarray):
586 587 del user_ns[x]
587 588 except ImportError:
588 print "reset array only works if Numpy is available."
589 print("reset array only works if Numpy is available.")
589 590
590 591 elif target == 'dhist':
591 print "Flushing directory history"
592 print("Flushing directory history")
592 593 del user_ns['_dh'][:]
593 594
594 595 else:
595 print "Don't know how to reset ",
596 print target + ", please run `%reset?` for details"
596 print("Don't know how to reset ", end=' ')
597 print(target + ", please run `%reset?` for details")
597 598
598 599 gc.collect()
599 600
600 601 @line_magic
601 602 def reset_selective(self, parameter_s=''):
602 603 """Resets the namespace by removing names defined by the user.
603 604
604 605 Input/Output history are left around in case you need them.
605 606
606 607 %reset_selective [-f] regex
607 608
608 609 No action is taken if regex is not included
609 610
610 611 Options
611 612 -f : force reset without asking for confirmation.
612 613
613 614 See Also
614 615 --------
615 616 magic_reset : invoked as ``%reset``
616 617
617 618 Examples
618 619 --------
619 620
620 621 We first fully reset the namespace so your output looks identical to
621 622 this example for pedagogical reasons; in practice you do not need a
622 623 full reset::
623 624
624 625 In [1]: %reset -f
625 626
626 627 Now, with a clean namespace we can make a few variables and use
627 628 ``%reset_selective`` to only delete names that match our regexp::
628 629
629 630 In [2]: a=1; b=2; c=3; b1m=4; b2m=5; b3m=6; b4m=7; b2s=8
630 631
631 632 In [3]: who_ls
632 633 Out[3]: ['a', 'b', 'b1m', 'b2m', 'b2s', 'b3m', 'b4m', 'c']
633 634
634 635 In [4]: %reset_selective -f b[2-3]m
635 636
636 637 In [5]: who_ls
637 638 Out[5]: ['a', 'b', 'b1m', 'b2s', 'b4m', 'c']
638 639
639 640 In [6]: %reset_selective -f d
640 641
641 642 In [7]: who_ls
642 643 Out[7]: ['a', 'b', 'b1m', 'b2s', 'b4m', 'c']
643 644
644 645 In [8]: %reset_selective -f c
645 646
646 647 In [9]: who_ls
647 648 Out[9]: ['a', 'b', 'b1m', 'b2s', 'b4m']
648 649
649 650 In [10]: %reset_selective -f b
650 651
651 652 In [11]: who_ls
652 653 Out[11]: ['a']
653 654
654 655 Notes
655 656 -----
656 657 Calling this magic from clients that do not implement standard input,
657 658 such as the ipython notebook interface, will reset the namespace
658 659 without confirmation.
659 660 """
660 661
661 662 opts, regex = self.parse_options(parameter_s,'f')
662 663
663 664 if 'f' in opts:
664 665 ans = True
665 666 else:
666 667 try:
667 668 ans = self.shell.ask_yes_no(
668 669 "Once deleted, variables cannot be recovered. Proceed (y/[n])? ",
669 670 default='n')
670 671 except StdinNotImplementedError:
671 672 ans = True
672 673 if not ans:
673 print 'Nothing done.'
674 print('Nothing done.')
674 675 return
675 676 user_ns = self.shell.user_ns
676 677 if not regex:
677 print 'No regex pattern specified. Nothing done.'
678 print('No regex pattern specified. Nothing done.')
678 679 return
679 680 else:
680 681 try:
681 682 m = re.compile(regex)
682 683 except TypeError:
683 684 raise TypeError('regex must be a string or compiled pattern')
684 685 for i in self.who_ls():
685 686 if m.search(i):
686 687 del(user_ns[i])
687 688
688 689 @line_magic
689 690 def xdel(self, parameter_s=''):
690 691 """Delete a variable, trying to clear it from anywhere that
691 692 IPython's machinery has references to it. By default, this uses
692 693 the identity of the named object in the user namespace to remove
693 694 references held under other names. The object is also removed
694 695 from the output history.
695 696
696 697 Options
697 698 -n : Delete the specified name from all namespaces, without
698 699 checking their identity.
699 700 """
700 701 opts, varname = self.parse_options(parameter_s,'n')
701 702 try:
702 703 self.shell.del_var(varname, ('n' in opts))
703 704 except (NameError, ValueError) as e:
704 print type(e).__name__ +": "+ str(e)
705 print(type(e).__name__ +": "+ str(e))
@@ -1,738 +1,739 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 from __future__ import print_function
6 7 #-----------------------------------------------------------------------------
7 8 # Copyright (c) 2012 The IPython Development Team.
8 9 #
9 10 # Distributed under the terms of the Modified BSD License.
10 11 #
11 12 # The full license is in the file COPYING.txt, distributed with this software.
12 13 #-----------------------------------------------------------------------------
13 14
14 15 #-----------------------------------------------------------------------------
15 16 # Imports
16 17 #-----------------------------------------------------------------------------
17 18
18 19 # Stdlib
19 20 import io
20 21 import os
21 22 import re
22 23 import sys
23 24 from pprint import pformat
24 25
25 26 # Our own packages
26 27 from IPython.core import magic_arguments
27 28 from IPython.core import oinspect
28 29 from IPython.core import page
29 30 from IPython.core.alias import AliasError, Alias
30 31 from IPython.core.error import UsageError
31 32 from IPython.core.magic import (
32 33 Magics, compress_dhist, magics_class, line_magic, cell_magic, line_cell_magic
33 34 )
34 35 from IPython.testing.skipdoctest import skip_doctest
35 36 from IPython.utils.openpy import source_to_unicode
36 37 from IPython.utils.path import unquote_filename
37 38 from IPython.utils.process import abbrev_cwd
38 39 from IPython.utils.terminal import set_term_title
39 40
40 41 #-----------------------------------------------------------------------------
41 42 # Magic implementation classes
42 43 #-----------------------------------------------------------------------------
43 44 @magics_class
44 45 class OSMagics(Magics):
45 46 """Magics to interact with the underlying OS (shell-type functionality).
46 47 """
47 48
48 49 @skip_doctest
49 50 @line_magic
50 51 def alias(self, parameter_s=''):
51 52 """Define an alias for a system command.
52 53
53 54 '%alias alias_name cmd' defines 'alias_name' as an alias for 'cmd'
54 55
55 56 Then, typing 'alias_name params' will execute the system command 'cmd
56 57 params' (from your underlying operating system).
57 58
58 59 Aliases have lower precedence than magic functions and Python normal
59 60 variables, so if 'foo' is both a Python variable and an alias, the
60 61 alias can not be executed until 'del foo' removes the Python variable.
61 62
62 63 You can use the %l specifier in an alias definition to represent the
63 64 whole line when the alias is called. For example::
64 65
65 66 In [2]: alias bracket echo "Input in brackets: <%l>"
66 67 In [3]: bracket hello world
67 68 Input in brackets: <hello world>
68 69
69 70 You can also define aliases with parameters using %s specifiers (one
70 71 per parameter)::
71 72
72 73 In [1]: alias parts echo first %s second %s
73 74 In [2]: %parts A B
74 75 first A second B
75 76 In [3]: %parts A
76 77 Incorrect number of arguments: 2 expected.
77 78 parts is an alias to: 'echo first %s second %s'
78 79
79 80 Note that %l and %s are mutually exclusive. You can only use one or
80 81 the other in your aliases.
81 82
82 83 Aliases expand Python variables just like system calls using ! or !!
83 84 do: all expressions prefixed with '$' get expanded. For details of
84 85 the semantic rules, see PEP-215:
85 86 http://www.python.org/peps/pep-0215.html. This is the library used by
86 87 IPython for variable expansion. If you want to access a true shell
87 88 variable, an extra $ is necessary to prevent its expansion by
88 89 IPython::
89 90
90 91 In [6]: alias show echo
91 92 In [7]: PATH='A Python string'
92 93 In [8]: show $PATH
93 94 A Python string
94 95 In [9]: show $$PATH
95 96 /usr/local/lf9560/bin:/usr/local/intel/compiler70/ia32/bin:...
96 97
97 98 You can use the alias facility to acess all of $PATH. See the %rehash
98 99 and %rehashx functions, which automatically create aliases for the
99 100 contents of your $PATH.
100 101
101 102 If called with no parameters, %alias prints the current alias table."""
102 103
103 104 par = parameter_s.strip()
104 105 if not par:
105 106 aliases = sorted(self.shell.alias_manager.aliases)
106 107 # stored = self.shell.db.get('stored_aliases', {} )
107 108 # for k, v in stored:
108 109 # atab.append(k, v[0])
109 110
110 print "Total number of aliases:", len(aliases)
111 print("Total number of aliases:", len(aliases))
111 112 sys.stdout.flush()
112 113 return aliases
113 114
114 115 # Now try to define a new one
115 116 try:
116 117 alias,cmd = par.split(None, 1)
117 118 except TypeError:
118 print(oinspect.getdoc(self.alias))
119 print((oinspect.getdoc(self.alias)))
119 120 return
120 121
121 122 try:
122 123 self.shell.alias_manager.define_alias(alias, cmd)
123 124 except AliasError as e:
124 125 print(e)
125 126 # end magic_alias
126 127
127 128 @line_magic
128 129 def unalias(self, parameter_s=''):
129 130 """Remove an alias"""
130 131
131 132 aname = parameter_s.strip()
132 133 try:
133 134 self.shell.alias_manager.undefine_alias(aname)
134 135 except ValueError as e:
135 136 print(e)
136 137 return
137 138
138 139 stored = self.shell.db.get('stored_aliases', {} )
139 140 if aname in stored:
140 print "Removing %stored alias",aname
141 print("Removing %stored alias",aname)
141 142 del stored[aname]
142 143 self.shell.db['stored_aliases'] = stored
143 144
144 145 @line_magic
145 146 def rehashx(self, parameter_s=''):
146 147 """Update the alias table with all executable files in $PATH.
147 148
148 149 This version explicitly checks that every entry in $PATH is a file
149 150 with execute access (os.X_OK), so it is much slower than %rehash.
150 151
151 152 Under Windows, it checks executability as a match against a
152 153 '|'-separated string of extensions, stored in the IPython config
153 154 variable win_exec_ext. This defaults to 'exe|com|bat'.
154 155
155 156 This function also resets the root module cache of module completer,
156 157 used on slow filesystems.
157 158 """
158 159 from IPython.core.alias import InvalidAliasError
159 160
160 161 # for the benefit of module completer in ipy_completers.py
161 162 del self.shell.db['rootmodules_cache']
162 163
163 164 path = [os.path.abspath(os.path.expanduser(p)) for p in
164 165 os.environ.get('PATH','').split(os.pathsep)]
165 166 path = filter(os.path.isdir,path)
166 167
167 168 syscmdlist = []
168 169 # Now define isexec in a cross platform manner.
169 170 if os.name == 'posix':
170 171 isexec = lambda fname:os.path.isfile(fname) and \
171 172 os.access(fname,os.X_OK)
172 173 else:
173 174 try:
174 175 winext = os.environ['pathext'].replace(';','|').replace('.','')
175 176 except KeyError:
176 177 winext = 'exe|com|bat|py'
177 178 if 'py' not in winext:
178 179 winext += '|py'
179 180 execre = re.compile(r'(.*)\.(%s)$' % winext,re.IGNORECASE)
180 181 isexec = lambda fname:os.path.isfile(fname) and execre.match(fname)
181 182 savedir = os.getcwdu()
182 183
183 184 # Now walk the paths looking for executables to alias.
184 185 try:
185 186 # write the whole loop for posix/Windows so we don't have an if in
186 187 # the innermost part
187 188 if os.name == 'posix':
188 189 for pdir in path:
189 190 os.chdir(pdir)
190 191 for ff in os.listdir(pdir):
191 192 if isexec(ff):
192 193 try:
193 194 # Removes dots from the name since ipython
194 195 # will assume names with dots to be python.
195 196 if not self.shell.alias_manager.is_alias(ff):
196 197 self.shell.alias_manager.define_alias(
197 198 ff.replace('.',''), ff)
198 199 except InvalidAliasError:
199 200 pass
200 201 else:
201 202 syscmdlist.append(ff)
202 203 else:
203 204 no_alias = Alias.blacklist
204 205 for pdir in path:
205 206 os.chdir(pdir)
206 207 for ff in os.listdir(pdir):
207 208 base, ext = os.path.splitext(ff)
208 209 if isexec(ff) and base.lower() not in no_alias:
209 210 if ext.lower() == '.exe':
210 211 ff = base
211 212 try:
212 213 # Removes dots from the name since ipython
213 214 # will assume names with dots to be python.
214 215 self.shell.alias_manager.define_alias(
215 216 base.lower().replace('.',''), ff)
216 217 except InvalidAliasError:
217 218 pass
218 219 syscmdlist.append(ff)
219 220 self.shell.db['syscmdlist'] = syscmdlist
220 221 finally:
221 222 os.chdir(savedir)
222 223
223 224 @skip_doctest
224 225 @line_magic
225 226 def pwd(self, parameter_s=''):
226 227 """Return the current working directory path.
227 228
228 229 Examples
229 230 --------
230 231 ::
231 232
232 233 In [9]: pwd
233 234 Out[9]: '/home/tsuser/sprint/ipython'
234 235 """
235 236 return os.getcwdu()
236 237
237 238 @skip_doctest
238 239 @line_magic
239 240 def cd(self, parameter_s=''):
240 241 """Change the current working directory.
241 242
242 243 This command automatically maintains an internal list of directories
243 244 you visit during your IPython session, in the variable _dh. The
244 245 command %dhist shows this history nicely formatted. You can also
245 246 do 'cd -<tab>' to see directory history conveniently.
246 247
247 248 Usage:
248 249
249 250 cd 'dir': changes to directory 'dir'.
250 251
251 252 cd -: changes to the last visited directory.
252 253
253 254 cd -<n>: changes to the n-th directory in the directory history.
254 255
255 256 cd --foo: change to directory that matches 'foo' in history
256 257
257 258 cd -b <bookmark_name>: jump to a bookmark set by %bookmark
258 259 (note: cd <bookmark_name> is enough if there is no
259 260 directory <bookmark_name>, but a bookmark with the name exists.)
260 261 'cd -b <tab>' allows you to tab-complete bookmark names.
261 262
262 263 Options:
263 264
264 265 -q: quiet. Do not print the working directory after the cd command is
265 266 executed. By default IPython's cd command does print this directory,
266 267 since the default prompts do not display path information.
267 268
268 269 Note that !cd doesn't work for this purpose because the shell where
269 270 !command runs is immediately discarded after executing 'command'.
270 271
271 272 Examples
272 273 --------
273 274 ::
274 275
275 276 In [10]: cd parent/child
276 277 /home/tsuser/parent/child
277 278 """
278 279
279 280 oldcwd = os.getcwdu()
280 281 numcd = re.match(r'(-)(\d+)$',parameter_s)
281 282 # jump in directory history by number
282 283 if numcd:
283 284 nn = int(numcd.group(2))
284 285 try:
285 286 ps = self.shell.user_ns['_dh'][nn]
286 287 except IndexError:
287 print 'The requested directory does not exist in history.'
288 print('The requested directory does not exist in history.')
288 289 return
289 290 else:
290 291 opts = {}
291 292 elif parameter_s.startswith('--'):
292 293 ps = None
293 294 fallback = None
294 295 pat = parameter_s[2:]
295 296 dh = self.shell.user_ns['_dh']
296 297 # first search only by basename (last component)
297 298 for ent in reversed(dh):
298 299 if pat in os.path.basename(ent) and os.path.isdir(ent):
299 300 ps = ent
300 301 break
301 302
302 303 if fallback is None and pat in ent and os.path.isdir(ent):
303 304 fallback = ent
304 305
305 306 # if we have no last part match, pick the first full path match
306 307 if ps is None:
307 308 ps = fallback
308 309
309 310 if ps is None:
310 print "No matching entry in directory history"
311 print("No matching entry in directory history")
311 312 return
312 313 else:
313 314 opts = {}
314 315
315 316
316 317 else:
317 318 #turn all non-space-escaping backslashes to slashes,
318 319 # for c:\windows\directory\names\
319 320 parameter_s = re.sub(r'\\(?! )','/', parameter_s)
320 321 opts,ps = self.parse_options(parameter_s,'qb',mode='string')
321 322 # jump to previous
322 323 if ps == '-':
323 324 try:
324 325 ps = self.shell.user_ns['_dh'][-2]
325 326 except IndexError:
326 327 raise UsageError('%cd -: No previous directory to change to.')
327 328 # jump to bookmark if needed
328 329 else:
329 330 if not os.path.isdir(ps) or 'b' in opts:
330 331 bkms = self.shell.db.get('bookmarks', {})
331 332
332 333 if ps in bkms:
333 334 target = bkms[ps]
334 print '(bookmark:%s) -> %s' % (ps, target)
335 print('(bookmark:%s) -> %s' % (ps, target))
335 336 ps = target
336 337 else:
337 338 if 'b' in opts:
338 339 raise UsageError("Bookmark '%s' not found. "
339 340 "Use '%%bookmark -l' to see your bookmarks." % ps)
340 341
341 342 # strip extra quotes on Windows, because os.chdir doesn't like them
342 343 ps = unquote_filename(ps)
343 344 # at this point ps should point to the target dir
344 345 if ps:
345 346 try:
346 347 os.chdir(os.path.expanduser(ps))
347 348 if hasattr(self.shell, 'term_title') and self.shell.term_title:
348 349 set_term_title('IPython: ' + abbrev_cwd())
349 350 except OSError:
350 print sys.exc_info()[1]
351 print(sys.exc_info()[1])
351 352 else:
352 353 cwd = os.getcwdu()
353 354 dhist = self.shell.user_ns['_dh']
354 355 if oldcwd != cwd:
355 356 dhist.append(cwd)
356 357 self.shell.db['dhist'] = compress_dhist(dhist)[-100:]
357 358
358 359 else:
359 360 os.chdir(self.shell.home_dir)
360 361 if hasattr(self.shell, 'term_title') and self.shell.term_title:
361 362 set_term_title('IPython: ' + '~')
362 363 cwd = os.getcwdu()
363 364 dhist = self.shell.user_ns['_dh']
364 365
365 366 if oldcwd != cwd:
366 367 dhist.append(cwd)
367 368 self.shell.db['dhist'] = compress_dhist(dhist)[-100:]
368 369 if not 'q' in opts and self.shell.user_ns['_dh']:
369 print self.shell.user_ns['_dh'][-1]
370 print(self.shell.user_ns['_dh'][-1])
370 371
371 372
372 373 @line_magic
373 374 def env(self, parameter_s=''):
374 375 """List environment variables."""
375 376
376 377 return dict(os.environ)
377 378
378 379 @line_magic
379 380 def pushd(self, parameter_s=''):
380 381 """Place the current dir on stack and change directory.
381 382
382 383 Usage:\\
383 384 %pushd ['dirname']
384 385 """
385 386
386 387 dir_s = self.shell.dir_stack
387 388 tgt = os.path.expanduser(unquote_filename(parameter_s))
388 389 cwd = os.getcwdu().replace(self.shell.home_dir,'~')
389 390 if tgt:
390 391 self.cd(parameter_s)
391 392 dir_s.insert(0,cwd)
392 393 return self.shell.magic('dirs')
393 394
394 395 @line_magic
395 396 def popd(self, parameter_s=''):
396 397 """Change to directory popped off the top of the stack.
397 398 """
398 399 if not self.shell.dir_stack:
399 400 raise UsageError("%popd on empty stack")
400 401 top = self.shell.dir_stack.pop(0)
401 402 self.cd(top)
402 print "popd ->",top
403 print("popd ->",top)
403 404
404 405 @line_magic
405 406 def dirs(self, parameter_s=''):
406 407 """Return the current directory stack."""
407 408
408 409 return self.shell.dir_stack
409 410
410 411 @line_magic
411 412 def dhist(self, parameter_s=''):
412 413 """Print your history of visited directories.
413 414
414 415 %dhist -> print full history\\
415 416 %dhist n -> print last n entries only\\
416 417 %dhist n1 n2 -> print entries between n1 and n2 (n2 not included)\\
417 418
418 419 This history is automatically maintained by the %cd command, and
419 420 always available as the global list variable _dh. You can use %cd -<n>
420 421 to go to directory number <n>.
421 422
422 423 Note that most of time, you should view directory history by entering
423 424 cd -<TAB>.
424 425
425 426 """
426 427
427 428 dh = self.shell.user_ns['_dh']
428 429 if parameter_s:
429 430 try:
430 431 args = map(int,parameter_s.split())
431 432 except:
432 433 self.arg_err(self.dhist)
433 434 return
434 435 if len(args) == 1:
435 436 ini,fin = max(len(dh)-(args[0]),0),len(dh)
436 437 elif len(args) == 2:
437 438 ini,fin = args
438 439 fin = min(fin, len(dh))
439 440 else:
440 441 self.arg_err(self.dhist)
441 442 return
442 443 else:
443 444 ini,fin = 0,len(dh)
444 print 'Directory history (kept in _dh)'
445 print('Directory history (kept in _dh)')
445 446 for i in range(ini, fin):
446 print "%d: %s" % (i, dh[i])
447 print("%d: %s" % (i, dh[i]))
447 448
448 449 @skip_doctest
449 450 @line_magic
450 451 def sc(self, parameter_s=''):
451 452 """Shell capture - run shell command and capture output (DEPRECATED use !).
452 453
453 454 DEPRECATED. Suboptimal, retained for backwards compatibility.
454 455
455 456 You should use the form 'var = !command' instead. Example:
456 457
457 458 "%sc -l myfiles = ls ~" should now be written as
458 459
459 460 "myfiles = !ls ~"
460 461
461 462 myfiles.s, myfiles.l and myfiles.n still apply as documented
462 463 below.
463 464
464 465 --
465 466 %sc [options] varname=command
466 467
467 468 IPython will run the given command using commands.getoutput(), and
468 469 will then update the user's interactive namespace with a variable
469 470 called varname, containing the value of the call. Your command can
470 471 contain shell wildcards, pipes, etc.
471 472
472 473 The '=' sign in the syntax is mandatory, and the variable name you
473 474 supply must follow Python's standard conventions for valid names.
474 475
475 476 (A special format without variable name exists for internal use)
476 477
477 478 Options:
478 479
479 480 -l: list output. Split the output on newlines into a list before
480 481 assigning it to the given variable. By default the output is stored
481 482 as a single string.
482 483
483 484 -v: verbose. Print the contents of the variable.
484 485
485 486 In most cases you should not need to split as a list, because the
486 487 returned value is a special type of string which can automatically
487 488 provide its contents either as a list (split on newlines) or as a
488 489 space-separated string. These are convenient, respectively, either
489 490 for sequential processing or to be passed to a shell command.
490 491
491 492 For example::
492 493
493 494 # Capture into variable a
494 495 In [1]: sc a=ls *py
495 496
496 497 # a is a string with embedded newlines
497 498 In [2]: a
498 499 Out[2]: 'setup.py\\nwin32_manual_post_install.py'
499 500
500 501 # which can be seen as a list:
501 502 In [3]: a.l
502 503 Out[3]: ['setup.py', 'win32_manual_post_install.py']
503 504
504 505 # or as a whitespace-separated string:
505 506 In [4]: a.s
506 507 Out[4]: 'setup.py win32_manual_post_install.py'
507 508
508 509 # a.s is useful to pass as a single command line:
509 510 In [5]: !wc -l $a.s
510 511 146 setup.py
511 512 130 win32_manual_post_install.py
512 513 276 total
513 514
514 515 # while the list form is useful to loop over:
515 516 In [6]: for f in a.l:
516 517 ...: !wc -l $f
517 518 ...:
518 519 146 setup.py
519 520 130 win32_manual_post_install.py
520 521
521 522 Similarly, the lists returned by the -l option are also special, in
522 523 the sense that you can equally invoke the .s attribute on them to
523 524 automatically get a whitespace-separated string from their contents::
524 525
525 526 In [7]: sc -l b=ls *py
526 527
527 528 In [8]: b
528 529 Out[8]: ['setup.py', 'win32_manual_post_install.py']
529 530
530 531 In [9]: b.s
531 532 Out[9]: 'setup.py win32_manual_post_install.py'
532 533
533 534 In summary, both the lists and strings used for output capture have
534 535 the following special attributes::
535 536
536 537 .l (or .list) : value as list.
537 538 .n (or .nlstr): value as newline-separated string.
538 539 .s (or .spstr): value as space-separated string.
539 540 """
540 541
541 542 opts,args = self.parse_options(parameter_s, 'lv')
542 543 # Try to get a variable name and command to run
543 544 try:
544 545 # the variable name must be obtained from the parse_options
545 546 # output, which uses shlex.split to strip options out.
546 547 var,_ = args.split('=', 1)
547 548 var = var.strip()
548 549 # But the command has to be extracted from the original input
549 550 # parameter_s, not on what parse_options returns, to avoid the
550 551 # quote stripping which shlex.split performs on it.
551 552 _,cmd = parameter_s.split('=', 1)
552 553 except ValueError:
553 554 var,cmd = '',''
554 555 # If all looks ok, proceed
555 556 split = 'l' in opts
556 557 out = self.shell.getoutput(cmd, split=split)
557 558 if 'v' in opts:
558 print '%s ==\n%s' % (var, pformat(out))
559 print('%s ==\n%s' % (var, pformat(out)))
559 560 if var:
560 561 self.shell.user_ns.update({var:out})
561 562 else:
562 563 return out
563 564
564 565 @line_cell_magic
565 566 def sx(self, line='', cell=None):
566 567 """Shell execute - run shell command and capture output (!! is short-hand).
567 568
568 569 %sx command
569 570
570 571 IPython will run the given command using commands.getoutput(), and
571 572 return the result formatted as a list (split on '\\n'). Since the
572 573 output is _returned_, it will be stored in ipython's regular output
573 574 cache Out[N] and in the '_N' automatic variables.
574 575
575 576 Notes:
576 577
577 578 1) If an input line begins with '!!', then %sx is automatically
578 579 invoked. That is, while::
579 580
580 581 !ls
581 582
582 583 causes ipython to simply issue system('ls'), typing::
583 584
584 585 !!ls
585 586
586 587 is a shorthand equivalent to::
587 588
588 589 %sx ls
589 590
590 591 2) %sx differs from %sc in that %sx automatically splits into a list,
591 592 like '%sc -l'. The reason for this is to make it as easy as possible
592 593 to process line-oriented shell output via further python commands.
593 594 %sc is meant to provide much finer control, but requires more
594 595 typing.
595 596
596 597 3) Just like %sc -l, this is a list with special attributes:
597 598 ::
598 599
599 600 .l (or .list) : value as list.
600 601 .n (or .nlstr): value as newline-separated string.
601 602 .s (or .spstr): value as whitespace-separated string.
602 603
603 604 This is very useful when trying to use such lists as arguments to
604 605 system commands."""
605 606
606 607 if cell is None:
607 608 # line magic
608 609 return self.shell.getoutput(line)
609 610 else:
610 611 opts,args = self.parse_options(line, '', 'out=')
611 612 output = self.shell.getoutput(cell)
612 613 out_name = opts.get('out', opts.get('o'))
613 614 if out_name:
614 615 self.shell.user_ns[out_name] = output
615 616 else:
616 617 return output
617 618
618 619 system = line_cell_magic('system')(sx)
619 620 bang = cell_magic('!')(sx)
620 621
621 622 @line_magic
622 623 def bookmark(self, parameter_s=''):
623 624 """Manage IPython's bookmark system.
624 625
625 626 %bookmark <name> - set bookmark to current dir
626 627 %bookmark <name> <dir> - set bookmark to <dir>
627 628 %bookmark -l - list all bookmarks
628 629 %bookmark -d <name> - remove bookmark
629 630 %bookmark -r - remove all bookmarks
630 631
631 632 You can later on access a bookmarked folder with::
632 633
633 634 %cd -b <name>
634 635
635 636 or simply '%cd <name>' if there is no directory called <name> AND
636 637 there is such a bookmark defined.
637 638
638 639 Your bookmarks persist through IPython sessions, but they are
639 640 associated with each profile."""
640 641
641 642 opts,args = self.parse_options(parameter_s,'drl',mode='list')
642 643 if len(args) > 2:
643 644 raise UsageError("%bookmark: too many arguments")
644 645
645 646 bkms = self.shell.db.get('bookmarks',{})
646 647
647 648 if 'd' in opts:
648 649 try:
649 650 todel = args[0]
650 651 except IndexError:
651 652 raise UsageError(
652 653 "%bookmark -d: must provide a bookmark to delete")
653 654 else:
654 655 try:
655 656 del bkms[todel]
656 657 except KeyError:
657 658 raise UsageError(
658 659 "%%bookmark -d: Can't delete bookmark '%s'" % todel)
659 660
660 661 elif 'r' in opts:
661 662 bkms = {}
662 663 elif 'l' in opts:
663 664 bks = bkms.keys()
664 665 bks.sort()
665 666 if bks:
666 667 size = max(map(len, bks))
667 668 else:
668 669 size = 0
669 670 fmt = '%-'+str(size)+'s -> %s'
670 print 'Current bookmarks:'
671 print('Current bookmarks:')
671 672 for bk in bks:
672 print fmt % (bk, bkms[bk])
673 print(fmt % (bk, bkms[bk]))
673 674 else:
674 675 if not args:
675 676 raise UsageError("%bookmark: You must specify the bookmark name")
676 677 elif len(args)==1:
677 678 bkms[args[0]] = os.getcwdu()
678 679 elif len(args)==2:
679 680 bkms[args[0]] = args[1]
680 681 self.shell.db['bookmarks'] = bkms
681 682
682 683 @line_magic
683 684 def pycat(self, parameter_s=''):
684 685 """Show a syntax-highlighted file through a pager.
685 686
686 687 This magic is similar to the cat utility, but it will assume the file
687 688 to be Python source and will show it with syntax highlighting.
688 689
689 690 This magic command can either take a local filename, an url,
690 691 an history range (see %history) or a macro as argument ::
691 692
692 693 %pycat myscript.py
693 694 %pycat 7-27
694 695 %pycat myMacro
695 696 %pycat http://www.example.com/myscript.py
696 697 """
697 698 if not parameter_s:
698 699 raise UsageError('Missing filename, URL, input history range, '
699 700 'or macro.')
700 701
701 702 try :
702 703 cont = self.shell.find_user_code(parameter_s, skip_encoding_cookie=False)
703 704 except (ValueError, IOError):
704 print "Error: no such file, variable, URL, history range or macro"
705 print("Error: no such file, variable, URL, history range or macro")
705 706 return
706 707
707 708 page.page(self.shell.pycolorize(source_to_unicode(cont)))
708 709
709 710 @magic_arguments.magic_arguments()
710 711 @magic_arguments.argument(
711 712 '-a', '--append', action='store_true', default=False,
712 713 help='Append contents of the cell to an existing file. '
713 714 'The file will be created if it does not exist.'
714 715 )
715 716 @magic_arguments.argument(
716 717 'filename', type=unicode,
717 718 help='file to write'
718 719 )
719 720 @cell_magic
720 721 def writefile(self, line, cell):
721 722 """Write the contents of the cell to a file.
722 723
723 724 The file will be overwritten unless the -a (--append) flag is specified.
724 725 """
725 726 args = magic_arguments.parse_argstring(self.writefile, line)
726 727 filename = os.path.expanduser(unquote_filename(args.filename))
727 728
728 729 if os.path.exists(filename):
729 730 if args.append:
730 print "Appending to %s" % filename
731 print("Appending to %s" % filename)
731 732 else:
732 print "Overwriting %s" % filename
733 print("Overwriting %s" % filename)
733 734 else:
734 print "Writing %s" % filename
735 print("Writing %s" % filename)
735 736
736 737 mode = 'a' if args.append else 'w'
737 738 with io.open(filename, mode, encoding='utf-8') as f:
738 739 f.write(cell)
@@ -1,143 +1,144 b''
1 1 """Implementation of magic functions for matplotlib/pylab support.
2 2 """
3 from __future__ import print_function
3 4 #-----------------------------------------------------------------------------
4 5 # Copyright (c) 2012 The IPython Development Team.
5 6 #
6 7 # Distributed under the terms of the Modified BSD License.
7 8 #
8 9 # The full license is in the file COPYING.txt, distributed with this software.
9 10 #-----------------------------------------------------------------------------
10 11
11 12 #-----------------------------------------------------------------------------
12 13 # Imports
13 14 #-----------------------------------------------------------------------------
14 15
15 16 # Our own packages
16 17 from IPython.config.application import Application
17 18 from IPython.core import magic_arguments
18 19 from IPython.core.magic import Magics, magics_class, line_magic
19 20 from IPython.testing.skipdoctest import skip_doctest
20 21 from IPython.utils.warn import warn
21 22 from IPython.core.pylabtools import backends
22 23
23 24 #-----------------------------------------------------------------------------
24 25 # Magic implementation classes
25 26 #-----------------------------------------------------------------------------
26 27
27 28 magic_gui_arg = magic_arguments.argument(
28 29 'gui', nargs='?',
29 30 help="""Name of the matplotlib backend to use %s.
30 31 If given, the corresponding matplotlib backend is used,
31 32 otherwise it will be matplotlib's default
32 33 (which you can set in your matplotlib config file).
33 34 """ % str(tuple(sorted(backends.keys())))
34 35 )
35 36
36 37
37 38 @magics_class
38 39 class PylabMagics(Magics):
39 40 """Magics related to matplotlib's pylab support"""
40 41
41 42 @skip_doctest
42 43 @line_magic
43 44 @magic_arguments.magic_arguments()
44 45 @magic_gui_arg
45 46 def matplotlib(self, line=''):
46 47 """Set up matplotlib to work interactively.
47 48
48 49 This function lets you activate matplotlib interactive support
49 50 at any point during an IPython session.
50 51 It does not import anything into the interactive namespace.
51 52
52 53 If you are using the inline matplotlib backend for embedded figures,
53 54 you can adjust its behavior via the %config magic::
54 55
55 56 # enable SVG figures, necessary for SVG+XHTML export in the qtconsole
56 57 In [1]: %config InlineBackend.figure_format = 'svg'
57 58
58 59 # change the behavior of closing all figures at the end of each
59 60 # execution (cell), or allowing reuse of active figures across
60 61 # cells:
61 62 In [2]: %config InlineBackend.close_figures = False
62 63
63 64 Examples
64 65 --------
65 66 In this case, where the MPL default is TkAgg::
66 67
67 68 In [2]: %matplotlib
68 69 Using matplotlib backend: TkAgg
69 70
70 71 But you can explicitly request a different backend::
71 72
72 73 In [3]: %matplotlib qt
73 74 """
74 75 args = magic_arguments.parse_argstring(self.matplotlib, line)
75 76 gui, backend = self.shell.enable_matplotlib(args.gui)
76 77 self._show_matplotlib_backend(args.gui, backend)
77 78
78 79 @skip_doctest
79 80 @line_magic
80 81 @magic_arguments.magic_arguments()
81 82 @magic_arguments.argument(
82 83 '--no-import-all', action='store_true', default=None,
83 84 help="""Prevent IPython from performing ``import *`` into the interactive namespace.
84 85
85 86 You can govern the default behavior of this flag with the
86 87 InteractiveShellApp.pylab_import_all configurable.
87 88 """
88 89 )
89 90 @magic_gui_arg
90 91 def pylab(self, line=''):
91 92 """Load numpy and matplotlib to work interactively.
92 93
93 94 This function lets you activate pylab (matplotlib, numpy and
94 95 interactive support) at any point during an IPython session.
95 96
96 97 %pylab makes the following imports::
97 98
98 99 import numpy
99 100 import matplotlib
100 101 from matplotlib import pylab, mlab, pyplot
101 102 np = numpy
102 103 plt = pyplot
103 104
104 105 from IPython.display import display
105 106 from IPython.core.pylabtools import figsize, getfigs
106 107
107 108 from pylab import *
108 109 from numpy import *
109 110
110 111 If you pass `--no-import-all`, the last two `*` imports will be excluded.
111 112
112 113 See the %matplotlib magic for more details about activating matplotlib
113 114 without affecting the interactive namespace.
114 115 """
115 116 args = magic_arguments.parse_argstring(self.pylab, line)
116 117 if args.no_import_all is None:
117 118 # get default from Application
118 119 if Application.initialized():
119 120 app = Application.instance()
120 121 try:
121 122 import_all = app.pylab_import_all
122 123 except AttributeError:
123 124 import_all = True
124 125 else:
125 126 # nothing specified, no app - default True
126 127 import_all = True
127 128 else:
128 129 # invert no-import flag
129 130 import_all = not args.no_import_all
130 131
131 132 gui, backend, clobbered = self.shell.enable_pylab(args.gui, import_all=import_all)
132 133 self._show_matplotlib_backend(args.gui, backend)
133 134 print ("Populating the interactive namespace from numpy and matplotlib")
134 135 if clobbered:
135 136 warn("pylab import has clobbered these variables: %s" % clobbered +
136 137 "\n`%pylab --no-import-all` prevents importing * from pylab and numpy"
137 138 )
138 139
139 140 def _show_matplotlib_backend(self, gui, backend):
140 141 """show matplotlib message backend message"""
141 142 if not gui or gui == 'auto':
142 print ("Using matplotlib backend: %s" % backend)
143 print(("Using matplotlib backend: %s" % backend))
143 144
@@ -1,279 +1,280 b''
1 1 """Magic functions for running cells in various scripts."""
2 from __future__ import print_function
2 3 #-----------------------------------------------------------------------------
3 4 # Copyright (c) 2012 The IPython Development Team.
4 5 #
5 6 # Distributed under the terms of the Modified BSD License.
6 7 #
7 8 # The full license is in the file COPYING.txt, distributed with this software.
8 9 #-----------------------------------------------------------------------------
9 10
10 11 #-----------------------------------------------------------------------------
11 12 # Imports
12 13 #-----------------------------------------------------------------------------
13 14
14 15 # Stdlib
15 16 import errno
16 17 import os
17 18 import sys
18 19 import signal
19 20 import time
20 21 from subprocess import Popen, PIPE
21 22 import atexit
22 23
23 24 # Our own packages
24 25 from IPython.config.configurable import Configurable
25 26 from IPython.core import magic_arguments
26 27 from IPython.core.magic import (
27 28 Magics, magics_class, line_magic, cell_magic
28 29 )
29 30 from IPython.lib.backgroundjobs import BackgroundJobManager
30 31 from IPython.utils import py3compat
31 32 from IPython.utils.process import arg_split
32 33 from IPython.utils.traitlets import List, Dict
33 34
34 35 #-----------------------------------------------------------------------------
35 36 # Magic implementation classes
36 37 #-----------------------------------------------------------------------------
37 38
38 39 def script_args(f):
39 40 """single decorator for adding script args"""
40 41 args = [
41 42 magic_arguments.argument(
42 43 '--out', type=str,
43 44 help="""The variable in which to store stdout from the script.
44 45 If the script is backgrounded, this will be the stdout *pipe*,
45 46 instead of the stderr text itself.
46 47 """
47 48 ),
48 49 magic_arguments.argument(
49 50 '--err', type=str,
50 51 help="""The variable in which to store stderr from the script.
51 52 If the script is backgrounded, this will be the stderr *pipe*,
52 53 instead of the stderr text itself.
53 54 """
54 55 ),
55 56 magic_arguments.argument(
56 57 '--bg', action="store_true",
57 58 help="""Whether to run the script in the background.
58 59 If given, the only way to see the output of the command is
59 60 with --out/err.
60 61 """
61 62 ),
62 63 magic_arguments.argument(
63 64 '--proc', type=str,
64 65 help="""The variable in which to store Popen instance.
65 66 This is used only when --bg option is given.
66 67 """
67 68 ),
68 69 ]
69 70 for arg in args:
70 71 f = arg(f)
71 72 return f
72 73
73 74 @magics_class
74 75 class ScriptMagics(Magics):
75 76 """Magics for talking to scripts
76 77
77 78 This defines a base `%%script` cell magic for running a cell
78 79 with a program in a subprocess, and registers a few top-level
79 80 magics that call %%script with common interpreters.
80 81 """
81 82 script_magics = List(config=True,
82 83 help="""Extra script cell magics to define
83 84
84 85 This generates simple wrappers of `%%script foo` as `%%foo`.
85 86
86 87 If you want to add script magics that aren't on your path,
87 88 specify them in script_paths
88 89 """,
89 90 )
90 91 def _script_magics_default(self):
91 92 """default to a common list of programs"""
92 93
93 94 defaults = [
94 95 'sh',
95 96 'bash',
96 97 'perl',
97 98 'ruby',
98 99 'python',
99 100 'python3',
100 101 'pypy',
101 102 ]
102 103 if os.name == 'nt':
103 104 defaults.extend([
104 105 'cmd',
105 106 'powershell',
106 107 ])
107 108
108 109 return defaults
109 110
110 111 script_paths = Dict(config=True,
111 112 help="""Dict mapping short 'ruby' names to full paths, such as '/opt/secret/bin/ruby'
112 113
113 114 Only necessary for items in script_magics where the default path will not
114 115 find the right interpreter.
115 116 """
116 117 )
117 118
118 119 def __init__(self, shell=None):
119 120 super(ScriptMagics, self).__init__(shell=shell)
120 121 self._generate_script_magics()
121 122 self.job_manager = BackgroundJobManager()
122 123 self.bg_processes = []
123 124 atexit.register(self.kill_bg_processes)
124 125
125 126 def __del__(self):
126 127 self.kill_bg_processes()
127 128
128 129 def _generate_script_magics(self):
129 130 cell_magics = self.magics['cell']
130 131 for name in self.script_magics:
131 132 cell_magics[name] = self._make_script_magic(name)
132 133
133 134 def _make_script_magic(self, name):
134 135 """make a named magic, that calls %%script with a particular program"""
135 136 # expand to explicit path if necessary:
136 137 script = self.script_paths.get(name, name)
137 138
138 139 @magic_arguments.magic_arguments()
139 140 @script_args
140 141 def named_script_magic(line, cell):
141 142 # if line, add it as cl-flags
142 143 if line:
143 144 line = "%s %s" % (script, line)
144 145 else:
145 146 line = script
146 147 return self.shebang(line, cell)
147 148
148 149 # write a basic docstring:
149 150 named_script_magic.__doc__ = \
150 151 """%%{name} script magic
151 152
152 153 Run cells with {script} in a subprocess.
153 154
154 155 This is a shortcut for `%%script {script}`
155 156 """.format(**locals())
156 157
157 158 return named_script_magic
158 159
159 160 @magic_arguments.magic_arguments()
160 161 @script_args
161 162 @cell_magic("script")
162 163 def shebang(self, line, cell):
163 164 """Run a cell via a shell command
164 165
165 166 The `%%script` line is like the #! line of script,
166 167 specifying a program (bash, perl, ruby, etc.) with which to run.
167 168
168 169 The rest of the cell is run by that program.
169 170
170 171 Examples
171 172 --------
172 173 ::
173 174
174 175 In [1]: %%script bash
175 176 ...: for i in 1 2 3; do
176 177 ...: echo $i
177 178 ...: done
178 179 1
179 180 2
180 181 3
181 182 """
182 183 argv = arg_split(line, posix = not sys.platform.startswith('win'))
183 184 args, cmd = self.shebang.parser.parse_known_args(argv)
184 185
185 186 try:
186 187 p = Popen(cmd, stdout=PIPE, stderr=PIPE, stdin=PIPE)
187 188 except OSError as e:
188 189 if e.errno == errno.ENOENT:
189 print "Couldn't find program: %r" % cmd[0]
190 print("Couldn't find program: %r" % cmd[0])
190 191 return
191 192 else:
192 193 raise
193 194
194 195 cell = cell.encode('utf8', 'replace')
195 196 if args.bg:
196 197 self.bg_processes.append(p)
197 198 self._gc_bg_processes()
198 199 if args.out:
199 200 self.shell.user_ns[args.out] = p.stdout
200 201 if args.err:
201 202 self.shell.user_ns[args.err] = p.stderr
202 203 self.job_manager.new(self._run_script, p, cell, daemon=True)
203 204 if args.proc:
204 205 self.shell.user_ns[args.proc] = p
205 206 return
206 207
207 208 try:
208 209 out, err = p.communicate(cell)
209 210 except KeyboardInterrupt:
210 211 try:
211 212 p.send_signal(signal.SIGINT)
212 213 time.sleep(0.1)
213 214 if p.poll() is not None:
214 print "Process is interrupted."
215 print("Process is interrupted.")
215 216 return
216 217 p.terminate()
217 218 time.sleep(0.1)
218 219 if p.poll() is not None:
219 print "Process is terminated."
220 print("Process is terminated.")
220 221 return
221 222 p.kill()
222 print "Process is killed."
223 print("Process is killed.")
223 224 except OSError:
224 225 pass
225 226 except Exception as e:
226 print "Error while terminating subprocess (pid=%i): %s" \
227 % (p.pid, e)
227 print("Error while terminating subprocess (pid=%i): %s" \
228 % (p.pid, e))
228 229 return
229 230 out = py3compat.bytes_to_str(out)
230 231 err = py3compat.bytes_to_str(err)
231 232 if args.out:
232 233 self.shell.user_ns[args.out] = out
233 234 else:
234 235 sys.stdout.write(out)
235 236 sys.stdout.flush()
236 237 if args.err:
237 238 self.shell.user_ns[args.err] = err
238 239 else:
239 240 sys.stderr.write(err)
240 241 sys.stderr.flush()
241 242
242 243 def _run_script(self, p, cell):
243 244 """callback for running the script in the background"""
244 245 p.stdin.write(cell)
245 246 p.stdin.close()
246 247 p.wait()
247 248
248 249 @line_magic("killbgscripts")
249 250 def killbgscripts(self, _nouse_=''):
250 251 """Kill all BG processes started by %%script and its family."""
251 252 self.kill_bg_processes()
252 print "All background processes were killed."
253 print("All background processes were killed.")
253 254
254 255 def kill_bg_processes(self):
255 256 """Kill all BG processes which are still running."""
256 257 for p in self.bg_processes:
257 258 if p.poll() is None:
258 259 try:
259 260 p.send_signal(signal.SIGINT)
260 261 except:
261 262 pass
262 263 time.sleep(0.1)
263 264 for p in self.bg_processes:
264 265 if p.poll() is None:
265 266 try:
266 267 p.terminate()
267 268 except:
268 269 pass
269 270 time.sleep(0.1)
270 271 for p in self.bg_processes:
271 272 if p.poll() is None:
272 273 try:
273 274 p.kill()
274 275 except:
275 276 pass
276 277 self._gc_bg_processes()
277 278
278 279 def _gc_bg_processes(self):
279 280 self.bg_processes = [p for p in self.bg_processes if p.poll() is None]
@@ -1,313 +1,314 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 from __future__ import print_function
12 13
13 14 #-----------------------------------------------------------------------------
14 15 # Copyright (C) 2008 The IPython Development Team
15 16 #
16 17 # Distributed under the terms of the BSD License. The full license is in
17 18 # the file COPYING, distributed as part of this software.
18 19 #-----------------------------------------------------------------------------
19 20
20 21 #-----------------------------------------------------------------------------
21 22 # Imports
22 23 #-----------------------------------------------------------------------------
23 24
24 25 import os
25 26
26 27 from IPython.config.application import Application
27 28 from IPython.core.application import (
28 29 BaseIPythonApplication, base_flags
29 30 )
30 31 from IPython.core.profiledir import ProfileDir
31 32 from IPython.utils.importstring import import_item
32 33 from IPython.utils.path import get_ipython_dir, get_ipython_package_dir
33 34 from IPython.utils.traitlets import Unicode, Bool, Dict
34 35
35 36 #-----------------------------------------------------------------------------
36 37 # Constants
37 38 #-----------------------------------------------------------------------------
38 39
39 40 create_help = """Create an IPython profile by name
40 41
41 42 Create an ipython profile directory by its name or
42 43 profile directory path. Profile directories contain
43 44 configuration, log and security related files and are named
44 45 using the convention 'profile_<name>'. By default they are
45 46 located in your ipython directory. Once created, you will
46 47 can edit the configuration files in the profile
47 48 directory to configure IPython. Most users will create a
48 49 profile directory by name,
49 50 `ipython profile create myprofile`, which will put the directory
50 51 in `<ipython_dir>/profile_myprofile`.
51 52 """
52 53 list_help = """List available IPython profiles
53 54
54 55 List all available profiles, by profile location, that can
55 56 be found in the current working directly or in the ipython
56 57 directory. Profile directories are named using the convention
57 58 'profile_<profile>'.
58 59 """
59 60 profile_help = """Manage IPython profiles
60 61
61 62 Profile directories contain
62 63 configuration, log and security related files and are named
63 64 using the convention 'profile_<name>'. By default they are
64 65 located in your ipython directory. You can create profiles
65 66 with `ipython profile create <name>`, or see the profiles you
66 67 already have with `ipython profile list`
67 68
68 69 To get started configuring IPython, simply do:
69 70
70 71 $> ipython profile create
71 72
72 73 and IPython will create the default profile in <ipython_dir>/profile_default,
73 74 where you can edit ipython_config.py to start configuring IPython.
74 75
75 76 """
76 77
77 78 _list_examples = "ipython profile list # list all profiles"
78 79
79 80 _create_examples = """
80 81 ipython profile create foo # create profile foo w/ default config files
81 82 ipython profile create foo --reset # restage default config files over current
82 83 ipython profile create foo --parallel # also stage parallel config files
83 84 """
84 85
85 86 _main_examples = """
86 87 ipython profile create -h # show the help string for the create subcommand
87 88 ipython profile list -h # show the help string for the list subcommand
88 89
89 90 ipython locate profile foo # print the path to the directory for profile 'foo'
90 91 """
91 92
92 93 #-----------------------------------------------------------------------------
93 94 # Profile Application Class (for `ipython profile` subcommand)
94 95 #-----------------------------------------------------------------------------
95 96
96 97
97 98 def list_profiles_in(path):
98 99 """list profiles in a given root directory"""
99 100 files = os.listdir(path)
100 101 profiles = []
101 102 for f in files:
102 103 try:
103 104 full_path = os.path.join(path, f)
104 105 except UnicodeError:
105 106 continue
106 107 if os.path.isdir(full_path) and f.startswith('profile_'):
107 108 profiles.append(f.split('_',1)[-1])
108 109 return profiles
109 110
110 111
111 112 def list_bundled_profiles():
112 113 """list profiles that are bundled with IPython."""
113 114 path = os.path.join(get_ipython_package_dir(), u'config', u'profile')
114 115 files = os.listdir(path)
115 116 profiles = []
116 117 for profile in files:
117 118 full_path = os.path.join(path, profile)
118 119 if os.path.isdir(full_path) and profile != "__pycache__":
119 120 profiles.append(profile)
120 121 return profiles
121 122
122 123
123 124 class ProfileLocate(BaseIPythonApplication):
124 125 description = """print the path to an IPython profile dir"""
125 126
126 127 def parse_command_line(self, argv=None):
127 128 super(ProfileLocate, self).parse_command_line(argv)
128 129 if self.extra_args:
129 130 self.profile = self.extra_args[0]
130 131
131 132 def start(self):
132 print self.profile_dir.location
133 print(self.profile_dir.location)
133 134
134 135
135 136 class ProfileList(Application):
136 137 name = u'ipython-profile'
137 138 description = list_help
138 139 examples = _list_examples
139 140
140 141 aliases = Dict({
141 142 'ipython-dir' : 'ProfileList.ipython_dir',
142 143 'log-level' : 'Application.log_level',
143 144 })
144 145 flags = Dict(dict(
145 146 debug = ({'Application' : {'log_level' : 0}},
146 147 "Set Application.log_level to 0, maximizing log output."
147 148 )
148 149 ))
149 150
150 151 ipython_dir = Unicode(get_ipython_dir(), config=True,
151 152 help="""
152 153 The name of the IPython directory. This directory is used for logging
153 154 configuration (through profiles), history storage, etc. The default
154 155 is usually $HOME/.ipython. This options can also be specified through
155 156 the environment variable IPYTHONDIR.
156 157 """
157 158 )
158 159
159 160
160 161 def _print_profiles(self, profiles):
161 162 """print list of profiles, indented."""
162 163 for profile in profiles:
163 print ' %s' % profile
164 print(' %s' % profile)
164 165
165 166 def list_profile_dirs(self):
166 167 profiles = list_bundled_profiles()
167 168 if profiles:
168 print
169 print "Available profiles in IPython:"
169 print()
170 print("Available profiles in IPython:")
170 171 self._print_profiles(profiles)
171 print
172 print " The first request for a bundled profile will copy it"
173 print " into your IPython directory (%s)," % self.ipython_dir
174 print " where you can customize it."
172 print()
173 print(" The first request for a bundled profile will copy it")
174 print(" into your IPython directory (%s)," % self.ipython_dir)
175 print(" where you can customize it.")
175 176
176 177 profiles = list_profiles_in(self.ipython_dir)
177 178 if profiles:
178 print
179 print "Available profiles in %s:" % self.ipython_dir
179 print()
180 print("Available profiles in %s:" % self.ipython_dir)
180 181 self._print_profiles(profiles)
181 182
182 183 profiles = list_profiles_in(os.getcwdu())
183 184 if profiles:
184 print
185 print "Available profiles in current directory (%s):" % os.getcwdu()
185 print()
186 print("Available profiles in current directory (%s):" % os.getcwdu())
186 187 self._print_profiles(profiles)
187 188
188 print
189 print "To use any of the above profiles, start IPython with:"
190 print " ipython --profile=<name>"
191 print
189 print()
190 print("To use any of the above profiles, start IPython with:")
191 print(" ipython --profile=<name>")
192 print()
192 193
193 194 def start(self):
194 195 self.list_profile_dirs()
195 196
196 197
197 198 create_flags = {}
198 199 create_flags.update(base_flags)
199 200 # don't include '--init' flag, which implies running profile create in other apps
200 201 create_flags.pop('init')
201 202 create_flags['reset'] = ({'ProfileCreate': {'overwrite' : True}},
202 203 "reset config files in this profile to the defaults.")
203 204 create_flags['parallel'] = ({'ProfileCreate': {'parallel' : True}},
204 205 "Include the config files for parallel "
205 206 "computing apps (ipengine, ipcontroller, etc.)")
206 207
207 208
208 209 class ProfileCreate(BaseIPythonApplication):
209 210 name = u'ipython-profile'
210 211 description = create_help
211 212 examples = _create_examples
212 213 auto_create = Bool(True, config=False)
213 214 def _log_format_default(self):
214 215 return "[%(name)s] %(message)s"
215 216
216 217 def _copy_config_files_default(self):
217 218 return True
218 219
219 220 parallel = Bool(False, config=True,
220 221 help="whether to include parallel computing config files")
221 222 def _parallel_changed(self, name, old, new):
222 223 parallel_files = [ 'ipcontroller_config.py',
223 224 'ipengine_config.py',
224 225 'ipcluster_config.py'
225 226 ]
226 227 if new:
227 228 for cf in parallel_files:
228 229 self.config_files.append(cf)
229 230 else:
230 231 for cf in parallel_files:
231 232 if cf in self.config_files:
232 233 self.config_files.remove(cf)
233 234
234 235 def parse_command_line(self, argv):
235 236 super(ProfileCreate, self).parse_command_line(argv)
236 237 # accept positional arg as profile name
237 238 if self.extra_args:
238 239 self.profile = self.extra_args[0]
239 240
240 241 flags = Dict(create_flags)
241 242
242 243 classes = [ProfileDir]
243 244
244 245 def _import_app(self, app_path):
245 246 """import an app class"""
246 247 app = None
247 248 name = app_path.rsplit('.', 1)[-1]
248 249 try:
249 250 app = import_item(app_path)
250 251 except ImportError as e:
251 252 self.log.info("Couldn't import %s, config file will be excluded", name)
252 253 except Exception:
253 254 self.log.warn('Unexpected error importing %s', name, exc_info=True)
254 255 return app
255 256
256 257 def init_config_files(self):
257 258 super(ProfileCreate, self).init_config_files()
258 259 # use local imports, since these classes may import from here
259 260 from IPython.terminal.ipapp import TerminalIPythonApp
260 261 apps = [TerminalIPythonApp]
261 262 for app_path in (
262 263 'IPython.qt.console.qtconsoleapp.IPythonQtConsoleApp',
263 264 'IPython.html.notebookapp.NotebookApp',
264 265 'IPython.nbconvert.nbconvertapp.NbConvertApp',
265 266 ):
266 267 app = self._import_app(app_path)
267 268 if app is not None:
268 269 apps.append(app)
269 270 if self.parallel:
270 271 from IPython.parallel.apps.ipcontrollerapp import IPControllerApp
271 272 from IPython.parallel.apps.ipengineapp import IPEngineApp
272 273 from IPython.parallel.apps.ipclusterapp import IPClusterStart
273 274 from IPython.parallel.apps.iploggerapp import IPLoggerApp
274 275 apps.extend([
275 276 IPControllerApp,
276 277 IPEngineApp,
277 278 IPClusterStart,
278 279 IPLoggerApp,
279 280 ])
280 281 for App in apps:
281 282 app = App()
282 283 app.config.update(self.config)
283 284 app.log = self.log
284 285 app.overwrite = self.overwrite
285 286 app.copy_config_files=True
286 287 app.profile = self.profile
287 288 app.init_profile_dir()
288 289 app.init_config_files()
289 290
290 291 def stage_default_config_file(self):
291 292 pass
292 293
293 294
294 295 class ProfileApp(Application):
295 296 name = u'ipython-profile'
296 297 description = profile_help
297 298 examples = _main_examples
298 299
299 300 subcommands = Dict(dict(
300 301 create = (ProfileCreate, ProfileCreate.description.splitlines()[0]),
301 302 list = (ProfileList, ProfileList.description.splitlines()[0]),
302 303 locate = (ProfileLocate, ProfileLocate.description.splitlines()[0]),
303 304 ))
304 305
305 306 def start(self):
306 307 if self.subapp is None:
307 print "No subcommand specified. Must specify one of: %s"%(self.subcommands.keys())
308 print
308 print("No subcommand specified. Must specify one of: %s"%(self.subcommands.keys()))
309 print()
309 310 self.print_description()
310 311 self.print_subcommands()
311 312 self.exit(1)
312 313 else:
313 314 return self.subapp.start()
@@ -1,339 +1,340 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Pylab (matplotlib) support utilities.
3 3
4 4 Authors
5 5 -------
6 6
7 7 * Fernando Perez.
8 8 * Brian Granger
9 9 """
10 from __future__ import print_function
10 11
11 12 #-----------------------------------------------------------------------------
12 13 # Copyright (C) 2009 The IPython Development Team
13 14 #
14 15 # Distributed under the terms of the BSD License. The full license is in
15 16 # the file COPYING, distributed as part of this software.
16 17 #-----------------------------------------------------------------------------
17 18
18 19 #-----------------------------------------------------------------------------
19 20 # Imports
20 21 #-----------------------------------------------------------------------------
21 22
22 23 import sys
23 24 from io import BytesIO
24 25
25 26 from IPython.core.display import _pngxy
26 27 from IPython.utils.decorators import flag_calls
27 28
28 29 # If user specifies a GUI, that dictates the backend, otherwise we read the
29 30 # user's mpl default from the mpl rc structure
30 31 backends = {'tk': 'TkAgg',
31 32 'gtk': 'GTKAgg',
32 33 'wx': 'WXAgg',
33 34 'qt': 'Qt4Agg', # qt3 not supported
34 35 'qt4': 'Qt4Agg',
35 36 'osx': 'MacOSX',
36 37 'inline' : 'module://IPython.kernel.zmq.pylab.backend_inline'}
37 38
38 39 # We also need a reverse backends2guis mapping that will properly choose which
39 40 # GUI support to activate based on the desired matplotlib backend. For the
40 41 # most part it's just a reverse of the above dict, but we also need to add a
41 42 # few others that map to the same GUI manually:
42 43 backend2gui = dict(zip(backends.values(), backends.keys()))
43 44 # Our tests expect backend2gui to just return 'qt'
44 45 backend2gui['Qt4Agg'] = 'qt'
45 46 # In the reverse mapping, there are a few extra valid matplotlib backends that
46 47 # map to the same GUI support
47 48 backend2gui['GTK'] = backend2gui['GTKCairo'] = 'gtk'
48 49 backend2gui['WX'] = 'wx'
49 50 backend2gui['CocoaAgg'] = 'osx'
50 51
51 52 #-----------------------------------------------------------------------------
52 53 # Matplotlib utilities
53 54 #-----------------------------------------------------------------------------
54 55
55 56
56 57 def getfigs(*fig_nums):
57 58 """Get a list of matplotlib figures by figure numbers.
58 59
59 60 If no arguments are given, all available figures are returned. If the
60 61 argument list contains references to invalid figures, a warning is printed
61 62 but the function continues pasting further figures.
62 63
63 64 Parameters
64 65 ----------
65 66 figs : tuple
66 67 A tuple of ints giving the figure numbers of the figures to return.
67 68 """
68 69 from matplotlib._pylab_helpers import Gcf
69 70 if not fig_nums:
70 71 fig_managers = Gcf.get_all_fig_managers()
71 72 return [fm.canvas.figure for fm in fig_managers]
72 73 else:
73 74 figs = []
74 75 for num in fig_nums:
75 76 f = Gcf.figs.get(num)
76 77 if f is None:
77 print('Warning: figure %s not available.' % num)
78 print(('Warning: figure %s not available.' % num))
78 79 else:
79 80 figs.append(f.canvas.figure)
80 81 return figs
81 82
82 83
83 84 def figsize(sizex, sizey):
84 85 """Set the default figure size to be [sizex, sizey].
85 86
86 87 This is just an easy to remember, convenience wrapper that sets::
87 88
88 89 matplotlib.rcParams['figure.figsize'] = [sizex, sizey]
89 90 """
90 91 import matplotlib
91 92 matplotlib.rcParams['figure.figsize'] = [sizex, sizey]
92 93
93 94
94 95 def print_figure(fig, fmt='png'):
95 96 """Convert a figure to svg or png for inline display."""
96 97 from matplotlib import rcParams
97 98 # When there's an empty figure, we shouldn't return anything, otherwise we
98 99 # get big blank areas in the qt console.
99 100 if not fig.axes and not fig.lines:
100 101 return
101 102
102 103 fc = fig.get_facecolor()
103 104 ec = fig.get_edgecolor()
104 105 bytes_io = BytesIO()
105 106 dpi = rcParams['savefig.dpi']
106 107 if fmt == 'retina':
107 108 dpi = dpi * 2
108 109 fmt = 'png'
109 110 fig.canvas.print_figure(bytes_io, format=fmt, bbox_inches='tight',
110 111 facecolor=fc, edgecolor=ec, dpi=dpi)
111 112 data = bytes_io.getvalue()
112 113 return data
113 114
114 115 def retina_figure(fig):
115 116 """format a figure as a pixel-doubled (retina) PNG"""
116 117 pngdata = print_figure(fig, fmt='retina')
117 118 w, h = _pngxy(pngdata)
118 119 metadata = dict(width=w//2, height=h//2)
119 120 return pngdata, metadata
120 121
121 122 # We need a little factory function here to create the closure where
122 123 # safe_execfile can live.
123 124 def mpl_runner(safe_execfile):
124 125 """Factory to return a matplotlib-enabled runner for %run.
125 126
126 127 Parameters
127 128 ----------
128 129 safe_execfile : function
129 130 This must be a function with the same interface as the
130 131 :meth:`safe_execfile` method of IPython.
131 132
132 133 Returns
133 134 -------
134 135 A function suitable for use as the ``runner`` argument of the %run magic
135 136 function.
136 137 """
137 138
138 139 def mpl_execfile(fname,*where,**kw):
139 140 """matplotlib-aware wrapper around safe_execfile.
140 141
141 142 Its interface is identical to that of the :func:`execfile` builtin.
142 143
143 144 This is ultimately a call to execfile(), but wrapped in safeties to
144 145 properly handle interactive rendering."""
145 146
146 147 import matplotlib
147 148 import matplotlib.pylab as pylab
148 149
149 150 #print '*** Matplotlib runner ***' # dbg
150 151 # turn off rendering until end of script
151 152 is_interactive = matplotlib.rcParams['interactive']
152 153 matplotlib.interactive(False)
153 154 safe_execfile(fname,*where,**kw)
154 155 matplotlib.interactive(is_interactive)
155 156 # make rendering call now, if the user tried to do it
156 157 if pylab.draw_if_interactive.called:
157 158 pylab.draw()
158 159 pylab.draw_if_interactive.called = False
159 160
160 161 return mpl_execfile
161 162
162 163
163 164 def select_figure_format(shell, fmt):
164 165 """Select figure format for inline backend, can be 'png', 'retina', or 'svg'.
165 166
166 167 Using this method ensures only one figure format is active at a time.
167 168 """
168 169 from matplotlib.figure import Figure
169 170 from IPython.kernel.zmq.pylab import backend_inline
170 171
171 172 svg_formatter = shell.display_formatter.formatters['image/svg+xml']
172 173 png_formatter = shell.display_formatter.formatters['image/png']
173 174
174 175 if fmt == 'png':
175 176 svg_formatter.type_printers.pop(Figure, None)
176 177 png_formatter.for_type(Figure, lambda fig: print_figure(fig, 'png'))
177 178 elif fmt in ('png2x', 'retina'):
178 179 svg_formatter.type_printers.pop(Figure, None)
179 180 png_formatter.for_type(Figure, retina_figure)
180 181 elif fmt == 'svg':
181 182 png_formatter.type_printers.pop(Figure, None)
182 183 svg_formatter.for_type(Figure, lambda fig: print_figure(fig, 'svg'))
183 184 else:
184 185 raise ValueError("supported formats are: 'png', 'retina', 'svg', not %r" % fmt)
185 186
186 187 # set the format to be used in the backend()
187 188 backend_inline._figure_format = fmt
188 189
189 190 #-----------------------------------------------------------------------------
190 191 # Code for initializing matplotlib and importing pylab
191 192 #-----------------------------------------------------------------------------
192 193
193 194
194 195 def find_gui_and_backend(gui=None, gui_select=None):
195 196 """Given a gui string return the gui and mpl backend.
196 197
197 198 Parameters
198 199 ----------
199 200 gui : str
200 201 Can be one of ('tk','gtk','wx','qt','qt4','inline').
201 202 gui_select : str
202 203 Can be one of ('tk','gtk','wx','qt','qt4','inline').
203 204 This is any gui already selected by the shell.
204 205
205 206 Returns
206 207 -------
207 208 A tuple of (gui, backend) where backend is one of ('TkAgg','GTKAgg',
208 209 'WXAgg','Qt4Agg','module://IPython.kernel.zmq.pylab.backend_inline').
209 210 """
210 211
211 212 import matplotlib
212 213
213 214 if gui and gui != 'auto':
214 215 # select backend based on requested gui
215 216 backend = backends[gui]
216 217 else:
217 218 # We need to read the backend from the original data structure, *not*
218 219 # from mpl.rcParams, since a prior invocation of %matplotlib may have
219 220 # overwritten that.
220 221 # WARNING: this assumes matplotlib 1.1 or newer!!
221 222 backend = matplotlib.rcParamsOrig['backend']
222 223 # In this case, we need to find what the appropriate gui selection call
223 224 # should be for IPython, so we can activate inputhook accordingly
224 225 gui = backend2gui.get(backend, None)
225 226
226 227 # If we have already had a gui active, we need it and inline are the
227 228 # ones allowed.
228 229 if gui_select and gui != gui_select:
229 230 gui = gui_select
230 231 backend = backends[gui]
231 232
232 233 return gui, backend
233 234
234 235
235 236 def activate_matplotlib(backend):
236 237 """Activate the given backend and set interactive to True."""
237 238
238 239 import matplotlib
239 240 matplotlib.interactive(True)
240 241
241 242 # Matplotlib had a bug where even switch_backend could not force
242 243 # the rcParam to update. This needs to be set *before* the module
243 244 # magic of switch_backend().
244 245 matplotlib.rcParams['backend'] = backend
245 246
246 247 import matplotlib.pyplot
247 248 matplotlib.pyplot.switch_backend(backend)
248 249
249 250 # This must be imported last in the matplotlib series, after
250 251 # backend/interactivity choices have been made
251 252 import matplotlib.pylab as pylab
252 253
253 254 pylab.show._needmain = False
254 255 # We need to detect at runtime whether show() is called by the user.
255 256 # For this, we wrap it into a decorator which adds a 'called' flag.
256 257 pylab.draw_if_interactive = flag_calls(pylab.draw_if_interactive)
257 258
258 259
259 260 def import_pylab(user_ns, import_all=True):
260 261 """Populate the namespace with pylab-related values.
261 262
262 263 Imports matplotlib, pylab, numpy, and everything from pylab and numpy.
263 264
264 265 Also imports a few names from IPython (figsize, display, getfigs)
265 266
266 267 """
267 268
268 269 # Import numpy as np/pyplot as plt are conventions we're trying to
269 270 # somewhat standardize on. Making them available to users by default
270 271 # will greatly help this.
271 272 s = ("import numpy\n"
272 273 "import matplotlib\n"
273 274 "from matplotlib import pylab, mlab, pyplot\n"
274 275 "np = numpy\n"
275 276 "plt = pyplot\n"
276 277 )
277 278 exec s in user_ns
278 279
279 280 if import_all:
280 281 s = ("from matplotlib.pylab import *\n"
281 282 "from numpy import *\n")
282 283 exec s in user_ns
283 284
284 285 # IPython symbols to add
285 286 user_ns['figsize'] = figsize
286 287 from IPython.core.display import display
287 288 # Add display and getfigs to the user's namespace
288 289 user_ns['display'] = display
289 290 user_ns['getfigs'] = getfigs
290 291
291 292
292 293 def configure_inline_support(shell, backend):
293 294 """Configure an IPython shell object for matplotlib use.
294 295
295 296 Parameters
296 297 ----------
297 298 shell : InteractiveShell instance
298 299
299 300 backend : matplotlib backend
300 301 """
301 302 # If using our svg payload backend, register the post-execution
302 303 # function that will pick up the results for display. This can only be
303 304 # done with access to the real shell object.
304 305
305 306 # Note: if we can't load the inline backend, then there's no point
306 307 # continuing (such as in terminal-only shells in environments without
307 308 # zeromq available).
308 309 try:
309 310 from IPython.kernel.zmq.pylab.backend_inline import InlineBackend
310 311 except ImportError:
311 312 return
312 313 from matplotlib import pyplot
313 314
314 315 cfg = InlineBackend.instance(parent=shell)
315 316 cfg.shell = shell
316 317 if cfg not in shell.configurables:
317 318 shell.configurables.append(cfg)
318 319
319 320 if backend == backends['inline']:
320 321 from IPython.kernel.zmq.pylab.backend_inline import flush_figures
321 322 shell.register_post_execute(flush_figures)
322 323
323 324 # Save rcParams that will be overwrittern
324 325 shell._saved_rcParams = dict()
325 326 for k in cfg.rc:
326 327 shell._saved_rcParams[k] = pyplot.rcParams[k]
327 328 # load inline_rc
328 329 pyplot.rcParams.update(cfg.rc)
329 330 else:
330 331 from IPython.kernel.zmq.pylab.backend_inline import flush_figures
331 332 if flush_figures in shell._post_execute:
332 333 shell._post_execute.pop(flush_figures)
333 334 if hasattr(shell, '_saved_rcParams'):
334 335 pyplot.rcParams.update(shell._saved_rcParams)
335 336 del shell._saved_rcParams
336 337
337 338 # Setup the default figure format
338 339 select_figure_format(shell, cfg.figure_format)
339 340
@@ -1,409 +1,410 b''
1 1 # encoding: utf-8
2 2 """
3 3 A mixin for :class:`~IPython.core.application.Application` classes that
4 4 launch InteractiveShell instances, load extensions, etc.
5 5
6 6 Authors
7 7 -------
8 8
9 9 * Min Ragan-Kelley
10 10 """
11 11
12 12 #-----------------------------------------------------------------------------
13 13 # Copyright (C) 2008-2011 The IPython Development Team
14 14 #
15 15 # Distributed under the terms of the BSD License. The full license is in
16 16 # the file COPYING, distributed as part of this software.
17 17 #-----------------------------------------------------------------------------
18 18
19 19 #-----------------------------------------------------------------------------
20 20 # Imports
21 21 #-----------------------------------------------------------------------------
22 22
23 23 from __future__ import absolute_import
24 from __future__ import print_function
24 25
25 26 import glob
26 27 import os
27 28 import sys
28 29
29 30 from IPython.config.application import boolean_flag
30 31 from IPython.config.configurable import Configurable
31 32 from IPython.config.loader import Config
32 33 from IPython.core import pylabtools
33 34 from IPython.utils import py3compat
34 35 from IPython.utils.contexts import preserve_keys
35 36 from IPython.utils.path import filefind
36 37 from IPython.utils.traitlets import (
37 38 Unicode, Instance, List, Bool, CaselessStrEnum, Dict
38 39 )
39 40 from IPython.lib.inputhook import guis
40 41
41 42 #-----------------------------------------------------------------------------
42 43 # Aliases and Flags
43 44 #-----------------------------------------------------------------------------
44 45
45 46 gui_keys = tuple(sorted([ key for key in guis if key is not None ]))
46 47
47 48 backend_keys = sorted(pylabtools.backends.keys())
48 49 backend_keys.insert(0, 'auto')
49 50
50 51 shell_flags = {}
51 52
52 53 addflag = lambda *args: shell_flags.update(boolean_flag(*args))
53 54 addflag('autoindent', 'InteractiveShell.autoindent',
54 55 'Turn on autoindenting.', 'Turn off autoindenting.'
55 56 )
56 57 addflag('automagic', 'InteractiveShell.automagic',
57 58 """Turn on the auto calling of magic commands. Type %%magic at the
58 59 IPython prompt for more information.""",
59 60 'Turn off the auto calling of magic commands.'
60 61 )
61 62 addflag('pdb', 'InteractiveShell.pdb',
62 63 "Enable auto calling the pdb debugger after every exception.",
63 64 "Disable auto calling the pdb debugger after every exception."
64 65 )
65 66 # pydb flag doesn't do any config, as core.debugger switches on import,
66 67 # which is before parsing. This just allows the flag to be passed.
67 68 shell_flags.update(dict(
68 69 pydb = ({},
69 70 """Use the third party 'pydb' package as debugger, instead of pdb.
70 71 Requires that pydb is installed."""
71 72 )
72 73 ))
73 74 addflag('pprint', 'PlainTextFormatter.pprint',
74 75 "Enable auto pretty printing of results.",
75 76 "Disable auto pretty printing of results."
76 77 )
77 78 addflag('color-info', 'InteractiveShell.color_info',
78 79 """IPython can display information about objects via a set of func-
79 80 tions, and optionally can use colors for this, syntax highlighting
80 81 source code and various other elements. However, because this
81 82 information is passed through a pager (like 'less') and many pagers get
82 83 confused with color codes, this option is off by default. You can test
83 84 it and turn it on permanently in your ipython_config.py file if it
84 85 works for you. Test it and turn it on permanently if it works with
85 86 your system. The magic function %%color_info allows you to toggle this
86 87 interactively for testing.""",
87 88 "Disable using colors for info related things."
88 89 )
89 90 addflag('deep-reload', 'InteractiveShell.deep_reload',
90 91 """Enable deep (recursive) reloading by default. IPython can use the
91 92 deep_reload module which reloads changes in modules recursively (it
92 93 replaces the reload() function, so you don't need to change anything to
93 94 use it). deep_reload() forces a full reload of modules whose code may
94 95 have changed, which the default reload() function does not. When
95 96 deep_reload is off, IPython will use the normal reload(), but
96 97 deep_reload will still be available as dreload(). This feature is off
97 98 by default [which means that you have both normal reload() and
98 99 dreload()].""",
99 100 "Disable deep (recursive) reloading by default."
100 101 )
101 102 nosep_config = Config()
102 103 nosep_config.InteractiveShell.separate_in = ''
103 104 nosep_config.InteractiveShell.separate_out = ''
104 105 nosep_config.InteractiveShell.separate_out2 = ''
105 106
106 107 shell_flags['nosep']=(nosep_config, "Eliminate all spacing between prompts.")
107 108 shell_flags['pylab'] = (
108 109 {'InteractiveShellApp' : {'pylab' : 'auto'}},
109 110 """Pre-load matplotlib and numpy for interactive use with
110 111 the default matplotlib backend."""
111 112 )
112 113 shell_flags['matplotlib'] = (
113 114 {'InteractiveShellApp' : {'matplotlib' : 'auto'}},
114 115 """Configure matplotlib for interactive use with
115 116 the default matplotlib backend."""
116 117 )
117 118
118 119 # it's possible we don't want short aliases for *all* of these:
119 120 shell_aliases = dict(
120 121 autocall='InteractiveShell.autocall',
121 122 colors='InteractiveShell.colors',
122 123 logfile='InteractiveShell.logfile',
123 124 logappend='InteractiveShell.logappend',
124 125 c='InteractiveShellApp.code_to_run',
125 126 m='InteractiveShellApp.module_to_run',
126 127 ext='InteractiveShellApp.extra_extension',
127 128 gui='InteractiveShellApp.gui',
128 129 pylab='InteractiveShellApp.pylab',
129 130 matplotlib='InteractiveShellApp.matplotlib',
130 131 )
131 132 shell_aliases['cache-size'] = 'InteractiveShell.cache_size'
132 133
133 134 #-----------------------------------------------------------------------------
134 135 # Main classes and functions
135 136 #-----------------------------------------------------------------------------
136 137
137 138 class InteractiveShellApp(Configurable):
138 139 """A Mixin for applications that start InteractiveShell instances.
139 140
140 141 Provides configurables for loading extensions and executing files
141 142 as part of configuring a Shell environment.
142 143
143 144 The following methods should be called by the :meth:`initialize` method
144 145 of the subclass:
145 146
146 147 - :meth:`init_path`
147 148 - :meth:`init_shell` (to be implemented by the subclass)
148 149 - :meth:`init_gui_pylab`
149 150 - :meth:`init_extensions`
150 151 - :meth:`init_code`
151 152 """
152 153 extensions = List(Unicode, config=True,
153 154 help="A list of dotted module names of IPython extensions to load."
154 155 )
155 156 extra_extension = Unicode('', config=True,
156 157 help="dotted module name of an IPython extension to load."
157 158 )
158 159 def _extra_extension_changed(self, name, old, new):
159 160 if new:
160 161 # add to self.extensions
161 162 self.extensions.append(new)
162 163
163 164 # Extensions that are always loaded (not configurable)
164 165 default_extensions = List(Unicode, [u'storemagic'], config=False)
165 166
166 167 exec_files = List(Unicode, config=True,
167 168 help="""List of files to run at IPython startup."""
168 169 )
169 170 file_to_run = Unicode('', config=True,
170 171 help="""A file to be run""")
171 172
172 173 exec_lines = List(Unicode, config=True,
173 174 help="""lines of code to run at IPython startup."""
174 175 )
175 176 code_to_run = Unicode('', config=True,
176 177 help="Execute the given command string."
177 178 )
178 179 module_to_run = Unicode('', config=True,
179 180 help="Run the module as a script."
180 181 )
181 182 gui = CaselessStrEnum(gui_keys, config=True,
182 183 help="Enable GUI event loop integration with any of {0}.".format(gui_keys)
183 184 )
184 185 matplotlib = CaselessStrEnum(backend_keys,
185 186 config=True,
186 187 help="""Configure matplotlib for interactive use with
187 188 the default matplotlib backend."""
188 189 )
189 190 pylab = CaselessStrEnum(backend_keys,
190 191 config=True,
191 192 help="""Pre-load matplotlib and numpy for interactive use,
192 193 selecting a particular matplotlib backend and loop integration.
193 194 """
194 195 )
195 196 pylab_import_all = Bool(True, config=True,
196 197 help="""If true, IPython will populate the user namespace with numpy, pylab, etc.
197 198 and an 'import *' is done from numpy and pylab, when using pylab mode.
198 199
199 200 When False, pylab mode should not import any names into the user namespace.
200 201 """
201 202 )
202 203 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
203 204
204 205 user_ns = Instance(dict, args=None, allow_none=True)
205 206 def _user_ns_changed(self, name, old, new):
206 207 if self.shell is not None:
207 208 self.shell.user_ns = new
208 209 self.shell.init_user_ns()
209 210
210 211 def init_path(self):
211 212 """Add current working directory, '', to sys.path"""
212 213 if sys.path[0] != '':
213 214 sys.path.insert(0, '')
214 215
215 216 def init_shell(self):
216 217 raise NotImplementedError("Override in subclasses")
217 218
218 219 def init_gui_pylab(self):
219 220 """Enable GUI event loop integration, taking pylab into account."""
220 221 enable = False
221 222 shell = self.shell
222 223 if self.pylab:
223 224 enable = lambda key: shell.enable_pylab(key, import_all=self.pylab_import_all)
224 225 key = self.pylab
225 226 elif self.matplotlib:
226 227 enable = shell.enable_matplotlib
227 228 key = self.matplotlib
228 229 elif self.gui:
229 230 enable = shell.enable_gui
230 231 key = self.gui
231 232
232 233 if not enable:
233 234 return
234 235
235 236 try:
236 237 r = enable(key)
237 238 except ImportError:
238 239 self.log.warn("Eventloop or matplotlib integration failed. Is matplotlib installed?")
239 240 self.shell.showtraceback()
240 241 return
241 242 except Exception:
242 243 self.log.warn("GUI event loop or pylab initialization failed")
243 244 self.shell.showtraceback()
244 245 return
245 246
246 247 if isinstance(r, tuple):
247 248 gui, backend = r[:2]
248 249 self.log.info("Enabling GUI event loop integration, "
249 250 "eventloop=%s, matplotlib=%s", gui, backend)
250 251 if key == "auto":
251 print ("Using matplotlib backend: %s" % backend)
252 print(("Using matplotlib backend: %s" % backend))
252 253 else:
253 254 gui = r
254 255 self.log.info("Enabling GUI event loop integration, "
255 256 "eventloop=%s", gui)
256 257
257 258 def init_extensions(self):
258 259 """Load all IPython extensions in IPythonApp.extensions.
259 260
260 261 This uses the :meth:`ExtensionManager.load_extensions` to load all
261 262 the extensions listed in ``self.extensions``.
262 263 """
263 264 try:
264 265 self.log.debug("Loading IPython extensions...")
265 266 extensions = self.default_extensions + self.extensions
266 267 for ext in extensions:
267 268 try:
268 269 self.log.info("Loading IPython extension: %s" % ext)
269 270 self.shell.extension_manager.load_extension(ext)
270 271 except:
271 272 self.log.warn("Error in loading extension: %s" % ext +
272 273 "\nCheck your config files in %s" % self.profile_dir.location
273 274 )
274 275 self.shell.showtraceback()
275 276 except:
276 277 self.log.warn("Unknown error in loading extensions:")
277 278 self.shell.showtraceback()
278 279
279 280 def init_code(self):
280 281 """run the pre-flight code, specified via exec_lines"""
281 282 self._run_startup_files()
282 283 self._run_exec_lines()
283 284 self._run_exec_files()
284 285 self._run_cmd_line_code()
285 286 self._run_module()
286 287
287 288 # flush output, so itwon't be attached to the first cell
288 289 sys.stdout.flush()
289 290 sys.stderr.flush()
290 291
291 292 # Hide variables defined here from %who etc.
292 293 self.shell.user_ns_hidden.update(self.shell.user_ns)
293 294
294 295 def _run_exec_lines(self):
295 296 """Run lines of code in IPythonApp.exec_lines in the user's namespace."""
296 297 if not self.exec_lines:
297 298 return
298 299 try:
299 300 self.log.debug("Running code from IPythonApp.exec_lines...")
300 301 for line in self.exec_lines:
301 302 try:
302 303 self.log.info("Running code in user namespace: %s" %
303 304 line)
304 305 self.shell.run_cell(line, store_history=False)
305 306 except:
306 307 self.log.warn("Error in executing line in user "
307 308 "namespace: %s" % line)
308 309 self.shell.showtraceback()
309 310 except:
310 311 self.log.warn("Unknown error in handling IPythonApp.exec_lines:")
311 312 self.shell.showtraceback()
312 313
313 314 def _exec_file(self, fname):
314 315 try:
315 316 full_filename = filefind(fname, [u'.', self.ipython_dir])
316 317 except IOError as e:
317 318 self.log.warn("File not found: %r"%fname)
318 319 return
319 320 # Make sure that the running script gets a proper sys.argv as if it
320 321 # were run from a system shell.
321 322 save_argv = sys.argv
322 323 sys.argv = [full_filename] + self.extra_args[1:]
323 324 # protect sys.argv from potential unicode strings on Python 2:
324 325 if not py3compat.PY3:
325 326 sys.argv = [ py3compat.cast_bytes(a) for a in sys.argv ]
326 327 try:
327 328 if os.path.isfile(full_filename):
328 329 self.log.info("Running file in user namespace: %s" %
329 330 full_filename)
330 331 # Ensure that __file__ is always defined to match Python
331 332 # behavior.
332 333 with preserve_keys(self.shell.user_ns, '__file__'):
333 334 self.shell.user_ns['__file__'] = fname
334 335 if full_filename.endswith('.ipy'):
335 336 self.shell.safe_execfile_ipy(full_filename)
336 337 else:
337 338 # default to python, even without extension
338 339 self.shell.safe_execfile(full_filename,
339 340 self.shell.user_ns)
340 341 finally:
341 342 sys.argv = save_argv
342 343
343 344 def _run_startup_files(self):
344 345 """Run files from profile startup directory"""
345 346 startup_dir = self.profile_dir.startup_dir
346 347 startup_files = []
347 348 if os.environ.get('PYTHONSTARTUP', False):
348 349 startup_files.append(os.environ['PYTHONSTARTUP'])
349 350 startup_files += glob.glob(os.path.join(startup_dir, '*.py'))
350 351 startup_files += glob.glob(os.path.join(startup_dir, '*.ipy'))
351 352 if not startup_files:
352 353 return
353 354
354 355 self.log.debug("Running startup files from %s...", startup_dir)
355 356 try:
356 357 for fname in sorted(startup_files):
357 358 self._exec_file(fname)
358 359 except:
359 360 self.log.warn("Unknown error in handling startup files:")
360 361 self.shell.showtraceback()
361 362
362 363 def _run_exec_files(self):
363 364 """Run files from IPythonApp.exec_files"""
364 365 if not self.exec_files:
365 366 return
366 367
367 368 self.log.debug("Running files in IPythonApp.exec_files...")
368 369 try:
369 370 for fname in self.exec_files:
370 371 self._exec_file(fname)
371 372 except:
372 373 self.log.warn("Unknown error in handling IPythonApp.exec_files:")
373 374 self.shell.showtraceback()
374 375
375 376 def _run_cmd_line_code(self):
376 377 """Run code or file specified at the command-line"""
377 378 if self.code_to_run:
378 379 line = self.code_to_run
379 380 try:
380 381 self.log.info("Running code given at command line (c=): %s" %
381 382 line)
382 383 self.shell.run_cell(line, store_history=False)
383 384 except:
384 385 self.log.warn("Error in executing line in user namespace: %s" %
385 386 line)
386 387 self.shell.showtraceback()
387 388
388 389 # Like Python itself, ignore the second if the first of these is present
389 390 elif self.file_to_run:
390 391 fname = self.file_to_run
391 392 try:
392 393 self._exec_file(fname)
393 394 except:
394 395 self.log.warn("Error in executing file in user namespace: %s" %
395 396 fname)
396 397 self.shell.showtraceback()
397 398
398 399 def _run_module(self):
399 400 """Run module specified at the command-line."""
400 401 if self.module_to_run:
401 402 # Make sure that the module gets a proper sys.argv as if it were
402 403 # run using `python -m`.
403 404 save_argv = sys.argv
404 405 sys.argv = [sys.executable] + self.extra_args
405 406 try:
406 407 self.shell.safe_run_module(self.module_to_run,
407 408 self.shell.user_ns)
408 409 finally:
409 410 sys.argv = save_argv
@@ -1,2 +1,3 b''
1 from __future__ import print_function
1 2 import sys
2 print sys.argv[1:]
3 print(sys.argv[1:])
@@ -1,47 +1,48 b''
1 1 """Minimal script to reproduce our nasty reference counting bug.
2 2
3 3 The problem is related to https://github.com/ipython/ipython/issues/141
4 4
5 5 The original fix for that appeared to work, but John D. Hunter found a
6 6 matplotlib example which, when run twice in a row, would break. The problem
7 7 were references held by open figures to internals of Tkinter.
8 8
9 9 This code reproduces the problem that John saw, without matplotlib.
10 10
11 11 This script is meant to be called by other parts of the test suite that call it
12 12 via %run as if it were executed interactively by the user. As of 2011-05-29,
13 13 test_run.py calls it.
14 14 """
15 from __future__ import print_function
15 16
16 17 #-----------------------------------------------------------------------------
17 18 # Module imports
18 19 #-----------------------------------------------------------------------------
19 20 import sys
20 21
21 22 from IPython import get_ipython
22 23
23 24 #-----------------------------------------------------------------------------
24 25 # Globals
25 26 #-----------------------------------------------------------------------------
26 27
27 28 # This needs to be here because nose and other test runners will import
28 29 # this module. Importing this module has potential side effects that we
29 30 # want to prevent.
30 31 if __name__ == '__main__':
31 32
32 33 ip = get_ipython()
33 34
34 35 if not '_refbug_cache' in ip.user_ns:
35 36 ip.user_ns['_refbug_cache'] = []
36 37
37 38
38 39 aglobal = 'Hello'
39 40 def f():
40 41 return aglobal
41 42
42 43 cache = ip.user_ns['_refbug_cache']
43 44 cache.append(f)
44 45
45 46 def call_f():
46 47 for func in cache:
47 print 'lowercased:',func().lower()
48 print('lowercased:',func().lower())
@@ -1,153 +1,154 b''
1 1 """Tests for debugging machinery.
2 2 """
3 from __future__ import print_function
3 4 #-----------------------------------------------------------------------------
4 5 # Copyright (c) 2012, The IPython Development Team.
5 6 #
6 7 # Distributed under the terms of the Modified BSD License.
7 8 #
8 9 # The full license is in the file COPYING.txt, distributed with this software.
9 10 #-----------------------------------------------------------------------------
10 11
11 12 #-----------------------------------------------------------------------------
12 13 # Imports
13 14 #-----------------------------------------------------------------------------
14 15
15 16 import sys
16 17
17 18 # third-party
18 19 import nose.tools as nt
19 20
20 21 # Our own
21 22 from IPython.core import debugger
22 23
23 24 #-----------------------------------------------------------------------------
24 25 # Helper classes, from CPython's Pdb test suite
25 26 #-----------------------------------------------------------------------------
26 27
27 28 class _FakeInput(object):
28 29 """
29 30 A fake input stream for pdb's interactive debugger. Whenever a
30 31 line is read, print it (to simulate the user typing it), and then
31 32 return it. The set of lines to return is specified in the
32 33 constructor; they should not have trailing newlines.
33 34 """
34 35 def __init__(self, lines):
35 36 self.lines = iter(lines)
36 37
37 38 def readline(self):
38 39 line = next(self.lines)
39 print line
40 print(line)
40 41 return line+'\n'
41 42
42 43 class PdbTestInput(object):
43 44 """Context manager that makes testing Pdb in doctests easier."""
44 45
45 46 def __init__(self, input):
46 47 self.input = input
47 48
48 49 def __enter__(self):
49 50 self.real_stdin = sys.stdin
50 51 sys.stdin = _FakeInput(self.input)
51 52
52 53 def __exit__(self, *exc):
53 54 sys.stdin = self.real_stdin
54 55
55 56 #-----------------------------------------------------------------------------
56 57 # Tests
57 58 #-----------------------------------------------------------------------------
58 59
59 60 def test_longer_repr():
60 61 from repr import repr as trepr
61 62
62 63 a = '1234567890'* 7
63 64 ar = "'1234567890123456789012345678901234567890123456789012345678901234567890'"
64 65 a_trunc = "'123456789012...8901234567890'"
65 66 nt.assert_equal(trepr(a), a_trunc)
66 67 # The creation of our tracer modifies the repr module's repr function
67 68 # in-place, since that global is used directly by the stdlib's pdb module.
68 69 t = debugger.Tracer()
69 70 nt.assert_equal(trepr(a), ar)
70 71
71 72 def test_ipdb_magics():
72 73 '''Test calling some IPython magics from ipdb.
73 74
74 75 First, set up some test functions and classes which we can inspect.
75 76
76 77 >>> class ExampleClass(object):
77 78 ... """Docstring for ExampleClass."""
78 79 ... def __init__(self):
79 80 ... """Docstring for ExampleClass.__init__"""
80 81 ... pass
81 82 ... def __str__(self):
82 83 ... return "ExampleClass()"
83 84
84 85 >>> def example_function(x, y, z="hello"):
85 86 ... """Docstring for example_function."""
86 87 ... pass
87 88
88 89 >>> old_trace = sys.gettrace()
89 90
90 91 Create a function which triggers ipdb.
91 92
92 93 >>> def trigger_ipdb():
93 94 ... a = ExampleClass()
94 95 ... debugger.Pdb().set_trace()
95 96
96 97 >>> with PdbTestInput([
97 98 ... 'pdef example_function',
98 99 ... 'pdoc ExampleClass',
99 100 ... 'pinfo a',
100 101 ... 'continue',
101 102 ... ]):
102 103 ... trigger_ipdb()
103 104 --Return--
104 105 None
105 106 > <doctest ...>(3)trigger_ipdb()
106 107 1 def trigger_ipdb():
107 108 2 a = ExampleClass()
108 109 ----> 3 debugger.Pdb().set_trace()
109 110 <BLANKLINE>
110 111 ipdb> pdef example_function
111 112 example_function(x, y, z='hello')
112 113 ipdb> pdoc ExampleClass
113 114 Class Docstring:
114 115 Docstring for ExampleClass.
115 116 Constructor Docstring:
116 117 Docstring for ExampleClass.__init__
117 118 ipdb> pinfo a
118 119 Type: ExampleClass
119 120 String Form:ExampleClass()
120 121 Namespace: Local...
121 122 Docstring: Docstring for ExampleClass.
122 123 Constructor Docstring:Docstring for ExampleClass.__init__
123 124 ipdb> continue
124 125
125 126 Restore previous trace function, e.g. for coverage.py
126 127
127 128 >>> sys.settrace(old_trace)
128 129 '''
129 130
130 131 def test_ipdb_magics2():
131 132 '''Test ipdb with a very short function.
132 133
133 134 >>> old_trace = sys.gettrace()
134 135
135 136 >>> def bar():
136 137 ... pass
137 138
138 139 Run ipdb.
139 140
140 141 >>> with PdbTestInput([
141 142 ... 'continue',
142 143 ... ]):
143 144 ... debugger.Pdb().runcall(bar)
144 145 > <doctest ...>(2)bar()
145 146 1 def bar():
146 147 ----> 2 pass
147 148 <BLANKLINE>
148 149 ipdb> continue
149 150
150 151 Restore previous trace function, e.g. for coverage.py
151 152
152 153 >>> sys.settrace(old_trace)
153 154 '''
@@ -1,582 +1,583 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Tests for the inputsplitter module.
3 3
4 4 Authors
5 5 -------
6 6 * Fernando Perez
7 7 * Robert Kern
8 8 """
9 from __future__ import print_function
9 10 #-----------------------------------------------------------------------------
10 11 # Copyright (C) 2010-2011 The IPython Development Team
11 12 #
12 13 # Distributed under the terms of the BSD License. The full license is in
13 14 # the file COPYING, distributed as part of this software.
14 15 #-----------------------------------------------------------------------------
15 16
16 17 #-----------------------------------------------------------------------------
17 18 # Imports
18 19 #-----------------------------------------------------------------------------
19 20 # stdlib
20 21 import unittest
21 22 import sys
22 23
23 24 # Third party
24 25 import nose.tools as nt
25 26
26 27 # Our own
27 28 from IPython.core import inputsplitter as isp
28 29 from IPython.core.tests.test_inputtransformer import syntax, syntax_ml
29 30 from IPython.testing import tools as tt
30 31 from IPython.utils import py3compat
31 32
32 33 #-----------------------------------------------------------------------------
33 34 # Semi-complete examples (also used as tests)
34 35 #-----------------------------------------------------------------------------
35 36
36 37 # Note: at the bottom, there's a slightly more complete version of this that
37 38 # can be useful during development of code here.
38 39
39 40 def mini_interactive_loop(input_func):
40 41 """Minimal example of the logic of an interactive interpreter loop.
41 42
42 43 This serves as an example, and it is used by the test system with a fake
43 44 raw_input that simulates interactive input."""
44 45
45 46 from IPython.core.inputsplitter import InputSplitter
46 47
47 48 isp = InputSplitter()
48 49 # In practice, this input loop would be wrapped in an outside loop to read
49 50 # input indefinitely, until some exit/quit command was issued. Here we
50 51 # only illustrate the basic inner loop.
51 52 while isp.push_accepts_more():
52 53 indent = ' '*isp.indent_spaces
53 54 prompt = '>>> ' + indent
54 55 line = indent + input_func(prompt)
55 56 isp.push(line)
56 57
57 58 # Here we just return input so we can use it in a test suite, but a real
58 59 # interpreter would instead send it for execution somewhere.
59 60 src = isp.source_reset()
60 61 #print 'Input source was:\n', src # dbg
61 62 return src
62 63
63 64 #-----------------------------------------------------------------------------
64 65 # Test utilities, just for local use
65 66 #-----------------------------------------------------------------------------
66 67
67 68 def assemble(block):
68 69 """Assemble a block into multi-line sub-blocks."""
69 70 return ['\n'.join(sub_block)+'\n' for sub_block in block]
70 71
71 72
72 73 def pseudo_input(lines):
73 74 """Return a function that acts like raw_input but feeds the input list."""
74 75 ilines = iter(lines)
75 76 def raw_in(prompt):
76 77 try:
77 78 return next(ilines)
78 79 except StopIteration:
79 80 return ''
80 81 return raw_in
81 82
82 83 #-----------------------------------------------------------------------------
83 84 # Tests
84 85 #-----------------------------------------------------------------------------
85 86 def test_spaces():
86 87 tests = [('', 0),
87 88 (' ', 1),
88 89 ('\n', 0),
89 90 (' \n', 1),
90 91 ('x', 0),
91 92 (' x', 1),
92 93 (' x',2),
93 94 (' x',4),
94 95 # Note: tabs are counted as a single whitespace!
95 96 ('\tx', 1),
96 97 ('\t x', 2),
97 98 ]
98 99 tt.check_pairs(isp.num_ini_spaces, tests)
99 100
100 101
101 102 def test_remove_comments():
102 103 tests = [('text', 'text'),
103 104 ('text # comment', 'text '),
104 105 ('text # comment\n', 'text \n'),
105 106 ('text # comment \n', 'text \n'),
106 107 ('line # c \nline\n','line \nline\n'),
107 108 ('line # c \nline#c2 \nline\nline #c\n\n',
108 109 'line \nline\nline\nline \n\n'),
109 110 ]
110 111 tt.check_pairs(isp.remove_comments, tests)
111 112
112 113
113 114 def test_get_input_encoding():
114 115 encoding = isp.get_input_encoding()
115 116 nt.assert_true(isinstance(encoding, basestring))
116 117 # simple-minded check that at least encoding a simple string works with the
117 118 # encoding we got.
118 119 nt.assert_equal(u'test'.encode(encoding), b'test')
119 120
120 121
121 122 class NoInputEncodingTestCase(unittest.TestCase):
122 123 def setUp(self):
123 124 self.old_stdin = sys.stdin
124 125 class X: pass
125 126 fake_stdin = X()
126 127 sys.stdin = fake_stdin
127 128
128 129 def test(self):
129 130 # Verify that if sys.stdin has no 'encoding' attribute we do the right
130 131 # thing
131 132 enc = isp.get_input_encoding()
132 133 self.assertEqual(enc, 'ascii')
133 134
134 135 def tearDown(self):
135 136 sys.stdin = self.old_stdin
136 137
137 138
138 139 class InputSplitterTestCase(unittest.TestCase):
139 140 def setUp(self):
140 141 self.isp = isp.InputSplitter()
141 142
142 143 def test_reset(self):
143 144 isp = self.isp
144 145 isp.push('x=1')
145 146 isp.reset()
146 147 self.assertEqual(isp._buffer, [])
147 148 self.assertEqual(isp.indent_spaces, 0)
148 149 self.assertEqual(isp.source, '')
149 150 self.assertEqual(isp.code, None)
150 151 self.assertEqual(isp._is_complete, False)
151 152
152 153 def test_source(self):
153 154 self.isp._store('1')
154 155 self.isp._store('2')
155 156 self.assertEqual(self.isp.source, '1\n2\n')
156 157 self.assertTrue(len(self.isp._buffer)>0)
157 158 self.assertEqual(self.isp.source_reset(), '1\n2\n')
158 159 self.assertEqual(self.isp._buffer, [])
159 160 self.assertEqual(self.isp.source, '')
160 161
161 162 def test_indent(self):
162 163 isp = self.isp # shorthand
163 164 isp.push('x=1')
164 165 self.assertEqual(isp.indent_spaces, 0)
165 166 isp.push('if 1:\n x=1')
166 167 self.assertEqual(isp.indent_spaces, 4)
167 168 isp.push('y=2\n')
168 169 self.assertEqual(isp.indent_spaces, 0)
169 170
170 171 def test_indent2(self):
171 172 isp = self.isp
172 173 isp.push('if 1:')
173 174 self.assertEqual(isp.indent_spaces, 4)
174 175 isp.push(' x=1')
175 176 self.assertEqual(isp.indent_spaces, 4)
176 177 # Blank lines shouldn't change the indent level
177 178 isp.push(' '*2)
178 179 self.assertEqual(isp.indent_spaces, 4)
179 180
180 181 def test_indent3(self):
181 182 isp = self.isp
182 183 # When a multiline statement contains parens or multiline strings, we
183 184 # shouldn't get confused.
184 185 isp.push("if 1:")
185 186 isp.push(" x = (1+\n 2)")
186 187 self.assertEqual(isp.indent_spaces, 4)
187 188
188 189 def test_indent4(self):
189 190 isp = self.isp
190 191 # whitespace after ':' should not screw up indent level
191 192 isp.push('if 1: \n x=1')
192 193 self.assertEqual(isp.indent_spaces, 4)
193 194 isp.push('y=2\n')
194 195 self.assertEqual(isp.indent_spaces, 0)
195 196 isp.push('if 1:\t\n x=1')
196 197 self.assertEqual(isp.indent_spaces, 4)
197 198 isp.push('y=2\n')
198 199 self.assertEqual(isp.indent_spaces, 0)
199 200
200 201 def test_dedent_pass(self):
201 202 isp = self.isp # shorthand
202 203 # should NOT cause dedent
203 204 isp.push('if 1:\n passes = 5')
204 205 self.assertEqual(isp.indent_spaces, 4)
205 206 isp.push('if 1:\n pass')
206 207 self.assertEqual(isp.indent_spaces, 0)
207 208 isp.push('if 1:\n pass ')
208 209 self.assertEqual(isp.indent_spaces, 0)
209 210
210 211 def test_dedent_break(self):
211 212 isp = self.isp # shorthand
212 213 # should NOT cause dedent
213 214 isp.push('while 1:\n breaks = 5')
214 215 self.assertEqual(isp.indent_spaces, 4)
215 216 isp.push('while 1:\n break')
216 217 self.assertEqual(isp.indent_spaces, 0)
217 218 isp.push('while 1:\n break ')
218 219 self.assertEqual(isp.indent_spaces, 0)
219 220
220 221 def test_dedent_continue(self):
221 222 isp = self.isp # shorthand
222 223 # should NOT cause dedent
223 224 isp.push('while 1:\n continues = 5')
224 225 self.assertEqual(isp.indent_spaces, 4)
225 226 isp.push('while 1:\n continue')
226 227 self.assertEqual(isp.indent_spaces, 0)
227 228 isp.push('while 1:\n continue ')
228 229 self.assertEqual(isp.indent_spaces, 0)
229 230
230 231 def test_dedent_raise(self):
231 232 isp = self.isp # shorthand
232 233 # should NOT cause dedent
233 234 isp.push('if 1:\n raised = 4')
234 235 self.assertEqual(isp.indent_spaces, 4)
235 236 isp.push('if 1:\n raise TypeError()')
236 237 self.assertEqual(isp.indent_spaces, 0)
237 238 isp.push('if 1:\n raise')
238 239 self.assertEqual(isp.indent_spaces, 0)
239 240 isp.push('if 1:\n raise ')
240 241 self.assertEqual(isp.indent_spaces, 0)
241 242
242 243 def test_dedent_return(self):
243 244 isp = self.isp # shorthand
244 245 # should NOT cause dedent
245 246 isp.push('if 1:\n returning = 4')
246 247 self.assertEqual(isp.indent_spaces, 4)
247 248 isp.push('if 1:\n return 5 + 493')
248 249 self.assertEqual(isp.indent_spaces, 0)
249 250 isp.push('if 1:\n return')
250 251 self.assertEqual(isp.indent_spaces, 0)
251 252 isp.push('if 1:\n return ')
252 253 self.assertEqual(isp.indent_spaces, 0)
253 254 isp.push('if 1:\n return(0)')
254 255 self.assertEqual(isp.indent_spaces, 0)
255 256
256 257 def test_push(self):
257 258 isp = self.isp
258 259 self.assertTrue(isp.push('x=1'))
259 260
260 261 def test_push2(self):
261 262 isp = self.isp
262 263 self.assertFalse(isp.push('if 1:'))
263 264 for line in [' x=1', '# a comment', ' y=2']:
264 265 print(line)
265 266 self.assertTrue(isp.push(line))
266 267
267 268 def test_push3(self):
268 269 isp = self.isp
269 270 isp.push('if True:')
270 271 isp.push(' a = 1')
271 272 self.assertFalse(isp.push('b = [1,'))
272 273
273 274 def test_push_accepts_more(self):
274 275 isp = self.isp
275 276 isp.push('x=1')
276 277 self.assertFalse(isp.push_accepts_more())
277 278
278 279 def test_push_accepts_more2(self):
279 280 isp = self.isp
280 281 isp.push('if 1:')
281 282 self.assertTrue(isp.push_accepts_more())
282 283 isp.push(' x=1')
283 284 self.assertTrue(isp.push_accepts_more())
284 285 isp.push('')
285 286 self.assertFalse(isp.push_accepts_more())
286 287
287 288 def test_push_accepts_more3(self):
288 289 isp = self.isp
289 290 isp.push("x = (2+\n3)")
290 291 self.assertFalse(isp.push_accepts_more())
291 292
292 293 def test_push_accepts_more4(self):
293 294 isp = self.isp
294 295 # When a multiline statement contains parens or multiline strings, we
295 296 # shouldn't get confused.
296 297 # FIXME: we should be able to better handle de-dents in statements like
297 298 # multiline strings and multiline expressions (continued with \ or
298 299 # parens). Right now we aren't handling the indentation tracking quite
299 300 # correctly with this, though in practice it may not be too much of a
300 301 # problem. We'll need to see.
301 302 isp.push("if 1:")
302 303 isp.push(" x = (2+")
303 304 isp.push(" 3)")
304 305 self.assertTrue(isp.push_accepts_more())
305 306 isp.push(" y = 3")
306 307 self.assertTrue(isp.push_accepts_more())
307 308 isp.push('')
308 309 self.assertFalse(isp.push_accepts_more())
309 310
310 311 def test_push_accepts_more5(self):
311 312 isp = self.isp
312 313 isp.push('try:')
313 314 isp.push(' a = 5')
314 315 isp.push('except:')
315 316 isp.push(' raise')
316 317 # We want to be able to add an else: block at this point, so it should
317 318 # wait for a blank line.
318 319 self.assertTrue(isp.push_accepts_more())
319 320
320 321 def test_continuation(self):
321 322 isp = self.isp
322 323 isp.push("import os, \\")
323 324 self.assertTrue(isp.push_accepts_more())
324 325 isp.push("sys")
325 326 self.assertFalse(isp.push_accepts_more())
326 327
327 328 def test_syntax_error(self):
328 329 isp = self.isp
329 330 # Syntax errors immediately produce a 'ready' block, so the invalid
330 331 # Python can be sent to the kernel for evaluation with possible ipython
331 332 # special-syntax conversion.
332 333 isp.push('run foo')
333 334 self.assertFalse(isp.push_accepts_more())
334 335
335 336 def test_unicode(self):
336 337 self.isp.push(u"Pérez")
337 338 self.isp.push(u'\xc3\xa9')
338 339 self.isp.push(u"u'\xc3\xa9'")
339 340
340 341 def test_line_continuation(self):
341 342 """ Test issue #2108."""
342 343 isp = self.isp
343 344 # A blank line after a line continuation should not accept more
344 345 isp.push("1 \\\n\n")
345 346 self.assertFalse(isp.push_accepts_more())
346 347 # Whitespace after a \ is a SyntaxError. The only way to test that
347 348 # here is to test that push doesn't accept more (as with
348 349 # test_syntax_error() above).
349 350 isp.push(r"1 \ ")
350 351 self.assertFalse(isp.push_accepts_more())
351 352 # Even if the line is continuable (c.f. the regular Python
352 353 # interpreter)
353 354 isp.push(r"(1 \ ")
354 355 self.assertFalse(isp.push_accepts_more())
355 356
356 357 class InteractiveLoopTestCase(unittest.TestCase):
357 358 """Tests for an interactive loop like a python shell.
358 359 """
359 360 def check_ns(self, lines, ns):
360 361 """Validate that the given input lines produce the resulting namespace.
361 362
362 363 Note: the input lines are given exactly as they would be typed in an
363 364 auto-indenting environment, as mini_interactive_loop above already does
364 365 auto-indenting and prepends spaces to the input.
365 366 """
366 367 src = mini_interactive_loop(pseudo_input(lines))
367 368 test_ns = {}
368 369 exec src in test_ns
369 370 # We can't check that the provided ns is identical to the test_ns,
370 371 # because Python fills test_ns with extra keys (copyright, etc). But
371 372 # we can check that the given dict is *contained* in test_ns
372 373 for k,v in ns.iteritems():
373 374 self.assertEqual(test_ns[k], v)
374 375
375 376 def test_simple(self):
376 377 self.check_ns(['x=1'], dict(x=1))
377 378
378 379 def test_simple2(self):
379 380 self.check_ns(['if 1:', 'x=2'], dict(x=2))
380 381
381 382 def test_xy(self):
382 383 self.check_ns(['x=1; y=2'], dict(x=1, y=2))
383 384
384 385 def test_abc(self):
385 386 self.check_ns(['if 1:','a=1','b=2','c=3'], dict(a=1, b=2, c=3))
386 387
387 388 def test_multi(self):
388 389 self.check_ns(['x =(1+','1+','2)'], dict(x=4))
389 390
390 391
391 392 class IPythonInputTestCase(InputSplitterTestCase):
392 393 """By just creating a new class whose .isp is a different instance, we
393 394 re-run the same test battery on the new input splitter.
394 395
395 396 In addition, this runs the tests over the syntax and syntax_ml dicts that
396 397 were tested by individual functions, as part of the OO interface.
397 398
398 399 It also makes some checks on the raw buffer storage.
399 400 """
400 401
401 402 def setUp(self):
402 403 self.isp = isp.IPythonInputSplitter()
403 404
404 405 def test_syntax(self):
405 406 """Call all single-line syntax tests from the main object"""
406 407 isp = self.isp
407 408 for example in syntax.itervalues():
408 409 for raw, out_t in example:
409 410 if raw.startswith(' '):
410 411 continue
411 412
412 413 isp.push(raw+'\n')
413 414 out, out_raw = isp.source_raw_reset()
414 415 self.assertEqual(out.rstrip(), out_t,
415 416 tt.pair_fail_msg.format("inputsplitter",raw, out_t, out))
416 417 self.assertEqual(out_raw.rstrip(), raw.rstrip())
417 418
418 419 def test_syntax_multiline(self):
419 420 isp = self.isp
420 421 for example in syntax_ml.itervalues():
421 422 for line_pairs in example:
422 423 out_t_parts = []
423 424 raw_parts = []
424 425 for lraw, out_t_part in line_pairs:
425 426 if out_t_part is not None:
426 427 out_t_parts.append(out_t_part)
427 428
428 429 if lraw is not None:
429 430 isp.push(lraw)
430 431 raw_parts.append(lraw)
431 432
432 433 out, out_raw = isp.source_raw_reset()
433 434 out_t = '\n'.join(out_t_parts).rstrip()
434 435 raw = '\n'.join(raw_parts).rstrip()
435 436 self.assertEqual(out.rstrip(), out_t)
436 437 self.assertEqual(out_raw.rstrip(), raw)
437 438
438 439 def test_syntax_multiline_cell(self):
439 440 isp = self.isp
440 441 for example in syntax_ml.itervalues():
441 442
442 443 out_t_parts = []
443 444 for line_pairs in example:
444 445 raw = '\n'.join(r for r, _ in line_pairs if r is not None)
445 446 out_t = '\n'.join(t for _,t in line_pairs if t is not None)
446 447 out = isp.transform_cell(raw)
447 448 # Match ignoring trailing whitespace
448 449 self.assertEqual(out.rstrip(), out_t.rstrip())
449 450
450 451 def test_cellmagic_preempt(self):
451 452 isp = self.isp
452 453 for raw, name, line, cell in [
453 454 ("%%cellm a\nIn[1]:", u'cellm', u'a', u'In[1]:'),
454 455 ("%%cellm \nline\n>>>hi", u'cellm', u'', u'line\n>>>hi'),
455 456 (">>>%%cellm \nline\n>>>hi", u'cellm', u'', u'line\nhi'),
456 457 ("%%cellm \n>>>hi", u'cellm', u'', u'hi'),
457 458 ("%%cellm \nline1\nline2", u'cellm', u'', u'line1\nline2'),
458 459 ("%%cellm \nline1\\\\\nline2", u'cellm', u'', u'line1\\\\\nline2'),
459 460 ]:
460 461 expected = "get_ipython().run_cell_magic(%r, %r, %r)" % (
461 462 name, line, cell
462 463 )
463 464 out = isp.transform_cell(raw)
464 465 self.assertEqual(out.rstrip(), expected.rstrip())
465 466
466 467
467 468
468 469 #-----------------------------------------------------------------------------
469 470 # Main - use as a script, mostly for developer experiments
470 471 #-----------------------------------------------------------------------------
471 472
472 473 if __name__ == '__main__':
473 474 # A simple demo for interactive experimentation. This code will not get
474 475 # picked up by any test suite.
475 476 from IPython.core.inputsplitter import InputSplitter, IPythonInputSplitter
476 477
477 478 # configure here the syntax to use, prompt and whether to autoindent
478 479 #isp, start_prompt = InputSplitter(), '>>> '
479 480 isp, start_prompt = IPythonInputSplitter(), 'In> '
480 481
481 482 autoindent = True
482 483 #autoindent = False
483 484
484 485 try:
485 486 while True:
486 487 prompt = start_prompt
487 488 while isp.push_accepts_more():
488 489 indent = ' '*isp.indent_spaces
489 490 if autoindent:
490 491 line = indent + raw_input(prompt+indent)
491 492 else:
492 493 line = raw_input(prompt)
493 494 isp.push(line)
494 495 prompt = '... '
495 496
496 497 # Here we just return input so we can use it in a test suite, but a
497 498 # real interpreter would instead send it for execution somewhere.
498 499 #src = isp.source; raise EOFError # dbg
499 500 src, raw = isp.source_raw_reset()
500 print 'Input source was:\n', src
501 print 'Raw source was:\n', raw
501 print('Input source was:\n', src)
502 print('Raw source was:\n', raw)
502 503 except EOFError:
503 print 'Bye'
504 print('Bye')
504 505
505 506 # Tests for cell magics support
506 507
507 508 def test_last_blank():
508 509 nt.assert_false(isp.last_blank(''))
509 510 nt.assert_false(isp.last_blank('abc'))
510 511 nt.assert_false(isp.last_blank('abc\n'))
511 512 nt.assert_false(isp.last_blank('abc\na'))
512 513
513 514 nt.assert_true(isp.last_blank('\n'))
514 515 nt.assert_true(isp.last_blank('\n '))
515 516 nt.assert_true(isp.last_blank('abc\n '))
516 517 nt.assert_true(isp.last_blank('abc\n\n'))
517 518 nt.assert_true(isp.last_blank('abc\nd\n\n'))
518 519 nt.assert_true(isp.last_blank('abc\nd\ne\n\n'))
519 520 nt.assert_true(isp.last_blank('abc \n \n \n\n'))
520 521
521 522
522 523 def test_last_two_blanks():
523 524 nt.assert_false(isp.last_two_blanks(''))
524 525 nt.assert_false(isp.last_two_blanks('abc'))
525 526 nt.assert_false(isp.last_two_blanks('abc\n'))
526 527 nt.assert_false(isp.last_two_blanks('abc\n\na'))
527 528 nt.assert_false(isp.last_two_blanks('abc\n \n'))
528 529 nt.assert_false(isp.last_two_blanks('abc\n\n'))
529 530
530 531 nt.assert_true(isp.last_two_blanks('\n\n'))
531 532 nt.assert_true(isp.last_two_blanks('\n\n '))
532 533 nt.assert_true(isp.last_two_blanks('\n \n'))
533 534 nt.assert_true(isp.last_two_blanks('abc\n\n '))
534 535 nt.assert_true(isp.last_two_blanks('abc\n\n\n'))
535 536 nt.assert_true(isp.last_two_blanks('abc\n\n \n'))
536 537 nt.assert_true(isp.last_two_blanks('abc\n\n \n '))
537 538 nt.assert_true(isp.last_two_blanks('abc\n\n \n \n'))
538 539 nt.assert_true(isp.last_two_blanks('abc\nd\n\n\n'))
539 540 nt.assert_true(isp.last_two_blanks('abc\nd\ne\nf\n\n\n'))
540 541
541 542
542 543 class CellMagicsCommon(object):
543 544
544 545 def test_whole_cell(self):
545 546 src = "%%cellm line\nbody\n"
546 547 sp = self.sp
547 548 sp.push(src)
548 549 out = sp.source_reset()
549 550 ref = u"get_ipython().run_cell_magic({u}'cellm', {u}'line', {u}'body')\n"
550 551 nt.assert_equal(out, py3compat.u_format(ref))
551 552
552 553 def test_cellmagic_help(self):
553 554 self.sp.push('%%cellm?')
554 555 nt.assert_false(self.sp.push_accepts_more())
555 556
556 557 def tearDown(self):
557 558 self.sp.reset()
558 559
559 560
560 561 class CellModeCellMagics(CellMagicsCommon, unittest.TestCase):
561 562 sp = isp.IPythonInputSplitter(line_input_checker=False)
562 563
563 564 def test_incremental(self):
564 565 sp = self.sp
565 566 sp.push('%%cellm firstline\n')
566 567 nt.assert_true(sp.push_accepts_more()) #1
567 568 sp.push('line2\n')
568 569 nt.assert_true(sp.push_accepts_more()) #2
569 570 sp.push('\n')
570 571 # This should accept a blank line and carry on until the cell is reset
571 572 nt.assert_true(sp.push_accepts_more()) #3
572 573
573 574 class LineModeCellMagics(CellMagicsCommon, unittest.TestCase):
574 575 sp = isp.IPythonInputSplitter(line_input_checker=True)
575 576
576 577 def test_incremental(self):
577 578 sp = self.sp
578 579 sp.push('%%cellm line2\n')
579 580 nt.assert_true(sp.push_accepts_more()) #1
580 581 sp.push('\n')
581 582 # In this case, a blank line should end the cell magic
582 583 nt.assert_false(sp.push_accepts_more()) #2
@@ -1,1266 +1,1267 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 ultratb.py -- Spice up your tracebacks!
4 4
5 5 * ColorTB
6 6 I've always found it a bit hard to visually parse tracebacks in Python. The
7 7 ColorTB class is a solution to that problem. It colors the different parts of a
8 8 traceback in a manner similar to what you would expect from a syntax-highlighting
9 9 text editor.
10 10
11 11 Installation instructions for ColorTB::
12 12
13 13 import sys,ultratb
14 14 sys.excepthook = ultratb.ColorTB()
15 15
16 16 * VerboseTB
17 17 I've also included a port of Ka-Ping Yee's "cgitb.py" that produces all kinds
18 18 of useful info when a traceback occurs. Ping originally had it spit out HTML
19 19 and intended it for CGI programmers, but why should they have all the fun? I
20 20 altered it to spit out colored text to the terminal. It's a bit overwhelming,
21 21 but kind of neat, and maybe useful for long-running programs that you believe
22 22 are bug-free. If a crash *does* occur in that type of program you want details.
23 23 Give it a shot--you'll love it or you'll hate it.
24 24
25 25 .. note::
26 26
27 27 The Verbose mode prints the variables currently visible where the exception
28 28 happened (shortening their strings if too long). This can potentially be
29 29 very slow, if you happen to have a huge data structure whose string
30 30 representation is complex to compute. Your computer may appear to freeze for
31 31 a while with cpu usage at 100%. If this occurs, you can cancel the traceback
32 32 with Ctrl-C (maybe hitting it more than once).
33 33
34 34 If you encounter this kind of situation often, you may want to use the
35 35 Verbose_novars mode instead of the regular Verbose, which avoids formatting
36 36 variables (but otherwise includes the information and context given by
37 37 Verbose).
38 38
39 39
40 40 Installation instructions for ColorTB::
41 41
42 42 import sys,ultratb
43 43 sys.excepthook = ultratb.VerboseTB()
44 44
45 45 Note: Much of the code in this module was lifted verbatim from the standard
46 46 library module 'traceback.py' and Ka-Ping Yee's 'cgitb.py'.
47 47
48 48 Color schemes
49 49 -------------
50 50
51 51 The colors are defined in the class TBTools through the use of the
52 52 ColorSchemeTable class. Currently the following exist:
53 53
54 54 - NoColor: allows all of this module to be used in any terminal (the color
55 55 escapes are just dummy blank strings).
56 56
57 57 - Linux: is meant to look good in a terminal like the Linux console (black
58 58 or very dark background).
59 59
60 60 - LightBG: similar to Linux but swaps dark/light colors to be more readable
61 61 in light background terminals.
62 62
63 63 You can implement other color schemes easily, the syntax is fairly
64 64 self-explanatory. Please send back new schemes you develop to the author for
65 65 possible inclusion in future releases.
66 66
67 67 Inheritance diagram:
68 68
69 69 .. inheritance-diagram:: IPython.core.ultratb
70 70 :parts: 3
71 71 """
72 72
73 73 #*****************************************************************************
74 74 # Copyright (C) 2001 Nathaniel Gray <n8gray@caltech.edu>
75 75 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
76 76 #
77 77 # Distributed under the terms of the BSD License. The full license is in
78 78 # the file COPYING, distributed as part of this software.
79 79 #*****************************************************************************
80 80
81 81 from __future__ import unicode_literals
82 from __future__ import print_function
82 83
83 84 import inspect
84 85 import keyword
85 86 import linecache
86 87 import os
87 88 import pydoc
88 89 import re
89 90 import sys
90 91 import time
91 92 import tokenize
92 93 import traceback
93 94 import types
94 95
95 96 try: # Python 2
96 97 generate_tokens = tokenize.generate_tokens
97 98 except AttributeError: # Python 3
98 99 generate_tokens = tokenize.tokenize
99 100
100 101 # For purposes of monkeypatching inspect to fix a bug in it.
101 102 from inspect import getsourcefile, getfile, getmodule,\
102 103 ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode
103 104
104 105 # IPython's own modules
105 106 # Modified pdb which doesn't damage IPython's readline handling
106 107 from IPython import get_ipython
107 108 from IPython.core import debugger
108 109 from IPython.core.display_trap import DisplayTrap
109 110 from IPython.core.excolors import exception_colors
110 111 from IPython.utils import PyColorize
111 112 from IPython.utils import io
112 113 from IPython.utils import openpy
113 114 from IPython.utils import path as util_path
114 115 from IPython.utils import py3compat
115 116 from IPython.utils import ulinecache
116 117 from IPython.utils.data import uniq_stable
117 118 from IPython.utils.warn import info, error
118 119
119 120 # Globals
120 121 # amount of space to put line numbers before verbose tracebacks
121 122 INDENT_SIZE = 8
122 123
123 124 # Default color scheme. This is used, for example, by the traceback
124 125 # formatter. When running in an actual IPython instance, the user's rc.colors
125 126 # value is used, but havinga module global makes this functionality available
126 127 # to users of ultratb who are NOT running inside ipython.
127 128 DEFAULT_SCHEME = 'NoColor'
128 129
129 130 #---------------------------------------------------------------------------
130 131 # Code begins
131 132
132 133 # Utility functions
133 134 def inspect_error():
134 135 """Print a message about internal inspect errors.
135 136
136 137 These are unfortunately quite common."""
137 138
138 139 error('Internal Python error in the inspect module.\n'
139 140 'Below is the traceback from this internal error.\n')
140 141
141 142 # This function is a monkeypatch we apply to the Python inspect module. We have
142 143 # now found when it's needed (see discussion on issue gh-1456), and we have a
143 144 # test case (IPython.core.tests.test_ultratb.ChangedPyFileTest) that fails if
144 145 # the monkeypatch is not applied. TK, Aug 2012.
145 146 def findsource(object):
146 147 """Return the entire source file and starting line number for an object.
147 148
148 149 The argument may be a module, class, method, function, traceback, frame,
149 150 or code object. The source code is returned as a list of all the lines
150 151 in the file and the line number indexes a line in that list. An IOError
151 152 is raised if the source code cannot be retrieved.
152 153
153 154 FIXED version with which we monkeypatch the stdlib to work around a bug."""
154 155
155 156 file = getsourcefile(object) or getfile(object)
156 157 # If the object is a frame, then trying to get the globals dict from its
157 158 # module won't work. Instead, the frame object itself has the globals
158 159 # dictionary.
159 160 globals_dict = None
160 161 if inspect.isframe(object):
161 162 # XXX: can this ever be false?
162 163 globals_dict = object.f_globals
163 164 else:
164 165 module = getmodule(object, file)
165 166 if module:
166 167 globals_dict = module.__dict__
167 168 lines = linecache.getlines(file, globals_dict)
168 169 if not lines:
169 170 raise IOError('could not get source code')
170 171
171 172 if ismodule(object):
172 173 return lines, 0
173 174
174 175 if isclass(object):
175 176 name = object.__name__
176 177 pat = re.compile(r'^(\s*)class\s*' + name + r'\b')
177 178 # make some effort to find the best matching class definition:
178 179 # use the one with the least indentation, which is the one
179 180 # that's most probably not inside a function definition.
180 181 candidates = []
181 182 for i in range(len(lines)):
182 183 match = pat.match(lines[i])
183 184 if match:
184 185 # if it's at toplevel, it's already the best one
185 186 if lines[i][0] == 'c':
186 187 return lines, i
187 188 # else add whitespace to candidate list
188 189 candidates.append((match.group(1), i))
189 190 if candidates:
190 191 # this will sort by whitespace, and by line number,
191 192 # less whitespace first
192 193 candidates.sort()
193 194 return lines, candidates[0][1]
194 195 else:
195 196 raise IOError('could not find class definition')
196 197
197 198 if ismethod(object):
198 199 object = object.im_func
199 200 if isfunction(object):
200 201 object = object.func_code
201 202 if istraceback(object):
202 203 object = object.tb_frame
203 204 if isframe(object):
204 205 object = object.f_code
205 206 if iscode(object):
206 207 if not hasattr(object, 'co_firstlineno'):
207 208 raise IOError('could not find function definition')
208 209 pat = re.compile(r'^(\s*def\s)|(.*(?<!\w)lambda(:|\s))|^(\s*@)')
209 210 pmatch = pat.match
210 211 # fperez - fix: sometimes, co_firstlineno can give a number larger than
211 212 # the length of lines, which causes an error. Safeguard against that.
212 213 lnum = min(object.co_firstlineno,len(lines))-1
213 214 while lnum > 0:
214 215 if pmatch(lines[lnum]): break
215 216 lnum -= 1
216 217
217 218 return lines, lnum
218 219 raise IOError('could not find code object')
219 220
220 221 # Monkeypatch inspect to apply our bugfix. This code only works with Python >= 2.5
221 222 inspect.findsource = findsource
222 223
223 224 def fix_frame_records_filenames(records):
224 225 """Try to fix the filenames in each record from inspect.getinnerframes().
225 226
226 227 Particularly, modules loaded from within zip files have useless filenames
227 228 attached to their code object, and inspect.getinnerframes() just uses it.
228 229 """
229 230 fixed_records = []
230 231 for frame, filename, line_no, func_name, lines, index in records:
231 232 # Look inside the frame's globals dictionary for __file__, which should
232 233 # be better.
233 234 better_fn = frame.f_globals.get('__file__', None)
234 235 if isinstance(better_fn, str):
235 236 # Check the type just in case someone did something weird with
236 237 # __file__. It might also be None if the error occurred during
237 238 # import.
238 239 filename = better_fn
239 240 fixed_records.append((frame, filename, line_no, func_name, lines, index))
240 241 return fixed_records
241 242
242 243
243 244 def _fixed_getinnerframes(etb, context=1,tb_offset=0):
244 245 LNUM_POS, LINES_POS, INDEX_POS = 2, 4, 5
245 246
246 247 records = fix_frame_records_filenames(inspect.getinnerframes(etb, context))
247 248
248 249 # If the error is at the console, don't build any context, since it would
249 250 # otherwise produce 5 blank lines printed out (there is no file at the
250 251 # console)
251 252 rec_check = records[tb_offset:]
252 253 try:
253 254 rname = rec_check[0][1]
254 255 if rname == '<ipython console>' or rname.endswith('<string>'):
255 256 return rec_check
256 257 except IndexError:
257 258 pass
258 259
259 260 aux = traceback.extract_tb(etb)
260 261 assert len(records) == len(aux)
261 262 for i, (file, lnum, _, _) in zip(range(len(records)), aux):
262 263 maybeStart = lnum-1 - context//2
263 264 start = max(maybeStart, 0)
264 265 end = start + context
265 266 lines = ulinecache.getlines(file)[start:end]
266 267 buf = list(records[i])
267 268 buf[LNUM_POS] = lnum
268 269 buf[INDEX_POS] = lnum - 1 - start
269 270 buf[LINES_POS] = lines
270 271 records[i] = tuple(buf)
271 272 return records[tb_offset:]
272 273
273 274 # Helper function -- largely belongs to VerboseTB, but we need the same
274 275 # functionality to produce a pseudo verbose TB for SyntaxErrors, so that they
275 276 # can be recognized properly by ipython.el's py-traceback-line-re
276 277 # (SyntaxErrors have to be treated specially because they have no traceback)
277 278
278 279 _parser = PyColorize.Parser()
279 280
280 281 def _format_traceback_lines(lnum, index, lines, Colors, lvals=None,scheme=None):
281 282 numbers_width = INDENT_SIZE - 1
282 283 res = []
283 284 i = lnum - index
284 285
285 286 # This lets us get fully syntax-highlighted tracebacks.
286 287 if scheme is None:
287 288 ipinst = get_ipython()
288 289 if ipinst is not None:
289 290 scheme = ipinst.colors
290 291 else:
291 292 scheme = DEFAULT_SCHEME
292 293
293 294 _line_format = _parser.format2
294 295
295 296 for line in lines:
296 297 line = py3compat.cast_unicode(line)
297 298
298 299 new_line, err = _line_format(line, 'str', scheme)
299 300 if not err: line = new_line
300 301
301 302 if i == lnum:
302 303 # This is the line with the error
303 304 pad = numbers_width - len(str(i))
304 305 if pad >= 3:
305 306 marker = '-'*(pad-3) + '-> '
306 307 elif pad == 2:
307 308 marker = '> '
308 309 elif pad == 1:
309 310 marker = '>'
310 311 else:
311 312 marker = ''
312 313 num = marker + str(i)
313 314 line = '%s%s%s %s%s' %(Colors.linenoEm, num,
314 315 Colors.line, line, Colors.Normal)
315 316 else:
316 317 num = '%*s' % (numbers_width,i)
317 318 line = '%s%s%s %s' %(Colors.lineno, num,
318 319 Colors.Normal, line)
319 320
320 321 res.append(line)
321 322 if lvals and i == lnum:
322 323 res.append(lvals + '\n')
323 324 i = i + 1
324 325 return res
325 326
326 327
327 328 #---------------------------------------------------------------------------
328 329 # Module classes
329 330 class TBTools(object):
330 331 """Basic tools used by all traceback printer classes."""
331 332
332 333 # Number of frames to skip when reporting tracebacks
333 334 tb_offset = 0
334 335
335 336 def __init__(self, color_scheme='NoColor', call_pdb=False, ostream=None):
336 337 # Whether to call the interactive pdb debugger after printing
337 338 # tracebacks or not
338 339 self.call_pdb = call_pdb
339 340
340 341 # Output stream to write to. Note that we store the original value in
341 342 # a private attribute and then make the public ostream a property, so
342 343 # that we can delay accessing io.stdout until runtime. The way
343 344 # things are written now, the io.stdout object is dynamically managed
344 345 # so a reference to it should NEVER be stored statically. This
345 346 # property approach confines this detail to a single location, and all
346 347 # subclasses can simply access self.ostream for writing.
347 348 self._ostream = ostream
348 349
349 350 # Create color table
350 351 self.color_scheme_table = exception_colors()
351 352
352 353 self.set_colors(color_scheme)
353 354 self.old_scheme = color_scheme # save initial value for toggles
354 355
355 356 if call_pdb:
356 357 self.pdb = debugger.Pdb(self.color_scheme_table.active_scheme_name)
357 358 else:
358 359 self.pdb = None
359 360
360 361 def _get_ostream(self):
361 362 """Output stream that exceptions are written to.
362 363
363 364 Valid values are:
364 365
365 366 - None: the default, which means that IPython will dynamically resolve
366 367 to io.stdout. This ensures compatibility with most tools, including
367 368 Windows (where plain stdout doesn't recognize ANSI escapes).
368 369
369 370 - Any object with 'write' and 'flush' attributes.
370 371 """
371 372 return io.stdout if self._ostream is None else self._ostream
372 373
373 374 def _set_ostream(self, val):
374 375 assert val is None or (hasattr(val, 'write') and hasattr(val, 'flush'))
375 376 self._ostream = val
376 377
377 378 ostream = property(_get_ostream, _set_ostream)
378 379
379 380 def set_colors(self,*args,**kw):
380 381 """Shorthand access to the color table scheme selector method."""
381 382
382 383 # Set own color table
383 384 self.color_scheme_table.set_active_scheme(*args,**kw)
384 385 # for convenience, set Colors to the active scheme
385 386 self.Colors = self.color_scheme_table.active_colors
386 387 # Also set colors of debugger
387 388 if hasattr(self,'pdb') and self.pdb is not None:
388 389 self.pdb.set_colors(*args,**kw)
389 390
390 391 def color_toggle(self):
391 392 """Toggle between the currently active color scheme and NoColor."""
392 393
393 394 if self.color_scheme_table.active_scheme_name == 'NoColor':
394 395 self.color_scheme_table.set_active_scheme(self.old_scheme)
395 396 self.Colors = self.color_scheme_table.active_colors
396 397 else:
397 398 self.old_scheme = self.color_scheme_table.active_scheme_name
398 399 self.color_scheme_table.set_active_scheme('NoColor')
399 400 self.Colors = self.color_scheme_table.active_colors
400 401
401 402 def stb2text(self, stb):
402 403 """Convert a structured traceback (a list) to a string."""
403 404 return '\n'.join(stb)
404 405
405 406 def text(self, etype, value, tb, tb_offset=None, context=5):
406 407 """Return formatted traceback.
407 408
408 409 Subclasses may override this if they add extra arguments.
409 410 """
410 411 tb_list = self.structured_traceback(etype, value, tb,
411 412 tb_offset, context)
412 413 return self.stb2text(tb_list)
413 414
414 415 def structured_traceback(self, etype, evalue, tb, tb_offset=None,
415 416 context=5, mode=None):
416 417 """Return a list of traceback frames.
417 418
418 419 Must be implemented by each class.
419 420 """
420 421 raise NotImplementedError()
421 422
422 423
423 424 #---------------------------------------------------------------------------
424 425 class ListTB(TBTools):
425 426 """Print traceback information from a traceback list, with optional color.
426 427
427 428 Calling requires 3 arguments: (etype, evalue, elist)
428 429 as would be obtained by::
429 430
430 431 etype, evalue, tb = sys.exc_info()
431 432 if tb:
432 433 elist = traceback.extract_tb(tb)
433 434 else:
434 435 elist = None
435 436
436 437 It can thus be used by programs which need to process the traceback before
437 438 printing (such as console replacements based on the code module from the
438 439 standard library).
439 440
440 441 Because they are meant to be called without a full traceback (only a
441 442 list), instances of this class can't call the interactive pdb debugger."""
442 443
443 444 def __init__(self,color_scheme = 'NoColor', call_pdb=False, ostream=None):
444 445 TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
445 446 ostream=ostream)
446 447
447 448 def __call__(self, etype, value, elist):
448 449 self.ostream.flush()
449 450 self.ostream.write(self.text(etype, value, elist))
450 451 self.ostream.write('\n')
451 452
452 453 def structured_traceback(self, etype, value, elist, tb_offset=None,
453 454 context=5):
454 455 """Return a color formatted string with the traceback info.
455 456
456 457 Parameters
457 458 ----------
458 459 etype : exception type
459 460 Type of the exception raised.
460 461
461 462 value : object
462 463 Data stored in the exception
463 464
464 465 elist : list
465 466 List of frames, see class docstring for details.
466 467
467 468 tb_offset : int, optional
468 469 Number of frames in the traceback to skip. If not given, the
469 470 instance value is used (set in constructor).
470 471
471 472 context : int, optional
472 473 Number of lines of context information to print.
473 474
474 475 Returns
475 476 -------
476 477 String with formatted exception.
477 478 """
478 479 tb_offset = self.tb_offset if tb_offset is None else tb_offset
479 480 Colors = self.Colors
480 481 out_list = []
481 482 if elist:
482 483
483 484 if tb_offset and len(elist) > tb_offset:
484 485 elist = elist[tb_offset:]
485 486
486 487 out_list.append('Traceback %s(most recent call last)%s:' %
487 488 (Colors.normalEm, Colors.Normal) + '\n')
488 489 out_list.extend(self._format_list(elist))
489 490 # The exception info should be a single entry in the list.
490 491 lines = ''.join(self._format_exception_only(etype, value))
491 492 out_list.append(lines)
492 493
493 494 # Note: this code originally read:
494 495
495 496 ## for line in lines[:-1]:
496 497 ## out_list.append(" "+line)
497 498 ## out_list.append(lines[-1])
498 499
499 500 # This means it was indenting everything but the last line by a little
500 501 # bit. I've disabled this for now, but if we see ugliness somewhre we
501 502 # can restore it.
502 503
503 504 return out_list
504 505
505 506 def _format_list(self, extracted_list):
506 507 """Format a list of traceback entry tuples for printing.
507 508
508 509 Given a list of tuples as returned by extract_tb() or
509 510 extract_stack(), return a list of strings ready for printing.
510 511 Each string in the resulting list corresponds to the item with the
511 512 same index in the argument list. Each string ends in a newline;
512 513 the strings may contain internal newlines as well, for those items
513 514 whose source text line is not None.
514 515
515 516 Lifted almost verbatim from traceback.py
516 517 """
517 518
518 519 Colors = self.Colors
519 520 list = []
520 521 for filename, lineno, name, line in extracted_list[:-1]:
521 522 item = ' File %s"%s"%s, line %s%d%s, in %s%s%s\n' % \
522 523 (Colors.filename, filename, Colors.Normal,
523 524 Colors.lineno, lineno, Colors.Normal,
524 525 Colors.name, name, Colors.Normal)
525 526 if line:
526 527 item += ' %s\n' % line.strip()
527 528 list.append(item)
528 529 # Emphasize the last entry
529 530 filename, lineno, name, line = extracted_list[-1]
530 531 item = '%s File %s"%s"%s, line %s%d%s, in %s%s%s%s\n' % \
531 532 (Colors.normalEm,
532 533 Colors.filenameEm, filename, Colors.normalEm,
533 534 Colors.linenoEm, lineno, Colors.normalEm,
534 535 Colors.nameEm, name, Colors.normalEm,
535 536 Colors.Normal)
536 537 if line:
537 538 item += '%s %s%s\n' % (Colors.line, line.strip(),
538 539 Colors.Normal)
539 540 list.append(item)
540 541 #from pprint import pformat; print 'LISTTB', pformat(list) # dbg
541 542 return list
542 543
543 544 def _format_exception_only(self, etype, value):
544 545 """Format the exception part of a traceback.
545 546
546 547 The arguments are the exception type and value such as given by
547 548 sys.exc_info()[:2]. The return value is a list of strings, each ending
548 549 in a newline. Normally, the list contains a single string; however,
549 550 for SyntaxError exceptions, it contains several lines that (when
550 551 printed) display detailed information about where the syntax error
551 552 occurred. The message indicating which exception occurred is the
552 553 always last string in the list.
553 554
554 555 Also lifted nearly verbatim from traceback.py
555 556 """
556 557 have_filedata = False
557 558 Colors = self.Colors
558 559 list = []
559 560 stype = Colors.excName + etype.__name__ + Colors.Normal
560 561 if value is None:
561 562 # Not sure if this can still happen in Python 2.6 and above
562 563 list.append( py3compat.cast_unicode(stype) + '\n')
563 564 else:
564 565 if issubclass(etype, SyntaxError):
565 566 have_filedata = True
566 567 #print 'filename is',filename # dbg
567 568 if not value.filename: value.filename = "<string>"
568 569 if value.lineno:
569 570 lineno = value.lineno
570 571 textline = ulinecache.getline(value.filename, value.lineno)
571 572 else:
572 573 lineno = 'unknown'
573 574 textline = ''
574 575 list.append('%s File %s"%s"%s, line %s%s%s\n' % \
575 576 (Colors.normalEm,
576 577 Colors.filenameEm, py3compat.cast_unicode(value.filename), Colors.normalEm,
577 578 Colors.linenoEm, lineno, Colors.Normal ))
578 579 if textline == '':
579 580 textline = py3compat.cast_unicode(value.text, "utf-8")
580 581
581 582 if textline is not None:
582 583 i = 0
583 584 while i < len(textline) and textline[i].isspace():
584 585 i += 1
585 586 list.append('%s %s%s\n' % (Colors.line,
586 587 textline.strip(),
587 588 Colors.Normal))
588 589 if value.offset is not None:
589 590 s = ' '
590 591 for c in textline[i:value.offset-1]:
591 592 if c.isspace():
592 593 s += c
593 594 else:
594 595 s += ' '
595 596 list.append('%s%s^%s\n' % (Colors.caret, s,
596 597 Colors.Normal) )
597 598
598 599 try:
599 600 s = value.msg
600 601 except Exception:
601 602 s = self._some_str(value)
602 603 if s:
603 604 list.append('%s%s:%s %s\n' % (str(stype), Colors.excName,
604 605 Colors.Normal, s))
605 606 else:
606 607 list.append('%s\n' % str(stype))
607 608
608 609 # sync with user hooks
609 610 if have_filedata:
610 611 ipinst = get_ipython()
611 612 if ipinst is not None:
612 613 ipinst.hooks.synchronize_with_editor(value.filename, value.lineno, 0)
613 614
614 615 return list
615 616
616 617 def get_exception_only(self, etype, value):
617 618 """Only print the exception type and message, without a traceback.
618 619
619 620 Parameters
620 621 ----------
621 622 etype : exception type
622 623 value : exception value
623 624 """
624 625 return ListTB.structured_traceback(self, etype, value, [])
625 626
626 627
627 628 def show_exception_only(self, etype, evalue):
628 629 """Only print the exception type and message, without a traceback.
629 630
630 631 Parameters
631 632 ----------
632 633 etype : exception type
633 634 value : exception value
634 635 """
635 636 # This method needs to use __call__ from *this* class, not the one from
636 637 # a subclass whose signature or behavior may be different
637 638 ostream = self.ostream
638 639 ostream.flush()
639 640 ostream.write('\n'.join(self.get_exception_only(etype, evalue)))
640 641 ostream.flush()
641 642
642 643 def _some_str(self, value):
643 644 # Lifted from traceback.py
644 645 try:
645 646 return str(value)
646 647 except:
647 648 return '<unprintable %s object>' % type(value).__name__
648 649
649 650 #----------------------------------------------------------------------------
650 651 class VerboseTB(TBTools):
651 652 """A port of Ka-Ping Yee's cgitb.py module that outputs color text instead
652 653 of HTML. Requires inspect and pydoc. Crazy, man.
653 654
654 655 Modified version which optionally strips the topmost entries from the
655 656 traceback, to be used with alternate interpreters (because their own code
656 657 would appear in the traceback)."""
657 658
658 659 def __init__(self,color_scheme = 'Linux', call_pdb=False, ostream=None,
659 660 tb_offset=0, long_header=False, include_vars=True,
660 661 check_cache=None):
661 662 """Specify traceback offset, headers and color scheme.
662 663
663 664 Define how many frames to drop from the tracebacks. Calling it with
664 665 tb_offset=1 allows use of this handler in interpreters which will have
665 666 their own code at the top of the traceback (VerboseTB will first
666 667 remove that frame before printing the traceback info)."""
667 668 TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
668 669 ostream=ostream)
669 670 self.tb_offset = tb_offset
670 671 self.long_header = long_header
671 672 self.include_vars = include_vars
672 673 # By default we use linecache.checkcache, but the user can provide a
673 674 # different check_cache implementation. This is used by the IPython
674 675 # kernel to provide tracebacks for interactive code that is cached,
675 676 # by a compiler instance that flushes the linecache but preserves its
676 677 # own code cache.
677 678 if check_cache is None:
678 679 check_cache = linecache.checkcache
679 680 self.check_cache = check_cache
680 681
681 682 def structured_traceback(self, etype, evalue, etb, tb_offset=None,
682 683 context=5):
683 684 """Return a nice text document describing the traceback."""
684 685
685 686 tb_offset = self.tb_offset if tb_offset is None else tb_offset
686 687
687 688 # some locals
688 689 try:
689 690 etype = etype.__name__
690 691 except AttributeError:
691 692 pass
692 693 Colors = self.Colors # just a shorthand + quicker name lookup
693 694 ColorsNormal = Colors.Normal # used a lot
694 695 col_scheme = self.color_scheme_table.active_scheme_name
695 696 indent = ' '*INDENT_SIZE
696 697 em_normal = '%s\n%s%s' % (Colors.valEm, indent,ColorsNormal)
697 698 undefined = '%sundefined%s' % (Colors.em, ColorsNormal)
698 699 exc = '%s%s%s' % (Colors.excName,etype,ColorsNormal)
699 700
700 701 # some internal-use functions
701 702 def text_repr(value):
702 703 """Hopefully pretty robust repr equivalent."""
703 704 # this is pretty horrible but should always return *something*
704 705 try:
705 706 return pydoc.text.repr(value)
706 707 except KeyboardInterrupt:
707 708 raise
708 709 except:
709 710 try:
710 711 return repr(value)
711 712 except KeyboardInterrupt:
712 713 raise
713 714 except:
714 715 try:
715 716 # all still in an except block so we catch
716 717 # getattr raising
717 718 name = getattr(value, '__name__', None)
718 719 if name:
719 720 # ick, recursion
720 721 return text_repr(name)
721 722 klass = getattr(value, '__class__', None)
722 723 if klass:
723 724 return '%s instance' % text_repr(klass)
724 725 except KeyboardInterrupt:
725 726 raise
726 727 except:
727 728 return 'UNRECOVERABLE REPR FAILURE'
728 729 def eqrepr(value, repr=text_repr): return '=%s' % repr(value)
729 730 def nullrepr(value, repr=text_repr): return ''
730 731
731 732 # meat of the code begins
732 733 try:
733 734 etype = etype.__name__
734 735 except AttributeError:
735 736 pass
736 737
737 738 if self.long_header:
738 739 # Header with the exception type, python version, and date
739 740 pyver = 'Python ' + sys.version.split()[0] + ': ' + sys.executable
740 741 date = time.ctime(time.time())
741 742
742 743 head = '%s%s%s\n%s%s%s\n%s' % (Colors.topline, '-'*75, ColorsNormal,
743 744 exc, ' '*(75-len(str(etype))-len(pyver)),
744 745 pyver, date.rjust(75) )
745 746 head += "\nA problem occured executing Python code. Here is the sequence of function"\
746 747 "\ncalls leading up to the error, with the most recent (innermost) call last."
747 748 else:
748 749 # Simplified header
749 750 head = '%s%s%s\n%s%s' % (Colors.topline, '-'*75, ColorsNormal,exc,
750 751 'Traceback (most recent call last)'.\
751 752 rjust(75 - len(str(etype)) ) )
752 753 frames = []
753 754 # Flush cache before calling inspect. This helps alleviate some of the
754 755 # problems with python 2.3's inspect.py.
755 756 ##self.check_cache()
756 757 # Drop topmost frames if requested
757 758 try:
758 759 # Try the default getinnerframes and Alex's: Alex's fixes some
759 760 # problems, but it generates empty tracebacks for console errors
760 761 # (5 blanks lines) where none should be returned.
761 762 #records = inspect.getinnerframes(etb, context)[tb_offset:]
762 763 #print 'python records:', records # dbg
763 764 records = _fixed_getinnerframes(etb, context, tb_offset)
764 765 #print 'alex records:', records # dbg
765 766 except:
766 767
767 768 # FIXME: I've been getting many crash reports from python 2.3
768 769 # users, traceable to inspect.py. If I can find a small test-case
769 770 # to reproduce this, I should either write a better workaround or
770 771 # file a bug report against inspect (if that's the real problem).
771 772 # So far, I haven't been able to find an isolated example to
772 773 # reproduce the problem.
773 774 inspect_error()
774 775 traceback.print_exc(file=self.ostream)
775 776 info('\nUnfortunately, your original traceback can not be constructed.\n')
776 777 return ''
777 778
778 779 # build some color string templates outside these nested loops
779 780 tpl_link = '%s%%s%s' % (Colors.filenameEm,ColorsNormal)
780 781 tpl_call = 'in %s%%s%s%%s%s' % (Colors.vName, Colors.valEm,
781 782 ColorsNormal)
782 783 tpl_call_fail = 'in %s%%s%s(***failed resolving arguments***)%s' % \
783 784 (Colors.vName, Colors.valEm, ColorsNormal)
784 785 tpl_local_var = '%s%%s%s' % (Colors.vName, ColorsNormal)
785 786 tpl_global_var = '%sglobal%s %s%%s%s' % (Colors.em, ColorsNormal,
786 787 Colors.vName, ColorsNormal)
787 788 tpl_name_val = '%%s %s= %%s%s' % (Colors.valEm, ColorsNormal)
788 789 tpl_line = '%s%%s%s %%s' % (Colors.lineno, ColorsNormal)
789 790 tpl_line_em = '%s%%s%s %%s%s' % (Colors.linenoEm,Colors.line,
790 791 ColorsNormal)
791 792
792 793 # now, loop over all records printing context and info
793 794 abspath = os.path.abspath
794 795 for frame, file, lnum, func, lines, index in records:
795 796 #print '*** record:',file,lnum,func,lines,index # dbg
796 797 if not file:
797 798 file = '?'
798 799 elif not(file.startswith(str("<")) and file.endswith(str(">"))):
799 800 # Guess that filenames like <string> aren't real filenames, so
800 801 # don't call abspath on them.
801 802 try:
802 803 file = abspath(file)
803 804 except OSError:
804 805 # Not sure if this can still happen: abspath now works with
805 806 # file names like <string>
806 807 pass
807 808 file = py3compat.cast_unicode(file, util_path.fs_encoding)
808 809 link = tpl_link % file
809 810 args, varargs, varkw, locals = inspect.getargvalues(frame)
810 811
811 812 if func == '?':
812 813 call = ''
813 814 else:
814 815 # Decide whether to include variable details or not
815 816 var_repr = self.include_vars and eqrepr or nullrepr
816 817 try:
817 818 call = tpl_call % (func,inspect.formatargvalues(args,
818 819 varargs, varkw,
819 820 locals,formatvalue=var_repr))
820 821 except KeyError:
821 822 # This happens in situations like errors inside generator
822 823 # expressions, where local variables are listed in the
823 824 # line, but can't be extracted from the frame. I'm not
824 825 # 100% sure this isn't actually a bug in inspect itself,
825 826 # but since there's no info for us to compute with, the
826 827 # best we can do is report the failure and move on. Here
827 828 # we must *not* call any traceback construction again,
828 829 # because that would mess up use of %debug later on. So we
829 830 # simply report the failure and move on. The only
830 831 # limitation will be that this frame won't have locals
831 832 # listed in the call signature. Quite subtle problem...
832 833 # I can't think of a good way to validate this in a unit
833 834 # test, but running a script consisting of:
834 835 # dict( (k,v.strip()) for (k,v) in range(10) )
835 836 # will illustrate the error, if this exception catch is
836 837 # disabled.
837 838 call = tpl_call_fail % func
838 839
839 840 # Don't attempt to tokenize binary files.
840 841 if file.endswith(('.so', '.pyd', '.dll')):
841 842 frames.append('%s %s\n' % (link,call))
842 843 continue
843 844 elif file.endswith(('.pyc','.pyo')):
844 845 # Look up the corresponding source file.
845 846 file = openpy.source_from_cache(file)
846 847
847 848 def linereader(file=file, lnum=[lnum], getline=ulinecache.getline):
848 849 line = getline(file, lnum[0])
849 850 lnum[0] += 1
850 851 return line
851 852
852 853 # Build the list of names on this line of code where the exception
853 854 # occurred.
854 855 try:
855 856 names = []
856 857 name_cont = False
857 858
858 859 for token_type, token, start, end, line in generate_tokens(linereader):
859 860 # build composite names
860 861 if token_type == tokenize.NAME and token not in keyword.kwlist:
861 862 if name_cont:
862 863 # Continuation of a dotted name
863 864 try:
864 865 names[-1].append(token)
865 866 except IndexError:
866 867 names.append([token])
867 868 name_cont = False
868 869 else:
869 870 # Regular new names. We append everything, the caller
870 871 # will be responsible for pruning the list later. It's
871 872 # very tricky to try to prune as we go, b/c composite
872 873 # names can fool us. The pruning at the end is easy
873 874 # to do (or the caller can print a list with repeated
874 875 # names if so desired.
875 876 names.append([token])
876 877 elif token == '.':
877 878 name_cont = True
878 879 elif token_type == tokenize.NEWLINE:
879 880 break
880 881
881 882 except (IndexError, UnicodeDecodeError):
882 883 # signals exit of tokenizer
883 884 pass
884 885 except tokenize.TokenError as msg:
885 886 _m = ("An unexpected error occurred while tokenizing input\n"
886 887 "The following traceback may be corrupted or invalid\n"
887 888 "The error message is: %s\n" % msg)
888 889 error(_m)
889 890
890 891 # Join composite names (e.g. "dict.fromkeys")
891 892 names = ['.'.join(n) for n in names]
892 893 # prune names list of duplicates, but keep the right order
893 894 unique_names = uniq_stable(names)
894 895
895 896 # Start loop over vars
896 897 lvals = []
897 898 if self.include_vars:
898 899 for name_full in unique_names:
899 900 name_base = name_full.split('.',1)[0]
900 901 if name_base in frame.f_code.co_varnames:
901 902 if name_base in locals:
902 903 try:
903 904 value = repr(eval(name_full,locals))
904 905 except:
905 906 value = undefined
906 907 else:
907 908 value = undefined
908 909 name = tpl_local_var % name_full
909 910 else:
910 911 if name_base in frame.f_globals:
911 912 try:
912 913 value = repr(eval(name_full,frame.f_globals))
913 914 except:
914 915 value = undefined
915 916 else:
916 917 value = undefined
917 918 name = tpl_global_var % name_full
918 919 lvals.append(tpl_name_val % (name,value))
919 920 if lvals:
920 921 lvals = '%s%s' % (indent,em_normal.join(lvals))
921 922 else:
922 923 lvals = ''
923 924
924 925 level = '%s %s\n' % (link,call)
925 926
926 927 if index is None:
927 928 frames.append(level)
928 929 else:
929 930 frames.append('%s%s' % (level,''.join(
930 931 _format_traceback_lines(lnum,index,lines,Colors,lvals,
931 932 col_scheme))))
932 933
933 934 # Get (safely) a string form of the exception info
934 935 try:
935 936 etype_str,evalue_str = map(str,(etype,evalue))
936 937 except:
937 938 # User exception is improperly defined.
938 939 etype,evalue = str,sys.exc_info()[:2]
939 940 etype_str,evalue_str = map(str,(etype,evalue))
940 941 # ... and format it
941 942 exception = ['%s%s%s: %s' % (Colors.excName, etype_str,
942 943 ColorsNormal, py3compat.cast_unicode(evalue_str))]
943 944 if (not py3compat.PY3) and type(evalue) is types.InstanceType:
944 945 try:
945 946 names = [w for w in dir(evalue) if isinstance(w, basestring)]
946 947 except:
947 948 # Every now and then, an object with funny inernals blows up
948 949 # when dir() is called on it. We do the best we can to report
949 950 # the problem and continue
950 951 _m = '%sException reporting error (object with broken dir())%s:'
951 952 exception.append(_m % (Colors.excName,ColorsNormal))
952 953 etype_str,evalue_str = map(str,sys.exc_info()[:2])
953 954 exception.append('%s%s%s: %s' % (Colors.excName,etype_str,
954 955 ColorsNormal, py3compat.cast_unicode(evalue_str)))
955 956 names = []
956 957 for name in names:
957 958 value = text_repr(getattr(evalue, name))
958 959 exception.append('\n%s%s = %s' % (indent, name, value))
959 960
960 961 # vds: >>
961 962 if records:
962 963 filepath, lnum = records[-1][1:3]
963 964 #print "file:", str(file), "linenb", str(lnum) # dbg
964 965 filepath = os.path.abspath(filepath)
965 966 ipinst = get_ipython()
966 967 if ipinst is not None:
967 968 ipinst.hooks.synchronize_with_editor(filepath, lnum, 0)
968 969 # vds: <<
969 970
970 971 # return all our info assembled as a single string
971 972 # return '%s\n\n%s\n%s' % (head,'\n'.join(frames),''.join(exception[0]) )
972 973 return [head] + frames + [''.join(exception[0])]
973 974
974 975 def debugger(self,force=False):
975 976 """Call up the pdb debugger if desired, always clean up the tb
976 977 reference.
977 978
978 979 Keywords:
979 980
980 981 - force(False): by default, this routine checks the instance call_pdb
981 982 flag and does not actually invoke the debugger if the flag is false.
982 983 The 'force' option forces the debugger to activate even if the flag
983 984 is false.
984 985
985 986 If the call_pdb flag is set, the pdb interactive debugger is
986 987 invoked. In all cases, the self.tb reference to the current traceback
987 988 is deleted to prevent lingering references which hamper memory
988 989 management.
989 990
990 991 Note that each call to pdb() does an 'import readline', so if your app
991 992 requires a special setup for the readline completers, you'll have to
992 993 fix that by hand after invoking the exception handler."""
993 994
994 995 if force or self.call_pdb:
995 996 if self.pdb is None:
996 997 self.pdb = debugger.Pdb(
997 998 self.color_scheme_table.active_scheme_name)
998 999 # the system displayhook may have changed, restore the original
999 1000 # for pdb
1000 1001 display_trap = DisplayTrap(hook=sys.__displayhook__)
1001 1002 with display_trap:
1002 1003 self.pdb.reset()
1003 1004 # Find the right frame so we don't pop up inside ipython itself
1004 1005 if hasattr(self,'tb') and self.tb is not None:
1005 1006 etb = self.tb
1006 1007 else:
1007 1008 etb = self.tb = sys.last_traceback
1008 1009 while self.tb is not None and self.tb.tb_next is not None:
1009 1010 self.tb = self.tb.tb_next
1010 1011 if etb and etb.tb_next:
1011 1012 etb = etb.tb_next
1012 1013 self.pdb.botframe = etb.tb_frame
1013 1014 self.pdb.interaction(self.tb.tb_frame, self.tb)
1014 1015
1015 1016 if hasattr(self,'tb'):
1016 1017 del self.tb
1017 1018
1018 1019 def handler(self, info=None):
1019 1020 (etype, evalue, etb) = info or sys.exc_info()
1020 1021 self.tb = etb
1021 1022 ostream = self.ostream
1022 1023 ostream.flush()
1023 1024 ostream.write(self.text(etype, evalue, etb))
1024 1025 ostream.write('\n')
1025 1026 ostream.flush()
1026 1027
1027 1028 # Changed so an instance can just be called as VerboseTB_inst() and print
1028 1029 # out the right info on its own.
1029 1030 def __call__(self, etype=None, evalue=None, etb=None):
1030 1031 """This hook can replace sys.excepthook (for Python 2.1 or higher)."""
1031 1032 if etb is None:
1032 1033 self.handler()
1033 1034 else:
1034 1035 self.handler((etype, evalue, etb))
1035 1036 try:
1036 1037 self.debugger()
1037 1038 except KeyboardInterrupt:
1038 print "\nKeyboardInterrupt"
1039 print("\nKeyboardInterrupt")
1039 1040
1040 1041 #----------------------------------------------------------------------------
1041 1042 class FormattedTB(VerboseTB, ListTB):
1042 1043 """Subclass ListTB but allow calling with a traceback.
1043 1044
1044 1045 It can thus be used as a sys.excepthook for Python > 2.1.
1045 1046
1046 1047 Also adds 'Context' and 'Verbose' modes, not available in ListTB.
1047 1048
1048 1049 Allows a tb_offset to be specified. This is useful for situations where
1049 1050 one needs to remove a number of topmost frames from the traceback (such as
1050 1051 occurs with python programs that themselves execute other python code,
1051 1052 like Python shells). """
1052 1053
1053 1054 def __init__(self, mode='Plain', color_scheme='Linux', call_pdb=False,
1054 1055 ostream=None,
1055 1056 tb_offset=0, long_header=False, include_vars=False,
1056 1057 check_cache=None):
1057 1058
1058 1059 # NEVER change the order of this list. Put new modes at the end:
1059 1060 self.valid_modes = ['Plain','Context','Verbose']
1060 1061 self.verbose_modes = self.valid_modes[1:3]
1061 1062
1062 1063 VerboseTB.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
1063 1064 ostream=ostream, tb_offset=tb_offset,
1064 1065 long_header=long_header, include_vars=include_vars,
1065 1066 check_cache=check_cache)
1066 1067
1067 1068 # Different types of tracebacks are joined with different separators to
1068 1069 # form a single string. They are taken from this dict
1069 1070 self._join_chars = dict(Plain='', Context='\n', Verbose='\n')
1070 1071 # set_mode also sets the tb_join_char attribute
1071 1072 self.set_mode(mode)
1072 1073
1073 1074 def _extract_tb(self,tb):
1074 1075 if tb:
1075 1076 return traceback.extract_tb(tb)
1076 1077 else:
1077 1078 return None
1078 1079
1079 1080 def structured_traceback(self, etype, value, tb, tb_offset=None, context=5):
1080 1081 tb_offset = self.tb_offset if tb_offset is None else tb_offset
1081 1082 mode = self.mode
1082 1083 if mode in self.verbose_modes:
1083 1084 # Verbose modes need a full traceback
1084 1085 return VerboseTB.structured_traceback(
1085 1086 self, etype, value, tb, tb_offset, context
1086 1087 )
1087 1088 else:
1088 1089 # We must check the source cache because otherwise we can print
1089 1090 # out-of-date source code.
1090 1091 self.check_cache()
1091 1092 # Now we can extract and format the exception
1092 1093 elist = self._extract_tb(tb)
1093 1094 return ListTB.structured_traceback(
1094 1095 self, etype, value, elist, tb_offset, context
1095 1096 )
1096 1097
1097 1098 def stb2text(self, stb):
1098 1099 """Convert a structured traceback (a list) to a string."""
1099 1100 return self.tb_join_char.join(stb)
1100 1101
1101 1102
1102 1103 def set_mode(self,mode=None):
1103 1104 """Switch to the desired mode.
1104 1105
1105 1106 If mode is not specified, cycles through the available modes."""
1106 1107
1107 1108 if not mode:
1108 1109 new_idx = ( self.valid_modes.index(self.mode) + 1 ) % \
1109 1110 len(self.valid_modes)
1110 1111 self.mode = self.valid_modes[new_idx]
1111 1112 elif mode not in self.valid_modes:
1112 1113 raise ValueError('Unrecognized mode in FormattedTB: <'+mode+'>\n'
1113 1114 'Valid modes: '+str(self.valid_modes))
1114 1115 else:
1115 1116 self.mode = mode
1116 1117 # include variable details only in 'Verbose' mode
1117 1118 self.include_vars = (self.mode == self.valid_modes[2])
1118 1119 # Set the join character for generating text tracebacks
1119 1120 self.tb_join_char = self._join_chars[self.mode]
1120 1121
1121 1122 # some convenient shorcuts
1122 1123 def plain(self):
1123 1124 self.set_mode(self.valid_modes[0])
1124 1125
1125 1126 def context(self):
1126 1127 self.set_mode(self.valid_modes[1])
1127 1128
1128 1129 def verbose(self):
1129 1130 self.set_mode(self.valid_modes[2])
1130 1131
1131 1132 #----------------------------------------------------------------------------
1132 1133 class AutoFormattedTB(FormattedTB):
1133 1134 """A traceback printer which can be called on the fly.
1134 1135
1135 1136 It will find out about exceptions by itself.
1136 1137
1137 1138 A brief example::
1138 1139
1139 1140 AutoTB = AutoFormattedTB(mode = 'Verbose',color_scheme='Linux')
1140 1141 try:
1141 1142 ...
1142 1143 except:
1143 1144 AutoTB() # or AutoTB(out=logfile) where logfile is an open file object
1144 1145 """
1145 1146
1146 1147 def __call__(self,etype=None,evalue=None,etb=None,
1147 1148 out=None,tb_offset=None):
1148 1149 """Print out a formatted exception traceback.
1149 1150
1150 1151 Optional arguments:
1151 1152 - out: an open file-like object to direct output to.
1152 1153
1153 1154 - tb_offset: the number of frames to skip over in the stack, on a
1154 1155 per-call basis (this overrides temporarily the instance's tb_offset
1155 1156 given at initialization time. """
1156 1157
1157 1158
1158 1159 if out is None:
1159 1160 out = self.ostream
1160 1161 out.flush()
1161 1162 out.write(self.text(etype, evalue, etb, tb_offset))
1162 1163 out.write('\n')
1163 1164 out.flush()
1164 1165 # FIXME: we should remove the auto pdb behavior from here and leave
1165 1166 # that to the clients.
1166 1167 try:
1167 1168 self.debugger()
1168 1169 except KeyboardInterrupt:
1169 print "\nKeyboardInterrupt"
1170 print("\nKeyboardInterrupt")
1170 1171
1171 1172 def structured_traceback(self, etype=None, value=None, tb=None,
1172 1173 tb_offset=None, context=5):
1173 1174 if etype is None:
1174 1175 etype,value,tb = sys.exc_info()
1175 1176 self.tb = tb
1176 1177 return FormattedTB.structured_traceback(
1177 1178 self, etype, value, tb, tb_offset, context)
1178 1179
1179 1180 #---------------------------------------------------------------------------
1180 1181
1181 1182 # A simple class to preserve Nathan's original functionality.
1182 1183 class ColorTB(FormattedTB):
1183 1184 """Shorthand to initialize a FormattedTB in Linux colors mode."""
1184 1185 def __init__(self,color_scheme='Linux',call_pdb=0):
1185 1186 FormattedTB.__init__(self,color_scheme=color_scheme,
1186 1187 call_pdb=call_pdb)
1187 1188
1188 1189
1189 1190 class SyntaxTB(ListTB):
1190 1191 """Extension which holds some state: the last exception value"""
1191 1192
1192 1193 def __init__(self,color_scheme = 'NoColor'):
1193 1194 ListTB.__init__(self,color_scheme)
1194 1195 self.last_syntax_error = None
1195 1196
1196 1197 def __call__(self, etype, value, elist):
1197 1198 self.last_syntax_error = value
1198 1199 ListTB.__call__(self,etype,value,elist)
1199 1200
1200 1201 def structured_traceback(self, etype, value, elist, tb_offset=None,
1201 1202 context=5):
1202 1203 # If the source file has been edited, the line in the syntax error can
1203 1204 # be wrong (retrieved from an outdated cache). This replaces it with
1204 1205 # the current value.
1205 1206 if isinstance(value, SyntaxError) \
1206 1207 and isinstance(value.filename, py3compat.string_types) \
1207 1208 and isinstance(value.lineno, int):
1208 1209 linecache.checkcache(value.filename)
1209 1210 newtext = ulinecache.getline(value.filename, value.lineno)
1210 1211 if newtext:
1211 1212 value.text = newtext
1212 1213 return super(SyntaxTB, self).structured_traceback(etype, value, elist,
1213 1214 tb_offset=tb_offset, context=context)
1214 1215
1215 1216 def clear_err_state(self):
1216 1217 """Return the current error state and clear it"""
1217 1218 e = self.last_syntax_error
1218 1219 self.last_syntax_error = None
1219 1220 return e
1220 1221
1221 1222 def stb2text(self, stb):
1222 1223 """Convert a structured traceback (a list) to a string."""
1223 1224 return ''.join(stb)
1224 1225
1225 1226
1226 1227 #----------------------------------------------------------------------------
1227 1228 # module testing (minimal)
1228 1229 if __name__ == "__main__":
1229 1230 def spam(c, d_e):
1230 1231 (d, e) = d_e
1231 1232 x = c + d
1232 1233 y = c * d
1233 1234 foo(x, y)
1234 1235
1235 1236 def foo(a, b, bar=1):
1236 1237 eggs(a, b + bar)
1237 1238
1238 1239 def eggs(f, g, z=globals()):
1239 1240 h = f + g
1240 1241 i = f - g
1241 1242 return h / i
1242 1243
1243 print ''
1244 print '*** Before ***'
1244 print('')
1245 print('*** Before ***')
1245 1246 try:
1246 print spam(1, (2, 3))
1247 print(spam(1, (2, 3)))
1247 1248 except:
1248 1249 traceback.print_exc()
1249 print ''
1250 print('')
1250 1251
1251 1252 handler = ColorTB()
1252 print '*** ColorTB ***'
1253 print('*** ColorTB ***')
1253 1254 try:
1254 print spam(1, (2, 3))
1255 print(spam(1, (2, 3)))
1255 1256 except:
1256 1257 handler(*sys.exc_info())
1257 print ''
1258 print('')
1258 1259
1259 1260 handler = VerboseTB()
1260 print '*** VerboseTB ***'
1261 print('*** VerboseTB ***')
1261 1262 try:
1262 print spam(1, (2, 3))
1263 print(spam(1, (2, 3)))
1263 1264 except:
1264 1265 handler(*sys.exc_info())
1265 print ''
1266 print('')
1266 1267
@@ -1,694 +1,695 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 ======
4 4 Rmagic
5 5 ======
6 6
7 7 Magic command interface for interactive work with R via rpy2
8 8
9 9 .. note::
10 10
11 11 The ``rpy2`` package needs to be installed separately. It
12 12 can be obtained using ``easy_install`` or ``pip``.
13 13
14 14 You will also need a working copy of R.
15 15
16 16 Usage
17 17 =====
18 18
19 19 To enable the magics below, execute ``%load_ext rmagic``.
20 20
21 21 ``%R``
22 22
23 23 {R_DOC}
24 24
25 25 ``%Rpush``
26 26
27 27 {RPUSH_DOC}
28 28
29 29 ``%Rpull``
30 30
31 31 {RPULL_DOC}
32 32
33 33 ``%Rget``
34 34
35 35 {RGET_DOC}
36 36
37 37 """
38 from __future__ import print_function
38 39
39 40 #-----------------------------------------------------------------------------
40 41 # Copyright (C) 2012 The IPython Development Team
41 42 #
42 43 # Distributed under the terms of the BSD License. The full license is in
43 44 # the file COPYING, distributed as part of this software.
44 45 #-----------------------------------------------------------------------------
45 46
46 47 import sys
47 48 import tempfile
48 49 from glob import glob
49 50 from shutil import rmtree
50 51
51 52 # numpy and rpy2 imports
52 53
53 54 import numpy as np
54 55
55 56 import rpy2.rinterface as ri
56 57 import rpy2.robjects as ro
57 58 try:
58 59 from rpy2.robjects import pandas2ri
59 60 pandas2ri.activate()
60 61 except ImportError:
61 62 pandas2ri = None
62 63 from rpy2.robjects import numpy2ri
63 64 numpy2ri.activate()
64 65
65 66 # IPython imports
66 67
67 68 from IPython.core.displaypub import publish_display_data
68 69 from IPython.core.magic import (Magics, magics_class, line_magic,
69 70 line_cell_magic, needs_local_scope)
70 71 from IPython.testing.skipdoctest import skip_doctest
71 72 from IPython.core.magic_arguments import (
72 73 argument, magic_arguments, parse_argstring
73 74 )
74 75 from IPython.external.simplegeneric import generic
75 76 from IPython.utils.py3compat import (str_to_unicode, unicode_to_str, PY3,
76 77 unicode_type)
77 78
78 79 class RInterpreterError(ri.RRuntimeError):
79 80 """An error when running R code in a %%R magic cell."""
80 81 def __init__(self, line, err, stdout):
81 82 self.line = line
82 83 self.err = err.rstrip()
83 84 self.stdout = stdout.rstrip()
84 85
85 86 def __unicode__(self):
86 87 s = 'Failed to parse and evaluate line %r.\nR error message: %r' % \
87 88 (self.line, self.err)
88 89 if self.stdout and (self.stdout != self.err):
89 90 s += '\nR stdout:\n' + self.stdout
90 91 return s
91 92
92 93 if PY3:
93 94 __str__ = __unicode__
94 95 else:
95 96 def __str__(self):
96 97 return unicode_to_str(unicode(self), 'utf-8')
97 98
98 99 def Rconverter(Robj, dataframe=False):
99 100 """
100 101 Convert an object in R's namespace to one suitable
101 102 for ipython's namespace.
102 103
103 104 For a data.frame, it tries to return a structured array.
104 105 It first checks for colnames, then names.
105 106 If all are NULL, it returns np.asarray(Robj), else
106 107 it tries to construct a recarray
107 108
108 109 Parameters
109 110 ----------
110 111
111 112 Robj: an R object returned from rpy2
112 113 """
113 114 is_data_frame = ro.r('is.data.frame')
114 115 colnames = ro.r('colnames')
115 116 rownames = ro.r('rownames') # with pandas, these could be used for the index
116 117 names = ro.r('names')
117 118
118 119 if dataframe:
119 120 as_data_frame = ro.r('as.data.frame')
120 121 cols = colnames(Robj)
121 122 _names = names(Robj)
122 123 if cols != ri.NULL:
123 124 Robj = as_data_frame(Robj)
124 125 names = tuple(np.array(cols))
125 126 elif _names != ri.NULL:
126 127 names = tuple(np.array(_names))
127 128 else: # failed to find names
128 129 return np.asarray(Robj)
129 130 Robj = np.rec.fromarrays(Robj, names = names)
130 131 return np.asarray(Robj)
131 132
132 133 @generic
133 134 def pyconverter(pyobj):
134 135 """Convert Python objects to R objects. Add types using the decorator:
135 136
136 137 @pyconverter.when_type
137 138 """
138 139 return pyobj
139 140
140 141 # The default conversion for lists seems to make them a nested list. That has
141 142 # some advantages, but is rarely convenient, so for interactive use, we convert
142 143 # lists to a numpy array, which becomes an R vector.
143 144 @pyconverter.when_type(list)
144 145 def pyconverter_list(pyobj):
145 146 return np.asarray(pyobj)
146 147
147 148 if pandas2ri is None:
148 149 # pandas2ri was new in rpy2 2.3.3, so for now we'll fallback to pandas'
149 150 # conversion function.
150 151 try:
151 152 from pandas import DataFrame
152 153 from pandas.rpy.common import convert_to_r_dataframe
153 154 @pyconverter.when_type(DataFrame)
154 155 def pyconverter_dataframe(pyobj):
155 156 return convert_to_r_dataframe(pyobj, strings_as_factors=True)
156 157 except ImportError:
157 158 pass
158 159
159 160 @magics_class
160 161 class RMagics(Magics):
161 162 """A set of magics useful for interactive work with R via rpy2.
162 163 """
163 164
164 165 def __init__(self, shell, Rconverter=Rconverter,
165 166 pyconverter=pyconverter,
166 167 cache_display_data=False):
167 168 """
168 169 Parameters
169 170 ----------
170 171
171 172 shell : IPython shell
172 173
173 174 Rconverter : callable
174 175 To be called on values taken from R before putting them in the
175 176 IPython namespace.
176 177
177 178 pyconverter : callable
178 179 To be called on values in ipython namespace before
179 180 assigning to variables in rpy2.
180 181
181 182 cache_display_data : bool
182 183 If True, the published results of the final call to R are
183 184 cached in the variable 'display_cache'.
184 185
185 186 """
186 187 super(RMagics, self).__init__(shell)
187 188 self.cache_display_data = cache_display_data
188 189
189 190 self.r = ro.R()
190 191
191 192 self.Rstdout_cache = []
192 193 self.pyconverter = pyconverter
193 194 self.Rconverter = Rconverter
194 195
195 196 def eval(self, line):
196 197 '''
197 198 Parse and evaluate a line of R code with rpy2.
198 199 Returns the output to R's stdout() connection,
199 200 the value generated by evaluating the code, and a
200 201 boolean indicating whether the return value would be
201 202 visible if the line of code were evaluated in an R REPL.
202 203
203 204 R Code evaluation and visibility determination are
204 205 done via an R call of the form withVisible({<code>})
205 206
206 207 '''
207 208 old_writeconsole = ri.get_writeconsole()
208 209 ri.set_writeconsole(self.write_console)
209 210 try:
210 211 res = ro.r("withVisible({%s})" % line)
211 212 value = res[0] #value (R object)
212 213 visible = ro.conversion.ri2py(res[1])[0] #visible (boolean)
213 214 except (ri.RRuntimeError, ValueError) as exception:
214 215 warning_or_other_msg = self.flush() # otherwise next return seems to have copy of error
215 216 raise RInterpreterError(line, str_to_unicode(str(exception)), warning_or_other_msg)
216 217 text_output = self.flush()
217 218 ri.set_writeconsole(old_writeconsole)
218 219 return text_output, value, visible
219 220
220 221 def write_console(self, output):
221 222 '''
222 223 A hook to capture R's stdout in a cache.
223 224 '''
224 225 self.Rstdout_cache.append(output)
225 226
226 227 def flush(self):
227 228 '''
228 229 Flush R's stdout cache to a string, returning the string.
229 230 '''
230 231 value = ''.join([str_to_unicode(s, 'utf-8') for s in self.Rstdout_cache])
231 232 self.Rstdout_cache = []
232 233 return value
233 234
234 235 @skip_doctest
235 236 @needs_local_scope
236 237 @line_magic
237 238 def Rpush(self, line, local_ns=None):
238 239 '''
239 240 A line-level magic for R that pushes
240 241 variables from python to rpy2. The line should be made up
241 242 of whitespace separated variable names in the IPython
242 243 namespace::
243 244
244 245 In [7]: import numpy as np
245 246
246 247 In [8]: X = np.array([4.5,6.3,7.9])
247 248
248 249 In [9]: X.mean()
249 250 Out[9]: 6.2333333333333343
250 251
251 252 In [10]: %Rpush X
252 253
253 254 In [11]: %R mean(X)
254 255 Out[11]: array([ 6.23333333])
255 256
256 257 '''
257 258 if local_ns is None:
258 259 local_ns = {}
259 260
260 261 inputs = line.split(' ')
261 262 for input in inputs:
262 263 try:
263 264 val = local_ns[input]
264 265 except KeyError:
265 266 try:
266 267 val = self.shell.user_ns[input]
267 268 except KeyError:
268 269 # reraise the KeyError as a NameError so that it looks like
269 270 # the standard python behavior when you use an unnamed
270 271 # variable
271 272 raise NameError("name '%s' is not defined" % input)
272 273
273 274 self.r.assign(input, self.pyconverter(val))
274 275
275 276 @skip_doctest
276 277 @magic_arguments()
277 278 @argument(
278 279 '-d', '--as_dataframe', action='store_true',
279 280 default=False,
280 281 help='Convert objects to data.frames before returning to ipython.'
281 282 )
282 283 @argument(
283 284 'outputs',
284 285 nargs='*',
285 286 )
286 287 @line_magic
287 288 def Rpull(self, line):
288 289 '''
289 290 A line-level magic for R that pulls
290 291 variables from python to rpy2::
291 292
292 293 In [18]: _ = %R x = c(3,4,6.7); y = c(4,6,7); z = c('a',3,4)
293 294
294 295 In [19]: %Rpull x y z
295 296
296 297 In [20]: x
297 298 Out[20]: array([ 3. , 4. , 6.7])
298 299
299 300 In [21]: y
300 301 Out[21]: array([ 4., 6., 7.])
301 302
302 303 In [22]: z
303 304 Out[22]:
304 305 array(['a', '3', '4'],
305 306 dtype='|S1')
306 307
307 308
308 309 If --as_dataframe, then each object is returned as a structured array
309 310 after first passed through "as.data.frame" in R before
310 311 being calling self.Rconverter.
311 312 This is useful when a structured array is desired as output, or
312 313 when the object in R has mixed data types.
313 314 See the %%R docstring for more examples.
314 315
315 316 Notes
316 317 -----
317 318
318 319 Beware that R names can have '.' so this is not fool proof.
319 320 To avoid this, don't name your R objects with '.'s...
320 321
321 322 '''
322 323 args = parse_argstring(self.Rpull, line)
323 324 outputs = args.outputs
324 325 for output in outputs:
325 326 self.shell.push({output:self.Rconverter(self.r(output),dataframe=args.as_dataframe)})
326 327
327 328 @skip_doctest
328 329 @magic_arguments()
329 330 @argument(
330 331 '-d', '--as_dataframe', action='store_true',
331 332 default=False,
332 333 help='Convert objects to data.frames before returning to ipython.'
333 334 )
334 335 @argument(
335 336 'output',
336 337 nargs=1,
337 338 type=str,
338 339 )
339 340 @line_magic
340 341 def Rget(self, line):
341 342 '''
342 343 Return an object from rpy2, possibly as a structured array (if possible).
343 344 Similar to Rpull except only one argument is accepted and the value is
344 345 returned rather than pushed to self.shell.user_ns::
345 346
346 347 In [3]: dtype=[('x', '<i4'), ('y', '<f8'), ('z', '|S1')]
347 348
348 349 In [4]: datapy = np.array([(1, 2.9, 'a'), (2, 3.5, 'b'), (3, 2.1, 'c'), (4, 5, 'e')], dtype=dtype)
349 350
350 351 In [5]: %R -i datapy
351 352
352 353 In [6]: %Rget datapy
353 354 Out[6]:
354 355 array([['1', '2', '3', '4'],
355 356 ['2', '3', '2', '5'],
356 357 ['a', 'b', 'c', 'e']],
357 358 dtype='|S1')
358 359
359 360 In [7]: %Rget -d datapy
360 361 Out[7]:
361 362 array([(1, 2.9, 'a'), (2, 3.5, 'b'), (3, 2.1, 'c'), (4, 5.0, 'e')],
362 363 dtype=[('x', '<i4'), ('y', '<f8'), ('z', '|S1')])
363 364
364 365 '''
365 366 args = parse_argstring(self.Rget, line)
366 367 output = args.output
367 368 return self.Rconverter(self.r(output[0]),dataframe=args.as_dataframe)
368 369
369 370
370 371 @skip_doctest
371 372 @magic_arguments()
372 373 @argument(
373 374 '-i', '--input', action='append',
374 375 help='Names of input variable from shell.user_ns to be assigned to R variables of the same names after calling self.pyconverter. Multiple names can be passed separated only by commas with no whitespace.'
375 376 )
376 377 @argument(
377 378 '-o', '--output', action='append',
378 379 help='Names of variables to be pushed from rpy2 to shell.user_ns after executing cell body and applying self.Rconverter. Multiple names can be passed separated only by commas with no whitespace.'
379 380 )
380 381 @argument(
381 382 '-w', '--width', type=int,
382 383 help='Width of png plotting device sent as an argument to *png* in R.'
383 384 )
384 385 @argument(
385 386 '-h', '--height', type=int,
386 387 help='Height of png plotting device sent as an argument to *png* in R.'
387 388 )
388 389
389 390 @argument(
390 391 '-d', '--dataframe', action='append',
391 392 help='Convert these objects to data.frames and return as structured arrays.'
392 393 )
393 394 @argument(
394 395 '-u', '--units', type=unicode_type, choices=["px", "in", "cm", "mm"],
395 396 help='Units of png plotting device sent as an argument to *png* in R. One of ["px", "in", "cm", "mm"].'
396 397 )
397 398 @argument(
398 399 '-r', '--res', type=int,
399 400 help='Resolution of png plotting device sent as an argument to *png* in R. Defaults to 72 if *units* is one of ["in", "cm", "mm"].'
400 401 )
401 402 @argument(
402 403 '-p', '--pointsize', type=int,
403 404 help='Pointsize of png plotting device sent as an argument to *png* in R.'
404 405 )
405 406 @argument(
406 407 '-b', '--bg',
407 408 help='Background of png plotting device sent as an argument to *png* in R.'
408 409 )
409 410 @argument(
410 411 '-n', '--noreturn',
411 412 help='Force the magic to not return anything.',
412 413 action='store_true',
413 414 default=False
414 415 )
415 416 @argument(
416 417 'code',
417 418 nargs='*',
418 419 )
419 420 @needs_local_scope
420 421 @line_cell_magic
421 422 def R(self, line, cell=None, local_ns=None):
422 423 '''
423 424 Execute code in R, and pull some of the results back into the Python namespace.
424 425
425 426 In line mode, this will evaluate an expression and convert the returned value to a Python object.
426 427 The return value is determined by rpy2's behaviour of returning the result of evaluating the
427 428 final line.
428 429
429 430 Multiple R lines can be executed by joining them with semicolons::
430 431
431 432 In [9]: %R X=c(1,4,5,7); sd(X); mean(X)
432 433 Out[9]: array([ 4.25])
433 434
434 435 In cell mode, this will run a block of R code. The resulting value
435 436 is printed if it would printed be when evaluating the same code
436 437 within a standard R REPL.
437 438
438 439 Nothing is returned to python by default in cell mode::
439 440
440 441 In [10]: %%R
441 442 ....: Y = c(2,4,3,9)
442 443 ....: summary(lm(Y~X))
443 444
444 445 Call:
445 446 lm(formula = Y ~ X)
446 447
447 448 Residuals:
448 449 1 2 3 4
449 450 0.88 -0.24 -2.28 1.64
450 451
451 452 Coefficients:
452 453 Estimate Std. Error t value Pr(>|t|)
453 454 (Intercept) 0.0800 2.3000 0.035 0.975
454 455 X 1.0400 0.4822 2.157 0.164
455 456
456 457 Residual standard error: 2.088 on 2 degrees of freedom
457 458 Multiple R-squared: 0.6993,Adjusted R-squared: 0.549
458 459 F-statistic: 4.651 on 1 and 2 DF, p-value: 0.1638
459 460
460 461 In the notebook, plots are published as the output of the cell::
461 462
462 463 %R plot(X, Y)
463 464
464 465 will create a scatter plot of X bs Y.
465 466
466 467 If cell is not None and line has some R code, it is prepended to
467 468 the R code in cell.
468 469
469 470 Objects can be passed back and forth between rpy2 and python via the -i -o flags in line::
470 471
471 472 In [14]: Z = np.array([1,4,5,10])
472 473
473 474 In [15]: %R -i Z mean(Z)
474 475 Out[15]: array([ 5.])
475 476
476 477
477 478 In [16]: %R -o W W=Z*mean(Z)
478 479 Out[16]: array([ 5., 20., 25., 50.])
479 480
480 481 In [17]: W
481 482 Out[17]: array([ 5., 20., 25., 50.])
482 483
483 484 The return value is determined by these rules:
484 485
485 486 * If the cell is not None, the magic returns None.
486 487
487 488 * If the cell evaluates as False, the resulting value is returned
488 489 unless the final line prints something to the console, in
489 490 which case None is returned.
490 491
491 492 * If the final line results in a NULL value when evaluated
492 493 by rpy2, then None is returned.
493 494
494 495 * No attempt is made to convert the final value to a structured array.
495 496 Use the --dataframe flag or %Rget to push / return a structured array.
496 497
497 498 * If the -n flag is present, there is no return value.
498 499
499 500 * A trailing ';' will also result in no return value as the last
500 501 value in the line is an empty string.
501 502
502 503 The --dataframe argument will attempt to return structured arrays.
503 504 This is useful for dataframes with
504 505 mixed data types. Note also that for a data.frame,
505 506 if it is returned as an ndarray, it is transposed::
506 507
507 508 In [18]: dtype=[('x', '<i4'), ('y', '<f8'), ('z', '|S1')]
508 509
509 510 In [19]: datapy = np.array([(1, 2.9, 'a'), (2, 3.5, 'b'), (3, 2.1, 'c'), (4, 5, 'e')], dtype=dtype)
510 511
511 512 In [20]: %%R -o datar
512 513 datar = datapy
513 514 ....:
514 515
515 516 In [21]: datar
516 517 Out[21]:
517 518 array([['1', '2', '3', '4'],
518 519 ['2', '3', '2', '5'],
519 520 ['a', 'b', 'c', 'e']],
520 521 dtype='|S1')
521 522
522 523 In [22]: %%R -d datar
523 524 datar = datapy
524 525 ....:
525 526
526 527 In [23]: datar
527 528 Out[23]:
528 529 array([(1, 2.9, 'a'), (2, 3.5, 'b'), (3, 2.1, 'c'), (4, 5.0, 'e')],
529 530 dtype=[('x', '<i4'), ('y', '<f8'), ('z', '|S1')])
530 531
531 532 The --dataframe argument first tries colnames, then names.
532 533 If both are NULL, it returns an ndarray (i.e. unstructured)::
533 534
534 535 In [1]: %R mydata=c(4,6,8.3); NULL
535 536
536 537 In [2]: %R -d mydata
537 538
538 539 In [3]: mydata
539 540 Out[3]: array([ 4. , 6. , 8.3])
540 541
541 542 In [4]: %R names(mydata) = c('a','b','c'); NULL
542 543
543 544 In [5]: %R -d mydata
544 545
545 546 In [6]: mydata
546 547 Out[6]:
547 548 array((4.0, 6.0, 8.3),
548 549 dtype=[('a', '<f8'), ('b', '<f8'), ('c', '<f8')])
549 550
550 551 In [7]: %R -o mydata
551 552
552 553 In [8]: mydata
553 554 Out[8]: array([ 4. , 6. , 8.3])
554 555
555 556 '''
556 557
557 558 args = parse_argstring(self.R, line)
558 559
559 560 # arguments 'code' in line are prepended to
560 561 # the cell lines
561 562
562 563 if cell is None:
563 564 code = ''
564 565 return_output = True
565 566 line_mode = True
566 567 else:
567 568 code = cell
568 569 return_output = False
569 570 line_mode = False
570 571
571 572 code = ' '.join(args.code) + code
572 573
573 574 # if there is no local namespace then default to an empty dict
574 575 if local_ns is None:
575 576 local_ns = {}
576 577
577 578 if args.input:
578 579 for input in ','.join(args.input).split(','):
579 580 try:
580 581 val = local_ns[input]
581 582 except KeyError:
582 583 try:
583 584 val = self.shell.user_ns[input]
584 585 except KeyError:
585 586 raise NameError("name '%s' is not defined" % input)
586 587 self.r.assign(input, self.pyconverter(val))
587 588
588 589 if getattr(args, 'units') is not None:
589 590 if args.units != "px" and getattr(args, 'res') is None:
590 591 args.res = 72
591 592 args.units = '"%s"' % args.units
592 593
593 594 png_argdict = dict([(n, getattr(args, n)) for n in ['units', 'res', 'height', 'width', 'bg', 'pointsize']])
594 595 png_args = ','.join(['%s=%s' % (o,v) for o, v in png_argdict.items() if v is not None])
595 596 # execute the R code in a temporary directory
596 597
597 598 tmpd = tempfile.mkdtemp()
598 599 self.r('png("%s/Rplots%%03d.png",%s)' % (tmpd.replace('\\', '/'), png_args))
599 600
600 601 text_output = ''
601 602 try:
602 603 if line_mode:
603 604 for line in code.split(';'):
604 605 text_result, result, visible = self.eval(line)
605 606 text_output += text_result
606 607 if text_result:
607 608 # the last line printed something to the console so we won't return it
608 609 return_output = False
609 610 else:
610 611 text_result, result, visible = self.eval(code)
611 612 text_output += text_result
612 613 if visible:
613 614 old_writeconsole = ri.get_writeconsole()
614 615 ri.set_writeconsole(self.write_console)
615 616 ro.r.show(result)
616 617 text_output += self.flush()
617 618 ri.set_writeconsole(old_writeconsole)
618 619
619 620 except RInterpreterError as e:
620 print(e.stdout)
621 print((e.stdout))
621 622 if not e.stdout.endswith(e.err):
622 print(e.err)
623 print((e.err))
623 624 rmtree(tmpd)
624 625 return
625 626
626 627 self.r('dev.off()')
627 628
628 629 # read out all the saved .png files
629 630
630 631 images = [open(imgfile, 'rb').read() for imgfile in glob("%s/Rplots*png" % tmpd)]
631 632
632 633 # now publish the images
633 634 # mimicking IPython/zmq/pylab/backend_inline.py
634 635 fmt = 'png'
635 636 mimetypes = { 'png' : 'image/png', 'svg' : 'image/svg+xml' }
636 637 mime = mimetypes[fmt]
637 638
638 639 # publish the printed R objects, if any
639 640
640 641 display_data = []
641 642 if text_output:
642 643 display_data.append(('RMagic.R', {'text/plain':text_output}))
643 644
644 645 # flush text streams before sending figures, helps a little with output
645 646 for image in images:
646 647 # synchronization in the console (though it's a bandaid, not a real sln)
647 648 sys.stdout.flush(); sys.stderr.flush()
648 649 display_data.append(('RMagic.R', {mime: image}))
649 650
650 651 # kill the temporary directory
651 652 rmtree(tmpd)
652 653
653 654 # try to turn every output into a numpy array
654 655 # this means that output are assumed to be castable
655 656 # as numpy arrays
656 657
657 658 if args.output:
658 659 for output in ','.join(args.output).split(','):
659 660 self.shell.push({output:self.Rconverter(self.r(output), dataframe=False)})
660 661
661 662 if args.dataframe:
662 663 for output in ','.join(args.dataframe).split(','):
663 664 self.shell.push({output:self.Rconverter(self.r(output), dataframe=True)})
664 665
665 666 for tag, disp_d in display_data:
666 667 publish_display_data(tag, disp_d)
667 668
668 669 # this will keep a reference to the display_data
669 670 # which might be useful to other objects who happen to use
670 671 # this method
671 672
672 673 if self.cache_display_data:
673 674 self.display_cache = display_data
674 675
675 676 # if in line mode and return_output, return the result as an ndarray
676 677 if return_output and not args.noreturn:
677 678 if result != ri.NULL:
678 679 return self.Rconverter(result, dataframe=False)
679 680
680 681 __doc__ = __doc__.format(
681 682 R_DOC = ' '*8 + RMagics.R.__doc__,
682 683 RPUSH_DOC = ' '*8 + RMagics.Rpush.__doc__,
683 684 RPULL_DOC = ' '*8 + RMagics.Rpull.__doc__,
684 685 RGET_DOC = ' '*8 + RMagics.Rget.__doc__
685 686 )
686 687
687 688
688 689 def load_ipython_extension(ip):
689 690 """Load the extension in IPython."""
690 691 ip.register_magics(RMagics)
691 692 # Initialising rpy2 interferes with readline. Since, at this point, we've
692 693 # probably just loaded rpy2, we reset the delimiters. See issue gh-2759.
693 694 if ip.has_readline:
694 695 ip.readline.set_completer_delims(ip.readline_delims)
@@ -1,241 +1,242 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 %store magic for lightweight persistence.
4 4
5 5 Stores variables, aliases and macros in IPython's database.
6 6
7 7 To automatically restore stored variables at startup, add this to your
8 8 :file:`ipython_config.py` file::
9 9
10 10 c.StoreMagic.autorestore = True
11 11 """
12 from __future__ import print_function
12 13 #-----------------------------------------------------------------------------
13 14 # Copyright (c) 2012, The IPython Development Team.
14 15 #
15 16 # Distributed under the terms of the Modified BSD License.
16 17 #
17 18 # The full license is in the file COPYING.txt, distributed with this software.
18 19 #-----------------------------------------------------------------------------
19 20
20 21 #-----------------------------------------------------------------------------
21 22 # Imports
22 23 #-----------------------------------------------------------------------------
23 24
24 25 # Stdlib
25 26 import inspect, os, sys, textwrap
26 27
27 28 # Our own
28 29 from IPython.core.error import UsageError
29 30 from IPython.core.magic import Magics, magics_class, line_magic
30 31 from IPython.testing.skipdoctest import skip_doctest
31 32 from IPython.utils.traitlets import Bool
32 33
33 34 #-----------------------------------------------------------------------------
34 35 # Functions and classes
35 36 #-----------------------------------------------------------------------------
36 37
37 38 def restore_aliases(ip):
38 39 staliases = ip.db.get('stored_aliases', {})
39 40 for k,v in staliases.items():
40 41 #print "restore alias",k,v # dbg
41 42 #self.alias_table[k] = v
42 43 ip.alias_manager.define_alias(k,v)
43 44
44 45
45 46 def refresh_variables(ip):
46 47 db = ip.db
47 48 for key in db.keys('autorestore/*'):
48 49 # strip autorestore
49 50 justkey = os.path.basename(key)
50 51 try:
51 52 obj = db[key]
52 53 except KeyError:
53 print "Unable to restore variable '%s', ignoring (use %%store -d to forget!)" % justkey
54 print "The error was:", sys.exc_info()[0]
54 print("Unable to restore variable '%s', ignoring (use %%store -d to forget!)" % justkey)
55 print("The error was:", sys.exc_info()[0])
55 56 else:
56 57 #print "restored",justkey,"=",obj #dbg
57 58 ip.user_ns[justkey] = obj
58 59
59 60
60 61 def restore_dhist(ip):
61 62 ip.user_ns['_dh'] = ip.db.get('dhist',[])
62 63
63 64
64 65 def restore_data(ip):
65 66 refresh_variables(ip)
66 67 restore_aliases(ip)
67 68 restore_dhist(ip)
68 69
69 70
70 71 @magics_class
71 72 class StoreMagics(Magics):
72 73 """Lightweight persistence for python variables.
73 74
74 75 Provides the %store magic."""
75 76
76 77 autorestore = Bool(False, config=True, help=
77 78 """If True, any %store-d variables will be automatically restored
78 79 when IPython starts.
79 80 """
80 81 )
81 82
82 83 def __init__(self, shell):
83 84 super(StoreMagics, self).__init__(shell=shell)
84 85 self.shell.configurables.append(self)
85 86 if self.autorestore:
86 87 restore_data(self.shell)
87 88
88 89 @skip_doctest
89 90 @line_magic
90 91 def store(self, parameter_s=''):
91 92 """Lightweight persistence for python variables.
92 93
93 94 Example::
94 95
95 96 In [1]: l = ['hello',10,'world']
96 97 In [2]: %store l
97 98 In [3]: exit
98 99
99 100 (IPython session is closed and started again...)
100 101
101 102 ville@badger:~$ ipython
102 103 In [1]: l
103 104 NameError: name 'l' is not defined
104 105 In [2]: %store -r
105 106 In [3]: l
106 107 Out[3]: ['hello', 10, 'world']
107 108
108 109 Usage:
109 110
110 111 * ``%store`` - Show list of all variables and their current
111 112 values
112 113 * ``%store spam`` - Store the *current* value of the variable spam
113 114 to disk
114 115 * ``%store -d spam`` - Remove the variable and its value from storage
115 116 * ``%store -z`` - Remove all variables from storage
116 117 * ``%store -r`` - Refresh all variables from store (overwrite
117 118 current vals)
118 119 * ``%store -r spam bar`` - Refresh specified variables from store
119 120 (delete current val)
120 121 * ``%store foo >a.txt`` - Store value of foo to new file a.txt
121 122 * ``%store foo >>a.txt`` - Append value of foo to file a.txt
122 123
123 124 It should be noted that if you change the value of a variable, you
124 125 need to %store it again if you want to persist the new value.
125 126
126 127 Note also that the variables will need to be pickleable; most basic
127 128 python types can be safely %store'd.
128 129
129 130 Also aliases can be %store'd across sessions.
130 131 """
131 132
132 133 opts,argsl = self.parse_options(parameter_s,'drz',mode='string')
133 134 args = argsl.split(None,1)
134 135 ip = self.shell
135 136 db = ip.db
136 137 # delete
137 138 if 'd' in opts:
138 139 try:
139 140 todel = args[0]
140 141 except IndexError:
141 142 raise UsageError('You must provide the variable to forget')
142 143 else:
143 144 try:
144 145 del db['autorestore/' + todel]
145 146 except:
146 147 raise UsageError("Can't delete variable '%s'" % todel)
147 148 # reset
148 149 elif 'z' in opts:
149 150 for k in db.keys('autorestore/*'):
150 151 del db[k]
151 152
152 153 elif 'r' in opts:
153 154 if args:
154 155 for arg in args:
155 156 try:
156 157 obj = db['autorestore/' + arg]
157 158 except KeyError:
158 print "no stored variable %s" % arg
159 print("no stored variable %s" % arg)
159 160 else:
160 161 ip.user_ns[arg] = obj
161 162 else:
162 163 restore_data(ip)
163 164
164 165 # run without arguments -> list variables & values
165 166 elif not args:
166 167 vars = db.keys('autorestore/*')
167 168 vars.sort()
168 169 if vars:
169 170 size = max(map(len, vars))
170 171 else:
171 172 size = 0
172 173
173 print 'Stored variables and their in-db values:'
174 print('Stored variables and their in-db values:')
174 175 fmt = '%-'+str(size)+'s -> %s'
175 176 get = db.get
176 177 for var in vars:
177 178 justkey = os.path.basename(var)
178 179 # print 30 first characters from every var
179 print fmt % (justkey, repr(get(var, '<unavailable>'))[:50])
180 print(fmt % (justkey, repr(get(var, '<unavailable>'))[:50]))
180 181
181 182 # default action - store the variable
182 183 else:
183 184 # %store foo >file.txt or >>file.txt
184 185 if len(args) > 1 and args[1].startswith('>'):
185 186 fnam = os.path.expanduser(args[1].lstrip('>').lstrip())
186 187 if args[1].startswith('>>'):
187 188 fil = open(fnam, 'a')
188 189 else:
189 190 fil = open(fnam, 'w')
190 191 obj = ip.ev(args[0])
191 print "Writing '%s' (%s) to file '%s'." % (args[0],
192 obj.__class__.__name__, fnam)
192 print("Writing '%s' (%s) to file '%s'." % (args[0],
193 obj.__class__.__name__, fnam))
193 194
194 195
195 196 if not isinstance (obj, basestring):
196 197 from pprint import pprint
197 198 pprint(obj, fil)
198 199 else:
199 200 fil.write(obj)
200 201 if not obj.endswith('\n'):
201 202 fil.write('\n')
202 203
203 204 fil.close()
204 205 return
205 206
206 207 # %store foo
207 208 try:
208 209 obj = ip.user_ns[args[0]]
209 210 except KeyError:
210 211 # it might be an alias
211 212 name = args[0]
212 213 try:
213 214 cmd = ip.alias_manager.retrieve_alias(name)
214 215 except ValueError:
215 216 raise UsageError("Unknown variable '%s'" % name)
216 217
217 218 staliases = db.get('stored_aliases',{})
218 219 staliases[name] = cmd
219 220 db['stored_aliases'] = staliases
220 print "Alias stored: %s (%s)" % (name, cmd)
221 print("Alias stored: %s (%s)" % (name, cmd))
221 222 return
222 223
223 224 else:
224 225 modname = getattr(inspect.getmodule(obj), '__name__', '')
225 226 if modname == '__main__':
226 print textwrap.dedent("""\
227 print(textwrap.dedent("""\
227 228 Warning:%s is %s
228 229 Proper storage of interactively declared classes (or instances
229 230 of those classes) is not possible! Only instances
230 231 of classes in real modules on file system can be %%store'd.
231 """ % (args[0], obj) )
232 """ % (args[0], obj) ))
232 233 return
233 234 #pickled = pickle.dumps(obj)
234 235 db[ 'autorestore/' + args[0] ] = obj
235 print "Stored '%s' (%s)" % (args[0], obj.__class__.__name__)
236 print("Stored '%s' (%s)" % (args[0], obj.__class__.__name__))
236 237
237 238
238 239 def load_ipython_extension(ip):
239 240 """Load the extension in IPython."""
240 241 ip.register_magics(StoreMagics)
241 242
@@ -1,220 +1,221 b''
1 1 ########################## LICENCE ###############################
2 2
3 3 # Copyright (c) 2005-2012, Michele Simionato
4 4 # All rights reserved.
5 5
6 6 # Redistribution and use in source and binary forms, with or without
7 7 # modification, are permitted provided that the following conditions are
8 8 # met:
9 9
10 10 # Redistributions of source code must retain the above copyright
11 11 # notice, this list of conditions and the following disclaimer.
12 12 # Redistributions in bytecode form must reproduce the above copyright
13 13 # notice, this list of conditions and the following disclaimer in
14 14 # the documentation and/or other materials provided with the
15 15 # distribution.
16 16
17 17 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 18 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 19 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 20 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 21 # HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22 22 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23 23 # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
24 24 # OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 25 # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
26 26 # TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
27 27 # USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
28 28 # DAMAGE.
29 29
30 30 """
31 31 Decorator module, see http://pypi.python.org/pypi/decorator
32 32 for the documentation.
33 33 """
34 from __future__ import print_function
34 35
35 36 __version__ = '3.3.3'
36 37
37 38 __all__ = ["decorator", "FunctionMaker", "partial"]
38 39
39 40 import sys, re, inspect
40 41
41 42 try:
42 43 from functools import partial
43 44 except ImportError: # for Python version < 2.5
44 45 class partial(object):
45 46 "A simple replacement of functools.partial"
46 47 def __init__(self, func, *args, **kw):
47 48 self.func = func
48 49 self.args = args
49 50 self.keywords = kw
50 51 def __call__(self, *otherargs, **otherkw):
51 52 kw = self.keywords.copy()
52 53 kw.update(otherkw)
53 54 return self.func(*(self.args + otherargs), **kw)
54 55
55 56 if sys.version >= '3':
56 57 from inspect import getfullargspec
57 58 else:
58 59 class getfullargspec(object):
59 60 "A quick and dirty replacement for getfullargspec for Python 2.X"
60 61 def __init__(self, f):
61 62 self.args, self.varargs, self.varkw, self.defaults = \
62 63 inspect.getargspec(f)
63 64 self.kwonlyargs = []
64 65 self.kwonlydefaults = None
65 66 def __iter__(self):
66 67 yield self.args
67 68 yield self.varargs
68 69 yield self.varkw
69 70 yield self.defaults
70 71
71 72 DEF = re.compile('\s*def\s*([_\w][_\w\d]*)\s*\(')
72 73
73 74 # basic functionality
74 75 class FunctionMaker(object):
75 76 """
76 77 An object with the ability to create functions with a given signature.
77 78 It has attributes name, doc, module, signature, defaults, dict and
78 79 methods update and make.
79 80 """
80 81 def __init__(self, func=None, name=None, signature=None,
81 82 defaults=None, doc=None, module=None, funcdict=None):
82 83 self.shortsignature = signature
83 84 if func:
84 85 # func can be a class or a callable, but not an instance method
85 86 self.name = func.__name__
86 87 if self.name == '<lambda>': # small hack for lambda functions
87 88 self.name = '_lambda_'
88 89 self.doc = func.__doc__
89 90 self.module = func.__module__
90 91 if inspect.isfunction(func):
91 92 argspec = getfullargspec(func)
92 93 self.annotations = getattr(func, '__annotations__', {})
93 94 for a in ('args', 'varargs', 'varkw', 'defaults', 'kwonlyargs',
94 95 'kwonlydefaults'):
95 96 setattr(self, a, getattr(argspec, a))
96 97 for i, arg in enumerate(self.args):
97 98 setattr(self, 'arg%d' % i, arg)
98 99 if sys.version < '3': # easy way
99 100 self.shortsignature = self.signature = \
100 101 inspect.formatargspec(
101 102 formatvalue=lambda val: "", *argspec)[1:-1]
102 103 else: # Python 3 way
103 104 self.signature = self.shortsignature = ', '.join(self.args)
104 105 if self.varargs:
105 106 self.signature += ', *' + self.varargs
106 107 self.shortsignature += ', *' + self.varargs
107 108 if self.kwonlyargs:
108 109 for a in self.kwonlyargs:
109 110 self.signature += ', %s=None' % a
110 111 self.shortsignature += ', %s=%s' % (a, a)
111 112 if self.varkw:
112 113 self.signature += ', **' + self.varkw
113 114 self.shortsignature += ', **' + self.varkw
114 115 self.dict = func.__dict__.copy()
115 116 # func=None happens when decorating a caller
116 117 if name:
117 118 self.name = name
118 119 if signature is not None:
119 120 self.signature = signature
120 121 if defaults:
121 122 self.defaults = defaults
122 123 if doc:
123 124 self.doc = doc
124 125 if module:
125 126 self.module = module
126 127 if funcdict:
127 128 self.dict = funcdict
128 129 # check existence required attributes
129 130 assert hasattr(self, 'name')
130 131 if not hasattr(self, 'signature'):
131 132 raise TypeError('You are decorating a non function: %s' % func)
132 133
133 134 def update(self, func, **kw):
134 135 "Update the signature of func with the data in self"
135 136 func.__name__ = self.name
136 137 func.__doc__ = getattr(self, 'doc', None)
137 138 func.__dict__ = getattr(self, 'dict', {})
138 139 func.func_defaults = getattr(self, 'defaults', ())
139 140 func.__kwdefaults__ = getattr(self, 'kwonlydefaults', None)
140 141 func.__annotations__ = getattr(self, 'annotations', None)
141 142 callermodule = sys._getframe(3).f_globals.get('__name__', '?')
142 143 func.__module__ = getattr(self, 'module', callermodule)
143 144 func.__dict__.update(kw)
144 145
145 146 def make(self, src_templ, evaldict=None, addsource=False, **attrs):
146 147 "Make a new function from a given template and update the signature"
147 148 src = src_templ % vars(self) # expand name and signature
148 149 evaldict = evaldict or {}
149 150 mo = DEF.match(src)
150 151 if mo is None:
151 152 raise SyntaxError('not a valid function template\n%s' % src)
152 153 name = mo.group(1) # extract the function name
153 154 names = set([name] + [arg.strip(' *') for arg in
154 155 self.shortsignature.split(',')])
155 156 for n in names:
156 157 if n in ('_func_', '_call_'):
157 158 raise NameError('%s is overridden in\n%s' % (n, src))
158 159 if not src.endswith('\n'): # add a newline just for safety
159 160 src += '\n' # this is needed in old versions of Python
160 161 try:
161 162 code = compile(src, '<string>', 'single')
162 163 # print >> sys.stderr, 'Compiling %s' % src
163 164 exec code in evaldict
164 165 except:
165 print >> sys.stderr, 'Error in generated code:'
166 print >> sys.stderr, src
166 print('Error in generated code:', file=sys.stderr)
167 print(src, file=sys.stderr)
167 168 raise
168 169 func = evaldict[name]
169 170 if addsource:
170 171 attrs['__source__'] = src
171 172 self.update(func, **attrs)
172 173 return func
173 174
174 175 @classmethod
175 176 def create(cls, obj, body, evaldict, defaults=None,
176 177 doc=None, module=None, addsource=True, **attrs):
177 178 """
178 179 Create a function from the strings name, signature and body.
179 180 evaldict is the evaluation dictionary. If addsource is true an attribute
180 181 __source__ is added to the result. The attributes attrs are added,
181 182 if any.
182 183 """
183 184 if isinstance(obj, str): # "name(signature)"
184 185 name, rest = obj.strip().split('(', 1)
185 186 signature = rest[:-1] #strip a right parens
186 187 func = None
187 188 else: # a function
188 189 name = None
189 190 signature = None
190 191 func = obj
191 192 self = cls(func, name, signature, defaults, doc, module)
192 193 ibody = '\n'.join(' ' + line for line in body.splitlines())
193 194 return self.make('def %(name)s(%(signature)s):\n' + ibody,
194 195 evaldict, addsource, **attrs)
195 196
196 197 def decorator(caller, func=None):
197 198 """
198 199 decorator(caller) converts a caller function into a decorator;
199 200 decorator(caller, func) decorates a function using a caller.
200 201 """
201 202 if func is not None: # returns a decorated function
202 203 evaldict = func.func_globals.copy()
203 204 evaldict['_call_'] = caller
204 205 evaldict['_func_'] = func
205 206 return FunctionMaker.create(
206 207 func, "return _call_(_func_, %(shortsignature)s)",
207 208 evaldict, undecorated=func, __wrapped__=func)
208 209 else: # returns a decorator
209 210 if isinstance(caller, partial):
210 211 return partial(decorator, caller)
211 212 # otherwise assume caller is a function
212 213 first = inspect.getargspec(caller)[0][0] # first arg
213 214 evaldict = caller.func_globals.copy()
214 215 evaldict['_call_'] = caller
215 216 evaldict['decorator'] = decorator
216 217 return FunctionMaker.create(
217 218 '%s(%s)' % (caller.__name__, first),
218 219 'return decorator(_call_, %s)' % first,
219 220 evaldict, undecorated=caller, __wrapped__=caller,
220 221 doc=caller.__doc__, module=caller.__module__)
@@ -1,233 +1,234 b''
1 1 #!/usr/bin/python
2 2 """Utility function for installing MathJax javascript library into
3 3 your IPython nbextensions directory, for offline use.
4 4
5 5 Authors:
6 6
7 7 * Min RK
8 8 * Mark Sienkiewicz
9 9 * Matthias Bussonnier
10 10
11 11 To download and install MathJax:
12 12
13 13 From Python:
14 14
15 15 >>> from IPython.external.mathjax import install_mathjax
16 16 >>> install_mathjax()
17 17
18 18 From the command line:
19 19
20 20 $ python -m IPython.external.mathjax
21 21
22 22 To a specific location:
23 23
24 24 $ python -m IPython.external.mathjax -i /usr/share/
25 25
26 26 will install mathjax to /usr/share/mathjax
27 27
28 28 To install MathJax from a file you have already downloaded:
29 29
30 30 $ python -m IPython.external.mathjax mathjax-xxx.tar.gz
31 31 $ python -m IPython.external.mathjax mathjax-xxx.zip
32 32
33 33 It will not install MathJax if it is already there. Use -r to
34 34 replace the existing copy of MathJax.
35 35
36 36 To find the directory where IPython would like MathJax installed:
37 37
38 38 $ python -m IPython.external.mathjax -d
39 39
40 40 """
41 from __future__ import print_function
41 42
42 43
43 44 #-----------------------------------------------------------------------------
44 45 # Copyright (C) 2011 The IPython Development Team
45 46 #
46 47 # Distributed under the terms of the BSD License. The full license is in
47 48 # the file COPYING, distributed as part of this software.
48 49 #-----------------------------------------------------------------------------
49 50
50 51
51 52 #-----------------------------------------------------------------------------
52 53 # Imports
53 54 #-----------------------------------------------------------------------------
54 55
55 56 import argparse
56 57 import os
57 58 import shutil
58 59 import sys
59 60 import tarfile
60 61 import urllib2
61 62 import zipfile
62 63
63 64 from IPython.utils.path import get_ipython_dir
64 65
65 66 #-----------------------------------------------------------------------------
66 67 #
67 68 #-----------------------------------------------------------------------------
68 69
69 70 # Where mathjax will be installed
70 71
71 72 nbextensions = os.path.join(get_ipython_dir(), 'nbextensions')
72 73 default_dest = os.path.join(nbextensions, 'mathjax')
73 74
74 75 # Test for access to install mathjax
75 76
76 77 def prepare_dest(dest, replace=False):
77 78 """prepare the destination folder for mathjax install
78 79
79 80 Returns False if mathjax appears to already be installed and there is nothing to do,
80 81 True otherwise.
81 82 """
82 83
83 84 parent = os.path.abspath(os.path.join(dest, os.path.pardir))
84 85 if not os.path.exists(parent):
85 86 os.makedirs(parent)
86 87
87 88 if os.path.exists(dest):
88 89 if replace:
89 print "removing existing MathJax at %s" % dest
90 print("removing existing MathJax at %s" % dest)
90 91 shutil.rmtree(dest)
91 92 return True
92 93 else:
93 94 mathjax_js = os.path.join(dest, 'MathJax.js')
94 95 if not os.path.exists(mathjax_js):
95 96 raise IOError("%s exists, but does not contain MathJax.js" % dest)
96 print "%s already exists" % mathjax_js
97 print("%s already exists" % mathjax_js)
97 98 return False
98 99 else:
99 100 return True
100 101
101 102
102 103 def extract_tar(fd, dest):
103 104 """extract a tarball from filelike `fd` to destination `dest`"""
104 105 # use 'r|gz' stream mode, because socket file-like objects can't seek:
105 106 tar = tarfile.open(fileobj=fd, mode='r|gz')
106 107
107 108 # The first entry in the archive is the top-level dir
108 109 topdir = tar.firstmember.path
109 110
110 111 # extract the archive (contains a single directory) to the destination directory
111 112 parent = os.path.abspath(os.path.join(dest, os.path.pardir))
112 113 tar.extractall(parent)
113 114
114 115 # it will be mathjax-MathJax-<sha>, rename to just mathjax
115 116 os.rename(os.path.join(parent, topdir), dest)
116 117
117 118
118 119 def extract_zip(fd, dest):
119 120 """extract a zip file from filelike `fd` to destination `dest`"""
120 121 z = zipfile.ZipFile(fd, 'r')
121 122
122 123 # The first entry in the archive is the top-level dir
123 124 topdir = z.namelist()[0]
124 125
125 126 # extract the archive (contains a single directory) to the static/ directory
126 127 parent = os.path.abspath(os.path.join(dest, os.path.pardir))
127 128 z.extractall(parent)
128 129
129 130 # it will be mathjax-MathJax-<sha>, rename to just mathjax
130 131 d = os.path.join(parent, topdir)
131 132 os.rename(os.path.join(parent, topdir), dest)
132 133
133 134
134 135 def install_mathjax(tag='v2.2', dest=default_dest, replace=False, file=None, extractor=extract_tar):
135 136 """Download and/or install MathJax for offline use.
136 137
137 138 This will install mathjax to the nbextensions dir in your IPYTHONDIR.
138 139
139 140 MathJax is a ~15MB download, and ~150MB installed.
140 141
141 142 Parameters
142 143 ----------
143 144
144 145 replace : bool [False]
145 146 Whether to remove and replace an existing install.
146 147 dest : str [IPYTHONDIR/nbextensions/mathjax]
147 148 Where to install mathjax
148 149 tag : str ['v2.2']
149 150 Which tag to download. Default is 'v2.2', the current stable release,
150 151 but alternatives include 'v1.1a' and 'master'.
151 152 file : file like object [ defualt to content of https://github.com/mathjax/MathJax/tarball/#{tag}]
152 153 File handle from which to untar/unzip/... mathjax
153 154 extractor : function
154 155 Method to use to untar/unzip/... `file`
155 156 """
156 157 try:
157 158 anything_to_do = prepare_dest(dest, replace)
158 159 except OSError as e:
159 print("ERROR %s, require write access to %s" % (e, dest))
160 print(("ERROR %s, require write access to %s" % (e, dest)))
160 161 return 1
161 162 else:
162 163 if not anything_to_do:
163 164 return 0
164 165
165 166 if file is None:
166 167 # download mathjax
167 168 mathjax_url = "https://github.com/mathjax/MathJax/archive/%s.tar.gz" %tag
168 print "Downloading mathjax source from %s" % mathjax_url
169 print("Downloading mathjax source from %s" % mathjax_url)
169 170 response = urllib2.urlopen(mathjax_url)
170 171 file = response.fp
171 172
172 print "Extracting to %s" % dest
173 print("Extracting to %s" % dest)
173 174 extractor(file, dest)
174 175 return 0
175 176
176 177
177 178 def main():
178 179 parser = argparse.ArgumentParser(
179 180 description="""Install mathjax from internet or local archive""",
180 181 )
181 182
182 183 parser.add_argument(
183 184 '-i',
184 185 '--install-dir',
185 186 default=nbextensions,
186 187 help='custom installation directory. Mathjax will be installed in here/mathjax')
187 188
188 189 parser.add_argument(
189 190 '-d',
190 191 '--print-dest',
191 192 action='store_true',
192 193 help='print where mathjax would be installed and exit')
193 194 parser.add_argument(
194 195 '-r',
195 196 '--replace',
196 197 action='store_true',
197 198 help='Whether to replace current mathjax if it already exists')
198 199 parser.add_argument('filename',
199 200 help="the local tar/zip-ball filename containing mathjax",
200 201 nargs='?',
201 202 metavar='filename')
202 203
203 204 pargs = parser.parse_args()
204 205
205 206 dest = os.path.join(pargs.install_dir, 'mathjax')
206 207
207 208 if pargs.print_dest:
208 print dest
209 print(dest)
209 210 return
210 211
211 212 # remove/replace existing mathjax?
212 213 replace = pargs.replace
213 214
214 215 # do it
215 216 if pargs.filename:
216 217 fname = pargs.filename
217 218
218 219 # automatically detect zip/tar - could do something based
219 220 # on file content, but really not cost-effective here.
220 221 if fname.endswith('.zip'):
221 222 extractor = extract_zip
222 223 else :
223 224 extractor = extract_tar
224 225 # do it
225 226 return install_mathjax(file=open(fname, "rb"), replace=replace, extractor=extractor, dest=dest)
226 227 else:
227 228 return install_mathjax(replace=replace, dest=dest)
228 229
229 230
230 231 if __name__ == '__main__' :
231 232 sys.exit(main())
232 233
233 234 __all__ = ['install_mathjax', 'main', 'default_dest']
@@ -1,747 +1,748 b''
1 1 # coding: utf-8
2 2 """A tornado based IPython notebook server.
3 3
4 4 Authors:
5 5
6 6 * Brian Granger
7 7 """
8 from __future__ import print_function
8 9 #-----------------------------------------------------------------------------
9 10 # Copyright (C) 2013 The IPython Development Team
10 11 #
11 12 # Distributed under the terms of the BSD License. The full license is in
12 13 # the file COPYING, distributed as part of this software.
13 14 #-----------------------------------------------------------------------------
14 15
15 16 #-----------------------------------------------------------------------------
16 17 # Imports
17 18 #-----------------------------------------------------------------------------
18 19
19 20 # stdlib
20 21 import errno
21 22 import logging
22 23 import os
23 24 import random
24 25 import select
25 26 import signal
26 27 import socket
27 28 import sys
28 29 import threading
29 30 import time
30 31 import webbrowser
31 32
32 33
33 34 # Third party
34 35 # check for pyzmq 2.1.11
35 36 from IPython.utils.zmqrelated import check_for_zmq
36 37 check_for_zmq('2.1.11', 'IPython.html')
37 38
38 39 from jinja2 import Environment, FileSystemLoader
39 40
40 41 # Install the pyzmq ioloop. This has to be done before anything else from
41 42 # tornado is imported.
42 43 from zmq.eventloop import ioloop
43 44 ioloop.install()
44 45
45 46 # check for tornado 3.1.0
46 47 msg = "The IPython Notebook requires tornado >= 3.1.0"
47 48 try:
48 49 import tornado
49 50 except ImportError:
50 51 raise ImportError(msg)
51 52 try:
52 53 version_info = tornado.version_info
53 54 except AttributeError:
54 55 raise ImportError(msg + ", but you have < 1.1.0")
55 56 if version_info < (3,1,0):
56 57 raise ImportError(msg + ", but you have %s" % tornado.version)
57 58
58 59 from tornado import httpserver
59 60 from tornado import web
60 61
61 62 # Our own libraries
62 63 from IPython.html import DEFAULT_STATIC_FILES_PATH
63 64
64 65 from .services.kernels.kernelmanager import MappingKernelManager
65 66 from .services.notebooks.nbmanager import NotebookManager
66 67 from .services.notebooks.filenbmanager import FileNotebookManager
67 68 from .services.clusters.clustermanager import ClusterManager
68 69 from .services.sessions.sessionmanager import SessionManager
69 70
70 71 from .base.handlers import AuthenticatedFileHandler, FileFindHandler
71 72
72 73 from IPython.config.application import catch_config_error, boolean_flag
73 74 from IPython.core.application import BaseIPythonApplication
74 75 from IPython.consoleapp import IPythonConsoleApp
75 76 from IPython.kernel import swallow_argv
76 77 from IPython.kernel.zmq.session import default_secure
77 78 from IPython.kernel.zmq.kernelapp import (
78 79 kernel_flags,
79 80 kernel_aliases,
80 81 )
81 82 from IPython.utils.importstring import import_item
82 83 from IPython.utils.localinterfaces import localhost
83 84 from IPython.utils import submodule
84 85 from IPython.utils.traitlets import (
85 86 Dict, Unicode, Integer, List, Bool, Bytes,
86 87 DottedObjectName
87 88 )
88 89 from IPython.utils import py3compat
89 90 from IPython.utils.path import filefind, get_ipython_dir
90 91
91 92 from .utils import url_path_join
92 93
93 94 #-----------------------------------------------------------------------------
94 95 # Module globals
95 96 #-----------------------------------------------------------------------------
96 97
97 98 _examples = """
98 99 ipython notebook # start the notebook
99 100 ipython notebook --profile=sympy # use the sympy profile
100 101 ipython notebook --certfile=mycert.pem # use SSL/TLS certificate
101 102 """
102 103
103 104 #-----------------------------------------------------------------------------
104 105 # Helper functions
105 106 #-----------------------------------------------------------------------------
106 107
107 108 def random_ports(port, n):
108 109 """Generate a list of n random ports near the given port.
109 110
110 111 The first 5 ports will be sequential, and the remaining n-5 will be
111 112 randomly selected in the range [port-2*n, port+2*n].
112 113 """
113 114 for i in range(min(5, n)):
114 115 yield port + i
115 116 for i in range(n-5):
116 117 yield max(1, port + random.randint(-2*n, 2*n))
117 118
118 119 def load_handlers(name):
119 120 """Load the (URL pattern, handler) tuples for each component."""
120 121 name = 'IPython.html.' + name
121 122 mod = __import__(name, fromlist=['default_handlers'])
122 123 return mod.default_handlers
123 124
124 125 #-----------------------------------------------------------------------------
125 126 # The Tornado web application
126 127 #-----------------------------------------------------------------------------
127 128
128 129 class NotebookWebApplication(web.Application):
129 130
130 131 def __init__(self, ipython_app, kernel_manager, notebook_manager,
131 132 cluster_manager, session_manager, log, base_project_url,
132 133 settings_overrides):
133 134
134 135 settings = self.init_settings(
135 136 ipython_app, kernel_manager, notebook_manager, cluster_manager,
136 137 session_manager, log, base_project_url, settings_overrides)
137 138 handlers = self.init_handlers(settings)
138 139
139 140 super(NotebookWebApplication, self).__init__(handlers, **settings)
140 141
141 142 def init_settings(self, ipython_app, kernel_manager, notebook_manager,
142 143 cluster_manager, session_manager, log, base_project_url,
143 144 settings_overrides):
144 145 # Python < 2.6.5 doesn't accept unicode keys in f(**kwargs), and
145 146 # base_project_url will always be unicode, which will in turn
146 147 # make the patterns unicode, and ultimately result in unicode
147 148 # keys in kwargs to handler._execute(**kwargs) in tornado.
148 149 # This enforces that base_project_url be ascii in that situation.
149 150 #
150 151 # Note that the URLs these patterns check against are escaped,
151 152 # and thus guaranteed to be ASCII: 'héllo' is really 'h%C3%A9llo'.
152 153 base_project_url = py3compat.unicode_to_str(base_project_url, 'ascii')
153 154 template_path = settings_overrides.get("template_path", os.path.join(os.path.dirname(__file__), "templates"))
154 155 settings = dict(
155 156 # basics
156 157 base_project_url=base_project_url,
157 158 base_kernel_url=ipython_app.base_kernel_url,
158 159 template_path=template_path,
159 160 static_path=ipython_app.static_file_path,
160 161 static_handler_class = FileFindHandler,
161 162 static_url_prefix = url_path_join(base_project_url,'/static/'),
162 163
163 164 # authentication
164 165 cookie_secret=ipython_app.cookie_secret,
165 166 login_url=url_path_join(base_project_url,'/login'),
166 167 password=ipython_app.password,
167 168
168 169 # managers
169 170 kernel_manager=kernel_manager,
170 171 notebook_manager=notebook_manager,
171 172 cluster_manager=cluster_manager,
172 173 session_manager=session_manager,
173 174
174 175 # IPython stuff
175 176 nbextensions_path = ipython_app.nbextensions_path,
176 177 mathjax_url=ipython_app.mathjax_url,
177 178 config=ipython_app.config,
178 179 use_less=ipython_app.use_less,
179 180 jinja2_env=Environment(loader=FileSystemLoader(template_path)),
180 181 )
181 182
182 183 # allow custom overrides for the tornado web app.
183 184 settings.update(settings_overrides)
184 185 return settings
185 186
186 187 def init_handlers(self, settings):
187 188 # Load the (URL pattern, handler) tuples for each component.
188 189 handlers = []
189 190 handlers.extend(load_handlers('base.handlers'))
190 191 handlers.extend(load_handlers('tree.handlers'))
191 192 handlers.extend(load_handlers('auth.login'))
192 193 handlers.extend(load_handlers('auth.logout'))
193 194 handlers.extend(load_handlers('notebook.handlers'))
194 195 handlers.extend(load_handlers('services.kernels.handlers'))
195 196 handlers.extend(load_handlers('services.notebooks.handlers'))
196 197 handlers.extend(load_handlers('services.clusters.handlers'))
197 198 handlers.extend(load_handlers('services.sessions.handlers'))
198 199 handlers.extend([
199 200 (r"/files/(.*)", AuthenticatedFileHandler, {'path' : settings['notebook_manager'].notebook_dir}),
200 201 (r"/nbextensions/(.*)", FileFindHandler, {'path' : settings['nbextensions_path']}),
201 202 ])
202 203 # prepend base_project_url onto the patterns that we match
203 204 new_handlers = []
204 205 for handler in handlers:
205 206 pattern = url_path_join(settings['base_project_url'], handler[0])
206 207 new_handler = tuple([pattern] + list(handler[1:]))
207 208 new_handlers.append(new_handler)
208 209 return new_handlers
209 210
210 211
211 212
212 213 #-----------------------------------------------------------------------------
213 214 # Aliases and Flags
214 215 #-----------------------------------------------------------------------------
215 216
216 217 flags = dict(kernel_flags)
217 218 flags['no-browser']=(
218 219 {'NotebookApp' : {'open_browser' : False}},
219 220 "Don't open the notebook in a browser after startup."
220 221 )
221 222 flags['no-mathjax']=(
222 223 {'NotebookApp' : {'enable_mathjax' : False}},
223 224 """Disable MathJax
224 225
225 226 MathJax is the javascript library IPython uses to render math/LaTeX. It is
226 227 very large, so you may want to disable it if you have a slow internet
227 228 connection, or for offline use of the notebook.
228 229
229 230 When disabled, equations etc. will appear as their untransformed TeX source.
230 231 """
231 232 )
232 233
233 234 # Add notebook manager flags
234 235 flags.update(boolean_flag('script', 'FileNotebookManager.save_script',
235 236 'Auto-save a .py script everytime the .ipynb notebook is saved',
236 237 'Do not auto-save .py scripts for every notebook'))
237 238
238 239 # the flags that are specific to the frontend
239 240 # these must be scrubbed before being passed to the kernel,
240 241 # or it will raise an error on unrecognized flags
241 242 notebook_flags = ['no-browser', 'no-mathjax', 'script', 'no-script']
242 243
243 244 aliases = dict(kernel_aliases)
244 245
245 246 aliases.update({
246 247 'ip': 'NotebookApp.ip',
247 248 'port': 'NotebookApp.port',
248 249 'port-retries': 'NotebookApp.port_retries',
249 250 'transport': 'KernelManager.transport',
250 251 'keyfile': 'NotebookApp.keyfile',
251 252 'certfile': 'NotebookApp.certfile',
252 253 'notebook-dir': 'NotebookManager.notebook_dir',
253 254 'browser': 'NotebookApp.browser',
254 255 })
255 256
256 257 # remove ipkernel flags that are singletons, and don't make sense in
257 258 # multi-kernel evironment:
258 259 aliases.pop('f', None)
259 260
260 261 notebook_aliases = [u'port', u'port-retries', u'ip', u'keyfile', u'certfile',
261 262 u'notebook-dir', u'profile', u'profile-dir']
262 263
263 264 #-----------------------------------------------------------------------------
264 265 # NotebookApp
265 266 #-----------------------------------------------------------------------------
266 267
267 268 class NotebookApp(BaseIPythonApplication):
268 269
269 270 name = 'ipython-notebook'
270 271
271 272 description = """
272 273 The IPython HTML Notebook.
273 274
274 275 This launches a Tornado based HTML Notebook Server that serves up an
275 276 HTML5/Javascript Notebook client.
276 277 """
277 278 examples = _examples
278 279
279 280 classes = IPythonConsoleApp.classes + [MappingKernelManager, NotebookManager,
280 281 FileNotebookManager]
281 282 flags = Dict(flags)
282 283 aliases = Dict(aliases)
283 284
284 285 kernel_argv = List(Unicode)
285 286
286 287 def _log_level_default(self):
287 288 return logging.INFO
288 289
289 290 def _log_format_default(self):
290 291 """override default log format to include time"""
291 292 return u"%(asctime)s.%(msecs).03d [%(name)s]%(highlevel)s %(message)s"
292 293
293 294 # create requested profiles by default, if they don't exist:
294 295 auto_create = Bool(True)
295 296
296 297 # file to be opened in the notebook server
297 298 file_to_run = Unicode('')
298 299
299 300 # Network related information.
300 301
301 302 ip = Unicode(config=True,
302 303 help="The IP address the notebook server will listen on."
303 304 )
304 305 def _ip_default(self):
305 306 return localhost()
306 307
307 308 def _ip_changed(self, name, old, new):
308 309 if new == u'*': self.ip = u''
309 310
310 311 port = Integer(8888, config=True,
311 312 help="The port the notebook server will listen on."
312 313 )
313 314 port_retries = Integer(50, config=True,
314 315 help="The number of additional ports to try if the specified port is not available."
315 316 )
316 317
317 318 certfile = Unicode(u'', config=True,
318 319 help="""The full path to an SSL/TLS certificate file."""
319 320 )
320 321
321 322 keyfile = Unicode(u'', config=True,
322 323 help="""The full path to a private key file for usage with SSL/TLS."""
323 324 )
324 325
325 326 cookie_secret = Bytes(b'', config=True,
326 327 help="""The random bytes used to secure cookies.
327 328 By default this is a new random number every time you start the Notebook.
328 329 Set it to a value in a config file to enable logins to persist across server sessions.
329 330
330 331 Note: Cookie secrets should be kept private, do not share config files with
331 332 cookie_secret stored in plaintext (you can read the value from a file).
332 333 """
333 334 )
334 335 def _cookie_secret_default(self):
335 336 return os.urandom(1024)
336 337
337 338 password = Unicode(u'', config=True,
338 339 help="""Hashed password to use for web authentication.
339 340
340 341 To generate, type in a python/IPython shell:
341 342
342 343 from IPython.lib import passwd; passwd()
343 344
344 345 The string should be of the form type:salt:hashed-password.
345 346 """
346 347 )
347 348
348 349 open_browser = Bool(True, config=True,
349 350 help="""Whether to open in a browser after starting.
350 351 The specific browser used is platform dependent and
351 352 determined by the python standard library `webbrowser`
352 353 module, unless it is overridden using the --browser
353 354 (NotebookApp.browser) configuration option.
354 355 """)
355 356
356 357 browser = Unicode(u'', config=True,
357 358 help="""Specify what command to use to invoke a web
358 359 browser when opening the notebook. If not specified, the
359 360 default browser will be determined by the `webbrowser`
360 361 standard library module, which allows setting of the
361 362 BROWSER environment variable to override it.
362 363 """)
363 364
364 365 use_less = Bool(False, config=True,
365 366 help="""Wether to use Browser Side less-css parsing
366 367 instead of compiled css version in templates that allows
367 368 it. This is mainly convenient when working on the less
368 369 file to avoid a build step, or if user want to overwrite
369 370 some of the less variables without having to recompile
370 371 everything.
371 372
372 373 You will need to install the less.js component in the static directory
373 374 either in the source tree or in your profile folder.
374 375 """)
375 376
376 377 webapp_settings = Dict(config=True,
377 378 help="Supply overrides for the tornado.web.Application that the "
378 379 "IPython notebook uses.")
379 380
380 381 enable_mathjax = Bool(True, config=True,
381 382 help="""Whether to enable MathJax for typesetting math/TeX
382 383
383 384 MathJax is the javascript library IPython uses to render math/LaTeX. It is
384 385 very large, so you may want to disable it if you have a slow internet
385 386 connection, or for offline use of the notebook.
386 387
387 388 When disabled, equations etc. will appear as their untransformed TeX source.
388 389 """
389 390 )
390 391 def _enable_mathjax_changed(self, name, old, new):
391 392 """set mathjax url to empty if mathjax is disabled"""
392 393 if not new:
393 394 self.mathjax_url = u''
394 395
395 396 base_project_url = Unicode('/', config=True,
396 397 help='''The base URL for the notebook server.
397 398
398 399 Leading and trailing slashes can be omitted,
399 400 and will automatically be added.
400 401 ''')
401 402 def _base_project_url_changed(self, name, old, new):
402 403 if not new.startswith('/'):
403 404 self.base_project_url = '/'+new
404 405 elif not new.endswith('/'):
405 406 self.base_project_url = new+'/'
406 407
407 408 base_kernel_url = Unicode('/', config=True,
408 409 help='''The base URL for the kernel server
409 410
410 411 Leading and trailing slashes can be omitted,
411 412 and will automatically be added.
412 413 ''')
413 414 def _base_kernel_url_changed(self, name, old, new):
414 415 if not new.startswith('/'):
415 416 self.base_kernel_url = '/'+new
416 417 elif not new.endswith('/'):
417 418 self.base_kernel_url = new+'/'
418 419
419 420 websocket_url = Unicode("", config=True,
420 421 help="""The base URL for the websocket server,
421 422 if it differs from the HTTP server (hint: it almost certainly doesn't).
422 423
423 424 Should be in the form of an HTTP origin: ws[s]://hostname[:port]
424 425 """
425 426 )
426 427
427 428 extra_static_paths = List(Unicode, config=True,
428 429 help="""Extra paths to search for serving static files.
429 430
430 431 This allows adding javascript/css to be available from the notebook server machine,
431 432 or overriding individual files in the IPython"""
432 433 )
433 434 def _extra_static_paths_default(self):
434 435 return [os.path.join(self.profile_dir.location, 'static')]
435 436
436 437 @property
437 438 def static_file_path(self):
438 439 """return extra paths + the default location"""
439 440 return self.extra_static_paths + [DEFAULT_STATIC_FILES_PATH]
440 441
441 442 nbextensions_path = List(Unicode, config=True,
442 443 help="""paths for Javascript extensions. By default, this is just IPYTHONDIR/nbextensions"""
443 444 )
444 445 def _nbextensions_path_default(self):
445 446 return [os.path.join(get_ipython_dir(), 'nbextensions')]
446 447
447 448 mathjax_url = Unicode("", config=True,
448 449 help="""The url for MathJax.js."""
449 450 )
450 451 def _mathjax_url_default(self):
451 452 if not self.enable_mathjax:
452 453 return u''
453 454 static_url_prefix = self.webapp_settings.get("static_url_prefix",
454 455 url_path_join(self.base_project_url, "static")
455 456 )
456 457
457 458 # try local mathjax, either in nbextensions/mathjax or static/mathjax
458 459 for (url_prefix, search_path) in [
459 460 (url_path_join(self.base_project_url, "nbextensions"), self.nbextensions_path),
460 461 (static_url_prefix, self.static_file_path),
461 462 ]:
462 463 self.log.debug("searching for local mathjax in %s", search_path)
463 464 try:
464 465 mathjax = filefind(os.path.join('mathjax', 'MathJax.js'), search_path)
465 466 except IOError:
466 467 continue
467 468 else:
468 469 url = url_path_join(url_prefix, u"mathjax/MathJax.js")
469 470 self.log.info("Serving local MathJax from %s at %s", mathjax, url)
470 471 return url
471 472
472 473 # no local mathjax, serve from CDN
473 474 if self.certfile:
474 475 # HTTPS: load from Rackspace CDN, because SSL certificate requires it
475 476 host = u"https://c328740.ssl.cf1.rackcdn.com"
476 477 else:
477 478 host = u"http://cdn.mathjax.org"
478 479
479 480 url = host + u"/mathjax/latest/MathJax.js"
480 481 self.log.info("Using MathJax from CDN: %s", url)
481 482 return url
482 483
483 484 def _mathjax_url_changed(self, name, old, new):
484 485 if new and not self.enable_mathjax:
485 486 # enable_mathjax=False overrides mathjax_url
486 487 self.mathjax_url = u''
487 488 else:
488 489 self.log.info("Using MathJax: %s", new)
489 490
490 491 notebook_manager_class = DottedObjectName('IPython.html.services.notebooks.filenbmanager.FileNotebookManager',
491 492 config=True,
492 493 help='The notebook manager class to use.')
493 494
494 495 trust_xheaders = Bool(False, config=True,
495 496 help=("Whether to trust or not X-Scheme/X-Forwarded-Proto and X-Real-Ip/X-Forwarded-For headers"
496 497 "sent by the upstream reverse proxy. Neccesary if the proxy handles SSL")
497 498 )
498 499
499 500 def parse_command_line(self, argv=None):
500 501 super(NotebookApp, self).parse_command_line(argv)
501 502
502 503 if self.extra_args:
503 504 arg0 = self.extra_args[0]
504 505 f = os.path.abspath(arg0)
505 506 self.argv.remove(arg0)
506 507 if not os.path.exists(f):
507 508 self.log.critical("No such file or directory: %s", f)
508 509 self.exit(1)
509 510 if os.path.isdir(f):
510 511 self.config.FileNotebookManager.notebook_dir = f
511 512 elif os.path.isfile(f):
512 513 self.file_to_run = f
513 514
514 515 def init_kernel_argv(self):
515 516 """construct the kernel arguments"""
516 517 # Scrub frontend-specific flags
517 518 self.kernel_argv = swallow_argv(self.argv, notebook_aliases, notebook_flags)
518 519 # Kernel should inherit default config file from frontend
519 520 self.kernel_argv.append("--IPKernelApp.parent_appname='%s'" % self.name)
520 521 # Kernel should get *absolute* path to profile directory
521 522 self.kernel_argv.extend(["--profile-dir", self.profile_dir.location])
522 523
523 524 def init_configurables(self):
524 525 # force Session default to be secure
525 526 default_secure(self.config)
526 527 self.kernel_manager = MappingKernelManager(
527 528 parent=self, log=self.log, kernel_argv=self.kernel_argv,
528 529 connection_dir = self.profile_dir.security_dir,
529 530 )
530 531 kls = import_item(self.notebook_manager_class)
531 532 self.notebook_manager = kls(parent=self, log=self.log)
532 533 self.session_manager = SessionManager(parent=self, log=self.log)
533 534 self.cluster_manager = ClusterManager(parent=self, log=self.log)
534 535 self.cluster_manager.update_profiles()
535 536
536 537 def init_logging(self):
537 538 # This prevents double log messages because tornado use a root logger that
538 539 # self.log is a child of. The logging module dipatches log messages to a log
539 540 # and all of its ancenstors until propagate is set to False.
540 541 self.log.propagate = False
541 542
542 543 # hook up tornado 3's loggers to our app handlers
543 544 for name in ('access', 'application', 'general'):
544 545 logger = logging.getLogger('tornado.%s' % name)
545 546 logger.parent = self.log
546 547 logger.setLevel(self.log.level)
547 548
548 549 def init_webapp(self):
549 550 """initialize tornado webapp and httpserver"""
550 551 self.web_app = NotebookWebApplication(
551 552 self, self.kernel_manager, self.notebook_manager,
552 553 self.cluster_manager, self.session_manager,
553 554 self.log, self.base_project_url, self.webapp_settings
554 555 )
555 556 if self.certfile:
556 557 ssl_options = dict(certfile=self.certfile)
557 558 if self.keyfile:
558 559 ssl_options['keyfile'] = self.keyfile
559 560 else:
560 561 ssl_options = None
561 562 self.web_app.password = self.password
562 563 self.http_server = httpserver.HTTPServer(self.web_app, ssl_options=ssl_options,
563 564 xheaders=self.trust_xheaders)
564 565 if not self.ip:
565 566 warning = "WARNING: The notebook server is listening on all IP addresses"
566 567 if ssl_options is None:
567 568 self.log.critical(warning + " and not using encryption. This "
568 569 "is not recommended.")
569 570 if not self.password:
570 571 self.log.critical(warning + " and not using authentication. "
571 572 "This is highly insecure and not recommended.")
572 573 success = None
573 574 for port in random_ports(self.port, self.port_retries+1):
574 575 try:
575 576 self.http_server.listen(port, self.ip)
576 577 except socket.error as e:
577 578 if e.errno == errno.EADDRINUSE:
578 579 self.log.info('The port %i is already in use, trying another random port.' % port)
579 580 continue
580 581 elif e.errno in (errno.EACCES, getattr(errno, 'WSAEACCES', errno.EACCES)):
581 582 self.log.warn("Permission to listen on port %i denied" % port)
582 583 continue
583 584 else:
584 585 raise
585 586 else:
586 587 self.port = port
587 588 success = True
588 589 break
589 590 if not success:
590 591 self.log.critical('ERROR: the notebook server could not be started because '
591 592 'no available port could be found.')
592 593 self.exit(1)
593 594
594 595 def init_signal(self):
595 596 if not sys.platform.startswith('win'):
596 597 signal.signal(signal.SIGINT, self._handle_sigint)
597 598 signal.signal(signal.SIGTERM, self._signal_stop)
598 599 if hasattr(signal, 'SIGUSR1'):
599 600 # Windows doesn't support SIGUSR1
600 601 signal.signal(signal.SIGUSR1, self._signal_info)
601 602 if hasattr(signal, 'SIGINFO'):
602 603 # only on BSD-based systems
603 604 signal.signal(signal.SIGINFO, self._signal_info)
604 605
605 606 def _handle_sigint(self, sig, frame):
606 607 """SIGINT handler spawns confirmation dialog"""
607 608 # register more forceful signal handler for ^C^C case
608 609 signal.signal(signal.SIGINT, self._signal_stop)
609 610 # request confirmation dialog in bg thread, to avoid
610 611 # blocking the App
611 612 thread = threading.Thread(target=self._confirm_exit)
612 613 thread.daemon = True
613 614 thread.start()
614 615
615 616 def _restore_sigint_handler(self):
616 617 """callback for restoring original SIGINT handler"""
617 618 signal.signal(signal.SIGINT, self._handle_sigint)
618 619
619 620 def _confirm_exit(self):
620 621 """confirm shutdown on ^C
621 622
622 623 A second ^C, or answering 'y' within 5s will cause shutdown,
623 624 otherwise original SIGINT handler will be restored.
624 625
625 626 This doesn't work on Windows.
626 627 """
627 628 # FIXME: remove this delay when pyzmq dependency is >= 2.1.11
628 629 time.sleep(0.1)
629 630 info = self.log.info
630 631 info('interrupted')
631 print self.notebook_info()
632 print(self.notebook_info())
632 633 sys.stdout.write("Shutdown this notebook server (y/[n])? ")
633 634 sys.stdout.flush()
634 635 r,w,x = select.select([sys.stdin], [], [], 5)
635 636 if r:
636 637 line = sys.stdin.readline()
637 638 if line.lower().startswith('y'):
638 639 self.log.critical("Shutdown confirmed")
639 640 ioloop.IOLoop.instance().stop()
640 641 return
641 642 else:
642 print "No answer for 5s:",
643 print "resuming operation..."
643 print("No answer for 5s:", end=' ')
644 print("resuming operation...")
644 645 # no answer, or answer is no:
645 646 # set it back to original SIGINT handler
646 647 # use IOLoop.add_callback because signal.signal must be called
647 648 # from main thread
648 649 ioloop.IOLoop.instance().add_callback(self._restore_sigint_handler)
649 650
650 651 def _signal_stop(self, sig, frame):
651 652 self.log.critical("received signal %s, stopping", sig)
652 653 ioloop.IOLoop.instance().stop()
653 654
654 655 def _signal_info(self, sig, frame):
655 print self.notebook_info()
656 print(self.notebook_info())
656 657
657 658 def init_components(self):
658 659 """Check the components submodule, and warn if it's unclean"""
659 660 status = submodule.check_submodule_status()
660 661 if status == 'missing':
661 662 self.log.warn("components submodule missing, running `git submodule update`")
662 663 submodule.update_submodules(submodule.ipython_parent())
663 664 elif status == 'unclean':
664 665 self.log.warn("components submodule unclean, you may see 404s on static/components")
665 666 self.log.warn("run `setup.py submodule` or `git submodule update` to update")
666 667
667 668
668 669 @catch_config_error
669 670 def initialize(self, argv=None):
670 671 super(NotebookApp, self).initialize(argv)
671 672 self.init_logging()
672 673 self.init_kernel_argv()
673 674 self.init_configurables()
674 675 self.init_components()
675 676 self.init_webapp()
676 677 self.init_signal()
677 678
678 679 def cleanup_kernels(self):
679 680 """Shutdown all kernels.
680 681
681 682 The kernels will shutdown themselves when this process no longer exists,
682 683 but explicit shutdown allows the KernelManagers to cleanup the connection files.
683 684 """
684 685 self.log.info('Shutting down kernels')
685 686 self.kernel_manager.shutdown_all()
686 687
687 688 def notebook_info(self):
688 689 "Return the current working directory and the server url information"
689 690 info = self.notebook_manager.info_string() + "\n"
690 691 info += "%d active kernels \n" % len(self.kernel_manager._kernels)
691 692 return info + "The IPython Notebook is running at: %s" % self._url
692 693
693 694 def start(self):
694 695 """ Start the IPython Notebook server app, after initialization
695 696
696 697 This method takes no arguments so all configuration and initialization
697 698 must be done prior to calling this method."""
698 699 ip = self.ip if self.ip else '[all ip addresses on your system]'
699 700 proto = 'https' if self.certfile else 'http'
700 701 info = self.log.info
701 702 self._url = "%s://%s:%i%s" % (proto, ip, self.port,
702 703 self.base_project_url)
703 704 for line in self.notebook_info().split("\n"):
704 705 info(line)
705 706 info("Use Control-C to stop this server and shut down all kernels (twice to skip confirmation).")
706 707
707 708 if self.open_browser or self.file_to_run:
708 709 ip = self.ip or localhost()
709 710 try:
710 711 browser = webbrowser.get(self.browser or None)
711 712 except webbrowser.Error as e:
712 713 self.log.warn('No web browser found: %s.' % e)
713 714 browser = None
714 715
715 716 nbdir = os.path.abspath(self.notebook_manager.notebook_dir)
716 717 f = self.file_to_run
717 718 if f and f.startswith(nbdir):
718 719 f = f[len(nbdir):]
719 720 else:
720 721 self.log.warn(
721 722 "Probably won't be able to open notebook %s "
722 723 "because it is not in notebook_dir %s",
723 724 f, nbdir,
724 725 )
725 726
726 727 if os.path.isfile(self.file_to_run):
727 728 url = url_path_join('notebooks', f)
728 729 else:
729 730 url = url_path_join('tree', f)
730 731 if browser:
731 732 b = lambda : browser.open("%s://%s:%i%s%s" % (proto, ip,
732 733 self.port, self.base_project_url, url), new=2)
733 734 threading.Thread(target=b).start()
734 735 try:
735 736 ioloop.IOLoop.instance().start()
736 737 except KeyboardInterrupt:
737 738 info("Interrupted...")
738 739 finally:
739 740 self.cleanup_kernels()
740 741
741 742
742 743 #-----------------------------------------------------------------------------
743 744 # Main entry point
744 745 #-----------------------------------------------------------------------------
745 746
746 747 launch_new_instance = NotebookApp.launch_instance
747 748
@@ -1,230 +1,231 b''
1 1 # coding: utf-8
2 2 """Tests for the notebook manager."""
3 from __future__ import print_function
3 4
4 5 import os
5 6
6 7 from tornado.web import HTTPError
7 8 from unittest import TestCase
8 9 from tempfile import NamedTemporaryFile
9 10
10 11 from IPython.utils.tempdir import TemporaryDirectory
11 12 from IPython.utils.traitlets import TraitError
12 13 from IPython.html.utils import url_path_join
13 14
14 15 from ..filenbmanager import FileNotebookManager
15 16 from ..nbmanager import NotebookManager
16 17
17 18 class TestFileNotebookManager(TestCase):
18 19
19 20 def test_nb_dir(self):
20 21 with TemporaryDirectory() as td:
21 22 fm = FileNotebookManager(notebook_dir=td)
22 23 self.assertEqual(fm.notebook_dir, td)
23 24
24 25 def test_create_nb_dir(self):
25 26 with TemporaryDirectory() as td:
26 27 nbdir = os.path.join(td, 'notebooks')
27 28 fm = FileNotebookManager(notebook_dir=nbdir)
28 29 self.assertEqual(fm.notebook_dir, nbdir)
29 30
30 31 def test_missing_nb_dir(self):
31 32 with TemporaryDirectory() as td:
32 33 nbdir = os.path.join(td, 'notebook', 'dir', 'is', 'missing')
33 34 self.assertRaises(TraitError, FileNotebookManager, notebook_dir=nbdir)
34 35
35 36 def test_invalid_nb_dir(self):
36 37 with NamedTemporaryFile() as tf:
37 38 self.assertRaises(TraitError, FileNotebookManager, notebook_dir=tf.name)
38 39
39 40 def test_get_os_path(self):
40 41 # full filesystem path should be returned with correct operating system
41 42 # separators.
42 43 with TemporaryDirectory() as td:
43 44 nbdir = os.path.join(td, 'notebooks')
44 45 fm = FileNotebookManager(notebook_dir=nbdir)
45 46 path = fm.get_os_path('test.ipynb', '/path/to/notebook/')
46 47 rel_path_list = '/path/to/notebook/test.ipynb'.split('/')
47 48 fs_path = os.path.join(fm.notebook_dir, *rel_path_list)
48 49 self.assertEqual(path, fs_path)
49 50
50 51 fm = FileNotebookManager(notebook_dir=nbdir)
51 52 path = fm.get_os_path('test.ipynb')
52 53 fs_path = os.path.join(fm.notebook_dir, 'test.ipynb')
53 54 self.assertEqual(path, fs_path)
54 55
55 56 fm = FileNotebookManager(notebook_dir=nbdir)
56 57 path = fm.get_os_path('test.ipynb', '////')
57 58 fs_path = os.path.join(fm.notebook_dir, 'test.ipynb')
58 59 self.assertEqual(path, fs_path)
59 60
60 61 class TestNotebookManager(TestCase):
61 62
62 63 def make_dir(self, abs_path, rel_path):
63 64 """make subdirectory, rel_path is the relative path
64 65 to that directory from the location where the server started"""
65 66 os_path = os.path.join(abs_path, rel_path)
66 67 try:
67 68 os.makedirs(os_path)
68 69 except OSError:
69 print "Directory already exists."
70 print("Directory already exists.")
70 71
71 72 def test_create_notebook_model(self):
72 73 with TemporaryDirectory() as td:
73 74 # Test in root directory
74 75 nm = FileNotebookManager(notebook_dir=td)
75 76 model = nm.create_notebook_model()
76 77 assert isinstance(model, dict)
77 78 self.assertIn('name', model)
78 79 self.assertIn('path', model)
79 80 self.assertEqual(model['name'], 'Untitled0.ipynb')
80 81 self.assertEqual(model['path'], '')
81 82
82 83 # Test in sub-directory
83 84 sub_dir = '/foo/'
84 85 self.make_dir(nm.notebook_dir, 'foo')
85 86 model = nm.create_notebook_model(None, sub_dir)
86 87 assert isinstance(model, dict)
87 88 self.assertIn('name', model)
88 89 self.assertIn('path', model)
89 90 self.assertEqual(model['name'], 'Untitled0.ipynb')
90 91 self.assertEqual(model['path'], sub_dir.strip('/'))
91 92
92 93 def test_get_notebook_model(self):
93 94 with TemporaryDirectory() as td:
94 95 # Test in root directory
95 96 # Create a notebook
96 97 nm = FileNotebookManager(notebook_dir=td)
97 98 model = nm.create_notebook_model()
98 99 name = model['name']
99 100 path = model['path']
100 101
101 102 # Check that we 'get' on the notebook we just created
102 103 model2 = nm.get_notebook_model(name, path)
103 104 assert isinstance(model2, dict)
104 105 self.assertIn('name', model2)
105 106 self.assertIn('path', model2)
106 107 self.assertEqual(model['name'], name)
107 108 self.assertEqual(model['path'], path)
108 109
109 110 # Test in sub-directory
110 111 sub_dir = '/foo/'
111 112 self.make_dir(nm.notebook_dir, 'foo')
112 113 model = nm.create_notebook_model(None, sub_dir)
113 114 model2 = nm.get_notebook_model(name, sub_dir)
114 115 assert isinstance(model2, dict)
115 116 self.assertIn('name', model2)
116 117 self.assertIn('path', model2)
117 118 self.assertIn('content', model2)
118 119 self.assertEqual(model2['name'], 'Untitled0.ipynb')
119 120 self.assertEqual(model2['path'], sub_dir.strip('/'))
120 121
121 122 def test_update_notebook_model(self):
122 123 with TemporaryDirectory() as td:
123 124 # Test in root directory
124 125 # Create a notebook
125 126 nm = FileNotebookManager(notebook_dir=td)
126 127 model = nm.create_notebook_model()
127 128 name = model['name']
128 129 path = model['path']
129 130
130 131 # Change the name in the model for rename
131 132 model['name'] = 'test.ipynb'
132 133 model = nm.update_notebook_model(model, name, path)
133 134 assert isinstance(model, dict)
134 135 self.assertIn('name', model)
135 136 self.assertIn('path', model)
136 137 self.assertEqual(model['name'], 'test.ipynb')
137 138
138 139 # Make sure the old name is gone
139 140 self.assertRaises(HTTPError, nm.get_notebook_model, name, path)
140 141
141 142 # Test in sub-directory
142 143 # Create a directory and notebook in that directory
143 144 sub_dir = '/foo/'
144 145 self.make_dir(nm.notebook_dir, 'foo')
145 146 model = nm.create_notebook_model(None, sub_dir)
146 147 name = model['name']
147 148 path = model['path']
148 149
149 150 # Change the name in the model for rename
150 151 model['name'] = 'test_in_sub.ipynb'
151 152 model = nm.update_notebook_model(model, name, path)
152 153 assert isinstance(model, dict)
153 154 self.assertIn('name', model)
154 155 self.assertIn('path', model)
155 156 self.assertEqual(model['name'], 'test_in_sub.ipynb')
156 157 self.assertEqual(model['path'], sub_dir.strip('/'))
157 158
158 159 # Make sure the old name is gone
159 160 self.assertRaises(HTTPError, nm.get_notebook_model, name, path)
160 161
161 162 def test_save_notebook_model(self):
162 163 with TemporaryDirectory() as td:
163 164 # Test in the root directory
164 165 # Create a notebook
165 166 nm = FileNotebookManager(notebook_dir=td)
166 167 model = nm.create_notebook_model()
167 168 name = model['name']
168 169 path = model['path']
169 170
170 171 # Get the model with 'content'
171 172 full_model = nm.get_notebook_model(name, path)
172 173
173 174 # Save the notebook
174 175 model = nm.save_notebook_model(full_model, name, path)
175 176 assert isinstance(model, dict)
176 177 self.assertIn('name', model)
177 178 self.assertIn('path', model)
178 179 self.assertEqual(model['name'], name)
179 180 self.assertEqual(model['path'], path)
180 181
181 182 # Test in sub-directory
182 183 # Create a directory and notebook in that directory
183 184 sub_dir = '/foo/'
184 185 self.make_dir(nm.notebook_dir, 'foo')
185 186 model = nm.create_notebook_model(None, sub_dir)
186 187 name = model['name']
187 188 path = model['path']
188 189 model = nm.get_notebook_model(name, path)
189 190
190 191 # Change the name in the model for rename
191 192 model = nm.save_notebook_model(model, name, path)
192 193 assert isinstance(model, dict)
193 194 self.assertIn('name', model)
194 195 self.assertIn('path', model)
195 196 self.assertEqual(model['name'], 'Untitled0.ipynb')
196 197 self.assertEqual(model['path'], sub_dir.strip('/'))
197 198
198 199 def test_delete_notebook_model(self):
199 200 with TemporaryDirectory() as td:
200 201 # Test in the root directory
201 202 # Create a notebook
202 203 nm = FileNotebookManager(notebook_dir=td)
203 204 model = nm.create_notebook_model()
204 205 name = model['name']
205 206 path = model['path']
206 207
207 208 # Delete the notebook
208 209 nm.delete_notebook_model(name, path)
209 210
210 211 # Check that a 'get' on the deleted notebook raises and error
211 212 self.assertRaises(HTTPError, nm.get_notebook_model, name, path)
212 213
213 214 def test_copy_notebook(self):
214 215 with TemporaryDirectory() as td:
215 216 # Test in the root directory
216 217 # Create a notebook
217 218 nm = FileNotebookManager(notebook_dir=td)
218 219 path = u'å b'
219 220 name = u'nb √.ipynb'
220 221 os.mkdir(os.path.join(td, path))
221 222 orig = nm.create_notebook_model({'name' : name}, path=path)
222 223
223 224 # copy with unspecified name
224 225 copy = nm.copy_notebook(name, path=path)
225 226 self.assertEqual(copy['name'], orig['name'].replace('.ipynb', '-Copy0.ipynb'))
226 227
227 228 # copy with specified name
228 229 copy2 = nm.copy_notebook(name, u'copy 2.ipynb', path=path)
229 230 self.assertEqual(copy2['name'], u'copy 2.ipynb')
230 231
@@ -1,484 +1,485 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Manage background (threaded) jobs conveniently from an interactive shell.
3 3
4 4 This module provides a BackgroundJobManager class. This is the main class
5 5 meant for public usage, it implements an object which can create and manage
6 6 new background jobs.
7 7
8 8 It also provides the actual job classes managed by these BackgroundJobManager
9 9 objects, see their docstrings below.
10 10
11 11
12 12 This system was inspired by discussions with B. Granger and the
13 13 BackgroundCommand class described in the book Python Scripting for
14 14 Computational Science, by H. P. Langtangen:
15 15
16 16 http://folk.uio.no/hpl/scripting
17 17
18 18 (although ultimately no code from this text was used, as IPython's system is a
19 19 separate implementation).
20 20
21 21 An example notebook is provided in our documentation illustrating interactive
22 22 use of the system.
23 23 """
24 from __future__ import print_function
24 25
25 26 #*****************************************************************************
26 27 # Copyright (C) 2005-2006 Fernando Perez <fperez@colorado.edu>
27 28 #
28 29 # Distributed under the terms of the BSD License. The full license is in
29 30 # the file COPYING, distributed as part of this software.
30 31 #*****************************************************************************
31 32
32 33 # Code begins
33 34 import sys
34 35 import threading
35 36
36 37 from IPython import get_ipython
37 38 from IPython.core.ultratb import AutoFormattedTB
38 39 from IPython.utils.warn import error
39 40
40 41
41 42 class BackgroundJobManager(object):
42 43 """Class to manage a pool of backgrounded threaded jobs.
43 44
44 45 Below, we assume that 'jobs' is a BackgroundJobManager instance.
45 46
46 47 Usage summary (see the method docstrings for details):
47 48
48 49 jobs.new(...) -> start a new job
49 50
50 51 jobs() or jobs.status() -> print status summary of all jobs
51 52
52 53 jobs[N] -> returns job number N.
53 54
54 55 foo = jobs[N].result -> assign to variable foo the result of job N
55 56
56 57 jobs[N].traceback() -> print the traceback of dead job N
57 58
58 59 jobs.remove(N) -> remove (finished) job N
59 60
60 61 jobs.flush() -> remove all finished jobs
61 62
62 63 As a convenience feature, BackgroundJobManager instances provide the
63 64 utility result and traceback methods which retrieve the corresponding
64 65 information from the jobs list:
65 66
66 67 jobs.result(N) <--> jobs[N].result
67 68 jobs.traceback(N) <--> jobs[N].traceback()
68 69
69 70 While this appears minor, it allows you to use tab completion
70 71 interactively on the job manager instance.
71 72 """
72 73
73 74 def __init__(self):
74 75 # Lists for job management, accessed via a property to ensure they're
75 76 # up to date.x
76 77 self._running = []
77 78 self._completed = []
78 79 self._dead = []
79 80 # A dict of all jobs, so users can easily access any of them
80 81 self.all = {}
81 82 # For reporting
82 83 self._comp_report = []
83 84 self._dead_report = []
84 85 # Store status codes locally for fast lookups
85 86 self._s_created = BackgroundJobBase.stat_created_c
86 87 self._s_running = BackgroundJobBase.stat_running_c
87 88 self._s_completed = BackgroundJobBase.stat_completed_c
88 89 self._s_dead = BackgroundJobBase.stat_dead_c
89 90
90 91 @property
91 92 def running(self):
92 93 self._update_status()
93 94 return self._running
94 95
95 96 @property
96 97 def dead(self):
97 98 self._update_status()
98 99 return self._dead
99 100
100 101 @property
101 102 def completed(self):
102 103 self._update_status()
103 104 return self._completed
104 105
105 106 def new(self, func_or_exp, *args, **kwargs):
106 107 """Add a new background job and start it in a separate thread.
107 108
108 109 There are two types of jobs which can be created:
109 110
110 111 1. Jobs based on expressions which can be passed to an eval() call.
111 112 The expression must be given as a string. For example:
112 113
113 114 job_manager.new('myfunc(x,y,z=1)'[,glob[,loc]])
114 115
115 116 The given expression is passed to eval(), along with the optional
116 117 global/local dicts provided. If no dicts are given, they are
117 118 extracted automatically from the caller's frame.
118 119
119 120 A Python statement is NOT a valid eval() expression. Basically, you
120 121 can only use as an eval() argument something which can go on the right
121 122 of an '=' sign and be assigned to a variable.
122 123
123 124 For example,"print 'hello'" is not valid, but '2+3' is.
124 125
125 126 2. Jobs given a function object, optionally passing additional
126 127 positional arguments:
127 128
128 129 job_manager.new(myfunc, x, y)
129 130
130 131 The function is called with the given arguments.
131 132
132 133 If you need to pass keyword arguments to your function, you must
133 134 supply them as a dict named kw:
134 135
135 136 job_manager.new(myfunc, x, y, kw=dict(z=1))
136 137
137 138 The reason for this assymmetry is that the new() method needs to
138 139 maintain access to its own keywords, and this prevents name collisions
139 140 between arguments to new() and arguments to your own functions.
140 141
141 142 In both cases, the result is stored in the job.result field of the
142 143 background job object.
143 144
144 145 You can set `daemon` attribute of the thread by giving the keyword
145 146 argument `daemon`.
146 147
147 148 Notes and caveats:
148 149
149 150 1. All threads running share the same standard output. Thus, if your
150 151 background jobs generate output, it will come out on top of whatever
151 152 you are currently writing. For this reason, background jobs are best
152 153 used with silent functions which simply return their output.
153 154
154 155 2. Threads also all work within the same global namespace, and this
155 156 system does not lock interactive variables. So if you send job to the
156 157 background which operates on a mutable object for a long time, and
157 158 start modifying that same mutable object interactively (or in another
158 159 backgrounded job), all sorts of bizarre behaviour will occur.
159 160
160 161 3. If a background job is spending a lot of time inside a C extension
161 162 module which does not release the Python Global Interpreter Lock
162 163 (GIL), this will block the IPython prompt. This is simply because the
163 164 Python interpreter can only switch between threads at Python
164 165 bytecodes. While the execution is inside C code, the interpreter must
165 166 simply wait unless the extension module releases the GIL.
166 167
167 168 4. There is no way, due to limitations in the Python threads library,
168 169 to kill a thread once it has started."""
169 170
170 171 if callable(func_or_exp):
171 172 kw = kwargs.get('kw',{})
172 173 job = BackgroundJobFunc(func_or_exp,*args,**kw)
173 174 elif isinstance(func_or_exp, basestring):
174 175 if not args:
175 176 frame = sys._getframe(1)
176 177 glob, loc = frame.f_globals, frame.f_locals
177 178 elif len(args)==1:
178 179 glob = loc = args[0]
179 180 elif len(args)==2:
180 181 glob,loc = args
181 182 else:
182 183 raise ValueError(
183 184 'Expression jobs take at most 2 args (globals,locals)')
184 185 job = BackgroundJobExpr(func_or_exp, glob, loc)
185 186 else:
186 187 raise TypeError('invalid args for new job')
187 188
188 189 if kwargs.get('daemon', False):
189 190 job.daemon = True
190 191 job.num = len(self.all)+1 if self.all else 0
191 192 self.running.append(job)
192 193 self.all[job.num] = job
193 print 'Starting job # %s in a separate thread.' % job.num
194 print('Starting job # %s in a separate thread.' % job.num)
194 195 job.start()
195 196 return job
196 197
197 198 def __getitem__(self, job_key):
198 199 num = job_key if isinstance(job_key, int) else job_key.num
199 200 return self.all[num]
200 201
201 202 def __call__(self):
202 203 """An alias to self.status(),
203 204
204 205 This allows you to simply call a job manager instance much like the
205 206 Unix `jobs` shell command."""
206 207
207 208 return self.status()
208 209
209 210 def _update_status(self):
210 211 """Update the status of the job lists.
211 212
212 213 This method moves finished jobs to one of two lists:
213 214 - self.completed: jobs which completed successfully
214 215 - self.dead: jobs which finished but died.
215 216
216 217 It also copies those jobs to corresponding _report lists. These lists
217 218 are used to report jobs completed/dead since the last update, and are
218 219 then cleared by the reporting function after each call."""
219 220
220 221 # Status codes
221 222 srun, scomp, sdead = self._s_running, self._s_completed, self._s_dead
222 223 # State lists, use the actual lists b/c the public names are properties
223 224 # that call this very function on access
224 225 running, completed, dead = self._running, self._completed, self._dead
225 226
226 227 # Now, update all state lists
227 228 for num, job in enumerate(running):
228 229 stat = job.stat_code
229 230 if stat == srun:
230 231 continue
231 232 elif stat == scomp:
232 233 completed.append(job)
233 234 self._comp_report.append(job)
234 235 running[num] = False
235 236 elif stat == sdead:
236 237 dead.append(job)
237 238 self._dead_report.append(job)
238 239 running[num] = False
239 240 # Remove dead/completed jobs from running list
240 241 running[:] = filter(None, running)
241 242
242 243 def _group_report(self,group,name):
243 244 """Report summary for a given job group.
244 245
245 246 Return True if the group had any elements."""
246 247
247 248 if group:
248 print '%s jobs:' % name
249 print('%s jobs:' % name)
249 250 for job in group:
250 print '%s : %s' % (job.num,job)
251 print
251 print('%s : %s' % (job.num,job))
252 print()
252 253 return True
253 254
254 255 def _group_flush(self,group,name):
255 256 """Flush a given job group
256 257
257 258 Return True if the group had any elements."""
258 259
259 260 njobs = len(group)
260 261 if njobs:
261 262 plural = {1:''}.setdefault(njobs,'s')
262 print 'Flushing %s %s job%s.' % (njobs,name,plural)
263 print('Flushing %s %s job%s.' % (njobs,name,plural))
263 264 group[:] = []
264 265 return True
265 266
266 267 def _status_new(self):
267 268 """Print the status of newly finished jobs.
268 269
269 270 Return True if any new jobs are reported.
270 271
271 272 This call resets its own state every time, so it only reports jobs
272 273 which have finished since the last time it was called."""
273 274
274 275 self._update_status()
275 276 new_comp = self._group_report(self._comp_report, 'Completed')
276 277 new_dead = self._group_report(self._dead_report,
277 278 'Dead, call jobs.traceback() for details')
278 279 self._comp_report[:] = []
279 280 self._dead_report[:] = []
280 281 return new_comp or new_dead
281 282
282 283 def status(self,verbose=0):
283 284 """Print a status of all jobs currently being managed."""
284 285
285 286 self._update_status()
286 287 self._group_report(self.running,'Running')
287 288 self._group_report(self.completed,'Completed')
288 289 self._group_report(self.dead,'Dead')
289 290 # Also flush the report queues
290 291 self._comp_report[:] = []
291 292 self._dead_report[:] = []
292 293
293 294 def remove(self,num):
294 295 """Remove a finished (completed or dead) job."""
295 296
296 297 try:
297 298 job = self.all[num]
298 299 except KeyError:
299 300 error('Job #%s not found' % num)
300 301 else:
301 302 stat_code = job.stat_code
302 303 if stat_code == self._s_running:
303 304 error('Job #%s is still running, it can not be removed.' % num)
304 305 return
305 306 elif stat_code == self._s_completed:
306 307 self.completed.remove(job)
307 308 elif stat_code == self._s_dead:
308 309 self.dead.remove(job)
309 310
310 311 def flush(self):
311 312 """Flush all finished jobs (completed and dead) from lists.
312 313
313 314 Running jobs are never flushed.
314 315
315 316 It first calls _status_new(), to update info. If any jobs have
316 317 completed since the last _status_new() call, the flush operation
317 318 aborts."""
318 319
319 320 # Remove the finished jobs from the master dict
320 321 alljobs = self.all
321 322 for job in self.completed+self.dead:
322 323 del(alljobs[job.num])
323 324
324 325 # Now flush these lists completely
325 326 fl_comp = self._group_flush(self.completed, 'Completed')
326 327 fl_dead = self._group_flush(self.dead, 'Dead')
327 328 if not (fl_comp or fl_dead):
328 print 'No jobs to flush.'
329 print('No jobs to flush.')
329 330
330 331 def result(self,num):
331 332 """result(N) -> return the result of job N."""
332 333 try:
333 334 return self.all[num].result
334 335 except KeyError:
335 336 error('Job #%s not found' % num)
336 337
337 338 def _traceback(self, job):
338 339 num = job if isinstance(job, int) else job.num
339 340 try:
340 341 self.all[num].traceback()
341 342 except KeyError:
342 343 error('Job #%s not found' % num)
343 344
344 345 def traceback(self, job=None):
345 346 if job is None:
346 347 self._update_status()
347 348 for deadjob in self.dead:
348 print "Traceback for: %r" % deadjob
349 print("Traceback for: %r" % deadjob)
349 350 self._traceback(deadjob)
350 print
351 print()
351 352 else:
352 353 self._traceback(job)
353 354
354 355
355 356 class BackgroundJobBase(threading.Thread):
356 357 """Base class to build BackgroundJob classes.
357 358
358 359 The derived classes must implement:
359 360
360 361 - Their own __init__, since the one here raises NotImplementedError. The
361 362 derived constructor must call self._init() at the end, to provide common
362 363 initialization.
363 364
364 365 - A strform attribute used in calls to __str__.
365 366
366 367 - A call() method, which will make the actual execution call and must
367 368 return a value to be held in the 'result' field of the job object."""
368 369
369 370 # Class constants for status, in string and as numerical codes (when
370 371 # updating jobs lists, we don't want to do string comparisons). This will
371 372 # be done at every user prompt, so it has to be as fast as possible
372 373 stat_created = 'Created'; stat_created_c = 0
373 374 stat_running = 'Running'; stat_running_c = 1
374 375 stat_completed = 'Completed'; stat_completed_c = 2
375 376 stat_dead = 'Dead (Exception), call jobs.traceback() for details'
376 377 stat_dead_c = -1
377 378
378 379 def __init__(self):
379 380 raise NotImplementedError("This class can not be instantiated directly.")
380 381
381 382 def _init(self):
382 383 """Common initialization for all BackgroundJob objects"""
383 384
384 385 for attr in ['call','strform']:
385 386 assert hasattr(self,attr), "Missing attribute <%s>" % attr
386 387
387 388 # The num tag can be set by an external job manager
388 389 self.num = None
389 390
390 391 self.status = BackgroundJobBase.stat_created
391 392 self.stat_code = BackgroundJobBase.stat_created_c
392 393 self.finished = False
393 394 self.result = '<BackgroundJob has not completed>'
394 395
395 396 # reuse the ipython traceback handler if we can get to it, otherwise
396 397 # make a new one
397 398 try:
398 399 make_tb = get_ipython().InteractiveTB.text
399 400 except:
400 401 make_tb = AutoFormattedTB(mode = 'Context',
401 402 color_scheme='NoColor',
402 403 tb_offset = 1).text
403 404 # Note that the actual API for text() requires the three args to be
404 405 # passed in, so we wrap it in a simple lambda.
405 406 self._make_tb = lambda : make_tb(None, None, None)
406 407
407 408 # Hold a formatted traceback if one is generated.
408 409 self._tb = None
409 410
410 411 threading.Thread.__init__(self)
411 412
412 413 def __str__(self):
413 414 return self.strform
414 415
415 416 def __repr__(self):
416 417 return '<BackgroundJob #%d: %s>' % (self.num, self.strform)
417 418
418 419 def traceback(self):
419 print self._tb
420 print(self._tb)
420 421
421 422 def run(self):
422 423 try:
423 424 self.status = BackgroundJobBase.stat_running
424 425 self.stat_code = BackgroundJobBase.stat_running_c
425 426 self.result = self.call()
426 427 except:
427 428 self.status = BackgroundJobBase.stat_dead
428 429 self.stat_code = BackgroundJobBase.stat_dead_c
429 430 self.finished = None
430 431 self.result = ('<BackgroundJob died, call jobs.traceback() for details>')
431 432 self._tb = self._make_tb()
432 433 else:
433 434 self.status = BackgroundJobBase.stat_completed
434 435 self.stat_code = BackgroundJobBase.stat_completed_c
435 436 self.finished = True
436 437
437 438
438 439 class BackgroundJobExpr(BackgroundJobBase):
439 440 """Evaluate an expression as a background job (uses a separate thread)."""
440 441
441 442 def __init__(self, expression, glob=None, loc=None):
442 443 """Create a new job from a string which can be fed to eval().
443 444
444 445 global/locals dicts can be provided, which will be passed to the eval
445 446 call."""
446 447
447 448 # fail immediately if the given expression can't be compiled
448 449 self.code = compile(expression,'<BackgroundJob compilation>','eval')
449 450
450 451 glob = {} if glob is None else glob
451 452 loc = {} if loc is None else loc
452 453 self.expression = self.strform = expression
453 454 self.glob = glob
454 455 self.loc = loc
455 456 self._init()
456 457
457 458 def call(self):
458 459 return eval(self.code,self.glob,self.loc)
459 460
460 461
461 462 class BackgroundJobFunc(BackgroundJobBase):
462 463 """Run a function call as a background job (uses a separate thread)."""
463 464
464 465 def __init__(self, func, *args, **kwargs):
465 466 """Create a new job from a callable object.
466 467
467 468 Any positional arguments and keyword args given to this constructor
468 469 after the initial callable are passed directly to it."""
469 470
470 471 if not callable(func):
471 472 raise TypeError(
472 473 'first argument to BackgroundJobFunc must be callable')
473 474
474 475 self.func = func
475 476 self.args = args
476 477 self.kwargs = kwargs
477 478 # The string form will only include the function passed, because
478 479 # generating string representations of the arguments is a potentially
479 480 # _very_ expensive operation (e.g. with large arrays).
480 481 self.strform = str(func)
481 482 self._init()
482 483
483 484 def call(self):
484 485 return self.func(*self.args, **self.kwargs)
@@ -1,337 +1,338 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 A module to change reload() so that it acts recursively.
4 4 To enable it type::
5 5
6 6 import __builtin__, deepreload
7 7 __builtin__.reload = deepreload.reload
8 8
9 9 You can then disable it with::
10 10
11 11 __builtin__.reload = deepreload.original_reload
12 12
13 13 Alternatively, you can add a dreload builtin alongside normal reload with::
14 14
15 15 __builtin__.dreload = deepreload.reload
16 16
17 17 This code is almost entirely based on knee.py, which is a Python
18 18 re-implementation of hierarchical module import.
19 19 """
20 from __future__ import print_function
20 21 #*****************************************************************************
21 22 # Copyright (C) 2001 Nathaniel Gray <n8gray@caltech.edu>
22 23 #
23 24 # Distributed under the terms of the BSD License. The full license is in
24 25 # the file COPYING, distributed as part of this software.
25 26 #*****************************************************************************
26 27
27 28 import __builtin__
28 29 from contextlib import contextmanager
29 30 import imp
30 31 import sys
31 32
32 33 from types import ModuleType
33 34 from warnings import warn
34 35
35 36 original_import = __builtin__.__import__
36 37
37 38 @contextmanager
38 39 def replace_import_hook(new_import):
39 40 saved_import = __builtin__.__import__
40 41 __builtin__.__import__ = new_import
41 42 try:
42 43 yield
43 44 finally:
44 45 __builtin__.__import__ = saved_import
45 46
46 47 def get_parent(globals, level):
47 48 """
48 49 parent, name = get_parent(globals, level)
49 50
50 51 Return the package that an import is being performed in. If globals comes
51 52 from the module foo.bar.bat (not itself a package), this returns the
52 53 sys.modules entry for foo.bar. If globals is from a package's __init__.py,
53 54 the package's entry in sys.modules is returned.
54 55
55 56 If globals doesn't come from a package or a module in a package, or a
56 57 corresponding entry is not found in sys.modules, None is returned.
57 58 """
58 59 orig_level = level
59 60
60 61 if not level or not isinstance(globals, dict):
61 62 return None, ''
62 63
63 64 pkgname = globals.get('__package__', None)
64 65
65 66 if pkgname is not None:
66 67 # __package__ is set, so use it
67 68 if not hasattr(pkgname, 'rindex'):
68 69 raise ValueError('__package__ set to non-string')
69 70 if len(pkgname) == 0:
70 71 if level > 0:
71 72 raise ValueError('Attempted relative import in non-package')
72 73 return None, ''
73 74 name = pkgname
74 75 else:
75 76 # __package__ not set, so figure it out and set it
76 77 if '__name__' not in globals:
77 78 return None, ''
78 79 modname = globals['__name__']
79 80
80 81 if '__path__' in globals:
81 82 # __path__ is set, so modname is already the package name
82 83 globals['__package__'] = name = modname
83 84 else:
84 85 # Normal module, so work out the package name if any
85 86 lastdot = modname.rfind('.')
86 87 if lastdot < 0 and level > 0:
87 88 raise ValueError("Attempted relative import in non-package")
88 89 if lastdot < 0:
89 90 globals['__package__'] = None
90 91 return None, ''
91 92 globals['__package__'] = name = modname[:lastdot]
92 93
93 94 dot = len(name)
94 95 for x in xrange(level, 1, -1):
95 96 try:
96 97 dot = name.rindex('.', 0, dot)
97 98 except ValueError:
98 99 raise ValueError("attempted relative import beyond top-level "
99 100 "package")
100 101 name = name[:dot]
101 102
102 103 try:
103 104 parent = sys.modules[name]
104 105 except:
105 106 if orig_level < 1:
106 107 warn("Parent module '%.200s' not found while handling absolute "
107 108 "import" % name)
108 109 parent = None
109 110 else:
110 111 raise SystemError("Parent module '%.200s' not loaded, cannot "
111 112 "perform relative import" % name)
112 113
113 114 # We expect, but can't guarantee, if parent != None, that:
114 115 # - parent.__name__ == name
115 116 # - parent.__dict__ is globals
116 117 # If this is violated... Who cares?
117 118 return parent, name
118 119
119 120 def load_next(mod, altmod, name, buf):
120 121 """
121 122 mod, name, buf = load_next(mod, altmod, name, buf)
122 123
123 124 altmod is either None or same as mod
124 125 """
125 126
126 127 if len(name) == 0:
127 128 # completely empty module name should only happen in
128 129 # 'from . import' (or '__import__("")')
129 130 return mod, None, buf
130 131
131 132 dot = name.find('.')
132 133 if dot == 0:
133 134 raise ValueError('Empty module name')
134 135
135 136 if dot < 0:
136 137 subname = name
137 138 next = None
138 139 else:
139 140 subname = name[:dot]
140 141 next = name[dot+1:]
141 142
142 143 if buf != '':
143 144 buf += '.'
144 145 buf += subname
145 146
146 147 result = import_submodule(mod, subname, buf)
147 148 if result is None and mod != altmod:
148 149 result = import_submodule(altmod, subname, subname)
149 150 if result is not None:
150 151 buf = subname
151 152
152 153 if result is None:
153 154 raise ImportError("No module named %.200s" % name)
154 155
155 156 return result, next, buf
156 157
157 158 # Need to keep track of what we've already reloaded to prevent cyclic evil
158 159 found_now = {}
159 160
160 161 def import_submodule(mod, subname, fullname):
161 162 """m = import_submodule(mod, subname, fullname)"""
162 163 # Require:
163 164 # if mod == None: subname == fullname
164 165 # else: mod.__name__ + "." + subname == fullname
165 166
166 167 global found_now
167 168 if fullname in found_now and fullname in sys.modules:
168 169 m = sys.modules[fullname]
169 170 else:
170 print 'Reloading', fullname
171 print('Reloading', fullname)
171 172 found_now[fullname] = 1
172 173 oldm = sys.modules.get(fullname, None)
173 174
174 175 if mod is None:
175 176 path = None
176 177 elif hasattr(mod, '__path__'):
177 178 path = mod.__path__
178 179 else:
179 180 return None
180 181
181 182 try:
182 183 # This appears to be necessary on Python 3, because imp.find_module()
183 184 # tries to import standard libraries (like io) itself, and we don't
184 185 # want them to be processed by our deep_import_hook.
185 186 with replace_import_hook(original_import):
186 187 fp, filename, stuff = imp.find_module(subname, path)
187 188 except ImportError:
188 189 return None
189 190
190 191 try:
191 192 m = imp.load_module(fullname, fp, filename, stuff)
192 193 except:
193 194 # load_module probably removed name from modules because of
194 195 # the error. Put back the original module object.
195 196 if oldm:
196 197 sys.modules[fullname] = oldm
197 198 raise
198 199 finally:
199 200 if fp: fp.close()
200 201
201 202 add_submodule(mod, m, fullname, subname)
202 203
203 204 return m
204 205
205 206 def add_submodule(mod, submod, fullname, subname):
206 207 """mod.{subname} = submod"""
207 208 if mod is None:
208 209 return #Nothing to do here.
209 210
210 211 if submod is None:
211 212 submod = sys.modules[fullname]
212 213
213 214 setattr(mod, subname, submod)
214 215
215 216 return
216 217
217 218 def ensure_fromlist(mod, fromlist, buf, recursive):
218 219 """Handle 'from module import a, b, c' imports."""
219 220 if not hasattr(mod, '__path__'):
220 221 return
221 222 for item in fromlist:
222 223 if not hasattr(item, 'rindex'):
223 224 raise TypeError("Item in ``from list'' not a string")
224 225 if item == '*':
225 226 if recursive:
226 227 continue # avoid endless recursion
227 228 try:
228 229 all = mod.__all__
229 230 except AttributeError:
230 231 pass
231 232 else:
232 233 ret = ensure_fromlist(mod, all, buf, 1)
233 234 if not ret:
234 235 return 0
235 236 elif not hasattr(mod, item):
236 237 import_submodule(mod, item, buf + '.' + item)
237 238
238 239 def deep_import_hook(name, globals=None, locals=None, fromlist=None, level=-1):
239 240 """Replacement for __import__()"""
240 241 parent, buf = get_parent(globals, level)
241 242
242 243 head, name, buf = load_next(parent, None if level < 0 else parent, name, buf)
243 244
244 245 tail = head
245 246 while name:
246 247 tail, name, buf = load_next(tail, tail, name, buf)
247 248
248 249 # If tail is None, both get_parent and load_next found
249 250 # an empty module name: someone called __import__("") or
250 251 # doctored faulty bytecode
251 252 if tail is None:
252 253 raise ValueError('Empty module name')
253 254
254 255 if not fromlist:
255 256 return head
256 257
257 258 ensure_fromlist(tail, fromlist, buf, 0)
258 259 return tail
259 260
260 261 modules_reloading = {}
261 262
262 263 def deep_reload_hook(m):
263 264 """Replacement for reload()."""
264 265 if not isinstance(m, ModuleType):
265 266 raise TypeError("reload() argument must be module")
266 267
267 268 name = m.__name__
268 269
269 270 if name not in sys.modules:
270 271 raise ImportError("reload(): module %.200s not in sys.modules" % name)
271 272
272 273 global modules_reloading
273 274 try:
274 275 return modules_reloading[name]
275 276 except:
276 277 modules_reloading[name] = m
277 278
278 279 dot = name.rfind('.')
279 280 if dot < 0:
280 281 subname = name
281 282 path = None
282 283 else:
283 284 try:
284 285 parent = sys.modules[name[:dot]]
285 286 except KeyError:
286 287 modules_reloading.clear()
287 288 raise ImportError("reload(): parent %.200s not in sys.modules" % name[:dot])
288 289 subname = name[dot+1:]
289 290 path = getattr(parent, "__path__", None)
290 291
291 292 try:
292 293 # This appears to be necessary on Python 3, because imp.find_module()
293 294 # tries to import standard libraries (like io) itself, and we don't
294 295 # want them to be processed by our deep_import_hook.
295 296 with replace_import_hook(original_import):
296 297 fp, filename, stuff = imp.find_module(subname, path)
297 298 finally:
298 299 modules_reloading.clear()
299 300
300 301 try:
301 302 newm = imp.load_module(name, fp, filename, stuff)
302 303 except:
303 304 # load_module probably removed name from modules because of
304 305 # the error. Put back the original module object.
305 306 sys.modules[name] = m
306 307 raise
307 308 finally:
308 309 if fp: fp.close()
309 310
310 311 modules_reloading.clear()
311 312 return newm
312 313
313 314 # Save the original hooks
314 315 try:
315 316 original_reload = __builtin__.reload
316 317 except AttributeError:
317 318 original_reload = imp.reload # Python 3
318 319
319 320 # Replacement for reload()
320 321 def reload(module, exclude=['sys', 'os.path', '__builtin__', '__main__']):
321 322 """Recursively reload all modules used in the given module. Optionally
322 323 takes a list of modules to exclude from reloading. The default exclude
323 324 list contains sys, __main__, and __builtin__, to prevent, e.g., resetting
324 325 display, exception, and io hooks.
325 326 """
326 327 global found_now
327 328 for i in exclude:
328 329 found_now[i] = 1
329 330 try:
330 331 with replace_import_hook(deep_import_hook):
331 332 return deep_reload_hook(module)
332 333 finally:
333 334 found_now = {}
334 335
335 336 # Uncomment the following to automatically activate deep reloading whenever
336 337 # this module is imported
337 338 #__builtin__.reload = reload
@@ -1,122 +1,123 b''
1 1 """ 'editor' hooks for common editors that work well with ipython
2 2
3 3 They should honor the line number argument, at least.
4 4
5 5 Contributions are *very* welcome.
6 6 """
7 from __future__ import print_function
7 8
8 9 import os
9 10 import pipes
10 11 import subprocess
11 12
12 13 from IPython import get_ipython
13 14 from IPython.core.error import TryNext
14 15
15 16
16 17 def install_editor(template, wait=False):
17 18 """Installs the editor that is called by IPython for the %edit magic.
18 19
19 20 This overrides the default editor, which is generally set by your EDITOR
20 21 environment variable or is notepad (windows) or vi (linux). By supplying a
21 22 template string `run_template`, you can control how the editor is invoked
22 23 by IPython -- (e.g. the format in which it accepts command line options)
23 24
24 25 Parameters
25 26 ----------
26 27 template : basestring
27 28 run_template acts as a template for how your editor is invoked by
28 29 the shell. It should contain '{filename}', which will be replaced on
29 30 invokation with the file name, and '{line}', $line by line number
30 31 (or 0) to invoke the file with.
31 32 wait : bool
32 33 If `wait` is true, wait until the user presses enter before returning,
33 34 to facilitate non-blocking editors that exit immediately after
34 35 the call.
35 36 """
36 37
37 38 # not all editors support $line, so we'll leave out this check
38 39 # for substitution in ['$file', '$line']:
39 40 # if not substitution in run_template:
40 41 # raise ValueError(('run_template should contain %s'
41 42 # ' for string substitution. You supplied "%s"' % (substitution,
42 43 # run_template)))
43 44
44 45 def call_editor(self, filename, line=0):
45 46 if line is None:
46 47 line = 0
47 48 cmd = template.format(filename=pipes.quote(filename), line=line)
48 print ">", cmd
49 print(">", cmd)
49 50 proc = subprocess.Popen(cmd, shell=True)
50 51 if wait and proc.wait() != 0:
51 52 raise TryNext()
52 53 if wait:
53 54 raw_input("Press Enter when done editing:")
54 55
55 56 get_ipython().set_hook('editor', call_editor)
56 57 get_ipython().editor = template
57 58
58 59
59 60 # in these, exe is always the path/name of the executable. Useful
60 61 # if you don't have the editor directory in your path
61 62 def komodo(exe=u'komodo'):
62 63 """ Activestate Komodo [Edit] """
63 64 install_editor(exe + u' -l {line} {filename}', wait=True)
64 65
65 66
66 67 def scite(exe=u"scite"):
67 68 """ SciTE or Sc1 """
68 69 install_editor(exe + u' {filename} -goto:{line}')
69 70
70 71
71 72 def notepadplusplus(exe=u'notepad++'):
72 73 """ Notepad++ http://notepad-plus.sourceforge.net """
73 74 install_editor(exe + u' -n{line} {filename}')
74 75
75 76
76 77 def jed(exe=u'jed'):
77 78 """ JED, the lightweight emacsish editor """
78 79 install_editor(exe + u' +{line} {filename}')
79 80
80 81
81 82 def idle(exe=u'idle'):
82 83 """ Idle, the editor bundled with python
83 84
84 85 Parameters
85 86 ----------
86 87 exe : str, None
87 88 If none, should be pretty smart about finding the executable.
88 89 """
89 90 if exe is None:
90 91 import idlelib
91 92 p = os.path.dirname(idlelib.__filename__)
92 93 # i'm not sure if this actually works. Is this idle.py script
93 94 # guarenteed to be executable?
94 95 exe = os.path.join(p, 'idle.py')
95 96 install_editor(exe + u' {filename}')
96 97
97 98
98 99 def mate(exe=u'mate'):
99 100 """ TextMate, the missing editor"""
100 101 # wait=True is not required since we're using the -w flag to mate
101 102 install_editor(exe + u' -w -l {line} {filename}')
102 103
103 104
104 105 # ##########################################
105 106 # these are untested, report any problems
106 107 # ##########################################
107 108
108 109
109 110 def emacs(exe=u'emacs'):
110 111 install_editor(exe + u' +{line} {filename}')
111 112
112 113
113 114 def gnuclient(exe=u'gnuclient'):
114 115 install_editor(exe + u' -nw +{line} {filename}')
115 116
116 117
117 118 def crimson_editor(exe=u'cedt.exe'):
118 119 install_editor(exe + u' /L:{line} {filename}')
119 120
120 121
121 122 def kate(exe=u'kate'):
122 123 install_editor(exe + u' -u -l {line} {filename}')
@@ -1,172 +1,173 b''
1 1 # coding: utf-8
2 2 """
3 3 GLUT Inputhook support functions
4 4 """
5 from __future__ import print_function
5 6
6 7 #-----------------------------------------------------------------------------
7 8 # Copyright (C) 2008-2011 The IPython Development Team
8 9 #
9 10 # Distributed under the terms of the BSD License. The full license is in
10 11 # the file COPYING, distributed as part of this software.
11 12 #-----------------------------------------------------------------------------
12 13
13 14 # GLUT is quite an old library and it is difficult to ensure proper
14 15 # integration within IPython since original GLUT does not allow to handle
15 16 # events one by one. Instead, it requires for the mainloop to be entered
16 17 # and never returned (there is not even a function to exit he
17 18 # mainloop). Fortunately, there are alternatives such as freeglut
18 19 # (available for linux and windows) and the OSX implementation gives
19 20 # access to a glutCheckLoop() function that blocks itself until a new
20 21 # event is received. This means we have to setup the idle callback to
21 22 # ensure we got at least one event that will unblock the function.
22 23 #
23 24 # Furthermore, it is not possible to install these handlers without a window
24 25 # being first created. We choose to make this window invisible. This means that
25 26 # display mode options are set at this level and user won't be able to change
26 27 # them later without modifying the code. This should probably be made available
27 28 # via IPython options system.
28 29
29 30 #-----------------------------------------------------------------------------
30 31 # Imports
31 32 #-----------------------------------------------------------------------------
32 33 import os
33 34 import sys
34 35 import time
35 36 import signal
36 37 import OpenGL.GLUT as glut
37 38 import OpenGL.platform as platform
38 39 from timeit import default_timer as clock
39 40
40 41 #-----------------------------------------------------------------------------
41 42 # Constants
42 43 #-----------------------------------------------------------------------------
43 44
44 45 # Frame per second : 60
45 46 # Should probably be an IPython option
46 47 glut_fps = 60
47 48
48 49
49 50 # Display mode : double buffeed + rgba + depth
50 51 # Should probably be an IPython option
51 52 glut_display_mode = (glut.GLUT_DOUBLE |
52 53 glut.GLUT_RGBA |
53 54 glut.GLUT_DEPTH)
54 55
55 56 glutMainLoopEvent = None
56 57 if sys.platform == 'darwin':
57 58 try:
58 59 glutCheckLoop = platform.createBaseFunction(
59 60 'glutCheckLoop', dll=platform.GLUT, resultType=None,
60 61 argTypes=[],
61 62 doc='glutCheckLoop( ) -> None',
62 63 argNames=(),
63 64 )
64 65 except AttributeError:
65 66 raise RuntimeError(
66 67 '''Your glut implementation does not allow interactive sessions'''
67 68 '''Consider installing freeglut.''')
68 69 glutMainLoopEvent = glutCheckLoop
69 70 elif glut.HAVE_FREEGLUT:
70 71 glutMainLoopEvent = glut.glutMainLoopEvent
71 72 else:
72 73 raise RuntimeError(
73 74 '''Your glut implementation does not allow interactive sessions. '''
74 75 '''Consider installing freeglut.''')
75 76
76 77
77 78 #-----------------------------------------------------------------------------
78 79 # Platform-dependent imports and functions
79 80 #-----------------------------------------------------------------------------
80 81
81 82 if os.name == 'posix':
82 83 import select
83 84
84 85 def stdin_ready():
85 86 infds, outfds, erfds = select.select([sys.stdin],[],[],0)
86 87 if infds:
87 88 return True
88 89 else:
89 90 return False
90 91
91 92 elif sys.platform == 'win32':
92 93 import msvcrt
93 94
94 95 def stdin_ready():
95 96 return msvcrt.kbhit()
96 97
97 98 #-----------------------------------------------------------------------------
98 99 # Callback functions
99 100 #-----------------------------------------------------------------------------
100 101
101 102 def glut_display():
102 103 # Dummy display function
103 104 pass
104 105
105 106 def glut_idle():
106 107 # Dummy idle function
107 108 pass
108 109
109 110 def glut_close():
110 111 # Close function only hides the current window
111 112 glut.glutHideWindow()
112 113 glutMainLoopEvent()
113 114
114 115 def glut_int_handler(signum, frame):
115 116 # Catch sigint and print the defautl message
116 117 signal.signal(signal.SIGINT, signal.default_int_handler)
117 print '\nKeyboardInterrupt'
118 print('\nKeyboardInterrupt')
118 119 # Need to reprint the prompt at this stage
119 120
120 121
121 122
122 123 #-----------------------------------------------------------------------------
123 124 # Code
124 125 #-----------------------------------------------------------------------------
125 126 def inputhook_glut():
126 127 """Run the pyglet event loop by processing pending events only.
127 128
128 129 This keeps processing pending events until stdin is ready. After
129 130 processing all pending events, a call to time.sleep is inserted. This is
130 131 needed, otherwise, CPU usage is at 100%. This sleep time should be tuned
131 132 though for best performance.
132 133 """
133 134 # We need to protect against a user pressing Control-C when IPython is
134 135 # idle and this is running. We trap KeyboardInterrupt and pass.
135 136
136 137 signal.signal(signal.SIGINT, glut_int_handler)
137 138
138 139 try:
139 140 t = clock()
140 141
141 142 # Make sure the default window is set after a window has been closed
142 143 if glut.glutGetWindow() == 0:
143 144 glut.glutSetWindow( 1 )
144 145 glutMainLoopEvent()
145 146 return 0
146 147
147 148 while not stdin_ready():
148 149 glutMainLoopEvent()
149 150 # We need to sleep at this point to keep the idle CPU load
150 151 # low. However, if sleep to long, GUI response is poor. As
151 152 # a compromise, we watch how often GUI events are being processed
152 153 # and switch between a short and long sleep time. Here are some
153 154 # stats useful in helping to tune this.
154 155 # time CPU load
155 156 # 0.001 13%
156 157 # 0.005 3%
157 158 # 0.01 1.5%
158 159 # 0.05 0.5%
159 160 used_time = clock() - t
160 161 if used_time > 10.0:
161 162 # print 'Sleep for 1 s' # dbg
162 163 time.sleep(1.0)
163 164 elif used_time > 0.1:
164 165 # Few GUI events coming in, so we can sleep longer
165 166 # print 'Sleep for 0.05 s' # dbg
166 167 time.sleep(0.05)
167 168 else:
168 169 # Many GUI events coming in, so sleep only very little
169 170 time.sleep(0.001)
170 171 except KeyboardInterrupt:
171 172 pass
172 173 return 0
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 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