##// END OF EJS Templates
allow_none=False by default for Type and Instance
Sylvain Corlay -
Show More

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

@@ -1,622 +1,622 b''
1 1 # encoding: utf-8
2 2 """A base class for a configurable application."""
3 3
4 4 # Copyright (c) IPython Development Team.
5 5 # Distributed under the terms of the Modified BSD License.
6 6
7 7 from __future__ import print_function
8 8
9 9 import json
10 10 import logging
11 11 import os
12 12 import re
13 13 import sys
14 14 from copy import deepcopy
15 15 from collections import defaultdict
16 16
17 17 from decorator import decorator
18 18
19 19 from IPython.config.configurable import SingletonConfigurable
20 20 from IPython.config.loader import (
21 21 KVArgParseConfigLoader, PyFileConfigLoader, Config, ArgumentError, ConfigFileNotFound, JSONFileConfigLoader
22 22 )
23 23
24 24 from IPython.utils.traitlets import (
25 25 Unicode, List, Enum, Dict, Instance, TraitError
26 26 )
27 27 from IPython.utils.importstring import import_item
28 28 from IPython.utils.text import indent, wrap_paragraphs, dedent
29 29 from IPython.utils import py3compat
30 30 from IPython.utils.py3compat import string_types, iteritems
31 31
32 32 #-----------------------------------------------------------------------------
33 33 # Descriptions for the various sections
34 34 #-----------------------------------------------------------------------------
35 35
36 36 # merge flags&aliases into options
37 37 option_description = """
38 38 Arguments that take values are actually convenience aliases to full
39 39 Configurables, whose aliases are listed on the help line. For more information
40 40 on full configurables, see '--help-all'.
41 41 """.strip() # trim newlines of front and back
42 42
43 43 keyvalue_description = """
44 44 Parameters are set from command-line arguments of the form:
45 45 `--Class.trait=value`.
46 46 This line is evaluated in Python, so simple expressions are allowed, e.g.::
47 47 `--C.a='range(3)'` For setting C.a=[0,1,2].
48 48 """.strip() # trim newlines of front and back
49 49
50 50 # sys.argv can be missing, for example when python is embedded. See the docs
51 51 # for details: http://docs.python.org/2/c-api/intro.html#embedding-python
52 52 if not hasattr(sys, "argv"):
53 53 sys.argv = [""]
54 54
55 55 subcommand_description = """
56 56 Subcommands are launched as `{app} cmd [args]`. For information on using
57 57 subcommand 'cmd', do: `{app} cmd -h`.
58 58 """
59 59 # get running program name
60 60
61 61 #-----------------------------------------------------------------------------
62 62 # Application class
63 63 #-----------------------------------------------------------------------------
64 64
65 65 @decorator
66 66 def catch_config_error(method, app, *args, **kwargs):
67 67 """Method decorator for catching invalid config (Trait/ArgumentErrors) during init.
68 68
69 69 On a TraitError (generally caused by bad config), this will print the trait's
70 70 message, and exit the app.
71 71
72 72 For use on init methods, to prevent invoking excepthook on invalid input.
73 73 """
74 74 try:
75 75 return method(app, *args, **kwargs)
76 76 except (TraitError, ArgumentError) as e:
77 77 app.print_help()
78 78 app.log.fatal("Bad config encountered during initialization:")
79 79 app.log.fatal(str(e))
80 80 app.log.debug("Config at the time: %s", app.config)
81 81 app.exit(1)
82 82
83 83
84 84 class ApplicationError(Exception):
85 85 pass
86 86
87 87 class LevelFormatter(logging.Formatter):
88 88 """Formatter with additional `highlevel` record
89 89
90 90 This field is empty if log level is less than highlevel_limit,
91 91 otherwise it is formatted with self.highlevel_format.
92 92
93 93 Useful for adding 'WARNING' to warning messages,
94 94 without adding 'INFO' to info, etc.
95 95 """
96 96 highlevel_limit = logging.WARN
97 97 highlevel_format = " %(levelname)s |"
98 98
99 99 def format(self, record):
100 100 if record.levelno >= self.highlevel_limit:
101 101 record.highlevel = self.highlevel_format % record.__dict__
102 102 else:
103 103 record.highlevel = ""
104 104 return super(LevelFormatter, self).format(record)
105 105
106 106
107 107 class Application(SingletonConfigurable):
108 108 """A singleton application with full configuration support."""
109 109
110 110 # The name of the application, will usually match the name of the command
111 111 # line application
112 112 name = Unicode(u'application')
113 113
114 114 # The description of the application that is printed at the beginning
115 115 # of the help.
116 116 description = Unicode(u'This is an application.')
117 117 # default section descriptions
118 118 option_description = Unicode(option_description)
119 119 keyvalue_description = Unicode(keyvalue_description)
120 120 subcommand_description = Unicode(subcommand_description)
121 121
122 122 python_config_loader_class = PyFileConfigLoader
123 123 json_config_loader_class = JSONFileConfigLoader
124 124
125 125 # The usage and example string that goes at the end of the help string.
126 126 examples = Unicode()
127 127
128 128 # A sequence of Configurable subclasses whose config=True attributes will
129 129 # be exposed at the command line.
130 130 classes = []
131 131 @property
132 132 def _help_classes(self):
133 133 """Define `App.help_classes` if CLI classes should differ from config file classes"""
134 134 return getattr(self, 'help_classes', self.classes)
135 135
136 136 @property
137 137 def _config_classes(self):
138 138 """Define `App.config_classes` if config file classes should differ from CLI classes."""
139 139 return getattr(self, 'config_classes', self.classes)
140 140
141 141 # The version string of this application.
142 142 version = Unicode(u'0.0')
143 143
144 144 # the argv used to initialize the application
145 145 argv = List()
146 146
147 147 # The log level for the application
148 148 log_level = Enum((0,10,20,30,40,50,'DEBUG','INFO','WARN','ERROR','CRITICAL'),
149 149 default_value=logging.WARN,
150 150 config=True,
151 151 help="Set the log level by value or name.")
152 152 def _log_level_changed(self, name, old, new):
153 153 """Adjust the log level when log_level is set."""
154 154 if isinstance(new, string_types):
155 155 new = getattr(logging, new)
156 156 self.log_level = new
157 157 self.log.setLevel(new)
158 158
159 159 _log_formatter_cls = LevelFormatter
160 160
161 161 log_datefmt = Unicode("%Y-%m-%d %H:%M:%S", config=True,
162 162 help="The date format used by logging formatters for %(asctime)s"
163 163 )
164 164 def _log_datefmt_changed(self, name, old, new):
165 165 self._log_format_changed('log_format', self.log_format, self.log_format)
166 166
167 167 log_format = Unicode("[%(name)s]%(highlevel)s %(message)s", config=True,
168 168 help="The Logging format template",
169 169 )
170 170 def _log_format_changed(self, name, old, new):
171 171 """Change the log formatter when log_format is set."""
172 172 _log_handler = self.log.handlers[0]
173 173 _log_formatter = self._log_formatter_cls(fmt=new, datefmt=self.log_datefmt)
174 174 _log_handler.setFormatter(_log_formatter)
175 175
176 176
177 log = Instance(logging.Logger)
177 log = Instance(logging.Logger, allow_none=True)
178 178 def _log_default(self):
179 179 """Start logging for this application.
180 180
181 181 The default is to log to stderr using a StreamHandler, if no default
182 182 handler already exists. The log level starts at logging.WARN, but this
183 183 can be adjusted by setting the ``log_level`` attribute.
184 184 """
185 185 log = logging.getLogger(self.__class__.__name__)
186 186 log.setLevel(self.log_level)
187 187 log.propagate = False
188 188 _log = log # copied from Logger.hasHandlers() (new in Python 3.2)
189 189 while _log:
190 190 if _log.handlers:
191 191 return log
192 192 if not _log.propagate:
193 193 break
194 194 else:
195 195 _log = _log.parent
196 196 if sys.executable.endswith('pythonw.exe'):
197 197 # this should really go to a file, but file-logging is only
198 198 # hooked up in parallel applications
199 199 _log_handler = logging.StreamHandler(open(os.devnull, 'w'))
200 200 else:
201 201 _log_handler = logging.StreamHandler()
202 202 _log_formatter = self._log_formatter_cls(fmt=self.log_format, datefmt=self.log_datefmt)
203 203 _log_handler.setFormatter(_log_formatter)
204 204 log.addHandler(_log_handler)
205 205 return log
206 206
207 207 # the alias map for configurables
208 208 aliases = Dict({'log-level' : 'Application.log_level'})
209 209
210 210 # flags for loading Configurables or store_const style flags
211 211 # flags are loaded from this dict by '--key' flags
212 212 # this must be a dict of two-tuples, the first element being the Config/dict
213 213 # and the second being the help string for the flag
214 214 flags = Dict()
215 215 def _flags_changed(self, name, old, new):
216 216 """ensure flags dict is valid"""
217 217 for key,value in iteritems(new):
218 218 assert len(value) == 2, "Bad flag: %r:%s"%(key,value)
219 219 assert isinstance(value[0], (dict, Config)), "Bad flag: %r:%s"%(key,value)
220 220 assert isinstance(value[1], string_types), "Bad flag: %r:%s"%(key,value)
221 221
222 222
223 223 # subcommands for launching other applications
224 224 # if this is not empty, this will be a parent Application
225 225 # this must be a dict of two-tuples,
226 226 # the first element being the application class/import string
227 227 # and the second being the help string for the subcommand
228 228 subcommands = Dict()
229 229 # parse_command_line will initialize a subapp, if requested
230 230 subapp = Instance('IPython.config.application.Application', allow_none=True)
231 231
232 232 # extra command-line arguments that don't set config values
233 233 extra_args = List(Unicode)
234 234
235 235
236 236 def __init__(self, **kwargs):
237 237 SingletonConfigurable.__init__(self, **kwargs)
238 238 # Ensure my class is in self.classes, so my attributes appear in command line
239 239 # options and config files.
240 240 if self.__class__ not in self.classes:
241 241 self.classes.insert(0, self.__class__)
242 242
243 243 def _config_changed(self, name, old, new):
244 244 SingletonConfigurable._config_changed(self, name, old, new)
245 245 self.log.debug('Config changed:')
246 246 self.log.debug(repr(new))
247 247
248 248 @catch_config_error
249 249 def initialize(self, argv=None):
250 250 """Do the basic steps to configure me.
251 251
252 252 Override in subclasses.
253 253 """
254 254 self.parse_command_line(argv)
255 255
256 256
257 257 def start(self):
258 258 """Start the app mainloop.
259 259
260 260 Override in subclasses.
261 261 """
262 262 if self.subapp is not None:
263 263 return self.subapp.start()
264 264
265 265 def print_alias_help(self):
266 266 """Print the alias part of the help."""
267 267 if not self.aliases:
268 268 return
269 269
270 270 lines = []
271 271 classdict = {}
272 272 for cls in self._help_classes:
273 273 # include all parents (up to, but excluding Configurable) in available names
274 274 for c in cls.mro()[:-3]:
275 275 classdict[c.__name__] = c
276 276
277 277 for alias, longname in iteritems(self.aliases):
278 278 classname, traitname = longname.split('.',1)
279 279 cls = classdict[classname]
280 280
281 281 trait = cls.class_traits(config=True)[traitname]
282 282 help = cls.class_get_trait_help(trait).splitlines()
283 283 # reformat first line
284 284 help[0] = help[0].replace(longname, alias) + ' (%s)'%longname
285 285 if len(alias) == 1:
286 286 help[0] = help[0].replace('--%s='%alias, '-%s '%alias)
287 287 lines.extend(help)
288 288 # lines.append('')
289 289 print(os.linesep.join(lines))
290 290
291 291 def print_flag_help(self):
292 292 """Print the flag part of the help."""
293 293 if not self.flags:
294 294 return
295 295
296 296 lines = []
297 297 for m, (cfg,help) in iteritems(self.flags):
298 298 prefix = '--' if len(m) > 1 else '-'
299 299 lines.append(prefix+m)
300 300 lines.append(indent(dedent(help.strip())))
301 301 # lines.append('')
302 302 print(os.linesep.join(lines))
303 303
304 304 def print_options(self):
305 305 if not self.flags and not self.aliases:
306 306 return
307 307 lines = ['Options']
308 308 lines.append('-'*len(lines[0]))
309 309 lines.append('')
310 310 for p in wrap_paragraphs(self.option_description):
311 311 lines.append(p)
312 312 lines.append('')
313 313 print(os.linesep.join(lines))
314 314 self.print_flag_help()
315 315 self.print_alias_help()
316 316 print()
317 317
318 318 def print_subcommands(self):
319 319 """Print the subcommand part of the help."""
320 320 if not self.subcommands:
321 321 return
322 322
323 323 lines = ["Subcommands"]
324 324 lines.append('-'*len(lines[0]))
325 325 lines.append('')
326 326 for p in wrap_paragraphs(self.subcommand_description.format(
327 327 app=self.name)):
328 328 lines.append(p)
329 329 lines.append('')
330 330 for subc, (cls, help) in iteritems(self.subcommands):
331 331 lines.append(subc)
332 332 if help:
333 333 lines.append(indent(dedent(help.strip())))
334 334 lines.append('')
335 335 print(os.linesep.join(lines))
336 336
337 337 def print_help(self, classes=False):
338 338 """Print the help for each Configurable class in self.classes.
339 339
340 340 If classes=False (the default), only flags and aliases are printed.
341 341 """
342 342 self.print_description()
343 343 self.print_subcommands()
344 344 self.print_options()
345 345
346 346 if classes:
347 347 help_classes = self._help_classes
348 348 if help_classes:
349 349 print("Class parameters")
350 350 print("----------------")
351 351 print()
352 352 for p in wrap_paragraphs(self.keyvalue_description):
353 353 print(p)
354 354 print()
355 355
356 356 for cls in help_classes:
357 357 cls.class_print_help()
358 358 print()
359 359 else:
360 360 print("To see all available configurables, use `--help-all`")
361 361 print()
362 362
363 363 self.print_examples()
364 364
365 365
366 366 def print_description(self):
367 367 """Print the application description."""
368 368 for p in wrap_paragraphs(self.description):
369 369 print(p)
370 370 print()
371 371
372 372 def print_examples(self):
373 373 """Print usage and examples.
374 374
375 375 This usage string goes at the end of the command line help string
376 376 and should contain examples of the application's usage.
377 377 """
378 378 if self.examples:
379 379 print("Examples")
380 380 print("--------")
381 381 print()
382 382 print(indent(dedent(self.examples.strip())))
383 383 print()
384 384
385 385 def print_version(self):
386 386 """Print the version string."""
387 387 print(self.version)
388 388
389 389 def update_config(self, config):
390 390 """Fire the traits events when the config is updated."""
391 391 # Save a copy of the current config.
392 392 newconfig = deepcopy(self.config)
393 393 # Merge the new config into the current one.
394 394 newconfig.merge(config)
395 395 # Save the combined config as self.config, which triggers the traits
396 396 # events.
397 397 self.config = newconfig
398 398
399 399 @catch_config_error
400 400 def initialize_subcommand(self, subc, argv=None):
401 401 """Initialize a subcommand with argv."""
402 402 subapp,help = self.subcommands.get(subc)
403 403
404 404 if isinstance(subapp, string_types):
405 405 subapp = import_item(subapp)
406 406
407 407 # clear existing instances
408 408 self.__class__.clear_instance()
409 409 # instantiate
410 410 self.subapp = subapp.instance(config=self.config)
411 411 # and initialize subapp
412 412 self.subapp.initialize(argv)
413 413
414 414 def flatten_flags(self):
415 415 """flatten flags and aliases, so cl-args override as expected.
416 416
417 417 This prevents issues such as an alias pointing to InteractiveShell,
418 418 but a config file setting the same trait in TerminalInteraciveShell
419 419 getting inappropriate priority over the command-line arg.
420 420
421 421 Only aliases with exactly one descendent in the class list
422 422 will be promoted.
423 423
424 424 """
425 425 # build a tree of classes in our list that inherit from a particular
426 426 # it will be a dict by parent classname of classes in our list
427 427 # that are descendents
428 428 mro_tree = defaultdict(list)
429 429 for cls in self._help_classes:
430 430 clsname = cls.__name__
431 431 for parent in cls.mro()[1:-3]:
432 432 # exclude cls itself and Configurable,HasTraits,object
433 433 mro_tree[parent.__name__].append(clsname)
434 434 # flatten aliases, which have the form:
435 435 # { 'alias' : 'Class.trait' }
436 436 aliases = {}
437 437 for alias, cls_trait in iteritems(self.aliases):
438 438 cls,trait = cls_trait.split('.',1)
439 439 children = mro_tree[cls]
440 440 if len(children) == 1:
441 441 # exactly one descendent, promote alias
442 442 cls = children[0]
443 443 aliases[alias] = '.'.join([cls,trait])
444 444
445 445 # flatten flags, which are of the form:
446 446 # { 'key' : ({'Cls' : {'trait' : value}}, 'help')}
447 447 flags = {}
448 448 for key, (flagdict, help) in iteritems(self.flags):
449 449 newflag = {}
450 450 for cls, subdict in iteritems(flagdict):
451 451 children = mro_tree[cls]
452 452 # exactly one descendent, promote flag section
453 453 if len(children) == 1:
454 454 cls = children[0]
455 455 newflag[cls] = subdict
456 456 flags[key] = (newflag, help)
457 457 return flags, aliases
458 458
459 459 @catch_config_error
460 460 def parse_command_line(self, argv=None):
461 461 """Parse the command line arguments."""
462 462 argv = sys.argv[1:] if argv is None else argv
463 463 self.argv = [ py3compat.cast_unicode(arg) for arg in argv ]
464 464
465 465 if argv and argv[0] == 'help':
466 466 # turn `ipython help notebook` into `ipython notebook -h`
467 467 argv = argv[1:] + ['-h']
468 468
469 469 if self.subcommands and len(argv) > 0:
470 470 # we have subcommands, and one may have been specified
471 471 subc, subargv = argv[0], argv[1:]
472 472 if re.match(r'^\w(\-?\w)*$', subc) and subc in self.subcommands:
473 473 # it's a subcommand, and *not* a flag or class parameter
474 474 return self.initialize_subcommand(subc, subargv)
475 475
476 476 # Arguments after a '--' argument are for the script IPython may be
477 477 # about to run, not IPython iteslf. For arguments parsed here (help and
478 478 # version), we want to only search the arguments up to the first
479 479 # occurrence of '--', which we're calling interpreted_argv.
480 480 try:
481 481 interpreted_argv = argv[:argv.index('--')]
482 482 except ValueError:
483 483 interpreted_argv = argv
484 484
485 485 if any(x in interpreted_argv for x in ('-h', '--help-all', '--help')):
486 486 self.print_help('--help-all' in interpreted_argv)
487 487 self.exit(0)
488 488
489 489 if '--version' in interpreted_argv or '-V' in interpreted_argv:
490 490 self.print_version()
491 491 self.exit(0)
492 492
493 493 # flatten flags&aliases, so cl-args get appropriate priority:
494 494 flags,aliases = self.flatten_flags()
495 495 loader = KVArgParseConfigLoader(argv=argv, aliases=aliases,
496 496 flags=flags, log=self.log)
497 497 config = loader.load_config()
498 498 self.update_config(config)
499 499 # store unparsed args in extra_args
500 500 self.extra_args = loader.extra_args
501 501
502 502 @classmethod
503 503 def _load_config_files(cls, basefilename, path=None, log=None):
504 504 """Load config files (py,json) by filename and path.
505 505
506 506 yield each config object in turn.
507 507 """
508 508
509 509 if not isinstance(path, list):
510 510 path = [path]
511 511 for path in path[::-1]:
512 512 # path list is in descending priority order, so load files backwards:
513 513 pyloader = cls.python_config_loader_class(basefilename+'.py', path=path, log=log)
514 514 jsonloader = cls.json_config_loader_class(basefilename+'.json', path=path, log=log)
515 515 config = None
516 516 for loader in [pyloader, jsonloader]:
517 517 try:
518 518 config = loader.load_config()
519 519 except ConfigFileNotFound:
520 520 pass
521 521 except Exception:
522 522 # try to get the full filename, but it will be empty in the
523 523 # unlikely event that the error raised before filefind finished
524 524 filename = loader.full_filename or basefilename
525 525 # problem while running the file
526 526 if log:
527 527 log.error("Exception while loading config file %s",
528 528 filename, exc_info=True)
529 529 else:
530 530 if log:
531 531 log.debug("Loaded config file: %s", loader.full_filename)
532 532 if config:
533 533 yield config
534 534
535 535 raise StopIteration
536 536
537 537
538 538 @catch_config_error
539 539 def load_config_file(self, filename, path=None):
540 540 """Load config files by filename and path."""
541 541 filename, ext = os.path.splitext(filename)
542 542 loaded = []
543 543 for config in self._load_config_files(filename, path=path, log=self.log):
544 544 loaded.append(config)
545 545 self.update_config(config)
546 546 if len(loaded) > 1:
547 547 collisions = loaded[0].collisions(loaded[1])
548 548 if collisions:
549 549 self.log.warn("Collisions detected in {0}.py and {0}.json config files."
550 550 " {0}.json has higher priority: {1}".format(
551 551 filename, json.dumps(collisions, indent=2),
552 552 ))
553 553
554 554
555 555 def generate_config_file(self):
556 556 """generate default config file from Configurables"""
557 557 lines = ["# Configuration file for %s." % self.name]
558 558 lines.append('')
559 559 for cls in self._config_classes:
560 560 lines.append(cls.class_config_section())
561 561 return '\n'.join(lines)
562 562
563 563 def exit(self, exit_status=0):
564 564 self.log.debug("Exiting application: %s" % self.name)
565 565 sys.exit(exit_status)
566 566
567 567 @classmethod
568 568 def launch_instance(cls, argv=None, **kwargs):
569 569 """Launch a global instance of this Application
570 570
571 571 If a global instance already exists, this reinitializes and starts it
572 572 """
573 573 app = cls.instance(**kwargs)
574 574 app.initialize(argv)
575 575 app.start()
576 576
577 577 #-----------------------------------------------------------------------------
578 578 # utility functions, for convenience
579 579 #-----------------------------------------------------------------------------
580 580
581 581 def boolean_flag(name, configurable, set_help='', unset_help=''):
582 582 """Helper for building basic --trait, --no-trait flags.
583 583
584 584 Parameters
585 585 ----------
586 586
587 587 name : str
588 588 The name of the flag.
589 589 configurable : str
590 590 The 'Class.trait' string of the trait to be set/unset with the flag
591 591 set_help : unicode
592 592 help string for --name flag
593 593 unset_help : unicode
594 594 help string for --no-name flag
595 595
596 596 Returns
597 597 -------
598 598
599 599 cfg : dict
600 600 A dict with two keys: 'name', and 'no-name', for setting and unsetting
601 601 the trait, respectively.
602 602 """
603 603 # default helpstrings
604 604 set_help = set_help or "set %s=True"%configurable
605 605 unset_help = unset_help or "set %s=False"%configurable
606 606
607 607 cls,trait = configurable.split('.')
608 608
609 609 setter = {cls : {trait : True}}
610 610 unsetter = {cls : {trait : False}}
611 611 return {name : (setter, set_help), 'no-'+name : (unsetter, unset_help)}
612 612
613 613
614 614 def get_config():
615 615 """Get the config object for the global Application instance, if there is one
616 616
617 617 otherwise return an empty config object
618 618 """
619 619 if Application.initialized():
620 620 return Application.instance().config
621 621 else:
622 622 return Config()
@@ -1,380 +1,380 b''
1 1 # encoding: utf-8
2 2 """A base class for objects that are configurable."""
3 3
4 4 # Copyright (c) IPython Development Team.
5 5 # Distributed under the terms of the Modified BSD License.
6 6
7 7 from __future__ import print_function
8 8
9 9 import logging
10 10 from copy import deepcopy
11 11
12 12 from .loader import Config, LazyConfigValue
13 13 from IPython.utils.traitlets import HasTraits, Instance
14 14 from IPython.utils.text import indent, wrap_paragraphs
15 15 from IPython.utils.py3compat import iteritems
16 16
17 17
18 18 #-----------------------------------------------------------------------------
19 19 # Helper classes for Configurables
20 20 #-----------------------------------------------------------------------------
21 21
22 22
23 23 class ConfigurableError(Exception):
24 24 pass
25 25
26 26
27 27 class MultipleInstanceError(ConfigurableError):
28 28 pass
29 29
30 30 #-----------------------------------------------------------------------------
31 31 # Configurable implementation
32 32 #-----------------------------------------------------------------------------
33 33
34 34 class Configurable(HasTraits):
35 35
36 36 config = Instance(Config, (), {})
37 parent = Instance('IPython.config.configurable.Configurable')
37 parent = Instance('IPython.config.configurable.Configurable', allow_none=True)
38 38
39 39 def __init__(self, **kwargs):
40 40 """Create a configurable given a config config.
41 41
42 42 Parameters
43 43 ----------
44 44 config : Config
45 45 If this is empty, default values are used. If config is a
46 46 :class:`Config` instance, it will be used to configure the
47 47 instance.
48 48 parent : Configurable instance, optional
49 49 The parent Configurable instance of this object.
50 50
51 51 Notes
52 52 -----
53 53 Subclasses of Configurable must call the :meth:`__init__` method of
54 54 :class:`Configurable` *before* doing anything else and using
55 55 :func:`super`::
56 56
57 57 class MyConfigurable(Configurable):
58 58 def __init__(self, config=None):
59 59 super(MyConfigurable, self).__init__(config=config)
60 60 # Then any other code you need to finish initialization.
61 61
62 62 This ensures that instances will be configured properly.
63 63 """
64 64 parent = kwargs.pop('parent', None)
65 65 if parent is not None:
66 66 # config is implied from parent
67 67 if kwargs.get('config', None) is None:
68 68 kwargs['config'] = parent.config
69 69 self.parent = parent
70 70
71 71 config = kwargs.pop('config', None)
72 72
73 73 # load kwarg traits, other than config
74 74 super(Configurable, self).__init__(**kwargs)
75 75
76 76 # load config
77 77 if config is not None:
78 78 # We used to deepcopy, but for now we are trying to just save
79 79 # by reference. This *could* have side effects as all components
80 80 # will share config. In fact, I did find such a side effect in
81 81 # _config_changed below. If a config attribute value was a mutable type
82 82 # all instances of a component were getting the same copy, effectively
83 83 # making that a class attribute.
84 84 # self.config = deepcopy(config)
85 85 self.config = config
86 86 else:
87 87 # allow _config_default to return something
88 88 self._load_config(self.config)
89 89
90 90 # Ensure explicit kwargs are applied after loading config.
91 91 # This is usually redundant, but ensures config doesn't override
92 92 # explicitly assigned values.
93 93 for key, value in kwargs.items():
94 94 setattr(self, key, value)
95 95
96 96 #-------------------------------------------------------------------------
97 97 # Static trait notifiations
98 98 #-------------------------------------------------------------------------
99 99
100 100 @classmethod
101 101 def section_names(cls):
102 102 """return section names as a list"""
103 103 return [c.__name__ for c in reversed(cls.__mro__) if
104 104 issubclass(c, Configurable) and issubclass(cls, c)
105 105 ]
106 106
107 107 def _find_my_config(self, cfg):
108 108 """extract my config from a global Config object
109 109
110 110 will construct a Config object of only the config values that apply to me
111 111 based on my mro(), as well as those of my parent(s) if they exist.
112 112
113 113 If I am Bar and my parent is Foo, and their parent is Tim,
114 114 this will return merge following config sections, in this order::
115 115
116 116 [Bar, Foo.bar, Tim.Foo.Bar]
117 117
118 118 With the last item being the highest priority.
119 119 """
120 120 cfgs = [cfg]
121 121 if self.parent:
122 122 cfgs.append(self.parent._find_my_config(cfg))
123 123 my_config = Config()
124 124 for c in cfgs:
125 125 for sname in self.section_names():
126 126 # Don't do a blind getattr as that would cause the config to
127 127 # dynamically create the section with name Class.__name__.
128 128 if c._has_section(sname):
129 129 my_config.merge(c[sname])
130 130 return my_config
131 131
132 132 def _load_config(self, cfg, section_names=None, traits=None):
133 133 """load traits from a Config object"""
134 134
135 135 if traits is None:
136 136 traits = self.traits(config=True)
137 137 if section_names is None:
138 138 section_names = self.section_names()
139 139
140 140 my_config = self._find_my_config(cfg)
141 141
142 142 # hold trait notifications until after all config has been loaded
143 143 with self.hold_trait_notifications():
144 144 for name, config_value in iteritems(my_config):
145 145 if name in traits:
146 146 if isinstance(config_value, LazyConfigValue):
147 147 # ConfigValue is a wrapper for using append / update on containers
148 148 # without having to copy the initial value
149 149 initial = getattr(self, name)
150 150 config_value = config_value.get_value(initial)
151 151 # We have to do a deepcopy here if we don't deepcopy the entire
152 152 # config object. If we don't, a mutable config_value will be
153 153 # shared by all instances, effectively making it a class attribute.
154 154 setattr(self, name, deepcopy(config_value))
155 155
156 156 def _config_changed(self, name, old, new):
157 157 """Update all the class traits having ``config=True`` as metadata.
158 158
159 159 For any class trait with a ``config`` metadata attribute that is
160 160 ``True``, we update the trait with the value of the corresponding
161 161 config entry.
162 162 """
163 163 # Get all traits with a config metadata entry that is True
164 164 traits = self.traits(config=True)
165 165
166 166 # We auto-load config section for this class as well as any parent
167 167 # classes that are Configurable subclasses. This starts with Configurable
168 168 # and works down the mro loading the config for each section.
169 169 section_names = self.section_names()
170 170 self._load_config(new, traits=traits, section_names=section_names)
171 171
172 172 def update_config(self, config):
173 173 """Fire the traits events when the config is updated."""
174 174 # Save a copy of the current config.
175 175 newconfig = deepcopy(self.config)
176 176 # Merge the new config into the current one.
177 177 newconfig.merge(config)
178 178 # Save the combined config as self.config, which triggers the traits
179 179 # events.
180 180 self.config = newconfig
181 181
182 182 @classmethod
183 183 def class_get_help(cls, inst=None):
184 184 """Get the help string for this class in ReST format.
185 185
186 186 If `inst` is given, it's current trait values will be used in place of
187 187 class defaults.
188 188 """
189 189 assert inst is None or isinstance(inst, cls)
190 190 final_help = []
191 191 final_help.append(u'%s options' % cls.__name__)
192 192 final_help.append(len(final_help[0])*u'-')
193 193 for k, v in sorted(cls.class_traits(config=True).items()):
194 194 help = cls.class_get_trait_help(v, inst)
195 195 final_help.append(help)
196 196 return '\n'.join(final_help)
197 197
198 198 @classmethod
199 199 def class_get_trait_help(cls, trait, inst=None):
200 200 """Get the help string for a single trait.
201 201
202 202 If `inst` is given, it's current trait values will be used in place of
203 203 the class default.
204 204 """
205 205 assert inst is None or isinstance(inst, cls)
206 206 lines = []
207 207 header = "--%s.%s=<%s>" % (cls.__name__, trait.name, trait.__class__.__name__)
208 208 lines.append(header)
209 209 if inst is not None:
210 210 lines.append(indent('Current: %r' % getattr(inst, trait.name), 4))
211 211 else:
212 212 try:
213 213 dvr = repr(trait.get_default_value())
214 214 except Exception:
215 215 dvr = None # ignore defaults we can't construct
216 216 if dvr is not None:
217 217 if len(dvr) > 64:
218 218 dvr = dvr[:61]+'...'
219 219 lines.append(indent('Default: %s' % dvr, 4))
220 220 if 'Enum' in trait.__class__.__name__:
221 221 # include Enum choices
222 222 lines.append(indent('Choices: %r' % (trait.values,)))
223 223
224 224 help = trait.get_metadata('help')
225 225 if help is not None:
226 226 help = '\n'.join(wrap_paragraphs(help, 76))
227 227 lines.append(indent(help, 4))
228 228 return '\n'.join(lines)
229 229
230 230 @classmethod
231 231 def class_print_help(cls, inst=None):
232 232 """Get the help string for a single trait and print it."""
233 233 print(cls.class_get_help(inst))
234 234
235 235 @classmethod
236 236 def class_config_section(cls):
237 237 """Get the config class config section"""
238 238 def c(s):
239 239 """return a commented, wrapped block."""
240 240 s = '\n\n'.join(wrap_paragraphs(s, 78))
241 241
242 242 return '# ' + s.replace('\n', '\n# ')
243 243
244 244 # section header
245 245 breaker = '#' + '-'*78
246 246 s = "# %s configuration" % cls.__name__
247 247 lines = [breaker, s, breaker, '']
248 248 # get the description trait
249 249 desc = cls.class_traits().get('description')
250 250 if desc:
251 251 desc = desc.default_value
252 252 else:
253 253 # no description trait, use __doc__
254 254 desc = getattr(cls, '__doc__', '')
255 255 if desc:
256 256 lines.append(c(desc))
257 257 lines.append('')
258 258
259 259 parents = []
260 260 for parent in cls.mro():
261 261 # only include parents that are not base classes
262 262 # and are not the class itself
263 263 # and have some configurable traits to inherit
264 264 if parent is not cls and issubclass(parent, Configurable) and \
265 265 parent.class_traits(config=True):
266 266 parents.append(parent)
267 267
268 268 if parents:
269 269 pstr = ', '.join([ p.__name__ for p in parents ])
270 270 lines.append(c('%s will inherit config from: %s'%(cls.__name__, pstr)))
271 271 lines.append('')
272 272
273 273 for name, trait in iteritems(cls.class_traits(config=True)):
274 274 help = trait.get_metadata('help') or ''
275 275 lines.append(c(help))
276 276 lines.append('# c.%s.%s = %r'%(cls.__name__, name, trait.get_default_value()))
277 277 lines.append('')
278 278 return '\n'.join(lines)
279 279
280 280
281 281
282 282 class SingletonConfigurable(Configurable):
283 283 """A configurable that only allows one instance.
284 284
285 285 This class is for classes that should only have one instance of itself
286 286 or *any* subclass. To create and retrieve such a class use the
287 287 :meth:`SingletonConfigurable.instance` method.
288 288 """
289 289
290 290 _instance = None
291 291
292 292 @classmethod
293 293 def _walk_mro(cls):
294 294 """Walk the cls.mro() for parent classes that are also singletons
295 295
296 296 For use in instance()
297 297 """
298 298
299 299 for subclass in cls.mro():
300 300 if issubclass(cls, subclass) and \
301 301 issubclass(subclass, SingletonConfigurable) and \
302 302 subclass != SingletonConfigurable:
303 303 yield subclass
304 304
305 305 @classmethod
306 306 def clear_instance(cls):
307 307 """unset _instance for this class and singleton parents.
308 308 """
309 309 if not cls.initialized():
310 310 return
311 311 for subclass in cls._walk_mro():
312 312 if isinstance(subclass._instance, cls):
313 313 # only clear instances that are instances
314 314 # of the calling class
315 315 subclass._instance = None
316 316
317 317 @classmethod
318 318 def instance(cls, *args, **kwargs):
319 319 """Returns a global instance of this class.
320 320
321 321 This method create a new instance if none have previously been created
322 322 and returns a previously created instance is one already exists.
323 323
324 324 The arguments and keyword arguments passed to this method are passed
325 325 on to the :meth:`__init__` method of the class upon instantiation.
326 326
327 327 Examples
328 328 --------
329 329
330 330 Create a singleton class using instance, and retrieve it::
331 331
332 332 >>> from IPython.config.configurable import SingletonConfigurable
333 333 >>> class Foo(SingletonConfigurable): pass
334 334 >>> foo = Foo.instance()
335 335 >>> foo == Foo.instance()
336 336 True
337 337
338 338 Create a subclass that is retrived using the base class instance::
339 339
340 340 >>> class Bar(SingletonConfigurable): pass
341 341 >>> class Bam(Bar): pass
342 342 >>> bam = Bam.instance()
343 343 >>> bam == Bar.instance()
344 344 True
345 345 """
346 346 # Create and save the instance
347 347 if cls._instance is None:
348 348 inst = cls(*args, **kwargs)
349 349 # Now make sure that the instance will also be returned by
350 350 # parent classes' _instance attribute.
351 351 for subclass in cls._walk_mro():
352 352 subclass._instance = inst
353 353
354 354 if isinstance(cls._instance, cls):
355 355 return cls._instance
356 356 else:
357 357 raise MultipleInstanceError(
358 358 'Multiple incompatible subclass instances of '
359 359 '%s are being created.' % cls.__name__
360 360 )
361 361
362 362 @classmethod
363 363 def initialized(cls):
364 364 """Has an instance been created?"""
365 365 return hasattr(cls, "_instance") and cls._instance is not None
366 366
367 367
368 368 class LoggingConfigurable(Configurable):
369 369 """A parent class for Configurables that log.
370 370
371 371 Subclasses have a log trait, and the default behavior
372 372 is to get the logger from the currently running Application.
373 373 """
374 374
375 log = Instance('logging.Logger')
375 log = Instance('logging.Logger', allow_none=True)
376 376 def _log_default(self):
377 377 from IPython.utils import log
378 378 return log.get_logger()
379 379
380 380
@@ -1,256 +1,256 b''
1 1 # encoding: utf-8
2 2 """
3 3 System command aliases.
4 4
5 5 Authors:
6 6
7 7 * Fernando Perez
8 8 * Brian Granger
9 9 """
10 10
11 11 #-----------------------------------------------------------------------------
12 12 # Copyright (C) 2008-2011 The IPython Development Team
13 13 #
14 14 # Distributed under the terms of the BSD License.
15 15 #
16 16 # The full license is in the file COPYING.txt, distributed with this software.
17 17 #-----------------------------------------------------------------------------
18 18
19 19 #-----------------------------------------------------------------------------
20 20 # Imports
21 21 #-----------------------------------------------------------------------------
22 22
23 23 import os
24 24 import re
25 25 import sys
26 26
27 27 from IPython.config.configurable import Configurable
28 28 from IPython.core.error import UsageError
29 29
30 30 from IPython.utils.py3compat import string_types
31 31 from IPython.utils.traitlets import List, Instance
32 32 from IPython.utils.warn import error
33 33
34 34 #-----------------------------------------------------------------------------
35 35 # Utilities
36 36 #-----------------------------------------------------------------------------
37 37
38 38 # This is used as the pattern for calls to split_user_input.
39 39 shell_line_split = re.compile(r'^(\s*)()(\S+)(.*$)')
40 40
41 41 def default_aliases():
42 42 """Return list of shell aliases to auto-define.
43 43 """
44 44 # Note: the aliases defined here should be safe to use on a kernel
45 45 # regardless of what frontend it is attached to. Frontends that use a
46 46 # kernel in-process can define additional aliases that will only work in
47 47 # their case. For example, things like 'less' or 'clear' that manipulate
48 48 # the terminal should NOT be declared here, as they will only work if the
49 49 # kernel is running inside a true terminal, and not over the network.
50 50
51 51 if os.name == 'posix':
52 52 default_aliases = [('mkdir', 'mkdir'), ('rmdir', 'rmdir'),
53 53 ('mv', 'mv'), ('rm', 'rm'), ('cp', 'cp'),
54 54 ('cat', 'cat'),
55 55 ]
56 56 # Useful set of ls aliases. The GNU and BSD options are a little
57 57 # different, so we make aliases that provide as similar as possible
58 58 # behavior in ipython, by passing the right flags for each platform
59 59 if sys.platform.startswith('linux'):
60 60 ls_aliases = [('ls', 'ls -F --color'),
61 61 # long ls
62 62 ('ll', 'ls -F -o --color'),
63 63 # ls normal files only
64 64 ('lf', 'ls -F -o --color %l | grep ^-'),
65 65 # ls symbolic links
66 66 ('lk', 'ls -F -o --color %l | grep ^l'),
67 67 # directories or links to directories,
68 68 ('ldir', 'ls -F -o --color %l | grep /$'),
69 69 # things which are executable
70 70 ('lx', 'ls -F -o --color %l | grep ^-..x'),
71 71 ]
72 72 elif sys.platform.startswith('openbsd') or sys.platform.startswith('netbsd'):
73 73 # OpenBSD, NetBSD. The ls implementation on these platforms do not support
74 74 # the -G switch and lack the ability to use colorized output.
75 75 ls_aliases = [('ls', 'ls -F'),
76 76 # long ls
77 77 ('ll', 'ls -F -l'),
78 78 # ls normal files only
79 79 ('lf', 'ls -F -l %l | grep ^-'),
80 80 # ls symbolic links
81 81 ('lk', 'ls -F -l %l | grep ^l'),
82 82 # directories or links to directories,
83 83 ('ldir', 'ls -F -l %l | grep /$'),
84 84 # things which are executable
85 85 ('lx', 'ls -F -l %l | grep ^-..x'),
86 86 ]
87 87 else:
88 88 # BSD, OSX, etc.
89 89 ls_aliases = [('ls', 'ls -F -G'),
90 90 # long ls
91 91 ('ll', 'ls -F -l -G'),
92 92 # ls normal files only
93 93 ('lf', 'ls -F -l -G %l | grep ^-'),
94 94 # ls symbolic links
95 95 ('lk', 'ls -F -l -G %l | grep ^l'),
96 96 # directories or links to directories,
97 97 ('ldir', 'ls -F -G -l %l | grep /$'),
98 98 # things which are executable
99 99 ('lx', 'ls -F -l -G %l | grep ^-..x'),
100 100 ]
101 101 default_aliases = default_aliases + ls_aliases
102 102 elif os.name in ['nt', 'dos']:
103 103 default_aliases = [('ls', 'dir /on'),
104 104 ('ddir', 'dir /ad /on'), ('ldir', 'dir /ad /on'),
105 105 ('mkdir', 'mkdir'), ('rmdir', 'rmdir'),
106 106 ('echo', 'echo'), ('ren', 'ren'), ('copy', 'copy'),
107 107 ]
108 108 else:
109 109 default_aliases = []
110 110
111 111 return default_aliases
112 112
113 113
114 114 class AliasError(Exception):
115 115 pass
116 116
117 117
118 118 class InvalidAliasError(AliasError):
119 119 pass
120 120
121 121 class Alias(object):
122 122 """Callable object storing the details of one alias.
123 123
124 124 Instances are registered as magic functions to allow use of aliases.
125 125 """
126 126
127 127 # Prepare blacklist
128 128 blacklist = {'cd','popd','pushd','dhist','alias','unalias'}
129 129
130 130 def __init__(self, shell, name, cmd):
131 131 self.shell = shell
132 132 self.name = name
133 133 self.cmd = cmd
134 134 self.nargs = self.validate()
135 135
136 136 def validate(self):
137 137 """Validate the alias, and return the number of arguments."""
138 138 if self.name in self.blacklist:
139 139 raise InvalidAliasError("The name %s can't be aliased "
140 140 "because it is a keyword or builtin." % self.name)
141 141 try:
142 142 caller = self.shell.magics_manager.magics['line'][self.name]
143 143 except KeyError:
144 144 pass
145 145 else:
146 146 if not isinstance(caller, Alias):
147 147 raise InvalidAliasError("The name %s can't be aliased "
148 148 "because it is another magic command." % self.name)
149 149
150 150 if not (isinstance(self.cmd, string_types)):
151 151 raise InvalidAliasError("An alias command must be a string, "
152 152 "got: %r" % self.cmd)
153 153
154 154 nargs = self.cmd.count('%s') - self.cmd.count('%%s')
155 155
156 156 if (nargs > 0) and (self.cmd.find('%l') >= 0):
157 157 raise InvalidAliasError('The %s and %l specifiers are mutually '
158 158 'exclusive in alias definitions.')
159 159
160 160 return nargs
161 161
162 162 def __repr__(self):
163 163 return "<alias {} for {!r}>".format(self.name, self.cmd)
164 164
165 165 def __call__(self, rest=''):
166 166 cmd = self.cmd
167 167 nargs = self.nargs
168 168 # Expand the %l special to be the user's input line
169 169 if cmd.find('%l') >= 0:
170 170 cmd = cmd.replace('%l', rest)
171 171 rest = ''
172 172
173 173 if nargs==0:
174 174 if cmd.find('%%s') >= 1:
175 175 cmd = cmd.replace('%%s', '%s')
176 176 # Simple, argument-less aliases
177 177 cmd = '%s %s' % (cmd, rest)
178 178 else:
179 179 # Handle aliases with positional arguments
180 180 args = rest.split(None, nargs)
181 181 if len(args) < nargs:
182 182 raise UsageError('Alias <%s> requires %s arguments, %s given.' %
183 183 (self.name, nargs, len(args)))
184 184 cmd = '%s %s' % (cmd % tuple(args[:nargs]),' '.join(args[nargs:]))
185 185
186 186 self.shell.system(cmd)
187 187
188 188 #-----------------------------------------------------------------------------
189 189 # Main AliasManager class
190 190 #-----------------------------------------------------------------------------
191 191
192 192 class AliasManager(Configurable):
193 193
194 194 default_aliases = List(default_aliases(), config=True)
195 195 user_aliases = List(default_value=[], config=True)
196 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
196 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
197 197
198 198 def __init__(self, shell=None, **kwargs):
199 199 super(AliasManager, self).__init__(shell=shell, **kwargs)
200 200 # For convenient access
201 201 self.linemagics = self.shell.magics_manager.magics['line']
202 202 self.init_aliases()
203 203
204 204 def init_aliases(self):
205 205 # Load default & user aliases
206 206 for name, cmd in self.default_aliases + self.user_aliases:
207 207 self.soft_define_alias(name, cmd)
208 208
209 209 @property
210 210 def aliases(self):
211 211 return [(n, func.cmd) for (n, func) in self.linemagics.items()
212 212 if isinstance(func, Alias)]
213 213
214 214 def soft_define_alias(self, name, cmd):
215 215 """Define an alias, but don't raise on an AliasError."""
216 216 try:
217 217 self.define_alias(name, cmd)
218 218 except AliasError as e:
219 219 error("Invalid alias: %s" % e)
220 220
221 221 def define_alias(self, name, cmd):
222 222 """Define a new alias after validating it.
223 223
224 224 This will raise an :exc:`AliasError` if there are validation
225 225 problems.
226 226 """
227 227 caller = Alias(shell=self.shell, name=name, cmd=cmd)
228 228 self.shell.magics_manager.register_function(caller, magic_kind='line',
229 229 magic_name=name)
230 230
231 231 def get_alias(self, name):
232 232 """Return an alias, or None if no alias by that name exists."""
233 233 aname = self.linemagics.get(name, None)
234 234 return aname if isinstance(aname, Alias) else None
235 235
236 236 def is_alias(self, name):
237 237 """Return whether or not a given name has been defined as an alias"""
238 238 return self.get_alias(name) is not None
239 239
240 240 def undefine_alias(self, name):
241 241 if self.is_alias(name):
242 242 del self.linemagics[name]
243 243 else:
244 244 raise ValueError('%s is not an alias' % name)
245 245
246 246 def clear_aliases(self):
247 247 for name, cmd in self.aliases:
248 248 self.undefine_alias(name)
249 249
250 250 def retrieve_alias(self, name):
251 251 """Retrieve the command to which an alias expands."""
252 252 caller = self.get_alias(name)
253 253 if caller:
254 254 return caller.cmd
255 255 else:
256 256 raise ValueError('%s is not an alias' % name)
@@ -1,396 +1,396 b''
1 1 # encoding: utf-8
2 2 """
3 3 An application for IPython.
4 4
5 5 All top-level applications should use the classes in this module for
6 6 handling configuration and creating configurables.
7 7
8 8 The job of an :class:`Application` is to create the master configuration
9 9 object and then create the configurable objects, passing the config to them.
10 10 """
11 11
12 12 # Copyright (c) IPython Development Team.
13 13 # Distributed under the terms of the Modified BSD License.
14 14
15 15 import atexit
16 16 import glob
17 17 import logging
18 18 import os
19 19 import shutil
20 20 import sys
21 21
22 22 from IPython.config.application import Application, catch_config_error
23 23 from IPython.config.loader import ConfigFileNotFound, PyFileConfigLoader
24 24 from IPython.core import release, crashhandler
25 25 from IPython.core.profiledir import ProfileDir, ProfileDirError
26 26 from IPython.utils.path import get_ipython_dir, get_ipython_package_dir, ensure_dir_exists
27 27 from IPython.utils import py3compat
28 28 from IPython.utils.traitlets import List, Unicode, Type, Bool, Dict, Set, Instance
29 29
30 30 if os.name == 'nt':
31 31 programdata = os.environ.get('PROGRAMDATA', None)
32 32 if programdata:
33 33 SYSTEM_CONFIG_DIRS = [os.path.join(programdata, 'ipython')]
34 34 else: # PROGRAMDATA is not defined by default on XP.
35 35 SYSTEM_CONFIG_DIRS = []
36 36 else:
37 37 SYSTEM_CONFIG_DIRS = [
38 38 "/usr/local/etc/ipython",
39 39 "/etc/ipython",
40 40 ]
41 41
42 42
43 43 # aliases and flags
44 44
45 45 base_aliases = {
46 46 'profile-dir' : 'ProfileDir.location',
47 47 'profile' : 'BaseIPythonApplication.profile',
48 48 'ipython-dir' : 'BaseIPythonApplication.ipython_dir',
49 49 'log-level' : 'Application.log_level',
50 50 'config' : 'BaseIPythonApplication.extra_config_file',
51 51 }
52 52
53 53 base_flags = dict(
54 54 debug = ({'Application' : {'log_level' : logging.DEBUG}},
55 55 "set log level to logging.DEBUG (maximize logging output)"),
56 56 quiet = ({'Application' : {'log_level' : logging.CRITICAL}},
57 57 "set log level to logging.CRITICAL (minimize logging output)"),
58 58 init = ({'BaseIPythonApplication' : {
59 59 'copy_config_files' : True,
60 60 'auto_create' : True}
61 61 }, """Initialize profile with default config files. This is equivalent
62 62 to running `ipython profile create <profile>` prior to startup.
63 63 """)
64 64 )
65 65
66 66 class ProfileAwareConfigLoader(PyFileConfigLoader):
67 67 """A Python file config loader that is aware of IPython profiles."""
68 68 def load_subconfig(self, fname, path=None, profile=None):
69 69 if profile is not None:
70 70 try:
71 71 profile_dir = ProfileDir.find_profile_dir_by_name(
72 72 get_ipython_dir(),
73 73 profile,
74 74 )
75 75 except ProfileDirError:
76 76 return
77 77 path = profile_dir.location
78 78 return super(ProfileAwareConfigLoader, self).load_subconfig(fname, path=path)
79 79
80 80 class BaseIPythonApplication(Application):
81 81
82 82 name = Unicode(u'ipython')
83 83 description = Unicode(u'IPython: an enhanced interactive Python shell.')
84 84 version = Unicode(release.version)
85 85
86 86 aliases = Dict(base_aliases)
87 87 flags = Dict(base_flags)
88 88 classes = List([ProfileDir])
89 89
90 90 # enable `load_subconfig('cfg.py', profile='name')`
91 91 python_config_loader_class = ProfileAwareConfigLoader
92 92
93 93 # Track whether the config_file has changed,
94 94 # because some logic happens only if we aren't using the default.
95 95 config_file_specified = Set()
96 96
97 97 config_file_name = Unicode()
98 98 def _config_file_name_default(self):
99 99 return self.name.replace('-','_') + u'_config.py'
100 100 def _config_file_name_changed(self, name, old, new):
101 101 if new != old:
102 102 self.config_file_specified.add(new)
103 103
104 104 # The directory that contains IPython's builtin profiles.
105 105 builtin_profile_dir = Unicode(
106 106 os.path.join(get_ipython_package_dir(), u'config', u'profile', u'default')
107 107 )
108 108
109 109 config_file_paths = List(Unicode)
110 110 def _config_file_paths_default(self):
111 111 return [py3compat.getcwd()]
112 112
113 113 extra_config_file = Unicode(config=True,
114 114 help="""Path to an extra config file to load.
115 115
116 116 If specified, load this config file in addition to any other IPython config.
117 117 """)
118 118 def _extra_config_file_changed(self, name, old, new):
119 119 try:
120 120 self.config_files.remove(old)
121 121 except ValueError:
122 122 pass
123 123 self.config_file_specified.add(new)
124 124 self.config_files.append(new)
125 125
126 126 profile = Unicode(u'default', config=True,
127 127 help="""The IPython profile to use."""
128 128 )
129 129
130 130 def _profile_changed(self, name, old, new):
131 131 self.builtin_profile_dir = os.path.join(
132 132 get_ipython_package_dir(), u'config', u'profile', new
133 133 )
134 134
135 135 ipython_dir = Unicode(config=True,
136 136 help="""
137 137 The name of the IPython directory. This directory is used for logging
138 138 configuration (through profiles), history storage, etc. The default
139 139 is usually $HOME/.ipython. This option can also be specified through
140 140 the environment variable IPYTHONDIR.
141 141 """
142 142 )
143 143 def _ipython_dir_default(self):
144 144 d = get_ipython_dir()
145 145 self._ipython_dir_changed('ipython_dir', d, d)
146 146 return d
147 147
148 148 _in_init_profile_dir = False
149 profile_dir = Instance(ProfileDir)
149 profile_dir = Instance(ProfileDir, allow_none=True)
150 150 def _profile_dir_default(self):
151 151 # avoid recursion
152 152 if self._in_init_profile_dir:
153 153 return
154 154 # profile_dir requested early, force initialization
155 155 self.init_profile_dir()
156 156 return self.profile_dir
157 157
158 158 overwrite = Bool(False, config=True,
159 159 help="""Whether to overwrite existing config files when copying""")
160 160 auto_create = Bool(False, config=True,
161 161 help="""Whether to create profile dir if it doesn't exist""")
162 162
163 163 config_files = List(Unicode)
164 164 def _config_files_default(self):
165 165 return [self.config_file_name]
166 166
167 167 copy_config_files = Bool(False, config=True,
168 168 help="""Whether to install the default config files into the profile dir.
169 169 If a new profile is being created, and IPython contains config files for that
170 170 profile, then they will be staged into the new directory. Otherwise,
171 171 default config files will be automatically generated.
172 172 """)
173 173
174 174 verbose_crash = Bool(False, config=True,
175 175 help="""Create a massive crash report when IPython encounters what may be an
176 176 internal error. The default is to append a short message to the
177 177 usual traceback""")
178 178
179 179 # The class to use as the crash handler.
180 180 crash_handler_class = Type(crashhandler.CrashHandler)
181 181
182 182 @catch_config_error
183 183 def __init__(self, **kwargs):
184 184 super(BaseIPythonApplication, self).__init__(**kwargs)
185 185 # ensure current working directory exists
186 186 try:
187 187 directory = py3compat.getcwd()
188 188 except:
189 189 # exit if cwd doesn't exist
190 190 self.log.error("Current working directory doesn't exist.")
191 191 self.exit(1)
192 192
193 193 #-------------------------------------------------------------------------
194 194 # Various stages of Application creation
195 195 #-------------------------------------------------------------------------
196 196
197 197 def init_crash_handler(self):
198 198 """Create a crash handler, typically setting sys.excepthook to it."""
199 199 self.crash_handler = self.crash_handler_class(self)
200 200 sys.excepthook = self.excepthook
201 201 def unset_crashhandler():
202 202 sys.excepthook = sys.__excepthook__
203 203 atexit.register(unset_crashhandler)
204 204
205 205 def excepthook(self, etype, evalue, tb):
206 206 """this is sys.excepthook after init_crashhandler
207 207
208 208 set self.verbose_crash=True to use our full crashhandler, instead of
209 209 a regular traceback with a short message (crash_handler_lite)
210 210 """
211 211
212 212 if self.verbose_crash:
213 213 return self.crash_handler(etype, evalue, tb)
214 214 else:
215 215 return crashhandler.crash_handler_lite(etype, evalue, tb)
216 216
217 217 def _ipython_dir_changed(self, name, old, new):
218 218 if old is not None:
219 219 str_old = py3compat.cast_bytes_py2(os.path.abspath(old),
220 220 sys.getfilesystemencoding()
221 221 )
222 222 if str_old in sys.path:
223 223 sys.path.remove(str_old)
224 224 str_path = py3compat.cast_bytes_py2(os.path.abspath(new),
225 225 sys.getfilesystemencoding()
226 226 )
227 227 sys.path.append(str_path)
228 228 ensure_dir_exists(new)
229 229 readme = os.path.join(new, 'README')
230 230 readme_src = os.path.join(get_ipython_package_dir(), u'config', u'profile', 'README')
231 231 if not os.path.exists(readme) and os.path.exists(readme_src):
232 232 shutil.copy(readme_src, readme)
233 233 for d in ('extensions', 'nbextensions'):
234 234 path = os.path.join(new, d)
235 235 try:
236 236 ensure_dir_exists(path)
237 237 except OSError:
238 238 # this will not be EEXIST
239 239 self.log.error("couldn't create path %s: %s", path, e)
240 240 self.log.debug("IPYTHONDIR set to: %s" % new)
241 241
242 242 def load_config_file(self, suppress_errors=True):
243 243 """Load the config file.
244 244
245 245 By default, errors in loading config are handled, and a warning
246 246 printed on screen. For testing, the suppress_errors option is set
247 247 to False, so errors will make tests fail.
248 248 """
249 249 self.log.debug("Searching path %s for config files", self.config_file_paths)
250 250 base_config = 'ipython_config.py'
251 251 self.log.debug("Attempting to load config file: %s" %
252 252 base_config)
253 253 try:
254 254 Application.load_config_file(
255 255 self,
256 256 base_config,
257 257 path=self.config_file_paths
258 258 )
259 259 except ConfigFileNotFound:
260 260 # ignore errors loading parent
261 261 self.log.debug("Config file %s not found", base_config)
262 262 pass
263 263
264 264 for config_file_name in self.config_files:
265 265 if not config_file_name or config_file_name == base_config:
266 266 continue
267 267 self.log.debug("Attempting to load config file: %s" %
268 268 self.config_file_name)
269 269 try:
270 270 Application.load_config_file(
271 271 self,
272 272 config_file_name,
273 273 path=self.config_file_paths
274 274 )
275 275 except ConfigFileNotFound:
276 276 # Only warn if the default config file was NOT being used.
277 277 if config_file_name in self.config_file_specified:
278 278 msg = self.log.warn
279 279 else:
280 280 msg = self.log.debug
281 281 msg("Config file not found, skipping: %s", config_file_name)
282 282 except:
283 283 # For testing purposes.
284 284 if not suppress_errors:
285 285 raise
286 286 self.log.warn("Error loading config file: %s" %
287 287 self.config_file_name, exc_info=True)
288 288
289 289 def init_profile_dir(self):
290 290 """initialize the profile dir"""
291 291 self._in_init_profile_dir = True
292 292 if self.profile_dir is not None:
293 293 # already ran
294 294 return
295 295 if 'ProfileDir.location' not in self.config:
296 296 # location not specified, find by profile name
297 297 try:
298 298 p = ProfileDir.find_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
299 299 except ProfileDirError:
300 300 # not found, maybe create it (always create default profile)
301 301 if self.auto_create or self.profile == 'default':
302 302 try:
303 303 p = ProfileDir.create_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
304 304 except ProfileDirError:
305 305 self.log.fatal("Could not create profile: %r"%self.profile)
306 306 self.exit(1)
307 307 else:
308 308 self.log.info("Created profile dir: %r"%p.location)
309 309 else:
310 310 self.log.fatal("Profile %r not found."%self.profile)
311 311 self.exit(1)
312 312 else:
313 313 self.log.debug("Using existing profile dir: %r"%p.location)
314 314 else:
315 315 location = self.config.ProfileDir.location
316 316 # location is fully specified
317 317 try:
318 318 p = ProfileDir.find_profile_dir(location, self.config)
319 319 except ProfileDirError:
320 320 # not found, maybe create it
321 321 if self.auto_create:
322 322 try:
323 323 p = ProfileDir.create_profile_dir(location, self.config)
324 324 except ProfileDirError:
325 325 self.log.fatal("Could not create profile directory: %r"%location)
326 326 self.exit(1)
327 327 else:
328 328 self.log.debug("Creating new profile dir: %r"%location)
329 329 else:
330 330 self.log.fatal("Profile directory %r not found."%location)
331 331 self.exit(1)
332 332 else:
333 333 self.log.info("Using existing profile dir: %r"%location)
334 334 # if profile_dir is specified explicitly, set profile name
335 335 dir_name = os.path.basename(p.location)
336 336 if dir_name.startswith('profile_'):
337 337 self.profile = dir_name[8:]
338 338
339 339 self.profile_dir = p
340 340 self.config_file_paths.append(p.location)
341 341 self._in_init_profile_dir = False
342 342
343 343 def init_config_files(self):
344 344 """[optionally] copy default config files into profile dir."""
345 345 self.config_file_paths.extend(SYSTEM_CONFIG_DIRS)
346 346 # copy config files
347 347 path = self.builtin_profile_dir
348 348 if self.copy_config_files:
349 349 src = self.profile
350 350
351 351 cfg = self.config_file_name
352 352 if path and os.path.exists(os.path.join(path, cfg)):
353 353 self.log.warn("Staging %r from %s into %r [overwrite=%s]"%(
354 354 cfg, src, self.profile_dir.location, self.overwrite)
355 355 )
356 356 self.profile_dir.copy_config_file(cfg, path=path, overwrite=self.overwrite)
357 357 else:
358 358 self.stage_default_config_file()
359 359 else:
360 360 # Still stage *bundled* config files, but not generated ones
361 361 # This is necessary for `ipython profile=sympy` to load the profile
362 362 # on the first go
363 363 files = glob.glob(os.path.join(path, '*.py'))
364 364 for fullpath in files:
365 365 cfg = os.path.basename(fullpath)
366 366 if self.profile_dir.copy_config_file(cfg, path=path, overwrite=False):
367 367 # file was copied
368 368 self.log.warn("Staging bundled %s from %s into %r"%(
369 369 cfg, self.profile, self.profile_dir.location)
370 370 )
371 371
372 372
373 373 def stage_default_config_file(self):
374 374 """auto generate default config file, and stage it into the profile."""
375 375 s = self.generate_config_file()
376 376 fname = os.path.join(self.profile_dir.location, self.config_file_name)
377 377 if self.overwrite or not os.path.exists(fname):
378 378 self.log.warn("Generating default config file: %r"%(fname))
379 379 with open(fname, 'w') as f:
380 380 f.write(s)
381 381
382 382 @catch_config_error
383 383 def initialize(self, argv=None):
384 384 # don't hook up crash handler before parsing command-line
385 385 self.parse_command_line(argv)
386 386 self.init_crash_handler()
387 387 if self.subapp is not None:
388 388 # stop here if subapp is taking over
389 389 return
390 390 cl_config = self.config
391 391 self.init_profile_dir()
392 392 self.init_config_files()
393 393 self.load_config_file()
394 394 # enforce cl-opts override configfile opts:
395 395 self.update_config(cl_config)
396 396
@@ -1,111 +1,112 b''
1 1 """
2 2 A context manager for managing things injected into :mod:`__builtin__`.
3 3
4 4 Authors:
5 5
6 6 * Brian Granger
7 7 * Fernando Perez
8 8 """
9 9 #-----------------------------------------------------------------------------
10 10 # Copyright (C) 2010-2011 The IPython Development Team.
11 11 #
12 12 # Distributed under the terms of the BSD License.
13 13 #
14 14 # Complete license in the file COPYING.txt, distributed with this software.
15 15 #-----------------------------------------------------------------------------
16 16
17 17 #-----------------------------------------------------------------------------
18 18 # Imports
19 19 #-----------------------------------------------------------------------------
20 20
21 21 from IPython.config.configurable import Configurable
22 22
23 23 from IPython.utils.py3compat import builtin_mod, iteritems
24 24 from IPython.utils.traitlets import Instance
25 25
26 26 #-----------------------------------------------------------------------------
27 27 # Classes and functions
28 28 #-----------------------------------------------------------------------------
29 29
30 30 class __BuiltinUndefined(object): pass
31 31 BuiltinUndefined = __BuiltinUndefined()
32 32
33 33 class __HideBuiltin(object): pass
34 34 HideBuiltin = __HideBuiltin()
35 35
36 36
37 37 class BuiltinTrap(Configurable):
38 38
39 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
39 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC',
40 allow_none=True)
40 41
41 42 def __init__(self, shell=None):
42 43 super(BuiltinTrap, self).__init__(shell=shell, config=None)
43 44 self._orig_builtins = {}
44 45 # We define this to track if a single BuiltinTrap is nested.
45 46 # Only turn off the trap when the outermost call to __exit__ is made.
46 47 self._nested_level = 0
47 48 self.shell = shell
48 49 # builtins we always add - if set to HideBuiltin, they will just
49 50 # be removed instead of being replaced by something else
50 51 self.auto_builtins = {'exit': HideBuiltin,
51 52 'quit': HideBuiltin,
52 53 'get_ipython': self.shell.get_ipython,
53 54 }
54 55 # Recursive reload function
55 56 try:
56 57 from IPython.lib import deepreload
57 58 if self.shell.deep_reload:
58 59 self.auto_builtins['reload'] = deepreload.reload
59 60 else:
60 61 self.auto_builtins['dreload']= deepreload.reload
61 62 except ImportError:
62 63 pass
63 64
64 65 def __enter__(self):
65 66 if self._nested_level == 0:
66 67 self.activate()
67 68 self._nested_level += 1
68 69 # I return self, so callers can use add_builtin in a with clause.
69 70 return self
70 71
71 72 def __exit__(self, type, value, traceback):
72 73 if self._nested_level == 1:
73 74 self.deactivate()
74 75 self._nested_level -= 1
75 76 # Returning False will cause exceptions to propagate
76 77 return False
77 78
78 79 def add_builtin(self, key, value):
79 80 """Add a builtin and save the original."""
80 81 bdict = builtin_mod.__dict__
81 82 orig = bdict.get(key, BuiltinUndefined)
82 83 if value is HideBuiltin:
83 84 if orig is not BuiltinUndefined: #same as 'key in bdict'
84 85 self._orig_builtins[key] = orig
85 86 del bdict[key]
86 87 else:
87 88 self._orig_builtins[key] = orig
88 89 bdict[key] = value
89 90
90 91 def remove_builtin(self, key, orig):
91 92 """Remove an added builtin and re-set the original."""
92 93 if orig is BuiltinUndefined:
93 94 del builtin_mod.__dict__[key]
94 95 else:
95 96 builtin_mod.__dict__[key] = orig
96 97
97 98 def activate(self):
98 99 """Store ipython references in the __builtin__ namespace."""
99 100
100 101 add_builtin = self.add_builtin
101 102 for name, func in iteritems(self.auto_builtins):
102 103 add_builtin(name, func)
103 104
104 105 def deactivate(self):
105 106 """Remove any builtins which might have been added by add_builtins, or
106 107 restore overwritten ones to their previous values."""
107 108 remove_builtin = self.remove_builtin
108 109 for key, val in iteritems(self._orig_builtins):
109 110 remove_builtin(key, val)
110 111 self._orig_builtins.clear()
111 112 self._builtins_added = False
@@ -1,282 +1,283 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Displayhook for IPython.
3 3
4 4 This defines a callable class that IPython uses for `sys.displayhook`.
5 5 """
6 6
7 7 # Copyright (c) IPython Development Team.
8 8 # Distributed under the terms of the Modified BSD License.
9 9
10 10 from __future__ import print_function
11 11
12 12 import sys
13 13
14 14 from IPython.core.formatters import _safe_get_formatter_method
15 15 from IPython.config.configurable import Configurable
16 16 from IPython.utils import io
17 17 from IPython.utils.py3compat import builtin_mod
18 18 from IPython.utils.traitlets import Instance, Float
19 19 from IPython.utils.warn import warn
20 20
21 21 # TODO: Move the various attributes (cache_size, [others now moved]). Some
22 22 # of these are also attributes of InteractiveShell. They should be on ONE object
23 23 # only and the other objects should ask that one object for their values.
24 24
25 25 class DisplayHook(Configurable):
26 26 """The custom IPython displayhook to replace sys.displayhook.
27 27
28 28 This class does many things, but the basic idea is that it is a callable
29 29 that gets called anytime user code returns a value.
30 30 """
31 31
32 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
32 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC',
33 allow_none=True)
33 34 exec_result = Instance('IPython.core.interactiveshell.ExecutionResult',
34 35 allow_none=True)
35 36 cull_fraction = Float(0.2)
36 37
37 38 def __init__(self, shell=None, cache_size=1000, **kwargs):
38 39 super(DisplayHook, self).__init__(shell=shell, **kwargs)
39 40 cache_size_min = 3
40 41 if cache_size <= 0:
41 42 self.do_full_cache = 0
42 43 cache_size = 0
43 44 elif cache_size < cache_size_min:
44 45 self.do_full_cache = 0
45 46 cache_size = 0
46 47 warn('caching was disabled (min value for cache size is %s).' %
47 48 cache_size_min,level=3)
48 49 else:
49 50 self.do_full_cache = 1
50 51
51 52 self.cache_size = cache_size
52 53
53 54 # we need a reference to the user-level namespace
54 55 self.shell = shell
55 56
56 57 self._,self.__,self.___ = '','',''
57 58
58 59 # these are deliberately global:
59 60 to_user_ns = {'_':self._,'__':self.__,'___':self.___}
60 61 self.shell.user_ns.update(to_user_ns)
61 62
62 63 @property
63 64 def prompt_count(self):
64 65 return self.shell.execution_count
65 66
66 67 #-------------------------------------------------------------------------
67 68 # Methods used in __call__. Override these methods to modify the behavior
68 69 # of the displayhook.
69 70 #-------------------------------------------------------------------------
70 71
71 72 def check_for_underscore(self):
72 73 """Check if the user has set the '_' variable by hand."""
73 74 # If something injected a '_' variable in __builtin__, delete
74 75 # ipython's automatic one so we don't clobber that. gettext() in
75 76 # particular uses _, so we need to stay away from it.
76 77 if '_' in builtin_mod.__dict__:
77 78 try:
78 79 del self.shell.user_ns['_']
79 80 except KeyError:
80 81 pass
81 82
82 83 def quiet(self):
83 84 """Should we silence the display hook because of ';'?"""
84 85 # do not print output if input ends in ';'
85 86 try:
86 87 cell = self.shell.history_manager.input_hist_parsed[self.prompt_count]
87 88 return cell.rstrip().endswith(';')
88 89 except IndexError:
89 90 # some uses of ipshellembed may fail here
90 91 return False
91 92
92 93 def start_displayhook(self):
93 94 """Start the displayhook, initializing resources."""
94 95 pass
95 96
96 97 def write_output_prompt(self):
97 98 """Write the output prompt.
98 99
99 100 The default implementation simply writes the prompt to
100 101 ``io.stdout``.
101 102 """
102 103 # Use write, not print which adds an extra space.
103 104 io.stdout.write(self.shell.separate_out)
104 105 outprompt = self.shell.prompt_manager.render('out')
105 106 if self.do_full_cache:
106 107 io.stdout.write(outprompt)
107 108
108 109 def compute_format_data(self, result):
109 110 """Compute format data of the object to be displayed.
110 111
111 112 The format data is a generalization of the :func:`repr` of an object.
112 113 In the default implementation the format data is a :class:`dict` of
113 114 key value pair where the keys are valid MIME types and the values
114 115 are JSON'able data structure containing the raw data for that MIME
115 116 type. It is up to frontends to determine pick a MIME to to use and
116 117 display that data in an appropriate manner.
117 118
118 119 This method only computes the format data for the object and should
119 120 NOT actually print or write that to a stream.
120 121
121 122 Parameters
122 123 ----------
123 124 result : object
124 125 The Python object passed to the display hook, whose format will be
125 126 computed.
126 127
127 128 Returns
128 129 -------
129 130 (format_dict, md_dict) : dict
130 131 format_dict is a :class:`dict` whose keys are valid MIME types and values are
131 132 JSON'able raw data for that MIME type. It is recommended that
132 133 all return values of this should always include the "text/plain"
133 134 MIME type representation of the object.
134 135 md_dict is a :class:`dict` with the same MIME type keys
135 136 of metadata associated with each output.
136 137
137 138 """
138 139 return self.shell.display_formatter.format(result)
139 140
140 141 def write_format_data(self, format_dict, md_dict=None):
141 142 """Write the format data dict to the frontend.
142 143
143 144 This default version of this method simply writes the plain text
144 145 representation of the object to ``io.stdout``. Subclasses should
145 146 override this method to send the entire `format_dict` to the
146 147 frontends.
147 148
148 149 Parameters
149 150 ----------
150 151 format_dict : dict
151 152 The format dict for the object passed to `sys.displayhook`.
152 153 md_dict : dict (optional)
153 154 The metadata dict to be associated with the display data.
154 155 """
155 156 if 'text/plain' not in format_dict:
156 157 # nothing to do
157 158 return
158 159 # We want to print because we want to always make sure we have a
159 160 # newline, even if all the prompt separators are ''. This is the
160 161 # standard IPython behavior.
161 162 result_repr = format_dict['text/plain']
162 163 if '\n' in result_repr:
163 164 # So that multi-line strings line up with the left column of
164 165 # the screen, instead of having the output prompt mess up
165 166 # their first line.
166 167 # We use the prompt template instead of the expanded prompt
167 168 # because the expansion may add ANSI escapes that will interfere
168 169 # with our ability to determine whether or not we should add
169 170 # a newline.
170 171 prompt_template = self.shell.prompt_manager.out_template
171 172 if prompt_template and not prompt_template.endswith('\n'):
172 173 # But avoid extraneous empty lines.
173 174 result_repr = '\n' + result_repr
174 175
175 176 print(result_repr, file=io.stdout)
176 177
177 178 def update_user_ns(self, result):
178 179 """Update user_ns with various things like _, __, _1, etc."""
179 180
180 181 # Avoid recursive reference when displaying _oh/Out
181 182 if result is not self.shell.user_ns['_oh']:
182 183 if len(self.shell.user_ns['_oh']) >= self.cache_size and self.do_full_cache:
183 184 self.cull_cache()
184 185 # Don't overwrite '_' and friends if '_' is in __builtin__ (otherwise
185 186 # we cause buggy behavior for things like gettext).
186 187
187 188 if '_' not in builtin_mod.__dict__:
188 189 self.___ = self.__
189 190 self.__ = self._
190 191 self._ = result
191 192 self.shell.push({'_':self._,
192 193 '__':self.__,
193 194 '___':self.___}, interactive=False)
194 195
195 196 # hackish access to top-level namespace to create _1,_2... dynamically
196 197 to_main = {}
197 198 if self.do_full_cache:
198 199 new_result = '_'+repr(self.prompt_count)
199 200 to_main[new_result] = result
200 201 self.shell.push(to_main, interactive=False)
201 202 self.shell.user_ns['_oh'][self.prompt_count] = result
202 203
203 204 def fill_exec_result(self, result):
204 205 if self.exec_result is not None:
205 206 self.exec_result.result = result
206 207
207 208 def log_output(self, format_dict):
208 209 """Log the output."""
209 210 if 'text/plain' not in format_dict:
210 211 # nothing to do
211 212 return
212 213 if self.shell.logger.log_output:
213 214 self.shell.logger.log_write(format_dict['text/plain'], 'output')
214 215 self.shell.history_manager.output_hist_reprs[self.prompt_count] = \
215 216 format_dict['text/plain']
216 217
217 218 def finish_displayhook(self):
218 219 """Finish up all displayhook activities."""
219 220 io.stdout.write(self.shell.separate_out2)
220 221 io.stdout.flush()
221 222
222 223 def __call__(self, result=None):
223 224 """Printing with history cache management.
224 225
225 226 This is invoked everytime the interpreter needs to print, and is
226 227 activated by setting the variable sys.displayhook to it.
227 228 """
228 229 self.check_for_underscore()
229 230 if result is not None and not self.quiet():
230 231 self.start_displayhook()
231 232 self.write_output_prompt()
232 233 format_dict, md_dict = self.compute_format_data(result)
233 234 self.update_user_ns(result)
234 235 self.fill_exec_result(result)
235 236 if format_dict:
236 237 self.write_format_data(format_dict, md_dict)
237 238 self.log_output(format_dict)
238 239 self.finish_displayhook()
239 240
240 241 def cull_cache(self):
241 242 """Output cache is full, cull the oldest entries"""
242 243 oh = self.shell.user_ns.get('_oh', {})
243 244 sz = len(oh)
244 245 cull_count = max(int(sz * self.cull_fraction), 2)
245 246 warn('Output cache limit (currently {sz} entries) hit.\n'
246 247 'Flushing oldest {cull_count} entries.'.format(sz=sz, cull_count=cull_count))
247 248
248 249 for i, n in enumerate(sorted(oh)):
249 250 if i >= cull_count:
250 251 break
251 252 self.shell.user_ns.pop('_%i' % n, None)
252 253 oh.pop(n, None)
253 254
254 255
255 256 def flush(self):
256 257 if not self.do_full_cache:
257 258 raise ValueError("You shouldn't have reached the cache flush "
258 259 "if full caching is not enabled!")
259 260 # delete auto-generated vars from global namespace
260 261
261 262 for n in range(1,self.prompt_count + 1):
262 263 key = '_'+repr(n)
263 264 try:
264 265 del self.shell.user_ns[key]
265 266 except: pass
266 267 # In some embedded circumstances, the user_ns doesn't have the
267 268 # '_oh' key set up.
268 269 oh = self.shell.user_ns.get('_oh', None)
269 270 if oh is not None:
270 271 oh.clear()
271 272
272 273 # Release our own references to objects:
273 274 self._, self.__, self.___ = '', '', ''
274 275
275 276 if '_' not in builtin_mod.__dict__:
276 277 self.shell.user_ns.update({'_':None,'__':None, '___':None})
277 278 import gc
278 279 # TODO: Is this really needed?
279 280 # IronPython blocks here forever
280 281 if sys.platform != "cli":
281 282 gc.collect()
282 283
@@ -1,175 +1,176 b''
1 1 # encoding: utf-8
2 2 """A class for managing IPython extensions."""
3 3
4 4 # Copyright (c) IPython Development Team.
5 5 # Distributed under the terms of the Modified BSD License.
6 6
7 7 import os
8 8 from shutil import copyfile
9 9 import sys
10 10
11 11 from IPython.config.configurable import Configurable
12 12 from IPython.utils.path import ensure_dir_exists
13 13 from IPython.utils.traitlets import Instance
14 14 from IPython.utils.py3compat import PY3
15 15 if PY3:
16 16 from imp import reload
17 17
18 18 #-----------------------------------------------------------------------------
19 19 # Main class
20 20 #-----------------------------------------------------------------------------
21 21
22 22 class ExtensionManager(Configurable):
23 23 """A class to manage IPython extensions.
24 24
25 25 An IPython extension is an importable Python module that has
26 26 a function with the signature::
27 27
28 28 def load_ipython_extension(ipython):
29 29 # Do things with ipython
30 30
31 31 This function is called after your extension is imported and the
32 32 currently active :class:`InteractiveShell` instance is passed as
33 33 the only argument. You can do anything you want with IPython at
34 34 that point, including defining new magic and aliases, adding new
35 35 components, etc.
36 36
37 37 You can also optionally define an :func:`unload_ipython_extension(ipython)`
38 38 function, which will be called if the user unloads or reloads the extension.
39 39 The extension manager will only call :func:`load_ipython_extension` again
40 40 if the extension is reloaded.
41 41
42 42 You can put your extension modules anywhere you want, as long as
43 43 they can be imported by Python's standard import mechanism. However,
44 44 to make it easy to write extensions, you can also put your extensions
45 45 in ``os.path.join(self.ipython_dir, 'extensions')``. This directory
46 46 is added to ``sys.path`` automatically.
47 47 """
48 48
49 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
49 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC',
50 allow_none=True)
50 51
51 52 def __init__(self, shell=None, **kwargs):
52 53 super(ExtensionManager, self).__init__(shell=shell, **kwargs)
53 54 self.shell.on_trait_change(
54 55 self._on_ipython_dir_changed, 'ipython_dir'
55 56 )
56 57 self.loaded = set()
57 58
58 59 def __del__(self):
59 60 self.shell.on_trait_change(
60 61 self._on_ipython_dir_changed, 'ipython_dir', remove=True
61 62 )
62 63
63 64 @property
64 65 def ipython_extension_dir(self):
65 66 return os.path.join(self.shell.ipython_dir, u'extensions')
66 67
67 68 def _on_ipython_dir_changed(self):
68 69 ensure_dir_exists(self.ipython_extension_dir)
69 70
70 71 def load_extension(self, module_str):
71 72 """Load an IPython extension by its module name.
72 73
73 74 Returns the string "already loaded" if the extension is already loaded,
74 75 "no load function" if the module doesn't have a load_ipython_extension
75 76 function, or None if it succeeded.
76 77 """
77 78 if module_str in self.loaded:
78 79 return "already loaded"
79 80
80 81 from IPython.utils.syspathcontext import prepended_to_syspath
81 82
82 83 with self.shell.builtin_trap:
83 84 if module_str not in sys.modules:
84 85 with prepended_to_syspath(self.ipython_extension_dir):
85 86 __import__(module_str)
86 87 mod = sys.modules[module_str]
87 88 if self._call_load_ipython_extension(mod):
88 89 self.loaded.add(module_str)
89 90 else:
90 91 return "no load function"
91 92
92 93 def unload_extension(self, module_str):
93 94 """Unload an IPython extension by its module name.
94 95
95 96 This function looks up the extension's name in ``sys.modules`` and
96 97 simply calls ``mod.unload_ipython_extension(self)``.
97 98
98 99 Returns the string "no unload function" if the extension doesn't define
99 100 a function to unload itself, "not loaded" if the extension isn't loaded,
100 101 otherwise None.
101 102 """
102 103 if module_str not in self.loaded:
103 104 return "not loaded"
104 105
105 106 if module_str in sys.modules:
106 107 mod = sys.modules[module_str]
107 108 if self._call_unload_ipython_extension(mod):
108 109 self.loaded.discard(module_str)
109 110 else:
110 111 return "no unload function"
111 112
112 113 def reload_extension(self, module_str):
113 114 """Reload an IPython extension by calling reload.
114 115
115 116 If the module has not been loaded before,
116 117 :meth:`InteractiveShell.load_extension` is called. Otherwise
117 118 :func:`reload` is called and then the :func:`load_ipython_extension`
118 119 function of the module, if it exists is called.
119 120 """
120 121 from IPython.utils.syspathcontext import prepended_to_syspath
121 122
122 123 if (module_str in self.loaded) and (module_str in sys.modules):
123 124 self.unload_extension(module_str)
124 125 mod = sys.modules[module_str]
125 126 with prepended_to_syspath(self.ipython_extension_dir):
126 127 reload(mod)
127 128 if self._call_load_ipython_extension(mod):
128 129 self.loaded.add(module_str)
129 130 else:
130 131 self.load_extension(module_str)
131 132
132 133 def _call_load_ipython_extension(self, mod):
133 134 if hasattr(mod, 'load_ipython_extension'):
134 135 mod.load_ipython_extension(self.shell)
135 136 return True
136 137
137 138 def _call_unload_ipython_extension(self, mod):
138 139 if hasattr(mod, 'unload_ipython_extension'):
139 140 mod.unload_ipython_extension(self.shell)
140 141 return True
141 142
142 143 def install_extension(self, url, filename=None):
143 144 """Download and install an IPython extension.
144 145
145 146 If filename is given, the file will be so named (inside the extension
146 147 directory). Otherwise, the name from the URL will be used. The file must
147 148 have a .py or .zip extension; otherwise, a ValueError will be raised.
148 149
149 150 Returns the full path to the installed file.
150 151 """
151 152 # Ensure the extension directory exists
152 153 ensure_dir_exists(self.ipython_extension_dir)
153 154
154 155 if os.path.isfile(url):
155 156 src_filename = os.path.basename(url)
156 157 copy = copyfile
157 158 else:
158 159 # Deferred imports
159 160 try:
160 161 from urllib.parse import urlparse # Py3
161 162 from urllib.request import urlretrieve
162 163 except ImportError:
163 164 from urlparse import urlparse
164 165 from urllib import urlretrieve
165 166 src_filename = urlparse(url).path.split('/')[-1]
166 167 copy = urlretrieve
167 168
168 169 if filename is None:
169 170 filename = src_filename
170 171 if os.path.splitext(filename)[1] not in ('.py', '.zip'):
171 172 raise ValueError("The file must have a .py or .zip extension", filename)
172 173
173 174 filename = os.path.join(self.ipython_extension_dir, filename)
174 175 copy(url, filename)
175 176 return filename
@@ -1,870 +1,872 b''
1 1 """ History related magics and functionality """
2 2 #-----------------------------------------------------------------------------
3 3 # Copyright (C) 2010-2011 The IPython Development Team.
4 4 #
5 5 # Distributed under the terms of the BSD License.
6 6 #
7 7 # The full license is in the file COPYING.txt, distributed with this software.
8 8 #-----------------------------------------------------------------------------
9 9
10 10 #-----------------------------------------------------------------------------
11 11 # Imports
12 12 #-----------------------------------------------------------------------------
13 13 from __future__ import print_function
14 14
15 15 # Stdlib imports
16 16 import atexit
17 17 import datetime
18 18 import os
19 19 import re
20 20 try:
21 21 import sqlite3
22 22 except ImportError:
23 23 try:
24 24 from pysqlite2 import dbapi2 as sqlite3
25 25 except ImportError:
26 26 sqlite3 = None
27 27 import threading
28 28
29 29 # Our own packages
30 30 from IPython.config.configurable import Configurable
31 31 from decorator import decorator
32 32 from IPython.utils.decorators import undoc
33 33 from IPython.utils.path import locate_profile
34 34 from IPython.utils import py3compat
35 35 from IPython.utils.traitlets import (
36 36 Any, Bool, Dict, Instance, Integer, List, Unicode, TraitError,
37 37 )
38 38 from IPython.utils.warn import warn
39 39
40 40 #-----------------------------------------------------------------------------
41 41 # Classes and functions
42 42 #-----------------------------------------------------------------------------
43 43
44 44 @undoc
45 45 class DummyDB(object):
46 46 """Dummy DB that will act as a black hole for history.
47 47
48 48 Only used in the absence of sqlite"""
49 49 def execute(*args, **kwargs):
50 50 return []
51 51
52 52 def commit(self, *args, **kwargs):
53 53 pass
54 54
55 55 def __enter__(self, *args, **kwargs):
56 56 pass
57 57
58 58 def __exit__(self, *args, **kwargs):
59 59 pass
60 60
61 61
62 62 @decorator
63 63 def needs_sqlite(f, self, *a, **kw):
64 64 """Decorator: return an empty list in the absence of sqlite."""
65 65 if sqlite3 is None or not self.enabled:
66 66 return []
67 67 else:
68 68 return f(self, *a, **kw)
69 69
70 70
71 71 if sqlite3 is not None:
72 72 DatabaseError = sqlite3.DatabaseError
73 73 else:
74 74 @undoc
75 75 class DatabaseError(Exception):
76 76 "Dummy exception when sqlite could not be imported. Should never occur."
77 77
78 78 @decorator
79 79 def catch_corrupt_db(f, self, *a, **kw):
80 80 """A decorator which wraps HistoryAccessor method calls to catch errors from
81 81 a corrupt SQLite database, move the old database out of the way, and create
82 82 a new one.
83 83 """
84 84 try:
85 85 return f(self, *a, **kw)
86 86 except DatabaseError:
87 87 if os.path.isfile(self.hist_file):
88 88 # Try to move the file out of the way
89 89 base,ext = os.path.splitext(self.hist_file)
90 90 newpath = base + '-corrupt' + ext
91 91 os.rename(self.hist_file, newpath)
92 92 self.init_db()
93 93 print("ERROR! History file wasn't a valid SQLite database.",
94 94 "It was moved to %s" % newpath, "and a new file created.")
95 95 return []
96 96
97 97 else:
98 98 # The hist_file is probably :memory: or something else.
99 99 raise
100 100
101 101 class HistoryAccessorBase(Configurable):
102 102 """An abstract class for History Accessors """
103 103
104 104 def get_tail(self, n=10, raw=True, output=False, include_latest=False):
105 105 raise NotImplementedError
106 106
107 107 def search(self, pattern="*", raw=True, search_raw=True,
108 108 output=False, n=None, unique=False):
109 109 raise NotImplementedError
110 110
111 111 def get_range(self, session, start=1, stop=None, raw=True,output=False):
112 112 raise NotImplementedError
113 113
114 114 def get_range_by_str(self, rangestr, raw=True, output=False):
115 115 raise NotImplementedError
116 116
117 117
118 118 class HistoryAccessor(HistoryAccessorBase):
119 119 """Access the history database without adding to it.
120 120
121 121 This is intended for use by standalone history tools. IPython shells use
122 122 HistoryManager, below, which is a subclass of this."""
123 123
124 124 # String holding the path to the history file
125 125 hist_file = Unicode(config=True,
126 126 help="""Path to file to use for SQLite history database.
127 127
128 128 By default, IPython will put the history database in the IPython
129 129 profile directory. If you would rather share one history among
130 130 profiles, you can set this value in each, so that they are consistent.
131 131
132 132 Due to an issue with fcntl, SQLite is known to misbehave on some NFS
133 133 mounts. If you see IPython hanging, try setting this to something on a
134 134 local disk, e.g::
135 135
136 136 ipython --HistoryManager.hist_file=/tmp/ipython_hist.sqlite
137 137
138 138 """)
139 139
140 140 enabled = Bool(True, config=True,
141 141 help="""enable the SQLite history
142 142
143 143 set enabled=False to disable the SQLite history,
144 144 in which case there will be no stored history, no SQLite connection,
145 145 and no background saving thread. This may be necessary in some
146 146 threaded environments where IPython is embedded.
147 147 """
148 148 )
149 149
150 150 connection_options = Dict(config=True,
151 151 help="""Options for configuring the SQLite connection
152 152
153 153 These options are passed as keyword args to sqlite3.connect
154 154 when establishing database conenctions.
155 155 """
156 156 )
157 157
158 158 # The SQLite database
159 159 db = Any()
160 160 def _db_changed(self, name, old, new):
161 161 """validate the db, since it can be an Instance of two different types"""
162 162 connection_types = (DummyDB,)
163 163 if sqlite3 is not None:
164 164 connection_types = (DummyDB, sqlite3.Connection)
165 165 if not isinstance(new, connection_types):
166 166 msg = "%s.db must be sqlite3 Connection or DummyDB, not %r" % \
167 167 (self.__class__.__name__, new)
168 168 raise TraitError(msg)
169 169
170 170 def __init__(self, profile='default', hist_file=u'', **traits):
171 171 """Create a new history accessor.
172 172
173 173 Parameters
174 174 ----------
175 175 profile : str
176 176 The name of the profile from which to open history.
177 177 hist_file : str
178 178 Path to an SQLite history database stored by IPython. If specified,
179 179 hist_file overrides profile.
180 180 config : :class:`~IPython.config.loader.Config`
181 181 Config object. hist_file can also be set through this.
182 182 """
183 183 # We need a pointer back to the shell for various tasks.
184 184 super(HistoryAccessor, self).__init__(**traits)
185 185 # defer setting hist_file from kwarg until after init,
186 186 # otherwise the default kwarg value would clobber any value
187 187 # set by config
188 188 if hist_file:
189 189 self.hist_file = hist_file
190 190
191 191 if self.hist_file == u'':
192 192 # No one has set the hist_file, yet.
193 193 self.hist_file = self._get_hist_file_name(profile)
194 194
195 195 if sqlite3 is None and self.enabled:
196 196 warn("IPython History requires SQLite, your history will not be saved")
197 197 self.enabled = False
198 198
199 199 self.init_db()
200 200
201 201 def _get_hist_file_name(self, profile='default'):
202 202 """Find the history file for the given profile name.
203 203
204 204 This is overridden by the HistoryManager subclass, to use the shell's
205 205 active profile.
206 206
207 207 Parameters
208 208 ----------
209 209 profile : str
210 210 The name of a profile which has a history file.
211 211 """
212 212 return os.path.join(locate_profile(profile), 'history.sqlite')
213 213
214 214 @catch_corrupt_db
215 215 def init_db(self):
216 216 """Connect to the database, and create tables if necessary."""
217 217 if not self.enabled:
218 218 self.db = DummyDB()
219 219 return
220 220
221 221 # use detect_types so that timestamps return datetime objects
222 222 kwargs = dict(detect_types=sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES)
223 223 kwargs.update(self.connection_options)
224 224 self.db = sqlite3.connect(self.hist_file, **kwargs)
225 225 self.db.execute("""CREATE TABLE IF NOT EXISTS sessions (session integer
226 226 primary key autoincrement, start timestamp,
227 227 end timestamp, num_cmds integer, remark text)""")
228 228 self.db.execute("""CREATE TABLE IF NOT EXISTS history
229 229 (session integer, line integer, source text, source_raw text,
230 230 PRIMARY KEY (session, line))""")
231 231 # Output history is optional, but ensure the table's there so it can be
232 232 # enabled later.
233 233 self.db.execute("""CREATE TABLE IF NOT EXISTS output_history
234 234 (session integer, line integer, output text,
235 235 PRIMARY KEY (session, line))""")
236 236 self.db.commit()
237 237
238 238 def writeout_cache(self):
239 239 """Overridden by HistoryManager to dump the cache before certain
240 240 database lookups."""
241 241 pass
242 242
243 243 ## -------------------------------
244 244 ## Methods for retrieving history:
245 245 ## -------------------------------
246 246 def _run_sql(self, sql, params, raw=True, output=False):
247 247 """Prepares and runs an SQL query for the history database.
248 248
249 249 Parameters
250 250 ----------
251 251 sql : str
252 252 Any filtering expressions to go after SELECT ... FROM ...
253 253 params : tuple
254 254 Parameters passed to the SQL query (to replace "?")
255 255 raw, output : bool
256 256 See :meth:`get_range`
257 257
258 258 Returns
259 259 -------
260 260 Tuples as :meth:`get_range`
261 261 """
262 262 toget = 'source_raw' if raw else 'source'
263 263 sqlfrom = "history"
264 264 if output:
265 265 sqlfrom = "history LEFT JOIN output_history USING (session, line)"
266 266 toget = "history.%s, output_history.output" % toget
267 267 cur = self.db.execute("SELECT session, line, %s FROM %s " %\
268 268 (toget, sqlfrom) + sql, params)
269 269 if output: # Regroup into 3-tuples, and parse JSON
270 270 return ((ses, lin, (inp, out)) for ses, lin, inp, out in cur)
271 271 return cur
272 272
273 273 @needs_sqlite
274 274 @catch_corrupt_db
275 275 def get_session_info(self, session):
276 276 """Get info about a session.
277 277
278 278 Parameters
279 279 ----------
280 280
281 281 session : int
282 282 Session number to retrieve.
283 283
284 284 Returns
285 285 -------
286 286
287 287 session_id : int
288 288 Session ID number
289 289 start : datetime
290 290 Timestamp for the start of the session.
291 291 end : datetime
292 292 Timestamp for the end of the session, or None if IPython crashed.
293 293 num_cmds : int
294 294 Number of commands run, or None if IPython crashed.
295 295 remark : unicode
296 296 A manually set description.
297 297 """
298 298 query = "SELECT * from sessions where session == ?"
299 299 return self.db.execute(query, (session,)).fetchone()
300 300
301 301 @catch_corrupt_db
302 302 def get_last_session_id(self):
303 303 """Get the last session ID currently in the database.
304 304
305 305 Within IPython, this should be the same as the value stored in
306 306 :attr:`HistoryManager.session_number`.
307 307 """
308 308 for record in self.get_tail(n=1, include_latest=True):
309 309 return record[0]
310 310
311 311 @catch_corrupt_db
312 312 def get_tail(self, n=10, raw=True, output=False, include_latest=False):
313 313 """Get the last n lines from the history database.
314 314
315 315 Parameters
316 316 ----------
317 317 n : int
318 318 The number of lines to get
319 319 raw, output : bool
320 320 See :meth:`get_range`
321 321 include_latest : bool
322 322 If False (default), n+1 lines are fetched, and the latest one
323 323 is discarded. This is intended to be used where the function
324 324 is called by a user command, which it should not return.
325 325
326 326 Returns
327 327 -------
328 328 Tuples as :meth:`get_range`
329 329 """
330 330 self.writeout_cache()
331 331 if not include_latest:
332 332 n += 1
333 333 cur = self._run_sql("ORDER BY session DESC, line DESC LIMIT ?",
334 334 (n,), raw=raw, output=output)
335 335 if not include_latest:
336 336 return reversed(list(cur)[1:])
337 337 return reversed(list(cur))
338 338
339 339 @catch_corrupt_db
340 340 def search(self, pattern="*", raw=True, search_raw=True,
341 341 output=False, n=None, unique=False):
342 342 """Search the database using unix glob-style matching (wildcards
343 343 * and ?).
344 344
345 345 Parameters
346 346 ----------
347 347 pattern : str
348 348 The wildcarded pattern to match when searching
349 349 search_raw : bool
350 350 If True, search the raw input, otherwise, the parsed input
351 351 raw, output : bool
352 352 See :meth:`get_range`
353 353 n : None or int
354 354 If an integer is given, it defines the limit of
355 355 returned entries.
356 356 unique : bool
357 357 When it is true, return only unique entries.
358 358
359 359 Returns
360 360 -------
361 361 Tuples as :meth:`get_range`
362 362 """
363 363 tosearch = "source_raw" if search_raw else "source"
364 364 if output:
365 365 tosearch = "history." + tosearch
366 366 self.writeout_cache()
367 367 sqlform = "WHERE %s GLOB ?" % tosearch
368 368 params = (pattern,)
369 369 if unique:
370 370 sqlform += ' GROUP BY {0}'.format(tosearch)
371 371 if n is not None:
372 372 sqlform += " ORDER BY session DESC, line DESC LIMIT ?"
373 373 params += (n,)
374 374 elif unique:
375 375 sqlform += " ORDER BY session, line"
376 376 cur = self._run_sql(sqlform, params, raw=raw, output=output)
377 377 if n is not None:
378 378 return reversed(list(cur))
379 379 return cur
380 380
381 381 @catch_corrupt_db
382 382 def get_range(self, session, start=1, stop=None, raw=True,output=False):
383 383 """Retrieve input by session.
384 384
385 385 Parameters
386 386 ----------
387 387 session : int
388 388 Session number to retrieve.
389 389 start : int
390 390 First line to retrieve.
391 391 stop : int
392 392 End of line range (excluded from output itself). If None, retrieve
393 393 to the end of the session.
394 394 raw : bool
395 395 If True, return untranslated input
396 396 output : bool
397 397 If True, attempt to include output. This will be 'real' Python
398 398 objects for the current session, or text reprs from previous
399 399 sessions if db_log_output was enabled at the time. Where no output
400 400 is found, None is used.
401 401
402 402 Returns
403 403 -------
404 404 entries
405 405 An iterator over the desired lines. Each line is a 3-tuple, either
406 406 (session, line, input) if output is False, or
407 407 (session, line, (input, output)) if output is True.
408 408 """
409 409 if stop:
410 410 lineclause = "line >= ? AND line < ?"
411 411 params = (session, start, stop)
412 412 else:
413 413 lineclause = "line>=?"
414 414 params = (session, start)
415 415
416 416 return self._run_sql("WHERE session==? AND %s" % lineclause,
417 417 params, raw=raw, output=output)
418 418
419 419 def get_range_by_str(self, rangestr, raw=True, output=False):
420 420 """Get lines of history from a string of ranges, as used by magic
421 421 commands %hist, %save, %macro, etc.
422 422
423 423 Parameters
424 424 ----------
425 425 rangestr : str
426 426 A string specifying ranges, e.g. "5 ~2/1-4". See
427 427 :func:`magic_history` for full details.
428 428 raw, output : bool
429 429 As :meth:`get_range`
430 430
431 431 Returns
432 432 -------
433 433 Tuples as :meth:`get_range`
434 434 """
435 435 for sess, s, e in extract_hist_ranges(rangestr):
436 436 for line in self.get_range(sess, s, e, raw=raw, output=output):
437 437 yield line
438 438
439 439
440 440 class HistoryManager(HistoryAccessor):
441 441 """A class to organize all history-related functionality in one place.
442 442 """
443 443 # Public interface
444 444
445 445 # An instance of the IPython shell we are attached to
446 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
446 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC',
447 allow_none=True)
447 448 # Lists to hold processed and raw history. These start with a blank entry
448 449 # so that we can index them starting from 1
449 450 input_hist_parsed = List([""])
450 451 input_hist_raw = List([""])
451 452 # A list of directories visited during session
452 453 dir_hist = List()
453 454 def _dir_hist_default(self):
454 455 try:
455 456 return [py3compat.getcwd()]
456 457 except OSError:
457 458 return []
458 459
459 460 # A dict of output history, keyed with ints from the shell's
460 461 # execution count.
461 462 output_hist = Dict()
462 463 # The text/plain repr of outputs.
463 464 output_hist_reprs = Dict()
464 465
465 466 # The number of the current session in the history database
466 467 session_number = Integer()
467 468
468 469 db_log_output = Bool(False, config=True,
469 470 help="Should the history database include output? (default: no)"
470 471 )
471 472 db_cache_size = Integer(0, config=True,
472 473 help="Write to database every x commands (higher values save disk access & power).\n"
473 474 "Values of 1 or less effectively disable caching."
474 475 )
475 476 # The input and output caches
476 477 db_input_cache = List()
477 478 db_output_cache = List()
478 479
479 480 # History saving in separate thread
480 save_thread = Instance('IPython.core.history.HistorySavingThread')
481 save_thread = Instance('IPython.core.history.HistorySavingThread',
482 allow_none=True)
481 483 try: # Event is a function returning an instance of _Event...
482 save_flag = Instance(threading._Event)
484 save_flag = Instance(threading._Event, allow_none=True)
483 485 except AttributeError: # ...until Python 3.3, when it's a class.
484 save_flag = Instance(threading.Event)
486 save_flag = Instance(threading.Event, allow_none=True)
485 487
486 488 # Private interface
487 489 # Variables used to store the three last inputs from the user. On each new
488 490 # history update, we populate the user's namespace with these, shifted as
489 491 # necessary.
490 492 _i00 = Unicode(u'')
491 493 _i = Unicode(u'')
492 494 _ii = Unicode(u'')
493 495 _iii = Unicode(u'')
494 496
495 497 # A regex matching all forms of the exit command, so that we don't store
496 498 # them in the history (it's annoying to rewind the first entry and land on
497 499 # an exit call).
498 500 _exit_re = re.compile(r"(exit|quit)(\s*\(.*\))?$")
499 501
500 502 def __init__(self, shell=None, config=None, **traits):
501 503 """Create a new history manager associated with a shell instance.
502 504 """
503 505 # We need a pointer back to the shell for various tasks.
504 506 super(HistoryManager, self).__init__(shell=shell, config=config,
505 507 **traits)
506 508 self.save_flag = threading.Event()
507 509 self.db_input_cache_lock = threading.Lock()
508 510 self.db_output_cache_lock = threading.Lock()
509 511 if self.enabled and self.hist_file != ':memory:':
510 512 self.save_thread = HistorySavingThread(self)
511 513 self.save_thread.start()
512 514
513 515 self.new_session()
514 516
515 517 def _get_hist_file_name(self, profile=None):
516 518 """Get default history file name based on the Shell's profile.
517 519
518 520 The profile parameter is ignored, but must exist for compatibility with
519 521 the parent class."""
520 522 profile_dir = self.shell.profile_dir.location
521 523 return os.path.join(profile_dir, 'history.sqlite')
522 524
523 525 @needs_sqlite
524 526 def new_session(self, conn=None):
525 527 """Get a new session number."""
526 528 if conn is None:
527 529 conn = self.db
528 530
529 531 with conn:
530 532 cur = conn.execute("""INSERT INTO sessions VALUES (NULL, ?, NULL,
531 533 NULL, "") """, (datetime.datetime.now(),))
532 534 self.session_number = cur.lastrowid
533 535
534 536 def end_session(self):
535 537 """Close the database session, filling in the end time and line count."""
536 538 self.writeout_cache()
537 539 with self.db:
538 540 self.db.execute("""UPDATE sessions SET end=?, num_cmds=? WHERE
539 541 session==?""", (datetime.datetime.now(),
540 542 len(self.input_hist_parsed)-1, self.session_number))
541 543 self.session_number = 0
542 544
543 545 def name_session(self, name):
544 546 """Give the current session a name in the history database."""
545 547 with self.db:
546 548 self.db.execute("UPDATE sessions SET remark=? WHERE session==?",
547 549 (name, self.session_number))
548 550
549 551 def reset(self, new_session=True):
550 552 """Clear the session history, releasing all object references, and
551 553 optionally open a new session."""
552 554 self.output_hist.clear()
553 555 # The directory history can't be completely empty
554 556 self.dir_hist[:] = [py3compat.getcwd()]
555 557
556 558 if new_session:
557 559 if self.session_number:
558 560 self.end_session()
559 561 self.input_hist_parsed[:] = [""]
560 562 self.input_hist_raw[:] = [""]
561 563 self.new_session()
562 564
563 565 # ------------------------------
564 566 # Methods for retrieving history
565 567 # ------------------------------
566 568 def get_session_info(self, session=0):
567 569 """Get info about a session.
568 570
569 571 Parameters
570 572 ----------
571 573
572 574 session : int
573 575 Session number to retrieve. The current session is 0, and negative
574 576 numbers count back from current session, so -1 is the previous session.
575 577
576 578 Returns
577 579 -------
578 580
579 581 session_id : int
580 582 Session ID number
581 583 start : datetime
582 584 Timestamp for the start of the session.
583 585 end : datetime
584 586 Timestamp for the end of the session, or None if IPython crashed.
585 587 num_cmds : int
586 588 Number of commands run, or None if IPython crashed.
587 589 remark : unicode
588 590 A manually set description.
589 591 """
590 592 if session <= 0:
591 593 session += self.session_number
592 594
593 595 return super(HistoryManager, self).get_session_info(session=session)
594 596
595 597 def _get_range_session(self, start=1, stop=None, raw=True, output=False):
596 598 """Get input and output history from the current session. Called by
597 599 get_range, and takes similar parameters."""
598 600 input_hist = self.input_hist_raw if raw else self.input_hist_parsed
599 601
600 602 n = len(input_hist)
601 603 if start < 0:
602 604 start += n
603 605 if not stop or (stop > n):
604 606 stop = n
605 607 elif stop < 0:
606 608 stop += n
607 609
608 610 for i in range(start, stop):
609 611 if output:
610 612 line = (input_hist[i], self.output_hist_reprs.get(i))
611 613 else:
612 614 line = input_hist[i]
613 615 yield (0, i, line)
614 616
615 617 def get_range(self, session=0, start=1, stop=None, raw=True,output=False):
616 618 """Retrieve input by session.
617 619
618 620 Parameters
619 621 ----------
620 622 session : int
621 623 Session number to retrieve. The current session is 0, and negative
622 624 numbers count back from current session, so -1 is previous session.
623 625 start : int
624 626 First line to retrieve.
625 627 stop : int
626 628 End of line range (excluded from output itself). If None, retrieve
627 629 to the end of the session.
628 630 raw : bool
629 631 If True, return untranslated input
630 632 output : bool
631 633 If True, attempt to include output. This will be 'real' Python
632 634 objects for the current session, or text reprs from previous
633 635 sessions if db_log_output was enabled at the time. Where no output
634 636 is found, None is used.
635 637
636 638 Returns
637 639 -------
638 640 entries
639 641 An iterator over the desired lines. Each line is a 3-tuple, either
640 642 (session, line, input) if output is False, or
641 643 (session, line, (input, output)) if output is True.
642 644 """
643 645 if session <= 0:
644 646 session += self.session_number
645 647 if session==self.session_number: # Current session
646 648 return self._get_range_session(start, stop, raw, output)
647 649 return super(HistoryManager, self).get_range(session, start, stop, raw,
648 650 output)
649 651
650 652 ## ----------------------------
651 653 ## Methods for storing history:
652 654 ## ----------------------------
653 655 def store_inputs(self, line_num, source, source_raw=None):
654 656 """Store source and raw input in history and create input cache
655 657 variables ``_i*``.
656 658
657 659 Parameters
658 660 ----------
659 661 line_num : int
660 662 The prompt number of this input.
661 663
662 664 source : str
663 665 Python input.
664 666
665 667 source_raw : str, optional
666 668 If given, this is the raw input without any IPython transformations
667 669 applied to it. If not given, ``source`` is used.
668 670 """
669 671 if source_raw is None:
670 672 source_raw = source
671 673 source = source.rstrip('\n')
672 674 source_raw = source_raw.rstrip('\n')
673 675
674 676 # do not store exit/quit commands
675 677 if self._exit_re.match(source_raw.strip()):
676 678 return
677 679
678 680 self.input_hist_parsed.append(source)
679 681 self.input_hist_raw.append(source_raw)
680 682
681 683 with self.db_input_cache_lock:
682 684 self.db_input_cache.append((line_num, source, source_raw))
683 685 # Trigger to flush cache and write to DB.
684 686 if len(self.db_input_cache) >= self.db_cache_size:
685 687 self.save_flag.set()
686 688
687 689 # update the auto _i variables
688 690 self._iii = self._ii
689 691 self._ii = self._i
690 692 self._i = self._i00
691 693 self._i00 = source_raw
692 694
693 695 # hackish access to user namespace to create _i1,_i2... dynamically
694 696 new_i = '_i%s' % line_num
695 697 to_main = {'_i': self._i,
696 698 '_ii': self._ii,
697 699 '_iii': self._iii,
698 700 new_i : self._i00 }
699 701
700 702 if self.shell is not None:
701 703 self.shell.push(to_main, interactive=False)
702 704
703 705 def store_output(self, line_num):
704 706 """If database output logging is enabled, this saves all the
705 707 outputs from the indicated prompt number to the database. It's
706 708 called by run_cell after code has been executed.
707 709
708 710 Parameters
709 711 ----------
710 712 line_num : int
711 713 The line number from which to save outputs
712 714 """
713 715 if (not self.db_log_output) or (line_num not in self.output_hist_reprs):
714 716 return
715 717 output = self.output_hist_reprs[line_num]
716 718
717 719 with self.db_output_cache_lock:
718 720 self.db_output_cache.append((line_num, output))
719 721 if self.db_cache_size <= 1:
720 722 self.save_flag.set()
721 723
722 724 def _writeout_input_cache(self, conn):
723 725 with conn:
724 726 for line in self.db_input_cache:
725 727 conn.execute("INSERT INTO history VALUES (?, ?, ?, ?)",
726 728 (self.session_number,)+line)
727 729
728 730 def _writeout_output_cache(self, conn):
729 731 with conn:
730 732 for line in self.db_output_cache:
731 733 conn.execute("INSERT INTO output_history VALUES (?, ?, ?)",
732 734 (self.session_number,)+line)
733 735
734 736 @needs_sqlite
735 737 def writeout_cache(self, conn=None):
736 738 """Write any entries in the cache to the database."""
737 739 if conn is None:
738 740 conn = self.db
739 741
740 742 with self.db_input_cache_lock:
741 743 try:
742 744 self._writeout_input_cache(conn)
743 745 except sqlite3.IntegrityError:
744 746 self.new_session(conn)
745 747 print("ERROR! Session/line number was not unique in",
746 748 "database. History logging moved to new session",
747 749 self.session_number)
748 750 try:
749 751 # Try writing to the new session. If this fails, don't
750 752 # recurse
751 753 self._writeout_input_cache(conn)
752 754 except sqlite3.IntegrityError:
753 755 pass
754 756 finally:
755 757 self.db_input_cache = []
756 758
757 759 with self.db_output_cache_lock:
758 760 try:
759 761 self._writeout_output_cache(conn)
760 762 except sqlite3.IntegrityError:
761 763 print("!! Session/line number for output was not unique",
762 764 "in database. Output will not be stored.")
763 765 finally:
764 766 self.db_output_cache = []
765 767
766 768
767 769 class HistorySavingThread(threading.Thread):
768 770 """This thread takes care of writing history to the database, so that
769 771 the UI isn't held up while that happens.
770 772
771 773 It waits for the HistoryManager's save_flag to be set, then writes out
772 774 the history cache. The main thread is responsible for setting the flag when
773 775 the cache size reaches a defined threshold."""
774 776 daemon = True
775 777 stop_now = False
776 778 enabled = True
777 779 def __init__(self, history_manager):
778 780 super(HistorySavingThread, self).__init__(name="IPythonHistorySavingThread")
779 781 self.history_manager = history_manager
780 782 self.enabled = history_manager.enabled
781 783 atexit.register(self.stop)
782 784
783 785 @needs_sqlite
784 786 def run(self):
785 787 # We need a separate db connection per thread:
786 788 try:
787 789 self.db = sqlite3.connect(self.history_manager.hist_file,
788 790 **self.history_manager.connection_options
789 791 )
790 792 while True:
791 793 self.history_manager.save_flag.wait()
792 794 if self.stop_now:
793 795 self.db.close()
794 796 return
795 797 self.history_manager.save_flag.clear()
796 798 self.history_manager.writeout_cache(self.db)
797 799 except Exception as e:
798 800 print(("The history saving thread hit an unexpected error (%s)."
799 801 "History will not be written to the database.") % repr(e))
800 802
801 803 def stop(self):
802 804 """This can be called from the main thread to safely stop this thread.
803 805
804 806 Note that it does not attempt to write out remaining history before
805 807 exiting. That should be done by calling the HistoryManager's
806 808 end_session method."""
807 809 self.stop_now = True
808 810 self.history_manager.save_flag.set()
809 811 self.join()
810 812
811 813
812 814 # To match, e.g. ~5/8-~2/3
813 815 range_re = re.compile(r"""
814 816 ((?P<startsess>~?\d+)/)?
815 817 (?P<start>\d+)?
816 818 ((?P<sep>[\-:])
817 819 ((?P<endsess>~?\d+)/)?
818 820 (?P<end>\d+))?
819 821 $""", re.VERBOSE)
820 822
821 823
822 824 def extract_hist_ranges(ranges_str):
823 825 """Turn a string of history ranges into 3-tuples of (session, start, stop).
824 826
825 827 Examples
826 828 --------
827 829 >>> list(extract_hist_ranges("~8/5-~7/4 2"))
828 830 [(-8, 5, None), (-7, 1, 5), (0, 2, 3)]
829 831 """
830 832 for range_str in ranges_str.split():
831 833 rmatch = range_re.match(range_str)
832 834 if not rmatch:
833 835 continue
834 836 start = rmatch.group("start")
835 837 if start:
836 838 start = int(start)
837 839 end = rmatch.group("end")
838 840 # If no end specified, get (a, a + 1)
839 841 end = int(end) if end else start + 1
840 842 else: # start not specified
841 843 if not rmatch.group('startsess'): # no startsess
842 844 continue
843 845 start = 1
844 846 end = None # provide the entire session hist
845 847
846 848 if rmatch.group("sep") == "-": # 1-3 == 1:4 --> [1, 2, 3]
847 849 end += 1
848 850 startsess = rmatch.group("startsess") or "0"
849 851 endsess = rmatch.group("endsess") or startsess
850 852 startsess = int(startsess.replace("~","-"))
851 853 endsess = int(endsess.replace("~","-"))
852 854 assert endsess >= startsess, "start session must be earlier than end session"
853 855
854 856 if endsess == startsess:
855 857 yield (startsess, start, end)
856 858 continue
857 859 # Multiple sessions in one range:
858 860 yield (startsess, start, None)
859 861 for sess in range(startsess+1, endsess):
860 862 yield (sess, 1, None)
861 863 yield (endsess, 1, end)
862 864
863 865
864 866 def _format_lineno(session, line):
865 867 """Helper function to format line numbers properly."""
866 868 if session == 0:
867 869 return str(line)
868 870 return "%s#%s" % (session, line)
869 871
870 872
@@ -1,3392 +1,3392 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Main IPython class."""
3 3
4 4 #-----------------------------------------------------------------------------
5 5 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de>
6 6 # Copyright (C) 2001-2007 Fernando Perez. <fperez@colorado.edu>
7 7 # Copyright (C) 2008-2011 The IPython Development Team
8 8 #
9 9 # Distributed under the terms of the BSD License. The full license is in
10 10 # the file COPYING, distributed as part of this software.
11 11 #-----------------------------------------------------------------------------
12 12
13 13 from __future__ import absolute_import, print_function
14 14
15 15 import __future__
16 16 import abc
17 17 import ast
18 18 import atexit
19 19 import functools
20 20 import os
21 21 import re
22 22 import runpy
23 23 import sys
24 24 import tempfile
25 25 import traceback
26 26 import types
27 27 import subprocess
28 28 from io import open as io_open
29 29
30 30 from pickleshare import PickleShareDB
31 31
32 32 from IPython.config.configurable import SingletonConfigurable
33 33 from IPython.core import debugger, oinspect
34 34 from IPython.core import magic
35 35 from IPython.core import page
36 36 from IPython.core import prefilter
37 37 from IPython.core import shadowns
38 38 from IPython.core import ultratb
39 39 from IPython.core.alias import Alias, AliasManager
40 40 from IPython.core.autocall import ExitAutocall
41 41 from IPython.core.builtin_trap import BuiltinTrap
42 42 from IPython.core.events import EventManager, available_events
43 43 from IPython.core.compilerop import CachingCompiler, check_linecache_ipython
44 44 from IPython.core.display_trap import DisplayTrap
45 45 from IPython.core.displayhook import DisplayHook
46 46 from IPython.core.displaypub import DisplayPublisher
47 47 from IPython.core.error import InputRejected, UsageError
48 48 from IPython.core.extensions import ExtensionManager
49 49 from IPython.core.formatters import DisplayFormatter
50 50 from IPython.core.history import HistoryManager
51 51 from IPython.core.inputsplitter import IPythonInputSplitter, ESC_MAGIC, ESC_MAGIC2
52 52 from IPython.core.logger import Logger
53 53 from IPython.core.macro import Macro
54 54 from IPython.core.payload import PayloadManager
55 55 from IPython.core.prefilter import PrefilterManager
56 56 from IPython.core.profiledir import ProfileDir
57 57 from IPython.core.prompts import PromptManager
58 58 from IPython.core.usage import default_banner
59 59 from IPython.testing.skipdoctest import skip_doctest
60 60 from IPython.utils import PyColorize
61 61 from IPython.utils import io
62 62 from IPython.utils import py3compat
63 63 from IPython.utils import openpy
64 64 from IPython.utils.decorators import undoc
65 65 from IPython.utils.io import ask_yes_no
66 66 from IPython.utils.ipstruct import Struct
67 67 from IPython.utils.path import get_home_dir, get_ipython_dir, get_py_filename, unquote_filename, ensure_dir_exists
68 68 from IPython.utils.process import system, getoutput
69 69 from IPython.utils.py3compat import (builtin_mod, unicode_type, string_types,
70 70 with_metaclass, iteritems)
71 71 from IPython.utils.strdispatch import StrDispatch
72 72 from IPython.utils.syspathcontext import prepended_to_syspath
73 73 from IPython.utils.text import (format_screen, LSString, SList,
74 74 DollarFormatter)
75 75 from IPython.utils.traitlets import (Integer, Bool, CBool, CaselessStrEnum, Enum,
76 76 List, Unicode, Instance, Type)
77 77 from IPython.utils.warn import warn, error
78 78 import IPython.core.hooks
79 79
80 80 #-----------------------------------------------------------------------------
81 81 # Globals
82 82 #-----------------------------------------------------------------------------
83 83
84 84 # compiled regexps for autoindent management
85 85 dedent_re = re.compile(r'^\s+raise|^\s+return|^\s+pass')
86 86
87 87 #-----------------------------------------------------------------------------
88 88 # Utilities
89 89 #-----------------------------------------------------------------------------
90 90
91 91 @undoc
92 92 def softspace(file, newvalue):
93 93 """Copied from code.py, to remove the dependency"""
94 94
95 95 oldvalue = 0
96 96 try:
97 97 oldvalue = file.softspace
98 98 except AttributeError:
99 99 pass
100 100 try:
101 101 file.softspace = newvalue
102 102 except (AttributeError, TypeError):
103 103 # "attribute-less object" or "read-only attributes"
104 104 pass
105 105 return oldvalue
106 106
107 107 @undoc
108 108 def no_op(*a, **kw): pass
109 109
110 110 @undoc
111 111 class NoOpContext(object):
112 112 def __enter__(self): pass
113 113 def __exit__(self, type, value, traceback): pass
114 114 no_op_context = NoOpContext()
115 115
116 116 class SpaceInInput(Exception): pass
117 117
118 118 @undoc
119 119 class Bunch: pass
120 120
121 121
122 122 def get_default_colors():
123 123 if sys.platform=='darwin':
124 124 return "LightBG"
125 125 elif os.name=='nt':
126 126 return 'Linux'
127 127 else:
128 128 return 'Linux'
129 129
130 130
131 131 class SeparateUnicode(Unicode):
132 132 r"""A Unicode subclass to validate separate_in, separate_out, etc.
133 133
134 134 This is a Unicode based trait that converts '0'->'' and ``'\\n'->'\n'``.
135 135 """
136 136
137 137 def validate(self, obj, value):
138 138 if value == '0': value = ''
139 139 value = value.replace('\\n','\n')
140 140 return super(SeparateUnicode, self).validate(obj, value)
141 141
142 142
143 143 class ReadlineNoRecord(object):
144 144 """Context manager to execute some code, then reload readline history
145 145 so that interactive input to the code doesn't appear when pressing up."""
146 146 def __init__(self, shell):
147 147 self.shell = shell
148 148 self._nested_level = 0
149 149
150 150 def __enter__(self):
151 151 if self._nested_level == 0:
152 152 try:
153 153 self.orig_length = self.current_length()
154 154 self.readline_tail = self.get_readline_tail()
155 155 except (AttributeError, IndexError): # Can fail with pyreadline
156 156 self.orig_length, self.readline_tail = 999999, []
157 157 self._nested_level += 1
158 158
159 159 def __exit__(self, type, value, traceback):
160 160 self._nested_level -= 1
161 161 if self._nested_level == 0:
162 162 # Try clipping the end if it's got longer
163 163 try:
164 164 e = self.current_length() - self.orig_length
165 165 if e > 0:
166 166 for _ in range(e):
167 167 self.shell.readline.remove_history_item(self.orig_length)
168 168
169 169 # If it still doesn't match, just reload readline history.
170 170 if self.current_length() != self.orig_length \
171 171 or self.get_readline_tail() != self.readline_tail:
172 172 self.shell.refill_readline_hist()
173 173 except (AttributeError, IndexError):
174 174 pass
175 175 # Returning False will cause exceptions to propagate
176 176 return False
177 177
178 178 def current_length(self):
179 179 return self.shell.readline.get_current_history_length()
180 180
181 181 def get_readline_tail(self, n=10):
182 182 """Get the last n items in readline history."""
183 183 end = self.shell.readline.get_current_history_length() + 1
184 184 start = max(end-n, 1)
185 185 ghi = self.shell.readline.get_history_item
186 186 return [ghi(x) for x in range(start, end)]
187 187
188 188
189 189 @undoc
190 190 class DummyMod(object):
191 191 """A dummy module used for IPython's interactive module when
192 192 a namespace must be assigned to the module's __dict__."""
193 193 pass
194 194
195 195
196 196 class ExecutionResult(object):
197 197 """The result of a call to :meth:`InteractiveShell.run_cell`
198 198
199 199 Stores information about what took place.
200 200 """
201 201 execution_count = None
202 202 error_before_exec = None
203 203 error_in_exec = None
204 204 result = None
205 205
206 206 @property
207 207 def success(self):
208 208 return (self.error_before_exec is None) and (self.error_in_exec is None)
209 209
210 210
211 211 class InteractiveShell(SingletonConfigurable):
212 212 """An enhanced, interactive shell for Python."""
213 213
214 214 _instance = None
215 215
216 216 ast_transformers = List([], config=True, help=
217 217 """
218 218 A list of ast.NodeTransformer subclass instances, which will be applied
219 219 to user input before code is run.
220 220 """
221 221 )
222 222
223 223 autocall = Enum((0,1,2), default_value=0, config=True, help=
224 224 """
225 225 Make IPython automatically call any callable object even if you didn't
226 226 type explicit parentheses. For example, 'str 43' becomes 'str(43)'
227 227 automatically. The value can be '0' to disable the feature, '1' for
228 228 'smart' autocall, where it is not applied if there are no more
229 229 arguments on the line, and '2' for 'full' autocall, where all callable
230 230 objects are automatically called (even if no arguments are present).
231 231 """
232 232 )
233 233 # TODO: remove all autoindent logic and put into frontends.
234 234 # We can't do this yet because even runlines uses the autoindent.
235 235 autoindent = CBool(True, config=True, help=
236 236 """
237 237 Autoindent IPython code entered interactively.
238 238 """
239 239 )
240 240 automagic = CBool(True, config=True, help=
241 241 """
242 242 Enable magic commands to be called without the leading %.
243 243 """
244 244 )
245 245
246 246 banner1 = Unicode(default_banner, config=True,
247 247 help="""The part of the banner to be printed before the profile"""
248 248 )
249 249 banner2 = Unicode('', config=True,
250 250 help="""The part of the banner to be printed after the profile"""
251 251 )
252 252
253 253 cache_size = Integer(1000, config=True, help=
254 254 """
255 255 Set the size of the output cache. The default is 1000, you can
256 256 change it permanently in your config file. Setting it to 0 completely
257 257 disables the caching system, and the minimum value accepted is 20 (if
258 258 you provide a value less than 20, it is reset to 0 and a warning is
259 259 issued). This limit is defined because otherwise you'll spend more
260 260 time re-flushing a too small cache than working
261 261 """
262 262 )
263 263 color_info = CBool(True, config=True, help=
264 264 """
265 265 Use colors for displaying information about objects. Because this
266 266 information is passed through a pager (like 'less'), and some pagers
267 267 get confused with color codes, this capability can be turned off.
268 268 """
269 269 )
270 270 colors = CaselessStrEnum(('NoColor','LightBG','Linux'),
271 271 default_value=get_default_colors(), config=True,
272 272 help="Set the color scheme (NoColor, Linux, or LightBG)."
273 273 )
274 274 colors_force = CBool(False, help=
275 275 """
276 276 Force use of ANSI color codes, regardless of OS and readline
277 277 availability.
278 278 """
279 279 # FIXME: This is essentially a hack to allow ZMQShell to show colors
280 280 # without readline on Win32. When the ZMQ formatting system is
281 281 # refactored, this should be removed.
282 282 )
283 283 debug = CBool(False, config=True)
284 284 deep_reload = CBool(False, config=True, help=
285 285 """
286 286 Enable deep (recursive) reloading by default. IPython can use the
287 287 deep_reload module which reloads changes in modules recursively (it
288 288 replaces the reload() function, so you don't need to change anything to
289 289 use it). deep_reload() forces a full reload of modules whose code may
290 290 have changed, which the default reload() function does not. When
291 291 deep_reload is off, IPython will use the normal reload(), but
292 292 deep_reload will still be available as dreload().
293 293 """
294 294 )
295 295 disable_failing_post_execute = CBool(False, config=True,
296 296 help="Don't call post-execute functions that have failed in the past."
297 297 )
298 display_formatter = Instance(DisplayFormatter)
299 displayhook_class = Type(DisplayHook)
300 display_pub_class = Type(DisplayPublisher)
298 display_formatter = Instance(DisplayFormatter, allow_none=True)
299 displayhook_class = Type(DisplayHook, allow_none=True)
300 display_pub_class = Type(DisplayPublisher, allow_none=True)
301 301 data_pub_class = None
302 302
303 303 exit_now = CBool(False)
304 exiter = Instance(ExitAutocall)
304 exiter = Instance(ExitAutocall, allow_none=True)
305 305 def _exiter_default(self):
306 306 return ExitAutocall(self)
307 307 # Monotonically increasing execution counter
308 308 execution_count = Integer(1)
309 309 filename = Unicode("<ipython console>")
310 310 ipython_dir= Unicode('', config=True) # Set to get_ipython_dir() in __init__
311 311
312 312 # Input splitter, to transform input line by line and detect when a block
313 313 # is ready to be executed.
314 314 input_splitter = Instance('IPython.core.inputsplitter.IPythonInputSplitter',
315 315 (), {'line_input_checker': True})
316 316
317 317 # This InputSplitter instance is used to transform completed cells before
318 318 # running them. It allows cell magics to contain blank lines.
319 319 input_transformer_manager = Instance('IPython.core.inputsplitter.IPythonInputSplitter',
320 320 (), {'line_input_checker': False})
321 321
322 322 logstart = CBool(False, config=True, help=
323 323 """
324 324 Start logging to the default log file in overwrite mode.
325 325 Use `logappend` to specify a log file to **append** logs to.
326 326 """
327 327 )
328 328 logfile = Unicode('', config=True, help=
329 329 """
330 330 The name of the logfile to use.
331 331 """
332 332 )
333 333 logappend = Unicode('', config=True, help=
334 334 """
335 335 Start logging to the given file in append mode.
336 336 Use `logfile` to specify a log file to **overwrite** logs to.
337 337 """
338 338 )
339 339 object_info_string_level = Enum((0,1,2), default_value=0,
340 340 config=True)
341 341 pdb = CBool(False, config=True, help=
342 342 """
343 343 Automatically call the pdb debugger after every exception.
344 344 """
345 345 )
346 346 multiline_history = CBool(sys.platform != 'win32', config=True,
347 347 help="Save multi-line entries as one entry in readline history"
348 348 )
349 349 display_page = Bool(False, config=True,
350 350 help="""If True, anything that would be passed to the pager
351 351 will be displayed as regular output instead."""
352 352 )
353 353
354 354 # deprecated prompt traits:
355 355
356 356 prompt_in1 = Unicode('In [\\#]: ', config=True,
357 357 help="Deprecated, use PromptManager.in_template")
358 358 prompt_in2 = Unicode(' .\\D.: ', config=True,
359 359 help="Deprecated, use PromptManager.in2_template")
360 360 prompt_out = Unicode('Out[\\#]: ', config=True,
361 361 help="Deprecated, use PromptManager.out_template")
362 362 prompts_pad_left = CBool(True, config=True,
363 363 help="Deprecated, use PromptManager.justify")
364 364
365 365 def _prompt_trait_changed(self, name, old, new):
366 366 table = {
367 367 'prompt_in1' : 'in_template',
368 368 'prompt_in2' : 'in2_template',
369 369 'prompt_out' : 'out_template',
370 370 'prompts_pad_left' : 'justify',
371 371 }
372 372 warn("InteractiveShell.{name} is deprecated, use PromptManager.{newname}".format(
373 373 name=name, newname=table[name])
374 374 )
375 375 # protect against weird cases where self.config may not exist:
376 376 if self.config is not None:
377 377 # propagate to corresponding PromptManager trait
378 378 setattr(self.config.PromptManager, table[name], new)
379 379
380 380 _prompt_in1_changed = _prompt_trait_changed
381 381 _prompt_in2_changed = _prompt_trait_changed
382 382 _prompt_out_changed = _prompt_trait_changed
383 383 _prompt_pad_left_changed = _prompt_trait_changed
384 384
385 385 show_rewritten_input = CBool(True, config=True,
386 386 help="Show rewritten input, e.g. for autocall."
387 387 )
388 388
389 389 quiet = CBool(False, config=True)
390 390
391 391 history_length = Integer(10000, config=True)
392 392
393 393 # The readline stuff will eventually be moved to the terminal subclass
394 394 # but for now, we can't do that as readline is welded in everywhere.
395 395 readline_use = CBool(True, config=True)
396 396 readline_remove_delims = Unicode('-/~', config=True)
397 397 readline_delims = Unicode() # set by init_readline()
398 398 # don't use \M- bindings by default, because they
399 399 # conflict with 8-bit encodings. See gh-58,gh-88
400 400 readline_parse_and_bind = List([
401 401 'tab: complete',
402 402 '"\C-l": clear-screen',
403 403 'set show-all-if-ambiguous on',
404 404 '"\C-o": tab-insert',
405 405 '"\C-r": reverse-search-history',
406 406 '"\C-s": forward-search-history',
407 407 '"\C-p": history-search-backward',
408 408 '"\C-n": history-search-forward',
409 409 '"\e[A": history-search-backward',
410 410 '"\e[B": history-search-forward',
411 411 '"\C-k": kill-line',
412 412 '"\C-u": unix-line-discard',
413 413 ], config=True)
414 414
415 415 _custom_readline_config = False
416 416
417 417 def _readline_parse_and_bind_changed(self, name, old, new):
418 418 # notice that readline config is customized
419 419 # indicates that it should have higher priority than inputrc
420 420 self._custom_readline_config = True
421 421
422 422 ast_node_interactivity = Enum(['all', 'last', 'last_expr', 'none'],
423 423 default_value='last_expr', config=True,
424 424 help="""
425 425 'all', 'last', 'last_expr' or 'none', specifying which nodes should be
426 426 run interactively (displaying output from expressions).""")
427 427
428 428 # TODO: this part of prompt management should be moved to the frontends.
429 429 # Use custom TraitTypes that convert '0'->'' and '\\n'->'\n'
430 430 separate_in = SeparateUnicode('\n', config=True)
431 431 separate_out = SeparateUnicode('', config=True)
432 432 separate_out2 = SeparateUnicode('', config=True)
433 433 wildcards_case_sensitive = CBool(True, config=True)
434 434 xmode = CaselessStrEnum(('Context','Plain', 'Verbose'),
435 435 default_value='Context', config=True)
436 436
437 437 # Subcomponents of InteractiveShell
438 alias_manager = Instance('IPython.core.alias.AliasManager')
439 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager')
440 builtin_trap = Instance('IPython.core.builtin_trap.BuiltinTrap')
441 display_trap = Instance('IPython.core.display_trap.DisplayTrap')
442 extension_manager = Instance('IPython.core.extensions.ExtensionManager')
443 payload_manager = Instance('IPython.core.payload.PayloadManager')
444 history_manager = Instance('IPython.core.history.HistoryAccessorBase')
445 magics_manager = Instance('IPython.core.magic.MagicsManager')
446
447 profile_dir = Instance('IPython.core.application.ProfileDir')
438 alias_manager = Instance('IPython.core.alias.AliasManager', allow_none=True)
439 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager', allow_none=True)
440 builtin_trap = Instance('IPython.core.builtin_trap.BuiltinTrap', allow_none=True)
441 display_trap = Instance('IPython.core.display_trap.DisplayTrap', allow_none=True)
442 extension_manager = Instance('IPython.core.extensions.ExtensionManager', allow_none=True)
443 payload_manager = Instance('IPython.core.payload.PayloadManager', allow_none=True)
444 history_manager = Instance('IPython.core.history.HistoryAccessorBase', allow_none=True)
445 magics_manager = Instance('IPython.core.magic.MagicsManager', allow_none=True)
446
447 profile_dir = Instance('IPython.core.application.ProfileDir', allow_none=True)
448 448 @property
449 449 def profile(self):
450 450 if self.profile_dir is not None:
451 451 name = os.path.basename(self.profile_dir.location)
452 452 return name.replace('profile_','')
453 453
454 454
455 455 # Private interface
456 _post_execute = Instance(dict)
456 _post_execute = Instance(dict, allow_none=True)
457 457
458 458 # Tracks any GUI loop loaded for pylab
459 459 pylab_gui_select = None
460 460
461 461 def __init__(self, ipython_dir=None, profile_dir=None,
462 462 user_module=None, user_ns=None,
463 463 custom_exceptions=((), None), **kwargs):
464 464
465 465 # This is where traits with a config_key argument are updated
466 466 # from the values on config.
467 467 super(InteractiveShell, self).__init__(**kwargs)
468 468 self.configurables = [self]
469 469
470 470 # These are relatively independent and stateless
471 471 self.init_ipython_dir(ipython_dir)
472 472 self.init_profile_dir(profile_dir)
473 473 self.init_instance_attrs()
474 474 self.init_environment()
475 475
476 476 # Check if we're in a virtualenv, and set up sys.path.
477 477 self.init_virtualenv()
478 478
479 479 # Create namespaces (user_ns, user_global_ns, etc.)
480 480 self.init_create_namespaces(user_module, user_ns)
481 481 # This has to be done after init_create_namespaces because it uses
482 482 # something in self.user_ns, but before init_sys_modules, which
483 483 # is the first thing to modify sys.
484 484 # TODO: When we override sys.stdout and sys.stderr before this class
485 485 # is created, we are saving the overridden ones here. Not sure if this
486 486 # is what we want to do.
487 487 self.save_sys_module_state()
488 488 self.init_sys_modules()
489 489
490 490 # While we're trying to have each part of the code directly access what
491 491 # it needs without keeping redundant references to objects, we have too
492 492 # much legacy code that expects ip.db to exist.
493 493 self.db = PickleShareDB(os.path.join(self.profile_dir.location, 'db'))
494 494
495 495 self.init_history()
496 496 self.init_encoding()
497 497 self.init_prefilter()
498 498
499 499 self.init_syntax_highlighting()
500 500 self.init_hooks()
501 501 self.init_events()
502 502 self.init_pushd_popd_magic()
503 503 # self.init_traceback_handlers use to be here, but we moved it below
504 504 # because it and init_io have to come after init_readline.
505 505 self.init_user_ns()
506 506 self.init_logger()
507 507 self.init_builtins()
508 508
509 509 # The following was in post_config_initialization
510 510 self.init_inspector()
511 511 # init_readline() must come before init_io(), because init_io uses
512 512 # readline related things.
513 513 self.init_readline()
514 514 # We save this here in case user code replaces raw_input, but it needs
515 515 # to be after init_readline(), because PyPy's readline works by replacing
516 516 # raw_input.
517 517 if py3compat.PY3:
518 518 self.raw_input_original = input
519 519 else:
520 520 self.raw_input_original = raw_input
521 521 # init_completer must come after init_readline, because it needs to
522 522 # know whether readline is present or not system-wide to configure the
523 523 # completers, since the completion machinery can now operate
524 524 # independently of readline (e.g. over the network)
525 525 self.init_completer()
526 526 # TODO: init_io() needs to happen before init_traceback handlers
527 527 # because the traceback handlers hardcode the stdout/stderr streams.
528 528 # This logic in in debugger.Pdb and should eventually be changed.
529 529 self.init_io()
530 530 self.init_traceback_handlers(custom_exceptions)
531 531 self.init_prompts()
532 532 self.init_display_formatter()
533 533 self.init_display_pub()
534 534 self.init_data_pub()
535 535 self.init_displayhook()
536 536 self.init_magics()
537 537 self.init_alias()
538 538 self.init_logstart()
539 539 self.init_pdb()
540 540 self.init_extension_manager()
541 541 self.init_payload()
542 542 self.hooks.late_startup_hook()
543 543 self.events.trigger('shell_initialized', self)
544 544 atexit.register(self.atexit_operations)
545 545
546 546 def get_ipython(self):
547 547 """Return the currently running IPython instance."""
548 548 return self
549 549
550 550 #-------------------------------------------------------------------------
551 551 # Trait changed handlers
552 552 #-------------------------------------------------------------------------
553 553
554 554 def _ipython_dir_changed(self, name, new):
555 555 ensure_dir_exists(new)
556 556
557 557 def set_autoindent(self,value=None):
558 558 """Set the autoindent flag, checking for readline support.
559 559
560 560 If called with no arguments, it acts as a toggle."""
561 561
562 562 if value != 0 and not self.has_readline:
563 563 if os.name == 'posix':
564 564 warn("The auto-indent feature requires the readline library")
565 565 self.autoindent = 0
566 566 return
567 567 if value is None:
568 568 self.autoindent = not self.autoindent
569 569 else:
570 570 self.autoindent = value
571 571
572 572 #-------------------------------------------------------------------------
573 573 # init_* methods called by __init__
574 574 #-------------------------------------------------------------------------
575 575
576 576 def init_ipython_dir(self, ipython_dir):
577 577 if ipython_dir is not None:
578 578 self.ipython_dir = ipython_dir
579 579 return
580 580
581 581 self.ipython_dir = get_ipython_dir()
582 582
583 583 def init_profile_dir(self, profile_dir):
584 584 if profile_dir is not None:
585 585 self.profile_dir = profile_dir
586 586 return
587 587 self.profile_dir =\
588 588 ProfileDir.create_profile_dir_by_name(self.ipython_dir, 'default')
589 589
590 590 def init_instance_attrs(self):
591 591 self.more = False
592 592
593 593 # command compiler
594 594 self.compile = CachingCompiler()
595 595
596 596 # Make an empty namespace, which extension writers can rely on both
597 597 # existing and NEVER being used by ipython itself. This gives them a
598 598 # convenient location for storing additional information and state
599 599 # their extensions may require, without fear of collisions with other
600 600 # ipython names that may develop later.
601 601 self.meta = Struct()
602 602
603 603 # Temporary files used for various purposes. Deleted at exit.
604 604 self.tempfiles = []
605 605 self.tempdirs = []
606 606
607 607 # Keep track of readline usage (later set by init_readline)
608 608 self.has_readline = False
609 609
610 610 # keep track of where we started running (mainly for crash post-mortem)
611 611 # This is not being used anywhere currently.
612 612 self.starting_dir = py3compat.getcwd()
613 613
614 614 # Indentation management
615 615 self.indent_current_nsp = 0
616 616
617 617 # Dict to track post-execution functions that have been registered
618 618 self._post_execute = {}
619 619
620 620 def init_environment(self):
621 621 """Any changes we need to make to the user's environment."""
622 622 pass
623 623
624 624 def init_encoding(self):
625 625 # Get system encoding at startup time. Certain terminals (like Emacs
626 626 # under Win32 have it set to None, and we need to have a known valid
627 627 # encoding to use in the raw_input() method
628 628 try:
629 629 self.stdin_encoding = sys.stdin.encoding or 'ascii'
630 630 except AttributeError:
631 631 self.stdin_encoding = 'ascii'
632 632
633 633 def init_syntax_highlighting(self):
634 634 # Python source parser/formatter for syntax highlighting
635 635 pyformat = PyColorize.Parser().format
636 636 self.pycolorize = lambda src: pyformat(src,'str',self.colors)
637 637
638 638 def init_pushd_popd_magic(self):
639 639 # for pushd/popd management
640 640 self.home_dir = get_home_dir()
641 641
642 642 self.dir_stack = []
643 643
644 644 def init_logger(self):
645 645 self.logger = Logger(self.home_dir, logfname='ipython_log.py',
646 646 logmode='rotate')
647 647
648 648 def init_logstart(self):
649 649 """Initialize logging in case it was requested at the command line.
650 650 """
651 651 if self.logappend:
652 652 self.magic('logstart %s append' % self.logappend)
653 653 elif self.logfile:
654 654 self.magic('logstart %s' % self.logfile)
655 655 elif self.logstart:
656 656 self.magic('logstart')
657 657
658 658 def init_builtins(self):
659 659 # A single, static flag that we set to True. Its presence indicates
660 660 # that an IPython shell has been created, and we make no attempts at
661 661 # removing on exit or representing the existence of more than one
662 662 # IPython at a time.
663 663 builtin_mod.__dict__['__IPYTHON__'] = True
664 664
665 665 # In 0.11 we introduced '__IPYTHON__active' as an integer we'd try to
666 666 # manage on enter/exit, but with all our shells it's virtually
667 667 # impossible to get all the cases right. We're leaving the name in for
668 668 # those who adapted their codes to check for this flag, but will
669 669 # eventually remove it after a few more releases.
670 670 builtin_mod.__dict__['__IPYTHON__active'] = \
671 671 'Deprecated, check for __IPYTHON__'
672 672
673 673 self.builtin_trap = BuiltinTrap(shell=self)
674 674
675 675 def init_inspector(self):
676 676 # Object inspector
677 677 self.inspector = oinspect.Inspector(oinspect.InspectColors,
678 678 PyColorize.ANSICodeColors,
679 679 'NoColor',
680 680 self.object_info_string_level)
681 681
682 682 def init_io(self):
683 683 # This will just use sys.stdout and sys.stderr. If you want to
684 684 # override sys.stdout and sys.stderr themselves, you need to do that
685 685 # *before* instantiating this class, because io holds onto
686 686 # references to the underlying streams.
687 687 if (sys.platform == 'win32' or sys.platform == 'cli') and self.has_readline:
688 688 io.stdout = io.stderr = io.IOStream(self.readline._outputfile)
689 689 else:
690 690 io.stdout = io.IOStream(sys.stdout)
691 691 io.stderr = io.IOStream(sys.stderr)
692 692
693 693 def init_prompts(self):
694 694 self.prompt_manager = PromptManager(shell=self, parent=self)
695 695 self.configurables.append(self.prompt_manager)
696 696 # Set system prompts, so that scripts can decide if they are running
697 697 # interactively.
698 698 sys.ps1 = 'In : '
699 699 sys.ps2 = '...: '
700 700 sys.ps3 = 'Out: '
701 701
702 702 def init_display_formatter(self):
703 703 self.display_formatter = DisplayFormatter(parent=self)
704 704 self.configurables.append(self.display_formatter)
705 705
706 706 def init_display_pub(self):
707 707 self.display_pub = self.display_pub_class(parent=self)
708 708 self.configurables.append(self.display_pub)
709 709
710 710 def init_data_pub(self):
711 711 if not self.data_pub_class:
712 712 self.data_pub = None
713 713 return
714 714 self.data_pub = self.data_pub_class(parent=self)
715 715 self.configurables.append(self.data_pub)
716 716
717 717 def init_displayhook(self):
718 718 # Initialize displayhook, set in/out prompts and printing system
719 719 self.displayhook = self.displayhook_class(
720 720 parent=self,
721 721 shell=self,
722 722 cache_size=self.cache_size,
723 723 )
724 724 self.configurables.append(self.displayhook)
725 725 # This is a context manager that installs/revmoes the displayhook at
726 726 # the appropriate time.
727 727 self.display_trap = DisplayTrap(hook=self.displayhook)
728 728
729 729 def init_virtualenv(self):
730 730 """Add a virtualenv to sys.path so the user can import modules from it.
731 731 This isn't perfect: it doesn't use the Python interpreter with which the
732 732 virtualenv was built, and it ignores the --no-site-packages option. A
733 733 warning will appear suggesting the user installs IPython in the
734 734 virtualenv, but for many cases, it probably works well enough.
735 735
736 736 Adapted from code snippets online.
737 737
738 738 http://blog.ufsoft.org/2009/1/29/ipython-and-virtualenv
739 739 """
740 740 if 'VIRTUAL_ENV' not in os.environ:
741 741 # Not in a virtualenv
742 742 return
743 743
744 744 # venv detection:
745 745 # stdlib venv may symlink sys.executable, so we can't use realpath.
746 746 # but others can symlink *to* the venv Python, so we can't just use sys.executable.
747 747 # So we just check every item in the symlink tree (generally <= 3)
748 748 p = os.path.normcase(sys.executable)
749 749 paths = [p]
750 750 while os.path.islink(p):
751 751 p = os.path.normcase(os.path.join(os.path.dirname(p), os.readlink(p)))
752 752 paths.append(p)
753 753 p_venv = os.path.normcase(os.environ['VIRTUAL_ENV'])
754 754 if any(p.startswith(p_venv) for p in paths):
755 755 # Running properly in the virtualenv, don't need to do anything
756 756 return
757 757
758 758 warn("Attempting to work in a virtualenv. If you encounter problems, please "
759 759 "install IPython inside the virtualenv.")
760 760 if sys.platform == "win32":
761 761 virtual_env = os.path.join(os.environ['VIRTUAL_ENV'], 'Lib', 'site-packages')
762 762 else:
763 763 virtual_env = os.path.join(os.environ['VIRTUAL_ENV'], 'lib',
764 764 'python%d.%d' % sys.version_info[:2], 'site-packages')
765 765
766 766 import site
767 767 sys.path.insert(0, virtual_env)
768 768 site.addsitedir(virtual_env)
769 769
770 770 #-------------------------------------------------------------------------
771 771 # Things related to injections into the sys module
772 772 #-------------------------------------------------------------------------
773 773
774 774 def save_sys_module_state(self):
775 775 """Save the state of hooks in the sys module.
776 776
777 777 This has to be called after self.user_module is created.
778 778 """
779 779 self._orig_sys_module_state = {}
780 780 self._orig_sys_module_state['stdin'] = sys.stdin
781 781 self._orig_sys_module_state['stdout'] = sys.stdout
782 782 self._orig_sys_module_state['stderr'] = sys.stderr
783 783 self._orig_sys_module_state['excepthook'] = sys.excepthook
784 784 self._orig_sys_modules_main_name = self.user_module.__name__
785 785 self._orig_sys_modules_main_mod = sys.modules.get(self.user_module.__name__)
786 786
787 787 def restore_sys_module_state(self):
788 788 """Restore the state of the sys module."""
789 789 try:
790 790 for k, v in iteritems(self._orig_sys_module_state):
791 791 setattr(sys, k, v)
792 792 except AttributeError:
793 793 pass
794 794 # Reset what what done in self.init_sys_modules
795 795 if self._orig_sys_modules_main_mod is not None:
796 796 sys.modules[self._orig_sys_modules_main_name] = self._orig_sys_modules_main_mod
797 797
798 798 #-------------------------------------------------------------------------
799 799 # Things related to the banner
800 800 #-------------------------------------------------------------------------
801 801
802 802 @property
803 803 def banner(self):
804 804 banner = self.banner1
805 805 if self.profile and self.profile != 'default':
806 806 banner += '\nIPython profile: %s\n' % self.profile
807 807 if self.banner2:
808 808 banner += '\n' + self.banner2
809 809 return banner
810 810
811 811 def show_banner(self, banner=None):
812 812 if banner is None:
813 813 banner = self.banner
814 814 self.write(banner)
815 815
816 816 #-------------------------------------------------------------------------
817 817 # Things related to hooks
818 818 #-------------------------------------------------------------------------
819 819
820 820 def init_hooks(self):
821 821 # hooks holds pointers used for user-side customizations
822 822 self.hooks = Struct()
823 823
824 824 self.strdispatchers = {}
825 825
826 826 # Set all default hooks, defined in the IPython.hooks module.
827 827 hooks = IPython.core.hooks
828 828 for hook_name in hooks.__all__:
829 829 # default hooks have priority 100, i.e. low; user hooks should have
830 830 # 0-100 priority
831 831 self.set_hook(hook_name,getattr(hooks,hook_name), 100, _warn_deprecated=False)
832 832
833 833 if self.display_page:
834 834 self.set_hook('show_in_pager', page.as_hook(page.display_page), 90)
835 835
836 836 def set_hook(self,name,hook, priority=50, str_key=None, re_key=None,
837 837 _warn_deprecated=True):
838 838 """set_hook(name,hook) -> sets an internal IPython hook.
839 839
840 840 IPython exposes some of its internal API as user-modifiable hooks. By
841 841 adding your function to one of these hooks, you can modify IPython's
842 842 behavior to call at runtime your own routines."""
843 843
844 844 # At some point in the future, this should validate the hook before it
845 845 # accepts it. Probably at least check that the hook takes the number
846 846 # of args it's supposed to.
847 847
848 848 f = types.MethodType(hook,self)
849 849
850 850 # check if the hook is for strdispatcher first
851 851 if str_key is not None:
852 852 sdp = self.strdispatchers.get(name, StrDispatch())
853 853 sdp.add_s(str_key, f, priority )
854 854 self.strdispatchers[name] = sdp
855 855 return
856 856 if re_key is not None:
857 857 sdp = self.strdispatchers.get(name, StrDispatch())
858 858 sdp.add_re(re.compile(re_key), f, priority )
859 859 self.strdispatchers[name] = sdp
860 860 return
861 861
862 862 dp = getattr(self.hooks, name, None)
863 863 if name not in IPython.core.hooks.__all__:
864 864 print("Warning! Hook '%s' is not one of %s" % \
865 865 (name, IPython.core.hooks.__all__ ))
866 866
867 867 if _warn_deprecated and (name in IPython.core.hooks.deprecated):
868 868 alternative = IPython.core.hooks.deprecated[name]
869 869 warn("Hook {} is deprecated. Use {} instead.".format(name, alternative))
870 870
871 871 if not dp:
872 872 dp = IPython.core.hooks.CommandChainDispatcher()
873 873
874 874 try:
875 875 dp.add(f,priority)
876 876 except AttributeError:
877 877 # it was not commandchain, plain old func - replace
878 878 dp = f
879 879
880 880 setattr(self.hooks,name, dp)
881 881
882 882 #-------------------------------------------------------------------------
883 883 # Things related to events
884 884 #-------------------------------------------------------------------------
885 885
886 886 def init_events(self):
887 887 self.events = EventManager(self, available_events)
888 888
889 889 self.events.register("pre_execute", self._clear_warning_registry)
890 890
891 891 def register_post_execute(self, func):
892 892 """DEPRECATED: Use ip.events.register('post_run_cell', func)
893 893
894 894 Register a function for calling after code execution.
895 895 """
896 896 warn("ip.register_post_execute is deprecated, use "
897 897 "ip.events.register('post_run_cell', func) instead.")
898 898 self.events.register('post_run_cell', func)
899 899
900 900 def _clear_warning_registry(self):
901 901 # clear the warning registry, so that different code blocks with
902 902 # overlapping line number ranges don't cause spurious suppression of
903 903 # warnings (see gh-6611 for details)
904 904 if "__warningregistry__" in self.user_global_ns:
905 905 del self.user_global_ns["__warningregistry__"]
906 906
907 907 #-------------------------------------------------------------------------
908 908 # Things related to the "main" module
909 909 #-------------------------------------------------------------------------
910 910
911 911 def new_main_mod(self, filename, modname):
912 912 """Return a new 'main' module object for user code execution.
913 913
914 914 ``filename`` should be the path of the script which will be run in the
915 915 module. Requests with the same filename will get the same module, with
916 916 its namespace cleared.
917 917
918 918 ``modname`` should be the module name - normally either '__main__' or
919 919 the basename of the file without the extension.
920 920
921 921 When scripts are executed via %run, we must keep a reference to their
922 922 __main__ module around so that Python doesn't
923 923 clear it, rendering references to module globals useless.
924 924
925 925 This method keeps said reference in a private dict, keyed by the
926 926 absolute path of the script. This way, for multiple executions of the
927 927 same script we only keep one copy of the namespace (the last one),
928 928 thus preventing memory leaks from old references while allowing the
929 929 objects from the last execution to be accessible.
930 930 """
931 931 filename = os.path.abspath(filename)
932 932 try:
933 933 main_mod = self._main_mod_cache[filename]
934 934 except KeyError:
935 935 main_mod = self._main_mod_cache[filename] = types.ModuleType(
936 936 py3compat.cast_bytes_py2(modname),
937 937 doc="Module created for script run in IPython")
938 938 else:
939 939 main_mod.__dict__.clear()
940 940 main_mod.__name__ = modname
941 941
942 942 main_mod.__file__ = filename
943 943 # It seems pydoc (and perhaps others) needs any module instance to
944 944 # implement a __nonzero__ method
945 945 main_mod.__nonzero__ = lambda : True
946 946
947 947 return main_mod
948 948
949 949 def clear_main_mod_cache(self):
950 950 """Clear the cache of main modules.
951 951
952 952 Mainly for use by utilities like %reset.
953 953
954 954 Examples
955 955 --------
956 956
957 957 In [15]: import IPython
958 958
959 959 In [16]: m = _ip.new_main_mod(IPython.__file__, 'IPython')
960 960
961 961 In [17]: len(_ip._main_mod_cache) > 0
962 962 Out[17]: True
963 963
964 964 In [18]: _ip.clear_main_mod_cache()
965 965
966 966 In [19]: len(_ip._main_mod_cache) == 0
967 967 Out[19]: True
968 968 """
969 969 self._main_mod_cache.clear()
970 970
971 971 #-------------------------------------------------------------------------
972 972 # Things related to debugging
973 973 #-------------------------------------------------------------------------
974 974
975 975 def init_pdb(self):
976 976 # Set calling of pdb on exceptions
977 977 # self.call_pdb is a property
978 978 self.call_pdb = self.pdb
979 979
980 980 def _get_call_pdb(self):
981 981 return self._call_pdb
982 982
983 983 def _set_call_pdb(self,val):
984 984
985 985 if val not in (0,1,False,True):
986 986 raise ValueError('new call_pdb value must be boolean')
987 987
988 988 # store value in instance
989 989 self._call_pdb = val
990 990
991 991 # notify the actual exception handlers
992 992 self.InteractiveTB.call_pdb = val
993 993
994 994 call_pdb = property(_get_call_pdb,_set_call_pdb,None,
995 995 'Control auto-activation of pdb at exceptions')
996 996
997 997 def debugger(self,force=False):
998 998 """Call the pydb/pdb debugger.
999 999
1000 1000 Keywords:
1001 1001
1002 1002 - force(False): by default, this routine checks the instance call_pdb
1003 1003 flag and does not actually invoke the debugger if the flag is false.
1004 1004 The 'force' option forces the debugger to activate even if the flag
1005 1005 is false.
1006 1006 """
1007 1007
1008 1008 if not (force or self.call_pdb):
1009 1009 return
1010 1010
1011 1011 if not hasattr(sys,'last_traceback'):
1012 1012 error('No traceback has been produced, nothing to debug.')
1013 1013 return
1014 1014
1015 1015 # use pydb if available
1016 1016 if debugger.has_pydb:
1017 1017 from pydb import pm
1018 1018 else:
1019 1019 # fallback to our internal debugger
1020 1020 pm = lambda : self.InteractiveTB.debugger(force=True)
1021 1021
1022 1022 with self.readline_no_record:
1023 1023 pm()
1024 1024
1025 1025 #-------------------------------------------------------------------------
1026 1026 # Things related to IPython's various namespaces
1027 1027 #-------------------------------------------------------------------------
1028 1028 default_user_namespaces = True
1029 1029
1030 1030 def init_create_namespaces(self, user_module=None, user_ns=None):
1031 1031 # Create the namespace where the user will operate. user_ns is
1032 1032 # normally the only one used, and it is passed to the exec calls as
1033 1033 # the locals argument. But we do carry a user_global_ns namespace
1034 1034 # given as the exec 'globals' argument, This is useful in embedding
1035 1035 # situations where the ipython shell opens in a context where the
1036 1036 # distinction between locals and globals is meaningful. For
1037 1037 # non-embedded contexts, it is just the same object as the user_ns dict.
1038 1038
1039 1039 # FIXME. For some strange reason, __builtins__ is showing up at user
1040 1040 # level as a dict instead of a module. This is a manual fix, but I
1041 1041 # should really track down where the problem is coming from. Alex
1042 1042 # Schmolck reported this problem first.
1043 1043
1044 1044 # A useful post by Alex Martelli on this topic:
1045 1045 # Re: inconsistent value from __builtins__
1046 1046 # Von: Alex Martelli <aleaxit@yahoo.com>
1047 1047 # Datum: Freitag 01 Oktober 2004 04:45:34 nachmittags/abends
1048 1048 # Gruppen: comp.lang.python
1049 1049
1050 1050 # Michael Hohn <hohn@hooknose.lbl.gov> wrote:
1051 1051 # > >>> print type(builtin_check.get_global_binding('__builtins__'))
1052 1052 # > <type 'dict'>
1053 1053 # > >>> print type(__builtins__)
1054 1054 # > <type 'module'>
1055 1055 # > Is this difference in return value intentional?
1056 1056
1057 1057 # Well, it's documented that '__builtins__' can be either a dictionary
1058 1058 # or a module, and it's been that way for a long time. Whether it's
1059 1059 # intentional (or sensible), I don't know. In any case, the idea is
1060 1060 # that if you need to access the built-in namespace directly, you
1061 1061 # should start with "import __builtin__" (note, no 's') which will
1062 1062 # definitely give you a module. Yeah, it's somewhat confusing:-(.
1063 1063
1064 1064 # These routines return a properly built module and dict as needed by
1065 1065 # the rest of the code, and can also be used by extension writers to
1066 1066 # generate properly initialized namespaces.
1067 1067 if (user_ns is not None) or (user_module is not None):
1068 1068 self.default_user_namespaces = False
1069 1069 self.user_module, self.user_ns = self.prepare_user_module(user_module, user_ns)
1070 1070
1071 1071 # A record of hidden variables we have added to the user namespace, so
1072 1072 # we can list later only variables defined in actual interactive use.
1073 1073 self.user_ns_hidden = {}
1074 1074
1075 1075 # Now that FakeModule produces a real module, we've run into a nasty
1076 1076 # problem: after script execution (via %run), the module where the user
1077 1077 # code ran is deleted. Now that this object is a true module (needed
1078 1078 # so docetst and other tools work correctly), the Python module
1079 1079 # teardown mechanism runs over it, and sets to None every variable
1080 1080 # present in that module. Top-level references to objects from the
1081 1081 # script survive, because the user_ns is updated with them. However,
1082 1082 # calling functions defined in the script that use other things from
1083 1083 # the script will fail, because the function's closure had references
1084 1084 # to the original objects, which are now all None. So we must protect
1085 1085 # these modules from deletion by keeping a cache.
1086 1086 #
1087 1087 # To avoid keeping stale modules around (we only need the one from the
1088 1088 # last run), we use a dict keyed with the full path to the script, so
1089 1089 # only the last version of the module is held in the cache. Note,
1090 1090 # however, that we must cache the module *namespace contents* (their
1091 1091 # __dict__). Because if we try to cache the actual modules, old ones
1092 1092 # (uncached) could be destroyed while still holding references (such as
1093 1093 # those held by GUI objects that tend to be long-lived)>
1094 1094 #
1095 1095 # The %reset command will flush this cache. See the cache_main_mod()
1096 1096 # and clear_main_mod_cache() methods for details on use.
1097 1097
1098 1098 # This is the cache used for 'main' namespaces
1099 1099 self._main_mod_cache = {}
1100 1100
1101 1101 # A table holding all the namespaces IPython deals with, so that
1102 1102 # introspection facilities can search easily.
1103 1103 self.ns_table = {'user_global':self.user_module.__dict__,
1104 1104 'user_local':self.user_ns,
1105 1105 'builtin':builtin_mod.__dict__
1106 1106 }
1107 1107
1108 1108 @property
1109 1109 def user_global_ns(self):
1110 1110 return self.user_module.__dict__
1111 1111
1112 1112 def prepare_user_module(self, user_module=None, user_ns=None):
1113 1113 """Prepare the module and namespace in which user code will be run.
1114 1114
1115 1115 When IPython is started normally, both parameters are None: a new module
1116 1116 is created automatically, and its __dict__ used as the namespace.
1117 1117
1118 1118 If only user_module is provided, its __dict__ is used as the namespace.
1119 1119 If only user_ns is provided, a dummy module is created, and user_ns
1120 1120 becomes the global namespace. If both are provided (as they may be
1121 1121 when embedding), user_ns is the local namespace, and user_module
1122 1122 provides the global namespace.
1123 1123
1124 1124 Parameters
1125 1125 ----------
1126 1126 user_module : module, optional
1127 1127 The current user module in which IPython is being run. If None,
1128 1128 a clean module will be created.
1129 1129 user_ns : dict, optional
1130 1130 A namespace in which to run interactive commands.
1131 1131
1132 1132 Returns
1133 1133 -------
1134 1134 A tuple of user_module and user_ns, each properly initialised.
1135 1135 """
1136 1136 if user_module is None and user_ns is not None:
1137 1137 user_ns.setdefault("__name__", "__main__")
1138 1138 user_module = DummyMod()
1139 1139 user_module.__dict__ = user_ns
1140 1140
1141 1141 if user_module is None:
1142 1142 user_module = types.ModuleType("__main__",
1143 1143 doc="Automatically created module for IPython interactive environment")
1144 1144
1145 1145 # We must ensure that __builtin__ (without the final 's') is always
1146 1146 # available and pointing to the __builtin__ *module*. For more details:
1147 1147 # http://mail.python.org/pipermail/python-dev/2001-April/014068.html
1148 1148 user_module.__dict__.setdefault('__builtin__', builtin_mod)
1149 1149 user_module.__dict__.setdefault('__builtins__', builtin_mod)
1150 1150
1151 1151 if user_ns is None:
1152 1152 user_ns = user_module.__dict__
1153 1153
1154 1154 return user_module, user_ns
1155 1155
1156 1156 def init_sys_modules(self):
1157 1157 # We need to insert into sys.modules something that looks like a
1158 1158 # module but which accesses the IPython namespace, for shelve and
1159 1159 # pickle to work interactively. Normally they rely on getting
1160 1160 # everything out of __main__, but for embedding purposes each IPython
1161 1161 # instance has its own private namespace, so we can't go shoving
1162 1162 # everything into __main__.
1163 1163
1164 1164 # note, however, that we should only do this for non-embedded
1165 1165 # ipythons, which really mimic the __main__.__dict__ with their own
1166 1166 # namespace. Embedded instances, on the other hand, should not do
1167 1167 # this because they need to manage the user local/global namespaces
1168 1168 # only, but they live within a 'normal' __main__ (meaning, they
1169 1169 # shouldn't overtake the execution environment of the script they're
1170 1170 # embedded in).
1171 1171
1172 1172 # This is overridden in the InteractiveShellEmbed subclass to a no-op.
1173 1173 main_name = self.user_module.__name__
1174 1174 sys.modules[main_name] = self.user_module
1175 1175
1176 1176 def init_user_ns(self):
1177 1177 """Initialize all user-visible namespaces to their minimum defaults.
1178 1178
1179 1179 Certain history lists are also initialized here, as they effectively
1180 1180 act as user namespaces.
1181 1181
1182 1182 Notes
1183 1183 -----
1184 1184 All data structures here are only filled in, they are NOT reset by this
1185 1185 method. If they were not empty before, data will simply be added to
1186 1186 therm.
1187 1187 """
1188 1188 # This function works in two parts: first we put a few things in
1189 1189 # user_ns, and we sync that contents into user_ns_hidden so that these
1190 1190 # initial variables aren't shown by %who. After the sync, we add the
1191 1191 # rest of what we *do* want the user to see with %who even on a new
1192 1192 # session (probably nothing, so theye really only see their own stuff)
1193 1193
1194 1194 # The user dict must *always* have a __builtin__ reference to the
1195 1195 # Python standard __builtin__ namespace, which must be imported.
1196 1196 # This is so that certain operations in prompt evaluation can be
1197 1197 # reliably executed with builtins. Note that we can NOT use
1198 1198 # __builtins__ (note the 's'), because that can either be a dict or a
1199 1199 # module, and can even mutate at runtime, depending on the context
1200 1200 # (Python makes no guarantees on it). In contrast, __builtin__ is
1201 1201 # always a module object, though it must be explicitly imported.
1202 1202
1203 1203 # For more details:
1204 1204 # http://mail.python.org/pipermail/python-dev/2001-April/014068.html
1205 1205 ns = dict()
1206 1206
1207 1207 # make global variables for user access to the histories
1208 1208 ns['_ih'] = self.history_manager.input_hist_parsed
1209 1209 ns['_oh'] = self.history_manager.output_hist
1210 1210 ns['_dh'] = self.history_manager.dir_hist
1211 1211
1212 1212 ns['_sh'] = shadowns
1213 1213
1214 1214 # user aliases to input and output histories. These shouldn't show up
1215 1215 # in %who, as they can have very large reprs.
1216 1216 ns['In'] = self.history_manager.input_hist_parsed
1217 1217 ns['Out'] = self.history_manager.output_hist
1218 1218
1219 1219 # Store myself as the public api!!!
1220 1220 ns['get_ipython'] = self.get_ipython
1221 1221
1222 1222 ns['exit'] = self.exiter
1223 1223 ns['quit'] = self.exiter
1224 1224
1225 1225 # Sync what we've added so far to user_ns_hidden so these aren't seen
1226 1226 # by %who
1227 1227 self.user_ns_hidden.update(ns)
1228 1228
1229 1229 # Anything put into ns now would show up in %who. Think twice before
1230 1230 # putting anything here, as we really want %who to show the user their
1231 1231 # stuff, not our variables.
1232 1232
1233 1233 # Finally, update the real user's namespace
1234 1234 self.user_ns.update(ns)
1235 1235
1236 1236 @property
1237 1237 def all_ns_refs(self):
1238 1238 """Get a list of references to all the namespace dictionaries in which
1239 1239 IPython might store a user-created object.
1240 1240
1241 1241 Note that this does not include the displayhook, which also caches
1242 1242 objects from the output."""
1243 1243 return [self.user_ns, self.user_global_ns, self.user_ns_hidden] + \
1244 1244 [m.__dict__ for m in self._main_mod_cache.values()]
1245 1245
1246 1246 def reset(self, new_session=True):
1247 1247 """Clear all internal namespaces, and attempt to release references to
1248 1248 user objects.
1249 1249
1250 1250 If new_session is True, a new history session will be opened.
1251 1251 """
1252 1252 # Clear histories
1253 1253 self.history_manager.reset(new_session)
1254 1254 # Reset counter used to index all histories
1255 1255 if new_session:
1256 1256 self.execution_count = 1
1257 1257
1258 1258 # Flush cached output items
1259 1259 if self.displayhook.do_full_cache:
1260 1260 self.displayhook.flush()
1261 1261
1262 1262 # The main execution namespaces must be cleared very carefully,
1263 1263 # skipping the deletion of the builtin-related keys, because doing so
1264 1264 # would cause errors in many object's __del__ methods.
1265 1265 if self.user_ns is not self.user_global_ns:
1266 1266 self.user_ns.clear()
1267 1267 ns = self.user_global_ns
1268 1268 drop_keys = set(ns.keys())
1269 1269 drop_keys.discard('__builtin__')
1270 1270 drop_keys.discard('__builtins__')
1271 1271 drop_keys.discard('__name__')
1272 1272 for k in drop_keys:
1273 1273 del ns[k]
1274 1274
1275 1275 self.user_ns_hidden.clear()
1276 1276
1277 1277 # Restore the user namespaces to minimal usability
1278 1278 self.init_user_ns()
1279 1279
1280 1280 # Restore the default and user aliases
1281 1281 self.alias_manager.clear_aliases()
1282 1282 self.alias_manager.init_aliases()
1283 1283
1284 1284 # Flush the private list of module references kept for script
1285 1285 # execution protection
1286 1286 self.clear_main_mod_cache()
1287 1287
1288 1288 def del_var(self, varname, by_name=False):
1289 1289 """Delete a variable from the various namespaces, so that, as
1290 1290 far as possible, we're not keeping any hidden references to it.
1291 1291
1292 1292 Parameters
1293 1293 ----------
1294 1294 varname : str
1295 1295 The name of the variable to delete.
1296 1296 by_name : bool
1297 1297 If True, delete variables with the given name in each
1298 1298 namespace. If False (default), find the variable in the user
1299 1299 namespace, and delete references to it.
1300 1300 """
1301 1301 if varname in ('__builtin__', '__builtins__'):
1302 1302 raise ValueError("Refusing to delete %s" % varname)
1303 1303
1304 1304 ns_refs = self.all_ns_refs
1305 1305
1306 1306 if by_name: # Delete by name
1307 1307 for ns in ns_refs:
1308 1308 try:
1309 1309 del ns[varname]
1310 1310 except KeyError:
1311 1311 pass
1312 1312 else: # Delete by object
1313 1313 try:
1314 1314 obj = self.user_ns[varname]
1315 1315 except KeyError:
1316 1316 raise NameError("name '%s' is not defined" % varname)
1317 1317 # Also check in output history
1318 1318 ns_refs.append(self.history_manager.output_hist)
1319 1319 for ns in ns_refs:
1320 1320 to_delete = [n for n, o in iteritems(ns) if o is obj]
1321 1321 for name in to_delete:
1322 1322 del ns[name]
1323 1323
1324 1324 # displayhook keeps extra references, but not in a dictionary
1325 1325 for name in ('_', '__', '___'):
1326 1326 if getattr(self.displayhook, name) is obj:
1327 1327 setattr(self.displayhook, name, None)
1328 1328
1329 1329 def reset_selective(self, regex=None):
1330 1330 """Clear selective variables from internal namespaces based on a
1331 1331 specified regular expression.
1332 1332
1333 1333 Parameters
1334 1334 ----------
1335 1335 regex : string or compiled pattern, optional
1336 1336 A regular expression pattern that will be used in searching
1337 1337 variable names in the users namespaces.
1338 1338 """
1339 1339 if regex is not None:
1340 1340 try:
1341 1341 m = re.compile(regex)
1342 1342 except TypeError:
1343 1343 raise TypeError('regex must be a string or compiled pattern')
1344 1344 # Search for keys in each namespace that match the given regex
1345 1345 # If a match is found, delete the key/value pair.
1346 1346 for ns in self.all_ns_refs:
1347 1347 for var in ns:
1348 1348 if m.search(var):
1349 1349 del ns[var]
1350 1350
1351 1351 def push(self, variables, interactive=True):
1352 1352 """Inject a group of variables into the IPython user namespace.
1353 1353
1354 1354 Parameters
1355 1355 ----------
1356 1356 variables : dict, str or list/tuple of str
1357 1357 The variables to inject into the user's namespace. If a dict, a
1358 1358 simple update is done. If a str, the string is assumed to have
1359 1359 variable names separated by spaces. A list/tuple of str can also
1360 1360 be used to give the variable names. If just the variable names are
1361 1361 give (list/tuple/str) then the variable values looked up in the
1362 1362 callers frame.
1363 1363 interactive : bool
1364 1364 If True (default), the variables will be listed with the ``who``
1365 1365 magic.
1366 1366 """
1367 1367 vdict = None
1368 1368
1369 1369 # We need a dict of name/value pairs to do namespace updates.
1370 1370 if isinstance(variables, dict):
1371 1371 vdict = variables
1372 1372 elif isinstance(variables, string_types+(list, tuple)):
1373 1373 if isinstance(variables, string_types):
1374 1374 vlist = variables.split()
1375 1375 else:
1376 1376 vlist = variables
1377 1377 vdict = {}
1378 1378 cf = sys._getframe(1)
1379 1379 for name in vlist:
1380 1380 try:
1381 1381 vdict[name] = eval(name, cf.f_globals, cf.f_locals)
1382 1382 except:
1383 1383 print('Could not get variable %s from %s' %
1384 1384 (name,cf.f_code.co_name))
1385 1385 else:
1386 1386 raise ValueError('variables must be a dict/str/list/tuple')
1387 1387
1388 1388 # Propagate variables to user namespace
1389 1389 self.user_ns.update(vdict)
1390 1390
1391 1391 # And configure interactive visibility
1392 1392 user_ns_hidden = self.user_ns_hidden
1393 1393 if interactive:
1394 1394 for name in vdict:
1395 1395 user_ns_hidden.pop(name, None)
1396 1396 else:
1397 1397 user_ns_hidden.update(vdict)
1398 1398
1399 1399 def drop_by_id(self, variables):
1400 1400 """Remove a dict of variables from the user namespace, if they are the
1401 1401 same as the values in the dictionary.
1402 1402
1403 1403 This is intended for use by extensions: variables that they've added can
1404 1404 be taken back out if they are unloaded, without removing any that the
1405 1405 user has overwritten.
1406 1406
1407 1407 Parameters
1408 1408 ----------
1409 1409 variables : dict
1410 1410 A dictionary mapping object names (as strings) to the objects.
1411 1411 """
1412 1412 for name, obj in iteritems(variables):
1413 1413 if name in self.user_ns and self.user_ns[name] is obj:
1414 1414 del self.user_ns[name]
1415 1415 self.user_ns_hidden.pop(name, None)
1416 1416
1417 1417 #-------------------------------------------------------------------------
1418 1418 # Things related to object introspection
1419 1419 #-------------------------------------------------------------------------
1420 1420
1421 1421 def _ofind(self, oname, namespaces=None):
1422 1422 """Find an object in the available namespaces.
1423 1423
1424 1424 self._ofind(oname) -> dict with keys: found,obj,ospace,ismagic
1425 1425
1426 1426 Has special code to detect magic functions.
1427 1427 """
1428 1428 oname = oname.strip()
1429 1429 #print '1- oname: <%r>' % oname # dbg
1430 1430 if not oname.startswith(ESC_MAGIC) and \
1431 1431 not oname.startswith(ESC_MAGIC2) and \
1432 1432 not py3compat.isidentifier(oname, dotted=True):
1433 1433 return dict(found=False)
1434 1434
1435 1435 alias_ns = None
1436 1436 if namespaces is None:
1437 1437 # Namespaces to search in:
1438 1438 # Put them in a list. The order is important so that we
1439 1439 # find things in the same order that Python finds them.
1440 1440 namespaces = [ ('Interactive', self.user_ns),
1441 1441 ('Interactive (global)', self.user_global_ns),
1442 1442 ('Python builtin', builtin_mod.__dict__),
1443 1443 ]
1444 1444
1445 1445 # initialize results to 'null'
1446 1446 found = False; obj = None; ospace = None; ds = None;
1447 1447 ismagic = False; isalias = False; parent = None
1448 1448
1449 1449 # We need to special-case 'print', which as of python2.6 registers as a
1450 1450 # function but should only be treated as one if print_function was
1451 1451 # loaded with a future import. In this case, just bail.
1452 1452 if (oname == 'print' and not py3compat.PY3 and not \
1453 1453 (self.compile.compiler_flags & __future__.CO_FUTURE_PRINT_FUNCTION)):
1454 1454 return {'found':found, 'obj':obj, 'namespace':ospace,
1455 1455 'ismagic':ismagic, 'isalias':isalias, 'parent':parent}
1456 1456
1457 1457 # Look for the given name by splitting it in parts. If the head is
1458 1458 # found, then we look for all the remaining parts as members, and only
1459 1459 # declare success if we can find them all.
1460 1460 oname_parts = oname.split('.')
1461 1461 oname_head, oname_rest = oname_parts[0],oname_parts[1:]
1462 1462 for nsname,ns in namespaces:
1463 1463 try:
1464 1464 obj = ns[oname_head]
1465 1465 except KeyError:
1466 1466 continue
1467 1467 else:
1468 1468 #print 'oname_rest:', oname_rest # dbg
1469 1469 for idx, part in enumerate(oname_rest):
1470 1470 try:
1471 1471 parent = obj
1472 1472 # The last part is looked up in a special way to avoid
1473 1473 # descriptor invocation as it may raise or have side
1474 1474 # effects.
1475 1475 if idx == len(oname_rest) - 1:
1476 1476 obj = self._getattr_property(obj, part)
1477 1477 else:
1478 1478 obj = getattr(obj, part)
1479 1479 except:
1480 1480 # Blanket except b/c some badly implemented objects
1481 1481 # allow __getattr__ to raise exceptions other than
1482 1482 # AttributeError, which then crashes IPython.
1483 1483 break
1484 1484 else:
1485 1485 # If we finish the for loop (no break), we got all members
1486 1486 found = True
1487 1487 ospace = nsname
1488 1488 break # namespace loop
1489 1489
1490 1490 # Try to see if it's magic
1491 1491 if not found:
1492 1492 obj = None
1493 1493 if oname.startswith(ESC_MAGIC2):
1494 1494 oname = oname.lstrip(ESC_MAGIC2)
1495 1495 obj = self.find_cell_magic(oname)
1496 1496 elif oname.startswith(ESC_MAGIC):
1497 1497 oname = oname.lstrip(ESC_MAGIC)
1498 1498 obj = self.find_line_magic(oname)
1499 1499 else:
1500 1500 # search without prefix, so run? will find %run?
1501 1501 obj = self.find_line_magic(oname)
1502 1502 if obj is None:
1503 1503 obj = self.find_cell_magic(oname)
1504 1504 if obj is not None:
1505 1505 found = True
1506 1506 ospace = 'IPython internal'
1507 1507 ismagic = True
1508 1508 isalias = isinstance(obj, Alias)
1509 1509
1510 1510 # Last try: special-case some literals like '', [], {}, etc:
1511 1511 if not found and oname_head in ["''",'""','[]','{}','()']:
1512 1512 obj = eval(oname_head)
1513 1513 found = True
1514 1514 ospace = 'Interactive'
1515 1515
1516 1516 return {'found':found, 'obj':obj, 'namespace':ospace,
1517 1517 'ismagic':ismagic, 'isalias':isalias, 'parent':parent}
1518 1518
1519 1519 @staticmethod
1520 1520 def _getattr_property(obj, attrname):
1521 1521 """Property-aware getattr to use in object finding.
1522 1522
1523 1523 If attrname represents a property, return it unevaluated (in case it has
1524 1524 side effects or raises an error.
1525 1525
1526 1526 """
1527 1527 if not isinstance(obj, type):
1528 1528 try:
1529 1529 # `getattr(type(obj), attrname)` is not guaranteed to return
1530 1530 # `obj`, but does so for property:
1531 1531 #
1532 1532 # property.__get__(self, None, cls) -> self
1533 1533 #
1534 1534 # The universal alternative is to traverse the mro manually
1535 1535 # searching for attrname in class dicts.
1536 1536 attr = getattr(type(obj), attrname)
1537 1537 except AttributeError:
1538 1538 pass
1539 1539 else:
1540 1540 # This relies on the fact that data descriptors (with both
1541 1541 # __get__ & __set__ magic methods) take precedence over
1542 1542 # instance-level attributes:
1543 1543 #
1544 1544 # class A(object):
1545 1545 # @property
1546 1546 # def foobar(self): return 123
1547 1547 # a = A()
1548 1548 # a.__dict__['foobar'] = 345
1549 1549 # a.foobar # == 123
1550 1550 #
1551 1551 # So, a property may be returned right away.
1552 1552 if isinstance(attr, property):
1553 1553 return attr
1554 1554
1555 1555 # Nothing helped, fall back.
1556 1556 return getattr(obj, attrname)
1557 1557
1558 1558 def _object_find(self, oname, namespaces=None):
1559 1559 """Find an object and return a struct with info about it."""
1560 1560 return Struct(self._ofind(oname, namespaces))
1561 1561
1562 1562 def _inspect(self, meth, oname, namespaces=None, **kw):
1563 1563 """Generic interface to the inspector system.
1564 1564
1565 1565 This function is meant to be called by pdef, pdoc & friends."""
1566 1566 info = self._object_find(oname, namespaces)
1567 1567 if info.found:
1568 1568 pmethod = getattr(self.inspector, meth)
1569 1569 formatter = format_screen if info.ismagic else None
1570 1570 if meth == 'pdoc':
1571 1571 pmethod(info.obj, oname, formatter)
1572 1572 elif meth == 'pinfo':
1573 1573 pmethod(info.obj, oname, formatter, info, **kw)
1574 1574 else:
1575 1575 pmethod(info.obj, oname)
1576 1576 else:
1577 1577 print('Object `%s` not found.' % oname)
1578 1578 return 'not found' # so callers can take other action
1579 1579
1580 1580 def object_inspect(self, oname, detail_level=0):
1581 1581 """Get object info about oname"""
1582 1582 with self.builtin_trap:
1583 1583 info = self._object_find(oname)
1584 1584 if info.found:
1585 1585 return self.inspector.info(info.obj, oname, info=info,
1586 1586 detail_level=detail_level
1587 1587 )
1588 1588 else:
1589 1589 return oinspect.object_info(name=oname, found=False)
1590 1590
1591 1591 def object_inspect_text(self, oname, detail_level=0):
1592 1592 """Get object info as formatted text"""
1593 1593 with self.builtin_trap:
1594 1594 info = self._object_find(oname)
1595 1595 if info.found:
1596 1596 return self.inspector._format_info(info.obj, oname, info=info,
1597 1597 detail_level=detail_level
1598 1598 )
1599 1599 else:
1600 1600 raise KeyError(oname)
1601 1601
1602 1602 #-------------------------------------------------------------------------
1603 1603 # Things related to history management
1604 1604 #-------------------------------------------------------------------------
1605 1605
1606 1606 def init_history(self):
1607 1607 """Sets up the command history, and starts regular autosaves."""
1608 1608 self.history_manager = HistoryManager(shell=self, parent=self)
1609 1609 self.configurables.append(self.history_manager)
1610 1610
1611 1611 #-------------------------------------------------------------------------
1612 1612 # Things related to exception handling and tracebacks (not debugging)
1613 1613 #-------------------------------------------------------------------------
1614 1614
1615 1615 def init_traceback_handlers(self, custom_exceptions):
1616 1616 # Syntax error handler.
1617 1617 self.SyntaxTB = ultratb.SyntaxTB(color_scheme='NoColor')
1618 1618
1619 1619 # The interactive one is initialized with an offset, meaning we always
1620 1620 # want to remove the topmost item in the traceback, which is our own
1621 1621 # internal code. Valid modes: ['Plain','Context','Verbose']
1622 1622 self.InteractiveTB = ultratb.AutoFormattedTB(mode = 'Plain',
1623 1623 color_scheme='NoColor',
1624 1624 tb_offset = 1,
1625 1625 check_cache=check_linecache_ipython)
1626 1626
1627 1627 # The instance will store a pointer to the system-wide exception hook,
1628 1628 # so that runtime code (such as magics) can access it. This is because
1629 1629 # during the read-eval loop, it may get temporarily overwritten.
1630 1630 self.sys_excepthook = sys.excepthook
1631 1631
1632 1632 # and add any custom exception handlers the user may have specified
1633 1633 self.set_custom_exc(*custom_exceptions)
1634 1634
1635 1635 # Set the exception mode
1636 1636 self.InteractiveTB.set_mode(mode=self.xmode)
1637 1637
1638 1638 def set_custom_exc(self, exc_tuple, handler):
1639 1639 """set_custom_exc(exc_tuple,handler)
1640 1640
1641 1641 Set a custom exception handler, which will be called if any of the
1642 1642 exceptions in exc_tuple occur in the mainloop (specifically, in the
1643 1643 run_code() method).
1644 1644
1645 1645 Parameters
1646 1646 ----------
1647 1647
1648 1648 exc_tuple : tuple of exception classes
1649 1649 A *tuple* of exception classes, for which to call the defined
1650 1650 handler. It is very important that you use a tuple, and NOT A
1651 1651 LIST here, because of the way Python's except statement works. If
1652 1652 you only want to trap a single exception, use a singleton tuple::
1653 1653
1654 1654 exc_tuple == (MyCustomException,)
1655 1655
1656 1656 handler : callable
1657 1657 handler must have the following signature::
1658 1658
1659 1659 def my_handler(self, etype, value, tb, tb_offset=None):
1660 1660 ...
1661 1661 return structured_traceback
1662 1662
1663 1663 Your handler must return a structured traceback (a list of strings),
1664 1664 or None.
1665 1665
1666 1666 This will be made into an instance method (via types.MethodType)
1667 1667 of IPython itself, and it will be called if any of the exceptions
1668 1668 listed in the exc_tuple are caught. If the handler is None, an
1669 1669 internal basic one is used, which just prints basic info.
1670 1670
1671 1671 To protect IPython from crashes, if your handler ever raises an
1672 1672 exception or returns an invalid result, it will be immediately
1673 1673 disabled.
1674 1674
1675 1675 WARNING: by putting in your own exception handler into IPython's main
1676 1676 execution loop, you run a very good chance of nasty crashes. This
1677 1677 facility should only be used if you really know what you are doing."""
1678 1678
1679 1679 assert type(exc_tuple)==type(()) , \
1680 1680 "The custom exceptions must be given AS A TUPLE."
1681 1681
1682 1682 def dummy_handler(self,etype,value,tb,tb_offset=None):
1683 1683 print('*** Simple custom exception handler ***')
1684 1684 print('Exception type :',etype)
1685 1685 print('Exception value:',value)
1686 1686 print('Traceback :',tb)
1687 1687 #print 'Source code :','\n'.join(self.buffer)
1688 1688
1689 1689 def validate_stb(stb):
1690 1690 """validate structured traceback return type
1691 1691
1692 1692 return type of CustomTB *should* be a list of strings, but allow
1693 1693 single strings or None, which are harmless.
1694 1694
1695 1695 This function will *always* return a list of strings,
1696 1696 and will raise a TypeError if stb is inappropriate.
1697 1697 """
1698 1698 msg = "CustomTB must return list of strings, not %r" % stb
1699 1699 if stb is None:
1700 1700 return []
1701 1701 elif isinstance(stb, string_types):
1702 1702 return [stb]
1703 1703 elif not isinstance(stb, list):
1704 1704 raise TypeError(msg)
1705 1705 # it's a list
1706 1706 for line in stb:
1707 1707 # check every element
1708 1708 if not isinstance(line, string_types):
1709 1709 raise TypeError(msg)
1710 1710 return stb
1711 1711
1712 1712 if handler is None:
1713 1713 wrapped = dummy_handler
1714 1714 else:
1715 1715 def wrapped(self,etype,value,tb,tb_offset=None):
1716 1716 """wrap CustomTB handler, to protect IPython from user code
1717 1717
1718 1718 This makes it harder (but not impossible) for custom exception
1719 1719 handlers to crash IPython.
1720 1720 """
1721 1721 try:
1722 1722 stb = handler(self,etype,value,tb,tb_offset=tb_offset)
1723 1723 return validate_stb(stb)
1724 1724 except:
1725 1725 # clear custom handler immediately
1726 1726 self.set_custom_exc((), None)
1727 1727 print("Custom TB Handler failed, unregistering", file=io.stderr)
1728 1728 # show the exception in handler first
1729 1729 stb = self.InteractiveTB.structured_traceback(*sys.exc_info())
1730 1730 print(self.InteractiveTB.stb2text(stb), file=io.stdout)
1731 1731 print("The original exception:", file=io.stdout)
1732 1732 stb = self.InteractiveTB.structured_traceback(
1733 1733 (etype,value,tb), tb_offset=tb_offset
1734 1734 )
1735 1735 return stb
1736 1736
1737 1737 self.CustomTB = types.MethodType(wrapped,self)
1738 1738 self.custom_exceptions = exc_tuple
1739 1739
1740 1740 def excepthook(self, etype, value, tb):
1741 1741 """One more defense for GUI apps that call sys.excepthook.
1742 1742
1743 1743 GUI frameworks like wxPython trap exceptions and call
1744 1744 sys.excepthook themselves. I guess this is a feature that
1745 1745 enables them to keep running after exceptions that would
1746 1746 otherwise kill their mainloop. This is a bother for IPython
1747 1747 which excepts to catch all of the program exceptions with a try:
1748 1748 except: statement.
1749 1749
1750 1750 Normally, IPython sets sys.excepthook to a CrashHandler instance, so if
1751 1751 any app directly invokes sys.excepthook, it will look to the user like
1752 1752 IPython crashed. In order to work around this, we can disable the
1753 1753 CrashHandler and replace it with this excepthook instead, which prints a
1754 1754 regular traceback using our InteractiveTB. In this fashion, apps which
1755 1755 call sys.excepthook will generate a regular-looking exception from
1756 1756 IPython, and the CrashHandler will only be triggered by real IPython
1757 1757 crashes.
1758 1758
1759 1759 This hook should be used sparingly, only in places which are not likely
1760 1760 to be true IPython errors.
1761 1761 """
1762 1762 self.showtraceback((etype, value, tb), tb_offset=0)
1763 1763
1764 1764 def _get_exc_info(self, exc_tuple=None):
1765 1765 """get exc_info from a given tuple, sys.exc_info() or sys.last_type etc.
1766 1766
1767 1767 Ensures sys.last_type,value,traceback hold the exc_info we found,
1768 1768 from whichever source.
1769 1769
1770 1770 raises ValueError if none of these contain any information
1771 1771 """
1772 1772 if exc_tuple is None:
1773 1773 etype, value, tb = sys.exc_info()
1774 1774 else:
1775 1775 etype, value, tb = exc_tuple
1776 1776
1777 1777 if etype is None:
1778 1778 if hasattr(sys, 'last_type'):
1779 1779 etype, value, tb = sys.last_type, sys.last_value, \
1780 1780 sys.last_traceback
1781 1781
1782 1782 if etype is None:
1783 1783 raise ValueError("No exception to find")
1784 1784
1785 1785 # Now store the exception info in sys.last_type etc.
1786 1786 # WARNING: these variables are somewhat deprecated and not
1787 1787 # necessarily safe to use in a threaded environment, but tools
1788 1788 # like pdb depend on their existence, so let's set them. If we
1789 1789 # find problems in the field, we'll need to revisit their use.
1790 1790 sys.last_type = etype
1791 1791 sys.last_value = value
1792 1792 sys.last_traceback = tb
1793 1793
1794 1794 return etype, value, tb
1795 1795
1796 1796 def show_usage_error(self, exc):
1797 1797 """Show a short message for UsageErrors
1798 1798
1799 1799 These are special exceptions that shouldn't show a traceback.
1800 1800 """
1801 1801 self.write_err("UsageError: %s" % exc)
1802 1802
1803 1803 def get_exception_only(self, exc_tuple=None):
1804 1804 """
1805 1805 Return as a string (ending with a newline) the exception that
1806 1806 just occurred, without any traceback.
1807 1807 """
1808 1808 etype, value, tb = self._get_exc_info(exc_tuple)
1809 1809 msg = traceback.format_exception_only(etype, value)
1810 1810 return ''.join(msg)
1811 1811
1812 1812 def showtraceback(self, exc_tuple=None, filename=None, tb_offset=None,
1813 1813 exception_only=False):
1814 1814 """Display the exception that just occurred.
1815 1815
1816 1816 If nothing is known about the exception, this is the method which
1817 1817 should be used throughout the code for presenting user tracebacks,
1818 1818 rather than directly invoking the InteractiveTB object.
1819 1819
1820 1820 A specific showsyntaxerror() also exists, but this method can take
1821 1821 care of calling it if needed, so unless you are explicitly catching a
1822 1822 SyntaxError exception, don't try to analyze the stack manually and
1823 1823 simply call this method."""
1824 1824
1825 1825 try:
1826 1826 try:
1827 1827 etype, value, tb = self._get_exc_info(exc_tuple)
1828 1828 except ValueError:
1829 1829 self.write_err('No traceback available to show.\n')
1830 1830 return
1831 1831
1832 1832 if issubclass(etype, SyntaxError):
1833 1833 # Though this won't be called by syntax errors in the input
1834 1834 # line, there may be SyntaxError cases with imported code.
1835 1835 self.showsyntaxerror(filename)
1836 1836 elif etype is UsageError:
1837 1837 self.show_usage_error(value)
1838 1838 else:
1839 1839 if exception_only:
1840 1840 stb = ['An exception has occurred, use %tb to see '
1841 1841 'the full traceback.\n']
1842 1842 stb.extend(self.InteractiveTB.get_exception_only(etype,
1843 1843 value))
1844 1844 else:
1845 1845 try:
1846 1846 # Exception classes can customise their traceback - we
1847 1847 # use this in IPython.parallel for exceptions occurring
1848 1848 # in the engines. This should return a list of strings.
1849 1849 stb = value._render_traceback_()
1850 1850 except Exception:
1851 1851 stb = self.InteractiveTB.structured_traceback(etype,
1852 1852 value, tb, tb_offset=tb_offset)
1853 1853
1854 1854 self._showtraceback(etype, value, stb)
1855 1855 if self.call_pdb:
1856 1856 # drop into debugger
1857 1857 self.debugger(force=True)
1858 1858 return
1859 1859
1860 1860 # Actually show the traceback
1861 1861 self._showtraceback(etype, value, stb)
1862 1862
1863 1863 except KeyboardInterrupt:
1864 1864 self.write_err('\n' + self.get_exception_only())
1865 1865
1866 1866 def _showtraceback(self, etype, evalue, stb):
1867 1867 """Actually show a traceback.
1868 1868
1869 1869 Subclasses may override this method to put the traceback on a different
1870 1870 place, like a side channel.
1871 1871 """
1872 1872 print(self.InteractiveTB.stb2text(stb), file=io.stdout)
1873 1873
1874 1874 def showsyntaxerror(self, filename=None):
1875 1875 """Display the syntax error that just occurred.
1876 1876
1877 1877 This doesn't display a stack trace because there isn't one.
1878 1878
1879 1879 If a filename is given, it is stuffed in the exception instead
1880 1880 of what was there before (because Python's parser always uses
1881 1881 "<string>" when reading from a string).
1882 1882 """
1883 1883 etype, value, last_traceback = self._get_exc_info()
1884 1884
1885 1885 if filename and issubclass(etype, SyntaxError):
1886 1886 try:
1887 1887 value.filename = filename
1888 1888 except:
1889 1889 # Not the format we expect; leave it alone
1890 1890 pass
1891 1891
1892 1892 stb = self.SyntaxTB.structured_traceback(etype, value, [])
1893 1893 self._showtraceback(etype, value, stb)
1894 1894
1895 1895 # This is overridden in TerminalInteractiveShell to show a message about
1896 1896 # the %paste magic.
1897 1897 def showindentationerror(self):
1898 1898 """Called by run_cell when there's an IndentationError in code entered
1899 1899 at the prompt.
1900 1900
1901 1901 This is overridden in TerminalInteractiveShell to show a message about
1902 1902 the %paste magic."""
1903 1903 self.showsyntaxerror()
1904 1904
1905 1905 #-------------------------------------------------------------------------
1906 1906 # Things related to readline
1907 1907 #-------------------------------------------------------------------------
1908 1908
1909 1909 def init_readline(self):
1910 1910 """Command history completion/saving/reloading."""
1911 1911
1912 1912 if self.readline_use:
1913 1913 import IPython.utils.rlineimpl as readline
1914 1914
1915 1915 self.rl_next_input = None
1916 1916 self.rl_do_indent = False
1917 1917
1918 1918 if not self.readline_use or not readline.have_readline:
1919 1919 self.has_readline = False
1920 1920 self.readline = None
1921 1921 # Set a number of methods that depend on readline to be no-op
1922 1922 self.readline_no_record = no_op_context
1923 1923 self.set_readline_completer = no_op
1924 1924 self.set_custom_completer = no_op
1925 1925 if self.readline_use:
1926 1926 warn('Readline services not available or not loaded.')
1927 1927 else:
1928 1928 self.has_readline = True
1929 1929 self.readline = readline
1930 1930 sys.modules['readline'] = readline
1931 1931
1932 1932 # Platform-specific configuration
1933 1933 if os.name == 'nt':
1934 1934 # FIXME - check with Frederick to see if we can harmonize
1935 1935 # naming conventions with pyreadline to avoid this
1936 1936 # platform-dependent check
1937 1937 self.readline_startup_hook = readline.set_pre_input_hook
1938 1938 else:
1939 1939 self.readline_startup_hook = readline.set_startup_hook
1940 1940
1941 1941 # Readline config order:
1942 1942 # - IPython config (default value)
1943 1943 # - custom inputrc
1944 1944 # - IPython config (user customized)
1945 1945
1946 1946 # load IPython config before inputrc if default
1947 1947 # skip if libedit because parse_and_bind syntax is different
1948 1948 if not self._custom_readline_config and not readline.uses_libedit:
1949 1949 for rlcommand in self.readline_parse_and_bind:
1950 1950 readline.parse_and_bind(rlcommand)
1951 1951
1952 1952 # Load user's initrc file (readline config)
1953 1953 # Or if libedit is used, load editrc.
1954 1954 inputrc_name = os.environ.get('INPUTRC')
1955 1955 if inputrc_name is None:
1956 1956 inputrc_name = '.inputrc'
1957 1957 if readline.uses_libedit:
1958 1958 inputrc_name = '.editrc'
1959 1959 inputrc_name = os.path.join(self.home_dir, inputrc_name)
1960 1960 if os.path.isfile(inputrc_name):
1961 1961 try:
1962 1962 readline.read_init_file(inputrc_name)
1963 1963 except:
1964 1964 warn('Problems reading readline initialization file <%s>'
1965 1965 % inputrc_name)
1966 1966
1967 1967 # load IPython config after inputrc if user has customized
1968 1968 if self._custom_readline_config:
1969 1969 for rlcommand in self.readline_parse_and_bind:
1970 1970 readline.parse_and_bind(rlcommand)
1971 1971
1972 1972 # Remove some chars from the delimiters list. If we encounter
1973 1973 # unicode chars, discard them.
1974 1974 delims = readline.get_completer_delims()
1975 1975 if not py3compat.PY3:
1976 1976 delims = delims.encode("ascii", "ignore")
1977 1977 for d in self.readline_remove_delims:
1978 1978 delims = delims.replace(d, "")
1979 1979 delims = delims.replace(ESC_MAGIC, '')
1980 1980 readline.set_completer_delims(delims)
1981 1981 # Store these so we can restore them if something like rpy2 modifies
1982 1982 # them.
1983 1983 self.readline_delims = delims
1984 1984 # otherwise we end up with a monster history after a while:
1985 1985 readline.set_history_length(self.history_length)
1986 1986
1987 1987 self.refill_readline_hist()
1988 1988 self.readline_no_record = ReadlineNoRecord(self)
1989 1989
1990 1990 # Configure auto-indent for all platforms
1991 1991 self.set_autoindent(self.autoindent)
1992 1992
1993 1993 def refill_readline_hist(self):
1994 1994 # Load the last 1000 lines from history
1995 1995 self.readline.clear_history()
1996 1996 stdin_encoding = sys.stdin.encoding or "utf-8"
1997 1997 last_cell = u""
1998 1998 for _, _, cell in self.history_manager.get_tail(1000,
1999 1999 include_latest=True):
2000 2000 # Ignore blank lines and consecutive duplicates
2001 2001 cell = cell.rstrip()
2002 2002 if cell and (cell != last_cell):
2003 2003 try:
2004 2004 if self.multiline_history:
2005 2005 self.readline.add_history(py3compat.unicode_to_str(cell,
2006 2006 stdin_encoding))
2007 2007 else:
2008 2008 for line in cell.splitlines():
2009 2009 self.readline.add_history(py3compat.unicode_to_str(line,
2010 2010 stdin_encoding))
2011 2011 last_cell = cell
2012 2012
2013 2013 except TypeError:
2014 2014 # The history DB can get corrupted so it returns strings
2015 2015 # containing null bytes, which readline objects to.
2016 2016 continue
2017 2017
2018 2018 @skip_doctest
2019 2019 def set_next_input(self, s, replace=False):
2020 2020 """ Sets the 'default' input string for the next command line.
2021 2021
2022 2022 Requires readline.
2023 2023
2024 2024 Example::
2025 2025
2026 2026 In [1]: _ip.set_next_input("Hello Word")
2027 2027 In [2]: Hello Word_ # cursor is here
2028 2028 """
2029 2029 self.rl_next_input = py3compat.cast_bytes_py2(s)
2030 2030
2031 2031 # Maybe move this to the terminal subclass?
2032 2032 def pre_readline(self):
2033 2033 """readline hook to be used at the start of each line.
2034 2034
2035 2035 Currently it handles auto-indent only."""
2036 2036
2037 2037 if self.rl_do_indent:
2038 2038 self.readline.insert_text(self._indent_current_str())
2039 2039 if self.rl_next_input is not None:
2040 2040 self.readline.insert_text(self.rl_next_input)
2041 2041 self.rl_next_input = None
2042 2042
2043 2043 def _indent_current_str(self):
2044 2044 """return the current level of indentation as a string"""
2045 2045 return self.input_splitter.indent_spaces * ' '
2046 2046
2047 2047 #-------------------------------------------------------------------------
2048 2048 # Things related to text completion
2049 2049 #-------------------------------------------------------------------------
2050 2050
2051 2051 def init_completer(self):
2052 2052 """Initialize the completion machinery.
2053 2053
2054 2054 This creates completion machinery that can be used by client code,
2055 2055 either interactively in-process (typically triggered by the readline
2056 2056 library), programatically (such as in test suites) or out-of-prcess
2057 2057 (typically over the network by remote frontends).
2058 2058 """
2059 2059 from IPython.core.completer import IPCompleter
2060 2060 from IPython.core.completerlib import (module_completer,
2061 2061 magic_run_completer, cd_completer, reset_completer)
2062 2062
2063 2063 self.Completer = IPCompleter(shell=self,
2064 2064 namespace=self.user_ns,
2065 2065 global_namespace=self.user_global_ns,
2066 2066 use_readline=self.has_readline,
2067 2067 parent=self,
2068 2068 )
2069 2069 self.configurables.append(self.Completer)
2070 2070
2071 2071 # Add custom completers to the basic ones built into IPCompleter
2072 2072 sdisp = self.strdispatchers.get('complete_command', StrDispatch())
2073 2073 self.strdispatchers['complete_command'] = sdisp
2074 2074 self.Completer.custom_completers = sdisp
2075 2075
2076 2076 self.set_hook('complete_command', module_completer, str_key = 'import')
2077 2077 self.set_hook('complete_command', module_completer, str_key = 'from')
2078 2078 self.set_hook('complete_command', magic_run_completer, str_key = '%run')
2079 2079 self.set_hook('complete_command', cd_completer, str_key = '%cd')
2080 2080 self.set_hook('complete_command', reset_completer, str_key = '%reset')
2081 2081
2082 2082 # Only configure readline if we truly are using readline. IPython can
2083 2083 # do tab-completion over the network, in GUIs, etc, where readline
2084 2084 # itself may be absent
2085 2085 if self.has_readline:
2086 2086 self.set_readline_completer()
2087 2087
2088 2088 def complete(self, text, line=None, cursor_pos=None):
2089 2089 """Return the completed text and a list of completions.
2090 2090
2091 2091 Parameters
2092 2092 ----------
2093 2093
2094 2094 text : string
2095 2095 A string of text to be completed on. It can be given as empty and
2096 2096 instead a line/position pair are given. In this case, the
2097 2097 completer itself will split the line like readline does.
2098 2098
2099 2099 line : string, optional
2100 2100 The complete line that text is part of.
2101 2101
2102 2102 cursor_pos : int, optional
2103 2103 The position of the cursor on the input line.
2104 2104
2105 2105 Returns
2106 2106 -------
2107 2107 text : string
2108 2108 The actual text that was completed.
2109 2109
2110 2110 matches : list
2111 2111 A sorted list with all possible completions.
2112 2112
2113 2113 The optional arguments allow the completion to take more context into
2114 2114 account, and are part of the low-level completion API.
2115 2115
2116 2116 This is a wrapper around the completion mechanism, similar to what
2117 2117 readline does at the command line when the TAB key is hit. By
2118 2118 exposing it as a method, it can be used by other non-readline
2119 2119 environments (such as GUIs) for text completion.
2120 2120
2121 2121 Simple usage example:
2122 2122
2123 2123 In [1]: x = 'hello'
2124 2124
2125 2125 In [2]: _ip.complete('x.l')
2126 2126 Out[2]: ('x.l', ['x.ljust', 'x.lower', 'x.lstrip'])
2127 2127 """
2128 2128
2129 2129 # Inject names into __builtin__ so we can complete on the added names.
2130 2130 with self.builtin_trap:
2131 2131 return self.Completer.complete(text, line, cursor_pos)
2132 2132
2133 2133 def set_custom_completer(self, completer, pos=0):
2134 2134 """Adds a new custom completer function.
2135 2135
2136 2136 The position argument (defaults to 0) is the index in the completers
2137 2137 list where you want the completer to be inserted."""
2138 2138
2139 2139 newcomp = types.MethodType(completer,self.Completer)
2140 2140 self.Completer.matchers.insert(pos,newcomp)
2141 2141
2142 2142 def set_readline_completer(self):
2143 2143 """Reset readline's completer to be our own."""
2144 2144 self.readline.set_completer(self.Completer.rlcomplete)
2145 2145
2146 2146 def set_completer_frame(self, frame=None):
2147 2147 """Set the frame of the completer."""
2148 2148 if frame:
2149 2149 self.Completer.namespace = frame.f_locals
2150 2150 self.Completer.global_namespace = frame.f_globals
2151 2151 else:
2152 2152 self.Completer.namespace = self.user_ns
2153 2153 self.Completer.global_namespace = self.user_global_ns
2154 2154
2155 2155 #-------------------------------------------------------------------------
2156 2156 # Things related to magics
2157 2157 #-------------------------------------------------------------------------
2158 2158
2159 2159 def init_magics(self):
2160 2160 from IPython.core import magics as m
2161 2161 self.magics_manager = magic.MagicsManager(shell=self,
2162 2162 parent=self,
2163 2163 user_magics=m.UserMagics(self))
2164 2164 self.configurables.append(self.magics_manager)
2165 2165
2166 2166 # Expose as public API from the magics manager
2167 2167 self.register_magics = self.magics_manager.register
2168 2168 self.define_magic = self.magics_manager.define_magic
2169 2169
2170 2170 self.register_magics(m.AutoMagics, m.BasicMagics, m.CodeMagics,
2171 2171 m.ConfigMagics, m.DeprecatedMagics, m.DisplayMagics, m.ExecutionMagics,
2172 2172 m.ExtensionMagics, m.HistoryMagics, m.LoggingMagics,
2173 2173 m.NamespaceMagics, m.OSMagics, m.PylabMagics, m.ScriptMagics,
2174 2174 )
2175 2175
2176 2176 # Register Magic Aliases
2177 2177 mman = self.magics_manager
2178 2178 # FIXME: magic aliases should be defined by the Magics classes
2179 2179 # or in MagicsManager, not here
2180 2180 mman.register_alias('ed', 'edit')
2181 2181 mman.register_alias('hist', 'history')
2182 2182 mman.register_alias('rep', 'recall')
2183 2183 mman.register_alias('SVG', 'svg', 'cell')
2184 2184 mman.register_alias('HTML', 'html', 'cell')
2185 2185 mman.register_alias('file', 'writefile', 'cell')
2186 2186
2187 2187 # FIXME: Move the color initialization to the DisplayHook, which
2188 2188 # should be split into a prompt manager and displayhook. We probably
2189 2189 # even need a centralize colors management object.
2190 2190 self.magic('colors %s' % self.colors)
2191 2191
2192 2192 # Defined here so that it's included in the documentation
2193 2193 @functools.wraps(magic.MagicsManager.register_function)
2194 2194 def register_magic_function(self, func, magic_kind='line', magic_name=None):
2195 2195 self.magics_manager.register_function(func,
2196 2196 magic_kind=magic_kind, magic_name=magic_name)
2197 2197
2198 2198 def run_line_magic(self, magic_name, line):
2199 2199 """Execute the given line magic.
2200 2200
2201 2201 Parameters
2202 2202 ----------
2203 2203 magic_name : str
2204 2204 Name of the desired magic function, without '%' prefix.
2205 2205
2206 2206 line : str
2207 2207 The rest of the input line as a single string.
2208 2208 """
2209 2209 fn = self.find_line_magic(magic_name)
2210 2210 if fn is None:
2211 2211 cm = self.find_cell_magic(magic_name)
2212 2212 etpl = "Line magic function `%%%s` not found%s."
2213 2213 extra = '' if cm is None else (' (But cell magic `%%%%%s` exists, '
2214 2214 'did you mean that instead?)' % magic_name )
2215 2215 error(etpl % (magic_name, extra))
2216 2216 else:
2217 2217 # Note: this is the distance in the stack to the user's frame.
2218 2218 # This will need to be updated if the internal calling logic gets
2219 2219 # refactored, or else we'll be expanding the wrong variables.
2220 2220 stack_depth = 2
2221 2221 magic_arg_s = self.var_expand(line, stack_depth)
2222 2222 # Put magic args in a list so we can call with f(*a) syntax
2223 2223 args = [magic_arg_s]
2224 2224 kwargs = {}
2225 2225 # Grab local namespace if we need it:
2226 2226 if getattr(fn, "needs_local_scope", False):
2227 2227 kwargs['local_ns'] = sys._getframe(stack_depth).f_locals
2228 2228 with self.builtin_trap:
2229 2229 result = fn(*args,**kwargs)
2230 2230 return result
2231 2231
2232 2232 def run_cell_magic(self, magic_name, line, cell):
2233 2233 """Execute the given cell magic.
2234 2234
2235 2235 Parameters
2236 2236 ----------
2237 2237 magic_name : str
2238 2238 Name of the desired magic function, without '%' prefix.
2239 2239
2240 2240 line : str
2241 2241 The rest of the first input line as a single string.
2242 2242
2243 2243 cell : str
2244 2244 The body of the cell as a (possibly multiline) string.
2245 2245 """
2246 2246 fn = self.find_cell_magic(magic_name)
2247 2247 if fn is None:
2248 2248 lm = self.find_line_magic(magic_name)
2249 2249 etpl = "Cell magic `%%{0}` not found{1}."
2250 2250 extra = '' if lm is None else (' (But line magic `%{0}` exists, '
2251 2251 'did you mean that instead?)'.format(magic_name))
2252 2252 error(etpl.format(magic_name, extra))
2253 2253 elif cell == '':
2254 2254 message = '%%{0} is a cell magic, but the cell body is empty.'.format(magic_name)
2255 2255 if self.find_line_magic(magic_name) is not None:
2256 2256 message += ' Did you mean the line magic %{0} (single %)?'.format(magic_name)
2257 2257 raise UsageError(message)
2258 2258 else:
2259 2259 # Note: this is the distance in the stack to the user's frame.
2260 2260 # This will need to be updated if the internal calling logic gets
2261 2261 # refactored, or else we'll be expanding the wrong variables.
2262 2262 stack_depth = 2
2263 2263 magic_arg_s = self.var_expand(line, stack_depth)
2264 2264 with self.builtin_trap:
2265 2265 result = fn(magic_arg_s, cell)
2266 2266 return result
2267 2267
2268 2268 def find_line_magic(self, magic_name):
2269 2269 """Find and return a line magic by name.
2270 2270
2271 2271 Returns None if the magic isn't found."""
2272 2272 return self.magics_manager.magics['line'].get(magic_name)
2273 2273
2274 2274 def find_cell_magic(self, magic_name):
2275 2275 """Find and return a cell magic by name.
2276 2276
2277 2277 Returns None if the magic isn't found."""
2278 2278 return self.magics_manager.magics['cell'].get(magic_name)
2279 2279
2280 2280 def find_magic(self, magic_name, magic_kind='line'):
2281 2281 """Find and return a magic of the given type by name.
2282 2282
2283 2283 Returns None if the magic isn't found."""
2284 2284 return self.magics_manager.magics[magic_kind].get(magic_name)
2285 2285
2286 2286 def magic(self, arg_s):
2287 2287 """DEPRECATED. Use run_line_magic() instead.
2288 2288
2289 2289 Call a magic function by name.
2290 2290
2291 2291 Input: a string containing the name of the magic function to call and
2292 2292 any additional arguments to be passed to the magic.
2293 2293
2294 2294 magic('name -opt foo bar') is equivalent to typing at the ipython
2295 2295 prompt:
2296 2296
2297 2297 In[1]: %name -opt foo bar
2298 2298
2299 2299 To call a magic without arguments, simply use magic('name').
2300 2300
2301 2301 This provides a proper Python function to call IPython's magics in any
2302 2302 valid Python code you can type at the interpreter, including loops and
2303 2303 compound statements.
2304 2304 """
2305 2305 # TODO: should we issue a loud deprecation warning here?
2306 2306 magic_name, _, magic_arg_s = arg_s.partition(' ')
2307 2307 magic_name = magic_name.lstrip(prefilter.ESC_MAGIC)
2308 2308 return self.run_line_magic(magic_name, magic_arg_s)
2309 2309
2310 2310 #-------------------------------------------------------------------------
2311 2311 # Things related to macros
2312 2312 #-------------------------------------------------------------------------
2313 2313
2314 2314 def define_macro(self, name, themacro):
2315 2315 """Define a new macro
2316 2316
2317 2317 Parameters
2318 2318 ----------
2319 2319 name : str
2320 2320 The name of the macro.
2321 2321 themacro : str or Macro
2322 2322 The action to do upon invoking the macro. If a string, a new
2323 2323 Macro object is created by passing the string to it.
2324 2324 """
2325 2325
2326 2326 from IPython.core import macro
2327 2327
2328 2328 if isinstance(themacro, string_types):
2329 2329 themacro = macro.Macro(themacro)
2330 2330 if not isinstance(themacro, macro.Macro):
2331 2331 raise ValueError('A macro must be a string or a Macro instance.')
2332 2332 self.user_ns[name] = themacro
2333 2333
2334 2334 #-------------------------------------------------------------------------
2335 2335 # Things related to the running of system commands
2336 2336 #-------------------------------------------------------------------------
2337 2337
2338 2338 def system_piped(self, cmd):
2339 2339 """Call the given cmd in a subprocess, piping stdout/err
2340 2340
2341 2341 Parameters
2342 2342 ----------
2343 2343 cmd : str
2344 2344 Command to execute (can not end in '&', as background processes are
2345 2345 not supported. Should not be a command that expects input
2346 2346 other than simple text.
2347 2347 """
2348 2348 if cmd.rstrip().endswith('&'):
2349 2349 # this is *far* from a rigorous test
2350 2350 # We do not support backgrounding processes because we either use
2351 2351 # pexpect or pipes to read from. Users can always just call
2352 2352 # os.system() or use ip.system=ip.system_raw
2353 2353 # if they really want a background process.
2354 2354 raise OSError("Background processes not supported.")
2355 2355
2356 2356 # we explicitly do NOT return the subprocess status code, because
2357 2357 # a non-None value would trigger :func:`sys.displayhook` calls.
2358 2358 # Instead, we store the exit_code in user_ns.
2359 2359 self.user_ns['_exit_code'] = system(self.var_expand(cmd, depth=1))
2360 2360
2361 2361 def system_raw(self, cmd):
2362 2362 """Call the given cmd in a subprocess using os.system on Windows or
2363 2363 subprocess.call using the system shell on other platforms.
2364 2364
2365 2365 Parameters
2366 2366 ----------
2367 2367 cmd : str
2368 2368 Command to execute.
2369 2369 """
2370 2370 cmd = self.var_expand(cmd, depth=1)
2371 2371 # protect os.system from UNC paths on Windows, which it can't handle:
2372 2372 if sys.platform == 'win32':
2373 2373 from IPython.utils._process_win32 import AvoidUNCPath
2374 2374 with AvoidUNCPath() as path:
2375 2375 if path is not None:
2376 2376 cmd = '"pushd %s &&"%s' % (path, cmd)
2377 2377 cmd = py3compat.unicode_to_str(cmd)
2378 2378 try:
2379 2379 ec = os.system(cmd)
2380 2380 except KeyboardInterrupt:
2381 2381 self.write_err('\n' + self.get_exception_only())
2382 2382 ec = -2
2383 2383 else:
2384 2384 cmd = py3compat.unicode_to_str(cmd)
2385 2385 # For posix the result of the subprocess.call() below is an exit
2386 2386 # code, which by convention is zero for success, positive for
2387 2387 # program failure. Exit codes above 128 are reserved for signals,
2388 2388 # and the formula for converting a signal to an exit code is usually
2389 2389 # signal_number+128. To more easily differentiate between exit
2390 2390 # codes and signals, ipython uses negative numbers. For instance
2391 2391 # since control-c is signal 2 but exit code 130, ipython's
2392 2392 # _exit_code variable will read -2. Note that some shells like
2393 2393 # csh and fish don't follow sh/bash conventions for exit codes.
2394 2394 executable = os.environ.get('SHELL', None)
2395 2395 try:
2396 2396 # Use env shell instead of default /bin/sh
2397 2397 ec = subprocess.call(cmd, shell=True, executable=executable)
2398 2398 except KeyboardInterrupt:
2399 2399 # intercept control-C; a long traceback is not useful here
2400 2400 self.write_err('\n' + self.get_exception_only())
2401 2401 ec = 130
2402 2402 if ec > 128:
2403 2403 ec = -(ec - 128)
2404 2404
2405 2405 # We explicitly do NOT return the subprocess status code, because
2406 2406 # a non-None value would trigger :func:`sys.displayhook` calls.
2407 2407 # Instead, we store the exit_code in user_ns. Note the semantics
2408 2408 # of _exit_code: for control-c, _exit_code == -signal.SIGNIT,
2409 2409 # but raising SystemExit(_exit_code) will give status 254!
2410 2410 self.user_ns['_exit_code'] = ec
2411 2411
2412 2412 # use piped system by default, because it is better behaved
2413 2413 system = system_piped
2414 2414
2415 2415 def getoutput(self, cmd, split=True, depth=0):
2416 2416 """Get output (possibly including stderr) from a subprocess.
2417 2417
2418 2418 Parameters
2419 2419 ----------
2420 2420 cmd : str
2421 2421 Command to execute (can not end in '&', as background processes are
2422 2422 not supported.
2423 2423 split : bool, optional
2424 2424 If True, split the output into an IPython SList. Otherwise, an
2425 2425 IPython LSString is returned. These are objects similar to normal
2426 2426 lists and strings, with a few convenience attributes for easier
2427 2427 manipulation of line-based output. You can use '?' on them for
2428 2428 details.
2429 2429 depth : int, optional
2430 2430 How many frames above the caller are the local variables which should
2431 2431 be expanded in the command string? The default (0) assumes that the
2432 2432 expansion variables are in the stack frame calling this function.
2433 2433 """
2434 2434 if cmd.rstrip().endswith('&'):
2435 2435 # this is *far* from a rigorous test
2436 2436 raise OSError("Background processes not supported.")
2437 2437 out = getoutput(self.var_expand(cmd, depth=depth+1))
2438 2438 if split:
2439 2439 out = SList(out.splitlines())
2440 2440 else:
2441 2441 out = LSString(out)
2442 2442 return out
2443 2443
2444 2444 #-------------------------------------------------------------------------
2445 2445 # Things related to aliases
2446 2446 #-------------------------------------------------------------------------
2447 2447
2448 2448 def init_alias(self):
2449 2449 self.alias_manager = AliasManager(shell=self, parent=self)
2450 2450 self.configurables.append(self.alias_manager)
2451 2451
2452 2452 #-------------------------------------------------------------------------
2453 2453 # Things related to extensions
2454 2454 #-------------------------------------------------------------------------
2455 2455
2456 2456 def init_extension_manager(self):
2457 2457 self.extension_manager = ExtensionManager(shell=self, parent=self)
2458 2458 self.configurables.append(self.extension_manager)
2459 2459
2460 2460 #-------------------------------------------------------------------------
2461 2461 # Things related to payloads
2462 2462 #-------------------------------------------------------------------------
2463 2463
2464 2464 def init_payload(self):
2465 2465 self.payload_manager = PayloadManager(parent=self)
2466 2466 self.configurables.append(self.payload_manager)
2467 2467
2468 2468 #-------------------------------------------------------------------------
2469 2469 # Things related to the prefilter
2470 2470 #-------------------------------------------------------------------------
2471 2471
2472 2472 def init_prefilter(self):
2473 2473 self.prefilter_manager = PrefilterManager(shell=self, parent=self)
2474 2474 self.configurables.append(self.prefilter_manager)
2475 2475 # Ultimately this will be refactored in the new interpreter code, but
2476 2476 # for now, we should expose the main prefilter method (there's legacy
2477 2477 # code out there that may rely on this).
2478 2478 self.prefilter = self.prefilter_manager.prefilter_lines
2479 2479
2480 2480 def auto_rewrite_input(self, cmd):
2481 2481 """Print to the screen the rewritten form of the user's command.
2482 2482
2483 2483 This shows visual feedback by rewriting input lines that cause
2484 2484 automatic calling to kick in, like::
2485 2485
2486 2486 /f x
2487 2487
2488 2488 into::
2489 2489
2490 2490 ------> f(x)
2491 2491
2492 2492 after the user's input prompt. This helps the user understand that the
2493 2493 input line was transformed automatically by IPython.
2494 2494 """
2495 2495 if not self.show_rewritten_input:
2496 2496 return
2497 2497
2498 2498 rw = self.prompt_manager.render('rewrite') + cmd
2499 2499
2500 2500 try:
2501 2501 # plain ascii works better w/ pyreadline, on some machines, so
2502 2502 # we use it and only print uncolored rewrite if we have unicode
2503 2503 rw = str(rw)
2504 2504 print(rw, file=io.stdout)
2505 2505 except UnicodeEncodeError:
2506 2506 print("------> " + cmd)
2507 2507
2508 2508 #-------------------------------------------------------------------------
2509 2509 # Things related to extracting values/expressions from kernel and user_ns
2510 2510 #-------------------------------------------------------------------------
2511 2511
2512 2512 def _user_obj_error(self):
2513 2513 """return simple exception dict
2514 2514
2515 2515 for use in user_expressions
2516 2516 """
2517 2517
2518 2518 etype, evalue, tb = self._get_exc_info()
2519 2519 stb = self.InteractiveTB.get_exception_only(etype, evalue)
2520 2520
2521 2521 exc_info = {
2522 2522 u'status' : 'error',
2523 2523 u'traceback' : stb,
2524 2524 u'ename' : unicode_type(etype.__name__),
2525 2525 u'evalue' : py3compat.safe_unicode(evalue),
2526 2526 }
2527 2527
2528 2528 return exc_info
2529 2529
2530 2530 def _format_user_obj(self, obj):
2531 2531 """format a user object to display dict
2532 2532
2533 2533 for use in user_expressions
2534 2534 """
2535 2535
2536 2536 data, md = self.display_formatter.format(obj)
2537 2537 value = {
2538 2538 'status' : 'ok',
2539 2539 'data' : data,
2540 2540 'metadata' : md,
2541 2541 }
2542 2542 return value
2543 2543
2544 2544 def user_expressions(self, expressions):
2545 2545 """Evaluate a dict of expressions in the user's namespace.
2546 2546
2547 2547 Parameters
2548 2548 ----------
2549 2549 expressions : dict
2550 2550 A dict with string keys and string values. The expression values
2551 2551 should be valid Python expressions, each of which will be evaluated
2552 2552 in the user namespace.
2553 2553
2554 2554 Returns
2555 2555 -------
2556 2556 A dict, keyed like the input expressions dict, with the rich mime-typed
2557 2557 display_data of each value.
2558 2558 """
2559 2559 out = {}
2560 2560 user_ns = self.user_ns
2561 2561 global_ns = self.user_global_ns
2562 2562
2563 2563 for key, expr in iteritems(expressions):
2564 2564 try:
2565 2565 value = self._format_user_obj(eval(expr, global_ns, user_ns))
2566 2566 except:
2567 2567 value = self._user_obj_error()
2568 2568 out[key] = value
2569 2569 return out
2570 2570
2571 2571 #-------------------------------------------------------------------------
2572 2572 # Things related to the running of code
2573 2573 #-------------------------------------------------------------------------
2574 2574
2575 2575 def ex(self, cmd):
2576 2576 """Execute a normal python statement in user namespace."""
2577 2577 with self.builtin_trap:
2578 2578 exec(cmd, self.user_global_ns, self.user_ns)
2579 2579
2580 2580 def ev(self, expr):
2581 2581 """Evaluate python expression expr in user namespace.
2582 2582
2583 2583 Returns the result of evaluation
2584 2584 """
2585 2585 with self.builtin_trap:
2586 2586 return eval(expr, self.user_global_ns, self.user_ns)
2587 2587
2588 2588 def safe_execfile(self, fname, *where, **kw):
2589 2589 """A safe version of the builtin execfile().
2590 2590
2591 2591 This version will never throw an exception, but instead print
2592 2592 helpful error messages to the screen. This only works on pure
2593 2593 Python files with the .py extension.
2594 2594
2595 2595 Parameters
2596 2596 ----------
2597 2597 fname : string
2598 2598 The name of the file to be executed.
2599 2599 where : tuple
2600 2600 One or two namespaces, passed to execfile() as (globals,locals).
2601 2601 If only one is given, it is passed as both.
2602 2602 exit_ignore : bool (False)
2603 2603 If True, then silence SystemExit for non-zero status (it is always
2604 2604 silenced for zero status, as it is so common).
2605 2605 raise_exceptions : bool (False)
2606 2606 If True raise exceptions everywhere. Meant for testing.
2607 2607 shell_futures : bool (False)
2608 2608 If True, the code will share future statements with the interactive
2609 2609 shell. It will both be affected by previous __future__ imports, and
2610 2610 any __future__ imports in the code will affect the shell. If False,
2611 2611 __future__ imports are not shared in either direction.
2612 2612
2613 2613 """
2614 2614 kw.setdefault('exit_ignore', False)
2615 2615 kw.setdefault('raise_exceptions', False)
2616 2616 kw.setdefault('shell_futures', False)
2617 2617
2618 2618 fname = os.path.abspath(os.path.expanduser(fname))
2619 2619
2620 2620 # Make sure we can open the file
2621 2621 try:
2622 2622 with open(fname) as thefile:
2623 2623 pass
2624 2624 except:
2625 2625 warn('Could not open file <%s> for safe execution.' % fname)
2626 2626 return
2627 2627
2628 2628 # Find things also in current directory. This is needed to mimic the
2629 2629 # behavior of running a script from the system command line, where
2630 2630 # Python inserts the script's directory into sys.path
2631 2631 dname = os.path.dirname(fname)
2632 2632
2633 2633 with prepended_to_syspath(dname):
2634 2634 try:
2635 2635 glob, loc = (where + (None, ))[:2]
2636 2636 py3compat.execfile(
2637 2637 fname, glob, loc,
2638 2638 self.compile if kw['shell_futures'] else None)
2639 2639 except SystemExit as status:
2640 2640 # If the call was made with 0 or None exit status (sys.exit(0)
2641 2641 # or sys.exit() ), don't bother showing a traceback, as both of
2642 2642 # these are considered normal by the OS:
2643 2643 # > python -c'import sys;sys.exit(0)'; echo $?
2644 2644 # 0
2645 2645 # > python -c'import sys;sys.exit()'; echo $?
2646 2646 # 0
2647 2647 # For other exit status, we show the exception unless
2648 2648 # explicitly silenced, but only in short form.
2649 2649 if kw['raise_exceptions']:
2650 2650 raise
2651 2651 if status.code and not kw['exit_ignore']:
2652 2652 self.showtraceback(exception_only=True)
2653 2653 except:
2654 2654 if kw['raise_exceptions']:
2655 2655 raise
2656 2656 # tb offset is 2 because we wrap execfile
2657 2657 self.showtraceback(tb_offset=2)
2658 2658
2659 2659 def safe_execfile_ipy(self, fname, shell_futures=False):
2660 2660 """Like safe_execfile, but for .ipy or .ipynb files with IPython syntax.
2661 2661
2662 2662 Parameters
2663 2663 ----------
2664 2664 fname : str
2665 2665 The name of the file to execute. The filename must have a
2666 2666 .ipy or .ipynb extension.
2667 2667 shell_futures : bool (False)
2668 2668 If True, the code will share future statements with the interactive
2669 2669 shell. It will both be affected by previous __future__ imports, and
2670 2670 any __future__ imports in the code will affect the shell. If False,
2671 2671 __future__ imports are not shared in either direction.
2672 2672 """
2673 2673 fname = os.path.abspath(os.path.expanduser(fname))
2674 2674
2675 2675 # Make sure we can open the file
2676 2676 try:
2677 2677 with open(fname) as thefile:
2678 2678 pass
2679 2679 except:
2680 2680 warn('Could not open file <%s> for safe execution.' % fname)
2681 2681 return
2682 2682
2683 2683 # Find things also in current directory. This is needed to mimic the
2684 2684 # behavior of running a script from the system command line, where
2685 2685 # Python inserts the script's directory into sys.path
2686 2686 dname = os.path.dirname(fname)
2687 2687
2688 2688 def get_cells():
2689 2689 """generator for sequence of code blocks to run"""
2690 2690 if fname.endswith('.ipynb'):
2691 2691 from IPython.nbformat import read
2692 2692 with io_open(fname) as f:
2693 2693 nb = read(f, as_version=4)
2694 2694 if not nb.cells:
2695 2695 return
2696 2696 for cell in nb.cells:
2697 2697 if cell.cell_type == 'code':
2698 2698 yield cell.source
2699 2699 else:
2700 2700 with open(fname) as f:
2701 2701 yield f.read()
2702 2702
2703 2703 with prepended_to_syspath(dname):
2704 2704 try:
2705 2705 for cell in get_cells():
2706 2706 # self.run_cell currently captures all exceptions
2707 2707 # raised in user code. It would be nice if there were
2708 2708 # versions of run_cell that did raise, so
2709 2709 # we could catch the errors.
2710 2710 result = self.run_cell(cell, silent=True, shell_futures=shell_futures)
2711 2711 if not result.success:
2712 2712 break
2713 2713 except:
2714 2714 self.showtraceback()
2715 2715 warn('Unknown failure executing file: <%s>' % fname)
2716 2716
2717 2717 def safe_run_module(self, mod_name, where):
2718 2718 """A safe version of runpy.run_module().
2719 2719
2720 2720 This version will never throw an exception, but instead print
2721 2721 helpful error messages to the screen.
2722 2722
2723 2723 `SystemExit` exceptions with status code 0 or None are ignored.
2724 2724
2725 2725 Parameters
2726 2726 ----------
2727 2727 mod_name : string
2728 2728 The name of the module to be executed.
2729 2729 where : dict
2730 2730 The globals namespace.
2731 2731 """
2732 2732 try:
2733 2733 try:
2734 2734 where.update(
2735 2735 runpy.run_module(str(mod_name), run_name="__main__",
2736 2736 alter_sys=True)
2737 2737 )
2738 2738 except SystemExit as status:
2739 2739 if status.code:
2740 2740 raise
2741 2741 except:
2742 2742 self.showtraceback()
2743 2743 warn('Unknown failure executing module: <%s>' % mod_name)
2744 2744
2745 2745 def _run_cached_cell_magic(self, magic_name, line):
2746 2746 """Special method to call a cell magic with the data stored in self.
2747 2747 """
2748 2748 cell = self._current_cell_magic_body
2749 2749 self._current_cell_magic_body = None
2750 2750 return self.run_cell_magic(magic_name, line, cell)
2751 2751
2752 2752 def run_cell(self, raw_cell, store_history=False, silent=False, shell_futures=True):
2753 2753 """Run a complete IPython cell.
2754 2754
2755 2755 Parameters
2756 2756 ----------
2757 2757 raw_cell : str
2758 2758 The code (including IPython code such as %magic functions) to run.
2759 2759 store_history : bool
2760 2760 If True, the raw and translated cell will be stored in IPython's
2761 2761 history. For user code calling back into IPython's machinery, this
2762 2762 should be set to False.
2763 2763 silent : bool
2764 2764 If True, avoid side-effects, such as implicit displayhooks and
2765 2765 and logging. silent=True forces store_history=False.
2766 2766 shell_futures : bool
2767 2767 If True, the code will share future statements with the interactive
2768 2768 shell. It will both be affected by previous __future__ imports, and
2769 2769 any __future__ imports in the code will affect the shell. If False,
2770 2770 __future__ imports are not shared in either direction.
2771 2771
2772 2772 Returns
2773 2773 -------
2774 2774 result : :class:`ExecutionResult`
2775 2775 """
2776 2776 result = ExecutionResult()
2777 2777
2778 2778 if (not raw_cell) or raw_cell.isspace():
2779 2779 return result
2780 2780
2781 2781 if silent:
2782 2782 store_history = False
2783 2783
2784 2784 if store_history:
2785 2785 result.execution_count = self.execution_count
2786 2786
2787 2787 def error_before_exec(value):
2788 2788 result.error_before_exec = value
2789 2789 return result
2790 2790
2791 2791 self.events.trigger('pre_execute')
2792 2792 if not silent:
2793 2793 self.events.trigger('pre_run_cell')
2794 2794
2795 2795 # If any of our input transformation (input_transformer_manager or
2796 2796 # prefilter_manager) raises an exception, we store it in this variable
2797 2797 # so that we can display the error after logging the input and storing
2798 2798 # it in the history.
2799 2799 preprocessing_exc_tuple = None
2800 2800 try:
2801 2801 # Static input transformations
2802 2802 cell = self.input_transformer_manager.transform_cell(raw_cell)
2803 2803 except SyntaxError:
2804 2804 preprocessing_exc_tuple = sys.exc_info()
2805 2805 cell = raw_cell # cell has to exist so it can be stored/logged
2806 2806 else:
2807 2807 if len(cell.splitlines()) == 1:
2808 2808 # Dynamic transformations - only applied for single line commands
2809 2809 with self.builtin_trap:
2810 2810 try:
2811 2811 # use prefilter_lines to handle trailing newlines
2812 2812 # restore trailing newline for ast.parse
2813 2813 cell = self.prefilter_manager.prefilter_lines(cell) + '\n'
2814 2814 except Exception:
2815 2815 # don't allow prefilter errors to crash IPython
2816 2816 preprocessing_exc_tuple = sys.exc_info()
2817 2817
2818 2818 # Store raw and processed history
2819 2819 if store_history:
2820 2820 self.history_manager.store_inputs(self.execution_count,
2821 2821 cell, raw_cell)
2822 2822 if not silent:
2823 2823 self.logger.log(cell, raw_cell)
2824 2824
2825 2825 # Display the exception if input processing failed.
2826 2826 if preprocessing_exc_tuple is not None:
2827 2827 self.showtraceback(preprocessing_exc_tuple)
2828 2828 if store_history:
2829 2829 self.execution_count += 1
2830 2830 return error_before_exec(preprocessing_exc_tuple[2])
2831 2831
2832 2832 # Our own compiler remembers the __future__ environment. If we want to
2833 2833 # run code with a separate __future__ environment, use the default
2834 2834 # compiler
2835 2835 compiler = self.compile if shell_futures else CachingCompiler()
2836 2836
2837 2837 with self.builtin_trap:
2838 2838 cell_name = self.compile.cache(cell, self.execution_count)
2839 2839
2840 2840 with self.display_trap:
2841 2841 # Compile to bytecode
2842 2842 try:
2843 2843 code_ast = compiler.ast_parse(cell, filename=cell_name)
2844 2844 except IndentationError as e:
2845 2845 self.showindentationerror()
2846 2846 if store_history:
2847 2847 self.execution_count += 1
2848 2848 return error_before_exec(e)
2849 2849 except (OverflowError, SyntaxError, ValueError, TypeError,
2850 2850 MemoryError) as e:
2851 2851 self.showsyntaxerror()
2852 2852 if store_history:
2853 2853 self.execution_count += 1
2854 2854 return error_before_exec(e)
2855 2855
2856 2856 # Apply AST transformations
2857 2857 try:
2858 2858 code_ast = self.transform_ast(code_ast)
2859 2859 except InputRejected as e:
2860 2860 self.showtraceback()
2861 2861 if store_history:
2862 2862 self.execution_count += 1
2863 2863 return error_before_exec(e)
2864 2864
2865 2865 # Give the displayhook a reference to our ExecutionResult so it
2866 2866 # can fill in the output value.
2867 2867 self.displayhook.exec_result = result
2868 2868
2869 2869 # Execute the user code
2870 2870 interactivity = "none" if silent else self.ast_node_interactivity
2871 2871 self.run_ast_nodes(code_ast.body, cell_name,
2872 2872 interactivity=interactivity, compiler=compiler, result=result)
2873 2873
2874 2874 # Reset this so later displayed values do not modify the
2875 2875 # ExecutionResult
2876 2876 self.displayhook.exec_result = None
2877 2877
2878 2878 self.events.trigger('post_execute')
2879 2879 if not silent:
2880 2880 self.events.trigger('post_run_cell')
2881 2881
2882 2882 if store_history:
2883 2883 # Write output to the database. Does nothing unless
2884 2884 # history output logging is enabled.
2885 2885 self.history_manager.store_output(self.execution_count)
2886 2886 # Each cell is a *single* input, regardless of how many lines it has
2887 2887 self.execution_count += 1
2888 2888
2889 2889 return result
2890 2890
2891 2891 def transform_ast(self, node):
2892 2892 """Apply the AST transformations from self.ast_transformers
2893 2893
2894 2894 Parameters
2895 2895 ----------
2896 2896 node : ast.Node
2897 2897 The root node to be transformed. Typically called with the ast.Module
2898 2898 produced by parsing user input.
2899 2899
2900 2900 Returns
2901 2901 -------
2902 2902 An ast.Node corresponding to the node it was called with. Note that it
2903 2903 may also modify the passed object, so don't rely on references to the
2904 2904 original AST.
2905 2905 """
2906 2906 for transformer in self.ast_transformers:
2907 2907 try:
2908 2908 node = transformer.visit(node)
2909 2909 except InputRejected:
2910 2910 # User-supplied AST transformers can reject an input by raising
2911 2911 # an InputRejected. Short-circuit in this case so that we
2912 2912 # don't unregister the transform.
2913 2913 raise
2914 2914 except Exception:
2915 2915 warn("AST transformer %r threw an error. It will be unregistered." % transformer)
2916 2916 self.ast_transformers.remove(transformer)
2917 2917
2918 2918 if self.ast_transformers:
2919 2919 ast.fix_missing_locations(node)
2920 2920 return node
2921 2921
2922 2922
2923 2923 def run_ast_nodes(self, nodelist, cell_name, interactivity='last_expr',
2924 2924 compiler=compile, result=None):
2925 2925 """Run a sequence of AST nodes. The execution mode depends on the
2926 2926 interactivity parameter.
2927 2927
2928 2928 Parameters
2929 2929 ----------
2930 2930 nodelist : list
2931 2931 A sequence of AST nodes to run.
2932 2932 cell_name : str
2933 2933 Will be passed to the compiler as the filename of the cell. Typically
2934 2934 the value returned by ip.compile.cache(cell).
2935 2935 interactivity : str
2936 2936 'all', 'last', 'last_expr' or 'none', specifying which nodes should be
2937 2937 run interactively (displaying output from expressions). 'last_expr'
2938 2938 will run the last node interactively only if it is an expression (i.e.
2939 2939 expressions in loops or other blocks are not displayed. Other values
2940 2940 for this parameter will raise a ValueError.
2941 2941 compiler : callable
2942 2942 A function with the same interface as the built-in compile(), to turn
2943 2943 the AST nodes into code objects. Default is the built-in compile().
2944 2944 result : ExecutionResult, optional
2945 2945 An object to store exceptions that occur during execution.
2946 2946
2947 2947 Returns
2948 2948 -------
2949 2949 True if an exception occurred while running code, False if it finished
2950 2950 running.
2951 2951 """
2952 2952 if not nodelist:
2953 2953 return
2954 2954
2955 2955 if interactivity == 'last_expr':
2956 2956 if isinstance(nodelist[-1], ast.Expr):
2957 2957 interactivity = "last"
2958 2958 else:
2959 2959 interactivity = "none"
2960 2960
2961 2961 if interactivity == 'none':
2962 2962 to_run_exec, to_run_interactive = nodelist, []
2963 2963 elif interactivity == 'last':
2964 2964 to_run_exec, to_run_interactive = nodelist[:-1], nodelist[-1:]
2965 2965 elif interactivity == 'all':
2966 2966 to_run_exec, to_run_interactive = [], nodelist
2967 2967 else:
2968 2968 raise ValueError("Interactivity was %r" % interactivity)
2969 2969
2970 2970 exec_count = self.execution_count
2971 2971
2972 2972 try:
2973 2973 for i, node in enumerate(to_run_exec):
2974 2974 mod = ast.Module([node])
2975 2975 code = compiler(mod, cell_name, "exec")
2976 2976 if self.run_code(code, result):
2977 2977 return True
2978 2978
2979 2979 for i, node in enumerate(to_run_interactive):
2980 2980 mod = ast.Interactive([node])
2981 2981 code = compiler(mod, cell_name, "single")
2982 2982 if self.run_code(code, result):
2983 2983 return True
2984 2984
2985 2985 # Flush softspace
2986 2986 if softspace(sys.stdout, 0):
2987 2987 print()
2988 2988
2989 2989 except:
2990 2990 # It's possible to have exceptions raised here, typically by
2991 2991 # compilation of odd code (such as a naked 'return' outside a
2992 2992 # function) that did parse but isn't valid. Typically the exception
2993 2993 # is a SyntaxError, but it's safest just to catch anything and show
2994 2994 # the user a traceback.
2995 2995
2996 2996 # We do only one try/except outside the loop to minimize the impact
2997 2997 # on runtime, and also because if any node in the node list is
2998 2998 # broken, we should stop execution completely.
2999 2999 if result:
3000 3000 result.error_before_exec = sys.exc_info()[1]
3001 3001 self.showtraceback()
3002 3002 return True
3003 3003
3004 3004 return False
3005 3005
3006 3006 def run_code(self, code_obj, result=None):
3007 3007 """Execute a code object.
3008 3008
3009 3009 When an exception occurs, self.showtraceback() is called to display a
3010 3010 traceback.
3011 3011
3012 3012 Parameters
3013 3013 ----------
3014 3014 code_obj : code object
3015 3015 A compiled code object, to be executed
3016 3016 result : ExecutionResult, optional
3017 3017 An object to store exceptions that occur during execution.
3018 3018
3019 3019 Returns
3020 3020 -------
3021 3021 False : successful execution.
3022 3022 True : an error occurred.
3023 3023 """
3024 3024 # Set our own excepthook in case the user code tries to call it
3025 3025 # directly, so that the IPython crash handler doesn't get triggered
3026 3026 old_excepthook, sys.excepthook = sys.excepthook, self.excepthook
3027 3027
3028 3028 # we save the original sys.excepthook in the instance, in case config
3029 3029 # code (such as magics) needs access to it.
3030 3030 self.sys_excepthook = old_excepthook
3031 3031 outflag = 1 # happens in more places, so it's easier as default
3032 3032 try:
3033 3033 try:
3034 3034 self.hooks.pre_run_code_hook()
3035 3035 #rprint('Running code', repr(code_obj)) # dbg
3036 3036 exec(code_obj, self.user_global_ns, self.user_ns)
3037 3037 finally:
3038 3038 # Reset our crash handler in place
3039 3039 sys.excepthook = old_excepthook
3040 3040 except SystemExit as e:
3041 3041 if result is not None:
3042 3042 result.error_in_exec = e
3043 3043 self.showtraceback(exception_only=True)
3044 3044 warn("To exit: use 'exit', 'quit', or Ctrl-D.", level=1)
3045 3045 except self.custom_exceptions:
3046 3046 etype, value, tb = sys.exc_info()
3047 3047 if result is not None:
3048 3048 result.error_in_exec = value
3049 3049 self.CustomTB(etype, value, tb)
3050 3050 except:
3051 3051 if result is not None:
3052 3052 result.error_in_exec = sys.exc_info()[1]
3053 3053 self.showtraceback()
3054 3054 else:
3055 3055 outflag = 0
3056 3056 return outflag
3057 3057
3058 3058 # For backwards compatibility
3059 3059 runcode = run_code
3060 3060
3061 3061 #-------------------------------------------------------------------------
3062 3062 # Things related to GUI support and pylab
3063 3063 #-------------------------------------------------------------------------
3064 3064
3065 3065 def enable_gui(self, gui=None):
3066 3066 raise NotImplementedError('Implement enable_gui in a subclass')
3067 3067
3068 3068 def enable_matplotlib(self, gui=None):
3069 3069 """Enable interactive matplotlib and inline figure support.
3070 3070
3071 3071 This takes the following steps:
3072 3072
3073 3073 1. select the appropriate eventloop and matplotlib backend
3074 3074 2. set up matplotlib for interactive use with that backend
3075 3075 3. configure formatters for inline figure display
3076 3076 4. enable the selected gui eventloop
3077 3077
3078 3078 Parameters
3079 3079 ----------
3080 3080 gui : optional, string
3081 3081 If given, dictates the choice of matplotlib GUI backend to use
3082 3082 (should be one of IPython's supported backends, 'qt', 'osx', 'tk',
3083 3083 'gtk', 'wx' or 'inline'), otherwise we use the default chosen by
3084 3084 matplotlib (as dictated by the matplotlib build-time options plus the
3085 3085 user's matplotlibrc configuration file). Note that not all backends
3086 3086 make sense in all contexts, for example a terminal ipython can't
3087 3087 display figures inline.
3088 3088 """
3089 3089 from IPython.core import pylabtools as pt
3090 3090 gui, backend = pt.find_gui_and_backend(gui, self.pylab_gui_select)
3091 3091
3092 3092 if gui != 'inline':
3093 3093 # If we have our first gui selection, store it
3094 3094 if self.pylab_gui_select is None:
3095 3095 self.pylab_gui_select = gui
3096 3096 # Otherwise if they are different
3097 3097 elif gui != self.pylab_gui_select:
3098 3098 print ('Warning: Cannot change to a different GUI toolkit: %s.'
3099 3099 ' Using %s instead.' % (gui, self.pylab_gui_select))
3100 3100 gui, backend = pt.find_gui_and_backend(self.pylab_gui_select)
3101 3101
3102 3102 pt.activate_matplotlib(backend)
3103 3103 pt.configure_inline_support(self, backend)
3104 3104
3105 3105 # Now we must activate the gui pylab wants to use, and fix %run to take
3106 3106 # plot updates into account
3107 3107 self.enable_gui(gui)
3108 3108 self.magics_manager.registry['ExecutionMagics'].default_runner = \
3109 3109 pt.mpl_runner(self.safe_execfile)
3110 3110
3111 3111 return gui, backend
3112 3112
3113 3113 def enable_pylab(self, gui=None, import_all=True, welcome_message=False):
3114 3114 """Activate pylab support at runtime.
3115 3115
3116 3116 This turns on support for matplotlib, preloads into the interactive
3117 3117 namespace all of numpy and pylab, and configures IPython to correctly
3118 3118 interact with the GUI event loop. The GUI backend to be used can be
3119 3119 optionally selected with the optional ``gui`` argument.
3120 3120
3121 3121 This method only adds preloading the namespace to InteractiveShell.enable_matplotlib.
3122 3122
3123 3123 Parameters
3124 3124 ----------
3125 3125 gui : optional, string
3126 3126 If given, dictates the choice of matplotlib GUI backend to use
3127 3127 (should be one of IPython's supported backends, 'qt', 'osx', 'tk',
3128 3128 'gtk', 'wx' or 'inline'), otherwise we use the default chosen by
3129 3129 matplotlib (as dictated by the matplotlib build-time options plus the
3130 3130 user's matplotlibrc configuration file). Note that not all backends
3131 3131 make sense in all contexts, for example a terminal ipython can't
3132 3132 display figures inline.
3133 3133 import_all : optional, bool, default: True
3134 3134 Whether to do `from numpy import *` and `from pylab import *`
3135 3135 in addition to module imports.
3136 3136 welcome_message : deprecated
3137 3137 This argument is ignored, no welcome message will be displayed.
3138 3138 """
3139 3139 from IPython.core.pylabtools import import_pylab
3140 3140
3141 3141 gui, backend = self.enable_matplotlib(gui)
3142 3142
3143 3143 # We want to prevent the loading of pylab to pollute the user's
3144 3144 # namespace as shown by the %who* magics, so we execute the activation
3145 3145 # code in an empty namespace, and we update *both* user_ns and
3146 3146 # user_ns_hidden with this information.
3147 3147 ns = {}
3148 3148 import_pylab(ns, import_all)
3149 3149 # warn about clobbered names
3150 3150 ignored = set(["__builtins__"])
3151 3151 both = set(ns).intersection(self.user_ns).difference(ignored)
3152 3152 clobbered = [ name for name in both if self.user_ns[name] is not ns[name] ]
3153 3153 self.user_ns.update(ns)
3154 3154 self.user_ns_hidden.update(ns)
3155 3155 return gui, backend, clobbered
3156 3156
3157 3157 #-------------------------------------------------------------------------
3158 3158 # Utilities
3159 3159 #-------------------------------------------------------------------------
3160 3160
3161 3161 def var_expand(self, cmd, depth=0, formatter=DollarFormatter()):
3162 3162 """Expand python variables in a string.
3163 3163
3164 3164 The depth argument indicates how many frames above the caller should
3165 3165 be walked to look for the local namespace where to expand variables.
3166 3166
3167 3167 The global namespace for expansion is always the user's interactive
3168 3168 namespace.
3169 3169 """
3170 3170 ns = self.user_ns.copy()
3171 3171 try:
3172 3172 frame = sys._getframe(depth+1)
3173 3173 except ValueError:
3174 3174 # This is thrown if there aren't that many frames on the stack,
3175 3175 # e.g. if a script called run_line_magic() directly.
3176 3176 pass
3177 3177 else:
3178 3178 ns.update(frame.f_locals)
3179 3179
3180 3180 try:
3181 3181 # We have to use .vformat() here, because 'self' is a valid and common
3182 3182 # name, and expanding **ns for .format() would make it collide with
3183 3183 # the 'self' argument of the method.
3184 3184 cmd = formatter.vformat(cmd, args=[], kwargs=ns)
3185 3185 except Exception:
3186 3186 # if formatter couldn't format, just let it go untransformed
3187 3187 pass
3188 3188 return cmd
3189 3189
3190 3190 def mktempfile(self, data=None, prefix='ipython_edit_'):
3191 3191 """Make a new tempfile and return its filename.
3192 3192
3193 3193 This makes a call to tempfile.mkstemp (created in a tempfile.mkdtemp),
3194 3194 but it registers the created filename internally so ipython cleans it up
3195 3195 at exit time.
3196 3196
3197 3197 Optional inputs:
3198 3198
3199 3199 - data(None): if data is given, it gets written out to the temp file
3200 3200 immediately, and the file is closed again."""
3201 3201
3202 3202 dirname = tempfile.mkdtemp(prefix=prefix)
3203 3203 self.tempdirs.append(dirname)
3204 3204
3205 3205 handle, filename = tempfile.mkstemp('.py', prefix, dir=dirname)
3206 3206 os.close(handle) # On Windows, there can only be one open handle on a file
3207 3207 self.tempfiles.append(filename)
3208 3208
3209 3209 if data:
3210 3210 tmp_file = open(filename,'w')
3211 3211 tmp_file.write(data)
3212 3212 tmp_file.close()
3213 3213 return filename
3214 3214
3215 3215 # TODO: This should be removed when Term is refactored.
3216 3216 def write(self,data):
3217 3217 """Write a string to the default output"""
3218 3218 io.stdout.write(data)
3219 3219
3220 3220 # TODO: This should be removed when Term is refactored.
3221 3221 def write_err(self,data):
3222 3222 """Write a string to the default error output"""
3223 3223 io.stderr.write(data)
3224 3224
3225 3225 def ask_yes_no(self, prompt, default=None):
3226 3226 if self.quiet:
3227 3227 return True
3228 3228 return ask_yes_no(prompt,default)
3229 3229
3230 3230 def show_usage(self):
3231 3231 """Show a usage message"""
3232 3232 page.page(IPython.core.usage.interactive_usage)
3233 3233
3234 3234 def extract_input_lines(self, range_str, raw=False):
3235 3235 """Return as a string a set of input history slices.
3236 3236
3237 3237 Parameters
3238 3238 ----------
3239 3239 range_str : string
3240 3240 The set of slices is given as a string, like "~5/6-~4/2 4:8 9",
3241 3241 since this function is for use by magic functions which get their
3242 3242 arguments as strings. The number before the / is the session
3243 3243 number: ~n goes n back from the current session.
3244 3244
3245 3245 raw : bool, optional
3246 3246 By default, the processed input is used. If this is true, the raw
3247 3247 input history is used instead.
3248 3248
3249 3249 Notes
3250 3250 -----
3251 3251
3252 3252 Slices can be described with two notations:
3253 3253
3254 3254 * ``N:M`` -> standard python form, means including items N...(M-1).
3255 3255 * ``N-M`` -> include items N..M (closed endpoint).
3256 3256 """
3257 3257 lines = self.history_manager.get_range_by_str(range_str, raw=raw)
3258 3258 return "\n".join(x for _, _, x in lines)
3259 3259
3260 3260 def find_user_code(self, target, raw=True, py_only=False, skip_encoding_cookie=True, search_ns=False):
3261 3261 """Get a code string from history, file, url, or a string or macro.
3262 3262
3263 3263 This is mainly used by magic functions.
3264 3264
3265 3265 Parameters
3266 3266 ----------
3267 3267
3268 3268 target : str
3269 3269
3270 3270 A string specifying code to retrieve. This will be tried respectively
3271 3271 as: ranges of input history (see %history for syntax), url,
3272 3272 correspnding .py file, filename, or an expression evaluating to a
3273 3273 string or Macro in the user namespace.
3274 3274
3275 3275 raw : bool
3276 3276 If true (default), retrieve raw history. Has no effect on the other
3277 3277 retrieval mechanisms.
3278 3278
3279 3279 py_only : bool (default False)
3280 3280 Only try to fetch python code, do not try alternative methods to decode file
3281 3281 if unicode fails.
3282 3282
3283 3283 Returns
3284 3284 -------
3285 3285 A string of code.
3286 3286
3287 3287 ValueError is raised if nothing is found, and TypeError if it evaluates
3288 3288 to an object of another type. In each case, .args[0] is a printable
3289 3289 message.
3290 3290 """
3291 3291 code = self.extract_input_lines(target, raw=raw) # Grab history
3292 3292 if code:
3293 3293 return code
3294 3294 utarget = unquote_filename(target)
3295 3295 try:
3296 3296 if utarget.startswith(('http://', 'https://')):
3297 3297 return openpy.read_py_url(utarget, skip_encoding_cookie=skip_encoding_cookie)
3298 3298 except UnicodeDecodeError:
3299 3299 if not py_only :
3300 3300 # Deferred import
3301 3301 try:
3302 3302 from urllib.request import urlopen # Py3
3303 3303 except ImportError:
3304 3304 from urllib import urlopen
3305 3305 response = urlopen(target)
3306 3306 return response.read().decode('latin1')
3307 3307 raise ValueError(("'%s' seem to be unreadable.") % utarget)
3308 3308
3309 3309 potential_target = [target]
3310 3310 try :
3311 3311 potential_target.insert(0,get_py_filename(target))
3312 3312 except IOError:
3313 3313 pass
3314 3314
3315 3315 for tgt in potential_target :
3316 3316 if os.path.isfile(tgt): # Read file
3317 3317 try :
3318 3318 return openpy.read_py_file(tgt, skip_encoding_cookie=skip_encoding_cookie)
3319 3319 except UnicodeDecodeError :
3320 3320 if not py_only :
3321 3321 with io_open(tgt,'r', encoding='latin1') as f :
3322 3322 return f.read()
3323 3323 raise ValueError(("'%s' seem to be unreadable.") % target)
3324 3324 elif os.path.isdir(os.path.expanduser(tgt)):
3325 3325 raise ValueError("'%s' is a directory, not a regular file." % target)
3326 3326
3327 3327 if search_ns:
3328 3328 # Inspect namespace to load object source
3329 3329 object_info = self.object_inspect(target, detail_level=1)
3330 3330 if object_info['found'] and object_info['source']:
3331 3331 return object_info['source']
3332 3332
3333 3333 try: # User namespace
3334 3334 codeobj = eval(target, self.user_ns)
3335 3335 except Exception:
3336 3336 raise ValueError(("'%s' was not found in history, as a file, url, "
3337 3337 "nor in the user namespace.") % target)
3338 3338
3339 3339 if isinstance(codeobj, string_types):
3340 3340 return codeobj
3341 3341 elif isinstance(codeobj, Macro):
3342 3342 return codeobj.value
3343 3343
3344 3344 raise TypeError("%s is neither a string nor a macro." % target,
3345 3345 codeobj)
3346 3346
3347 3347 #-------------------------------------------------------------------------
3348 3348 # Things related to IPython exiting
3349 3349 #-------------------------------------------------------------------------
3350 3350 def atexit_operations(self):
3351 3351 """This will be executed at the time of exit.
3352 3352
3353 3353 Cleanup operations and saving of persistent data that is done
3354 3354 unconditionally by IPython should be performed here.
3355 3355
3356 3356 For things that may depend on startup flags or platform specifics (such
3357 3357 as having readline or not), register a separate atexit function in the
3358 3358 code that has the appropriate information, rather than trying to
3359 3359 clutter
3360 3360 """
3361 3361 # Close the history session (this stores the end time and line count)
3362 3362 # this must be *before* the tempfile cleanup, in case of temporary
3363 3363 # history db
3364 3364 self.history_manager.end_session()
3365 3365
3366 3366 # Cleanup all tempfiles and folders left around
3367 3367 for tfile in self.tempfiles:
3368 3368 try:
3369 3369 os.unlink(tfile)
3370 3370 except OSError:
3371 3371 pass
3372 3372
3373 3373 for tdir in self.tempdirs:
3374 3374 try:
3375 3375 os.rmdir(tdir)
3376 3376 except OSError:
3377 3377 pass
3378 3378
3379 3379 # Clear all user namespaces to release all references cleanly.
3380 3380 self.reset(new_session=False)
3381 3381
3382 3382 # Run user hooks
3383 3383 self.hooks.shutdown_hook()
3384 3384
3385 3385 def cleanup(self):
3386 3386 self.restore_sys_module_state()
3387 3387
3388 3388
3389 3389 class InteractiveShellABC(with_metaclass(abc.ABCMeta, object)):
3390 3390 """An abstract base class for InteractiveShell."""
3391 3391
3392 3392 InteractiveShellABC.register(InteractiveShell)
@@ -1,702 +1,702 b''
1 1 # encoding: utf-8
2 2 """Magic functions for InteractiveShell.
3 3 """
4 4 from __future__ import print_function
5 5
6 6 #-----------------------------------------------------------------------------
7 7 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de> and
8 8 # Copyright (C) 2001 Fernando Perez <fperez@colorado.edu>
9 9 # Copyright (C) 2008 The IPython Development Team
10 10
11 11 # Distributed under the terms of the BSD License. The full license is in
12 12 # the file COPYING, distributed as part of this software.
13 13 #-----------------------------------------------------------------------------
14 14
15 15 #-----------------------------------------------------------------------------
16 16 # Imports
17 17 #-----------------------------------------------------------------------------
18 18 # Stdlib
19 19 import os
20 20 import re
21 21 import sys
22 22 import types
23 23 from getopt import getopt, GetoptError
24 24
25 25 # Our own
26 26 from IPython.config.configurable import Configurable
27 27 from IPython.core import oinspect
28 28 from IPython.core.error import UsageError
29 29 from IPython.core.inputsplitter import ESC_MAGIC, ESC_MAGIC2
30 30 from decorator import decorator
31 31 from IPython.utils.ipstruct import Struct
32 32 from IPython.utils.process import arg_split
33 33 from IPython.utils.py3compat import string_types, iteritems
34 34 from IPython.utils.text import dedent
35 35 from IPython.utils.traitlets import Bool, Dict, Instance, MetaHasTraits
36 36 from IPython.utils.warn import error
37 37
38 38 #-----------------------------------------------------------------------------
39 39 # Globals
40 40 #-----------------------------------------------------------------------------
41 41
42 42 # A dict we'll use for each class that has magics, used as temporary storage to
43 43 # pass information between the @line/cell_magic method decorators and the
44 44 # @magics_class class decorator, because the method decorators have no
45 45 # access to the class when they run. See for more details:
46 46 # http://stackoverflow.com/questions/2366713/can-a-python-decorator-of-an-instance-method-access-the-class
47 47
48 48 magics = dict(line={}, cell={})
49 49
50 50 magic_kinds = ('line', 'cell')
51 51 magic_spec = ('line', 'cell', 'line_cell')
52 52 magic_escapes = dict(line=ESC_MAGIC, cell=ESC_MAGIC2)
53 53
54 54 #-----------------------------------------------------------------------------
55 55 # Utility classes and functions
56 56 #-----------------------------------------------------------------------------
57 57
58 58 class Bunch: pass
59 59
60 60
61 61 def on_off(tag):
62 62 """Return an ON/OFF string for a 1/0 input. Simple utility function."""
63 63 return ['OFF','ON'][tag]
64 64
65 65
66 66 def compress_dhist(dh):
67 67 """Compress a directory history into a new one with at most 20 entries.
68 68
69 69 Return a new list made from the first and last 10 elements of dhist after
70 70 removal of duplicates.
71 71 """
72 72 head, tail = dh[:-10], dh[-10:]
73 73
74 74 newhead = []
75 75 done = set()
76 76 for h in head:
77 77 if h in done:
78 78 continue
79 79 newhead.append(h)
80 80 done.add(h)
81 81
82 82 return newhead + tail
83 83
84 84
85 85 def needs_local_scope(func):
86 86 """Decorator to mark magic functions which need to local scope to run."""
87 87 func.needs_local_scope = True
88 88 return func
89 89
90 90 #-----------------------------------------------------------------------------
91 91 # Class and method decorators for registering magics
92 92 #-----------------------------------------------------------------------------
93 93
94 94 def magics_class(cls):
95 95 """Class decorator for all subclasses of the main Magics class.
96 96
97 97 Any class that subclasses Magics *must* also apply this decorator, to
98 98 ensure that all the methods that have been decorated as line/cell magics
99 99 get correctly registered in the class instance. This is necessary because
100 100 when method decorators run, the class does not exist yet, so they
101 101 temporarily store their information into a module global. Application of
102 102 this class decorator copies that global data to the class instance and
103 103 clears the global.
104 104
105 105 Obviously, this mechanism is not thread-safe, which means that the
106 106 *creation* of subclasses of Magic should only be done in a single-thread
107 107 context. Instantiation of the classes has no restrictions. Given that
108 108 these classes are typically created at IPython startup time and before user
109 109 application code becomes active, in practice this should not pose any
110 110 problems.
111 111 """
112 112 cls.registered = True
113 113 cls.magics = dict(line = magics['line'],
114 114 cell = magics['cell'])
115 115 magics['line'] = {}
116 116 magics['cell'] = {}
117 117 return cls
118 118
119 119
120 120 def record_magic(dct, magic_kind, magic_name, func):
121 121 """Utility function to store a function as a magic of a specific kind.
122 122
123 123 Parameters
124 124 ----------
125 125 dct : dict
126 126 A dictionary with 'line' and 'cell' subdicts.
127 127
128 128 magic_kind : str
129 129 Kind of magic to be stored.
130 130
131 131 magic_name : str
132 132 Key to store the magic as.
133 133
134 134 func : function
135 135 Callable object to store.
136 136 """
137 137 if magic_kind == 'line_cell':
138 138 dct['line'][magic_name] = dct['cell'][magic_name] = func
139 139 else:
140 140 dct[magic_kind][magic_name] = func
141 141
142 142
143 143 def validate_type(magic_kind):
144 144 """Ensure that the given magic_kind is valid.
145 145
146 146 Check that the given magic_kind is one of the accepted spec types (stored
147 147 in the global `magic_spec`), raise ValueError otherwise.
148 148 """
149 149 if magic_kind not in magic_spec:
150 150 raise ValueError('magic_kind must be one of %s, %s given' %
151 151 magic_kinds, magic_kind)
152 152
153 153
154 154 # The docstrings for the decorator below will be fairly similar for the two
155 155 # types (method and function), so we generate them here once and reuse the
156 156 # templates below.
157 157 _docstring_template = \
158 158 """Decorate the given {0} as {1} magic.
159 159
160 160 The decorator can be used with or without arguments, as follows.
161 161
162 162 i) without arguments: it will create a {1} magic named as the {0} being
163 163 decorated::
164 164
165 165 @deco
166 166 def foo(...)
167 167
168 168 will create a {1} magic named `foo`.
169 169
170 170 ii) with one string argument: which will be used as the actual name of the
171 171 resulting magic::
172 172
173 173 @deco('bar')
174 174 def foo(...)
175 175
176 176 will create a {1} magic named `bar`.
177 177 """
178 178
179 179 # These two are decorator factories. While they are conceptually very similar,
180 180 # there are enough differences in the details that it's simpler to have them
181 181 # written as completely standalone functions rather than trying to share code
182 182 # and make a single one with convoluted logic.
183 183
184 184 def _method_magic_marker(magic_kind):
185 185 """Decorator factory for methods in Magics subclasses.
186 186 """
187 187
188 188 validate_type(magic_kind)
189 189
190 190 # This is a closure to capture the magic_kind. We could also use a class,
191 191 # but it's overkill for just that one bit of state.
192 192 def magic_deco(arg):
193 193 call = lambda f, *a, **k: f(*a, **k)
194 194
195 195 if callable(arg):
196 196 # "Naked" decorator call (just @foo, no args)
197 197 func = arg
198 198 name = func.__name__
199 199 retval = decorator(call, func)
200 200 record_magic(magics, magic_kind, name, name)
201 201 elif isinstance(arg, string_types):
202 202 # Decorator called with arguments (@foo('bar'))
203 203 name = arg
204 204 def mark(func, *a, **kw):
205 205 record_magic(magics, magic_kind, name, func.__name__)
206 206 return decorator(call, func)
207 207 retval = mark
208 208 else:
209 209 raise TypeError("Decorator can only be called with "
210 210 "string or function")
211 211 return retval
212 212
213 213 # Ensure the resulting decorator has a usable docstring
214 214 magic_deco.__doc__ = _docstring_template.format('method', magic_kind)
215 215 return magic_deco
216 216
217 217
218 218 def _function_magic_marker(magic_kind):
219 219 """Decorator factory for standalone functions.
220 220 """
221 221 validate_type(magic_kind)
222 222
223 223 # This is a closure to capture the magic_kind. We could also use a class,
224 224 # but it's overkill for just that one bit of state.
225 225 def magic_deco(arg):
226 226 call = lambda f, *a, **k: f(*a, **k)
227 227
228 228 # Find get_ipython() in the caller's namespace
229 229 caller = sys._getframe(1)
230 230 for ns in ['f_locals', 'f_globals', 'f_builtins']:
231 231 get_ipython = getattr(caller, ns).get('get_ipython')
232 232 if get_ipython is not None:
233 233 break
234 234 else:
235 235 raise NameError('Decorator can only run in context where '
236 236 '`get_ipython` exists')
237 237
238 238 ip = get_ipython()
239 239
240 240 if callable(arg):
241 241 # "Naked" decorator call (just @foo, no args)
242 242 func = arg
243 243 name = func.__name__
244 244 ip.register_magic_function(func, magic_kind, name)
245 245 retval = decorator(call, func)
246 246 elif isinstance(arg, string_types):
247 247 # Decorator called with arguments (@foo('bar'))
248 248 name = arg
249 249 def mark(func, *a, **kw):
250 250 ip.register_magic_function(func, magic_kind, name)
251 251 return decorator(call, func)
252 252 retval = mark
253 253 else:
254 254 raise TypeError("Decorator can only be called with "
255 255 "string or function")
256 256 return retval
257 257
258 258 # Ensure the resulting decorator has a usable docstring
259 259 ds = _docstring_template.format('function', magic_kind)
260 260
261 261 ds += dedent("""
262 262 Note: this decorator can only be used in a context where IPython is already
263 263 active, so that the `get_ipython()` call succeeds. You can therefore use
264 264 it in your startup files loaded after IPython initializes, but *not* in the
265 265 IPython configuration file itself, which is executed before IPython is
266 266 fully up and running. Any file located in the `startup` subdirectory of
267 267 your configuration profile will be OK in this sense.
268 268 """)
269 269
270 270 magic_deco.__doc__ = ds
271 271 return magic_deco
272 272
273 273
274 274 # Create the actual decorators for public use
275 275
276 276 # These three are used to decorate methods in class definitions
277 277 line_magic = _method_magic_marker('line')
278 278 cell_magic = _method_magic_marker('cell')
279 279 line_cell_magic = _method_magic_marker('line_cell')
280 280
281 281 # These three decorate standalone functions and perform the decoration
282 282 # immediately. They can only run where get_ipython() works
283 283 register_line_magic = _function_magic_marker('line')
284 284 register_cell_magic = _function_magic_marker('cell')
285 285 register_line_cell_magic = _function_magic_marker('line_cell')
286 286
287 287 #-----------------------------------------------------------------------------
288 288 # Core Magic classes
289 289 #-----------------------------------------------------------------------------
290 290
291 291 class MagicsManager(Configurable):
292 292 """Object that handles all magic-related functionality for IPython.
293 293 """
294 294 # Non-configurable class attributes
295 295
296 296 # A two-level dict, first keyed by magic type, then by magic function, and
297 297 # holding the actual callable object as value. This is the dict used for
298 298 # magic function dispatch
299 299 magics = Dict
300 300
301 301 # A registry of the original objects that we've been given holding magics.
302 302 registry = Dict
303 303
304 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
304 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
305 305
306 306 auto_magic = Bool(True, config=True, help=
307 307 "Automatically call line magics without requiring explicit % prefix")
308 308
309 309 def _auto_magic_changed(self, name, value):
310 310 self.shell.automagic = value
311 311
312 312 _auto_status = [
313 313 'Automagic is OFF, % prefix IS needed for line magics.',
314 314 'Automagic is ON, % prefix IS NOT needed for line magics.']
315 315
316 user_magics = Instance('IPython.core.magics.UserMagics')
316 user_magics = Instance('IPython.core.magics.UserMagics', allow_none=True)
317 317
318 318 def __init__(self, shell=None, config=None, user_magics=None, **traits):
319 319
320 320 super(MagicsManager, self).__init__(shell=shell, config=config,
321 321 user_magics=user_magics, **traits)
322 322 self.magics = dict(line={}, cell={})
323 323 # Let's add the user_magics to the registry for uniformity, so *all*
324 324 # registered magic containers can be found there.
325 325 self.registry[user_magics.__class__.__name__] = user_magics
326 326
327 327 def auto_status(self):
328 328 """Return descriptive string with automagic status."""
329 329 return self._auto_status[self.auto_magic]
330 330
331 331 def lsmagic(self):
332 332 """Return a dict of currently available magic functions.
333 333
334 334 The return dict has the keys 'line' and 'cell', corresponding to the
335 335 two types of magics we support. Each value is a list of names.
336 336 """
337 337 return self.magics
338 338
339 339 def lsmagic_docs(self, brief=False, missing=''):
340 340 """Return dict of documentation of magic functions.
341 341
342 342 The return dict has the keys 'line' and 'cell', corresponding to the
343 343 two types of magics we support. Each value is a dict keyed by magic
344 344 name whose value is the function docstring. If a docstring is
345 345 unavailable, the value of `missing` is used instead.
346 346
347 347 If brief is True, only the first line of each docstring will be returned.
348 348 """
349 349 docs = {}
350 350 for m_type in self.magics:
351 351 m_docs = {}
352 352 for m_name, m_func in iteritems(self.magics[m_type]):
353 353 if m_func.__doc__:
354 354 if brief:
355 355 m_docs[m_name] = m_func.__doc__.split('\n', 1)[0]
356 356 else:
357 357 m_docs[m_name] = m_func.__doc__.rstrip()
358 358 else:
359 359 m_docs[m_name] = missing
360 360 docs[m_type] = m_docs
361 361 return docs
362 362
363 363 def register(self, *magic_objects):
364 364 """Register one or more instances of Magics.
365 365
366 366 Take one or more classes or instances of classes that subclass the main
367 367 `core.Magic` class, and register them with IPython to use the magic
368 368 functions they provide. The registration process will then ensure that
369 369 any methods that have decorated to provide line and/or cell magics will
370 370 be recognized with the `%x`/`%%x` syntax as a line/cell magic
371 371 respectively.
372 372
373 373 If classes are given, they will be instantiated with the default
374 374 constructor. If your classes need a custom constructor, you should
375 375 instanitate them first and pass the instance.
376 376
377 377 The provided arguments can be an arbitrary mix of classes and instances.
378 378
379 379 Parameters
380 380 ----------
381 381 magic_objects : one or more classes or instances
382 382 """
383 383 # Start by validating them to ensure they have all had their magic
384 384 # methods registered at the instance level
385 385 for m in magic_objects:
386 386 if not m.registered:
387 387 raise ValueError("Class of magics %r was constructed without "
388 388 "the @register_magics class decorator")
389 389 if type(m) in (type, MetaHasTraits):
390 390 # If we're given an uninstantiated class
391 391 m = m(shell=self.shell)
392 392
393 393 # Now that we have an instance, we can register it and update the
394 394 # table of callables
395 395 self.registry[m.__class__.__name__] = m
396 396 for mtype in magic_kinds:
397 397 self.magics[mtype].update(m.magics[mtype])
398 398
399 399 def register_function(self, func, magic_kind='line', magic_name=None):
400 400 """Expose a standalone function as magic function for IPython.
401 401
402 402 This will create an IPython magic (line, cell or both) from a
403 403 standalone function. The functions should have the following
404 404 signatures:
405 405
406 406 * For line magics: `def f(line)`
407 407 * For cell magics: `def f(line, cell)`
408 408 * For a function that does both: `def f(line, cell=None)`
409 409
410 410 In the latter case, the function will be called with `cell==None` when
411 411 invoked as `%f`, and with cell as a string when invoked as `%%f`.
412 412
413 413 Parameters
414 414 ----------
415 415 func : callable
416 416 Function to be registered as a magic.
417 417
418 418 magic_kind : str
419 419 Kind of magic, one of 'line', 'cell' or 'line_cell'
420 420
421 421 magic_name : optional str
422 422 If given, the name the magic will have in the IPython namespace. By
423 423 default, the name of the function itself is used.
424 424 """
425 425
426 426 # Create the new method in the user_magics and register it in the
427 427 # global table
428 428 validate_type(magic_kind)
429 429 magic_name = func.__name__ if magic_name is None else magic_name
430 430 setattr(self.user_magics, magic_name, func)
431 431 record_magic(self.magics, magic_kind, magic_name, func)
432 432
433 433 def define_magic(self, name, func):
434 434 """[Deprecated] Expose own function as magic function for IPython.
435 435
436 436 Example::
437 437
438 438 def foo_impl(self, parameter_s=''):
439 439 'My very own magic!. (Use docstrings, IPython reads them).'
440 440 print 'Magic function. Passed parameter is between < >:'
441 441 print '<%s>' % parameter_s
442 442 print 'The self object is:', self
443 443
444 444 ip.define_magic('foo',foo_impl)
445 445 """
446 446 meth = types.MethodType(func, self.user_magics)
447 447 setattr(self.user_magics, name, meth)
448 448 record_magic(self.magics, 'line', name, meth)
449 449
450 450 def register_alias(self, alias_name, magic_name, magic_kind='line'):
451 451 """Register an alias to a magic function.
452 452
453 453 The alias is an instance of :class:`MagicAlias`, which holds the
454 454 name and kind of the magic it should call. Binding is done at
455 455 call time, so if the underlying magic function is changed the alias
456 456 will call the new function.
457 457
458 458 Parameters
459 459 ----------
460 460 alias_name : str
461 461 The name of the magic to be registered.
462 462
463 463 magic_name : str
464 464 The name of an existing magic.
465 465
466 466 magic_kind : str
467 467 Kind of magic, one of 'line' or 'cell'
468 468 """
469 469
470 470 # `validate_type` is too permissive, as it allows 'line_cell'
471 471 # which we do not handle.
472 472 if magic_kind not in magic_kinds:
473 473 raise ValueError('magic_kind must be one of %s, %s given' %
474 474 magic_kinds, magic_kind)
475 475
476 476 alias = MagicAlias(self.shell, magic_name, magic_kind)
477 477 setattr(self.user_magics, alias_name, alias)
478 478 record_magic(self.magics, magic_kind, alias_name, alias)
479 479
480 480 # Key base class that provides the central functionality for magics.
481 481
482 482
483 483 class Magics(Configurable):
484 484 """Base class for implementing magic functions.
485 485
486 486 Shell functions which can be reached as %function_name. All magic
487 487 functions should accept a string, which they can parse for their own
488 488 needs. This can make some functions easier to type, eg `%cd ../`
489 489 vs. `%cd("../")`
490 490
491 491 Classes providing magic functions need to subclass this class, and they
492 492 MUST:
493 493
494 494 - Use the method decorators `@line_magic` and `@cell_magic` to decorate
495 495 individual methods as magic functions, AND
496 496
497 497 - Use the class decorator `@magics_class` to ensure that the magic
498 498 methods are properly registered at the instance level upon instance
499 499 initialization.
500 500
501 501 See :mod:`magic_functions` for examples of actual implementation classes.
502 502 """
503 503 # Dict holding all command-line options for each magic.
504 504 options_table = None
505 505 # Dict for the mapping of magic names to methods, set by class decorator
506 506 magics = None
507 507 # Flag to check that the class decorator was properly applied
508 508 registered = False
509 509 # Instance of IPython shell
510 510 shell = None
511 511
512 512 def __init__(self, shell=None, **kwargs):
513 513 if not(self.__class__.registered):
514 514 raise ValueError('Magics subclass without registration - '
515 515 'did you forget to apply @magics_class?')
516 516 if shell is not None:
517 517 if hasattr(shell, 'configurables'):
518 518 shell.configurables.append(self)
519 519 if hasattr(shell, 'config'):
520 520 kwargs.setdefault('parent', shell)
521 521 kwargs['shell'] = shell
522 522
523 523 self.shell = shell
524 524 self.options_table = {}
525 525 # The method decorators are run when the instance doesn't exist yet, so
526 526 # they can only record the names of the methods they are supposed to
527 527 # grab. Only now, that the instance exists, can we create the proper
528 528 # mapping to bound methods. So we read the info off the original names
529 529 # table and replace each method name by the actual bound method.
530 530 # But we mustn't clobber the *class* mapping, in case of multiple instances.
531 531 class_magics = self.magics
532 532 self.magics = {}
533 533 for mtype in magic_kinds:
534 534 tab = self.magics[mtype] = {}
535 535 cls_tab = class_magics[mtype]
536 536 for magic_name, meth_name in iteritems(cls_tab):
537 537 if isinstance(meth_name, string_types):
538 538 # it's a method name, grab it
539 539 tab[magic_name] = getattr(self, meth_name)
540 540 else:
541 541 # it's the real thing
542 542 tab[magic_name] = meth_name
543 543 # Configurable **needs** to be initiated at the end or the config
544 544 # magics get screwed up.
545 545 super(Magics, self).__init__(**kwargs)
546 546
547 547 def arg_err(self,func):
548 548 """Print docstring if incorrect arguments were passed"""
549 549 print('Error in arguments:')
550 550 print(oinspect.getdoc(func))
551 551
552 552 def format_latex(self, strng):
553 553 """Format a string for latex inclusion."""
554 554
555 555 # Characters that need to be escaped for latex:
556 556 escape_re = re.compile(r'(%|_|\$|#|&)',re.MULTILINE)
557 557 # Magic command names as headers:
558 558 cmd_name_re = re.compile(r'^(%s.*?):' % ESC_MAGIC,
559 559 re.MULTILINE)
560 560 # Magic commands
561 561 cmd_re = re.compile(r'(?P<cmd>%s.+?\b)(?!\}\}:)' % ESC_MAGIC,
562 562 re.MULTILINE)
563 563 # Paragraph continue
564 564 par_re = re.compile(r'\\$',re.MULTILINE)
565 565
566 566 # The "\n" symbol
567 567 newline_re = re.compile(r'\\n')
568 568
569 569 # Now build the string for output:
570 570 #strng = cmd_name_re.sub(r'\n\\texttt{\\textsl{\\large \1}}:',strng)
571 571 strng = cmd_name_re.sub(r'\n\\bigskip\n\\texttt{\\textbf{ \1}}:',
572 572 strng)
573 573 strng = cmd_re.sub(r'\\texttt{\g<cmd>}',strng)
574 574 strng = par_re.sub(r'\\\\',strng)
575 575 strng = escape_re.sub(r'\\\1',strng)
576 576 strng = newline_re.sub(r'\\textbackslash{}n',strng)
577 577 return strng
578 578
579 579 def parse_options(self, arg_str, opt_str, *long_opts, **kw):
580 580 """Parse options passed to an argument string.
581 581
582 582 The interface is similar to that of :func:`getopt.getopt`, but it
583 583 returns a :class:`~IPython.utils.struct.Struct` with the options as keys
584 584 and the stripped argument string still as a string.
585 585
586 586 arg_str is quoted as a true sys.argv vector by using shlex.split.
587 587 This allows us to easily expand variables, glob files, quote
588 588 arguments, etc.
589 589
590 590 Parameters
591 591 ----------
592 592
593 593 arg_str : str
594 594 The arguments to parse.
595 595
596 596 opt_str : str
597 597 The options specification.
598 598
599 599 mode : str, default 'string'
600 600 If given as 'list', the argument string is returned as a list (split
601 601 on whitespace) instead of a string.
602 602
603 603 list_all : bool, default False
604 604 Put all option values in lists. Normally only options
605 605 appearing more than once are put in a list.
606 606
607 607 posix : bool, default True
608 608 Whether to split the input line in POSIX mode or not, as per the
609 609 conventions outlined in the :mod:`shlex` module from the standard
610 610 library.
611 611 """
612 612
613 613 # inject default options at the beginning of the input line
614 614 caller = sys._getframe(1).f_code.co_name
615 615 arg_str = '%s %s' % (self.options_table.get(caller,''),arg_str)
616 616
617 617 mode = kw.get('mode','string')
618 618 if mode not in ['string','list']:
619 619 raise ValueError('incorrect mode given: %s' % mode)
620 620 # Get options
621 621 list_all = kw.get('list_all',0)
622 622 posix = kw.get('posix', os.name == 'posix')
623 623 strict = kw.get('strict', True)
624 624
625 625 # Check if we have more than one argument to warrant extra processing:
626 626 odict = {} # Dictionary with options
627 627 args = arg_str.split()
628 628 if len(args) >= 1:
629 629 # If the list of inputs only has 0 or 1 thing in it, there's no
630 630 # need to look for options
631 631 argv = arg_split(arg_str, posix, strict)
632 632 # Do regular option processing
633 633 try:
634 634 opts,args = getopt(argv, opt_str, long_opts)
635 635 except GetoptError as e:
636 636 raise UsageError('%s ( allowed: "%s" %s)' % (e.msg,opt_str,
637 637 " ".join(long_opts)))
638 638 for o,a in opts:
639 639 if o.startswith('--'):
640 640 o = o[2:]
641 641 else:
642 642 o = o[1:]
643 643 try:
644 644 odict[o].append(a)
645 645 except AttributeError:
646 646 odict[o] = [odict[o],a]
647 647 except KeyError:
648 648 if list_all:
649 649 odict[o] = [a]
650 650 else:
651 651 odict[o] = a
652 652
653 653 # Prepare opts,args for return
654 654 opts = Struct(odict)
655 655 if mode == 'string':
656 656 args = ' '.join(args)
657 657
658 658 return opts,args
659 659
660 660 def default_option(self, fn, optstr):
661 661 """Make an entry in the options_table for fn, with value optstr"""
662 662
663 663 if fn not in self.lsmagic():
664 664 error("%s is not a magic function" % fn)
665 665 self.options_table[fn] = optstr
666 666
667 667
668 668 class MagicAlias(object):
669 669 """An alias to another magic function.
670 670
671 671 An alias is determined by its magic name and magic kind. Lookup
672 672 is done at call time, so if the underlying magic changes the alias
673 673 will call the new function.
674 674
675 675 Use the :meth:`MagicsManager.register_alias` method or the
676 676 `%alias_magic` magic function to create and register a new alias.
677 677 """
678 678 def __init__(self, shell, magic_name, magic_kind):
679 679 self.shell = shell
680 680 self.magic_name = magic_name
681 681 self.magic_kind = magic_kind
682 682
683 683 self.pretty_target = '%s%s' % (magic_escapes[self.magic_kind], self.magic_name)
684 684 self.__doc__ = "Alias for `%s`." % self.pretty_target
685 685
686 686 self._in_call = False
687 687
688 688 def __call__(self, *args, **kwargs):
689 689 """Call the magic alias."""
690 690 fn = self.shell.find_magic(self.magic_name, self.magic_kind)
691 691 if fn is None:
692 692 raise UsageError("Magic `%s` not found." % self.pretty_target)
693 693
694 694 # Protect against infinite recursion.
695 695 if self._in_call:
696 696 raise UsageError("Infinite recursion detected; "
697 697 "magic aliases cannot call themselves.")
698 698 self._in_call = True
699 699 try:
700 700 return fn(*args, **kwargs)
701 701 finally:
702 702 self._in_call = False
@@ -1,715 +1,715 b''
1 1 # encoding: utf-8
2 2 """
3 3 Prefiltering components.
4 4
5 5 Prefilters transform user input before it is exec'd by Python. These
6 6 transforms are used to implement additional syntax such as !ls and %magic.
7 7
8 8 Authors:
9 9
10 10 * Brian Granger
11 11 * Fernando Perez
12 12 * Dan Milstein
13 13 * Ville Vainio
14 14 """
15 15
16 16 #-----------------------------------------------------------------------------
17 17 # Copyright (C) 2008-2011 The IPython Development Team
18 18 #
19 19 # Distributed under the terms of the BSD License. The full license is in
20 20 # the file COPYING, distributed as part of this software.
21 21 #-----------------------------------------------------------------------------
22 22
23 23 #-----------------------------------------------------------------------------
24 24 # Imports
25 25 #-----------------------------------------------------------------------------
26 26
27 27 from keyword import iskeyword
28 28 import re
29 29
30 30 from IPython.core.autocall import IPyAutocall
31 31 from IPython.config.configurable import Configurable
32 32 from IPython.core.inputsplitter import (
33 33 ESC_MAGIC,
34 34 ESC_QUOTE,
35 35 ESC_QUOTE2,
36 36 ESC_PAREN,
37 37 )
38 38 from IPython.core.macro import Macro
39 39 from IPython.core.splitinput import LineInfo
40 40
41 41 from IPython.utils.traitlets import (
42 42 List, Integer, Unicode, CBool, Bool, Instance, CRegExp
43 43 )
44 44
45 45 #-----------------------------------------------------------------------------
46 46 # Global utilities, errors and constants
47 47 #-----------------------------------------------------------------------------
48 48
49 49
50 50 class PrefilterError(Exception):
51 51 pass
52 52
53 53
54 54 # RegExp to identify potential function names
55 55 re_fun_name = re.compile(r'[a-zA-Z_]([a-zA-Z0-9_.]*) *$')
56 56
57 57 # RegExp to exclude strings with this start from autocalling. In
58 58 # particular, all binary operators should be excluded, so that if foo is
59 59 # callable, foo OP bar doesn't become foo(OP bar), which is invalid. The
60 60 # characters '!=()' don't need to be checked for, as the checkPythonChars
61 61 # routine explicitely does so, to catch direct calls and rebindings of
62 62 # existing names.
63 63
64 64 # Warning: the '-' HAS TO BE AT THE END of the first group, otherwise
65 65 # it affects the rest of the group in square brackets.
66 66 re_exclude_auto = re.compile(r'^[,&^\|\*/\+-]'
67 67 r'|^is |^not |^in |^and |^or ')
68 68
69 69 # try to catch also methods for stuff in lists/tuples/dicts: off
70 70 # (experimental). For this to work, the line_split regexp would need
71 71 # to be modified so it wouldn't break things at '['. That line is
72 72 # nasty enough that I shouldn't change it until I can test it _well_.
73 73 #self.re_fun_name = re.compile (r'[a-zA-Z_]([a-zA-Z0-9_.\[\]]*) ?$')
74 74
75 75
76 76 # Handler Check Utilities
77 77 def is_shadowed(identifier, ip):
78 78 """Is the given identifier defined in one of the namespaces which shadow
79 79 the alias and magic namespaces? Note that an identifier is different
80 80 than ifun, because it can not contain a '.' character."""
81 81 # This is much safer than calling ofind, which can change state
82 82 return (identifier in ip.user_ns \
83 83 or identifier in ip.user_global_ns \
84 84 or identifier in ip.ns_table['builtin']\
85 85 or iskeyword(identifier))
86 86
87 87
88 88 #-----------------------------------------------------------------------------
89 89 # Main Prefilter manager
90 90 #-----------------------------------------------------------------------------
91 91
92 92
93 93 class PrefilterManager(Configurable):
94 94 """Main prefilter component.
95 95
96 96 The IPython prefilter is run on all user input before it is run. The
97 97 prefilter consumes lines of input and produces transformed lines of
98 98 input.
99 99
100 100 The iplementation consists of two phases:
101 101
102 102 1. Transformers
103 103 2. Checkers and handlers
104 104
105 105 Over time, we plan on deprecating the checkers and handlers and doing
106 106 everything in the transformers.
107 107
108 108 The transformers are instances of :class:`PrefilterTransformer` and have
109 109 a single method :meth:`transform` that takes a line and returns a
110 110 transformed line. The transformation can be accomplished using any
111 111 tool, but our current ones use regular expressions for speed.
112 112
113 113 After all the transformers have been run, the line is fed to the checkers,
114 114 which are instances of :class:`PrefilterChecker`. The line is passed to
115 115 the :meth:`check` method, which either returns `None` or a
116 116 :class:`PrefilterHandler` instance. If `None` is returned, the other
117 117 checkers are tried. If an :class:`PrefilterHandler` instance is returned,
118 118 the line is passed to the :meth:`handle` method of the returned
119 119 handler and no further checkers are tried.
120 120
121 121 Both transformers and checkers have a `priority` attribute, that determines
122 122 the order in which they are called. Smaller priorities are tried first.
123 123
124 124 Both transformers and checkers also have `enabled` attribute, which is
125 125 a boolean that determines if the instance is used.
126 126
127 127 Users or developers can change the priority or enabled attribute of
128 128 transformers or checkers, but they must call the :meth:`sort_checkers`
129 129 or :meth:`sort_transformers` method after changing the priority.
130 130 """
131 131
132 132 multi_line_specials = CBool(True, config=True)
133 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
133 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
134 134
135 135 def __init__(self, shell=None, **kwargs):
136 136 super(PrefilterManager, self).__init__(shell=shell, **kwargs)
137 137 self.shell = shell
138 138 self.init_transformers()
139 139 self.init_handlers()
140 140 self.init_checkers()
141 141
142 142 #-------------------------------------------------------------------------
143 143 # API for managing transformers
144 144 #-------------------------------------------------------------------------
145 145
146 146 def init_transformers(self):
147 147 """Create the default transformers."""
148 148 self._transformers = []
149 149 for transformer_cls in _default_transformers:
150 150 transformer_cls(
151 151 shell=self.shell, prefilter_manager=self, parent=self
152 152 )
153 153
154 154 def sort_transformers(self):
155 155 """Sort the transformers by priority.
156 156
157 157 This must be called after the priority of a transformer is changed.
158 158 The :meth:`register_transformer` method calls this automatically.
159 159 """
160 160 self._transformers.sort(key=lambda x: x.priority)
161 161
162 162 @property
163 163 def transformers(self):
164 164 """Return a list of checkers, sorted by priority."""
165 165 return self._transformers
166 166
167 167 def register_transformer(self, transformer):
168 168 """Register a transformer instance."""
169 169 if transformer not in self._transformers:
170 170 self._transformers.append(transformer)
171 171 self.sort_transformers()
172 172
173 173 def unregister_transformer(self, transformer):
174 174 """Unregister a transformer instance."""
175 175 if transformer in self._transformers:
176 176 self._transformers.remove(transformer)
177 177
178 178 #-------------------------------------------------------------------------
179 179 # API for managing checkers
180 180 #-------------------------------------------------------------------------
181 181
182 182 def init_checkers(self):
183 183 """Create the default checkers."""
184 184 self._checkers = []
185 185 for checker in _default_checkers:
186 186 checker(
187 187 shell=self.shell, prefilter_manager=self, parent=self
188 188 )
189 189
190 190 def sort_checkers(self):
191 191 """Sort the checkers by priority.
192 192
193 193 This must be called after the priority of a checker is changed.
194 194 The :meth:`register_checker` method calls this automatically.
195 195 """
196 196 self._checkers.sort(key=lambda x: x.priority)
197 197
198 198 @property
199 199 def checkers(self):
200 200 """Return a list of checkers, sorted by priority."""
201 201 return self._checkers
202 202
203 203 def register_checker(self, checker):
204 204 """Register a checker instance."""
205 205 if checker not in self._checkers:
206 206 self._checkers.append(checker)
207 207 self.sort_checkers()
208 208
209 209 def unregister_checker(self, checker):
210 210 """Unregister a checker instance."""
211 211 if checker in self._checkers:
212 212 self._checkers.remove(checker)
213 213
214 214 #-------------------------------------------------------------------------
215 215 # API for managing handlers
216 216 #-------------------------------------------------------------------------
217 217
218 218 def init_handlers(self):
219 219 """Create the default handlers."""
220 220 self._handlers = {}
221 221 self._esc_handlers = {}
222 222 for handler in _default_handlers:
223 223 handler(
224 224 shell=self.shell, prefilter_manager=self, parent=self
225 225 )
226 226
227 227 @property
228 228 def handlers(self):
229 229 """Return a dict of all the handlers."""
230 230 return self._handlers
231 231
232 232 def register_handler(self, name, handler, esc_strings):
233 233 """Register a handler instance by name with esc_strings."""
234 234 self._handlers[name] = handler
235 235 for esc_str in esc_strings:
236 236 self._esc_handlers[esc_str] = handler
237 237
238 238 def unregister_handler(self, name, handler, esc_strings):
239 239 """Unregister a handler instance by name with esc_strings."""
240 240 try:
241 241 del self._handlers[name]
242 242 except KeyError:
243 243 pass
244 244 for esc_str in esc_strings:
245 245 h = self._esc_handlers.get(esc_str)
246 246 if h is handler:
247 247 del self._esc_handlers[esc_str]
248 248
249 249 def get_handler_by_name(self, name):
250 250 """Get a handler by its name."""
251 251 return self._handlers.get(name)
252 252
253 253 def get_handler_by_esc(self, esc_str):
254 254 """Get a handler by its escape string."""
255 255 return self._esc_handlers.get(esc_str)
256 256
257 257 #-------------------------------------------------------------------------
258 258 # Main prefiltering API
259 259 #-------------------------------------------------------------------------
260 260
261 261 def prefilter_line_info(self, line_info):
262 262 """Prefilter a line that has been converted to a LineInfo object.
263 263
264 264 This implements the checker/handler part of the prefilter pipe.
265 265 """
266 266 # print "prefilter_line_info: ", line_info
267 267 handler = self.find_handler(line_info)
268 268 return handler.handle(line_info)
269 269
270 270 def find_handler(self, line_info):
271 271 """Find a handler for the line_info by trying checkers."""
272 272 for checker in self.checkers:
273 273 if checker.enabled:
274 274 handler = checker.check(line_info)
275 275 if handler:
276 276 return handler
277 277 return self.get_handler_by_name('normal')
278 278
279 279 def transform_line(self, line, continue_prompt):
280 280 """Calls the enabled transformers in order of increasing priority."""
281 281 for transformer in self.transformers:
282 282 if transformer.enabled:
283 283 line = transformer.transform(line, continue_prompt)
284 284 return line
285 285
286 286 def prefilter_line(self, line, continue_prompt=False):
287 287 """Prefilter a single input line as text.
288 288
289 289 This method prefilters a single line of text by calling the
290 290 transformers and then the checkers/handlers.
291 291 """
292 292
293 293 # print "prefilter_line: ", line, continue_prompt
294 294 # All handlers *must* return a value, even if it's blank ('').
295 295
296 296 # save the line away in case we crash, so the post-mortem handler can
297 297 # record it
298 298 self.shell._last_input_line = line
299 299
300 300 if not line:
301 301 # Return immediately on purely empty lines, so that if the user
302 302 # previously typed some whitespace that started a continuation
303 303 # prompt, he can break out of that loop with just an empty line.
304 304 # This is how the default python prompt works.
305 305 return ''
306 306
307 307 # At this point, we invoke our transformers.
308 308 if not continue_prompt or (continue_prompt and self.multi_line_specials):
309 309 line = self.transform_line(line, continue_prompt)
310 310
311 311 # Now we compute line_info for the checkers and handlers
312 312 line_info = LineInfo(line, continue_prompt)
313 313
314 314 # the input history needs to track even empty lines
315 315 stripped = line.strip()
316 316
317 317 normal_handler = self.get_handler_by_name('normal')
318 318 if not stripped:
319 319 return normal_handler.handle(line_info)
320 320
321 321 # special handlers are only allowed for single line statements
322 322 if continue_prompt and not self.multi_line_specials:
323 323 return normal_handler.handle(line_info)
324 324
325 325 prefiltered = self.prefilter_line_info(line_info)
326 326 # print "prefiltered line: %r" % prefiltered
327 327 return prefiltered
328 328
329 329 def prefilter_lines(self, lines, continue_prompt=False):
330 330 """Prefilter multiple input lines of text.
331 331
332 332 This is the main entry point for prefiltering multiple lines of
333 333 input. This simply calls :meth:`prefilter_line` for each line of
334 334 input.
335 335
336 336 This covers cases where there are multiple lines in the user entry,
337 337 which is the case when the user goes back to a multiline history
338 338 entry and presses enter.
339 339 """
340 340 llines = lines.rstrip('\n').split('\n')
341 341 # We can get multiple lines in one shot, where multiline input 'blends'
342 342 # into one line, in cases like recalling from the readline history
343 343 # buffer. We need to make sure that in such cases, we correctly
344 344 # communicate downstream which line is first and which are continuation
345 345 # ones.
346 346 if len(llines) > 1:
347 347 out = '\n'.join([self.prefilter_line(line, lnum>0)
348 348 for lnum, line in enumerate(llines) ])
349 349 else:
350 350 out = self.prefilter_line(llines[0], continue_prompt)
351 351
352 352 return out
353 353
354 354 #-----------------------------------------------------------------------------
355 355 # Prefilter transformers
356 356 #-----------------------------------------------------------------------------
357 357
358 358
359 359 class PrefilterTransformer(Configurable):
360 360 """Transform a line of user input."""
361 361
362 362 priority = Integer(100, config=True)
363 363 # Transformers don't currently use shell or prefilter_manager, but as we
364 364 # move away from checkers and handlers, they will need them.
365 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
366 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager')
365 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
366 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager', allow_none=True)
367 367 enabled = Bool(True, config=True)
368 368
369 369 def __init__(self, shell=None, prefilter_manager=None, **kwargs):
370 370 super(PrefilterTransformer, self).__init__(
371 371 shell=shell, prefilter_manager=prefilter_manager, **kwargs
372 372 )
373 373 self.prefilter_manager.register_transformer(self)
374 374
375 375 def transform(self, line, continue_prompt):
376 376 """Transform a line, returning the new one."""
377 377 return None
378 378
379 379 def __repr__(self):
380 380 return "<%s(priority=%r, enabled=%r)>" % (
381 381 self.__class__.__name__, self.priority, self.enabled)
382 382
383 383
384 384 #-----------------------------------------------------------------------------
385 385 # Prefilter checkers
386 386 #-----------------------------------------------------------------------------
387 387
388 388
389 389 class PrefilterChecker(Configurable):
390 390 """Inspect an input line and return a handler for that line."""
391 391
392 392 priority = Integer(100, config=True)
393 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
394 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager')
393 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
394 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager', allow_none=True)
395 395 enabled = Bool(True, config=True)
396 396
397 397 def __init__(self, shell=None, prefilter_manager=None, **kwargs):
398 398 super(PrefilterChecker, self).__init__(
399 399 shell=shell, prefilter_manager=prefilter_manager, **kwargs
400 400 )
401 401 self.prefilter_manager.register_checker(self)
402 402
403 403 def check(self, line_info):
404 404 """Inspect line_info and return a handler instance or None."""
405 405 return None
406 406
407 407 def __repr__(self):
408 408 return "<%s(priority=%r, enabled=%r)>" % (
409 409 self.__class__.__name__, self.priority, self.enabled)
410 410
411 411
412 412 class EmacsChecker(PrefilterChecker):
413 413
414 414 priority = Integer(100, config=True)
415 415 enabled = Bool(False, config=True)
416 416
417 417 def check(self, line_info):
418 418 "Emacs ipython-mode tags certain input lines."
419 419 if line_info.line.endswith('# PYTHON-MODE'):
420 420 return self.prefilter_manager.get_handler_by_name('emacs')
421 421 else:
422 422 return None
423 423
424 424
425 425 class MacroChecker(PrefilterChecker):
426 426
427 427 priority = Integer(250, config=True)
428 428
429 429 def check(self, line_info):
430 430 obj = self.shell.user_ns.get(line_info.ifun)
431 431 if isinstance(obj, Macro):
432 432 return self.prefilter_manager.get_handler_by_name('macro')
433 433 else:
434 434 return None
435 435
436 436
437 437 class IPyAutocallChecker(PrefilterChecker):
438 438
439 439 priority = Integer(300, config=True)
440 440
441 441 def check(self, line_info):
442 442 "Instances of IPyAutocall in user_ns get autocalled immediately"
443 443 obj = self.shell.user_ns.get(line_info.ifun, None)
444 444 if isinstance(obj, IPyAutocall):
445 445 obj.set_ip(self.shell)
446 446 return self.prefilter_manager.get_handler_by_name('auto')
447 447 else:
448 448 return None
449 449
450 450
451 451 class AssignmentChecker(PrefilterChecker):
452 452
453 453 priority = Integer(600, config=True)
454 454
455 455 def check(self, line_info):
456 456 """Check to see if user is assigning to a var for the first time, in
457 457 which case we want to avoid any sort of automagic / autocall games.
458 458
459 459 This allows users to assign to either alias or magic names true python
460 460 variables (the magic/alias systems always take second seat to true
461 461 python code). E.g. ls='hi', or ls,that=1,2"""
462 462 if line_info.the_rest:
463 463 if line_info.the_rest[0] in '=,':
464 464 return self.prefilter_manager.get_handler_by_name('normal')
465 465 else:
466 466 return None
467 467
468 468
469 469 class AutoMagicChecker(PrefilterChecker):
470 470
471 471 priority = Integer(700, config=True)
472 472
473 473 def check(self, line_info):
474 474 """If the ifun is magic, and automagic is on, run it. Note: normal,
475 475 non-auto magic would already have been triggered via '%' in
476 476 check_esc_chars. This just checks for automagic. Also, before
477 477 triggering the magic handler, make sure that there is nothing in the
478 478 user namespace which could shadow it."""
479 479 if not self.shell.automagic or not self.shell.find_magic(line_info.ifun):
480 480 return None
481 481
482 482 # We have a likely magic method. Make sure we should actually call it.
483 483 if line_info.continue_prompt and not self.prefilter_manager.multi_line_specials:
484 484 return None
485 485
486 486 head = line_info.ifun.split('.',1)[0]
487 487 if is_shadowed(head, self.shell):
488 488 return None
489 489
490 490 return self.prefilter_manager.get_handler_by_name('magic')
491 491
492 492
493 493 class PythonOpsChecker(PrefilterChecker):
494 494
495 495 priority = Integer(900, config=True)
496 496
497 497 def check(self, line_info):
498 498 """If the 'rest' of the line begins with a function call or pretty much
499 499 any python operator, we should simply execute the line (regardless of
500 500 whether or not there's a possible autocall expansion). This avoids
501 501 spurious (and very confusing) geattr() accesses."""
502 502 if line_info.the_rest and line_info.the_rest[0] in '!=()<>,+*/%^&|':
503 503 return self.prefilter_manager.get_handler_by_name('normal')
504 504 else:
505 505 return None
506 506
507 507
508 508 class AutocallChecker(PrefilterChecker):
509 509
510 510 priority = Integer(1000, config=True)
511 511
512 512 function_name_regexp = CRegExp(re_fun_name, config=True,
513 513 help="RegExp to identify potential function names.")
514 514 exclude_regexp = CRegExp(re_exclude_auto, config=True,
515 515 help="RegExp to exclude strings with this start from autocalling.")
516 516
517 517 def check(self, line_info):
518 518 "Check if the initial word/function is callable and autocall is on."
519 519 if not self.shell.autocall:
520 520 return None
521 521
522 522 oinfo = line_info.ofind(self.shell) # This can mutate state via getattr
523 523 if not oinfo['found']:
524 524 return None
525 525
526 526 if callable(oinfo['obj']) \
527 527 and (not self.exclude_regexp.match(line_info.the_rest)) \
528 528 and self.function_name_regexp.match(line_info.ifun):
529 529 return self.prefilter_manager.get_handler_by_name('auto')
530 530 else:
531 531 return None
532 532
533 533
534 534 #-----------------------------------------------------------------------------
535 535 # Prefilter handlers
536 536 #-----------------------------------------------------------------------------
537 537
538 538
539 539 class PrefilterHandler(Configurable):
540 540
541 541 handler_name = Unicode('normal')
542 542 esc_strings = List([])
543 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
544 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager')
543 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
544 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager', allow_none=True)
545 545
546 546 def __init__(self, shell=None, prefilter_manager=None, **kwargs):
547 547 super(PrefilterHandler, self).__init__(
548 548 shell=shell, prefilter_manager=prefilter_manager, **kwargs
549 549 )
550 550 self.prefilter_manager.register_handler(
551 551 self.handler_name,
552 552 self,
553 553 self.esc_strings
554 554 )
555 555
556 556 def handle(self, line_info):
557 557 # print "normal: ", line_info
558 558 """Handle normal input lines. Use as a template for handlers."""
559 559
560 560 # With autoindent on, we need some way to exit the input loop, and I
561 561 # don't want to force the user to have to backspace all the way to
562 562 # clear the line. The rule will be in this case, that either two
563 563 # lines of pure whitespace in a row, or a line of pure whitespace but
564 564 # of a size different to the indent level, will exit the input loop.
565 565 line = line_info.line
566 566 continue_prompt = line_info.continue_prompt
567 567
568 568 if (continue_prompt and
569 569 self.shell.autoindent and
570 570 line.isspace() and
571 571 0 < abs(len(line) - self.shell.indent_current_nsp) <= 2):
572 572 line = ''
573 573
574 574 return line
575 575
576 576 def __str__(self):
577 577 return "<%s(name=%s)>" % (self.__class__.__name__, self.handler_name)
578 578
579 579
580 580 class MacroHandler(PrefilterHandler):
581 581 handler_name = Unicode("macro")
582 582
583 583 def handle(self, line_info):
584 584 obj = self.shell.user_ns.get(line_info.ifun)
585 585 pre_space = line_info.pre_whitespace
586 586 line_sep = "\n" + pre_space
587 587 return pre_space + line_sep.join(obj.value.splitlines())
588 588
589 589
590 590 class MagicHandler(PrefilterHandler):
591 591
592 592 handler_name = Unicode('magic')
593 593 esc_strings = List([ESC_MAGIC])
594 594
595 595 def handle(self, line_info):
596 596 """Execute magic functions."""
597 597 ifun = line_info.ifun
598 598 the_rest = line_info.the_rest
599 599 cmd = '%sget_ipython().magic(%r)' % (line_info.pre_whitespace,
600 600 (ifun + " " + the_rest))
601 601 return cmd
602 602
603 603
604 604 class AutoHandler(PrefilterHandler):
605 605
606 606 handler_name = Unicode('auto')
607 607 esc_strings = List([ESC_PAREN, ESC_QUOTE, ESC_QUOTE2])
608 608
609 609 def handle(self, line_info):
610 610 """Handle lines which can be auto-executed, quoting if requested."""
611 611 line = line_info.line
612 612 ifun = line_info.ifun
613 613 the_rest = line_info.the_rest
614 614 pre = line_info.pre
615 615 esc = line_info.esc
616 616 continue_prompt = line_info.continue_prompt
617 617 obj = line_info.ofind(self.shell)['obj']
618 618 #print 'pre <%s> ifun <%s> rest <%s>' % (pre,ifun,the_rest) # dbg
619 619
620 620 # This should only be active for single-line input!
621 621 if continue_prompt:
622 622 return line
623 623
624 624 force_auto = isinstance(obj, IPyAutocall)
625 625
626 626 # User objects sometimes raise exceptions on attribute access other
627 627 # than AttributeError (we've seen it in the past), so it's safest to be
628 628 # ultra-conservative here and catch all.
629 629 try:
630 630 auto_rewrite = obj.rewrite
631 631 except Exception:
632 632 auto_rewrite = True
633 633
634 634 if esc == ESC_QUOTE:
635 635 # Auto-quote splitting on whitespace
636 636 newcmd = '%s("%s")' % (ifun,'", "'.join(the_rest.split()) )
637 637 elif esc == ESC_QUOTE2:
638 638 # Auto-quote whole string
639 639 newcmd = '%s("%s")' % (ifun,the_rest)
640 640 elif esc == ESC_PAREN:
641 641 newcmd = '%s(%s)' % (ifun,",".join(the_rest.split()))
642 642 else:
643 643 # Auto-paren.
644 644 if force_auto:
645 645 # Don't rewrite if it is already a call.
646 646 do_rewrite = not the_rest.startswith('(')
647 647 else:
648 648 if not the_rest:
649 649 # We only apply it to argument-less calls if the autocall
650 650 # parameter is set to 2.
651 651 do_rewrite = (self.shell.autocall >= 2)
652 652 elif the_rest.startswith('[') and hasattr(obj, '__getitem__'):
653 653 # Don't autocall in this case: item access for an object
654 654 # which is BOTH callable and implements __getitem__.
655 655 do_rewrite = False
656 656 else:
657 657 do_rewrite = True
658 658
659 659 # Figure out the rewritten command
660 660 if do_rewrite:
661 661 if the_rest.endswith(';'):
662 662 newcmd = '%s(%s);' % (ifun.rstrip(),the_rest[:-1])
663 663 else:
664 664 newcmd = '%s(%s)' % (ifun.rstrip(), the_rest)
665 665 else:
666 666 normal_handler = self.prefilter_manager.get_handler_by_name('normal')
667 667 return normal_handler.handle(line_info)
668 668
669 669 # Display the rewritten call
670 670 if auto_rewrite:
671 671 self.shell.auto_rewrite_input(newcmd)
672 672
673 673 return newcmd
674 674
675 675
676 676 class EmacsHandler(PrefilterHandler):
677 677
678 678 handler_name = Unicode('emacs')
679 679 esc_strings = List([])
680 680
681 681 def handle(self, line_info):
682 682 """Handle input lines marked by python-mode."""
683 683
684 684 # Currently, nothing is done. Later more functionality can be added
685 685 # here if needed.
686 686
687 687 # The input cache shouldn't be updated
688 688 return line_info.line
689 689
690 690
691 691 #-----------------------------------------------------------------------------
692 692 # Defaults
693 693 #-----------------------------------------------------------------------------
694 694
695 695
696 696 _default_transformers = [
697 697 ]
698 698
699 699 _default_checkers = [
700 700 EmacsChecker,
701 701 MacroChecker,
702 702 IPyAutocallChecker,
703 703 AssignmentChecker,
704 704 AutoMagicChecker,
705 705 PythonOpsChecker,
706 706 AutocallChecker
707 707 ]
708 708
709 709 _default_handlers = [
710 710 PrefilterHandler,
711 711 MacroHandler,
712 712 MagicHandler,
713 713 AutoHandler,
714 714 EmacsHandler
715 715 ]
@@ -1,442 +1,442 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Classes for handling input/output prompts.
3 3
4 4 Authors:
5 5
6 6 * Fernando Perez
7 7 * Brian Granger
8 8 * Thomas Kluyver
9 9 """
10 10
11 11 #-----------------------------------------------------------------------------
12 12 # Copyright (C) 2008-2011 The IPython Development Team
13 13 # Copyright (C) 2001-2007 Fernando Perez <fperez@colorado.edu>
14 14 #
15 15 # Distributed under the terms of the BSD License. The full license is in
16 16 # the file COPYING, distributed as part of this software.
17 17 #-----------------------------------------------------------------------------
18 18
19 19 #-----------------------------------------------------------------------------
20 20 # Imports
21 21 #-----------------------------------------------------------------------------
22 22
23 23 import os
24 24 import re
25 25 import socket
26 26 import sys
27 27 import time
28 28
29 29 from string import Formatter
30 30
31 31 from IPython.config.configurable import Configurable
32 32 from IPython.core import release
33 33 from IPython.utils import coloransi, py3compat
34 34 from IPython.utils.traitlets import (Unicode, Instance, Dict, Bool, Int)
35 35
36 36 #-----------------------------------------------------------------------------
37 37 # Color schemes for prompts
38 38 #-----------------------------------------------------------------------------
39 39
40 40 InputColors = coloransi.InputTermColors # just a shorthand
41 41 Colors = coloransi.TermColors # just a shorthand
42 42
43 43 color_lists = dict(normal=Colors(), inp=InputColors(), nocolor=coloransi.NoColors())
44 44
45 45 PColNoColors = coloransi.ColorScheme(
46 46 'NoColor',
47 47 in_prompt = InputColors.NoColor, # Input prompt
48 48 in_number = InputColors.NoColor, # Input prompt number
49 49 in_prompt2 = InputColors.NoColor, # Continuation prompt
50 50 in_normal = InputColors.NoColor, # color off (usu. Colors.Normal)
51 51
52 52 out_prompt = Colors.NoColor, # Output prompt
53 53 out_number = Colors.NoColor, # Output prompt number
54 54
55 55 normal = Colors.NoColor # color off (usu. Colors.Normal)
56 56 )
57 57
58 58 # make some schemes as instances so we can copy them for modification easily:
59 59 PColLinux = coloransi.ColorScheme(
60 60 'Linux',
61 61 in_prompt = InputColors.Green,
62 62 in_number = InputColors.LightGreen,
63 63 in_prompt2 = InputColors.Green,
64 64 in_normal = InputColors.Normal, # color off (usu. Colors.Normal)
65 65
66 66 out_prompt = Colors.Red,
67 67 out_number = Colors.LightRed,
68 68
69 69 normal = Colors.Normal
70 70 )
71 71
72 72 # Slightly modified Linux for light backgrounds
73 73 PColLightBG = PColLinux.copy('LightBG')
74 74
75 75 PColLightBG.colors.update(
76 76 in_prompt = InputColors.Blue,
77 77 in_number = InputColors.LightBlue,
78 78 in_prompt2 = InputColors.Blue
79 79 )
80 80
81 81 #-----------------------------------------------------------------------------
82 82 # Utilities
83 83 #-----------------------------------------------------------------------------
84 84
85 85 class LazyEvaluate(object):
86 86 """This is used for formatting strings with values that need to be updated
87 87 at that time, such as the current time or working directory."""
88 88 def __init__(self, func, *args, **kwargs):
89 89 self.func = func
90 90 self.args = args
91 91 self.kwargs = kwargs
92 92
93 93 def __call__(self, **kwargs):
94 94 self.kwargs.update(kwargs)
95 95 return self.func(*self.args, **self.kwargs)
96 96
97 97 def __str__(self):
98 98 return str(self())
99 99
100 100 def __unicode__(self):
101 101 return py3compat.unicode_type(self())
102 102
103 103 def __format__(self, format_spec):
104 104 return format(self(), format_spec)
105 105
106 106 def multiple_replace(dict, text):
107 107 """ Replace in 'text' all occurences of any key in the given
108 108 dictionary by its corresponding value. Returns the new string."""
109 109
110 110 # Function by Xavier Defrang, originally found at:
111 111 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/81330
112 112
113 113 # Create a regular expression from the dictionary keys
114 114 regex = re.compile("(%s)" % "|".join(map(re.escape, dict.keys())))
115 115 # For each match, look-up corresponding value in dictionary
116 116 return regex.sub(lambda mo: dict[mo.string[mo.start():mo.end()]], text)
117 117
118 118 #-----------------------------------------------------------------------------
119 119 # Special characters that can be used in prompt templates, mainly bash-like
120 120 #-----------------------------------------------------------------------------
121 121
122 122 # If $HOME isn't defined (Windows), make it an absurd string so that it can
123 123 # never be expanded out into '~'. Basically anything which can never be a
124 124 # reasonable directory name will do, we just want the $HOME -> '~' operation
125 125 # to become a no-op. We pre-compute $HOME here so it's not done on every
126 126 # prompt call.
127 127
128 128 # FIXME:
129 129
130 130 # - This should be turned into a class which does proper namespace management,
131 131 # since the prompt specials need to be evaluated in a certain namespace.
132 132 # Currently it's just globals, which need to be managed manually by code
133 133 # below.
134 134
135 135 # - I also need to split up the color schemes from the prompt specials
136 136 # somehow. I don't have a clean design for that quite yet.
137 137
138 138 HOME = py3compat.str_to_unicode(os.environ.get("HOME","//////:::::ZZZZZ,,,~~~"))
139 139
140 140 # This is needed on FreeBSD, and maybe other systems which symlink /home to
141 141 # /usr/home, but retain the $HOME variable as pointing to /home
142 142 HOME = os.path.realpath(HOME)
143 143
144 144 # We precompute a few more strings here for the prompt_specials, which are
145 145 # fixed once ipython starts. This reduces the runtime overhead of computing
146 146 # prompt strings.
147 147 USER = py3compat.str_to_unicode(os.environ.get("USER",''))
148 148 HOSTNAME = py3compat.str_to_unicode(socket.gethostname())
149 149 HOSTNAME_SHORT = HOSTNAME.split(".")[0]
150 150
151 151 # IronPython doesn't currently have os.getuid() even if
152 152 # os.name == 'posix'; 2/8/2014
153 153 ROOT_SYMBOL = "#" if (os.name=='nt' or sys.platform=='cli' or os.getuid()==0) else "$"
154 154
155 155 prompt_abbreviations = {
156 156 # Prompt/history count
157 157 '%n' : '{color.number}' '{count}' '{color.prompt}',
158 158 r'\#': '{color.number}' '{count}' '{color.prompt}',
159 159 # Just the prompt counter number, WITHOUT any coloring wrappers, so users
160 160 # can get numbers displayed in whatever color they want.
161 161 r'\N': '{count}',
162 162
163 163 # Prompt/history count, with the actual digits replaced by dots. Used
164 164 # mainly in continuation prompts (prompt_in2)
165 165 r'\D': '{dots}',
166 166
167 167 # Current time
168 168 r'\T' : '{time}',
169 169 # Current working directory
170 170 r'\w': '{cwd}',
171 171 # Basename of current working directory.
172 172 # (use os.sep to make this portable across OSes)
173 173 r'\W' : '{cwd_last}',
174 174 # These X<N> are an extension to the normal bash prompts. They return
175 175 # N terms of the path, after replacing $HOME with '~'
176 176 r'\X0': '{cwd_x[0]}',
177 177 r'\X1': '{cwd_x[1]}',
178 178 r'\X2': '{cwd_x[2]}',
179 179 r'\X3': '{cwd_x[3]}',
180 180 r'\X4': '{cwd_x[4]}',
181 181 r'\X5': '{cwd_x[5]}',
182 182 # Y<N> are similar to X<N>, but they show '~' if it's the directory
183 183 # N+1 in the list. Somewhat like %cN in tcsh.
184 184 r'\Y0': '{cwd_y[0]}',
185 185 r'\Y1': '{cwd_y[1]}',
186 186 r'\Y2': '{cwd_y[2]}',
187 187 r'\Y3': '{cwd_y[3]}',
188 188 r'\Y4': '{cwd_y[4]}',
189 189 r'\Y5': '{cwd_y[5]}',
190 190 # Hostname up to first .
191 191 r'\h': HOSTNAME_SHORT,
192 192 # Full hostname
193 193 r'\H': HOSTNAME,
194 194 # Username of current user
195 195 r'\u': USER,
196 196 # Escaped '\'
197 197 '\\\\': '\\',
198 198 # Newline
199 199 r'\n': '\n',
200 200 # Carriage return
201 201 r'\r': '\r',
202 202 # Release version
203 203 r'\v': release.version,
204 204 # Root symbol ($ or #)
205 205 r'\$': ROOT_SYMBOL,
206 206 }
207 207
208 208 #-----------------------------------------------------------------------------
209 209 # More utilities
210 210 #-----------------------------------------------------------------------------
211 211
212 212 def cwd_filt(depth):
213 213 """Return the last depth elements of the current working directory.
214 214
215 215 $HOME is always replaced with '~'.
216 216 If depth==0, the full path is returned."""
217 217
218 218 cwd = py3compat.getcwd().replace(HOME,"~")
219 219 out = os.sep.join(cwd.split(os.sep)[-depth:])
220 220 return out or os.sep
221 221
222 222 def cwd_filt2(depth):
223 223 """Return the last depth elements of the current working directory.
224 224
225 225 $HOME is always replaced with '~'.
226 226 If depth==0, the full path is returned."""
227 227
228 228 full_cwd = py3compat.getcwd()
229 229 cwd = full_cwd.replace(HOME,"~").split(os.sep)
230 230 if '~' in cwd and len(cwd) == depth+1:
231 231 depth += 1
232 232 drivepart = ''
233 233 if sys.platform == 'win32' and len(cwd) > depth:
234 234 drivepart = os.path.splitdrive(full_cwd)[0]
235 235 out = drivepart + '/'.join(cwd[-depth:])
236 236
237 237 return out or os.sep
238 238
239 239 #-----------------------------------------------------------------------------
240 240 # Prompt classes
241 241 #-----------------------------------------------------------------------------
242 242
243 243 lazily_evaluate = {'time': LazyEvaluate(time.strftime, "%H:%M:%S"),
244 244 'cwd': LazyEvaluate(py3compat.getcwd),
245 245 'cwd_last': LazyEvaluate(lambda: py3compat.getcwd().split(os.sep)[-1]),
246 246 'cwd_x': [LazyEvaluate(lambda: py3compat.getcwd().replace(HOME,"~"))] +\
247 247 [LazyEvaluate(cwd_filt, x) for x in range(1,6)],
248 248 'cwd_y': [LazyEvaluate(cwd_filt2, x) for x in range(6)]
249 249 }
250 250
251 251 def _lenlastline(s):
252 252 """Get the length of the last line. More intelligent than
253 253 len(s.splitlines()[-1]).
254 254 """
255 255 if not s or s.endswith(('\n', '\r')):
256 256 return 0
257 257 return len(s.splitlines()[-1])
258 258
259 259
260 260 class UserNSFormatter(Formatter):
261 261 """A Formatter that falls back on a shell's user_ns and __builtins__ for name resolution"""
262 262 def __init__(self, shell):
263 263 self.shell = shell
264 264
265 265 def get_value(self, key, args, kwargs):
266 266 # try regular formatting first:
267 267 try:
268 268 return Formatter.get_value(self, key, args, kwargs)
269 269 except Exception:
270 270 pass
271 271 # next, look in user_ns and builtins:
272 272 for container in (self.shell.user_ns, __builtins__):
273 273 if key in container:
274 274 return container[key]
275 275 # nothing found, put error message in its place
276 276 return "<ERROR: '%s' not found>" % key
277 277
278 278
279 279 class PromptManager(Configurable):
280 280 """This is the primary interface for producing IPython's prompts."""
281 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
281 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
282 282
283 color_scheme_table = Instance(coloransi.ColorSchemeTable)
283 color_scheme_table = Instance(coloransi.ColorSchemeTable, allow_none=True)
284 284 color_scheme = Unicode('Linux', config=True)
285 285 def _color_scheme_changed(self, name, new_value):
286 286 self.color_scheme_table.set_active_scheme(new_value)
287 287 for pname in ['in', 'in2', 'out', 'rewrite']:
288 288 # We need to recalculate the number of invisible characters
289 289 self.update_prompt(pname)
290 290
291 291 lazy_evaluate_fields = Dict(help="""
292 292 This maps field names used in the prompt templates to functions which
293 293 will be called when the prompt is rendered. This allows us to include
294 294 things like the current time in the prompts. Functions are only called
295 295 if they are used in the prompt.
296 296 """)
297 297 def _lazy_evaluate_fields_default(self): return lazily_evaluate.copy()
298 298
299 299 in_template = Unicode('In [\\#]: ', config=True,
300 300 help="Input prompt. '\\#' will be transformed to the prompt number")
301 301 in2_template = Unicode(' .\\D.: ', config=True,
302 302 help="Continuation prompt.")
303 303 out_template = Unicode('Out[\\#]: ', config=True,
304 304 help="Output prompt. '\\#' will be transformed to the prompt number")
305 305
306 306 justify = Bool(True, config=True, help="""
307 307 If True (default), each prompt will be right-aligned with the
308 308 preceding one.
309 309 """)
310 310
311 311 # We actually store the expanded templates here:
312 312 templates = Dict()
313 313
314 314 # The number of characters in the last prompt rendered, not including
315 315 # colour characters.
316 316 width = Int()
317 317 txtwidth = Int() # Not including right-justification
318 318
319 319 # The number of characters in each prompt which don't contribute to width
320 320 invisible_chars = Dict()
321 321 def _invisible_chars_default(self):
322 322 return {'in': 0, 'in2': 0, 'out': 0, 'rewrite':0}
323 323
324 324 def __init__(self, shell, **kwargs):
325 325 super(PromptManager, self).__init__(shell=shell, **kwargs)
326 326
327 327 # Prepare colour scheme table
328 328 self.color_scheme_table = coloransi.ColorSchemeTable([PColNoColors,
329 329 PColLinux, PColLightBG], self.color_scheme)
330 330
331 331 self._formatter = UserNSFormatter(shell)
332 332 # Prepare templates & numbers of invisible characters
333 333 self.update_prompt('in', self.in_template)
334 334 self.update_prompt('in2', self.in2_template)
335 335 self.update_prompt('out', self.out_template)
336 336 self.update_prompt('rewrite')
337 337 self.on_trait_change(self._update_prompt_trait, ['in_template',
338 338 'in2_template', 'out_template'])
339 339
340 340 def update_prompt(self, name, new_template=None):
341 341 """This is called when a prompt template is updated. It processes
342 342 abbreviations used in the prompt template (like \#) and calculates how
343 343 many invisible characters (ANSI colour escapes) the resulting prompt
344 344 contains.
345 345
346 346 It is also called for each prompt on changing the colour scheme. In both
347 347 cases, traitlets should take care of calling this automatically.
348 348 """
349 349 if new_template is not None:
350 350 self.templates[name] = multiple_replace(prompt_abbreviations, new_template)
351 351 # We count invisible characters (colour escapes) on the last line of the
352 352 # prompt, to calculate the width for lining up subsequent prompts.
353 353 invis_chars = _lenlastline(self._render(name, color=True)) - \
354 354 _lenlastline(self._render(name, color=False))
355 355 self.invisible_chars[name] = invis_chars
356 356
357 357 def _update_prompt_trait(self, traitname, new_template):
358 358 name = traitname[:-9] # Cut off '_template'
359 359 self.update_prompt(name, new_template)
360 360
361 361 def _render(self, name, color=True, **kwargs):
362 362 """Render but don't justify, or update the width or txtwidth attributes.
363 363 """
364 364 if name == 'rewrite':
365 365 return self._render_rewrite(color=color)
366 366
367 367 if color:
368 368 scheme = self.color_scheme_table.active_colors
369 369 if name=='out':
370 370 colors = color_lists['normal']
371 371 colors.number, colors.prompt, colors.normal = \
372 372 scheme.out_number, scheme.out_prompt, scheme.normal
373 373 else:
374 374 colors = color_lists['inp']
375 375 colors.number, colors.prompt, colors.normal = \
376 376 scheme.in_number, scheme.in_prompt, scheme.in_normal
377 377 if name=='in2':
378 378 colors.prompt = scheme.in_prompt2
379 379 else:
380 380 # No color
381 381 colors = color_lists['nocolor']
382 382 colors.number, colors.prompt, colors.normal = '', '', ''
383 383
384 384 count = self.shell.execution_count # Shorthand
385 385 # Build the dictionary to be passed to string formatting
386 386 fmtargs = dict(color=colors, count=count,
387 387 dots="."*len(str(count)),
388 388 width=self.width, txtwidth=self.txtwidth )
389 389 fmtargs.update(self.lazy_evaluate_fields)
390 390 fmtargs.update(kwargs)
391 391
392 392 # Prepare the prompt
393 393 prompt = colors.prompt + self.templates[name] + colors.normal
394 394
395 395 # Fill in required fields
396 396 return self._formatter.format(prompt, **fmtargs)
397 397
398 398 def _render_rewrite(self, color=True):
399 399 """Render the ---> rewrite prompt."""
400 400 if color:
401 401 scheme = self.color_scheme_table.active_colors
402 402 # We need a non-input version of these escapes
403 403 color_prompt = scheme.in_prompt.replace("\001","").replace("\002","")
404 404 color_normal = scheme.normal
405 405 else:
406 406 color_prompt, color_normal = '', ''
407 407
408 408 return color_prompt + "-> ".rjust(self.txtwidth, "-") + color_normal
409 409
410 410 def render(self, name, color=True, just=None, **kwargs):
411 411 """
412 412 Render the selected prompt.
413 413
414 414 Parameters
415 415 ----------
416 416 name : str
417 417 Which prompt to render. One of 'in', 'in2', 'out', 'rewrite'
418 418 color : bool
419 419 If True (default), include ANSI escape sequences for a coloured prompt.
420 420 just : bool
421 421 If True, justify the prompt to the width of the last prompt. The
422 422 default is stored in self.justify.
423 423 **kwargs :
424 424 Additional arguments will be passed to the string formatting operation,
425 425 so they can override the values that would otherwise fill in the
426 426 template.
427 427
428 428 Returns
429 429 -------
430 430 A string containing the rendered prompt.
431 431 """
432 432 res = self._render(name, color=color, **kwargs)
433 433
434 434 # Handle justification of prompt
435 435 invis_chars = self.invisible_chars[name] if color else 0
436 436 self.txtwidth = _lenlastline(res) - invis_chars
437 437 just = self.justify if (just is None) else just
438 438 # If the prompt spans more than one line, don't try to justify it:
439 439 if just and name != 'in' and ('\n' not in res) and ('\r' not in res):
440 440 res = res.rjust(self.width + invis_chars)
441 441 self.width = _lenlastline(res) - invis_chars
442 442 return res
@@ -1,432 +1,433 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
7 7 # Copyright (c) IPython Development Team.
8 8 # Distributed under the terms of the Modified BSD License.
9 9
10 10 from __future__ import absolute_import
11 11 from __future__ import print_function
12 12
13 13 import glob
14 14 import os
15 15 import sys
16 16
17 17 from IPython.config.application import boolean_flag
18 18 from IPython.config.configurable import Configurable
19 19 from IPython.config.loader import Config
20 20 from IPython.core import pylabtools
21 21 from IPython.utils import py3compat
22 22 from IPython.utils.contexts import preserve_keys
23 23 from IPython.utils.path import filefind
24 24 from IPython.utils.traitlets import (
25 25 Unicode, Instance, List, Bool, CaselessStrEnum
26 26 )
27 27 from IPython.lib.inputhook import guis
28 28
29 29 #-----------------------------------------------------------------------------
30 30 # Aliases and Flags
31 31 #-----------------------------------------------------------------------------
32 32
33 33 gui_keys = tuple(sorted([ key for key in guis if key is not None ]))
34 34
35 35 backend_keys = sorted(pylabtools.backends.keys())
36 36 backend_keys.insert(0, 'auto')
37 37
38 38 shell_flags = {}
39 39
40 40 addflag = lambda *args: shell_flags.update(boolean_flag(*args))
41 41 addflag('autoindent', 'InteractiveShell.autoindent',
42 42 'Turn on autoindenting.', 'Turn off autoindenting.'
43 43 )
44 44 addflag('automagic', 'InteractiveShell.automagic',
45 45 """Turn on the auto calling of magic commands. Type %%magic at the
46 46 IPython prompt for more information.""",
47 47 'Turn off the auto calling of magic commands.'
48 48 )
49 49 addflag('pdb', 'InteractiveShell.pdb',
50 50 "Enable auto calling the pdb debugger after every exception.",
51 51 "Disable auto calling the pdb debugger after every exception."
52 52 )
53 53 # pydb flag doesn't do any config, as core.debugger switches on import,
54 54 # which is before parsing. This just allows the flag to be passed.
55 55 shell_flags.update(dict(
56 56 pydb = ({},
57 57 """Use the third party 'pydb' package as debugger, instead of pdb.
58 58 Requires that pydb is installed."""
59 59 )
60 60 ))
61 61 addflag('pprint', 'PlainTextFormatter.pprint',
62 62 "Enable auto pretty printing of results.",
63 63 "Disable auto pretty printing of results."
64 64 )
65 65 addflag('color-info', 'InteractiveShell.color_info',
66 66 """IPython can display information about objects via a set of functions,
67 67 and optionally can use colors for this, syntax highlighting
68 68 source code and various other elements. This is on by default, but can cause
69 69 problems with some pagers. If you see such problems, you can disable the
70 70 colours.""",
71 71 "Disable using colors for info related things."
72 72 )
73 73 addflag('deep-reload', 'InteractiveShell.deep_reload',
74 74 """Enable deep (recursive) reloading by default. IPython can use the
75 75 deep_reload module which reloads changes in modules recursively (it
76 76 replaces the reload() function, so you don't need to change anything to
77 77 use it). deep_reload() forces a full reload of modules whose code may
78 78 have changed, which the default reload() function does not. When
79 79 deep_reload is off, IPython will use the normal reload(), but
80 80 deep_reload will still be available as dreload(). This feature is off
81 81 by default [which means that you have both normal reload() and
82 82 dreload()].""",
83 83 "Disable deep (recursive) reloading by default."
84 84 )
85 85 nosep_config = Config()
86 86 nosep_config.InteractiveShell.separate_in = ''
87 87 nosep_config.InteractiveShell.separate_out = ''
88 88 nosep_config.InteractiveShell.separate_out2 = ''
89 89
90 90 shell_flags['nosep']=(nosep_config, "Eliminate all spacing between prompts.")
91 91 shell_flags['pylab'] = (
92 92 {'InteractiveShellApp' : {'pylab' : 'auto'}},
93 93 """Pre-load matplotlib and numpy for interactive use with
94 94 the default matplotlib backend."""
95 95 )
96 96 shell_flags['matplotlib'] = (
97 97 {'InteractiveShellApp' : {'matplotlib' : 'auto'}},
98 98 """Configure matplotlib for interactive use with
99 99 the default matplotlib backend."""
100 100 )
101 101
102 102 # it's possible we don't want short aliases for *all* of these:
103 103 shell_aliases = dict(
104 104 autocall='InteractiveShell.autocall',
105 105 colors='InteractiveShell.colors',
106 106 logfile='InteractiveShell.logfile',
107 107 logappend='InteractiveShell.logappend',
108 108 c='InteractiveShellApp.code_to_run',
109 109 m='InteractiveShellApp.module_to_run',
110 110 ext='InteractiveShellApp.extra_extension',
111 111 gui='InteractiveShellApp.gui',
112 112 pylab='InteractiveShellApp.pylab',
113 113 matplotlib='InteractiveShellApp.matplotlib',
114 114 )
115 115 shell_aliases['cache-size'] = 'InteractiveShell.cache_size'
116 116
117 117 #-----------------------------------------------------------------------------
118 118 # Main classes and functions
119 119 #-----------------------------------------------------------------------------
120 120
121 121 class InteractiveShellApp(Configurable):
122 122 """A Mixin for applications that start InteractiveShell instances.
123 123
124 124 Provides configurables for loading extensions and executing files
125 125 as part of configuring a Shell environment.
126 126
127 127 The following methods should be called by the :meth:`initialize` method
128 128 of the subclass:
129 129
130 130 - :meth:`init_path`
131 131 - :meth:`init_shell` (to be implemented by the subclass)
132 132 - :meth:`init_gui_pylab`
133 133 - :meth:`init_extensions`
134 134 - :meth:`init_code`
135 135 """
136 136 extensions = List(Unicode, config=True,
137 137 help="A list of dotted module names of IPython extensions to load."
138 138 )
139 139 extra_extension = Unicode('', config=True,
140 140 help="dotted module name of an IPython extension to load."
141 141 )
142 142
143 143 reraise_ipython_extension_failures = Bool(
144 144 False,
145 145 config=True,
146 146 help="Reraise exceptions encountered loading IPython extensions?",
147 147 )
148 148
149 149 # Extensions that are always loaded (not configurable)
150 150 default_extensions = List(Unicode, [u'storemagic'], config=False)
151 151
152 152 hide_initial_ns = Bool(True, config=True,
153 153 help="""Should variables loaded at startup (by startup files, exec_lines, etc.)
154 154 be hidden from tools like %who?"""
155 155 )
156 156
157 157 exec_files = List(Unicode, config=True,
158 158 help="""List of files to run at IPython startup."""
159 159 )
160 160 exec_PYTHONSTARTUP = Bool(True, config=True,
161 161 help="""Run the file referenced by the PYTHONSTARTUP environment
162 162 variable at IPython startup."""
163 163 )
164 164 file_to_run = Unicode('', config=True,
165 165 help="""A file to be run""")
166 166
167 167 exec_lines = List(Unicode, config=True,
168 168 help="""lines of code to run at IPython startup."""
169 169 )
170 170 code_to_run = Unicode('', config=True,
171 171 help="Execute the given command string."
172 172 )
173 173 module_to_run = Unicode('', config=True,
174 174 help="Run the module as a script."
175 175 )
176 176 gui = CaselessStrEnum(gui_keys, config=True, allow_none=True,
177 177 help="Enable GUI event loop integration with any of {0}.".format(gui_keys)
178 178 )
179 179 matplotlib = CaselessStrEnum(backend_keys, allow_none=True,
180 180 config=True,
181 181 help="""Configure matplotlib for interactive use with
182 182 the default matplotlib backend."""
183 183 )
184 184 pylab = CaselessStrEnum(backend_keys, allow_none=True,
185 185 config=True,
186 186 help="""Pre-load matplotlib and numpy for interactive use,
187 187 selecting a particular matplotlib backend and loop integration.
188 188 """
189 189 )
190 190 pylab_import_all = Bool(True, config=True,
191 191 help="""If true, IPython will populate the user namespace with numpy, pylab, etc.
192 192 and an ``import *`` is done from numpy and pylab, when using pylab mode.
193 193
194 194 When False, pylab mode should not import any names into the user namespace.
195 195 """
196 196 )
197 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
197 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC',
198 allow_none=True)
198 199
199 200 user_ns = Instance(dict, args=None, allow_none=True)
200 201 def _user_ns_changed(self, name, old, new):
201 202 if self.shell is not None:
202 203 self.shell.user_ns = new
203 204 self.shell.init_user_ns()
204 205
205 206 def init_path(self):
206 207 """Add current working directory, '', to sys.path"""
207 208 if sys.path[0] != '':
208 209 sys.path.insert(0, '')
209 210
210 211 def init_shell(self):
211 212 raise NotImplementedError("Override in subclasses")
212 213
213 214 def init_gui_pylab(self):
214 215 """Enable GUI event loop integration, taking pylab into account."""
215 216 enable = False
216 217 shell = self.shell
217 218 if self.pylab:
218 219 enable = lambda key: shell.enable_pylab(key, import_all=self.pylab_import_all)
219 220 key = self.pylab
220 221 elif self.matplotlib:
221 222 enable = shell.enable_matplotlib
222 223 key = self.matplotlib
223 224 elif self.gui:
224 225 enable = shell.enable_gui
225 226 key = self.gui
226 227
227 228 if not enable:
228 229 return
229 230
230 231 try:
231 232 r = enable(key)
232 233 except ImportError:
233 234 self.log.warn("Eventloop or matplotlib integration failed. Is matplotlib installed?")
234 235 self.shell.showtraceback()
235 236 return
236 237 except Exception:
237 238 self.log.warn("GUI event loop or pylab initialization failed")
238 239 self.shell.showtraceback()
239 240 return
240 241
241 242 if isinstance(r, tuple):
242 243 gui, backend = r[:2]
243 244 self.log.info("Enabling GUI event loop integration, "
244 245 "eventloop=%s, matplotlib=%s", gui, backend)
245 246 if key == "auto":
246 247 print("Using matplotlib backend: %s" % backend)
247 248 else:
248 249 gui = r
249 250 self.log.info("Enabling GUI event loop integration, "
250 251 "eventloop=%s", gui)
251 252
252 253 def init_extensions(self):
253 254 """Load all IPython extensions in IPythonApp.extensions.
254 255
255 256 This uses the :meth:`ExtensionManager.load_extensions` to load all
256 257 the extensions listed in ``self.extensions``.
257 258 """
258 259 try:
259 260 self.log.debug("Loading IPython extensions...")
260 261 extensions = self.default_extensions + self.extensions
261 262 if self.extra_extension:
262 263 extensions.append(self.extra_extension)
263 264 for ext in extensions:
264 265 try:
265 266 self.log.info("Loading IPython extension: %s" % ext)
266 267 self.shell.extension_manager.load_extension(ext)
267 268 except:
268 269 if self.reraise_ipython_extension_failures:
269 270 raise
270 271 msg = ("Error in loading extension: {ext}\n"
271 272 "Check your config files in {location}".format(
272 273 ext=ext,
273 274 location=self.profile_dir.location
274 275 ))
275 276 self.log.warn(msg, exc_info=True)
276 277 except:
277 278 if self.reraise_ipython_extension_failures:
278 279 raise
279 280 self.log.warn("Unknown error in loading extensions:", exc_info=True)
280 281
281 282 def init_code(self):
282 283 """run the pre-flight code, specified via exec_lines"""
283 284 self._run_startup_files()
284 285 self._run_exec_lines()
285 286 self._run_exec_files()
286 287
287 288 # Hide variables defined here from %who etc.
288 289 if self.hide_initial_ns:
289 290 self.shell.user_ns_hidden.update(self.shell.user_ns)
290 291
291 292 # command-line execution (ipython -i script.py, ipython -m module)
292 293 # should *not* be excluded from %whos
293 294 self._run_cmd_line_code()
294 295 self._run_module()
295 296
296 297 # flush output, so itwon't be attached to the first cell
297 298 sys.stdout.flush()
298 299 sys.stderr.flush()
299 300
300 301 def _run_exec_lines(self):
301 302 """Run lines of code in IPythonApp.exec_lines in the user's namespace."""
302 303 if not self.exec_lines:
303 304 return
304 305 try:
305 306 self.log.debug("Running code from IPythonApp.exec_lines...")
306 307 for line in self.exec_lines:
307 308 try:
308 309 self.log.info("Running code in user namespace: %s" %
309 310 line)
310 311 self.shell.run_cell(line, store_history=False)
311 312 except:
312 313 self.log.warn("Error in executing line in user "
313 314 "namespace: %s" % line)
314 315 self.shell.showtraceback()
315 316 except:
316 317 self.log.warn("Unknown error in handling IPythonApp.exec_lines:")
317 318 self.shell.showtraceback()
318 319
319 320 def _exec_file(self, fname, shell_futures=False):
320 321 try:
321 322 full_filename = filefind(fname, [u'.', self.ipython_dir])
322 323 except IOError as e:
323 324 self.log.warn("File not found: %r"%fname)
324 325 return
325 326 # Make sure that the running script gets a proper sys.argv as if it
326 327 # were run from a system shell.
327 328 save_argv = sys.argv
328 329 sys.argv = [full_filename] + self.extra_args[1:]
329 330 # protect sys.argv from potential unicode strings on Python 2:
330 331 if not py3compat.PY3:
331 332 sys.argv = [ py3compat.cast_bytes(a) for a in sys.argv ]
332 333 try:
333 334 if os.path.isfile(full_filename):
334 335 self.log.info("Running file in user namespace: %s" %
335 336 full_filename)
336 337 # Ensure that __file__ is always defined to match Python
337 338 # behavior.
338 339 with preserve_keys(self.shell.user_ns, '__file__'):
339 340 self.shell.user_ns['__file__'] = fname
340 341 if full_filename.endswith('.ipy'):
341 342 self.shell.safe_execfile_ipy(full_filename,
342 343 shell_futures=shell_futures)
343 344 else:
344 345 # default to python, even without extension
345 346 self.shell.safe_execfile(full_filename,
346 347 self.shell.user_ns,
347 348 shell_futures=shell_futures)
348 349 finally:
349 350 sys.argv = save_argv
350 351
351 352 def _run_startup_files(self):
352 353 """Run files from profile startup directory"""
353 354 startup_dir = self.profile_dir.startup_dir
354 355 startup_files = []
355 356
356 357 if self.exec_PYTHONSTARTUP and os.environ.get('PYTHONSTARTUP', False) and \
357 358 not (self.file_to_run or self.code_to_run or self.module_to_run):
358 359 python_startup = os.environ['PYTHONSTARTUP']
359 360 self.log.debug("Running PYTHONSTARTUP file %s...", python_startup)
360 361 try:
361 362 self._exec_file(python_startup)
362 363 except:
363 364 self.log.warn("Unknown error in handling PYTHONSTARTUP file %s:", python_startup)
364 365 self.shell.showtraceback()
365 366 finally:
366 367 # Many PYTHONSTARTUP files set up the readline completions,
367 368 # but this is often at odds with IPython's own completions.
368 369 # Do not allow PYTHONSTARTUP to set up readline.
369 370 if self.shell.has_readline:
370 371 self.shell.set_readline_completer()
371 372
372 373 startup_files += glob.glob(os.path.join(startup_dir, '*.py'))
373 374 startup_files += glob.glob(os.path.join(startup_dir, '*.ipy'))
374 375 if not startup_files:
375 376 return
376 377
377 378 self.log.debug("Running startup files from %s...", startup_dir)
378 379 try:
379 380 for fname in sorted(startup_files):
380 381 self._exec_file(fname)
381 382 except:
382 383 self.log.warn("Unknown error in handling startup files:")
383 384 self.shell.showtraceback()
384 385
385 386 def _run_exec_files(self):
386 387 """Run files from IPythonApp.exec_files"""
387 388 if not self.exec_files:
388 389 return
389 390
390 391 self.log.debug("Running files in IPythonApp.exec_files...")
391 392 try:
392 393 for fname in self.exec_files:
393 394 self._exec_file(fname)
394 395 except:
395 396 self.log.warn("Unknown error in handling IPythonApp.exec_files:")
396 397 self.shell.showtraceback()
397 398
398 399 def _run_cmd_line_code(self):
399 400 """Run code or file specified at the command-line"""
400 401 if self.code_to_run:
401 402 line = self.code_to_run
402 403 try:
403 404 self.log.info("Running code given at command line (c=): %s" %
404 405 line)
405 406 self.shell.run_cell(line, store_history=False)
406 407 except:
407 408 self.log.warn("Error in executing line in user namespace: %s" %
408 409 line)
409 410 self.shell.showtraceback()
410 411
411 412 # Like Python itself, ignore the second if the first of these is present
412 413 elif self.file_to_run:
413 414 fname = self.file_to_run
414 415 try:
415 416 self._exec_file(fname, shell_futures=True)
416 417 except:
417 418 self.log.warn("Error in executing file in user namespace: %s" %
418 419 fname)
419 420 self.shell.showtraceback()
420 421
421 422 def _run_module(self):
422 423 """Run module specified at the command-line."""
423 424 if self.module_to_run:
424 425 # Make sure that the module gets a proper sys.argv as if it were
425 426 # run using `python -m`.
426 427 save_argv = sys.argv
427 428 sys.argv = [sys.executable] + self.extra_args
428 429 try:
429 430 self.shell.safe_run_module(self.module_to_run,
430 431 self.shell.user_ns)
431 432 finally:
432 433 sys.argv = save_argv
@@ -1,1127 +1,1127 b''
1 1 # coding: utf-8
2 2 """A tornado based IPython notebook server."""
3 3
4 4 # Copyright (c) IPython Development Team.
5 5 # Distributed under the terms of the Modified BSD License.
6 6
7 7 from __future__ import print_function
8 8
9 9 import base64
10 10 import datetime
11 11 import errno
12 12 import importlib
13 13 import io
14 14 import json
15 15 import logging
16 16 import os
17 17 import random
18 18 import re
19 19 import select
20 20 import signal
21 21 import socket
22 22 import sys
23 23 import threading
24 24 import webbrowser
25 25
26 26
27 27 # check for pyzmq
28 28 from IPython.utils.zmqrelated import check_for_zmq
29 29 check_for_zmq('13', 'IPython.html')
30 30
31 31 from jinja2 import Environment, FileSystemLoader
32 32
33 33 # Install the pyzmq ioloop. This has to be done before anything else from
34 34 # tornado is imported.
35 35 from zmq.eventloop import ioloop
36 36 ioloop.install()
37 37
38 38 # check for tornado 3.1.0
39 39 msg = "The IPython Notebook requires tornado >= 4.0"
40 40 try:
41 41 import tornado
42 42 except ImportError:
43 43 raise ImportError(msg)
44 44 try:
45 45 version_info = tornado.version_info
46 46 except AttributeError:
47 47 raise ImportError(msg + ", but you have < 1.1.0")
48 48 if version_info < (4,0):
49 49 raise ImportError(msg + ", but you have %s" % tornado.version)
50 50
51 51 from tornado import httpserver
52 52 from tornado import web
53 53 from tornado.log import LogFormatter, app_log, access_log, gen_log
54 54
55 55 from IPython.html import (
56 56 DEFAULT_STATIC_FILES_PATH,
57 57 DEFAULT_TEMPLATE_PATH_LIST,
58 58 )
59 59 from .base.handlers import Template404
60 60 from .log import log_request
61 61 from .services.kernels.kernelmanager import MappingKernelManager
62 62 from .services.config import ConfigManager
63 63 from .services.contents.manager import ContentsManager
64 64 from .services.contents.filemanager import FileContentsManager
65 65 from .services.clusters.clustermanager import ClusterManager
66 66 from .services.sessions.sessionmanager import SessionManager
67 67
68 68 from .auth.login import LoginHandler
69 69 from .auth.logout import LogoutHandler
70 70 from .base.handlers import IPythonHandler, FileFindHandler
71 71
72 72 from IPython.config import Config
73 73 from IPython.config.application import catch_config_error, boolean_flag
74 74 from IPython.core.application import (
75 75 BaseIPythonApplication, base_flags, base_aliases,
76 76 )
77 77 from IPython.core.profiledir import ProfileDir
78 78 from IPython.kernel import KernelManager
79 79 from IPython.kernel.kernelspec import KernelSpecManager
80 80 from IPython.kernel.zmq.session import Session
81 81 from IPython.nbformat.sign import NotebookNotary
82 82 from IPython.utils.importstring import import_item
83 83 from IPython.utils import submodule
84 84 from IPython.utils.process import check_pid
85 85 from IPython.utils.traitlets import (
86 86 Dict, Unicode, Integer, List, Bool, Bytes, Instance,
87 87 TraitError, Type,
88 88 )
89 89 from IPython.utils import py3compat
90 90 from IPython.utils.path import filefind, get_ipython_dir
91 91 from IPython.utils.sysinfo import get_sys_info
92 92
93 93 from .nbextensions import SYSTEM_NBEXTENSIONS_DIRS
94 94 from .utils import url_path_join
95 95
96 96 #-----------------------------------------------------------------------------
97 97 # Module globals
98 98 #-----------------------------------------------------------------------------
99 99
100 100 _examples = """
101 101 ipython notebook # start the notebook
102 102 ipython notebook --profile=sympy # use the sympy profile
103 103 ipython notebook --certfile=mycert.pem # use SSL/TLS certificate
104 104 """
105 105
106 106 #-----------------------------------------------------------------------------
107 107 # Helper functions
108 108 #-----------------------------------------------------------------------------
109 109
110 110 def random_ports(port, n):
111 111 """Generate a list of n random ports near the given port.
112 112
113 113 The first 5 ports will be sequential, and the remaining n-5 will be
114 114 randomly selected in the range [port-2*n, port+2*n].
115 115 """
116 116 for i in range(min(5, n)):
117 117 yield port + i
118 118 for i in range(n-5):
119 119 yield max(1, port + random.randint(-2*n, 2*n))
120 120
121 121 def load_handlers(name):
122 122 """Load the (URL pattern, handler) tuples for each component."""
123 123 name = 'IPython.html.' + name
124 124 mod = __import__(name, fromlist=['default_handlers'])
125 125 return mod.default_handlers
126 126
127 127 #-----------------------------------------------------------------------------
128 128 # The Tornado web application
129 129 #-----------------------------------------------------------------------------
130 130
131 131 class NotebookWebApplication(web.Application):
132 132
133 133 def __init__(self, ipython_app, kernel_manager, contents_manager,
134 134 cluster_manager, session_manager, kernel_spec_manager,
135 135 config_manager, log,
136 136 base_url, default_url, settings_overrides, jinja_env_options):
137 137
138 138 settings = self.init_settings(
139 139 ipython_app, kernel_manager, contents_manager, cluster_manager,
140 140 session_manager, kernel_spec_manager, config_manager, log, base_url,
141 141 default_url, settings_overrides, jinja_env_options)
142 142 handlers = self.init_handlers(settings)
143 143
144 144 super(NotebookWebApplication, self).__init__(handlers, **settings)
145 145
146 146 def init_settings(self, ipython_app, kernel_manager, contents_manager,
147 147 cluster_manager, session_manager, kernel_spec_manager,
148 148 config_manager,
149 149 log, base_url, default_url, settings_overrides,
150 150 jinja_env_options=None):
151 151
152 152 _template_path = settings_overrides.get(
153 153 "template_path",
154 154 ipython_app.template_file_path,
155 155 )
156 156 if isinstance(_template_path, str):
157 157 _template_path = (_template_path,)
158 158 template_path = [os.path.expanduser(path) for path in _template_path]
159 159
160 160 jenv_opt = jinja_env_options if jinja_env_options else {}
161 161 env = Environment(loader=FileSystemLoader(template_path), **jenv_opt)
162 162
163 163 sys_info = get_sys_info()
164 164 if sys_info['commit_source'] == 'repository':
165 165 # don't cache (rely on 304) when working from master
166 166 version_hash = ''
167 167 else:
168 168 # reset the cache on server restart
169 169 version_hash = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
170 170
171 171 settings = dict(
172 172 # basics
173 173 log_function=log_request,
174 174 base_url=base_url,
175 175 default_url=default_url,
176 176 template_path=template_path,
177 177 static_path=ipython_app.static_file_path,
178 178 static_handler_class = FileFindHandler,
179 179 static_url_prefix = url_path_join(base_url,'/static/'),
180 180 static_handler_args = {
181 181 # don't cache custom.js
182 182 'no_cache_paths': [url_path_join(base_url, 'static', 'custom')],
183 183 },
184 184 version_hash=version_hash,
185 185
186 186 # authentication
187 187 cookie_secret=ipython_app.cookie_secret,
188 188 login_url=url_path_join(base_url,'/login'),
189 189 login_handler_class=ipython_app.login_handler_class,
190 190 logout_handler_class=ipython_app.logout_handler_class,
191 191 password=ipython_app.password,
192 192
193 193 # managers
194 194 kernel_manager=kernel_manager,
195 195 contents_manager=contents_manager,
196 196 cluster_manager=cluster_manager,
197 197 session_manager=session_manager,
198 198 kernel_spec_manager=kernel_spec_manager,
199 199 config_manager=config_manager,
200 200
201 201 # IPython stuff
202 202 nbextensions_path=ipython_app.nbextensions_path,
203 203 websocket_url=ipython_app.websocket_url,
204 204 mathjax_url=ipython_app.mathjax_url,
205 205 config=ipython_app.config,
206 206 jinja2_env=env,
207 207 terminals_available=False, # Set later if terminals are available
208 208 )
209 209
210 210 # allow custom overrides for the tornado web app.
211 211 settings.update(settings_overrides)
212 212 return settings
213 213
214 214 def init_handlers(self, settings):
215 215 """Load the (URL pattern, handler) tuples for each component."""
216 216
217 217 # Order matters. The first handler to match the URL will handle the request.
218 218 handlers = []
219 219 handlers.extend(load_handlers('tree.handlers'))
220 220 handlers.extend([(r"/login", settings['login_handler_class'])])
221 221 handlers.extend([(r"/logout", settings['logout_handler_class'])])
222 222 handlers.extend(load_handlers('files.handlers'))
223 223 handlers.extend(load_handlers('notebook.handlers'))
224 224 handlers.extend(load_handlers('nbconvert.handlers'))
225 225 handlers.extend(load_handlers('kernelspecs.handlers'))
226 226 handlers.extend(load_handlers('edit.handlers'))
227 227 handlers.extend(load_handlers('services.config.handlers'))
228 228 handlers.extend(load_handlers('services.kernels.handlers'))
229 229 handlers.extend(load_handlers('services.contents.handlers'))
230 230 handlers.extend(load_handlers('services.clusters.handlers'))
231 231 handlers.extend(load_handlers('services.sessions.handlers'))
232 232 handlers.extend(load_handlers('services.nbconvert.handlers'))
233 233 handlers.extend(load_handlers('services.kernelspecs.handlers'))
234 234 handlers.extend(load_handlers('services.security.handlers'))
235 235 handlers.append(
236 236 (r"/nbextensions/(.*)", FileFindHandler, {
237 237 'path': settings['nbextensions_path'],
238 238 'no_cache_paths': ['/'], # don't cache anything in nbextensions
239 239 }),
240 240 )
241 241 # register base handlers last
242 242 handlers.extend(load_handlers('base.handlers'))
243 243 # set the URL that will be redirected from `/`
244 244 handlers.append(
245 245 (r'/?', web.RedirectHandler, {
246 246 'url' : settings['default_url'],
247 247 'permanent': False, # want 302, not 301
248 248 })
249 249 )
250 250 # prepend base_url onto the patterns that we match
251 251 new_handlers = []
252 252 for handler in handlers:
253 253 pattern = url_path_join(settings['base_url'], handler[0])
254 254 new_handler = tuple([pattern] + list(handler[1:]))
255 255 new_handlers.append(new_handler)
256 256 # add 404 on the end, which will catch everything that falls through
257 257 new_handlers.append((r'(.*)', Template404))
258 258 return new_handlers
259 259
260 260
261 261 class NbserverListApp(BaseIPythonApplication):
262 262
263 263 description="List currently running notebook servers in this profile."
264 264
265 265 flags = dict(
266 266 json=({'NbserverListApp': {'json': True}},
267 267 "Produce machine-readable JSON output."),
268 268 )
269 269
270 270 json = Bool(False, config=True,
271 271 help="If True, each line of output will be a JSON object with the "
272 272 "details from the server info file.")
273 273
274 274 def start(self):
275 275 if not self.json:
276 276 print("Currently running servers:")
277 277 for serverinfo in list_running_servers(self.profile):
278 278 if self.json:
279 279 print(json.dumps(serverinfo))
280 280 else:
281 281 print(serverinfo['url'], "::", serverinfo['notebook_dir'])
282 282
283 283 #-----------------------------------------------------------------------------
284 284 # Aliases and Flags
285 285 #-----------------------------------------------------------------------------
286 286
287 287 flags = dict(base_flags)
288 288 flags['no-browser']=(
289 289 {'NotebookApp' : {'open_browser' : False}},
290 290 "Don't open the notebook in a browser after startup."
291 291 )
292 292 flags['pylab']=(
293 293 {'NotebookApp' : {'pylab' : 'warn'}},
294 294 "DISABLED: use %pylab or %matplotlib in the notebook to enable matplotlib."
295 295 )
296 296 flags['no-mathjax']=(
297 297 {'NotebookApp' : {'enable_mathjax' : False}},
298 298 """Disable MathJax
299 299
300 300 MathJax is the javascript library IPython uses to render math/LaTeX. It is
301 301 very large, so you may want to disable it if you have a slow internet
302 302 connection, or for offline use of the notebook.
303 303
304 304 When disabled, equations etc. will appear as their untransformed TeX source.
305 305 """
306 306 )
307 307
308 308 # Add notebook manager flags
309 309 flags.update(boolean_flag('script', 'FileContentsManager.save_script',
310 310 'DEPRECATED, IGNORED',
311 311 'DEPRECATED, IGNORED'))
312 312
313 313 aliases = dict(base_aliases)
314 314
315 315 aliases.update({
316 316 'ip': 'NotebookApp.ip',
317 317 'port': 'NotebookApp.port',
318 318 'port-retries': 'NotebookApp.port_retries',
319 319 'transport': 'KernelManager.transport',
320 320 'keyfile': 'NotebookApp.keyfile',
321 321 'certfile': 'NotebookApp.certfile',
322 322 'notebook-dir': 'NotebookApp.notebook_dir',
323 323 'browser': 'NotebookApp.browser',
324 324 'pylab': 'NotebookApp.pylab',
325 325 })
326 326
327 327 #-----------------------------------------------------------------------------
328 328 # NotebookApp
329 329 #-----------------------------------------------------------------------------
330 330
331 331 class NotebookApp(BaseIPythonApplication):
332 332
333 333 name = 'ipython-notebook'
334 334
335 335 description = """
336 336 The IPython HTML Notebook.
337 337
338 338 This launches a Tornado based HTML Notebook Server that serves up an
339 339 HTML5/Javascript Notebook client.
340 340 """
341 341 examples = _examples
342 342 aliases = aliases
343 343 flags = flags
344 344
345 345 classes = [
346 346 KernelManager, ProfileDir, Session, MappingKernelManager,
347 347 ContentsManager, FileContentsManager, NotebookNotary,
348 348 KernelSpecManager,
349 349 ]
350 350 flags = Dict(flags)
351 351 aliases = Dict(aliases)
352 352
353 353 subcommands = dict(
354 354 list=(NbserverListApp, NbserverListApp.description.splitlines()[0]),
355 355 )
356 356
357 357 _log_formatter_cls = LogFormatter
358 358
359 359 def _log_level_default(self):
360 360 return logging.INFO
361 361
362 362 def _log_datefmt_default(self):
363 363 """Exclude date from default date format"""
364 364 return "%H:%M:%S"
365 365
366 366 def _log_format_default(self):
367 367 """override default log format to include time"""
368 368 return u"%(color)s[%(levelname)1.1s %(asctime)s.%(msecs).03d %(name)s]%(end_color)s %(message)s"
369 369
370 370 # create requested profiles by default, if they don't exist:
371 371 auto_create = Bool(True)
372 372
373 373 # file to be opened in the notebook server
374 374 file_to_run = Unicode('', config=True)
375 375
376 376 # Network related information
377 377
378 378 allow_origin = Unicode('', config=True,
379 379 help="""Set the Access-Control-Allow-Origin header
380 380
381 381 Use '*' to allow any origin to access your server.
382 382
383 383 Takes precedence over allow_origin_pat.
384 384 """
385 385 )
386 386
387 387 allow_origin_pat = Unicode('', config=True,
388 388 help="""Use a regular expression for the Access-Control-Allow-Origin header
389 389
390 390 Requests from an origin matching the expression will get replies with:
391 391
392 392 Access-Control-Allow-Origin: origin
393 393
394 394 where `origin` is the origin of the request.
395 395
396 396 Ignored if allow_origin is set.
397 397 """
398 398 )
399 399
400 400 allow_credentials = Bool(False, config=True,
401 401 help="Set the Access-Control-Allow-Credentials: true header"
402 402 )
403 403
404 404 default_url = Unicode('/tree', config=True,
405 405 help="The default URL to redirect to from `/`"
406 406 )
407 407
408 408 ip = Unicode('localhost', config=True,
409 409 help="The IP address the notebook server will listen on."
410 410 )
411 411 def _ip_default(self):
412 412 """Return localhost if available, 127.0.0.1 otherwise.
413 413
414 414 On some (horribly broken) systems, localhost cannot be bound.
415 415 """
416 416 s = socket.socket()
417 417 try:
418 418 s.bind(('localhost', 0))
419 419 except socket.error as e:
420 420 self.log.warn("Cannot bind to localhost, using 127.0.0.1 as default ip\n%s", e)
421 421 return '127.0.0.1'
422 422 else:
423 423 s.close()
424 424 return 'localhost'
425 425
426 426 def _ip_changed(self, name, old, new):
427 427 if new == u'*': self.ip = u''
428 428
429 429 port = Integer(8888, config=True,
430 430 help="The port the notebook server will listen on."
431 431 )
432 432 port_retries = Integer(50, config=True,
433 433 help="The number of additional ports to try if the specified port is not available."
434 434 )
435 435
436 436 certfile = Unicode(u'', config=True,
437 437 help="""The full path to an SSL/TLS certificate file."""
438 438 )
439 439
440 440 keyfile = Unicode(u'', config=True,
441 441 help="""The full path to a private key file for usage with SSL/TLS."""
442 442 )
443 443
444 444 cookie_secret_file = Unicode(config=True,
445 445 help="""The file where the cookie secret is stored."""
446 446 )
447 447 def _cookie_secret_file_default(self):
448 448 if self.profile_dir is None:
449 449 return ''
450 450 return os.path.join(self.profile_dir.security_dir, 'notebook_cookie_secret')
451 451
452 452 cookie_secret = Bytes(b'', config=True,
453 453 help="""The random bytes used to secure cookies.
454 454 By default this is a new random number every time you start the Notebook.
455 455 Set it to a value in a config file to enable logins to persist across server sessions.
456 456
457 457 Note: Cookie secrets should be kept private, do not share config files with
458 458 cookie_secret stored in plaintext (you can read the value from a file).
459 459 """
460 460 )
461 461 def _cookie_secret_default(self):
462 462 if os.path.exists(self.cookie_secret_file):
463 463 with io.open(self.cookie_secret_file, 'rb') as f:
464 464 return f.read()
465 465 else:
466 466 secret = base64.encodestring(os.urandom(1024))
467 467 self._write_cookie_secret_file(secret)
468 468 return secret
469 469
470 470 def _write_cookie_secret_file(self, secret):
471 471 """write my secret to my secret_file"""
472 472 self.log.info("Writing notebook server cookie secret to %s", self.cookie_secret_file)
473 473 with io.open(self.cookie_secret_file, 'wb') as f:
474 474 f.write(secret)
475 475 try:
476 476 os.chmod(self.cookie_secret_file, 0o600)
477 477 except OSError:
478 478 self.log.warn(
479 479 "Could not set permissions on %s",
480 480 self.cookie_secret_file
481 481 )
482 482
483 483 password = Unicode(u'', config=True,
484 484 help="""Hashed password to use for web authentication.
485 485
486 486 To generate, type in a python/IPython shell:
487 487
488 488 from IPython.lib import passwd; passwd()
489 489
490 490 The string should be of the form type:salt:hashed-password.
491 491 """
492 492 )
493 493
494 494 open_browser = Bool(True, config=True,
495 495 help="""Whether to open in a browser after starting.
496 496 The specific browser used is platform dependent and
497 497 determined by the python standard library `webbrowser`
498 498 module, unless it is overridden using the --browser
499 499 (NotebookApp.browser) configuration option.
500 500 """)
501 501
502 502 browser = Unicode(u'', config=True,
503 503 help="""Specify what command to use to invoke a web
504 504 browser when opening the notebook. If not specified, the
505 505 default browser will be determined by the `webbrowser`
506 506 standard library module, which allows setting of the
507 507 BROWSER environment variable to override it.
508 508 """)
509 509
510 510 webapp_settings = Dict(config=True,
511 511 help="DEPRECATED, use tornado_settings"
512 512 )
513 513 def _webapp_settings_changed(self, name, old, new):
514 514 self.log.warn("\n webapp_settings is deprecated, use tornado_settings.\n")
515 515 self.tornado_settings = new
516 516
517 517 tornado_settings = Dict(config=True,
518 518 help="Supply overrides for the tornado.web.Application that the "
519 519 "IPython notebook uses.")
520 520
521 521 ssl_options = Dict(config=True,
522 522 help="""Supply SSL options for the tornado HTTPServer.
523 523 See the tornado docs for details.""")
524 524
525 525 jinja_environment_options = Dict(config=True,
526 526 help="Supply extra arguments that will be passed to Jinja environment.")
527 527
528 528 enable_mathjax = Bool(True, config=True,
529 529 help="""Whether to enable MathJax for typesetting math/TeX
530 530
531 531 MathJax is the javascript library IPython uses to render math/LaTeX. It is
532 532 very large, so you may want to disable it if you have a slow internet
533 533 connection, or for offline use of the notebook.
534 534
535 535 When disabled, equations etc. will appear as their untransformed TeX source.
536 536 """
537 537 )
538 538 def _enable_mathjax_changed(self, name, old, new):
539 539 """set mathjax url to empty if mathjax is disabled"""
540 540 if not new:
541 541 self.mathjax_url = u''
542 542
543 543 base_url = Unicode('/', config=True,
544 544 help='''The base URL for the notebook server.
545 545
546 546 Leading and trailing slashes can be omitted,
547 547 and will automatically be added.
548 548 ''')
549 549 def _base_url_changed(self, name, old, new):
550 550 if not new.startswith('/'):
551 551 self.base_url = '/'+new
552 552 elif not new.endswith('/'):
553 553 self.base_url = new+'/'
554 554
555 555 base_project_url = Unicode('/', config=True, help="""DEPRECATED use base_url""")
556 556 def _base_project_url_changed(self, name, old, new):
557 557 self.log.warn("base_project_url is deprecated, use base_url")
558 558 self.base_url = new
559 559
560 560 extra_static_paths = List(Unicode, config=True,
561 561 help="""Extra paths to search for serving static files.
562 562
563 563 This allows adding javascript/css to be available from the notebook server machine,
564 564 or overriding individual files in the IPython"""
565 565 )
566 566 def _extra_static_paths_default(self):
567 567 return [os.path.join(self.profile_dir.location, 'static')]
568 568
569 569 @property
570 570 def static_file_path(self):
571 571 """return extra paths + the default location"""
572 572 return self.extra_static_paths + [DEFAULT_STATIC_FILES_PATH]
573 573
574 574 extra_template_paths = List(Unicode, config=True,
575 575 help="""Extra paths to search for serving jinja templates.
576 576
577 577 Can be used to override templates from IPython.html.templates."""
578 578 )
579 579 def _extra_template_paths_default(self):
580 580 return []
581 581
582 582 @property
583 583 def template_file_path(self):
584 584 """return extra paths + the default locations"""
585 585 return self.extra_template_paths + DEFAULT_TEMPLATE_PATH_LIST
586 586
587 587 extra_nbextensions_path = List(Unicode, config=True,
588 588 help="""extra paths to look for Javascript notebook extensions"""
589 589 )
590 590
591 591 @property
592 592 def nbextensions_path(self):
593 593 """The path to look for Javascript notebook extensions"""
594 594 return self.extra_nbextensions_path + [os.path.join(get_ipython_dir(), 'nbextensions')] + SYSTEM_NBEXTENSIONS_DIRS
595 595
596 596 websocket_url = Unicode("", config=True,
597 597 help="""The base URL for websockets,
598 598 if it differs from the HTTP server (hint: it almost certainly doesn't).
599 599
600 600 Should be in the form of an HTTP origin: ws[s]://hostname[:port]
601 601 """
602 602 )
603 603 mathjax_url = Unicode("", config=True,
604 604 help="""The url for MathJax.js."""
605 605 )
606 606 def _mathjax_url_default(self):
607 607 if not self.enable_mathjax:
608 608 return u''
609 609 static_url_prefix = self.tornado_settings.get("static_url_prefix",
610 610 url_path_join(self.base_url, "static")
611 611 )
612 612
613 613 # try local mathjax, either in nbextensions/mathjax or static/mathjax
614 614 for (url_prefix, search_path) in [
615 615 (url_path_join(self.base_url, "nbextensions"), self.nbextensions_path),
616 616 (static_url_prefix, self.static_file_path),
617 617 ]:
618 618 self.log.debug("searching for local mathjax in %s", search_path)
619 619 try:
620 620 mathjax = filefind(os.path.join('mathjax', 'MathJax.js'), search_path)
621 621 except IOError:
622 622 continue
623 623 else:
624 624 url = url_path_join(url_prefix, u"mathjax/MathJax.js")
625 625 self.log.info("Serving local MathJax from %s at %s", mathjax, url)
626 626 return url
627 627
628 628 # no local mathjax, serve from CDN
629 629 url = u"https://cdn.mathjax.org/mathjax/latest/MathJax.js"
630 630 self.log.info("Using MathJax from CDN: %s", url)
631 631 return url
632 632
633 633 def _mathjax_url_changed(self, name, old, new):
634 634 if new and not self.enable_mathjax:
635 635 # enable_mathjax=False overrides mathjax_url
636 636 self.mathjax_url = u''
637 637 else:
638 638 self.log.info("Using MathJax: %s", new)
639 639
640 640 contents_manager_class = Type(
641 641 default_value=FileContentsManager,
642 642 klass=ContentsManager,
643 643 config=True,
644 644 help='The notebook manager class to use.'
645 645 )
646 646 kernel_manager_class = Type(
647 647 default_value=MappingKernelManager,
648 648 config=True,
649 649 help='The kernel manager class to use.'
650 650 )
651 651 session_manager_class = Type(
652 652 default_value=SessionManager,
653 653 config=True,
654 654 help='The session manager class to use.'
655 655 )
656 656 cluster_manager_class = Type(
657 657 default_value=ClusterManager,
658 658 config=True,
659 659 help='The cluster manager class to use.'
660 660 )
661 661
662 662 config_manager_class = Type(
663 663 default_value=ConfigManager,
664 664 config = True,
665 665 help='The config manager class to use'
666 666 )
667 667
668 kernel_spec_manager = Instance(KernelSpecManager)
668 kernel_spec_manager = Instance(KernelSpecManager, allow_none=True)
669 669
670 670 kernel_spec_manager_class = Type(
671 671 default_value=KernelSpecManager,
672 672 config=True,
673 673 help="""
674 674 The kernel spec manager class to use. Should be a subclass
675 675 of `IPython.kernel.kernelspec.KernelSpecManager`.
676 676
677 677 The Api of KernelSpecManager is provisional and might change
678 678 without warning between this version of IPython and the next stable one.
679 679 """
680 680 )
681 681
682 682 login_handler_class = Type(
683 683 default_value=LoginHandler,
684 684 klass=web.RequestHandler,
685 685 config=True,
686 686 help='The login handler class to use.',
687 687 )
688 688
689 689 logout_handler_class = Type(
690 690 default_value=LogoutHandler,
691 691 klass=web.RequestHandler,
692 692 config=True,
693 693 help='The logout handler class to use.',
694 694 )
695 695
696 696 trust_xheaders = Bool(False, config=True,
697 697 help=("Whether to trust or not X-Scheme/X-Forwarded-Proto and X-Real-Ip/X-Forwarded-For headers"
698 698 "sent by the upstream reverse proxy. Necessary if the proxy handles SSL")
699 699 )
700 700
701 701 info_file = Unicode()
702 702
703 703 def _info_file_default(self):
704 704 info_file = "nbserver-%s.json"%os.getpid()
705 705 return os.path.join(self.profile_dir.security_dir, info_file)
706 706
707 707 pylab = Unicode('disabled', config=True,
708 708 help="""
709 709 DISABLED: use %pylab or %matplotlib in the notebook to enable matplotlib.
710 710 """
711 711 )
712 712 def _pylab_changed(self, name, old, new):
713 713 """when --pylab is specified, display a warning and exit"""
714 714 if new != 'warn':
715 715 backend = ' %s' % new
716 716 else:
717 717 backend = ''
718 718 self.log.error("Support for specifying --pylab on the command line has been removed.")
719 719 self.log.error(
720 720 "Please use `%pylab{0}` or `%matplotlib{0}` in the notebook itself.".format(backend)
721 721 )
722 722 self.exit(1)
723 723
724 724 notebook_dir = Unicode(config=True,
725 725 help="The directory to use for notebooks and kernels."
726 726 )
727 727
728 728 def _notebook_dir_default(self):
729 729 if self.file_to_run:
730 730 return os.path.dirname(os.path.abspath(self.file_to_run))
731 731 else:
732 732 return py3compat.getcwd()
733 733
734 734 def _notebook_dir_changed(self, name, old, new):
735 735 """Do a bit of validation of the notebook dir."""
736 736 if not os.path.isabs(new):
737 737 # If we receive a non-absolute path, make it absolute.
738 738 self.notebook_dir = os.path.abspath(new)
739 739 return
740 740 if not os.path.isdir(new):
741 741 raise TraitError("No such notebook dir: %r" % new)
742 742
743 743 # setting App.notebook_dir implies setting notebook and kernel dirs as well
744 744 self.config.FileContentsManager.root_dir = new
745 745 self.config.MappingKernelManager.root_dir = new
746 746
747 747 server_extensions = List(Unicode(), config=True,
748 748 help=("Python modules to load as notebook server extensions. "
749 749 "This is an experimental API, and may change in future releases.")
750 750 )
751 751
752 752 reraise_server_extension_failures = Bool(
753 753 False,
754 754 config=True,
755 755 help="Reraise exceptions encountered loading server extensions?",
756 756 )
757 757
758 758 def parse_command_line(self, argv=None):
759 759 super(NotebookApp, self).parse_command_line(argv)
760 760
761 761 if self.extra_args:
762 762 arg0 = self.extra_args[0]
763 763 f = os.path.abspath(arg0)
764 764 self.argv.remove(arg0)
765 765 if not os.path.exists(f):
766 766 self.log.critical("No such file or directory: %s", f)
767 767 self.exit(1)
768 768
769 769 # Use config here, to ensure that it takes higher priority than
770 770 # anything that comes from the profile.
771 771 c = Config()
772 772 if os.path.isdir(f):
773 773 c.NotebookApp.notebook_dir = f
774 774 elif os.path.isfile(f):
775 775 c.NotebookApp.file_to_run = f
776 776 self.update_config(c)
777 777
778 778 def init_configurables(self):
779 779 self.kernel_spec_manager = self.kernel_spec_manager_class(
780 780 parent=self,
781 781 ipython_dir=self.ipython_dir,
782 782 )
783 783 self.kernel_manager = self.kernel_manager_class(
784 784 parent=self,
785 785 log=self.log,
786 786 connection_dir=self.profile_dir.security_dir,
787 787 )
788 788 self.contents_manager = self.contents_manager_class(
789 789 parent=self,
790 790 log=self.log,
791 791 )
792 792 self.session_manager = self.session_manager_class(
793 793 parent=self,
794 794 log=self.log,
795 795 kernel_manager=self.kernel_manager,
796 796 contents_manager=self.contents_manager,
797 797 )
798 798 self.cluster_manager = self.cluster_manager_class(
799 799 parent=self,
800 800 log=self.log,
801 801 )
802 802
803 803 self.config_manager = self.config_manager_class(
804 804 parent=self,
805 805 log=self.log,
806 806 profile_dir=self.profile_dir.location,
807 807 )
808 808
809 809 def init_logging(self):
810 810 # This prevents double log messages because tornado use a root logger that
811 811 # self.log is a child of. The logging module dipatches log messages to a log
812 812 # and all of its ancenstors until propagate is set to False.
813 813 self.log.propagate = False
814 814
815 815 for log in app_log, access_log, gen_log:
816 816 # consistent log output name (NotebookApp instead of tornado.access, etc.)
817 817 log.name = self.log.name
818 818 # hook up tornado 3's loggers to our app handlers
819 819 logger = logging.getLogger('tornado')
820 820 logger.propagate = True
821 821 logger.parent = self.log
822 822 logger.setLevel(self.log.level)
823 823
824 824 def init_webapp(self):
825 825 """initialize tornado webapp and httpserver"""
826 826 self.tornado_settings['allow_origin'] = self.allow_origin
827 827 if self.allow_origin_pat:
828 828 self.tornado_settings['allow_origin_pat'] = re.compile(self.allow_origin_pat)
829 829 self.tornado_settings['allow_credentials'] = self.allow_credentials
830 830 # ensure default_url starts with base_url
831 831 if not self.default_url.startswith(self.base_url):
832 832 self.default_url = url_path_join(self.base_url, self.default_url)
833 833
834 834 self.web_app = NotebookWebApplication(
835 835 self, self.kernel_manager, self.contents_manager,
836 836 self.cluster_manager, self.session_manager, self.kernel_spec_manager,
837 837 self.config_manager,
838 838 self.log, self.base_url, self.default_url, self.tornado_settings,
839 839 self.jinja_environment_options
840 840 )
841 841 ssl_options = self.ssl_options
842 842 if self.certfile:
843 843 ssl_options['certfile'] = self.certfile
844 844 if self.keyfile:
845 845 ssl_options['keyfile'] = self.keyfile
846 846 if not ssl_options:
847 847 # None indicates no SSL config
848 848 ssl_options = None
849 849 self.login_handler_class.validate_security(self, ssl_options=ssl_options)
850 850 self.http_server = httpserver.HTTPServer(self.web_app, ssl_options=ssl_options,
851 851 xheaders=self.trust_xheaders)
852 852
853 853 success = None
854 854 for port in random_ports(self.port, self.port_retries+1):
855 855 try:
856 856 self.http_server.listen(port, self.ip)
857 857 except socket.error as e:
858 858 if e.errno == errno.EADDRINUSE:
859 859 self.log.info('The port %i is already in use, trying another random port.' % port)
860 860 continue
861 861 elif e.errno in (errno.EACCES, getattr(errno, 'WSAEACCES', errno.EACCES)):
862 862 self.log.warn("Permission to listen on port %i denied" % port)
863 863 continue
864 864 else:
865 865 raise
866 866 else:
867 867 self.port = port
868 868 success = True
869 869 break
870 870 if not success:
871 871 self.log.critical('ERROR: the notebook server could not be started because '
872 872 'no available port could be found.')
873 873 self.exit(1)
874 874
875 875 @property
876 876 def display_url(self):
877 877 ip = self.ip if self.ip else '[all ip addresses on your system]'
878 878 return self._url(ip)
879 879
880 880 @property
881 881 def connection_url(self):
882 882 ip = self.ip if self.ip else 'localhost'
883 883 return self._url(ip)
884 884
885 885 def _url(self, ip):
886 886 proto = 'https' if self.certfile else 'http'
887 887 return "%s://%s:%i%s" % (proto, ip, self.port, self.base_url)
888 888
889 889 def init_terminals(self):
890 890 try:
891 891 from .terminal import initialize
892 892 initialize(self.web_app)
893 893 self.web_app.settings['terminals_available'] = True
894 894 except ImportError as e:
895 895 log = self.log.debug if sys.platform == 'win32' else self.log.warn
896 896 log("Terminals not available (error was %s)", e)
897 897
898 898 def init_signal(self):
899 899 if not sys.platform.startswith('win'):
900 900 signal.signal(signal.SIGINT, self._handle_sigint)
901 901 signal.signal(signal.SIGTERM, self._signal_stop)
902 902 if hasattr(signal, 'SIGUSR1'):
903 903 # Windows doesn't support SIGUSR1
904 904 signal.signal(signal.SIGUSR1, self._signal_info)
905 905 if hasattr(signal, 'SIGINFO'):
906 906 # only on BSD-based systems
907 907 signal.signal(signal.SIGINFO, self._signal_info)
908 908
909 909 def _handle_sigint(self, sig, frame):
910 910 """SIGINT handler spawns confirmation dialog"""
911 911 # register more forceful signal handler for ^C^C case
912 912 signal.signal(signal.SIGINT, self._signal_stop)
913 913 # request confirmation dialog in bg thread, to avoid
914 914 # blocking the App
915 915 thread = threading.Thread(target=self._confirm_exit)
916 916 thread.daemon = True
917 917 thread.start()
918 918
919 919 def _restore_sigint_handler(self):
920 920 """callback for restoring original SIGINT handler"""
921 921 signal.signal(signal.SIGINT, self._handle_sigint)
922 922
923 923 def _confirm_exit(self):
924 924 """confirm shutdown on ^C
925 925
926 926 A second ^C, or answering 'y' within 5s will cause shutdown,
927 927 otherwise original SIGINT handler will be restored.
928 928
929 929 This doesn't work on Windows.
930 930 """
931 931 info = self.log.info
932 932 info('interrupted')
933 933 print(self.notebook_info())
934 934 sys.stdout.write("Shutdown this notebook server (y/[n])? ")
935 935 sys.stdout.flush()
936 936 r,w,x = select.select([sys.stdin], [], [], 5)
937 937 if r:
938 938 line = sys.stdin.readline()
939 939 if line.lower().startswith('y') and 'n' not in line.lower():
940 940 self.log.critical("Shutdown confirmed")
941 941 ioloop.IOLoop.current().stop()
942 942 return
943 943 else:
944 944 print("No answer for 5s:", end=' ')
945 945 print("resuming operation...")
946 946 # no answer, or answer is no:
947 947 # set it back to original SIGINT handler
948 948 # use IOLoop.add_callback because signal.signal must be called
949 949 # from main thread
950 950 ioloop.IOLoop.current().add_callback(self._restore_sigint_handler)
951 951
952 952 def _signal_stop(self, sig, frame):
953 953 self.log.critical("received signal %s, stopping", sig)
954 954 ioloop.IOLoop.current().stop()
955 955
956 956 def _signal_info(self, sig, frame):
957 957 print(self.notebook_info())
958 958
959 959 def init_components(self):
960 960 """Check the components submodule, and warn if it's unclean"""
961 961 status = submodule.check_submodule_status()
962 962 if status == 'missing':
963 963 self.log.warn("components submodule missing, running `git submodule update`")
964 964 submodule.update_submodules(submodule.ipython_parent())
965 965 elif status == 'unclean':
966 966 self.log.warn("components submodule unclean, you may see 404s on static/components")
967 967 self.log.warn("run `setup.py submodule` or `git submodule update` to update")
968 968
969 969 def init_server_extensions(self):
970 970 """Load any extensions specified by config.
971 971
972 972 Import the module, then call the load_jupyter_server_extension function,
973 973 if one exists.
974 974
975 975 The extension API is experimental, and may change in future releases.
976 976 """
977 977 for modulename in self.server_extensions:
978 978 try:
979 979 mod = importlib.import_module(modulename)
980 980 func = getattr(mod, 'load_jupyter_server_extension', None)
981 981 if func is not None:
982 982 func(self)
983 983 except Exception:
984 984 if self.reraise_server_extension_failures:
985 985 raise
986 986 self.log.warn("Error loading server extension %s", modulename,
987 987 exc_info=True)
988 988
989 989 @catch_config_error
990 990 def initialize(self, argv=None):
991 991 super(NotebookApp, self).initialize(argv)
992 992 self.init_logging()
993 993 self.init_configurables()
994 994 self.init_components()
995 995 self.init_webapp()
996 996 self.init_terminals()
997 997 self.init_signal()
998 998 self.init_server_extensions()
999 999
1000 1000 def cleanup_kernels(self):
1001 1001 """Shutdown all kernels.
1002 1002
1003 1003 The kernels will shutdown themselves when this process no longer exists,
1004 1004 but explicit shutdown allows the KernelManagers to cleanup the connection files.
1005 1005 """
1006 1006 self.log.info('Shutting down kernels')
1007 1007 self.kernel_manager.shutdown_all()
1008 1008
1009 1009 def notebook_info(self):
1010 1010 "Return the current working directory and the server url information"
1011 1011 info = self.contents_manager.info_string() + "\n"
1012 1012 info += "%d active kernels \n" % len(self.kernel_manager._kernels)
1013 1013 return info + "The IPython Notebook is running at: %s" % self.display_url
1014 1014
1015 1015 def server_info(self):
1016 1016 """Return a JSONable dict of information about this server."""
1017 1017 return {'url': self.connection_url,
1018 1018 'hostname': self.ip if self.ip else 'localhost',
1019 1019 'port': self.port,
1020 1020 'secure': bool(self.certfile),
1021 1021 'base_url': self.base_url,
1022 1022 'notebook_dir': os.path.abspath(self.notebook_dir),
1023 1023 'pid': os.getpid()
1024 1024 }
1025 1025
1026 1026 def write_server_info_file(self):
1027 1027 """Write the result of server_info() to the JSON file info_file."""
1028 1028 with open(self.info_file, 'w') as f:
1029 1029 json.dump(self.server_info(), f, indent=2)
1030 1030
1031 1031 def remove_server_info_file(self):
1032 1032 """Remove the nbserver-<pid>.json file created for this server.
1033 1033
1034 1034 Ignores the error raised when the file has already been removed.
1035 1035 """
1036 1036 try:
1037 1037 os.unlink(self.info_file)
1038 1038 except OSError as e:
1039 1039 if e.errno != errno.ENOENT:
1040 1040 raise
1041 1041
1042 1042 def start(self):
1043 1043 """ Start the IPython Notebook server app, after initialization
1044 1044
1045 1045 This method takes no arguments so all configuration and initialization
1046 1046 must be done prior to calling this method."""
1047 1047 if self.subapp is not None:
1048 1048 return self.subapp.start()
1049 1049
1050 1050 info = self.log.info
1051 1051 for line in self.notebook_info().split("\n"):
1052 1052 info(line)
1053 1053 info("Use Control-C to stop this server and shut down all kernels (twice to skip confirmation).")
1054 1054
1055 1055 self.write_server_info_file()
1056 1056
1057 1057 if self.open_browser or self.file_to_run:
1058 1058 try:
1059 1059 browser = webbrowser.get(self.browser or None)
1060 1060 except webbrowser.Error as e:
1061 1061 self.log.warn('No web browser found: %s.' % e)
1062 1062 browser = None
1063 1063
1064 1064 if self.file_to_run:
1065 1065 if not os.path.exists(self.file_to_run):
1066 1066 self.log.critical("%s does not exist" % self.file_to_run)
1067 1067 self.exit(1)
1068 1068
1069 1069 relpath = os.path.relpath(self.file_to_run, self.notebook_dir)
1070 1070 uri = url_path_join('notebooks', *relpath.split(os.sep))
1071 1071 else:
1072 1072 uri = 'tree'
1073 1073 if browser:
1074 1074 b = lambda : browser.open(url_path_join(self.connection_url, uri),
1075 1075 new=2)
1076 1076 threading.Thread(target=b).start()
1077 1077
1078 1078 self.io_loop = ioloop.IOLoop.current()
1079 1079 if sys.platform.startswith('win'):
1080 1080 # add no-op to wake every 5s
1081 1081 # to handle signals that may be ignored by the inner loop
1082 1082 pc = ioloop.PeriodicCallback(lambda : None, 5000)
1083 1083 pc.start()
1084 1084 try:
1085 1085 self.io_loop.start()
1086 1086 except KeyboardInterrupt:
1087 1087 info("Interrupted...")
1088 1088 finally:
1089 1089 self.cleanup_kernels()
1090 1090 self.remove_server_info_file()
1091 1091
1092 1092 def stop(self):
1093 1093 def _stop():
1094 1094 self.http_server.stop()
1095 1095 self.io_loop.stop()
1096 1096 self.io_loop.add_callback(_stop)
1097 1097
1098 1098
1099 1099 def list_running_servers(profile='default'):
1100 1100 """Iterate over the server info files of running notebook servers.
1101 1101
1102 1102 Given a profile name, find nbserver-* files in the security directory of
1103 1103 that profile, and yield dicts of their information, each one pertaining to
1104 1104 a currently running notebook server instance.
1105 1105 """
1106 1106 pd = ProfileDir.find_profile_dir_by_name(get_ipython_dir(), name=profile)
1107 1107 for file in os.listdir(pd.security_dir):
1108 1108 if file.startswith('nbserver-'):
1109 1109 with io.open(os.path.join(pd.security_dir, file), encoding='utf-8') as f:
1110 1110 info = json.load(f)
1111 1111
1112 1112 # Simple check whether that process is really still running
1113 1113 # Also remove leftover files from IPython 2.x without a pid field
1114 1114 if ('pid' in info) and check_pid(info['pid']):
1115 1115 yield info
1116 1116 else:
1117 1117 # If the process has died, try to delete its info file
1118 1118 try:
1119 1119 os.unlink(file)
1120 1120 except OSError:
1121 1121 pass # TODO: This should warn or log or something
1122 1122 #-----------------------------------------------------------------------------
1123 1123 # Main entry point
1124 1124 #-----------------------------------------------------------------------------
1125 1125
1126 1126 launch_new_instance = NotebookApp.launch_instance
1127 1127
@@ -1,162 +1,162 b''
1 1 """Manage IPython.parallel clusters in the notebook."""
2 2
3 3 # Copyright (c) IPython Development Team.
4 4 # Distributed under the terms of the Modified BSD License.
5 5
6 6 from tornado import web
7 7
8 8 from IPython.config.configurable import LoggingConfigurable
9 9 from IPython.utils.traitlets import Dict, Instance, Float
10 10 from IPython.core.profileapp import list_profiles_in
11 11 from IPython.core.profiledir import ProfileDir
12 12 from IPython.utils import py3compat
13 13 from IPython.utils.path import get_ipython_dir
14 14
15 15
16 16 class ClusterManager(LoggingConfigurable):
17 17
18 18 profiles = Dict()
19 19
20 20 delay = Float(1., config=True,
21 21 help="delay (in s) between starting the controller and the engines")
22 22
23 loop = Instance('zmq.eventloop.ioloop.IOLoop')
23 loop = Instance('zmq.eventloop.ioloop.IOLoop', allow_none=True)
24 24 def _loop_default(self):
25 25 from zmq.eventloop.ioloop import IOLoop
26 26 return IOLoop.instance()
27 27
28 28 def build_launchers(self, profile_dir):
29 29 from IPython.parallel.apps.ipclusterapp import IPClusterStart
30 30
31 31 class DummyIPClusterStart(IPClusterStart):
32 32 """Dummy subclass to skip init steps that conflict with global app.
33 33
34 34 Instantiating and initializing this class should result in fully configured
35 35 launchers, but no other side effects or state.
36 36 """
37 37
38 38 def init_signal(self):
39 39 pass
40 40 def reinit_logging(self):
41 41 pass
42 42
43 43 starter = DummyIPClusterStart(log=self.log)
44 44 starter.initialize(['--profile-dir', profile_dir])
45 45 cl = starter.controller_launcher
46 46 esl = starter.engine_launcher
47 47 n = starter.n
48 48 return cl, esl, n
49 49
50 50 def get_profile_dir(self, name, path):
51 51 p = ProfileDir.find_profile_dir_by_name(path,name=name)
52 52 return p.location
53 53
54 54 def update_profiles(self):
55 55 """List all profiles in the ipython_dir and cwd.
56 56 """
57 57
58 58 stale = set(self.profiles)
59 59 for path in [get_ipython_dir(), py3compat.getcwd()]:
60 60 for profile in list_profiles_in(path):
61 61 if profile in stale:
62 62 stale.remove(profile)
63 63 pd = self.get_profile_dir(profile, path)
64 64 if profile not in self.profiles:
65 65 self.log.debug("Adding cluster profile '%s'", profile)
66 66 self.profiles[profile] = {
67 67 'profile': profile,
68 68 'profile_dir': pd,
69 69 'status': 'stopped'
70 70 }
71 71 for profile in stale:
72 72 # remove profiles that no longer exist
73 73 self.log.debug("Profile '%s' no longer exists", profile)
74 74 self.profiles.pop(stale)
75 75
76 76 def list_profiles(self):
77 77 self.update_profiles()
78 78 # sorted list, but ensure that 'default' always comes first
79 79 default_first = lambda name: name if name != 'default' else ''
80 80 result = [self.profile_info(p) for p in sorted(self.profiles, key=default_first)]
81 81 return result
82 82
83 83 def check_profile(self, profile):
84 84 if profile not in self.profiles:
85 85 raise web.HTTPError(404, u'profile not found')
86 86
87 87 def profile_info(self, profile):
88 88 self.check_profile(profile)
89 89 result = {}
90 90 data = self.profiles.get(profile)
91 91 result['profile'] = profile
92 92 result['profile_dir'] = data['profile_dir']
93 93 result['status'] = data['status']
94 94 if 'n' in data:
95 95 result['n'] = data['n']
96 96 return result
97 97
98 98 def start_cluster(self, profile, n=None):
99 99 """Start a cluster for a given profile."""
100 100 self.check_profile(profile)
101 101 data = self.profiles[profile]
102 102 if data['status'] == 'running':
103 103 raise web.HTTPError(409, u'cluster already running')
104 104 cl, esl, default_n = self.build_launchers(data['profile_dir'])
105 105 n = n if n is not None else default_n
106 106 def clean_data():
107 107 data.pop('controller_launcher',None)
108 108 data.pop('engine_set_launcher',None)
109 109 data.pop('n',None)
110 110 data['status'] = 'stopped'
111 111 def engines_stopped(r):
112 112 self.log.debug('Engines stopped')
113 113 if cl.running:
114 114 cl.stop()
115 115 clean_data()
116 116 esl.on_stop(engines_stopped)
117 117 def controller_stopped(r):
118 118 self.log.debug('Controller stopped')
119 119 if esl.running:
120 120 esl.stop()
121 121 clean_data()
122 122 cl.on_stop(controller_stopped)
123 123 loop = self.loop
124 124
125 125 def start():
126 126 """start the controller, then the engines after a delay"""
127 127 cl.start()
128 128 loop.add_timeout(self.loop.time() + self.delay, lambda : esl.start(n))
129 129 self.loop.add_callback(start)
130 130
131 131 self.log.debug('Cluster started')
132 132 data['controller_launcher'] = cl
133 133 data['engine_set_launcher'] = esl
134 134 data['n'] = n
135 135 data['status'] = 'running'
136 136 return self.profile_info(profile)
137 137
138 138 def stop_cluster(self, profile):
139 139 """Stop a cluster for a given profile."""
140 140 self.check_profile(profile)
141 141 data = self.profiles[profile]
142 142 if data['status'] == 'stopped':
143 143 raise web.HTTPError(409, u'cluster not running')
144 144 data = self.profiles[profile]
145 145 cl = data['controller_launcher']
146 146 esl = data['engine_set_launcher']
147 147 if cl.running:
148 148 cl.stop()
149 149 if esl.running:
150 150 esl.stop()
151 151 # Return a temp info dict, the real one is updated in the on_stop
152 152 # logic above.
153 153 result = {
154 154 'profile': data['profile'],
155 155 'profile_dir': data['profile_dir'],
156 156 'status': 'stopped'
157 157 }
158 158 return result
159 159
160 160 def stop_all_clusters(self):
161 161 for p in self.profiles.keys():
162 162 self.stop_cluster(p)
@@ -1,497 +1,497 b''
1 1 """Base Widget class. Allows user to create widgets in the back-end that render
2 2 in the IPython notebook front-end.
3 3 """
4 4 #-----------------------------------------------------------------------------
5 5 # Copyright (c) 2013, the IPython Development Team.
6 6 #
7 7 # Distributed under the terms of the Modified BSD License.
8 8 #
9 9 # The full license is in the file COPYING.txt, distributed with this software.
10 10 #-----------------------------------------------------------------------------
11 11
12 12 #-----------------------------------------------------------------------------
13 13 # Imports
14 14 #-----------------------------------------------------------------------------
15 15 from contextlib import contextmanager
16 16 import collections
17 17
18 18 from IPython.core.getipython import get_ipython
19 19 from IPython.kernel.comm import Comm
20 20 from IPython.config import LoggingConfigurable
21 21 from IPython.utils.importstring import import_item
22 22 from IPython.utils.traitlets import Unicode, Dict, Instance, Bool, List, \
23 23 CaselessStrEnum, Tuple, CUnicode, Int, Set
24 24 from IPython.utils.py3compat import string_types
25 25 from .trait_types import Color
26 26
27 27 #-----------------------------------------------------------------------------
28 28 # Classes
29 29 #-----------------------------------------------------------------------------
30 30 class CallbackDispatcher(LoggingConfigurable):
31 31 """A structure for registering and running callbacks"""
32 32 callbacks = List()
33 33
34 34 def __call__(self, *args, **kwargs):
35 35 """Call all of the registered callbacks."""
36 36 value = None
37 37 for callback in self.callbacks:
38 38 try:
39 39 local_value = callback(*args, **kwargs)
40 40 except Exception as e:
41 41 ip = get_ipython()
42 42 if ip is None:
43 43 self.log.warn("Exception in callback %s: %s", callback, e, exc_info=True)
44 44 else:
45 45 ip.showtraceback()
46 46 else:
47 47 value = local_value if local_value is not None else value
48 48 return value
49 49
50 50 def register_callback(self, callback, remove=False):
51 51 """(Un)Register a callback
52 52
53 53 Parameters
54 54 ----------
55 55 callback: method handle
56 56 Method to be registered or unregistered.
57 57 remove=False: bool
58 58 Whether to unregister the callback."""
59 59
60 60 # (Un)Register the callback.
61 61 if remove and callback in self.callbacks:
62 62 self.callbacks.remove(callback)
63 63 elif not remove and callback not in self.callbacks:
64 64 self.callbacks.append(callback)
65 65
66 66 def _show_traceback(method):
67 67 """decorator for showing tracebacks in IPython"""
68 68 def m(self, *args, **kwargs):
69 69 try:
70 70 return(method(self, *args, **kwargs))
71 71 except Exception as e:
72 72 ip = get_ipython()
73 73 if ip is None:
74 74 self.log.warn("Exception in widget method %s: %s", method, e, exc_info=True)
75 75 else:
76 76 ip.showtraceback()
77 77 return m
78 78
79 79
80 80 def register(key=None):
81 81 """Returns a decorator registering a widget class in the widget registry.
82 82 If no key is provided, the class name is used as a key. A key is
83 83 provided for each core IPython widget so that the frontend can use
84 84 this key regardless of the language of the kernel"""
85 85 def wrap(widget):
86 86 l = key if key is not None else widget.__module__ + widget.__name__
87 87 Widget.widget_types[l] = widget
88 88 return widget
89 89 return wrap
90 90
91 91
92 92 class Widget(LoggingConfigurable):
93 93 #-------------------------------------------------------------------------
94 94 # Class attributes
95 95 #-------------------------------------------------------------------------
96 96 _widget_construction_callback = None
97 97 widgets = {}
98 98 widget_types = {}
99 99
100 100 @staticmethod
101 101 def on_widget_constructed(callback):
102 102 """Registers a callback to be called when a widget is constructed.
103 103
104 104 The callback must have the following signature:
105 105 callback(widget)"""
106 106 Widget._widget_construction_callback = callback
107 107
108 108 @staticmethod
109 109 def _call_widget_constructed(widget):
110 110 """Static method, called when a widget is constructed."""
111 111 if Widget._widget_construction_callback is not None and callable(Widget._widget_construction_callback):
112 112 Widget._widget_construction_callback(widget)
113 113
114 114 @staticmethod
115 115 def handle_comm_opened(comm, msg):
116 116 """Static method, called when a widget is constructed."""
117 117 widget_class = import_item(msg['content']['data']['widget_class'])
118 118 widget = widget_class(comm=comm)
119 119
120 120
121 121 #-------------------------------------------------------------------------
122 122 # Traits
123 123 #-------------------------------------------------------------------------
124 124 _model_module = Unicode(None, allow_none=True, help="""A requirejs module name
125 125 in which to find _model_name. If empty, look in the global registry.""")
126 126 _model_name = Unicode('WidgetModel', help="""Name of the backbone model
127 127 registered in the front-end to create and sync this widget with.""")
128 128 _view_module = Unicode(help="""A requirejs module in which to find _view_name.
129 129 If empty, look in the global registry.""", sync=True)
130 130 _view_name = Unicode(None, allow_none=True, help="""Default view registered in the front-end
131 131 to use to represent the widget.""", sync=True)
132 comm = Instance('IPython.kernel.comm.Comm')
132 comm = Instance('IPython.kernel.comm.Comm', allow_none=True)
133 133
134 134 msg_throttle = Int(3, sync=True, help="""Maximum number of msgs the
135 135 front-end can send before receiving an idle msg from the back-end.""")
136 136
137 137 version = Int(0, sync=True, help="""Widget's version""")
138 138 keys = List()
139 139 def _keys_default(self):
140 140 return [name for name in self.traits(sync=True)]
141 141
142 142 _property_lock = Tuple((None, None))
143 143 _send_state_lock = Int(0)
144 144 _states_to_send = Set()
145 145 _display_callbacks = Instance(CallbackDispatcher, ())
146 146 _msg_callbacks = Instance(CallbackDispatcher, ())
147 147
148 148 #-------------------------------------------------------------------------
149 149 # (Con/de)structor
150 150 #-------------------------------------------------------------------------
151 151 def __init__(self, **kwargs):
152 152 """Public constructor"""
153 153 self._model_id = kwargs.pop('model_id', None)
154 154 super(Widget, self).__init__(**kwargs)
155 155
156 156 Widget._call_widget_constructed(self)
157 157 self.open()
158 158
159 159 def __del__(self):
160 160 """Object disposal"""
161 161 self.close()
162 162
163 163 #-------------------------------------------------------------------------
164 164 # Properties
165 165 #-------------------------------------------------------------------------
166 166
167 167 def open(self):
168 168 """Open a comm to the frontend if one isn't already open."""
169 169 if self.comm is None:
170 170 args = dict(target_name='ipython.widget',
171 171 data={'model_name': self._model_name,
172 172 'model_module': self._model_module})
173 173 if self._model_id is not None:
174 174 args['comm_id'] = self._model_id
175 175 self.comm = Comm(**args)
176 176
177 177 def _comm_changed(self, name, new):
178 178 """Called when the comm is changed."""
179 179 if new is None:
180 180 return
181 181 self._model_id = self.model_id
182 182
183 183 self.comm.on_msg(self._handle_msg)
184 184 Widget.widgets[self.model_id] = self
185 185
186 186 # first update
187 187 self.send_state()
188 188
189 189 @property
190 190 def model_id(self):
191 191 """Gets the model id of this widget.
192 192
193 193 If a Comm doesn't exist yet, a Comm will be created automagically."""
194 194 return self.comm.comm_id
195 195
196 196 #-------------------------------------------------------------------------
197 197 # Methods
198 198 #-------------------------------------------------------------------------
199 199
200 200 def close(self):
201 201 """Close method.
202 202
203 203 Closes the underlying comm.
204 204 When the comm is closed, all of the widget views are automatically
205 205 removed from the front-end."""
206 206 if self.comm is not None:
207 207 Widget.widgets.pop(self.model_id, None)
208 208 self.comm.close()
209 209 self.comm = None
210 210
211 211 def send_state(self, key=None):
212 212 """Sends the widget state, or a piece of it, to the front-end.
213 213
214 214 Parameters
215 215 ----------
216 216 key : unicode, or iterable (optional)
217 217 A single property's name or iterable of property names to sync with the front-end.
218 218 """
219 219 self._send({
220 220 "method" : "update",
221 221 "state" : self.get_state(key=key)
222 222 })
223 223
224 224 def get_state(self, key=None):
225 225 """Gets the widget state, or a piece of it.
226 226
227 227 Parameters
228 228 ----------
229 229 key : unicode or iterable (optional)
230 230 A single property's name or iterable of property names to get.
231 231 """
232 232 if key is None:
233 233 keys = self.keys
234 234 elif isinstance(key, string_types):
235 235 keys = [key]
236 236 elif isinstance(key, collections.Iterable):
237 237 keys = key
238 238 else:
239 239 raise ValueError("key must be a string, an iterable of keys, or None")
240 240 state = {}
241 241 for k in keys:
242 242 f = self.trait_metadata(k, 'to_json', self._trait_to_json)
243 243 value = getattr(self, k)
244 244 state[k] = f(value)
245 245 return state
246 246
247 247 def set_state(self, sync_data):
248 248 """Called when a state is received from the front-end."""
249 249 for name in self.keys:
250 250 if name in sync_data:
251 251 json_value = sync_data[name]
252 252 from_json = self.trait_metadata(name, 'from_json', self._trait_from_json)
253 253 with self._lock_property(name, json_value):
254 254 setattr(self, name, from_json(json_value))
255 255
256 256 def send(self, content):
257 257 """Sends a custom msg to the widget model in the front-end.
258 258
259 259 Parameters
260 260 ----------
261 261 content : dict
262 262 Content of the message to send.
263 263 """
264 264 self._send({"method": "custom", "content": content})
265 265
266 266 def on_msg(self, callback, remove=False):
267 267 """(Un)Register a custom msg receive callback.
268 268
269 269 Parameters
270 270 ----------
271 271 callback: callable
272 272 callback will be passed two arguments when a message arrives::
273 273
274 274 callback(widget, content)
275 275
276 276 remove: bool
277 277 True if the callback should be unregistered."""
278 278 self._msg_callbacks.register_callback(callback, remove=remove)
279 279
280 280 def on_displayed(self, callback, remove=False):
281 281 """(Un)Register a widget displayed callback.
282 282
283 283 Parameters
284 284 ----------
285 285 callback: method handler
286 286 Must have a signature of::
287 287
288 288 callback(widget, **kwargs)
289 289
290 290 kwargs from display are passed through without modification.
291 291 remove: bool
292 292 True if the callback should be unregistered."""
293 293 self._display_callbacks.register_callback(callback, remove=remove)
294 294
295 295 def add_trait(self, traitname, trait):
296 296 """Dynamically add a trait attribute to the Widget."""
297 297 super(Widget, self).add_trait(traitname, trait)
298 298 if trait.get_metadata('sync'):
299 299 self.keys.append(traitname)
300 300 self.send_state(traitname)
301 301
302 302 #-------------------------------------------------------------------------
303 303 # Support methods
304 304 #-------------------------------------------------------------------------
305 305 @contextmanager
306 306 def _lock_property(self, key, value):
307 307 """Lock a property-value pair.
308 308
309 309 The value should be the JSON state of the property.
310 310
311 311 NOTE: This, in addition to the single lock for all state changes, is
312 312 flawed. In the future we may want to look into buffering state changes
313 313 back to the front-end."""
314 314 self._property_lock = (key, value)
315 315 try:
316 316 yield
317 317 finally:
318 318 self._property_lock = (None, None)
319 319
320 320 @contextmanager
321 321 def hold_sync(self):
322 322 """Hold syncing any state until the context manager is released"""
323 323 # We increment a value so that this can be nested. Syncing will happen when
324 324 # all levels have been released.
325 325 self._send_state_lock += 1
326 326 try:
327 327 yield
328 328 finally:
329 329 self._send_state_lock -=1
330 330 if self._send_state_lock == 0:
331 331 self.send_state(self._states_to_send)
332 332 self._states_to_send.clear()
333 333
334 334 def _should_send_property(self, key, value):
335 335 """Check the property lock (property_lock)"""
336 336 to_json = self.trait_metadata(key, 'to_json', self._trait_to_json)
337 337 if (key == self._property_lock[0]
338 338 and to_json(value) == self._property_lock[1]):
339 339 return False
340 340 elif self._send_state_lock > 0:
341 341 self._states_to_send.add(key)
342 342 return False
343 343 else:
344 344 return True
345 345
346 346 # Event handlers
347 347 @_show_traceback
348 348 def _handle_msg(self, msg):
349 349 """Called when a msg is received from the front-end"""
350 350 data = msg['content']['data']
351 351 method = data['method']
352 352
353 353 # Handle backbone sync methods CREATE, PATCH, and UPDATE all in one.
354 354 if method == 'backbone':
355 355 if 'sync_data' in data:
356 356 sync_data = data['sync_data']
357 357 self.set_state(sync_data) # handles all methods
358 358
359 359 # Handle a state request.
360 360 elif method == 'request_state':
361 361 self.send_state()
362 362
363 363 # Handle a custom msg from the front-end.
364 364 elif method == 'custom':
365 365 if 'content' in data:
366 366 self._handle_custom_msg(data['content'])
367 367
368 368 # Catch remainder.
369 369 else:
370 370 self.log.error('Unknown front-end to back-end widget msg with method "%s"' % method)
371 371
372 372 def _handle_custom_msg(self, content):
373 373 """Called when a custom msg is received."""
374 374 self._msg_callbacks(self, content)
375 375
376 376 def _notify_trait(self, name, old_value, new_value):
377 377 """Called when a property has been changed."""
378 378 # Trigger default traitlet callback machinery. This allows any user
379 379 # registered validation to be processed prior to allowing the widget
380 380 # machinery to handle the state.
381 381 LoggingConfigurable._notify_trait(self, name, old_value, new_value)
382 382
383 383 # Send the state after the user registered callbacks for trait changes
384 384 # have all fired (allows for user to validate values).
385 385 if self.comm is not None and name in self.keys:
386 386 # Make sure this isn't information that the front-end just sent us.
387 387 if self._should_send_property(name, new_value):
388 388 # Send new state to front-end
389 389 self.send_state(key=name)
390 390
391 391 def _handle_displayed(self, **kwargs):
392 392 """Called when a view has been displayed for this widget instance"""
393 393 self._display_callbacks(self, **kwargs)
394 394
395 395 def _trait_to_json(self, x):
396 396 """Convert a trait value to json
397 397
398 398 Traverse lists/tuples and dicts and serialize their values as well.
399 399 Replace any widgets with their model_id
400 400 """
401 401 if isinstance(x, dict):
402 402 return {k: self._trait_to_json(v) for k, v in x.items()}
403 403 elif isinstance(x, (list, tuple)):
404 404 return [self._trait_to_json(v) for v in x]
405 405 elif isinstance(x, Widget):
406 406 return "IPY_MODEL_" + x.model_id
407 407 else:
408 408 return x # Value must be JSON-able
409 409
410 410 def _trait_from_json(self, x):
411 411 """Convert json values to objects
412 412
413 413 Replace any strings representing valid model id values to Widget references.
414 414 """
415 415 if isinstance(x, dict):
416 416 return {k: self._trait_from_json(v) for k, v in x.items()}
417 417 elif isinstance(x, (list, tuple)):
418 418 return [self._trait_from_json(v) for v in x]
419 419 elif isinstance(x, string_types) and x.startswith('IPY_MODEL_') and x[10:] in Widget.widgets:
420 420 # we want to support having child widgets at any level in a hierarchy
421 421 # trusting that a widget UUID will not appear out in the wild
422 422 return Widget.widgets[x[10:]]
423 423 else:
424 424 return x
425 425
426 426 def _ipython_display_(self, **kwargs):
427 427 """Called when `IPython.display.display` is called on the widget."""
428 428 # Show view.
429 429 if self._view_name is not None:
430 430 self._send({"method": "display"})
431 431 self._handle_displayed(**kwargs)
432 432
433 433 def _send(self, msg):
434 434 """Sends a message to the model in the front-end."""
435 435 self.comm.send(msg)
436 436
437 437
438 438 class DOMWidget(Widget):
439 439 visible = Bool(True, allow_none=True, help="Whether the widget is visible. False collapses the empty space, while None preserves the empty space.", sync=True)
440 440 _css = Tuple(sync=True, help="CSS property list: (selector, key, value)")
441 441 _dom_classes = Tuple(sync=True, help="DOM classes applied to widget.$el.")
442 442
443 443 width = CUnicode(sync=True)
444 444 height = CUnicode(sync=True)
445 445 # A default padding of 2.5 px makes the widgets look nice when displayed inline.
446 446 padding = CUnicode(sync=True)
447 447 margin = CUnicode(sync=True)
448 448
449 449 color = Color(None, allow_none=True, sync=True)
450 450 background_color = Color(None, allow_none=True, sync=True)
451 451 border_color = Color(None, allow_none=True, sync=True)
452 452
453 453 border_width = CUnicode(sync=True)
454 454 border_radius = CUnicode(sync=True)
455 455 border_style = CaselessStrEnum(values=[ # http://www.w3schools.com/cssref/pr_border-style.asp
456 456 'none',
457 457 'hidden',
458 458 'dotted',
459 459 'dashed',
460 460 'solid',
461 461 'double',
462 462 'groove',
463 463 'ridge',
464 464 'inset',
465 465 'outset',
466 466 'initial',
467 467 'inherit', ''],
468 468 default_value='', sync=True)
469 469
470 470 font_style = CaselessStrEnum(values=[ # http://www.w3schools.com/cssref/pr_font_font-style.asp
471 471 'normal',
472 472 'italic',
473 473 'oblique',
474 474 'initial',
475 475 'inherit', ''],
476 476 default_value='', sync=True)
477 477 font_weight = CaselessStrEnum(values=[ # http://www.w3schools.com/cssref/pr_font_weight.asp
478 478 'normal',
479 479 'bold',
480 480 'bolder',
481 481 'lighter',
482 482 'initial',
483 483 'inherit', ''] + list(map(str, range(100,1000,100))),
484 484 default_value='', sync=True)
485 485 font_size = CUnicode(sync=True)
486 486 font_family = Unicode(sync=True)
487 487
488 488 def __init__(self, *pargs, **kwargs):
489 489 super(DOMWidget, self).__init__(*pargs, **kwargs)
490 490
491 491 def _validate_border(name, old, new):
492 492 if new is not None and new != '':
493 493 if name != 'border_width' and not self.border_width:
494 494 self.border_width = 1
495 495 if name != 'border_style' and self.border_style == '':
496 496 self.border_style = 'solid'
497 497 self.on_trait_change(_validate_border, ['border_width', 'border_style', 'border_color'])
@@ -1,156 +1,157 b''
1 1 """A client for in-process kernels."""
2 2
3 3 #-----------------------------------------------------------------------------
4 4 # Copyright (C) 2012 The IPython Development Team
5 5 #
6 6 # Distributed under the terms of the BSD License. The full license is in
7 7 # the file COPYING, distributed as part of this software.
8 8 #-----------------------------------------------------------------------------
9 9
10 10 #-----------------------------------------------------------------------------
11 11 # Imports
12 12 #-----------------------------------------------------------------------------
13 13
14 14 # IPython imports
15 15 from IPython.kernel.inprocess.socket import DummySocket
16 16 from IPython.utils.traitlets import Type, Instance
17 17 from IPython.kernel.clientabc import KernelClientABC
18 18 from IPython.kernel.client import KernelClient
19 19
20 20 # Local imports
21 21 from .channels import (
22 22 InProcessChannel,
23 23 InProcessHBChannel,
24 24
25 25 )
26 26
27 27 #-----------------------------------------------------------------------------
28 28 # Main kernel Client class
29 29 #-----------------------------------------------------------------------------
30 30
31 31 class InProcessKernelClient(KernelClient):
32 32 """A client for an in-process kernel.
33 33
34 34 This class implements the interface of
35 35 `IPython.kernel.clientabc.KernelClientABC` and allows
36 36 (asynchronous) frontends to be used seamlessly with an in-process kernel.
37 37
38 38 See `IPython.kernel.client.KernelClient` for docstrings.
39 39 """
40 40
41 41 # The classes to use for the various channels.
42 42 shell_channel_class = Type(InProcessChannel)
43 43 iopub_channel_class = Type(InProcessChannel)
44 44 stdin_channel_class = Type(InProcessChannel)
45 45 hb_channel_class = Type(InProcessHBChannel)
46 46
47 kernel = Instance('IPython.kernel.inprocess.ipkernel.InProcessKernel')
47 kernel = Instance('IPython.kernel.inprocess.ipkernel.InProcessKernel',
48 allow_none=True)
48 49
49 50 #--------------------------------------------------------------------------
50 51 # Channel management methods
51 52 #--------------------------------------------------------------------------
52 53
53 54 def start_channels(self, *args, **kwargs):
54 55 super(InProcessKernelClient, self).start_channels(self)
55 56 self.kernel.frontends.append(self)
56 57
57 58 @property
58 59 def shell_channel(self):
59 60 if self._shell_channel is None:
60 61 self._shell_channel = self.shell_channel_class(self)
61 62 return self._shell_channel
62 63
63 64 @property
64 65 def iopub_channel(self):
65 66 if self._iopub_channel is None:
66 67 self._iopub_channel = self.iopub_channel_class(self)
67 68 return self._iopub_channel
68 69
69 70 @property
70 71 def stdin_channel(self):
71 72 if self._stdin_channel is None:
72 73 self._stdin_channel = self.stdin_channel_class(self)
73 74 return self._stdin_channel
74 75
75 76 @property
76 77 def hb_channel(self):
77 78 if self._hb_channel is None:
78 79 self._hb_channel = self.hb_channel_class(self)
79 80 return self._hb_channel
80 81
81 82 # Methods for sending specific messages
82 83 # -------------------------------------
83 84
84 85 def execute(self, code, silent=False, store_history=True,
85 86 user_expressions={}, allow_stdin=None):
86 87 if allow_stdin is None:
87 88 allow_stdin = self.allow_stdin
88 89 content = dict(code=code, silent=silent, store_history=store_history,
89 90 user_expressions=user_expressions,
90 91 allow_stdin=allow_stdin)
91 92 msg = self.session.msg('execute_request', content)
92 93 self._dispatch_to_kernel(msg)
93 94 return msg['header']['msg_id']
94 95
95 96 def complete(self, code, cursor_pos=None):
96 97 if cursor_pos is None:
97 98 cursor_pos = len(code)
98 99 content = dict(code=code, cursor_pos=cursor_pos)
99 100 msg = self.session.msg('complete_request', content)
100 101 self._dispatch_to_kernel(msg)
101 102 return msg['header']['msg_id']
102 103
103 104 def inspect(self, code, cursor_pos=None, detail_level=0):
104 105 if cursor_pos is None:
105 106 cursor_pos = len(code)
106 107 content = dict(code=code, cursor_pos=cursor_pos,
107 108 detail_level=detail_level,
108 109 )
109 110 msg = self.session.msg('inspect_request', content)
110 111 self._dispatch_to_kernel(msg)
111 112 return msg['header']['msg_id']
112 113
113 114 def history(self, raw=True, output=False, hist_access_type='range', **kwds):
114 115 content = dict(raw=raw, output=output,
115 116 hist_access_type=hist_access_type, **kwds)
116 117 msg = self.session.msg('history_request', content)
117 118 self._dispatch_to_kernel(msg)
118 119 return msg['header']['msg_id']
119 120
120 121 def shutdown(self, restart=False):
121 122 # FIXME: What to do here?
122 123 raise NotImplementedError('Cannot shutdown in-process kernel')
123 124
124 125 def kernel_info(self):
125 126 """Request kernel info."""
126 127 msg = self.session.msg('kernel_info_request')
127 128 self._dispatch_to_kernel(msg)
128 129 return msg['header']['msg_id']
129 130
130 131 def input(self, string):
131 132 if self.kernel is None:
132 133 raise RuntimeError('Cannot send input reply. No kernel exists.')
133 134 self.kernel.raw_input_str = string
134 135
135 136
136 137 def _dispatch_to_kernel(self, msg):
137 138 """ Send a message to the kernel and handle a reply.
138 139 """
139 140 kernel = self.kernel
140 141 if kernel is None:
141 142 raise RuntimeError('Cannot send request. No kernel exists.')
142 143
143 144 stream = DummySocket()
144 145 self.session.send(stream, msg)
145 146 msg_parts = stream.recv_multipart()
146 147 kernel.dispatch_shell(stream, msg_parts)
147 148
148 149 idents, reply_msg = self.session.recv(stream, copy=False)
149 150 self.shell_channel.call_handlers_later(reply_msg)
150 151
151 152
152 153 #-----------------------------------------------------------------------------
153 154 # ABC Registration
154 155 #-----------------------------------------------------------------------------
155 156
156 157 KernelClientABC.register(InProcessKernelClient)
@@ -1,169 +1,171 b''
1 1 """An in-process kernel"""
2 2
3 3 # Copyright (c) IPython Development Team.
4 4 # Distributed under the terms of the Modified BSD License.
5 5
6 6 from contextlib import contextmanager
7 7 import logging
8 8 import sys
9 9
10 10 from IPython.core.interactiveshell import InteractiveShellABC
11 11 from IPython.utils.jsonutil import json_clean
12 12 from IPython.utils.traitlets import Any, Enum, Instance, List, Type
13 13 from IPython.kernel.zmq.ipkernel import IPythonKernel
14 14 from IPython.kernel.zmq.zmqshell import ZMQInteractiveShell
15 15
16 16 from .socket import DummySocket
17 17
18 18 #-----------------------------------------------------------------------------
19 19 # Main kernel class
20 20 #-----------------------------------------------------------------------------
21 21
22 22 class InProcessKernel(IPythonKernel):
23 23
24 24 #-------------------------------------------------------------------------
25 25 # InProcessKernel interface
26 26 #-------------------------------------------------------------------------
27 27
28 28 # The frontends connected to this kernel.
29 29 frontends = List(
30 Instance('IPython.kernel.inprocess.client.InProcessKernelClient')
30 Instance('IPython.kernel.inprocess.client.InProcessKernelClient'
31 allow_none=True)
31 32 )
32 33
33 34 # The GUI environment that the kernel is running under. This need not be
34 35 # specified for the normal operation for the kernel, but is required for
35 36 # IPython's GUI support (including pylab). The default is 'inline' because
36 37 # it is safe under all GUI toolkits.
37 38 gui = Enum(('tk', 'gtk', 'wx', 'qt', 'qt4', 'inline'),
38 39 default_value='inline')
39 40
40 41 raw_input_str = Any()
41 42 stdout = Any()
42 43 stderr = Any()
43 44
44 45 #-------------------------------------------------------------------------
45 46 # Kernel interface
46 47 #-------------------------------------------------------------------------
47 48
48 49 shell_class = Type()
49 50 shell_streams = List()
50 51 control_stream = Any()
51 52 iopub_socket = Instance(DummySocket, ())
52 53 stdin_socket = Instance(DummySocket, ())
53 54
54 55 def __init__(self, **traits):
55 56 super(InProcessKernel, self).__init__(**traits)
56 57
57 58 self.iopub_socket.on_trait_change(self._io_dispatch, 'message_sent')
58 59 self.shell.kernel = self
59 60
60 61 def execute_request(self, stream, ident, parent):
61 62 """ Override for temporary IO redirection. """
62 63 with self._redirected_io():
63 64 super(InProcessKernel, self).execute_request(stream, ident, parent)
64 65
65 66 def start(self):
66 67 """ Override registration of dispatchers for streams. """
67 68 self.shell.exit_now = False
68 69
69 70 def _abort_queue(self, stream):
70 71 """ The in-process kernel doesn't abort requests. """
71 72 pass
72 73
73 74 def _input_request(self, prompt, ident, parent, password=False):
74 75 # Flush output before making the request.
75 76 self.raw_input_str = None
76 77 sys.stderr.flush()
77 78 sys.stdout.flush()
78 79
79 80 # Send the input request.
80 81 content = json_clean(dict(prompt=prompt, password=password))
81 82 msg = self.session.msg(u'input_request', content, parent)
82 83 for frontend in self.frontends:
83 84 if frontend.session.session == parent['header']['session']:
84 85 frontend.stdin_channel.call_handlers(msg)
85 86 break
86 87 else:
87 88 logging.error('No frontend found for raw_input request')
88 89 return str()
89 90
90 91 # Await a response.
91 92 while self.raw_input_str is None:
92 93 frontend.stdin_channel.process_events()
93 94 return self.raw_input_str
94 95
95 96 #-------------------------------------------------------------------------
96 97 # Protected interface
97 98 #-------------------------------------------------------------------------
98 99
99 100 @contextmanager
100 101 def _redirected_io(self):
101 102 """ Temporarily redirect IO to the kernel.
102 103 """
103 104 sys_stdout, sys_stderr = sys.stdout, sys.stderr
104 105 sys.stdout, sys.stderr = self.stdout, self.stderr
105 106 yield
106 107 sys.stdout, sys.stderr = sys_stdout, sys_stderr
107 108
108 109 #------ Trait change handlers --------------------------------------------
109 110
110 111 def _io_dispatch(self):
111 112 """ Called when a message is sent to the IO socket.
112 113 """
113 114 ident, msg = self.session.recv(self.iopub_socket, copy=False)
114 115 for frontend in self.frontends:
115 116 frontend.iopub_channel.call_handlers(msg)
116 117
117 118 #------ Trait initializers -----------------------------------------------
118 119
119 120 def _log_default(self):
120 121 return logging.getLogger(__name__)
121 122
122 123 def _session_default(self):
123 124 from IPython.kernel.zmq.session import Session
124 125 return Session(parent=self, key=b'')
125 126
126 127 def _shell_class_default(self):
127 128 return InProcessInteractiveShell
128 129
129 130 def _stdout_default(self):
130 131 from IPython.kernel.zmq.iostream import OutStream
131 132 return OutStream(self.session, self.iopub_socket, u'stdout', pipe=False)
132 133
133 134 def _stderr_default(self):
134 135 from IPython.kernel.zmq.iostream import OutStream
135 136 return OutStream(self.session, self.iopub_socket, u'stderr', pipe=False)
136 137
137 138 #-----------------------------------------------------------------------------
138 139 # Interactive shell subclass
139 140 #-----------------------------------------------------------------------------
140 141
141 142 class InProcessInteractiveShell(ZMQInteractiveShell):
142 143
143 kernel = Instance('IPython.kernel.inprocess.ipkernel.InProcessKernel')
144 kernel = Instance('IPython.kernel.inprocess.ipkernel.InProcessKernel',
145 allow_none=True)
144 146
145 147 #-------------------------------------------------------------------------
146 148 # InteractiveShell interface
147 149 #-------------------------------------------------------------------------
148 150
149 151 def enable_gui(self, gui=None):
150 152 """Enable GUI integration for the kernel."""
151 153 from IPython.kernel.zmq.eventloops import enable_gui
152 154 if not gui:
153 155 gui = self.kernel.gui
154 156 return enable_gui(gui, kernel=self.kernel)
155 157
156 158 def enable_matplotlib(self, gui=None):
157 159 """Enable matplotlib integration for the kernel."""
158 160 if not gui:
159 161 gui = self.kernel.gui
160 162 return super(InProcessInteractiveShell, self).enable_matplotlib(gui)
161 163
162 164 def enable_pylab(self, gui=None, import_all=True, welcome_message=False):
163 165 """Activate pylab support at runtime."""
164 166 if not gui:
165 167 gui = self.kernel.gui
166 168 return super(InProcessInteractiveShell, self).enable_pylab(gui, import_all,
167 169 welcome_message)
168 170
169 171 InteractiveShellABC.register(InProcessInteractiveShell)
@@ -1,71 +1,72 b''
1 1 """A kernel manager for in-process kernels."""
2 2
3 3 # Copyright (c) IPython Development Team.
4 4 # Distributed under the terms of the Modified BSD License.
5 5
6 6 from IPython.utils.traitlets import Instance, DottedObjectName
7 7 from IPython.kernel.managerabc import KernelManagerABC
8 8 from IPython.kernel.manager import KernelManager
9 9 from IPython.kernel.zmq.session import Session
10 10
11 11
12 12 class InProcessKernelManager(KernelManager):
13 13 """A manager for an in-process kernel.
14 14
15 15 This class implements the interface of
16 16 `IPython.kernel.kernelmanagerabc.KernelManagerABC` and allows
17 17 (asynchronous) frontends to be used seamlessly with an in-process kernel.
18 18
19 19 See `IPython.kernel.kernelmanager.KernelManager` for docstrings.
20 20 """
21 21
22 22 # The kernel process with which the KernelManager is communicating.
23 kernel = Instance('IPython.kernel.inprocess.ipkernel.InProcessKernel')
23 kernel = Instance('IPython.kernel.inprocess.ipkernel.InProcessKernel',
24 allow_none=True)
24 25 # the client class for KM.client() shortcut
25 26 client_class = DottedObjectName('IPython.kernel.inprocess.BlockingInProcessKernelClient')
26 27
27 28 def _session_default(self):
28 29 # don't sign in-process messages
29 30 return Session(key=b'', parent=self)
30 31
31 32 #--------------------------------------------------------------------------
32 33 # Kernel management methods
33 34 #--------------------------------------------------------------------------
34 35
35 36 def start_kernel(self, **kwds):
36 37 from IPython.kernel.inprocess.ipkernel import InProcessKernel
37 38 self.kernel = InProcessKernel(parent=self, session=self.session)
38 39
39 40 def shutdown_kernel(self):
40 41 self._kill_kernel()
41 42
42 43 def restart_kernel(self, now=False, **kwds):
43 44 self.shutdown_kernel()
44 45 self.start_kernel(**kwds)
45 46
46 47 @property
47 48 def has_kernel(self):
48 49 return self.kernel is not None
49 50
50 51 def _kill_kernel(self):
51 52 self.kernel = None
52 53
53 54 def interrupt_kernel(self):
54 55 raise NotImplementedError("Cannot interrupt in-process kernel.")
55 56
56 57 def signal_kernel(self, signum):
57 58 raise NotImplementedError("Cannot signal in-process kernel.")
58 59
59 60 def is_alive(self):
60 61 return self.kernel is not None
61 62
62 63 def client(self, **kwargs):
63 64 kwargs['kernel'] = self.kernel
64 65 return super(InProcessKernelManager, self).client(**kwargs)
65 66
66 67
67 68 #-----------------------------------------------------------------------------
68 69 # ABC Registration
69 70 #-----------------------------------------------------------------------------
70 71
71 72 KernelManagerABC.register(InProcessKernelManager)
@@ -1,62 +1,62 b''
1 1 """A kernel manager with a tornado IOLoop"""
2 2
3 3 #-----------------------------------------------------------------------------
4 4 # Copyright (C) 2013 The IPython Development Team
5 5 #
6 6 # Distributed under the terms of the BSD License. The full license is in
7 7 # the file COPYING, distributed as part of this software.
8 8 #-----------------------------------------------------------------------------
9 9
10 10 #-----------------------------------------------------------------------------
11 11 # Imports
12 12 #-----------------------------------------------------------------------------
13 13
14 14 from __future__ import absolute_import
15 15
16 16 from zmq.eventloop import ioloop
17 17 from zmq.eventloop.zmqstream import ZMQStream
18 18
19 19 from IPython.utils.traitlets import (
20 20 Instance
21 21 )
22 22
23 23 from IPython.kernel.manager import KernelManager
24 24 from .restarter import IOLoopKernelRestarter
25 25
26 26 #-----------------------------------------------------------------------------
27 27 # Code
28 28 #-----------------------------------------------------------------------------
29 29
30 30
31 31 def as_zmqstream(f):
32 32 def wrapped(self, *args, **kwargs):
33 33 socket = f(self, *args, **kwargs)
34 34 return ZMQStream(socket, self.loop)
35 35 return wrapped
36 36
37 37 class IOLoopKernelManager(KernelManager):
38 38
39 loop = Instance('zmq.eventloop.ioloop.IOLoop', allow_none=False)
39 loop = Instance('zmq.eventloop.ioloop.IOLoop')
40 40 def _loop_default(self):
41 41 return ioloop.IOLoop.instance()
42 42
43 _restarter = Instance('IPython.kernel.ioloop.IOLoopKernelRestarter')
43 _restarter = Instance('IPython.kernel.ioloop.IOLoopKernelRestarter', allow_none=True)
44 44
45 45 def start_restarter(self):
46 46 if self.autorestart and self.has_kernel:
47 47 if self._restarter is None:
48 48 self._restarter = IOLoopKernelRestarter(
49 49 kernel_manager=self, loop=self.loop,
50 50 parent=self, log=self.log
51 51 )
52 52 self._restarter.start()
53 53
54 54 def stop_restarter(self):
55 55 if self.autorestart:
56 56 if self._restarter is not None:
57 57 self._restarter.stop()
58 58
59 59 connect_shell = as_zmqstream(KernelManager.connect_shell)
60 60 connect_iopub = as_zmqstream(KernelManager.connect_iopub)
61 61 connect_stdin = as_zmqstream(KernelManager.connect_stdin)
62 62 connect_hb = as_zmqstream(KernelManager.connect_hb)
@@ -1,54 +1,54 b''
1 1 """A basic in process kernel monitor with autorestarting.
2 2
3 3 This watches a kernel's state using KernelManager.is_alive and auto
4 4 restarts the kernel if it dies.
5 5 """
6 6
7 7 #-----------------------------------------------------------------------------
8 8 # Copyright (C) 2013 The IPython Development Team
9 9 #
10 10 # Distributed under the terms of the BSD License. The full license is in
11 11 # the file COPYING, distributed as part of this software.
12 12 #-----------------------------------------------------------------------------
13 13
14 14 #-----------------------------------------------------------------------------
15 15 # Imports
16 16 #-----------------------------------------------------------------------------
17 17
18 18 from __future__ import absolute_import
19 19
20 20 from zmq.eventloop import ioloop
21 21
22 22
23 23 from IPython.kernel.restarter import KernelRestarter
24 24 from IPython.utils.traitlets import (
25 25 Instance,
26 26 )
27 27
28 28 #-----------------------------------------------------------------------------
29 29 # Code
30 30 #-----------------------------------------------------------------------------
31 31
32 32 class IOLoopKernelRestarter(KernelRestarter):
33 33 """Monitor and autorestart a kernel."""
34 34
35 loop = Instance('zmq.eventloop.ioloop.IOLoop', allow_none=False)
35 loop = Instance('zmq.eventloop.ioloop.IOLoop')
36 36 def _loop_default(self):
37 37 return ioloop.IOLoop.instance()
38 38
39 39 _pcallback = None
40 40
41 41 def start(self):
42 42 """Start the polling of the kernel."""
43 43 if self._pcallback is None:
44 44 self._pcallback = ioloop.PeriodicCallback(
45 45 self.poll, 1000*self.time_to_dead, self.loop
46 46 )
47 47 self._pcallback.start()
48 48
49 49 def stop(self):
50 50 """Stop the kernel polling."""
51 51 if self._pcallback is not None:
52 52 self._pcallback.stop()
53 53 self._pcallback = None
54 54
@@ -1,70 +1,70 b''
1 1 """Publishing native (typically pickled) objects.
2 2 """
3 3
4 4 #-----------------------------------------------------------------------------
5 5 # Copyright (C) 2012 The IPython Development Team
6 6 #
7 7 # Distributed under the terms of the BSD License. The full license is in
8 8 # the file COPYING, distributed as part of this software.
9 9 #-----------------------------------------------------------------------------
10 10
11 11 #-----------------------------------------------------------------------------
12 12 # Imports
13 13 #-----------------------------------------------------------------------------
14 14
15 15 from IPython.config import Configurable
16 16 from IPython.kernel.inprocess.socket import SocketABC
17 17 from IPython.utils.jsonutil import json_clean
18 18 from IPython.utils.traitlets import Instance, Dict, CBytes
19 19 from IPython.kernel.zmq.serialize import serialize_object
20 20 from IPython.kernel.zmq.session import Session, extract_header
21 21
22 22 #-----------------------------------------------------------------------------
23 23 # Code
24 24 #-----------------------------------------------------------------------------
25 25
26 26
27 27 class ZMQDataPublisher(Configurable):
28 28
29 29 topic = topic = CBytes(b'datapub')
30 session = Instance(Session)
31 pub_socket = Instance(SocketABC)
30 session = Instance(Session, allow_none=True)
31 pub_socket = Instance(SocketABC, allow_none=True)
32 32 parent_header = Dict({})
33 33
34 34 def set_parent(self, parent):
35 35 """Set the parent for outbound messages."""
36 36 self.parent_header = extract_header(parent)
37 37
38 38 def publish_data(self, data):
39 39 """publish a data_message on the IOPub channel
40 40
41 41 Parameters
42 42 ----------
43 43
44 44 data : dict
45 45 The data to be published. Think of it as a namespace.
46 46 """
47 47 session = self.session
48 48 buffers = serialize_object(data,
49 49 buffer_threshold=session.buffer_threshold,
50 50 item_threshold=session.item_threshold,
51 51 )
52 52 content = json_clean(dict(keys=data.keys()))
53 53 session.send(self.pub_socket, 'data_message', content=content,
54 54 parent=self.parent_header,
55 55 buffers=buffers,
56 56 ident=self.topic,
57 57 )
58 58
59 59
60 60 def publish_data(data):
61 61 """publish a data_message on the IOPub channel
62 62
63 63 Parameters
64 64 ----------
65 65
66 66 data : dict
67 67 The data to be published. Think of it as a namespace.
68 68 """
69 69 from IPython.kernel.zmq.zmqshell import ZMQInteractiveShell
70 70 ZMQInteractiveShell.instance().data_pub.publish_data(data)
@@ -1,74 +1,74 b''
1 1 """Replacements for sys.displayhook that publish over ZMQ."""
2 2
3 3 # Copyright (c) IPython Development Team.
4 4 # Distributed under the terms of the Modified BSD License.
5 5
6 6 import sys
7 7
8 8 from IPython.core.displayhook import DisplayHook
9 9 from IPython.kernel.inprocess.socket import SocketABC
10 10 from IPython.utils.jsonutil import encode_images
11 11 from IPython.utils.py3compat import builtin_mod
12 12 from IPython.utils.traitlets import Instance, Dict
13 13 from .session import extract_header, Session
14 14
15 15 class ZMQDisplayHook(object):
16 16 """A simple displayhook that publishes the object's repr over a ZeroMQ
17 17 socket."""
18 18 topic=b'execute_result'
19 19
20 20 def __init__(self, session, pub_socket):
21 21 self.session = session
22 22 self.pub_socket = pub_socket
23 23 self.parent_header = {}
24 24
25 25 def __call__(self, obj):
26 26 if obj is None:
27 27 return
28 28
29 29 builtin_mod._ = obj
30 30 sys.stdout.flush()
31 31 sys.stderr.flush()
32 32 msg = self.session.send(self.pub_socket, u'execute_result', {u'data':repr(obj)},
33 33 parent=self.parent_header, ident=self.topic)
34 34
35 35 def set_parent(self, parent):
36 36 self.parent_header = extract_header(parent)
37 37
38 38
39 39 class ZMQShellDisplayHook(DisplayHook):
40 40 """A displayhook subclass that publishes data using ZeroMQ. This is intended
41 41 to work with an InteractiveShell instance. It sends a dict of different
42 42 representations of the object."""
43 43 topic=None
44 44
45 session = Instance(Session)
46 pub_socket = Instance(SocketABC)
45 session = Instance(Session, allow_none=True)
46 pub_socket = Instance(SocketABC, allow_none=True)
47 47 parent_header = Dict({})
48 48
49 49 def set_parent(self, parent):
50 50 """Set the parent for outbound messages."""
51 51 self.parent_header = extract_header(parent)
52 52
53 53 def start_displayhook(self):
54 54 self.msg = self.session.msg(u'execute_result', {
55 55 'data': {},
56 56 'metadata': {},
57 57 }, parent=self.parent_header)
58 58
59 59 def write_output_prompt(self):
60 60 """Write the output prompt."""
61 61 self.msg['content']['execution_count'] = self.prompt_count
62 62
63 63 def write_format_data(self, format_dict, md_dict=None):
64 64 self.msg['content']['data'] = encode_images(format_dict)
65 65 self.msg['content']['metadata'] = md_dict
66 66
67 67 def finish_displayhook(self):
68 68 """Finish up all displayhook activities."""
69 69 sys.stdout.flush()
70 70 sys.stderr.flush()
71 71 if self.msg['content']['data']:
72 72 self.session.send(self.pub_socket, self.msg, ident=self.topic)
73 73 self.msg = None
74 74
@@ -1,367 +1,368 b''
1 1 """The IPython kernel implementation"""
2 2
3 3 import getpass
4 4 import sys
5 5 import traceback
6 6
7 7 from IPython.core import release
8 8 from IPython.utils.py3compat import builtin_mod, PY3
9 9 from IPython.utils.tokenutil import token_at_cursor, line_at_cursor
10 10 from IPython.utils.traitlets import Instance, Type, Any, List
11 11 from IPython.utils.decorators import undoc
12 12
13 13 from ..comm import CommManager
14 14 from .kernelbase import Kernel as KernelBase
15 15 from .serialize import serialize_object, unpack_apply_message
16 16 from .zmqshell import ZMQInteractiveShell
17 17
18 18
19 19 def lazy_import_handle_comm_opened(*args, **kwargs):
20 20 from IPython.html.widgets import Widget
21 21 Widget.handle_comm_opened(*args, **kwargs)
22 22
23 23
24 24 class IPythonKernel(KernelBase):
25 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
25 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC',
26 allow_none=True)
26 27 shell_class = Type(ZMQInteractiveShell)
27 28
28 29 user_module = Any()
29 30 def _user_module_changed(self, name, old, new):
30 31 if self.shell is not None:
31 32 self.shell.user_module = new
32 33
33 34 user_ns = Instance(dict, args=None, allow_none=True)
34 35 def _user_ns_changed(self, name, old, new):
35 36 if self.shell is not None:
36 37 self.shell.user_ns = new
37 38 self.shell.init_user_ns()
38 39
39 40 # A reference to the Python builtin 'raw_input' function.
40 41 # (i.e., __builtin__.raw_input for Python 2.7, builtins.input for Python 3)
41 42 _sys_raw_input = Any()
42 43 _sys_eval_input = Any()
43 44
44 45 def __init__(self, **kwargs):
45 46 super(IPythonKernel, self).__init__(**kwargs)
46 47
47 48 # Initialize the InteractiveShell subclass
48 49 self.shell = self.shell_class.instance(parent=self,
49 50 profile_dir = self.profile_dir,
50 51 user_module = self.user_module,
51 52 user_ns = self.user_ns,
52 53 kernel = self,
53 54 )
54 55 self.shell.displayhook.session = self.session
55 56 self.shell.displayhook.pub_socket = self.iopub_socket
56 57 self.shell.displayhook.topic = self._topic('execute_result')
57 58 self.shell.display_pub.session = self.session
58 59 self.shell.display_pub.pub_socket = self.iopub_socket
59 60 self.shell.data_pub.session = self.session
60 61 self.shell.data_pub.pub_socket = self.iopub_socket
61 62
62 63 # TMP - hack while developing
63 64 self.shell._reply_content = None
64 65
65 66 self.comm_manager = CommManager(shell=self.shell, parent=self,
66 67 kernel=self)
67 68 self.comm_manager.register_target('ipython.widget', lazy_import_handle_comm_opened)
68 69
69 70 self.shell.configurables.append(self.comm_manager)
70 71 comm_msg_types = [ 'comm_open', 'comm_msg', 'comm_close' ]
71 72 for msg_type in comm_msg_types:
72 73 self.shell_handlers[msg_type] = getattr(self.comm_manager, msg_type)
73 74
74 75 help_links = List([
75 76 {
76 77 'text': "Python",
77 78 'url': "http://docs.python.org/%i.%i" % sys.version_info[:2],
78 79 },
79 80 {
80 81 'text': "IPython",
81 82 'url': "http://ipython.org/documentation.html",
82 83 },
83 84 {
84 85 'text': "NumPy",
85 86 'url': "http://docs.scipy.org/doc/numpy/reference/",
86 87 },
87 88 {
88 89 'text': "SciPy",
89 90 'url': "http://docs.scipy.org/doc/scipy/reference/",
90 91 },
91 92 {
92 93 'text': "Matplotlib",
93 94 'url': "http://matplotlib.org/contents.html",
94 95 },
95 96 {
96 97 'text': "SymPy",
97 98 'url': "http://docs.sympy.org/latest/index.html",
98 99 },
99 100 {
100 101 'text': "pandas",
101 102 'url': "http://pandas.pydata.org/pandas-docs/stable/",
102 103 },
103 104 ])
104 105
105 106 # Kernel info fields
106 107 implementation = 'ipython'
107 108 implementation_version = release.version
108 109 language_info = {
109 110 'name': 'python',
110 111 'version': sys.version.split()[0],
111 112 'mimetype': 'text/x-python',
112 113 'codemirror_mode': {'name': 'ipython',
113 114 'version': sys.version_info[0]},
114 115 'pygments_lexer': 'ipython%d' % (3 if PY3 else 2),
115 116 'nbconvert_exporter': 'python',
116 117 'file_extension': '.py'
117 118 }
118 119 @property
119 120 def banner(self):
120 121 return self.shell.banner
121 122
122 123 def start(self):
123 124 self.shell.exit_now = False
124 125 super(IPythonKernel, self).start()
125 126
126 127 def set_parent(self, ident, parent):
127 128 """Overridden from parent to tell the display hook and output streams
128 129 about the parent message.
129 130 """
130 131 super(IPythonKernel, self).set_parent(ident, parent)
131 132 self.shell.set_parent(parent)
132 133
133 134 def _forward_input(self, allow_stdin=False):
134 135 """Forward raw_input and getpass to the current frontend.
135 136
136 137 via input_request
137 138 """
138 139 self._allow_stdin = allow_stdin
139 140
140 141 if PY3:
141 142 self._sys_raw_input = builtin_mod.input
142 143 builtin_mod.input = self.raw_input
143 144 else:
144 145 self._sys_raw_input = builtin_mod.raw_input
145 146 self._sys_eval_input = builtin_mod.input
146 147 builtin_mod.raw_input = self.raw_input
147 148 builtin_mod.input = lambda prompt='': eval(self.raw_input(prompt))
148 149 self._save_getpass = getpass.getpass
149 150 getpass.getpass = self.getpass
150 151
151 152 def _restore_input(self):
152 153 """Restore raw_input, getpass"""
153 154 if PY3:
154 155 builtin_mod.input = self._sys_raw_input
155 156 else:
156 157 builtin_mod.raw_input = self._sys_raw_input
157 158 builtin_mod.input = self._sys_eval_input
158 159
159 160 getpass.getpass = self._save_getpass
160 161
161 162 @property
162 163 def execution_count(self):
163 164 return self.shell.execution_count
164 165
165 166 @execution_count.setter
166 167 def execution_count(self, value):
167 168 # Ignore the incrememnting done by KernelBase, in favour of our shell's
168 169 # execution counter.
169 170 pass
170 171
171 172 def do_execute(self, code, silent, store_history=True,
172 173 user_expressions=None, allow_stdin=False):
173 174 shell = self.shell # we'll need this a lot here
174 175
175 176 self._forward_input(allow_stdin)
176 177
177 178 reply_content = {}
178 179 # FIXME: the shell calls the exception handler itself.
179 180 shell._reply_content = None
180 181 try:
181 182 shell.run_cell(code, store_history=store_history, silent=silent)
182 183 except:
183 184 status = u'error'
184 185 # FIXME: this code right now isn't being used yet by default,
185 186 # because the run_cell() call above directly fires off exception
186 187 # reporting. This code, therefore, is only active in the scenario
187 188 # where runlines itself has an unhandled exception. We need to
188 189 # uniformize this, for all exception construction to come from a
189 190 # single location in the codbase.
190 191 etype, evalue, tb = sys.exc_info()
191 192 tb_list = traceback.format_exception(etype, evalue, tb)
192 193 reply_content.update(shell._showtraceback(etype, evalue, tb_list))
193 194 else:
194 195 status = u'ok'
195 196 finally:
196 197 self._restore_input()
197 198
198 199 reply_content[u'status'] = status
199 200
200 201 # Return the execution counter so clients can display prompts
201 202 reply_content['execution_count'] = shell.execution_count - 1
202 203
203 204 # FIXME - fish exception info out of shell, possibly left there by
204 205 # runlines. We'll need to clean up this logic later.
205 206 if shell._reply_content is not None:
206 207 reply_content.update(shell._reply_content)
207 208 e_info = dict(engine_uuid=self.ident, engine_id=self.int_id, method='execute')
208 209 reply_content['engine_info'] = e_info
209 210 # reset after use
210 211 shell._reply_content = None
211 212
212 213 if 'traceback' in reply_content:
213 214 self.log.info("Exception in execute request:\n%s", '\n'.join(reply_content['traceback']))
214 215
215 216
216 217 # At this point, we can tell whether the main code execution succeeded
217 218 # or not. If it did, we proceed to evaluate user_expressions
218 219 if reply_content['status'] == 'ok':
219 220 reply_content[u'user_expressions'] = \
220 221 shell.user_expressions(user_expressions or {})
221 222 else:
222 223 # If there was an error, don't even try to compute expressions
223 224 reply_content[u'user_expressions'] = {}
224 225
225 226 # Payloads should be retrieved regardless of outcome, so we can both
226 227 # recover partial output (that could have been generated early in a
227 228 # block, before an error) and clear the payload system always.
228 229 reply_content[u'payload'] = shell.payload_manager.read_payload()
229 230 # Be agressive about clearing the payload because we don't want
230 231 # it to sit in memory until the next execute_request comes in.
231 232 shell.payload_manager.clear_payload()
232 233
233 234 return reply_content
234 235
235 236 def do_complete(self, code, cursor_pos):
236 237 # FIXME: IPython completers currently assume single line,
237 238 # but completion messages give multi-line context
238 239 # For now, extract line from cell, based on cursor_pos:
239 240 if cursor_pos is None:
240 241 cursor_pos = len(code)
241 242 line, offset = line_at_cursor(code, cursor_pos)
242 243 line_cursor = cursor_pos - offset
243 244
244 245 txt, matches = self.shell.complete('', line, line_cursor)
245 246 return {'matches' : matches,
246 247 'cursor_end' : cursor_pos,
247 248 'cursor_start' : cursor_pos - len(txt),
248 249 'metadata' : {},
249 250 'status' : 'ok'}
250 251
251 252 def do_inspect(self, code, cursor_pos, detail_level=0):
252 253 name = token_at_cursor(code, cursor_pos)
253 254 info = self.shell.object_inspect(name)
254 255
255 256 reply_content = {'status' : 'ok'}
256 257 reply_content['data'] = data = {}
257 258 reply_content['metadata'] = {}
258 259 reply_content['found'] = info['found']
259 260 if info['found']:
260 261 info_text = self.shell.object_inspect_text(
261 262 name,
262 263 detail_level=detail_level,
263 264 )
264 265 data['text/plain'] = info_text
265 266
266 267 return reply_content
267 268
268 269 def do_history(self, hist_access_type, output, raw, session=None, start=None,
269 270 stop=None, n=None, pattern=None, unique=False):
270 271 if hist_access_type == 'tail':
271 272 hist = self.shell.history_manager.get_tail(n, raw=raw, output=output,
272 273 include_latest=True)
273 274
274 275 elif hist_access_type == 'range':
275 276 hist = self.shell.history_manager.get_range(session, start, stop,
276 277 raw=raw, output=output)
277 278
278 279 elif hist_access_type == 'search':
279 280 hist = self.shell.history_manager.search(
280 281 pattern, raw=raw, output=output, n=n, unique=unique)
281 282 else:
282 283 hist = []
283 284
284 285 return {'history' : list(hist)}
285 286
286 287 def do_shutdown(self, restart):
287 288 self.shell.exit_now = True
288 289 return dict(status='ok', restart=restart)
289 290
290 291 def do_is_complete(self, code):
291 292 status, indent_spaces = self.shell.input_transformer_manager.check_complete(code)
292 293 r = {'status': status}
293 294 if status == 'incomplete':
294 295 r['indent'] = ' ' * indent_spaces
295 296 return r
296 297
297 298 def do_apply(self, content, bufs, msg_id, reply_metadata):
298 299 shell = self.shell
299 300 try:
300 301 working = shell.user_ns
301 302
302 303 prefix = "_"+str(msg_id).replace("-","")+"_"
303 304
304 305 f,args,kwargs = unpack_apply_message(bufs, working, copy=False)
305 306
306 307 fname = getattr(f, '__name__', 'f')
307 308
308 309 fname = prefix+"f"
309 310 argname = prefix+"args"
310 311 kwargname = prefix+"kwargs"
311 312 resultname = prefix+"result"
312 313
313 314 ns = { fname : f, argname : args, kwargname : kwargs , resultname : None }
314 315 # print ns
315 316 working.update(ns)
316 317 code = "%s = %s(*%s,**%s)" % (resultname, fname, argname, kwargname)
317 318 try:
318 319 exec(code, shell.user_global_ns, shell.user_ns)
319 320 result = working.get(resultname)
320 321 finally:
321 322 for key in ns:
322 323 working.pop(key)
323 324
324 325 result_buf = serialize_object(result,
325 326 buffer_threshold=self.session.buffer_threshold,
326 327 item_threshold=self.session.item_threshold,
327 328 )
328 329
329 330 except:
330 331 # invoke IPython traceback formatting
331 332 shell.showtraceback()
332 333 # FIXME - fish exception info out of shell, possibly left there by
333 334 # run_code. We'll need to clean up this logic later.
334 335 reply_content = {}
335 336 if shell._reply_content is not None:
336 337 reply_content.update(shell._reply_content)
337 338 e_info = dict(engine_uuid=self.ident, engine_id=self.int_id, method='apply')
338 339 reply_content['engine_info'] = e_info
339 340 # reset after use
340 341 shell._reply_content = None
341 342
342 343 self.send_response(self.iopub_socket, u'error', reply_content,
343 344 ident=self._topic('error'))
344 345 self.log.info("Exception in apply request:\n%s", '\n'.join(reply_content['traceback']))
345 346 result_buf = []
346 347
347 348 if reply_content['ename'] == 'UnmetDependency':
348 349 reply_metadata['dependencies_met'] = False
349 350 else:
350 351 reply_content = {'status' : 'ok'}
351 352
352 353 return reply_content, result_buf
353 354
354 355 def do_clear(self):
355 356 self.shell.reset(False)
356 357 return dict(status='ok')
357 358
358 359
359 360 # This exists only for backwards compatibility - use IPythonKernel instead
360 361
361 362 @undoc
362 363 class Kernel(IPythonKernel):
363 364 def __init__(self, *args, **kwargs):
364 365 import warnings
365 366 warnings.warn('Kernel is a deprecated alias of IPython.kernel.zmq.ipkernel.IPythonKernel',
366 367 DeprecationWarning)
367 368 super(Kernel, self).__init__(*args, **kwargs)
@@ -1,387 +1,387 b''
1 1 """An Application for launching a kernel"""
2 2
3 3 # Copyright (c) IPython Development Team.
4 4 # Distributed under the terms of the Modified BSD License.
5 5
6 6 from __future__ import print_function
7 7
8 8 import atexit
9 9 import os
10 10 import sys
11 11 import signal
12 12
13 13 import zmq
14 14 from zmq.eventloop import ioloop
15 15 from zmq.eventloop.zmqstream import ZMQStream
16 16
17 17 from IPython.core.ultratb import FormattedTB
18 18 from IPython.core.application import (
19 19 BaseIPythonApplication, base_flags, base_aliases, catch_config_error
20 20 )
21 21 from IPython.core.profiledir import ProfileDir
22 22 from IPython.core.shellapp import (
23 23 InteractiveShellApp, shell_flags, shell_aliases
24 24 )
25 25 from IPython.utils import io
26 26 from IPython.utils.path import filefind
27 27 from IPython.utils.traitlets import (
28 28 Any, Instance, Dict, Unicode, Integer, Bool, DottedObjectName, Type,
29 29 )
30 30 from IPython.utils.importstring import import_item
31 31 from IPython.kernel import write_connection_file
32 32 from IPython.kernel.connect import ConnectionFileMixin
33 33
34 34 # local imports
35 35 from .heartbeat import Heartbeat
36 36 from .ipkernel import IPythonKernel
37 37 from .parentpoller import ParentPollerUnix, ParentPollerWindows
38 38 from .session import (
39 39 Session, session_flags, session_aliases,
40 40 )
41 41 from .zmqshell import ZMQInteractiveShell
42 42
43 43 #-----------------------------------------------------------------------------
44 44 # Flags and Aliases
45 45 #-----------------------------------------------------------------------------
46 46
47 47 kernel_aliases = dict(base_aliases)
48 48 kernel_aliases.update({
49 49 'ip' : 'IPKernelApp.ip',
50 50 'hb' : 'IPKernelApp.hb_port',
51 51 'shell' : 'IPKernelApp.shell_port',
52 52 'iopub' : 'IPKernelApp.iopub_port',
53 53 'stdin' : 'IPKernelApp.stdin_port',
54 54 'control' : 'IPKernelApp.control_port',
55 55 'f' : 'IPKernelApp.connection_file',
56 56 'transport': 'IPKernelApp.transport',
57 57 })
58 58
59 59 kernel_flags = dict(base_flags)
60 60 kernel_flags.update({
61 61 'no-stdout' : (
62 62 {'IPKernelApp' : {'no_stdout' : True}},
63 63 "redirect stdout to the null device"),
64 64 'no-stderr' : (
65 65 {'IPKernelApp' : {'no_stderr' : True}},
66 66 "redirect stderr to the null device"),
67 67 'pylab' : (
68 68 {'IPKernelApp' : {'pylab' : 'auto'}},
69 69 """Pre-load matplotlib and numpy for interactive use with
70 70 the default matplotlib backend."""),
71 71 })
72 72
73 73 # inherit flags&aliases for any IPython shell apps
74 74 kernel_aliases.update(shell_aliases)
75 75 kernel_flags.update(shell_flags)
76 76
77 77 # inherit flags&aliases for Sessions
78 78 kernel_aliases.update(session_aliases)
79 79 kernel_flags.update(session_flags)
80 80
81 81 _ctrl_c_message = """\
82 82 NOTE: When using the `ipython kernel` entry point, Ctrl-C will not work.
83 83
84 84 To exit, you will have to explicitly quit this process, by either sending
85 85 "quit" from a client, or using Ctrl-\\ in UNIX-like environments.
86 86
87 87 To read more about this, see https://github.com/ipython/ipython/issues/2049
88 88
89 89 """
90 90
91 91 #-----------------------------------------------------------------------------
92 92 # Application class for starting an IPython Kernel
93 93 #-----------------------------------------------------------------------------
94 94
95 95 class IPKernelApp(BaseIPythonApplication, InteractiveShellApp,
96 96 ConnectionFileMixin):
97 97 name='ipython-kernel'
98 98 aliases = Dict(kernel_aliases)
99 99 flags = Dict(kernel_flags)
100 100 classes = [IPythonKernel, ZMQInteractiveShell, ProfileDir, Session]
101 101 # the kernel class, as an importstring
102 102 kernel_class = Type('IPython.kernel.zmq.ipkernel.IPythonKernel', config=True,
103 103 klass='IPython.kernel.zmq.kernelbase.Kernel',
104 104 help="""The Kernel subclass to be used.
105 105
106 106 This should allow easy re-use of the IPKernelApp entry point
107 107 to configure and launch kernels other than IPython's own.
108 108 """)
109 109 kernel = Any()
110 110 poller = Any() # don't restrict this even though current pollers are all Threads
111 heartbeat = Instance(Heartbeat)
111 heartbeat = Instance(Heartbeat, allow_none=True)
112 112 ports = Dict()
113 113
114 114 # connection info:
115 115
116 116 @property
117 117 def abs_connection_file(self):
118 118 if os.path.basename(self.connection_file) == self.connection_file:
119 119 return os.path.join(self.profile_dir.security_dir, self.connection_file)
120 120 else:
121 121 return self.connection_file
122 122
123 123
124 124 # streams, etc.
125 125 no_stdout = Bool(False, config=True, help="redirect stdout to the null device")
126 126 no_stderr = Bool(False, config=True, help="redirect stderr to the null device")
127 127 outstream_class = DottedObjectName('IPython.kernel.zmq.iostream.OutStream',
128 128 config=True, help="The importstring for the OutStream factory")
129 129 displayhook_class = DottedObjectName('IPython.kernel.zmq.displayhook.ZMQDisplayHook',
130 130 config=True, help="The importstring for the DisplayHook factory")
131 131
132 132 # polling
133 133 parent_handle = Integer(int(os.environ.get('JPY_PARENT_PID') or 0), config=True,
134 134 help="""kill this process if its parent dies. On Windows, the argument
135 135 specifies the HANDLE of the parent process, otherwise it is simply boolean.
136 136 """)
137 137 interrupt = Integer(int(os.environ.get('JPY_INTERRUPT_EVENT') or 0), config=True,
138 138 help="""ONLY USED ON WINDOWS
139 139 Interrupt this process when the parent is signaled.
140 140 """)
141 141
142 142 def init_crash_handler(self):
143 143 # Install minimal exception handling
144 144 sys.excepthook = FormattedTB(mode='Verbose', color_scheme='NoColor',
145 145 ostream=sys.__stdout__)
146 146
147 147 def init_poller(self):
148 148 if sys.platform == 'win32':
149 149 if self.interrupt or self.parent_handle:
150 150 self.poller = ParentPollerWindows(self.interrupt, self.parent_handle)
151 151 elif self.parent_handle:
152 152 self.poller = ParentPollerUnix()
153 153
154 154 def _bind_socket(self, s, port):
155 155 iface = '%s://%s' % (self.transport, self.ip)
156 156 if self.transport == 'tcp':
157 157 if port <= 0:
158 158 port = s.bind_to_random_port(iface)
159 159 else:
160 160 s.bind("tcp://%s:%i" % (self.ip, port))
161 161 elif self.transport == 'ipc':
162 162 if port <= 0:
163 163 port = 1
164 164 path = "%s-%i" % (self.ip, port)
165 165 while os.path.exists(path):
166 166 port = port + 1
167 167 path = "%s-%i" % (self.ip, port)
168 168 else:
169 169 path = "%s-%i" % (self.ip, port)
170 170 s.bind("ipc://%s" % path)
171 171 return port
172 172
173 173 def write_connection_file(self):
174 174 """write connection info to JSON file"""
175 175 cf = self.abs_connection_file
176 176 self.log.debug("Writing connection file: %s", cf)
177 177 write_connection_file(cf, ip=self.ip, key=self.session.key, transport=self.transport,
178 178 shell_port=self.shell_port, stdin_port=self.stdin_port, hb_port=self.hb_port,
179 179 iopub_port=self.iopub_port, control_port=self.control_port)
180 180
181 181 def cleanup_connection_file(self):
182 182 cf = self.abs_connection_file
183 183 self.log.debug("Cleaning up connection file: %s", cf)
184 184 try:
185 185 os.remove(cf)
186 186 except (IOError, OSError):
187 187 pass
188 188
189 189 self.cleanup_ipc_files()
190 190
191 191 def init_connection_file(self):
192 192 if not self.connection_file:
193 193 self.connection_file = "kernel-%s.json"%os.getpid()
194 194 try:
195 195 self.connection_file = filefind(self.connection_file, ['.', self.profile_dir.security_dir])
196 196 except IOError:
197 197 self.log.debug("Connection file not found: %s", self.connection_file)
198 198 # This means I own it, so I will clean it up:
199 199 atexit.register(self.cleanup_connection_file)
200 200 return
201 201 try:
202 202 self.load_connection_file()
203 203 except Exception:
204 204 self.log.error("Failed to load connection file: %r", self.connection_file, exc_info=True)
205 205 self.exit(1)
206 206
207 207 def init_sockets(self):
208 208 # Create a context, a session, and the kernel sockets.
209 209 self.log.info("Starting the kernel at pid: %i", os.getpid())
210 210 context = zmq.Context.instance()
211 211 # Uncomment this to try closing the context.
212 212 # atexit.register(context.term)
213 213
214 214 self.shell_socket = context.socket(zmq.ROUTER)
215 215 self.shell_socket.linger = 1000
216 216 self.shell_port = self._bind_socket(self.shell_socket, self.shell_port)
217 217 self.log.debug("shell ROUTER Channel on port: %i" % self.shell_port)
218 218
219 219 self.iopub_socket = context.socket(zmq.PUB)
220 220 self.iopub_socket.linger = 1000
221 221 self.iopub_port = self._bind_socket(self.iopub_socket, self.iopub_port)
222 222 self.log.debug("iopub PUB Channel on port: %i" % self.iopub_port)
223 223
224 224 self.stdin_socket = context.socket(zmq.ROUTER)
225 225 self.stdin_socket.linger = 1000
226 226 self.stdin_port = self._bind_socket(self.stdin_socket, self.stdin_port)
227 227 self.log.debug("stdin ROUTER Channel on port: %i" % self.stdin_port)
228 228
229 229 self.control_socket = context.socket(zmq.ROUTER)
230 230 self.control_socket.linger = 1000
231 231 self.control_port = self._bind_socket(self.control_socket, self.control_port)
232 232 self.log.debug("control ROUTER Channel on port: %i" % self.control_port)
233 233
234 234 def init_heartbeat(self):
235 235 """start the heart beating"""
236 236 # heartbeat doesn't share context, because it mustn't be blocked
237 237 # by the GIL, which is accessed by libzmq when freeing zero-copy messages
238 238 hb_ctx = zmq.Context()
239 239 self.heartbeat = Heartbeat(hb_ctx, (self.transport, self.ip, self.hb_port))
240 240 self.hb_port = self.heartbeat.port
241 241 self.log.debug("Heartbeat REP Channel on port: %i" % self.hb_port)
242 242 self.heartbeat.start()
243 243
244 244 def log_connection_info(self):
245 245 """display connection info, and store ports"""
246 246 basename = os.path.basename(self.connection_file)
247 247 if basename == self.connection_file or \
248 248 os.path.dirname(self.connection_file) == self.profile_dir.security_dir:
249 249 # use shortname
250 250 tail = basename
251 251 if self.profile != 'default':
252 252 tail += " --profile %s" % self.profile
253 253 else:
254 254 tail = self.connection_file
255 255 lines = [
256 256 "To connect another client to this kernel, use:",
257 257 " --existing %s" % tail,
258 258 ]
259 259 # log connection info
260 260 # info-level, so often not shown.
261 261 # frontends should use the %connect_info magic
262 262 # to see the connection info
263 263 for line in lines:
264 264 self.log.info(line)
265 265 # also raw print to the terminal if no parent_handle (`ipython kernel`)
266 266 if not self.parent_handle:
267 267 io.rprint(_ctrl_c_message)
268 268 for line in lines:
269 269 io.rprint(line)
270 270
271 271 self.ports = dict(shell=self.shell_port, iopub=self.iopub_port,
272 272 stdin=self.stdin_port, hb=self.hb_port,
273 273 control=self.control_port)
274 274
275 275 def init_blackhole(self):
276 276 """redirects stdout/stderr to devnull if necessary"""
277 277 if self.no_stdout or self.no_stderr:
278 278 blackhole = open(os.devnull, 'w')
279 279 if self.no_stdout:
280 280 sys.stdout = sys.__stdout__ = blackhole
281 281 if self.no_stderr:
282 282 sys.stderr = sys.__stderr__ = blackhole
283 283
284 284 def init_io(self):
285 285 """Redirect input streams and set a display hook."""
286 286 if self.outstream_class:
287 287 outstream_factory = import_item(str(self.outstream_class))
288 288 sys.stdout = outstream_factory(self.session, self.iopub_socket, u'stdout')
289 289 sys.stderr = outstream_factory(self.session, self.iopub_socket, u'stderr')
290 290 if self.displayhook_class:
291 291 displayhook_factory = import_item(str(self.displayhook_class))
292 292 sys.displayhook = displayhook_factory(self.session, self.iopub_socket)
293 293
294 294 def init_signal(self):
295 295 signal.signal(signal.SIGINT, signal.SIG_IGN)
296 296
297 297 def init_kernel(self):
298 298 """Create the Kernel object itself"""
299 299 shell_stream = ZMQStream(self.shell_socket)
300 300 control_stream = ZMQStream(self.control_socket)
301 301
302 302 kernel_factory = self.kernel_class.instance
303 303
304 304 kernel = kernel_factory(parent=self, session=self.session,
305 305 shell_streams=[shell_stream, control_stream],
306 306 iopub_socket=self.iopub_socket,
307 307 stdin_socket=self.stdin_socket,
308 308 log=self.log,
309 309 profile_dir=self.profile_dir,
310 310 user_ns=self.user_ns,
311 311 )
312 312 kernel.record_ports(self.ports)
313 313 self.kernel = kernel
314 314
315 315 def init_gui_pylab(self):
316 316 """Enable GUI event loop integration, taking pylab into account."""
317 317
318 318 # Provide a wrapper for :meth:`InteractiveShellApp.init_gui_pylab`
319 319 # to ensure that any exception is printed straight to stderr.
320 320 # Normally _showtraceback associates the reply with an execution,
321 321 # which means frontends will never draw it, as this exception
322 322 # is not associated with any execute request.
323 323
324 324 shell = self.shell
325 325 _showtraceback = shell._showtraceback
326 326 try:
327 327 # replace error-sending traceback with stderr
328 328 def print_tb(etype, evalue, stb):
329 329 print ("GUI event loop or pylab initialization failed",
330 330 file=io.stderr)
331 331 print (shell.InteractiveTB.stb2text(stb), file=io.stderr)
332 332 shell._showtraceback = print_tb
333 333 InteractiveShellApp.init_gui_pylab(self)
334 334 finally:
335 335 shell._showtraceback = _showtraceback
336 336
337 337 def init_shell(self):
338 338 self.shell = getattr(self.kernel, 'shell', None)
339 339 if self.shell:
340 340 self.shell.configurables.append(self)
341 341
342 342 @catch_config_error
343 343 def initialize(self, argv=None):
344 344 super(IPKernelApp, self).initialize(argv)
345 345 self.init_blackhole()
346 346 self.init_connection_file()
347 347 self.init_poller()
348 348 self.init_sockets()
349 349 self.init_heartbeat()
350 350 # writing/displaying connection info must be *after* init_sockets/heartbeat
351 351 self.log_connection_info()
352 352 self.write_connection_file()
353 353 self.init_io()
354 354 self.init_signal()
355 355 self.init_kernel()
356 356 # shell init steps
357 357 self.init_path()
358 358 self.init_shell()
359 359 if self.shell:
360 360 self.init_gui_pylab()
361 361 self.init_extensions()
362 362 self.init_code()
363 363 # flush stdout/stderr, so that anything written to these streams during
364 364 # initialization do not get associated with the first execution request
365 365 sys.stdout.flush()
366 366 sys.stderr.flush()
367 367
368 368 def start(self):
369 369 if self.poller is not None:
370 370 self.poller.start()
371 371 self.kernel.start()
372 372 try:
373 373 ioloop.IOLoop.instance().start()
374 374 except KeyboardInterrupt:
375 375 pass
376 376
377 377 launch_new_instance = IPKernelApp.launch_instance
378 378
379 379 def main():
380 380 """Run an IPKernel as an application"""
381 381 app = IPKernelApp.instance()
382 382 app.initialize()
383 383 app.start()
384 384
385 385
386 386 if __name__ == '__main__':
387 387 main()
@@ -1,701 +1,701 b''
1 1 """Base class for a kernel that talks to frontends over 0MQ."""
2 2
3 3 # Copyright (c) IPython Development Team.
4 4 # Distributed under the terms of the Modified BSD License.
5 5
6 6 from __future__ import print_function
7 7
8 8 import sys
9 9 import time
10 10 import logging
11 11 import uuid
12 12
13 13 from datetime import datetime
14 14 from signal import (
15 15 signal, default_int_handler, SIGINT
16 16 )
17 17
18 18 import zmq
19 19 from zmq.eventloop import ioloop
20 20 from zmq.eventloop.zmqstream import ZMQStream
21 21
22 22 from IPython.config.configurable import SingletonConfigurable
23 23 from IPython.core.error import StdinNotImplementedError
24 24 from IPython.core import release
25 25 from IPython.utils import py3compat
26 26 from IPython.utils.py3compat import unicode_type, string_types
27 27 from IPython.utils.jsonutil import json_clean
28 28 from IPython.utils.traitlets import (
29 29 Any, Instance, Float, Dict, List, Set, Integer, Unicode, Bool,
30 30 )
31 31
32 32 from .session import Session
33 33
34 34
35 35 class Kernel(SingletonConfigurable):
36 36
37 37 #---------------------------------------------------------------------------
38 38 # Kernel interface
39 39 #---------------------------------------------------------------------------
40 40
41 41 # attribute to override with a GUI
42 42 eventloop = Any(None)
43 43 def _eventloop_changed(self, name, old, new):
44 44 """schedule call to eventloop from IOLoop"""
45 45 loop = ioloop.IOLoop.instance()
46 46 loop.add_callback(self.enter_eventloop)
47 47
48 session = Instance(Session)
49 profile_dir = Instance('IPython.core.profiledir.ProfileDir')
48 session = Instance(Session, allow_none=True)
49 profile_dir = Instance('IPython.core.profiledir.ProfileDir', allow_none=True)
50 50 shell_streams = List()
51 control_stream = Instance(ZMQStream)
52 iopub_socket = Instance(zmq.Socket)
53 stdin_socket = Instance(zmq.Socket)
54 log = Instance(logging.Logger)
51 control_stream = Instance(ZMQStream, allow_none=True)
52 iopub_socket = Instance(zmq.Socket, allow_none=True)
53 stdin_socket = Instance(zmq.Socket, allow_none=True)
54 log = Instance(logging.Logger, allow_none=True)
55 55
56 56 # identities:
57 57 int_id = Integer(-1)
58 58 ident = Unicode()
59 59
60 60 def _ident_default(self):
61 61 return unicode_type(uuid.uuid4())
62 62
63 63 # This should be overridden by wrapper kernels that implement any real
64 64 # language.
65 65 language_info = {}
66 66
67 67 # any links that should go in the help menu
68 68 help_links = List()
69 69
70 70 # Private interface
71 71
72 72 _darwin_app_nap = Bool(True, config=True,
73 73 help="""Whether to use appnope for compatiblity with OS X App Nap.
74 74
75 75 Only affects OS X >= 10.9.
76 76 """
77 77 )
78 78
79 79 # track associations with current request
80 80 _allow_stdin = Bool(False)
81 81 _parent_header = Dict()
82 82 _parent_ident = Any(b'')
83 83 # Time to sleep after flushing the stdout/err buffers in each execute
84 84 # cycle. While this introduces a hard limit on the minimal latency of the
85 85 # execute cycle, it helps prevent output synchronization problems for
86 86 # clients.
87 87 # Units are in seconds. The minimum zmq latency on local host is probably
88 88 # ~150 microseconds, set this to 500us for now. We may need to increase it
89 89 # a little if it's not enough after more interactive testing.
90 90 _execute_sleep = Float(0.0005, config=True)
91 91
92 92 # Frequency of the kernel's event loop.
93 93 # Units are in seconds, kernel subclasses for GUI toolkits may need to
94 94 # adapt to milliseconds.
95 95 _poll_interval = Float(0.05, config=True)
96 96
97 97 # If the shutdown was requested over the network, we leave here the
98 98 # necessary reply message so it can be sent by our registered atexit
99 99 # handler. This ensures that the reply is only sent to clients truly at
100 100 # the end of our shutdown process (which happens after the underlying
101 101 # IPython shell's own shutdown).
102 102 _shutdown_message = None
103 103
104 104 # This is a dict of port number that the kernel is listening on. It is set
105 105 # by record_ports and used by connect_request.
106 106 _recorded_ports = Dict()
107 107
108 108 # set of aborted msg_ids
109 109 aborted = Set()
110 110
111 111 # Track execution count here. For IPython, we override this to use the
112 112 # execution count we store in the shell.
113 113 execution_count = 0
114 114
115 115
116 116 def __init__(self, **kwargs):
117 117 super(Kernel, self).__init__(**kwargs)
118 118
119 119 # Build dict of handlers for message types
120 120 msg_types = [ 'execute_request', 'complete_request',
121 121 'inspect_request', 'history_request',
122 122 'kernel_info_request',
123 123 'connect_request', 'shutdown_request',
124 124 'apply_request', 'is_complete_request',
125 125 ]
126 126 self.shell_handlers = {}
127 127 for msg_type in msg_types:
128 128 self.shell_handlers[msg_type] = getattr(self, msg_type)
129 129
130 130 control_msg_types = msg_types + [ 'clear_request', 'abort_request' ]
131 131 self.control_handlers = {}
132 132 for msg_type in control_msg_types:
133 133 self.control_handlers[msg_type] = getattr(self, msg_type)
134 134
135 135
136 136 def dispatch_control(self, msg):
137 137 """dispatch control requests"""
138 138 idents,msg = self.session.feed_identities(msg, copy=False)
139 139 try:
140 140 msg = self.session.deserialize(msg, content=True, copy=False)
141 141 except:
142 142 self.log.error("Invalid Control Message", exc_info=True)
143 143 return
144 144
145 145 self.log.debug("Control received: %s", msg)
146 146
147 147 # Set the parent message for side effects.
148 148 self.set_parent(idents, msg)
149 149 self._publish_status(u'busy')
150 150
151 151 header = msg['header']
152 152 msg_type = header['msg_type']
153 153
154 154 handler = self.control_handlers.get(msg_type, None)
155 155 if handler is None:
156 156 self.log.error("UNKNOWN CONTROL MESSAGE TYPE: %r", msg_type)
157 157 else:
158 158 try:
159 159 handler(self.control_stream, idents, msg)
160 160 except Exception:
161 161 self.log.error("Exception in control handler:", exc_info=True)
162 162
163 163 sys.stdout.flush()
164 164 sys.stderr.flush()
165 165 self._publish_status(u'idle')
166 166
167 167 def dispatch_shell(self, stream, msg):
168 168 """dispatch shell requests"""
169 169 # flush control requests first
170 170 if self.control_stream:
171 171 self.control_stream.flush()
172 172
173 173 idents,msg = self.session.feed_identities(msg, copy=False)
174 174 try:
175 175 msg = self.session.deserialize(msg, content=True, copy=False)
176 176 except:
177 177 self.log.error("Invalid Message", exc_info=True)
178 178 return
179 179
180 180 # Set the parent message for side effects.
181 181 self.set_parent(idents, msg)
182 182 self._publish_status(u'busy')
183 183
184 184 header = msg['header']
185 185 msg_id = header['msg_id']
186 186 msg_type = msg['header']['msg_type']
187 187
188 188 # Print some info about this message and leave a '--->' marker, so it's
189 189 # easier to trace visually the message chain when debugging. Each
190 190 # handler prints its message at the end.
191 191 self.log.debug('\n*** MESSAGE TYPE:%s***', msg_type)
192 192 self.log.debug(' Content: %s\n --->\n ', msg['content'])
193 193
194 194 if msg_id in self.aborted:
195 195 self.aborted.remove(msg_id)
196 196 # is it safe to assume a msg_id will not be resubmitted?
197 197 reply_type = msg_type.split('_')[0] + '_reply'
198 198 status = {'status' : 'aborted'}
199 199 md = {'engine' : self.ident}
200 200 md.update(status)
201 201 self.session.send(stream, reply_type, metadata=md,
202 202 content=status, parent=msg, ident=idents)
203 203 return
204 204
205 205 handler = self.shell_handlers.get(msg_type, None)
206 206 if handler is None:
207 207 self.log.error("UNKNOWN MESSAGE TYPE: %r", msg_type)
208 208 else:
209 209 # ensure default_int_handler during handler call
210 210 sig = signal(SIGINT, default_int_handler)
211 211 self.log.debug("%s: %s", msg_type, msg)
212 212 try:
213 213 handler(stream, idents, msg)
214 214 except Exception:
215 215 self.log.error("Exception in message handler:", exc_info=True)
216 216 finally:
217 217 signal(SIGINT, sig)
218 218
219 219 sys.stdout.flush()
220 220 sys.stderr.flush()
221 221 self._publish_status(u'idle')
222 222
223 223 def enter_eventloop(self):
224 224 """enter eventloop"""
225 225 self.log.info("entering eventloop %s", self.eventloop)
226 226 for stream in self.shell_streams:
227 227 # flush any pending replies,
228 228 # which may be skipped by entering the eventloop
229 229 stream.flush(zmq.POLLOUT)
230 230 # restore default_int_handler
231 231 signal(SIGINT, default_int_handler)
232 232 while self.eventloop is not None:
233 233 try:
234 234 self.eventloop(self)
235 235 except KeyboardInterrupt:
236 236 # Ctrl-C shouldn't crash the kernel
237 237 self.log.error("KeyboardInterrupt caught in kernel")
238 238 continue
239 239 else:
240 240 # eventloop exited cleanly, this means we should stop (right?)
241 241 self.eventloop = None
242 242 break
243 243 self.log.info("exiting eventloop")
244 244
245 245 def start(self):
246 246 """register dispatchers for streams"""
247 247 if self.control_stream:
248 248 self.control_stream.on_recv(self.dispatch_control, copy=False)
249 249
250 250 def make_dispatcher(stream):
251 251 def dispatcher(msg):
252 252 return self.dispatch_shell(stream, msg)
253 253 return dispatcher
254 254
255 255 for s in self.shell_streams:
256 256 s.on_recv(make_dispatcher(s), copy=False)
257 257
258 258 # publish idle status
259 259 self._publish_status('starting')
260 260
261 261 def do_one_iteration(self):
262 262 """step eventloop just once"""
263 263 if self.control_stream:
264 264 self.control_stream.flush()
265 265 for stream in self.shell_streams:
266 266 # handle at most one request per iteration
267 267 stream.flush(zmq.POLLIN, 1)
268 268 stream.flush(zmq.POLLOUT)
269 269
270 270
271 271 def record_ports(self, ports):
272 272 """Record the ports that this kernel is using.
273 273
274 274 The creator of the Kernel instance must call this methods if they
275 275 want the :meth:`connect_request` method to return the port numbers.
276 276 """
277 277 self._recorded_ports = ports
278 278
279 279 #---------------------------------------------------------------------------
280 280 # Kernel request handlers
281 281 #---------------------------------------------------------------------------
282 282
283 283 def _make_metadata(self, other=None):
284 284 """init metadata dict, for execute/apply_reply"""
285 285 new_md = {
286 286 'dependencies_met' : True,
287 287 'engine' : self.ident,
288 288 'started': datetime.now(),
289 289 }
290 290 if other:
291 291 new_md.update(other)
292 292 return new_md
293 293
294 294 def _publish_execute_input(self, code, parent, execution_count):
295 295 """Publish the code request on the iopub stream."""
296 296
297 297 self.session.send(self.iopub_socket, u'execute_input',
298 298 {u'code':code, u'execution_count': execution_count},
299 299 parent=parent, ident=self._topic('execute_input')
300 300 )
301 301
302 302 def _publish_status(self, status, parent=None):
303 303 """send status (busy/idle) on IOPub"""
304 304 self.session.send(self.iopub_socket,
305 305 u'status',
306 306 {u'execution_state': status},
307 307 parent=parent or self._parent_header,
308 308 ident=self._topic('status'),
309 309 )
310 310
311 311 def set_parent(self, ident, parent):
312 312 """Set the current parent_header
313 313
314 314 Side effects (IOPub messages) and replies are associated with
315 315 the request that caused them via the parent_header.
316 316
317 317 The parent identity is used to route input_request messages
318 318 on the stdin channel.
319 319 """
320 320 self._parent_ident = ident
321 321 self._parent_header = parent
322 322
323 323 def send_response(self, stream, msg_or_type, content=None, ident=None,
324 324 buffers=None, track=False, header=None, metadata=None):
325 325 """Send a response to the message we're currently processing.
326 326
327 327 This accepts all the parameters of :meth:`IPython.kernel.zmq.session.Session.send`
328 328 except ``parent``.
329 329
330 330 This relies on :meth:`set_parent` having been called for the current
331 331 message.
332 332 """
333 333 return self.session.send(stream, msg_or_type, content, self._parent_header,
334 334 ident, buffers, track, header, metadata)
335 335
336 336 def execute_request(self, stream, ident, parent):
337 337 """handle an execute_request"""
338 338
339 339 try:
340 340 content = parent[u'content']
341 341 code = py3compat.cast_unicode_py2(content[u'code'])
342 342 silent = content[u'silent']
343 343 store_history = content.get(u'store_history', not silent)
344 344 user_expressions = content.get('user_expressions', {})
345 345 allow_stdin = content.get('allow_stdin', False)
346 346 except:
347 347 self.log.error("Got bad msg: ")
348 348 self.log.error("%s", parent)
349 349 return
350 350
351 351 stop_on_error = content.get('stop_on_error', True)
352 352
353 353 md = self._make_metadata(parent['metadata'])
354 354
355 355 # Re-broadcast our input for the benefit of listening clients, and
356 356 # start computing output
357 357 if not silent:
358 358 self.execution_count += 1
359 359 self._publish_execute_input(code, parent, self.execution_count)
360 360
361 361 reply_content = self.do_execute(code, silent, store_history,
362 362 user_expressions, allow_stdin)
363 363
364 364 # Flush output before sending the reply.
365 365 sys.stdout.flush()
366 366 sys.stderr.flush()
367 367 # FIXME: on rare occasions, the flush doesn't seem to make it to the
368 368 # clients... This seems to mitigate the problem, but we definitely need
369 369 # to better understand what's going on.
370 370 if self._execute_sleep:
371 371 time.sleep(self._execute_sleep)
372 372
373 373 # Send the reply.
374 374 reply_content = json_clean(reply_content)
375 375
376 376 md['status'] = reply_content['status']
377 377 if reply_content['status'] == 'error' and \
378 378 reply_content['ename'] == 'UnmetDependency':
379 379 md['dependencies_met'] = False
380 380
381 381 reply_msg = self.session.send(stream, u'execute_reply',
382 382 reply_content, parent, metadata=md,
383 383 ident=ident)
384 384
385 385 self.log.debug("%s", reply_msg)
386 386
387 387 if not silent and reply_msg['content']['status'] == u'error' and stop_on_error:
388 388 self._abort_queues()
389 389
390 390 def do_execute(self, code, silent, store_history=True,
391 391 user_expressions=None, allow_stdin=False):
392 392 """Execute user code. Must be overridden by subclasses.
393 393 """
394 394 raise NotImplementedError
395 395
396 396 def complete_request(self, stream, ident, parent):
397 397 content = parent['content']
398 398 code = content['code']
399 399 cursor_pos = content['cursor_pos']
400 400
401 401 matches = self.do_complete(code, cursor_pos)
402 402 matches = json_clean(matches)
403 403 completion_msg = self.session.send(stream, 'complete_reply',
404 404 matches, parent, ident)
405 405 self.log.debug("%s", completion_msg)
406 406
407 407 def do_complete(self, code, cursor_pos):
408 408 """Override in subclasses to find completions.
409 409 """
410 410 return {'matches' : [],
411 411 'cursor_end' : cursor_pos,
412 412 'cursor_start' : cursor_pos,
413 413 'metadata' : {},
414 414 'status' : 'ok'}
415 415
416 416 def inspect_request(self, stream, ident, parent):
417 417 content = parent['content']
418 418
419 419 reply_content = self.do_inspect(content['code'], content['cursor_pos'],
420 420 content.get('detail_level', 0))
421 421 # Before we send this object over, we scrub it for JSON usage
422 422 reply_content = json_clean(reply_content)
423 423 msg = self.session.send(stream, 'inspect_reply',
424 424 reply_content, parent, ident)
425 425 self.log.debug("%s", msg)
426 426
427 427 def do_inspect(self, code, cursor_pos, detail_level=0):
428 428 """Override in subclasses to allow introspection.
429 429 """
430 430 return {'status': 'ok', 'data':{}, 'metadata':{}, 'found':False}
431 431
432 432 def history_request(self, stream, ident, parent):
433 433 content = parent['content']
434 434
435 435 reply_content = self.do_history(**content)
436 436
437 437 reply_content = json_clean(reply_content)
438 438 msg = self.session.send(stream, 'history_reply',
439 439 reply_content, parent, ident)
440 440 self.log.debug("%s", msg)
441 441
442 442 def do_history(self, hist_access_type, output, raw, session=None, start=None,
443 443 stop=None, n=None, pattern=None, unique=False):
444 444 """Override in subclasses to access history.
445 445 """
446 446 return {'history': []}
447 447
448 448 def connect_request(self, stream, ident, parent):
449 449 if self._recorded_ports is not None:
450 450 content = self._recorded_ports.copy()
451 451 else:
452 452 content = {}
453 453 msg = self.session.send(stream, 'connect_reply',
454 454 content, parent, ident)
455 455 self.log.debug("%s", msg)
456 456
457 457 @property
458 458 def kernel_info(self):
459 459 return {
460 460 'protocol_version': release.kernel_protocol_version,
461 461 'implementation': self.implementation,
462 462 'implementation_version': self.implementation_version,
463 463 'language_info': self.language_info,
464 464 'banner': self.banner,
465 465 'help_links': self.help_links,
466 466 }
467 467
468 468 def kernel_info_request(self, stream, ident, parent):
469 469 msg = self.session.send(stream, 'kernel_info_reply',
470 470 self.kernel_info, parent, ident)
471 471 self.log.debug("%s", msg)
472 472
473 473 def shutdown_request(self, stream, ident, parent):
474 474 content = self.do_shutdown(parent['content']['restart'])
475 475 self.session.send(stream, u'shutdown_reply', content, parent, ident=ident)
476 476 # same content, but different msg_id for broadcasting on IOPub
477 477 self._shutdown_message = self.session.msg(u'shutdown_reply',
478 478 content, parent
479 479 )
480 480
481 481 self._at_shutdown()
482 482 # call sys.exit after a short delay
483 483 loop = ioloop.IOLoop.instance()
484 484 loop.add_timeout(time.time()+0.1, loop.stop)
485 485
486 486 def do_shutdown(self, restart):
487 487 """Override in subclasses to do things when the frontend shuts down the
488 488 kernel.
489 489 """
490 490 return {'status': 'ok', 'restart': restart}
491 491
492 492 def is_complete_request(self, stream, ident, parent):
493 493 content = parent['content']
494 494 code = content['code']
495 495
496 496 reply_content = self.do_is_complete(code)
497 497 reply_content = json_clean(reply_content)
498 498 reply_msg = self.session.send(stream, 'is_complete_reply',
499 499 reply_content, parent, ident)
500 500 self.log.debug("%s", reply_msg)
501 501
502 502 def do_is_complete(self, code):
503 503 """Override in subclasses to find completions.
504 504 """
505 505 return {'status' : 'unknown',
506 506 }
507 507
508 508 #---------------------------------------------------------------------------
509 509 # Engine methods
510 510 #---------------------------------------------------------------------------
511 511
512 512 def apply_request(self, stream, ident, parent):
513 513 try:
514 514 content = parent[u'content']
515 515 bufs = parent[u'buffers']
516 516 msg_id = parent['header']['msg_id']
517 517 except:
518 518 self.log.error("Got bad msg: %s", parent, exc_info=True)
519 519 return
520 520
521 521 md = self._make_metadata(parent['metadata'])
522 522
523 523 reply_content, result_buf = self.do_apply(content, bufs, msg_id, md)
524 524
525 525 # put 'ok'/'error' status in header, for scheduler introspection:
526 526 md['status'] = reply_content['status']
527 527
528 528 # flush i/o
529 529 sys.stdout.flush()
530 530 sys.stderr.flush()
531 531
532 532 self.session.send(stream, u'apply_reply', reply_content,
533 533 parent=parent, ident=ident,buffers=result_buf, metadata=md)
534 534
535 535 def do_apply(self, content, bufs, msg_id, reply_metadata):
536 536 """Override in subclasses to support the IPython parallel framework.
537 537 """
538 538 raise NotImplementedError
539 539
540 540 #---------------------------------------------------------------------------
541 541 # Control messages
542 542 #---------------------------------------------------------------------------
543 543
544 544 def abort_request(self, stream, ident, parent):
545 545 """abort a specific msg by id"""
546 546 msg_ids = parent['content'].get('msg_ids', None)
547 547 if isinstance(msg_ids, string_types):
548 548 msg_ids = [msg_ids]
549 549 if not msg_ids:
550 550 self._abort_queues()
551 551 for mid in msg_ids:
552 552 self.aborted.add(str(mid))
553 553
554 554 content = dict(status='ok')
555 555 reply_msg = self.session.send(stream, 'abort_reply', content=content,
556 556 parent=parent, ident=ident)
557 557 self.log.debug("%s", reply_msg)
558 558
559 559 def clear_request(self, stream, idents, parent):
560 560 """Clear our namespace."""
561 561 content = self.do_clear()
562 562 self.session.send(stream, 'clear_reply', ident=idents, parent=parent,
563 563 content = content)
564 564
565 565 def do_clear(self):
566 566 """Override in subclasses to clear the namespace
567 567
568 568 This is only required for IPython.parallel.
569 569 """
570 570 raise NotImplementedError
571 571
572 572 #---------------------------------------------------------------------------
573 573 # Protected interface
574 574 #---------------------------------------------------------------------------
575 575
576 576 def _topic(self, topic):
577 577 """prefixed topic for IOPub messages"""
578 578 if self.int_id >= 0:
579 579 base = "engine.%i" % self.int_id
580 580 else:
581 581 base = "kernel.%s" % self.ident
582 582
583 583 return py3compat.cast_bytes("%s.%s" % (base, topic))
584 584
585 585 def _abort_queues(self):
586 586 for stream in self.shell_streams:
587 587 if stream:
588 588 self._abort_queue(stream)
589 589
590 590 def _abort_queue(self, stream):
591 591 poller = zmq.Poller()
592 592 poller.register(stream.socket, zmq.POLLIN)
593 593 while True:
594 594 idents,msg = self.session.recv(stream, zmq.NOBLOCK, content=True)
595 595 if msg is None:
596 596 return
597 597
598 598 self.log.info("Aborting:")
599 599 self.log.info("%s", msg)
600 600 msg_type = msg['header']['msg_type']
601 601 reply_type = msg_type.split('_')[0] + '_reply'
602 602
603 603 status = {'status' : 'aborted'}
604 604 md = {'engine' : self.ident}
605 605 md.update(status)
606 606 reply_msg = self.session.send(stream, reply_type, metadata=md,
607 607 content=status, parent=msg, ident=idents)
608 608 self.log.debug("%s", reply_msg)
609 609 # We need to wait a bit for requests to come in. This can probably
610 610 # be set shorter for true asynchronous clients.
611 611 poller.poll(50)
612 612
613 613
614 614 def _no_raw_input(self):
615 615 """Raise StdinNotImplentedError if active frontend doesn't support
616 616 stdin."""
617 617 raise StdinNotImplementedError("raw_input was called, but this "
618 618 "frontend does not support stdin.")
619 619
620 620 def getpass(self, prompt=''):
621 621 """Forward getpass to frontends
622 622
623 623 Raises
624 624 ------
625 625 StdinNotImplentedError if active frontend doesn't support stdin.
626 626 """
627 627 if not self._allow_stdin:
628 628 raise StdinNotImplementedError(
629 629 "getpass was called, but this frontend does not support input requests."
630 630 )
631 631 return self._input_request(prompt,
632 632 self._parent_ident,
633 633 self._parent_header,
634 634 password=True,
635 635 )
636 636
637 637 def raw_input(self, prompt=''):
638 638 """Forward raw_input to frontends
639 639
640 640 Raises
641 641 ------
642 642 StdinNotImplentedError if active frontend doesn't support stdin.
643 643 """
644 644 if not self._allow_stdin:
645 645 raise StdinNotImplementedError(
646 646 "raw_input was called, but this frontend does not support input requests."
647 647 )
648 648 return self._input_request(prompt,
649 649 self._parent_ident,
650 650 self._parent_header,
651 651 password=False,
652 652 )
653 653
654 654 def _input_request(self, prompt, ident, parent, password=False):
655 655 # Flush output before making the request.
656 656 sys.stderr.flush()
657 657 sys.stdout.flush()
658 658 # flush the stdin socket, to purge stale replies
659 659 while True:
660 660 try:
661 661 self.stdin_socket.recv_multipart(zmq.NOBLOCK)
662 662 except zmq.ZMQError as e:
663 663 if e.errno == zmq.EAGAIN:
664 664 break
665 665 else:
666 666 raise
667 667
668 668 # Send the input request.
669 669 content = json_clean(dict(prompt=prompt, password=password))
670 670 self.session.send(self.stdin_socket, u'input_request', content, parent,
671 671 ident=ident)
672 672
673 673 # Await a response.
674 674 while True:
675 675 try:
676 676 ident, reply = self.session.recv(self.stdin_socket, 0)
677 677 except Exception:
678 678 self.log.warn("Invalid Message:", exc_info=True)
679 679 except KeyboardInterrupt:
680 680 # re-raise KeyboardInterrupt, to truncate traceback
681 681 raise KeyboardInterrupt
682 682 else:
683 683 break
684 684 try:
685 685 value = py3compat.unicode_to_str(reply['content']['value'])
686 686 except:
687 687 self.log.error("Bad input_reply: %s", parent)
688 688 value = ''
689 689 if value == '\x04':
690 690 # EOF
691 691 raise EOFError
692 692 return value
693 693
694 694 def _at_shutdown(self):
695 695 """Actions taken at shutdown by the kernel, called by python's atexit.
696 696 """
697 697 # io.rprint("Kernel at_shutdown") # dbg
698 698 if self._shutdown_message is not None:
699 699 self.session.send(self.iopub_socket, self._shutdown_message, ident=self._topic('shutdown'))
700 700 self.log.debug("%s", self._shutdown_message)
701 701 [ s.flush(zmq.POLLOUT) for s in self.shell_streams ]
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