##// END OF EJS Templates
Misc. typo fixes...
luzpaz -
Show More
@@ -1,2045 +1,2045 b''
1 1 """Completion for IPython.
2 2
3 3 This module started as fork of the rlcompleter module in the Python standard
4 4 library. The original enhancements made to rlcompleter have been sent
5 5 upstream and were accepted as of Python 2.3,
6 6
7 7 This module now support a wide variety of completion mechanism both available
8 8 for normal classic Python code, as well as completer for IPython specific
9 9 Syntax like magics.
10 10
11 11 Latex and Unicode completion
12 12 ============================
13 13
14 14 IPython and compatible frontends not only can complete your code, but can help
15 15 you to input a wide range of characters. In particular we allow you to insert
16 16 a unicode character using the tab completion mechanism.
17 17
18 18 Forward latex/unicode completion
19 19 --------------------------------
20 20
21 21 Forward completion allows you to easily type a unicode character using its latex
22 22 name, or unicode long description. To do so type a backslash follow by the
23 23 relevant name and press tab:
24 24
25 25
26 26 Using latex completion:
27 27
28 28 .. code::
29 29
30 30 \\alpha<tab>
31 31 α
32 32
33 33 or using unicode completion:
34 34
35 35
36 36 .. code::
37 37
38 38 \\greek small letter alpha<tab>
39 39 α
40 40
41 41
42 42 Only valid Python identifiers will complete. Combining characters (like arrow or
43 43 dots) are also available, unlike latex they need to be put after the their
44 44 counterpart that is to say, `F\\\\vec<tab>` is correct, not `\\\\vec<tab>F`.
45 45
46 46 Some browsers are known to display combining characters incorrectly.
47 47
48 48 Backward latex completion
49 49 -------------------------
50 50
51 51 It is sometime challenging to know how to type a character, if you are using
52 52 IPython, or any compatible frontend you can prepend backslash to the character
53 53 and press `<tab>` to expand it to its latex form.
54 54
55 55 .. code::
56 56
57 57 \\α<tab>
58 58 \\alpha
59 59
60 60
61 61 Both forward and backward completions can be deactivated by setting the
62 62 ``Completer.backslash_combining_completions`` option to ``False``.
63 63
64 64
65 65 Experimental
66 66 ============
67 67
68 68 Starting with IPython 6.0, this module can make use of the Jedi library to
69 69 generate completions both using static analysis of the code, and dynamically
70 70 inspecting multiple namespaces. The APIs attached to this new mechanism is
71 71 unstable and will raise unless use in an :any:`provisionalcompleter` context
72 72 manager.
73 73
74 74 You will find that the following are experimental:
75 75
76 76 - :any:`provisionalcompleter`
77 77 - :any:`IPCompleter.completions`
78 78 - :any:`Completion`
79 79 - :any:`rectify_completions`
80 80
81 81 .. note::
82 82
83 83 better name for :any:`rectify_completions` ?
84 84
85 85 We welcome any feedback on these new API, and we also encourage you to try this
86 86 module in debug mode (start IPython with ``--Completer.debug=True``) in order
87 87 to have extra logging information is :any:`jedi` is crashing, or if current
88 88 IPython completer pending deprecations are returning results not yet handled
89 89 by :any:`jedi`
90 90
91 91 Using Jedi for tab completion allow snippets like the following to work without
92 92 having to execute any code:
93 93
94 94 >>> myvar = ['hello', 42]
95 95 ... myvar[1].bi<tab>
96 96
97 97 Tab completion will be able to infer that ``myvar[1]`` is a real number without
98 98 executing any code unlike the previously available ``IPCompleter.greedy``
99 99 option.
100 100
101 101 Be sure to update :any:`jedi` to the latest stable version or to try the
102 102 current development version to get better completions.
103 103 """
104 104
105 105
106 106 # Copyright (c) IPython Development Team.
107 107 # Distributed under the terms of the Modified BSD License.
108 108 #
109 109 # Some of this code originated from rlcompleter in the Python standard library
110 110 # Copyright (C) 2001 Python Software Foundation, www.python.org
111 111
112 112
113 113 import __main__
114 114 import builtins as builtin_mod
115 115 import glob
116 116 import time
117 117 import inspect
118 118 import itertools
119 119 import keyword
120 120 import os
121 121 import re
122 122 import sys
123 123 import unicodedata
124 124 import string
125 125 import warnings
126 126
127 127 from contextlib import contextmanager
128 128 from importlib import import_module
129 129 from typing import Iterator, List, Tuple, Iterable, Union
130 130 from types import SimpleNamespace
131 131
132 132 from traitlets.config.configurable import Configurable
133 133 from IPython.core.error import TryNext
134 134 from IPython.core.inputsplitter import ESC_MAGIC
135 135 from IPython.core.latex_symbols import latex_symbols, reverse_latex_symbol
136 136 from IPython.core.oinspect import InspectColors
137 137 from IPython.utils import generics
138 138 from IPython.utils.dir2 import dir2, get_real_method
139 139 from IPython.utils.process import arg_split
140 140 from traitlets import Bool, Enum, observe, Int
141 141
142 142 # skip module docstests
143 143 skip_doctest = True
144 144
145 145 try:
146 146 import jedi
147 147 import jedi.api.helpers
148 148 import jedi.api.classes
149 149 JEDI_INSTALLED = True
150 150 except ImportError:
151 151 JEDI_INSTALLED = False
152 152 #-----------------------------------------------------------------------------
153 153 # Globals
154 154 #-----------------------------------------------------------------------------
155 155
156 156 # Public API
157 157 __all__ = ['Completer','IPCompleter']
158 158
159 159 if sys.platform == 'win32':
160 160 PROTECTABLES = ' '
161 161 else:
162 162 PROTECTABLES = ' ()[]{}?=\\|;:\'#*"^&'
163 163
164 164 # Protect against returning an enormous number of completions which the frontend
165 165 # may have trouble processing.
166 166 MATCHES_LIMIT = 500
167 167
168 168 _deprecation_readline_sentinel = object()
169 169
170 170
171 171 class ProvisionalCompleterWarning(FutureWarning):
172 172 """
173 173 Exception raise by an experimental feature in this module.
174 174
175 175 Wrap code in :any:`provisionalcompleter` context manager if you
176 176 are certain you want to use an unstable feature.
177 177 """
178 178 pass
179 179
180 180 warnings.filterwarnings('error', category=ProvisionalCompleterWarning)
181 181
182 182 @contextmanager
183 183 def provisionalcompleter(action='ignore'):
184 184 """
185 185
186 186
187 187 This contest manager has to be used in any place where unstable completer
188 188 behavior and API may be called.
189 189
190 190 >>> with provisionalcompleter():
191 191 ... completer.do_experimetal_things() # works
192 192
193 193 >>> completer.do_experimental_things() # raises.
194 194
195 195 .. note:: Unstable
196 196
197 197 By using this context manager you agree that the API in use may change
198 198 without warning, and that you won't complain if they do so.
199 199
200 200 You also understand that if the API is not to you liking you should report
201 201 a bug to explain your use case upstream and improve the API and will loose
202 202 credibility if you complain after the API is make stable.
203 203
204 204 We'll be happy to get your feedback , feature request and improvement on
205 205 any of the unstable APIs !
206 206 """
207 207 with warnings.catch_warnings():
208 208 warnings.filterwarnings(action, category=ProvisionalCompleterWarning)
209 209 yield
210 210
211 211
212 212 def has_open_quotes(s):
213 213 """Return whether a string has open quotes.
214 214
215 215 This simply counts whether the number of quote characters of either type in
216 216 the string is odd.
217 217
218 218 Returns
219 219 -------
220 220 If there is an open quote, the quote character is returned. Else, return
221 221 False.
222 222 """
223 223 # We check " first, then ', so complex cases with nested quotes will get
224 224 # the " to take precedence.
225 225 if s.count('"') % 2:
226 226 return '"'
227 227 elif s.count("'") % 2:
228 228 return "'"
229 229 else:
230 230 return False
231 231
232 232
233 233 def protect_filename(s, protectables=PROTECTABLES):
234 234 """Escape a string to protect certain characters."""
235 235 if set(s) & set(protectables):
236 236 if sys.platform == "win32":
237 237 return '"' + s + '"'
238 238 else:
239 239 return "".join(("\\" + c if c in protectables else c) for c in s)
240 240 else:
241 241 return s
242 242
243 243
244 244 def expand_user(path:str) -> Tuple[str, bool, str]:
245 245 """Expand ``~``-style usernames in strings.
246 246
247 247 This is similar to :func:`os.path.expanduser`, but it computes and returns
248 248 extra information that will be useful if the input was being used in
249 249 computing completions, and you wish to return the completions with the
250 250 original '~' instead of its expanded value.
251 251
252 252 Parameters
253 253 ----------
254 254 path : str
255 255 String to be expanded. If no ~ is present, the output is the same as the
256 256 input.
257 257
258 258 Returns
259 259 -------
260 260 newpath : str
261 261 Result of ~ expansion in the input path.
262 262 tilde_expand : bool
263 263 Whether any expansion was performed or not.
264 264 tilde_val : str
265 265 The value that ~ was replaced with.
266 266 """
267 267 # Default values
268 268 tilde_expand = False
269 269 tilde_val = ''
270 270 newpath = path
271 271
272 272 if path.startswith('~'):
273 273 tilde_expand = True
274 274 rest = len(path)-1
275 275 newpath = os.path.expanduser(path)
276 276 if rest:
277 277 tilde_val = newpath[:-rest]
278 278 else:
279 279 tilde_val = newpath
280 280
281 281 return newpath, tilde_expand, tilde_val
282 282
283 283
284 284 def compress_user(path:str, tilde_expand:bool, tilde_val:str) -> str:
285 285 """Does the opposite of expand_user, with its outputs.
286 286 """
287 287 if tilde_expand:
288 288 return path.replace(tilde_val, '~')
289 289 else:
290 290 return path
291 291
292 292
293 293 def completions_sorting_key(word):
294 294 """key for sorting completions
295 295
296 296 This does several things:
297 297
298 298 - Demote any completions starting with underscores to the end
299 299 - Insert any %magic and %%cellmagic completions in the alphabetical order
300 300 by their name
301 301 """
302 302 prio1, prio2 = 0, 0
303 303
304 304 if word.startswith('__'):
305 305 prio1 = 2
306 306 elif word.startswith('_'):
307 307 prio1 = 1
308 308
309 309 if word.endswith('='):
310 310 prio1 = -1
311 311
312 312 if word.startswith('%%'):
313 313 # If there's another % in there, this is something else, so leave it alone
314 314 if not "%" in word[2:]:
315 315 word = word[2:]
316 316 prio2 = 2
317 317 elif word.startswith('%'):
318 318 if not "%" in word[1:]:
319 319 word = word[1:]
320 320 prio2 = 1
321 321
322 322 return prio1, word, prio2
323 323
324 324
325 325 class _FakeJediCompletion:
326 326 """
327 327 This is a workaround to communicate to the UI that Jedi has crashed and to
328 328 report a bug. Will be used only id :any:`IPCompleter.debug` is set to true.
329 329
330 330 Added in IPython 6.0 so should likely be removed for 7.0
331 331
332 332 """
333 333
334 334 def __init__(self, name):
335 335
336 336 self.name = name
337 337 self.complete = name
338 338 self.type = 'crashed'
339 339 self.name_with_symbols = name
340 340 self.signature = ''
341 341 self._origin = 'fake'
342 342
343 343 def __repr__(self):
344 344 return '<Fake completion object jedi has crashed>'
345 345
346 346
347 347 class Completion:
348 348 """
349 349 Completion object used and return by IPython completers.
350 350
351 351 .. warning:: Unstable
352 352
353 353 This function is unstable, API may change without warning.
354 354 It will also raise unless use in proper context manager.
355 355
356 356 This act as a middle ground :any:`Completion` object between the
357 357 :any:`jedi.api.classes.Completion` object and the Prompt Toolkit completion
358 358 object. While Jedi need a lot of information about evaluator and how the
359 359 code should be ran/inspected, PromptToolkit (and other frontend) mostly
360 360 need user facing information.
361 361
362 362 - Which range should be replaced replaced by what.
363 - Some metadata (like completion type), or meta informations to displayed to
363 - Some metadata (like completion type), or meta information to displayed to
364 364 the use user.
365 365
366 366 For debugging purpose we can also store the origin of the completion (``jedi``,
367 367 ``IPython.python_matches``, ``IPython.magics_matches``...).
368 368 """
369 369
370 370 __slots__ = ['start', 'end', 'text', 'type', 'signature', '_origin']
371 371
372 372 def __init__(self, start: int, end: int, text: str, *, type: str=None, _origin='', signature='') -> None:
373 373 warnings.warn("``Completion`` is a provisional API (as of IPython 6.0). "
374 374 "It may change without warnings. "
375 375 "Use in corresponding context manager.",
376 376 category=ProvisionalCompleterWarning, stacklevel=2)
377 377
378 378 self.start = start
379 379 self.end = end
380 380 self.text = text
381 381 self.type = type
382 382 self.signature = signature
383 383 self._origin = _origin
384 384
385 385 def __repr__(self):
386 386 return '<Completion start=%s end=%s text=%r type=%r, signature=%r,>' % \
387 387 (self.start, self.end, self.text, self.type or '?', self.signature or '?')
388 388
389 389 def __eq__(self, other)->Bool:
390 390 """
391 391 Equality and hash do not hash the type (as some completer may not be
392 392 able to infer the type), but are use to (partially) de-duplicate
393 393 completion.
394 394
395 395 Completely de-duplicating completion is a bit tricker that just
396 396 comparing as it depends on surrounding text, which Completions are not
397 397 aware of.
398 398 """
399 399 return self.start == other.start and \
400 400 self.end == other.end and \
401 401 self.text == other.text
402 402
403 403 def __hash__(self):
404 404 return hash((self.start, self.end, self.text))
405 405
406 406
407 407 _IC = Iterable[Completion]
408 408
409 409
410 410 def _deduplicate_completions(text: str, completions: _IC)-> _IC:
411 411 """
412 412 Deduplicate a set of completions.
413 413
414 414 .. warning:: Unstable
415 415
416 416 This function is unstable, API may change without warning.
417 417
418 418 Parameters
419 419 ----------
420 420 text: str
421 421 text that should be completed.
422 422 completions: Iterator[Completion]
423 423 iterator over the completions to deduplicate
424 424
425 425 Yields
426 426 ------
427 427 `Completions` objects
428 428
429 429
430 430 Completions coming from multiple sources, may be different but end up having
431 431 the same effect when applied to ``text``. If this is the case, this will
432 432 consider completions as equal and only emit the first encountered.
433 433
434 434 Not folded in `completions()` yet for debugging purpose, and to detect when
435 435 the IPython completer does return things that Jedi does not, but should be
436 436 at some point.
437 437 """
438 438 completions = list(completions)
439 439 if not completions:
440 440 return
441 441
442 442 new_start = min(c.start for c in completions)
443 443 new_end = max(c.end for c in completions)
444 444
445 445 seen = set()
446 446 for c in completions:
447 447 new_text = text[new_start:c.start] + c.text + text[c.end:new_end]
448 448 if new_text not in seen:
449 449 yield c
450 450 seen.add(new_text)
451 451
452 452
453 453 def rectify_completions(text: str, completions: _IC, *, _debug=False)->_IC:
454 454 """
455 455 Rectify a set of completions to all have the same ``start`` and ``end``
456 456
457 457 .. warning:: Unstable
458 458
459 459 This function is unstable, API may change without warning.
460 460 It will also raise unless use in proper context manager.
461 461
462 462 Parameters
463 463 ----------
464 464 text: str
465 465 text that should be completed.
466 466 completions: Iterator[Completion]
467 467 iterator over the completions to rectify
468 468
469 469
470 470 :any:`jedi.api.classes.Completion` s returned by Jedi may not have the same start and end, though
471 471 the Jupyter Protocol requires them to behave like so. This will readjust
472 472 the completion to have the same ``start`` and ``end`` by padding both
473 473 extremities with surrounding text.
474 474
475 475 During stabilisation should support a ``_debug`` option to log which
476 476 completion are return by the IPython completer and not found in Jedi in
477 477 order to make upstream bug report.
478 478 """
479 479 warnings.warn("`rectify_completions` is a provisional API (as of IPython 6.0). "
480 480 "It may change without warnings. "
481 481 "Use in corresponding context manager.",
482 482 category=ProvisionalCompleterWarning, stacklevel=2)
483 483
484 484 completions = list(completions)
485 485 if not completions:
486 486 return
487 487 starts = (c.start for c in completions)
488 488 ends = (c.end for c in completions)
489 489
490 490 new_start = min(starts)
491 491 new_end = max(ends)
492 492
493 493 seen_jedi = set()
494 494 seen_python_matches = set()
495 495 for c in completions:
496 496 new_text = text[new_start:c.start] + c.text + text[c.end:new_end]
497 497 if c._origin == 'jedi':
498 498 seen_jedi.add(new_text)
499 499 elif c._origin == 'IPCompleter.python_matches':
500 500 seen_python_matches.add(new_text)
501 501 yield Completion(new_start, new_end, new_text, type=c.type, _origin=c._origin, signature=c.signature)
502 502 diff = seen_python_matches.difference(seen_jedi)
503 503 if diff and _debug:
504 504 print('IPython.python matches have extras:', diff)
505 505
506 506
507 507 if sys.platform == 'win32':
508 508 DELIMS = ' \t\n`!@#$^&*()=+[{]}|;\'",<>?'
509 509 else:
510 510 DELIMS = ' \t\n`!@#$^&*()=+[{]}\\|;:\'",<>?'
511 511
512 512 GREEDY_DELIMS = ' =\r\n'
513 513
514 514
515 515 class CompletionSplitter(object):
516 516 """An object to split an input line in a manner similar to readline.
517 517
518 518 By having our own implementation, we can expose readline-like completion in
519 519 a uniform manner to all frontends. This object only needs to be given the
520 520 line of text to be split and the cursor position on said line, and it
521 521 returns the 'word' to be completed on at the cursor after splitting the
522 522 entire line.
523 523
524 524 What characters are used as splitting delimiters can be controlled by
525 525 setting the ``delims`` attribute (this is a property that internally
526 526 automatically builds the necessary regular expression)"""
527 527
528 528 # Private interface
529 529
530 530 # A string of delimiter characters. The default value makes sense for
531 531 # IPython's most typical usage patterns.
532 532 _delims = DELIMS
533 533
534 534 # The expression (a normal string) to be compiled into a regular expression
535 535 # for actual splitting. We store it as an attribute mostly for ease of
536 536 # debugging, since this type of code can be so tricky to debug.
537 537 _delim_expr = None
538 538
539 539 # The regular expression that does the actual splitting
540 540 _delim_re = None
541 541
542 542 def __init__(self, delims=None):
543 543 delims = CompletionSplitter._delims if delims is None else delims
544 544 self.delims = delims
545 545
546 546 @property
547 547 def delims(self):
548 548 """Return the string of delimiter characters."""
549 549 return self._delims
550 550
551 551 @delims.setter
552 552 def delims(self, delims):
553 553 """Set the delimiters for line splitting."""
554 554 expr = '[' + ''.join('\\'+ c for c in delims) + ']'
555 555 self._delim_re = re.compile(expr)
556 556 self._delims = delims
557 557 self._delim_expr = expr
558 558
559 559 def split_line(self, line, cursor_pos=None):
560 560 """Split a line of text with a cursor at the given position.
561 561 """
562 562 l = line if cursor_pos is None else line[:cursor_pos]
563 563 return self._delim_re.split(l)[-1]
564 564
565 565
566 566
567 567 class Completer(Configurable):
568 568
569 569 greedy = Bool(False,
570 570 help="""Activate greedy completion
571 571 PENDING DEPRECTION. this is now mostly taken care of with Jedi.
572 572
573 573 This will enable completion on elements of lists, results of function calls, etc.,
574 574 but can be unsafe because the code is actually evaluated on TAB.
575 575 """
576 576 ).tag(config=True)
577 577
578 578 use_jedi = Bool(default_value=JEDI_INSTALLED,
579 579 help="Experimental: Use Jedi to generate autocompletions. "
580 580 "Default to True if jedi is installed").tag(config=True)
581 581
582 582 jedi_compute_type_timeout = Int(default_value=400,
583 583 help="""Experimental: restrict time (in milliseconds) during which Jedi can compute types.
584 584 Set to 0 to stop computing types. Non-zero value lower than 100ms may hurt
585 585 performance by preventing jedi to build its cache.
586 586 """).tag(config=True)
587 587
588 588 debug = Bool(default_value=False,
589 589 help='Enable debug for the Completer. Mostly print extra '
590 590 'information for experimental jedi integration.')\
591 591 .tag(config=True)
592 592
593 593 backslash_combining_completions = Bool(True,
594 594 help="Enable unicode completions, e.g. \\alpha<tab> . "
595 595 "Includes completion of latex commands, unicode names, and expanding "
596 596 "unicode characters back to latex commands.").tag(config=True)
597 597
598 598
599 599
600 600 def __init__(self, namespace=None, global_namespace=None, **kwargs):
601 601 """Create a new completer for the command line.
602 602
603 603 Completer(namespace=ns, global_namespace=ns2) -> completer instance.
604 604
605 605 If unspecified, the default namespace where completions are performed
606 606 is __main__ (technically, __main__.__dict__). Namespaces should be
607 607 given as dictionaries.
608 608
609 609 An optional second namespace can be given. This allows the completer
610 610 to handle cases where both the local and global scopes need to be
611 611 distinguished.
612 612 """
613 613
614 614 # Don't bind to namespace quite yet, but flag whether the user wants a
615 615 # specific namespace or to use __main__.__dict__. This will allow us
616 616 # to bind to __main__.__dict__ at completion time, not now.
617 617 if namespace is None:
618 618 self.use_main_ns = True
619 619 else:
620 620 self.use_main_ns = False
621 621 self.namespace = namespace
622 622
623 623 # The global namespace, if given, can be bound directly
624 624 if global_namespace is None:
625 625 self.global_namespace = {}
626 626 else:
627 627 self.global_namespace = global_namespace
628 628
629 629 super(Completer, self).__init__(**kwargs)
630 630
631 631 def complete(self, text, state):
632 632 """Return the next possible completion for 'text'.
633 633
634 634 This is called successively with state == 0, 1, 2, ... until it
635 635 returns None. The completion should begin with 'text'.
636 636
637 637 """
638 638 if self.use_main_ns:
639 639 self.namespace = __main__.__dict__
640 640
641 641 if state == 0:
642 642 if "." in text:
643 643 self.matches = self.attr_matches(text)
644 644 else:
645 645 self.matches = self.global_matches(text)
646 646 try:
647 647 return self.matches[state]
648 648 except IndexError:
649 649 return None
650 650
651 651 def global_matches(self, text):
652 652 """Compute matches when text is a simple name.
653 653
654 654 Return a list of all keywords, built-in functions and names currently
655 655 defined in self.namespace or self.global_namespace that match.
656 656
657 657 """
658 658 matches = []
659 659 match_append = matches.append
660 660 n = len(text)
661 661 for lst in [keyword.kwlist,
662 662 builtin_mod.__dict__.keys(),
663 663 self.namespace.keys(),
664 664 self.global_namespace.keys()]:
665 665 for word in lst:
666 666 if word[:n] == text and word != "__builtins__":
667 667 match_append(word)
668 668
669 669 snake_case_re = re.compile(r"[^_]+(_[^_]+)+?\Z")
670 670 for lst in [self.namespace.keys(),
671 671 self.global_namespace.keys()]:
672 672 shortened = {"_".join([sub[0] for sub in word.split('_')]) : word
673 673 for word in lst if snake_case_re.match(word)}
674 674 for word in shortened.keys():
675 675 if word[:n] == text and word != "__builtins__":
676 676 match_append(shortened[word])
677 677 return matches
678 678
679 679 def attr_matches(self, text):
680 680 """Compute matches when text contains a dot.
681 681
682 682 Assuming the text is of the form NAME.NAME....[NAME], and is
683 683 evaluatable in self.namespace or self.global_namespace, it will be
684 684 evaluated and its attributes (as revealed by dir()) are used as
685 685 possible completions. (For class instances, class members are are
686 686 also considered.)
687 687
688 688 WARNING: this can still invoke arbitrary C code, if an object
689 689 with a __getattr__ hook is evaluated.
690 690
691 691 """
692 692
693 693 # Another option, seems to work great. Catches things like ''.<tab>
694 694 m = re.match(r"(\S+(\.\w+)*)\.(\w*)$", text)
695 695
696 696 if m:
697 697 expr, attr = m.group(1, 3)
698 698 elif self.greedy:
699 699 m2 = re.match(r"(.+)\.(\w*)$", self.line_buffer)
700 700 if not m2:
701 701 return []
702 702 expr, attr = m2.group(1,2)
703 703 else:
704 704 return []
705 705
706 706 try:
707 707 obj = eval(expr, self.namespace)
708 708 except:
709 709 try:
710 710 obj = eval(expr, self.global_namespace)
711 711 except:
712 712 return []
713 713
714 714 if self.limit_to__all__ and hasattr(obj, '__all__'):
715 715 words = get__all__entries(obj)
716 716 else:
717 717 words = dir2(obj)
718 718
719 719 try:
720 720 words = generics.complete_object(obj, words)
721 721 except TryNext:
722 722 pass
723 723 except AssertionError:
724 724 raise
725 725 except Exception:
726 726 # Silence errors from completion function
727 727 #raise # dbg
728 728 pass
729 729 # Build match list to return
730 730 n = len(attr)
731 731 return [u"%s.%s" % (expr, w) for w in words if w[:n] == attr ]
732 732
733 733
734 734 def get__all__entries(obj):
735 735 """returns the strings in the __all__ attribute"""
736 736 try:
737 737 words = getattr(obj, '__all__')
738 738 except:
739 739 return []
740 740
741 741 return [w for w in words if isinstance(w, str)]
742 742
743 743
744 744 def match_dict_keys(keys: List[str], prefix: str, delims: str):
745 745 """Used by dict_key_matches, matching the prefix to a list of keys
746 746
747 747 Parameters
748 748 ==========
749 749 keys:
750 750 list of keys in dictionary currently being completed.
751 751 prefix:
752 752 Part of the text already typed by the user. e.g. `mydict[b'fo`
753 753 delims:
754 754 String of delimiters to consider when finding the current key.
755 755
756 756 Returns
757 757 =======
758 758
759 759 A tuple of three elements: ``quote``, ``token_start``, ``matched``, with
760 760 ``quote`` being the quote that need to be used to close current string.
761 761 ``token_start`` the position where the replacement should start occurring,
762 762 ``matches`` a list of replacement/completion
763 763
764 764 """
765 765 if not prefix:
766 766 return None, 0, [repr(k) for k in keys
767 767 if isinstance(k, (str, bytes))]
768 768 quote_match = re.search('["\']', prefix)
769 769 quote = quote_match.group()
770 770 try:
771 771 prefix_str = eval(prefix + quote, {})
772 772 except Exception:
773 773 return None, 0, []
774 774
775 775 pattern = '[^' + ''.join('\\' + c for c in delims) + ']*$'
776 776 token_match = re.search(pattern, prefix, re.UNICODE)
777 777 token_start = token_match.start()
778 778 token_prefix = token_match.group()
779 779
780 780 matched = []
781 781 for key in keys:
782 782 try:
783 783 if not key.startswith(prefix_str):
784 784 continue
785 785 except (AttributeError, TypeError, UnicodeError):
786 786 # Python 3+ TypeError on b'a'.startswith('a') or vice-versa
787 787 continue
788 788
789 789 # reformat remainder of key to begin with prefix
790 790 rem = key[len(prefix_str):]
791 791 # force repr wrapped in '
792 792 rem_repr = repr(rem + '"') if isinstance(rem, str) else repr(rem + b'"')
793 793 if rem_repr.startswith('u') and prefix[0] not in 'uU':
794 794 # Found key is unicode, but prefix is Py2 string.
795 795 # Therefore attempt to interpret key as string.
796 796 try:
797 797 rem_repr = repr(rem.encode('ascii') + '"')
798 798 except UnicodeEncodeError:
799 799 continue
800 800
801 801 rem_repr = rem_repr[1 + rem_repr.index("'"):-2]
802 802 if quote == '"':
803 803 # The entered prefix is quoted with ",
804 804 # but the match is quoted with '.
805 805 # A contained " hence needs escaping for comparison:
806 806 rem_repr = rem_repr.replace('"', '\\"')
807 807
808 808 # then reinsert prefix from start of token
809 809 matched.append('%s%s' % (token_prefix, rem_repr))
810 810 return quote, token_start, matched
811 811
812 812
813 813 def cursor_to_position(text:str, line:int, column:int)->int:
814 814 """
815 815
816 816 Convert the (line,column) position of the cursor in text to an offset in a
817 817 string.
818 818
819 819 Parameters
820 820 ----------
821 821
822 822 text : str
823 823 The text in which to calculate the cursor offset
824 824 line : int
825 825 Line of the cursor; 0-indexed
826 826 column : int
827 827 Column of the cursor 0-indexed
828 828
829 829 Return
830 830 ------
831 831 Position of the cursor in ``text``, 0-indexed.
832 832
833 833 See Also
834 834 --------
835 835 position_to_cursor: reciprocal of this function
836 836
837 837 """
838 838 lines = text.split('\n')
839 839 assert line <= len(lines), '{} <= {}'.format(str(line), str(len(lines)))
840 840
841 841 return sum(len(l) + 1 for l in lines[:line]) + column
842 842
843 843 def position_to_cursor(text:str, offset:int)->Tuple[int, int]:
844 844 """
845 845 Convert the position of the cursor in text (0 indexed) to a line
846 846 number(0-indexed) and a column number (0-indexed) pair
847 847
848 848 Position should be a valid position in ``text``.
849 849
850 850 Parameters
851 851 ----------
852 852
853 853 text : str
854 854 The text in which to calculate the cursor offset
855 855 offset : int
856 856 Position of the cursor in ``text``, 0-indexed.
857 857
858 858 Return
859 859 ------
860 860 (line, column) : (int, int)
861 861 Line of the cursor; 0-indexed, column of the cursor 0-indexed
862 862
863 863
864 864 See Also
865 865 --------
866 866 cursor_to_position : reciprocal of this function
867 867
868 868
869 869 """
870 870
871 871 assert 0 < offset <= len(text) , "0 < %s <= %s" % (offset , len(text))
872 872
873 873 before = text[:offset]
874 874 blines = before.split('\n') # ! splitnes trim trailing \n
875 875 line = before.count('\n')
876 876 col = len(blines[-1])
877 877 return line, col
878 878
879 879
880 880 def _safe_isinstance(obj, module, class_name):
881 881 """Checks if obj is an instance of module.class_name if loaded
882 882 """
883 883 return (module in sys.modules and
884 884 isinstance(obj, getattr(import_module(module), class_name)))
885 885
886 886
887 887 def back_unicode_name_matches(text):
888 888 u"""Match unicode characters back to unicode name
889 889
890 890 This does ``☃`` -> ``\\snowman``
891 891
892 892 Note that snowman is not a valid python3 combining character but will be expanded.
893 893 Though it will not recombine back to the snowman character by the completion machinery.
894 894
895 895 This will not either back-complete standard sequences like \\n, \\b ...
896 896
897 897 Used on Python 3 only.
898 898 """
899 899 if len(text)<2:
900 900 return u'', ()
901 901 maybe_slash = text[-2]
902 902 if maybe_slash != '\\':
903 903 return u'', ()
904 904
905 905 char = text[-1]
906 906 # no expand on quote for completion in strings.
907 907 # nor backcomplete standard ascii keys
908 908 if char in string.ascii_letters or char in ['"',"'"]:
909 909 return u'', ()
910 910 try :
911 911 unic = unicodedata.name(char)
912 912 return '\\'+char,['\\'+unic]
913 913 except KeyError:
914 914 pass
915 915 return u'', ()
916 916
917 917 def back_latex_name_matches(text:str):
918 918 """Match latex characters back to unicode name
919 919
920 920 This does ``\\ℵ`` -> ``\\aleph``
921 921
922 922 Used on Python 3 only.
923 923 """
924 924 if len(text)<2:
925 925 return u'', ()
926 926 maybe_slash = text[-2]
927 927 if maybe_slash != '\\':
928 928 return u'', ()
929 929
930 930
931 931 char = text[-1]
932 932 # no expand on quote for completion in strings.
933 933 # nor backcomplete standard ascii keys
934 934 if char in string.ascii_letters or char in ['"',"'"]:
935 935 return u'', ()
936 936 try :
937 937 latex = reverse_latex_symbol[char]
938 938 # '\\' replace the \ as well
939 939 return '\\'+char,[latex]
940 940 except KeyError:
941 941 pass
942 942 return u'', ()
943 943
944 944
945 945 def _formatparamchildren(parameter) -> str:
946 946 """
947 947 Get parameter name and value from Jedi Private API
948 948
949 949 Jedi does not expose a simple way to get `param=value` from its API.
950 950
951 951 Prameter
952 952 ========
953 953
954 954 parameter:
955 955 Jedi's function `Param`
956 956
957 957 Returns
958 958 =======
959 959
960 960 A string like 'a', 'b=1', '*args', '**kwargs'
961 961
962 962
963 963 """
964 964 description = parameter.description
965 965 if not description.startswith('param '):
966 966 raise ValueError('Jedi function parameter description have change format.'
967 967 'Expected "param ...", found %r".' % description)
968 968 return description[6:]
969 969
970 970 def _make_signature(completion)-> str:
971 971 """
972 972 Make the signature from a jedi completion
973 973
974 974 Parameter
975 975 =========
976 976
977 977 completion: jedi.Completion
978 978 object does not complete a function type
979 979
980 980 Returns
981 981 =======
982 982
983 983 a string consisting of the function signature, with the parenthesis but
984 984 without the function name. example:
985 985 `(a, *args, b=1, **kwargs)`
986 986
987 987 """
988 988
989 989 return '(%s)'% ', '.join([f for f in (_formatparamchildren(p) for p in completion.params) if f])
990 990
991 991 class IPCompleter(Completer):
992 992 """Extension of the completer class with IPython-specific features"""
993 993
994 994 @observe('greedy')
995 995 def _greedy_changed(self, change):
996 996 """update the splitter and readline delims when greedy is changed"""
997 997 if change['new']:
998 998 self.splitter.delims = GREEDY_DELIMS
999 999 else:
1000 1000 self.splitter.delims = DELIMS
1001 1001
1002 1002 merge_completions = Bool(True,
1003 1003 help="""Whether to merge completion results into a single list
1004 1004
1005 1005 If False, only the completion results from the first non-empty
1006 1006 completer will be returned.
1007 1007 """
1008 1008 ).tag(config=True)
1009 1009 omit__names = Enum((0,1,2), default_value=2,
1010 1010 help="""Instruct the completer to omit private method names
1011 1011
1012 1012 Specifically, when completing on ``object.<tab>``.
1013 1013
1014 1014 When 2 [default]: all names that start with '_' will be excluded.
1015 1015
1016 1016 When 1: all 'magic' names (``__foo__``) will be excluded.
1017 1017
1018 1018 When 0: nothing will be excluded.
1019 1019 """
1020 1020 ).tag(config=True)
1021 1021 limit_to__all__ = Bool(False,
1022 1022 help="""
1023 1023 DEPRECATED as of version 5.0.
1024 1024
1025 1025 Instruct the completer to use __all__ for the completion
1026 1026
1027 1027 Specifically, when completing on ``object.<tab>``.
1028 1028
1029 1029 When True: only those names in obj.__all__ will be included.
1030 1030
1031 1031 When False [default]: the __all__ attribute is ignored
1032 1032 """,
1033 1033 ).tag(config=True)
1034 1034
1035 1035 @observe('limit_to__all__')
1036 1036 def _limit_to_all_changed(self, change):
1037 1037 warnings.warn('`IPython.core.IPCompleter.limit_to__all__` configuration '
1038 1038 'value has been deprecated since IPython 5.0, will be made to have '
1039 1039 'no effects and then removed in future version of IPython.',
1040 1040 UserWarning)
1041 1041
1042 1042 def __init__(self, shell=None, namespace=None, global_namespace=None,
1043 1043 use_readline=_deprecation_readline_sentinel, config=None, **kwargs):
1044 1044 """IPCompleter() -> completer
1045 1045
1046 1046 Return a completer object.
1047 1047
1048 1048 Parameters
1049 1049 ----------
1050 1050
1051 1051 shell
1052 1052 a pointer to the ipython shell itself. This is needed
1053 1053 because this completer knows about magic functions, and those can
1054 1054 only be accessed via the ipython instance.
1055 1055
1056 1056 namespace : dict, optional
1057 1057 an optional dict where completions are performed.
1058 1058
1059 1059 global_namespace : dict, optional
1060 1060 secondary optional dict for completions, to
1061 1061 handle cases (such as IPython embedded inside functions) where
1062 1062 both Python scopes are visible.
1063 1063
1064 1064 use_readline : bool, optional
1065 1065 DEPRECATED, ignored since IPython 6.0, will have no effects
1066 1066 """
1067 1067
1068 1068 self.magic_escape = ESC_MAGIC
1069 1069 self.splitter = CompletionSplitter()
1070 1070
1071 1071 if use_readline is not _deprecation_readline_sentinel:
1072 1072 warnings.warn('The `use_readline` parameter is deprecated and ignored since IPython 6.0.',
1073 1073 DeprecationWarning, stacklevel=2)
1074 1074
1075 1075 # _greedy_changed() depends on splitter and readline being defined:
1076 1076 Completer.__init__(self, namespace=namespace, global_namespace=global_namespace,
1077 1077 config=config, **kwargs)
1078 1078
1079 1079 # List where completion matches will be stored
1080 1080 self.matches = []
1081 1081 self.shell = shell
1082 1082 # Regexp to split filenames with spaces in them
1083 1083 self.space_name_re = re.compile(r'([^\\] )')
1084 1084 # Hold a local ref. to glob.glob for speed
1085 1085 self.glob = glob.glob
1086 1086
1087 1087 # Determine if we are running on 'dumb' terminals, like (X)Emacs
1088 1088 # buffers, to avoid completion problems.
1089 1089 term = os.environ.get('TERM','xterm')
1090 1090 self.dumb_terminal = term in ['dumb','emacs']
1091 1091
1092 1092 # Special handling of backslashes needed in win32 platforms
1093 1093 if sys.platform == "win32":
1094 1094 self.clean_glob = self._clean_glob_win32
1095 1095 else:
1096 1096 self.clean_glob = self._clean_glob
1097 1097
1098 1098 #regexp to parse docstring for function signature
1099 1099 self.docstring_sig_re = re.compile(r'^[\w|\s.]+\(([^)]*)\).*')
1100 1100 self.docstring_kwd_re = re.compile(r'[\s|\[]*(\w+)(?:\s*=\s*.*)')
1101 1101 #use this if positional argument name is also needed
1102 1102 #= re.compile(r'[\s|\[]*(\w+)(?:\s*=?\s*.*)')
1103 1103
1104 1104 # All active matcher routines for completion
1105 1105 self.matchers = [
1106 1106 self.python_matches,
1107 1107 self.file_matches,
1108 1108 self.magic_matches,
1109 1109 self.python_func_kw_matches,
1110 1110 self.dict_key_matches,
1111 1111 ]
1112 1112 self.magic_arg_matchers = [
1113 1113 self.magic_config_matches,
1114 1114 self.magic_color_matches,
1115 1115 ]
1116 1116
1117 1117 # This is set externally by InteractiveShell
1118 1118 self.custom_completers = None
1119 1119
1120 1120 def all_completions(self, text):
1121 1121 """
1122 1122 Wrapper around the complete method for the benefit of emacs.
1123 1123 """
1124 1124 return self.complete(text)[1]
1125 1125
1126 1126 def _clean_glob(self, text):
1127 1127 return self.glob("%s*" % text)
1128 1128
1129 1129 def _clean_glob_win32(self,text):
1130 1130 return [f.replace("\\","/")
1131 1131 for f in self.glob("%s*" % text)]
1132 1132
1133 1133 def file_matches(self, text):
1134 1134 """Match filenames, expanding ~USER type strings.
1135 1135
1136 1136 Most of the seemingly convoluted logic in this completer is an
1137 1137 attempt to handle filenames with spaces in them. And yet it's not
1138 1138 quite perfect, because Python's readline doesn't expose all of the
1139 1139 GNU readline details needed for this to be done correctly.
1140 1140
1141 1141 For a filename with a space in it, the printed completions will be
1142 1142 only the parts after what's already been typed (instead of the
1143 1143 full completions, as is normally done). I don't think with the
1144 1144 current (as of Python 2.3) Python readline it's possible to do
1145 1145 better."""
1146 1146
1147 1147 # chars that require escaping with backslash - i.e. chars
1148 1148 # that readline treats incorrectly as delimiters, but we
1149 1149 # don't want to treat as delimiters in filename matching
1150 1150 # when escaped with backslash
1151 1151 if text.startswith('!'):
1152 1152 text = text[1:]
1153 1153 text_prefix = u'!'
1154 1154 else:
1155 1155 text_prefix = u''
1156 1156
1157 1157 text_until_cursor = self.text_until_cursor
1158 1158 # track strings with open quotes
1159 1159 open_quotes = has_open_quotes(text_until_cursor)
1160 1160
1161 1161 if '(' in text_until_cursor or '[' in text_until_cursor:
1162 1162 lsplit = text
1163 1163 else:
1164 1164 try:
1165 1165 # arg_split ~ shlex.split, but with unicode bugs fixed by us
1166 1166 lsplit = arg_split(text_until_cursor)[-1]
1167 1167 except ValueError:
1168 1168 # typically an unmatched ", or backslash without escaped char.
1169 1169 if open_quotes:
1170 1170 lsplit = text_until_cursor.split(open_quotes)[-1]
1171 1171 else:
1172 1172 return []
1173 1173 except IndexError:
1174 1174 # tab pressed on empty line
1175 1175 lsplit = ""
1176 1176
1177 1177 if not open_quotes and lsplit != protect_filename(lsplit):
1178 1178 # if protectables are found, do matching on the whole escaped name
1179 1179 has_protectables = True
1180 1180 text0,text = text,lsplit
1181 1181 else:
1182 1182 has_protectables = False
1183 1183 text = os.path.expanduser(text)
1184 1184
1185 1185 if text == "":
1186 1186 return [text_prefix + protect_filename(f) for f in self.glob("*")]
1187 1187
1188 1188 # Compute the matches from the filesystem
1189 1189 if sys.platform == 'win32':
1190 1190 m0 = self.clean_glob(text)
1191 1191 else:
1192 1192 m0 = self.clean_glob(text.replace('\\', ''))
1193 1193
1194 1194 if has_protectables:
1195 1195 # If we had protectables, we need to revert our changes to the
1196 1196 # beginning of filename so that we don't double-write the part
1197 1197 # of the filename we have so far
1198 1198 len_lsplit = len(lsplit)
1199 1199 matches = [text_prefix + text0 +
1200 1200 protect_filename(f[len_lsplit:]) for f in m0]
1201 1201 else:
1202 1202 if open_quotes:
1203 1203 # if we have a string with an open quote, we don't need to
1204 1204 # protect the names beyond the quote (and we _shouldn't_, as
1205 1205 # it would cause bugs when the filesystem call is made).
1206 1206 matches = m0 if sys.platform == "win32" else\
1207 1207 [protect_filename(f, open_quotes) for f in m0]
1208 1208 else:
1209 1209 matches = [text_prefix +
1210 1210 protect_filename(f) for f in m0]
1211 1211
1212 1212 # Mark directories in input list by appending '/' to their names.
1213 1213 return [x+'/' if os.path.isdir(x) else x for x in matches]
1214 1214
1215 1215 def magic_matches(self, text):
1216 1216 """Match magics"""
1217 1217 # Get all shell magics now rather than statically, so magics loaded at
1218 1218 # runtime show up too.
1219 1219 lsm = self.shell.magics_manager.lsmagic()
1220 1220 line_magics = lsm['line']
1221 1221 cell_magics = lsm['cell']
1222 1222 pre = self.magic_escape
1223 1223 pre2 = pre+pre
1224 1224
1225 1225 explicit_magic = text.startswith(pre)
1226 1226
1227 1227 # Completion logic:
1228 1228 # - user gives %%: only do cell magics
1229 1229 # - user gives %: do both line and cell magics
1230 1230 # - no prefix: do both
1231 1231 # In other words, line magics are skipped if the user gives %% explicitly
1232 1232 #
1233 1233 # We also exclude magics that match any currently visible names:
1234 1234 # https://github.com/ipython/ipython/issues/4877, unless the user has
1235 1235 # typed a %:
1236 1236 # https://github.com/ipython/ipython/issues/10754
1237 1237 bare_text = text.lstrip(pre)
1238 1238 global_matches = self.global_matches(bare_text)
1239 1239 if not explicit_magic:
1240 1240 def matches(magic):
1241 1241 """
1242 1242 Filter magics, in particular remove magics that match
1243 1243 a name present in global namespace.
1244 1244 """
1245 1245 return ( magic.startswith(bare_text) and
1246 1246 magic not in global_matches )
1247 1247 else:
1248 1248 def matches(magic):
1249 1249 return magic.startswith(bare_text)
1250 1250
1251 1251 comp = [ pre2+m for m in cell_magics if matches(m)]
1252 1252 if not text.startswith(pre2):
1253 1253 comp += [ pre+m for m in line_magics if matches(m)]
1254 1254
1255 1255 return comp
1256 1256
1257 1257 def magic_config_matches(self, text:str) -> List[str]:
1258 1258 """ Match class names and attributes for %config magic """
1259 1259 texts = text.strip().split()
1260 1260
1261 1261 if len(texts) > 0 and (texts[0] == 'config' or texts[0] == '%config'):
1262 1262 # get all configuration classes
1263 1263 classes = sorted(set([ c for c in self.shell.configurables
1264 1264 if c.__class__.class_traits(config=True)
1265 1265 ]), key=lambda x: x.__class__.__name__)
1266 1266 classnames = [ c.__class__.__name__ for c in classes ]
1267 1267
1268 1268 # return all classnames if config or %config is given
1269 1269 if len(texts) == 1:
1270 1270 return classnames
1271 1271
1272 1272 # match classname
1273 1273 classname_texts = texts[1].split('.')
1274 1274 classname = classname_texts[0]
1275 1275 classname_matches = [ c for c in classnames
1276 1276 if c.startswith(classname) ]
1277 1277
1278 1278 # return matched classes or the matched class with attributes
1279 1279 if texts[1].find('.') < 0:
1280 1280 return classname_matches
1281 1281 elif len(classname_matches) == 1 and \
1282 1282 classname_matches[0] == classname:
1283 1283 cls = classes[classnames.index(classname)].__class__
1284 1284 help = cls.class_get_help()
1285 1285 # strip leading '--' from cl-args:
1286 1286 help = re.sub(re.compile(r'^--', re.MULTILINE), '', help)
1287 1287 return [ attr.split('=')[0]
1288 1288 for attr in help.strip().splitlines()
1289 1289 if attr.startswith(texts[1]) ]
1290 1290 return []
1291 1291
1292 1292 def magic_color_matches(self, text:str) -> List[str] :
1293 1293 """ Match color schemes for %colors magic"""
1294 1294 texts = text.split()
1295 1295 if text.endswith(' '):
1296 1296 # .split() strips off the trailing whitespace. Add '' back
1297 1297 # so that: '%colors ' -> ['%colors', '']
1298 1298 texts.append('')
1299 1299
1300 1300 if len(texts) == 2 and (texts[0] == 'colors' or texts[0] == '%colors'):
1301 1301 prefix = texts[1]
1302 1302 return [ color for color in InspectColors.keys()
1303 1303 if color.startswith(prefix) ]
1304 1304 return []
1305 1305
1306 1306 def _jedi_matches(self, cursor_column:int, cursor_line:int, text:str):
1307 1307 """
1308 1308
1309 1309 Return a list of :any:`jedi.api.Completions` object from a ``text`` and
1310 1310 cursor position.
1311 1311
1312 1312 Parameters
1313 1313 ----------
1314 1314 cursor_column : int
1315 1315 column position of the cursor in ``text``, 0-indexed.
1316 1316 cursor_line : int
1317 1317 line position of the cursor in ``text``, 0-indexed
1318 1318 text : str
1319 1319 text to complete
1320 1320
1321 1321 Debugging
1322 1322 ---------
1323 1323
1324 1324 If ``IPCompleter.debug`` is ``True`` may return a :any:`_FakeJediCompletion`
1325 1325 object containing a string with the Jedi debug information attached.
1326 1326 """
1327 1327 namespaces = [self.namespace]
1328 1328 if self.global_namespace is not None:
1329 1329 namespaces.append(self.global_namespace)
1330 1330
1331 1331 completion_filter = lambda x:x
1332 1332 # cursor_pos is an it, jedi wants line and column
1333 1333 offset = cursor_to_position(text, cursor_line, cursor_column)
1334 1334 # filter output if we are completing for object members
1335 1335 if offset:
1336 1336 pre = text[offset-1]
1337 1337 if pre == '.':
1338 1338 if self.omit__names == 2:
1339 1339 completion_filter = lambda c:not c.name.startswith('_')
1340 1340 elif self.omit__names == 1:
1341 1341 completion_filter = lambda c:not (c.name.startswith('__') and c.name.endswith('__'))
1342 1342 elif self.omit__names == 0:
1343 1343 completion_filter = lambda x:x
1344 1344 else:
1345 1345 raise ValueError("Don't understand self.omit__names == {}".format(self.omit__names))
1346 1346
1347 1347 interpreter = jedi.Interpreter(
1348 1348 text, namespaces, column=cursor_column, line=cursor_line + 1)
1349 1349 try_jedi = True
1350 1350
1351 1351 try:
1352 1352 # should we check the type of the node is Error ?
1353 1353 try:
1354 1354 # jedi >= 0.11
1355 1355 from parso.tree import ErrorLeaf
1356 1356 except ImportError:
1357 1357 # jedi < 0.11
1358 1358 from jedi.parser.tree import ErrorLeaf
1359 1359
1360 1360 next_to_last_tree = interpreter._get_module().tree_node.children[-2]
1361 1361 completing_string = False
1362 1362 if isinstance(next_to_last_tree, ErrorLeaf):
1363 1363 completing_string = next_to_last_tree.value[0] in {'"', "'"}
1364 1364 # if we are in a string jedi is likely not the right candidate for
1365 1365 # now. Skip it.
1366 1366 try_jedi = not completing_string
1367 1367 except Exception as e:
1368 1368 # many of things can go wrong, we are using private API just don't crash.
1369 1369 if self.debug:
1370 1370 print("Error detecting if completing a non-finished string :", e, '|')
1371 1371
1372 1372 if not try_jedi:
1373 1373 return []
1374 1374 try:
1375 1375 return filter(completion_filter, interpreter.completions())
1376 1376 except Exception as e:
1377 1377 if self.debug:
1378 1378 return [_FakeJediCompletion('Oops Jedi has crashed, please report a bug with the following:\n"""\n%s\ns"""' % (e))]
1379 1379 else:
1380 1380 return []
1381 1381
1382 1382 def python_matches(self, text):
1383 1383 """Match attributes or global python names"""
1384 1384 if "." in text:
1385 1385 try:
1386 1386 matches = self.attr_matches(text)
1387 1387 if text.endswith('.') and self.omit__names:
1388 1388 if self.omit__names == 1:
1389 1389 # true if txt is _not_ a __ name, false otherwise:
1390 1390 no__name = (lambda txt:
1391 1391 re.match(r'.*\.__.*?__',txt) is None)
1392 1392 else:
1393 1393 # true if txt is _not_ a _ name, false otherwise:
1394 1394 no__name = (lambda txt:
1395 1395 re.match(r'\._.*?',txt[txt.rindex('.'):]) is None)
1396 1396 matches = filter(no__name, matches)
1397 1397 except NameError:
1398 1398 # catches <undefined attributes>.<tab>
1399 1399 matches = []
1400 1400 else:
1401 1401 matches = self.global_matches(text)
1402 1402 return matches
1403 1403
1404 1404 def _default_arguments_from_docstring(self, doc):
1405 1405 """Parse the first line of docstring for call signature.
1406 1406
1407 1407 Docstring should be of the form 'min(iterable[, key=func])\n'.
1408 1408 It can also parse cython docstring of the form
1409 1409 'Minuit.migrad(self, int ncall=10000, resume=True, int nsplit=1)'.
1410 1410 """
1411 1411 if doc is None:
1412 1412 return []
1413 1413
1414 1414 #care only the firstline
1415 1415 line = doc.lstrip().splitlines()[0]
1416 1416
1417 1417 #p = re.compile(r'^[\w|\s.]+\(([^)]*)\).*')
1418 1418 #'min(iterable[, key=func])\n' -> 'iterable[, key=func]'
1419 1419 sig = self.docstring_sig_re.search(line)
1420 1420 if sig is None:
1421 1421 return []
1422 1422 # iterable[, key=func]' -> ['iterable[' ,' key=func]']
1423 1423 sig = sig.groups()[0].split(',')
1424 1424 ret = []
1425 1425 for s in sig:
1426 1426 #re.compile(r'[\s|\[]*(\w+)(?:\s*=\s*.*)')
1427 1427 ret += self.docstring_kwd_re.findall(s)
1428 1428 return ret
1429 1429
1430 1430 def _default_arguments(self, obj):
1431 1431 """Return the list of default arguments of obj if it is callable,
1432 1432 or empty list otherwise."""
1433 1433 call_obj = obj
1434 1434 ret = []
1435 1435 if inspect.isbuiltin(obj):
1436 1436 pass
1437 1437 elif not (inspect.isfunction(obj) or inspect.ismethod(obj)):
1438 1438 if inspect.isclass(obj):
1439 1439 #for cython embedsignature=True the constructor docstring
1440 1440 #belongs to the object itself not __init__
1441 1441 ret += self._default_arguments_from_docstring(
1442 1442 getattr(obj, '__doc__', ''))
1443 1443 # for classes, check for __init__,__new__
1444 1444 call_obj = (getattr(obj, '__init__', None) or
1445 1445 getattr(obj, '__new__', None))
1446 1446 # for all others, check if they are __call__able
1447 1447 elif hasattr(obj, '__call__'):
1448 1448 call_obj = obj.__call__
1449 1449 ret += self._default_arguments_from_docstring(
1450 1450 getattr(call_obj, '__doc__', ''))
1451 1451
1452 1452 _keeps = (inspect.Parameter.KEYWORD_ONLY,
1453 1453 inspect.Parameter.POSITIONAL_OR_KEYWORD)
1454 1454
1455 1455 try:
1456 1456 sig = inspect.signature(call_obj)
1457 1457 ret.extend(k for k, v in sig.parameters.items() if
1458 1458 v.kind in _keeps)
1459 1459 except ValueError:
1460 1460 pass
1461 1461
1462 1462 return list(set(ret))
1463 1463
1464 1464 def python_func_kw_matches(self,text):
1465 1465 """Match named parameters (kwargs) of the last open function"""
1466 1466
1467 1467 if "." in text: # a parameter cannot be dotted
1468 1468 return []
1469 1469 try: regexp = self.__funcParamsRegex
1470 1470 except AttributeError:
1471 1471 regexp = self.__funcParamsRegex = re.compile(r'''
1472 1472 '.*?(?<!\\)' | # single quoted strings or
1473 1473 ".*?(?<!\\)" | # double quoted strings or
1474 1474 \w+ | # identifier
1475 1475 \S # other characters
1476 1476 ''', re.VERBOSE | re.DOTALL)
1477 1477 # 1. find the nearest identifier that comes before an unclosed
1478 1478 # parenthesis before the cursor
1479 1479 # e.g. for "foo (1+bar(x), pa<cursor>,a=1)", the candidate is "foo"
1480 1480 tokens = regexp.findall(self.text_until_cursor)
1481 1481 iterTokens = reversed(tokens); openPar = 0
1482 1482
1483 1483 for token in iterTokens:
1484 1484 if token == ')':
1485 1485 openPar -= 1
1486 1486 elif token == '(':
1487 1487 openPar += 1
1488 1488 if openPar > 0:
1489 1489 # found the last unclosed parenthesis
1490 1490 break
1491 1491 else:
1492 1492 return []
1493 1493 # 2. Concatenate dotted names ("foo.bar" for "foo.bar(x, pa" )
1494 1494 ids = []
1495 1495 isId = re.compile(r'\w+$').match
1496 1496
1497 1497 while True:
1498 1498 try:
1499 1499 ids.append(next(iterTokens))
1500 1500 if not isId(ids[-1]):
1501 1501 ids.pop(); break
1502 1502 if not next(iterTokens) == '.':
1503 1503 break
1504 1504 except StopIteration:
1505 1505 break
1506 1506
1507 1507 # Find all named arguments already assigned to, as to avoid suggesting
1508 1508 # them again
1509 1509 usedNamedArgs = set()
1510 1510 par_level = -1
1511 1511 for token, next_token in zip(tokens, tokens[1:]):
1512 1512 if token == '(':
1513 1513 par_level += 1
1514 1514 elif token == ')':
1515 1515 par_level -= 1
1516 1516
1517 1517 if par_level != 0:
1518 1518 continue
1519 1519
1520 1520 if next_token != '=':
1521 1521 continue
1522 1522
1523 1523 usedNamedArgs.add(token)
1524 1524
1525 1525 # lookup the candidate callable matches either using global_matches
1526 1526 # or attr_matches for dotted names
1527 1527 if len(ids) == 1:
1528 1528 callableMatches = self.global_matches(ids[0])
1529 1529 else:
1530 1530 callableMatches = self.attr_matches('.'.join(ids[::-1]))
1531 1531 argMatches = []
1532 1532 for callableMatch in callableMatches:
1533 1533 try:
1534 1534 namedArgs = self._default_arguments(eval(callableMatch,
1535 1535 self.namespace))
1536 1536 except:
1537 1537 continue
1538 1538
1539 1539 # Remove used named arguments from the list, no need to show twice
1540 1540 for namedArg in set(namedArgs) - usedNamedArgs:
1541 1541 if namedArg.startswith(text):
1542 1542 argMatches.append(u"%s=" %namedArg)
1543 1543 return argMatches
1544 1544
1545 1545 def dict_key_matches(self, text):
1546 1546 "Match string keys in a dictionary, after e.g. 'foo[' "
1547 1547 def get_keys(obj):
1548 1548 # Objects can define their own completions by defining an
1549 1549 # _ipy_key_completions_() method.
1550 1550 method = get_real_method(obj, '_ipython_key_completions_')
1551 1551 if method is not None:
1552 1552 return method()
1553 1553
1554 1554 # Special case some common in-memory dict-like types
1555 1555 if isinstance(obj, dict) or\
1556 1556 _safe_isinstance(obj, 'pandas', 'DataFrame'):
1557 1557 try:
1558 1558 return list(obj.keys())
1559 1559 except Exception:
1560 1560 return []
1561 1561 elif _safe_isinstance(obj, 'numpy', 'ndarray') or\
1562 1562 _safe_isinstance(obj, 'numpy', 'void'):
1563 1563 return obj.dtype.names or []
1564 1564 return []
1565 1565
1566 1566 try:
1567 1567 regexps = self.__dict_key_regexps
1568 1568 except AttributeError:
1569 1569 dict_key_re_fmt = r'''(?x)
1570 1570 ( # match dict-referring expression wrt greedy setting
1571 1571 %s
1572 1572 )
1573 1573 \[ # open bracket
1574 1574 \s* # and optional whitespace
1575 1575 ([uUbB]? # string prefix (r not handled)
1576 1576 (?: # unclosed string
1577 1577 '(?:[^']|(?<!\\)\\')*
1578 1578 |
1579 1579 "(?:[^"]|(?<!\\)\\")*
1580 1580 )
1581 1581 )?
1582 1582 $
1583 1583 '''
1584 1584 regexps = self.__dict_key_regexps = {
1585 1585 False: re.compile(dict_key_re_fmt % '''
1586 1586 # identifiers separated by .
1587 1587 (?!\d)\w+
1588 1588 (?:\.(?!\d)\w+)*
1589 1589 '''),
1590 1590 True: re.compile(dict_key_re_fmt % '''
1591 1591 .+
1592 1592 ''')
1593 1593 }
1594 1594
1595 1595 match = regexps[self.greedy].search(self.text_until_cursor)
1596 1596 if match is None:
1597 1597 return []
1598 1598
1599 1599 expr, prefix = match.groups()
1600 1600 try:
1601 1601 obj = eval(expr, self.namespace)
1602 1602 except Exception:
1603 1603 try:
1604 1604 obj = eval(expr, self.global_namespace)
1605 1605 except Exception:
1606 1606 return []
1607 1607
1608 1608 keys = get_keys(obj)
1609 1609 if not keys:
1610 1610 return keys
1611 1611 closing_quote, token_offset, matches = match_dict_keys(keys, prefix, self.splitter.delims)
1612 1612 if not matches:
1613 1613 return matches
1614 1614
1615 1615 # get the cursor position of
1616 1616 # - the text being completed
1617 1617 # - the start of the key text
1618 1618 # - the start of the completion
1619 1619 text_start = len(self.text_until_cursor) - len(text)
1620 1620 if prefix:
1621 1621 key_start = match.start(2)
1622 1622 completion_start = key_start + token_offset
1623 1623 else:
1624 1624 key_start = completion_start = match.end()
1625 1625
1626 1626 # grab the leading prefix, to make sure all completions start with `text`
1627 1627 if text_start > key_start:
1628 1628 leading = ''
1629 1629 else:
1630 1630 leading = text[text_start:completion_start]
1631 1631
1632 1632 # the index of the `[` character
1633 1633 bracket_idx = match.end(1)
1634 1634
1635 1635 # append closing quote and bracket as appropriate
1636 1636 # this is *not* appropriate if the opening quote or bracket is outside
1637 1637 # the text given to this method
1638 1638 suf = ''
1639 1639 continuation = self.line_buffer[len(self.text_until_cursor):]
1640 1640 if key_start > text_start and closing_quote:
1641 1641 # quotes were opened inside text, maybe close them
1642 1642 if continuation.startswith(closing_quote):
1643 1643 continuation = continuation[len(closing_quote):]
1644 1644 else:
1645 1645 suf += closing_quote
1646 1646 if bracket_idx > text_start:
1647 1647 # brackets were opened inside text, maybe close them
1648 1648 if not continuation.startswith(']'):
1649 1649 suf += ']'
1650 1650
1651 1651 return [leading + k + suf for k in matches]
1652 1652
1653 1653 def unicode_name_matches(self, text):
1654 1654 u"""Match Latex-like syntax for unicode characters base
1655 1655 on the name of the character.
1656 1656
1657 1657 This does ``\\GREEK SMALL LETTER ETA`` -> ``η``
1658 1658
1659 1659 Works only on valid python 3 identifier, or on combining characters that
1660 1660 will combine to form a valid identifier.
1661 1661
1662 1662 Used on Python 3 only.
1663 1663 """
1664 1664 slashpos = text.rfind('\\')
1665 1665 if slashpos > -1:
1666 1666 s = text[slashpos+1:]
1667 1667 try :
1668 1668 unic = unicodedata.lookup(s)
1669 1669 # allow combining chars
1670 1670 if ('a'+unic).isidentifier():
1671 1671 return '\\'+s,[unic]
1672 1672 except KeyError:
1673 1673 pass
1674 1674 return u'', []
1675 1675
1676 1676
1677 1677 def latex_matches(self, text):
1678 1678 u"""Match Latex syntax for unicode characters.
1679 1679
1680 1680 This does both ``\\alp`` -> ``\\alpha`` and ``\\alpha`` -> ``α``
1681 1681
1682 1682 Used on Python 3 only.
1683 1683 """
1684 1684 slashpos = text.rfind('\\')
1685 1685 if slashpos > -1:
1686 1686 s = text[slashpos:]
1687 1687 if s in latex_symbols:
1688 1688 # Try to complete a full latex symbol to unicode
1689 1689 # \\alpha -> α
1690 1690 return s, [latex_symbols[s]]
1691 1691 else:
1692 1692 # If a user has partially typed a latex symbol, give them
1693 1693 # a full list of options \al -> [\aleph, \alpha]
1694 1694 matches = [k for k in latex_symbols if k.startswith(s)]
1695 1695 return s, matches
1696 1696 return u'', []
1697 1697
1698 1698 def dispatch_custom_completer(self, text):
1699 1699 if not self.custom_completers:
1700 1700 return
1701 1701
1702 1702 line = self.line_buffer
1703 1703 if not line.strip():
1704 1704 return None
1705 1705
1706 1706 # Create a little structure to pass all the relevant information about
1707 1707 # the current completion to any custom completer.
1708 1708 event = SimpleNamespace()
1709 1709 event.line = line
1710 1710 event.symbol = text
1711 1711 cmd = line.split(None,1)[0]
1712 1712 event.command = cmd
1713 1713 event.text_until_cursor = self.text_until_cursor
1714 1714
1715 1715 # for foo etc, try also to find completer for %foo
1716 1716 if not cmd.startswith(self.magic_escape):
1717 1717 try_magic = self.custom_completers.s_matches(
1718 1718 self.magic_escape + cmd)
1719 1719 else:
1720 1720 try_magic = []
1721 1721
1722 1722 for c in itertools.chain(self.custom_completers.s_matches(cmd),
1723 1723 try_magic,
1724 1724 self.custom_completers.flat_matches(self.text_until_cursor)):
1725 1725 try:
1726 1726 res = c(event)
1727 1727 if res:
1728 1728 # first, try case sensitive match
1729 1729 withcase = [r for r in res if r.startswith(text)]
1730 1730 if withcase:
1731 1731 return withcase
1732 1732 # if none, then case insensitive ones are ok too
1733 1733 text_low = text.lower()
1734 1734 return [r for r in res if r.lower().startswith(text_low)]
1735 1735 except TryNext:
1736 1736 pass
1737 1737 except KeyboardInterrupt:
1738 1738 """
1739 1739 If custom completer take too long,
1740 1740 let keyboard interrupt abort and return nothing.
1741 1741 """
1742 1742 break
1743 1743
1744 1744 return None
1745 1745
1746 1746 def completions(self, text: str, offset: int)->Iterator[Completion]:
1747 1747 """
1748 1748 Returns an iterator over the possible completions
1749 1749
1750 1750 .. warning:: Unstable
1751 1751
1752 1752 This function is unstable, API may change without warning.
1753 1753 It will also raise unless use in proper context manager.
1754 1754
1755 1755 Parameters
1756 1756 ----------
1757 1757
1758 1758 text:str
1759 1759 Full text of the current input, multi line string.
1760 1760 offset:int
1761 1761 Integer representing the position of the cursor in ``text``. Offset
1762 1762 is 0-based indexed.
1763 1763
1764 1764 Yields
1765 1765 ------
1766 1766 :any:`Completion` object
1767 1767
1768 1768
1769 1769 The cursor on a text can either be seen as being "in between"
1770 1770 characters or "On" a character depending on the interface visible to
1771 1771 the user. For consistency the cursor being on "in between" characters X
1772 1772 and Y is equivalent to the cursor being "on" character Y, that is to say
1773 1773 the character the cursor is on is considered as being after the cursor.
1774 1774
1775 1775 Combining characters may span more that one position in the
1776 1776 text.
1777 1777
1778 1778
1779 1779 .. note::
1780 1780
1781 1781 If ``IPCompleter.debug`` is :any:`True` will yield a ``--jedi/ipython--``
1782 1782 fake Completion token to distinguish completion returned by Jedi
1783 1783 and usual IPython completion.
1784 1784
1785 1785 .. note::
1786 1786
1787 1787 Completions are not completely deduplicated yet. If identical
1788 1788 completions are coming from different sources this function does not
1789 1789 ensure that each completion object will only be present once.
1790 1790 """
1791 1791 warnings.warn("_complete is a provisional API (as of IPython 6.0). "
1792 1792 "It may change without warnings. "
1793 1793 "Use in corresponding context manager.",
1794 1794 category=ProvisionalCompleterWarning, stacklevel=2)
1795 1795
1796 1796 seen = set()
1797 1797 for c in self._completions(text, offset, _timeout=self.jedi_compute_type_timeout/1000):
1798 1798 if c and (c in seen):
1799 1799 continue
1800 1800 yield c
1801 1801 seen.add(c)
1802 1802
1803 1803 def _completions(self, full_text: str, offset: int, *, _timeout)->Iterator[Completion]:
1804 1804 """
1805 1805 Core completion module.Same signature as :any:`completions`, with the
1806 1806 extra `timeout` parameter (in seconds).
1807 1807
1808 1808
1809 1809 Computing jedi's completion ``.type`` can be quite expensive (it is a
1810 1810 lazy property) and can require some warm-up, more warm up than just
1811 1811 computing the ``name`` of a completion. The warm-up can be :
1812 1812
1813 1813 - Long warm-up the first time a module is encountered after
1814 1814 install/update: actually build parse/inference tree.
1815 1815
1816 1816 - first time the module is encountered in a session: load tree from
1817 1817 disk.
1818 1818
1819 1819 We don't want to block completions for tens of seconds so we give the
1820 1820 completer a "budget" of ``_timeout`` seconds per invocation to compute
1821 1821 completions types, the completions that have not yet been computed will
1822 1822 be marked as "unknown" an will have a chance to be computed next round
1823 1823 are things get cached.
1824 1824
1825 1825 Keep in mind that Jedi is not the only thing treating the completion so
1826 1826 keep the timeout short-ish as if we take more than 0.3 second we still
1827 1827 have lots of processing to do.
1828 1828
1829 1829 """
1830 1830 deadline = time.monotonic() + _timeout
1831 1831
1832 1832
1833 1833 before = full_text[:offset]
1834 1834 cursor_line, cursor_column = position_to_cursor(full_text, offset)
1835 1835
1836 1836 matched_text, matches, matches_origin, jedi_matches = self._complete(
1837 1837 full_text=full_text, cursor_line=cursor_line, cursor_pos=cursor_column)
1838 1838
1839 1839 iter_jm = iter(jedi_matches)
1840 1840 if _timeout:
1841 1841 for jm in iter_jm:
1842 1842 try:
1843 1843 type_ = jm.type
1844 1844 except Exception:
1845 1845 if self.debug:
1846 1846 print("Error in Jedi getting type of ", jm)
1847 1847 type_ = None
1848 1848 delta = len(jm.name_with_symbols) - len(jm.complete)
1849 1849 if type_ == 'function':
1850 1850 signature = _make_signature(jm)
1851 1851 else:
1852 1852 signature = ''
1853 1853 yield Completion(start=offset - delta,
1854 1854 end=offset,
1855 1855 text=jm.name_with_symbols,
1856 1856 type=type_,
1857 1857 signature=signature,
1858 1858 _origin='jedi')
1859 1859
1860 1860 if time.monotonic() > deadline:
1861 1861 break
1862 1862
1863 1863 for jm in iter_jm:
1864 1864 delta = len(jm.name_with_symbols) - len(jm.complete)
1865 1865 yield Completion(start=offset - delta,
1866 1866 end=offset,
1867 1867 text=jm.name_with_symbols,
1868 1868 type='<unknown>', # don't compute type for speed
1869 1869 _origin='jedi',
1870 1870 signature='')
1871 1871
1872 1872
1873 1873 start_offset = before.rfind(matched_text)
1874 1874
1875 1875 # TODO:
1876 # Supress this, right now just for debug.
1876 # Suppress this, right now just for debug.
1877 1877 if jedi_matches and matches and self.debug:
1878 1878 yield Completion(start=start_offset, end=offset, text='--jedi/ipython--',
1879 1879 _origin='debug', type='none', signature='')
1880 1880
1881 1881 # I'm unsure if this is always true, so let's assert and see if it
1882 1882 # crash
1883 1883 assert before.endswith(matched_text)
1884 1884 for m, t in zip(matches, matches_origin):
1885 1885 yield Completion(start=start_offset, end=offset, text=m, _origin=t, signature='', type='<unknown>')
1886 1886
1887 1887
1888 1888 def complete(self, text=None, line_buffer=None, cursor_pos=None):
1889 1889 """Find completions for the given text and line context.
1890 1890
1891 1891 Note that both the text and the line_buffer are optional, but at least
1892 1892 one of them must be given.
1893 1893
1894 1894 Parameters
1895 1895 ----------
1896 1896 text : string, optional
1897 1897 Text to perform the completion on. If not given, the line buffer
1898 1898 is split using the instance's CompletionSplitter object.
1899 1899
1900 1900 line_buffer : string, optional
1901 1901 If not given, the completer attempts to obtain the current line
1902 1902 buffer via readline. This keyword allows clients which are
1903 1903 requesting for text completions in non-readline contexts to inform
1904 1904 the completer of the entire text.
1905 1905
1906 1906 cursor_pos : int, optional
1907 1907 Index of the cursor in the full line buffer. Should be provided by
1908 1908 remote frontends where kernel has no access to frontend state.
1909 1909
1910 1910 Returns
1911 1911 -------
1912 1912 text : str
1913 1913 Text that was actually used in the completion.
1914 1914
1915 1915 matches : list
1916 1916 A list of completion matches.
1917 1917
1918 1918
1919 1919 .. note::
1920 1920
1921 1921 This API is likely to be deprecated and replaced by
1922 1922 :any:`IPCompleter.completions` in the future.
1923 1923
1924 1924
1925 1925 """
1926 1926 warnings.warn('`Completer.complete` is pending deprecation since '
1927 1927 'IPython 6.0 and will be replaced by `Completer.completions`.',
1928 1928 PendingDeprecationWarning)
1929 1929 # potential todo, FOLD the 3rd throw away argument of _complete
1930 1930 # into the first 2 one.
1931 1931 return self._complete(line_buffer=line_buffer, cursor_pos=cursor_pos, text=text, cursor_line=0)[:2]
1932 1932
1933 1933 def _complete(self, *, cursor_line, cursor_pos, line_buffer=None, text=None,
1934 1934 full_text=None, return_jedi_results=True) -> Tuple[str, List[str], List[str], Iterable[_FakeJediCompletion]]:
1935 1935 """
1936 1936
1937 1937 Like complete but can also returns raw jedi completions as well as the
1938 1938 origin of the completion text. This could (and should) be made much
1939 1939 cleaner but that will be simpler once we drop the old (and stateful)
1940 1940 :any:`complete` API.
1941 1941
1942 1942
1943 1943 With current provisional API, cursor_pos act both (depending on the
1944 1944 caller) as the offset in the ``text`` or ``line_buffer``, or as the
1945 1945 ``column`` when passing multiline strings this could/should be renamed
1946 1946 but would add extra noise.
1947 1947 """
1948 1948
1949 1949 # if the cursor position isn't given, the only sane assumption we can
1950 1950 # make is that it's at the end of the line (the common case)
1951 1951 if cursor_pos is None:
1952 1952 cursor_pos = len(line_buffer) if text is None else len(text)
1953 1953
1954 1954 if self.use_main_ns:
1955 1955 self.namespace = __main__.__dict__
1956 1956
1957 1957 # if text is either None or an empty string, rely on the line buffer
1958 1958 if (not line_buffer) and full_text:
1959 1959 line_buffer = full_text.split('\n')[cursor_line]
1960 1960 if not text:
1961 1961 text = self.splitter.split_line(line_buffer, cursor_pos)
1962 1962
1963 1963 if self.backslash_combining_completions:
1964 1964 # allow deactivation of these on windows.
1965 1965 base_text = text if not line_buffer else line_buffer[:cursor_pos]
1966 1966 latex_text, latex_matches = self.latex_matches(base_text)
1967 1967 if latex_matches:
1968 1968 return latex_text, latex_matches, ['latex_matches']*len(latex_matches), ()
1969 1969 name_text = ''
1970 1970 name_matches = []
1971 1971 for meth in (self.unicode_name_matches, back_latex_name_matches, back_unicode_name_matches):
1972 1972 name_text, name_matches = meth(base_text)
1973 1973 if name_text:
1974 1974 return name_text, name_matches[:MATCHES_LIMIT], \
1975 1975 [meth.__qualname__]*min(len(name_matches), MATCHES_LIMIT), ()
1976 1976
1977 1977
1978 1978 # If no line buffer is given, assume the input text is all there was
1979 1979 if line_buffer is None:
1980 1980 line_buffer = text
1981 1981
1982 1982 self.line_buffer = line_buffer
1983 1983 self.text_until_cursor = self.line_buffer[:cursor_pos]
1984 1984
1985 1985 # Do magic arg matches
1986 1986 for matcher in self.magic_arg_matchers:
1987 1987 matches = list(matcher(line_buffer))[:MATCHES_LIMIT]
1988 1988 if matches:
1989 1989 origins = [matcher.__qualname__] * len(matches)
1990 1990 return text, matches, origins, ()
1991 1991
1992 1992 # Start with a clean slate of completions
1993 1993 matches = []
1994 1994 custom_res = self.dispatch_custom_completer(text)
1995 1995 # FIXME: we should extend our api to return a dict with completions for
1996 1996 # different types of objects. The rlcomplete() method could then
1997 1997 # simply collapse the dict into a list for readline, but we'd have
1998 1998 # richer completion semantics in other evironments.
1999 1999 completions = ()
2000 2000 if self.use_jedi and return_jedi_results:
2001 2001 if not full_text:
2002 2002 full_text = line_buffer
2003 2003 completions = self._jedi_matches(
2004 2004 cursor_pos, cursor_line, full_text)
2005 2005 if custom_res is not None:
2006 2006 # did custom completers produce something?
2007 2007 matches = [(m, 'custom') for m in custom_res]
2008 2008 else:
2009 2009 # Extend the list of completions with the results of each
2010 2010 # matcher, so we return results to the user from all
2011 2011 # namespaces.
2012 2012 if self.merge_completions:
2013 2013 matches = []
2014 2014 for matcher in self.matchers:
2015 2015 try:
2016 2016 matches.extend([(m, matcher.__qualname__)
2017 2017 for m in matcher(text)])
2018 2018 except:
2019 2019 # Show the ugly traceback if the matcher causes an
2020 2020 # exception, but do NOT crash the kernel!
2021 2021 sys.excepthook(*sys.exc_info())
2022 2022 else:
2023 2023 for matcher in self.matchers:
2024 2024 matches = [(m, matcher.__qualname__)
2025 2025 for m in matcher(text)]
2026 2026 if matches:
2027 2027 break
2028 2028 seen = set()
2029 2029 filtered_matches = set()
2030 2030 for m in matches:
2031 2031 t, c = m
2032 2032 if t not in seen:
2033 2033 filtered_matches.add(m)
2034 2034 seen.add(t)
2035 2035
2036 2036 _filtered_matches = sorted(
2037 2037 set(filtered_matches), key=lambda x: completions_sorting_key(x[0]))\
2038 2038 [:MATCHES_LIMIT]
2039 2039
2040 2040 _matches = [m[0] for m in _filtered_matches]
2041 2041 origins = [m[1] for m in _filtered_matches]
2042 2042
2043 2043 self.matches = _matches
2044 2044
2045 2045 return text, _matches, origins, completions
@@ -1,229 +1,229 b''
1 1 """Hooks for IPython.
2 2
3 3 In Python, it is possible to overwrite any method of any object if you really
4 4 want to. But IPython exposes a few 'hooks', methods which are *designed* to
5 5 be overwritten by users for customization purposes. This module defines the
6 6 default versions of all such hooks, which get used by IPython if not
7 7 overridden by the user.
8 8
9 9 Hooks are simple functions, but they should be declared with ``self`` as their
10 10 first argument, because when activated they are registered into IPython as
11 11 instance methods. The self argument will be the IPython running instance
12 12 itself, so hooks have full access to the entire IPython object.
13 13
14 14 If you wish to define a new hook and activate it, you can make an :doc:`extension
15 15 </config/extensions/index>` or a :ref:`startup script <startup_files>`. For
16 16 example, you could use a startup file like this::
17 17
18 18 import os
19 19
20 20 def calljed(self,filename, linenum):
21 21 "My editor hook calls the jed editor directly."
22 22 print "Calling my own editor, jed ..."
23 23 if os.system('jed +%d %s' % (linenum,filename)) != 0:
24 24 raise TryNext()
25 25
26 26 def load_ipython_extension(ip):
27 27 ip.set_hook('editor', calljed)
28 28
29 29 """
30 30
31 31 #*****************************************************************************
32 32 # Copyright (C) 2005 Fernando Perez. <fperez@colorado.edu>
33 33 #
34 34 # Distributed under the terms of the BSD License. The full license is in
35 35 # the file COPYING, distributed as part of this software.
36 36 #*****************************************************************************
37 37
38 38 import os
39 39 import subprocess
40 40 import warnings
41 41 import sys
42 42
43 43 from IPython.core.error import TryNext
44 44
45 45 # List here all the default hooks. For now it's just the editor functions
46 46 # but over time we'll move here all the public API for user-accessible things.
47 47
48 48 __all__ = ['editor', 'synchronize_with_editor',
49 49 'shutdown_hook', 'late_startup_hook',
50 50 'show_in_pager','pre_prompt_hook',
51 51 'pre_run_code_hook', 'clipboard_get']
52 52
53 53 deprecated = {'pre_run_code_hook': "a callback for the 'pre_execute' or 'pre_run_cell' event",
54 54 'late_startup_hook': "a callback for the 'shell_initialized' event",
55 55 'shutdown_hook': "the atexit module",
56 56 }
57 57
58 58 def editor(self, filename, linenum=None, wait=True):
59 59 """Open the default editor at the given filename and linenumber.
60 60
61 61 This is IPython's default editor hook, you can use it as an example to
62 62 write your own modified one. To set your own editor function as the
63 63 new editor hook, call ip.set_hook('editor',yourfunc)."""
64 64
65 65 # IPython configures a default editor at startup by reading $EDITOR from
66 66 # the environment, and falling back on vi (unix) or notepad (win32).
67 67 editor = self.editor
68 68
69 69 # marker for at which line to open the file (for existing objects)
70 70 if linenum is None or editor=='notepad':
71 71 linemark = ''
72 72 else:
73 73 linemark = '+%d' % int(linenum)
74 74
75 75 # Enclose in quotes if necessary and legal
76 76 if ' ' in editor and os.path.isfile(editor) and editor[0] != '"':
77 77 editor = '"%s"' % editor
78 78
79 79 # Call the actual editor
80 80 proc = subprocess.Popen('%s %s %s' % (editor, linemark, filename),
81 81 shell=True)
82 82 if wait and proc.wait() != 0:
83 83 raise TryNext()
84 84
85 85 import tempfile
86 86 from IPython.utils.decorators import undoc
87 87
88 88 @undoc
89 89 def fix_error_editor(self,filename,linenum,column,msg):
90 90 """DEPRECATED
91 91
92 92 Open the editor at the given filename, linenumber, column and
93 93 show an error message. This is used for correcting syntax errors.
94 94 The current implementation only has special support for the VIM editor,
95 95 and falls back on the 'editor' hook if VIM is not used.
96 96
97 97 Call ip.set_hook('fix_error_editor',yourfunc) to use your own function,
98 98 """
99 99
100 100 warnings.warn("""
101 101 `fix_error_editor` is deprecated as of IPython 6.0 and will be removed
102 102 in future versions. It appears to be used only for automatically fixing syntax
103 103 error that has been broken for a few years and has thus been removed. If you
104 happend to use this function and still need it please make your voice heard on
104 happened to use this function and still need it please make your voice heard on
105 105 the mailing list ipython-dev@python.org , or on the GitHub Issue tracker:
106 106 https://github.com/ipython/ipython/issues/9649 """, UserWarning)
107 107
108 108 def vim_quickfix_file():
109 109 t = tempfile.NamedTemporaryFile()
110 110 t.write('%s:%d:%d:%s\n' % (filename,linenum,column,msg))
111 111 t.flush()
112 112 return t
113 113 if os.path.basename(self.editor) != 'vim':
114 114 self.hooks.editor(filename,linenum)
115 115 return
116 116 t = vim_quickfix_file()
117 117 try:
118 118 if os.system('vim --cmd "set errorformat=%f:%l:%c:%m" -q ' + t.name):
119 119 raise TryNext()
120 120 finally:
121 121 t.close()
122 122
123 123
124 124 def synchronize_with_editor(self, filename, linenum, column):
125 125 pass
126 126
127 127
128 128 class CommandChainDispatcher:
129 129 """ Dispatch calls to a chain of commands until some func can handle it
130 130
131 131 Usage: instantiate, execute "add" to add commands (with optional
132 132 priority), execute normally via f() calling mechanism.
133 133
134 134 """
135 135 def __init__(self,commands=None):
136 136 if commands is None:
137 137 self.chain = []
138 138 else:
139 139 self.chain = commands
140 140
141 141
142 142 def __call__(self,*args, **kw):
143 143 """ Command chain is called just like normal func.
144 144
145 145 This will call all funcs in chain with the same args as were given to
146 146 this function, and return the result of first func that didn't raise
147 147 TryNext"""
148 148 last_exc = TryNext()
149 149 for prio,cmd in self.chain:
150 150 #print "prio",prio,"cmd",cmd #dbg
151 151 try:
152 152 return cmd(*args, **kw)
153 153 except TryNext as exc:
154 154 last_exc = exc
155 155 # if no function will accept it, raise TryNext up to the caller
156 156 raise last_exc
157 157
158 158 def __str__(self):
159 159 return str(self.chain)
160 160
161 161 def add(self, func, priority=0):
162 162 """ Add a func to the cmd chain with given priority """
163 163 self.chain.append((priority, func))
164 164 self.chain.sort(key=lambda x: x[0])
165 165
166 166 def __iter__(self):
167 167 """ Return all objects in chain.
168 168
169 169 Handy if the objects are not callable.
170 170 """
171 171 return iter(self.chain)
172 172
173 173
174 174 def shutdown_hook(self):
175 175 """ default shutdown hook
176 176
177 177 Typically, shotdown hooks should raise TryNext so all shutdown ops are done
178 178 """
179 179
180 180 #print "default shutdown hook ok" # dbg
181 181 return
182 182
183 183
184 184 def late_startup_hook(self):
185 185 """ Executed after ipython has been constructed and configured
186 186
187 187 """
188 188 #print "default startup hook ok" # dbg
189 189
190 190
191 191 def show_in_pager(self, data, start, screen_lines):
192 192 """ Run a string through pager """
193 193 # raising TryNext here will use the default paging functionality
194 194 raise TryNext
195 195
196 196
197 197 def pre_prompt_hook(self):
198 198 """ Run before displaying the next prompt
199 199
200 200 Use this e.g. to display output from asynchronous operations (in order
201 201 to not mess up text entry)
202 202 """
203 203
204 204 return None
205 205
206 206
207 207 def pre_run_code_hook(self):
208 208 """ Executed before running the (prefiltered) code in IPython """
209 209 return None
210 210
211 211
212 212 def clipboard_get(self):
213 213 """ Get text from the clipboard.
214 214 """
215 215 from IPython.lib.clipboard import (
216 216 osx_clipboard_get, tkinter_clipboard_get,
217 217 win32_clipboard_get
218 218 )
219 219 if sys.platform == 'win32':
220 220 chain = [win32_clipboard_get, tkinter_clipboard_get]
221 221 elif sys.platform == 'darwin':
222 222 chain = [osx_clipboard_get, tkinter_clipboard_get]
223 223 else:
224 224 chain = [tkinter_clipboard_get]
225 225 dispatcher = CommandChainDispatcher()
226 226 for func in chain:
227 227 dispatcher.add(func)
228 228 text = dispatcher()
229 229 return text
@@ -1,3322 +1,3322 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Main IPython class."""
3 3
4 4 #-----------------------------------------------------------------------------
5 5 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de>
6 6 # Copyright (C) 2001-2007 Fernando Perez. <fperez@colorado.edu>
7 7 # Copyright (C) 2008-2011 The IPython Development Team
8 8 #
9 9 # Distributed under the terms of the BSD License. The full license is in
10 10 # the file COPYING, distributed as part of this software.
11 11 #-----------------------------------------------------------------------------
12 12
13 13
14 14 import abc
15 15 import ast
16 16 import atexit
17 17 import builtins as builtin_mod
18 18 import functools
19 19 import os
20 20 import re
21 21 import runpy
22 22 import sys
23 23 import tempfile
24 24 import traceback
25 25 import types
26 26 import subprocess
27 27 import warnings
28 28 from io import open as io_open
29 29
30 30 from pickleshare import PickleShareDB
31 31
32 32 from traitlets.config.configurable import SingletonConfigurable
33 33 from IPython.core import 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 ultratb
38 38 from IPython.core.alias import Alias, AliasManager
39 39 from IPython.core.autocall import ExitAutocall
40 40 from IPython.core.builtin_trap import BuiltinTrap
41 41 from IPython.core.events import EventManager, available_events
42 42 from IPython.core.compilerop import CachingCompiler, check_linecache_ipython
43 43 from IPython.core.debugger import Pdb
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 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.usage import default_banner
58 58 from IPython.display import display
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.paths import get_ipython_dir
68 68 from IPython.utils.path import get_home_dir, get_py_filename, ensure_dir_exists
69 69 from IPython.utils.process import system, getoutput
70 70 from IPython.utils.strdispatch import StrDispatch
71 71 from IPython.utils.syspathcontext import prepended_to_syspath
72 72 from IPython.utils.text import format_screen, LSString, SList, DollarFormatter
73 73 from IPython.utils.tempdir import TemporaryDirectory
74 74 from traitlets import (
75 75 Integer, Bool, CaselessStrEnum, Enum, List, Dict, Unicode, Instance, Type,
76 76 observe, default,
77 77 )
78 78 from warnings import warn
79 79 from logging import error
80 80 import IPython.core.hooks
81 81
82 82 from typing import List as ListType
83 83 from ast import AST
84 84
85 85 # NoOpContext is deprecated, but ipykernel imports it from here.
86 86 # See https://github.com/ipython/ipykernel/issues/157
87 87 from IPython.utils.contexts import NoOpContext
88 88
89 89 try:
90 90 import docrepr.sphinxify as sphx
91 91
92 92 def sphinxify(doc):
93 93 with TemporaryDirectory() as dirname:
94 94 return {
95 95 'text/html': sphx.sphinxify(doc, dirname),
96 96 'text/plain': doc
97 97 }
98 98 except ImportError:
99 99 sphinxify = None
100 100
101 101
102 102 class ProvisionalWarning(DeprecationWarning):
103 103 """
104 104 Warning class for unstable features
105 105 """
106 106 pass
107 107
108 108 if sys.version_info > (3,6):
109 109 _assign_nodes = (ast.AugAssign, ast.AnnAssign, ast.Assign)
110 110 _single_targets_nodes = (ast.AugAssign, ast.AnnAssign)
111 111 else:
112 112 _assign_nodes = (ast.AugAssign, ast.Assign )
113 113 _single_targets_nodes = (ast.AugAssign, )
114 114
115 115 #-----------------------------------------------------------------------------
116 116 # Globals
117 117 #-----------------------------------------------------------------------------
118 118
119 119 # compiled regexps for autoindent management
120 120 dedent_re = re.compile(r'^\s+raise|^\s+return|^\s+pass')
121 121
122 122 #-----------------------------------------------------------------------------
123 123 # Utilities
124 124 #-----------------------------------------------------------------------------
125 125
126 126 @undoc
127 127 def softspace(file, newvalue):
128 128 """Copied from code.py, to remove the dependency"""
129 129
130 130 oldvalue = 0
131 131 try:
132 132 oldvalue = file.softspace
133 133 except AttributeError:
134 134 pass
135 135 try:
136 136 file.softspace = newvalue
137 137 except (AttributeError, TypeError):
138 138 # "attribute-less object" or "read-only attributes"
139 139 pass
140 140 return oldvalue
141 141
142 142 @undoc
143 143 def no_op(*a, **kw):
144 144 pass
145 145
146 146
147 147 class SpaceInInput(Exception): pass
148 148
149 149
150 150 def get_default_colors():
151 151 "DEPRECATED"
152 152 warn('get_default_color is deprecated since IPython 5.0, and returns `Neutral` on all platforms.',
153 153 DeprecationWarning, stacklevel=2)
154 154 return 'Neutral'
155 155
156 156
157 157 class SeparateUnicode(Unicode):
158 158 r"""A Unicode subclass to validate separate_in, separate_out, etc.
159 159
160 160 This is a Unicode based trait that converts '0'->'' and ``'\\n'->'\n'``.
161 161 """
162 162
163 163 def validate(self, obj, value):
164 164 if value == '0': value = ''
165 165 value = value.replace('\\n','\n')
166 166 return super(SeparateUnicode, self).validate(obj, value)
167 167
168 168
169 169 @undoc
170 170 class DummyMod(object):
171 171 """A dummy module used for IPython's interactive module when
172 172 a namespace must be assigned to the module's __dict__."""
173 173 pass
174 174
175 175
176 176 class ExecutionInfo(object):
177 177 """The arguments used for a call to :meth:`InteractiveShell.run_cell`
178 178
179 179 Stores information about what is going to happen.
180 180 """
181 181 raw_cell = None
182 182 store_history = False
183 183 silent = False
184 184 shell_futures = True
185 185
186 186 def __init__(self, raw_cell, store_history, silent, shell_futures):
187 187 self.raw_cell = raw_cell
188 188 self.store_history = store_history
189 189 self.silent = silent
190 190 self.shell_futures = shell_futures
191 191
192 192 def __repr__(self):
193 193 name = self.__class__.__qualname__
194 194 raw_cell = ((self.raw_cell[:50] + '..')
195 195 if len(self.raw_cell) > 50 else self.raw_cell)
196 196 return '<%s object at %x, raw_cell="%s" store_history=%s silent=%s shell_futures=%s result=%s>' %\
197 197 (name, id(self), raw_cell, store_history, silent, shell_futures, repr(self.result))
198 198
199 199
200 200 class ExecutionResult(object):
201 201 """The result of a call to :meth:`InteractiveShell.run_cell`
202 202
203 203 Stores information about what took place.
204 204 """
205 205 execution_count = None
206 206 error_before_exec = None
207 207 error_in_exec = None
208 208 info = None
209 209 result = None
210 210
211 211 def __init__(self, info):
212 212 self.info = info
213 213
214 214 @property
215 215 def success(self):
216 216 return (self.error_before_exec is None) and (self.error_in_exec is None)
217 217
218 218 def raise_error(self):
219 219 """Reraises error if `success` is `False`, otherwise does nothing"""
220 220 if self.error_before_exec is not None:
221 221 raise self.error_before_exec
222 222 if self.error_in_exec is not None:
223 223 raise self.error_in_exec
224 224
225 225 def __repr__(self):
226 226 name = self.__class__.__qualname__
227 227 return '<%s object at %x, execution_count=%s error_before_exec=%s error_in_exec=%s info=%s result=%s>' %\
228 228 (name, id(self), self.execution_count, self.error_before_exec, self.error_in_exec, repr(self.info), repr(self.result))
229 229
230 230
231 231 class InteractiveShell(SingletonConfigurable):
232 232 """An enhanced, interactive shell for Python."""
233 233
234 234 _instance = None
235 235
236 236 ast_transformers = List([], help=
237 237 """
238 238 A list of ast.NodeTransformer subclass instances, which will be applied
239 239 to user input before code is run.
240 240 """
241 241 ).tag(config=True)
242 242
243 243 autocall = Enum((0,1,2), default_value=0, help=
244 244 """
245 245 Make IPython automatically call any callable object even if you didn't
246 246 type explicit parentheses. For example, 'str 43' becomes 'str(43)'
247 247 automatically. The value can be '0' to disable the feature, '1' for
248 248 'smart' autocall, where it is not applied if there are no more
249 249 arguments on the line, and '2' for 'full' autocall, where all callable
250 250 objects are automatically called (even if no arguments are present).
251 251 """
252 252 ).tag(config=True)
253 253 # TODO: remove all autoindent logic and put into frontends.
254 254 # We can't do this yet because even runlines uses the autoindent.
255 255 autoindent = Bool(True, help=
256 256 """
257 257 Autoindent IPython code entered interactively.
258 258 """
259 259 ).tag(config=True)
260 260
261 261 automagic = Bool(True, help=
262 262 """
263 263 Enable magic commands to be called without the leading %.
264 264 """
265 265 ).tag(config=True)
266 266
267 267 banner1 = Unicode(default_banner,
268 268 help="""The part of the banner to be printed before the profile"""
269 269 ).tag(config=True)
270 270 banner2 = Unicode('',
271 271 help="""The part of the banner to be printed after the profile"""
272 272 ).tag(config=True)
273 273
274 274 cache_size = Integer(1000, help=
275 275 """
276 276 Set the size of the output cache. The default is 1000, you can
277 277 change it permanently in your config file. Setting it to 0 completely
278 278 disables the caching system, and the minimum value accepted is 3 (if
279 279 you provide a value less than 3, it is reset to 0 and a warning is
280 280 issued). This limit is defined because otherwise you'll spend more
281 281 time re-flushing a too small cache than working
282 282 """
283 283 ).tag(config=True)
284 284 color_info = Bool(True, help=
285 285 """
286 286 Use colors for displaying information about objects. Because this
287 287 information is passed through a pager (like 'less'), and some pagers
288 288 get confused with color codes, this capability can be turned off.
289 289 """
290 290 ).tag(config=True)
291 291 colors = CaselessStrEnum(('Neutral', 'NoColor','LightBG','Linux'),
292 292 default_value='Neutral',
293 293 help="Set the color scheme (NoColor, Neutral, Linux, or LightBG)."
294 294 ).tag(config=True)
295 295 debug = Bool(False).tag(config=True)
296 296 disable_failing_post_execute = Bool(False,
297 297 help="Don't call post-execute functions that have failed in the past."
298 298 ).tag(config=True)
299 299 display_formatter = Instance(DisplayFormatter, allow_none=True)
300 300 displayhook_class = Type(DisplayHook)
301 301 display_pub_class = Type(DisplayPublisher)
302 302
303 303 sphinxify_docstring = Bool(False, help=
304 304 """
305 305 Enables rich html representation of docstrings. (This requires the
306 306 docrepr module).
307 307 """).tag(config=True)
308 308
309 309 @observe("sphinxify_docstring")
310 310 def _sphinxify_docstring_changed(self, change):
311 311 if change['new']:
312 312 warn("`sphinxify_docstring` is provisional since IPython 5.0 and might change in future versions." , ProvisionalWarning)
313 313
314 314 enable_html_pager = Bool(False, help=
315 315 """
316 316 (Provisional API) enables html representation in mime bundles sent
317 317 to pagers.
318 318 """).tag(config=True)
319 319
320 320 @observe("enable_html_pager")
321 321 def _enable_html_pager_changed(self, change):
322 322 if change['new']:
323 323 warn("`enable_html_pager` is provisional since IPython 5.0 and might change in future versions.", ProvisionalWarning)
324 324
325 325 data_pub_class = None
326 326
327 327 exit_now = Bool(False)
328 328 exiter = Instance(ExitAutocall)
329 329 @default('exiter')
330 330 def _exiter_default(self):
331 331 return ExitAutocall(self)
332 332 # Monotonically increasing execution counter
333 333 execution_count = Integer(1)
334 334 filename = Unicode("<ipython console>")
335 335 ipython_dir= Unicode('').tag(config=True) # Set to get_ipython_dir() in __init__
336 336
337 337 # Input splitter, to transform input line by line and detect when a block
338 338 # is ready to be executed.
339 339 input_splitter = Instance('IPython.core.inputsplitter.IPythonInputSplitter',
340 340 (), {'line_input_checker': True})
341 341
342 342 # This InputSplitter instance is used to transform completed cells before
343 343 # running them. It allows cell magics to contain blank lines.
344 344 input_transformer_manager = Instance('IPython.core.inputsplitter.IPythonInputSplitter',
345 345 (), {'line_input_checker': False})
346 346
347 347 logstart = Bool(False, help=
348 348 """
349 349 Start logging to the default log file in overwrite mode.
350 350 Use `logappend` to specify a log file to **append** logs to.
351 351 """
352 352 ).tag(config=True)
353 353 logfile = Unicode('', help=
354 354 """
355 355 The name of the logfile to use.
356 356 """
357 357 ).tag(config=True)
358 358 logappend = Unicode('', help=
359 359 """
360 360 Start logging to the given file in append mode.
361 361 Use `logfile` to specify a log file to **overwrite** logs to.
362 362 """
363 363 ).tag(config=True)
364 364 object_info_string_level = Enum((0,1,2), default_value=0,
365 365 ).tag(config=True)
366 366 pdb = Bool(False, help=
367 367 """
368 368 Automatically call the pdb debugger after every exception.
369 369 """
370 370 ).tag(config=True)
371 371 display_page = Bool(False,
372 372 help="""If True, anything that would be passed to the pager
373 373 will be displayed as regular output instead."""
374 374 ).tag(config=True)
375 375
376 376 # deprecated prompt traits:
377 377
378 378 prompt_in1 = Unicode('In [\\#]: ',
379 379 help="Deprecated since IPython 4.0 and ignored since 5.0, set TerminalInteractiveShell.prompts object directly."
380 380 ).tag(config=True)
381 381 prompt_in2 = Unicode(' .\\D.: ',
382 382 help="Deprecated since IPython 4.0 and ignored since 5.0, set TerminalInteractiveShell.prompts object directly."
383 383 ).tag(config=True)
384 384 prompt_out = Unicode('Out[\\#]: ',
385 385 help="Deprecated since IPython 4.0 and ignored since 5.0, set TerminalInteractiveShell.prompts object directly."
386 386 ).tag(config=True)
387 387 prompts_pad_left = Bool(True,
388 388 help="Deprecated since IPython 4.0 and ignored since 5.0, set TerminalInteractiveShell.prompts object directly."
389 389 ).tag(config=True)
390 390
391 391 @observe('prompt_in1', 'prompt_in2', 'prompt_out', 'prompt_pad_left')
392 392 def _prompt_trait_changed(self, change):
393 393 name = change['name']
394 394 warn("InteractiveShell.{name} is deprecated since IPython 4.0"
395 395 " and ignored since 5.0, set TerminalInteractiveShell.prompts"
396 396 " object directly.".format(name=name))
397 397
398 398 # protect against weird cases where self.config may not exist:
399 399
400 400 show_rewritten_input = Bool(True,
401 401 help="Show rewritten input, e.g. for autocall."
402 402 ).tag(config=True)
403 403
404 404 quiet = Bool(False).tag(config=True)
405 405
406 406 history_length = Integer(10000,
407 407 help='Total length of command history'
408 408 ).tag(config=True)
409 409
410 410 history_load_length = Integer(1000, help=
411 411 """
412 412 The number of saved history entries to be loaded
413 413 into the history buffer at startup.
414 414 """
415 415 ).tag(config=True)
416 416
417 417 ast_node_interactivity = Enum(['all', 'last', 'last_expr', 'none', 'last_expr_or_assign'],
418 418 default_value='last_expr',
419 419 help="""
420 420 'all', 'last', 'last_expr' or 'none', 'last_expr_or_assign' specifying
421 421 which nodes should be run interactively (displaying output from expressions).
422 422 """
423 423 ).tag(config=True)
424 424
425 425 # TODO: this part of prompt management should be moved to the frontends.
426 426 # Use custom TraitTypes that convert '0'->'' and '\\n'->'\n'
427 427 separate_in = SeparateUnicode('\n').tag(config=True)
428 428 separate_out = SeparateUnicode('').tag(config=True)
429 429 separate_out2 = SeparateUnicode('').tag(config=True)
430 430 wildcards_case_sensitive = Bool(True).tag(config=True)
431 431 xmode = CaselessStrEnum(('Context','Plain', 'Verbose'),
432 432 default_value='Context',
433 433 help="Switch modes for the IPython exception handlers."
434 434 ).tag(config=True)
435 435
436 436 # Subcomponents of InteractiveShell
437 437 alias_manager = Instance('IPython.core.alias.AliasManager', allow_none=True)
438 438 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager', allow_none=True)
439 439 builtin_trap = Instance('IPython.core.builtin_trap.BuiltinTrap', allow_none=True)
440 440 display_trap = Instance('IPython.core.display_trap.DisplayTrap', allow_none=True)
441 441 extension_manager = Instance('IPython.core.extensions.ExtensionManager', allow_none=True)
442 442 payload_manager = Instance('IPython.core.payload.PayloadManager', allow_none=True)
443 443 history_manager = Instance('IPython.core.history.HistoryAccessorBase', allow_none=True)
444 444 magics_manager = Instance('IPython.core.magic.MagicsManager', allow_none=True)
445 445
446 446 profile_dir = Instance('IPython.core.application.ProfileDir', allow_none=True)
447 447 @property
448 448 def profile(self):
449 449 if self.profile_dir is not None:
450 450 name = os.path.basename(self.profile_dir.location)
451 451 return name.replace('profile_','')
452 452
453 453
454 454 # Private interface
455 455 _post_execute = Dict()
456 456
457 457 # Tracks any GUI loop loaded for pylab
458 458 pylab_gui_select = None
459 459
460 460 last_execution_succeeded = Bool(True, help='Did last executed command succeeded')
461 461
462 462 last_execution_result = Instance('IPython.core.interactiveshell.ExecutionResult', help='Result of executing the last command', allow_none=True)
463 463
464 464 def __init__(self, ipython_dir=None, profile_dir=None,
465 465 user_module=None, user_ns=None,
466 466 custom_exceptions=((), None), **kwargs):
467 467
468 468 # This is where traits with a config_key argument are updated
469 469 # from the values on config.
470 470 super(InteractiveShell, self).__init__(**kwargs)
471 471 if 'PromptManager' in self.config:
472 472 warn('As of IPython 5.0 `PromptManager` config will have no effect'
473 473 ' and has been replaced by TerminalInteractiveShell.prompts_class')
474 474 self.configurables = [self]
475 475
476 476 # These are relatively independent and stateless
477 477 self.init_ipython_dir(ipython_dir)
478 478 self.init_profile_dir(profile_dir)
479 479 self.init_instance_attrs()
480 480 self.init_environment()
481 481
482 482 # Check if we're in a virtualenv, and set up sys.path.
483 483 self.init_virtualenv()
484 484
485 485 # Create namespaces (user_ns, user_global_ns, etc.)
486 486 self.init_create_namespaces(user_module, user_ns)
487 487 # This has to be done after init_create_namespaces because it uses
488 488 # something in self.user_ns, but before init_sys_modules, which
489 489 # is the first thing to modify sys.
490 490 # TODO: When we override sys.stdout and sys.stderr before this class
491 491 # is created, we are saving the overridden ones here. Not sure if this
492 492 # is what we want to do.
493 493 self.save_sys_module_state()
494 494 self.init_sys_modules()
495 495
496 496 # While we're trying to have each part of the code directly access what
497 497 # it needs without keeping redundant references to objects, we have too
498 498 # much legacy code that expects ip.db to exist.
499 499 self.db = PickleShareDB(os.path.join(self.profile_dir.location, 'db'))
500 500
501 501 self.init_history()
502 502 self.init_encoding()
503 503 self.init_prefilter()
504 504
505 505 self.init_syntax_highlighting()
506 506 self.init_hooks()
507 507 self.init_events()
508 508 self.init_pushd_popd_magic()
509 509 self.init_user_ns()
510 510 self.init_logger()
511 511 self.init_builtins()
512 512
513 513 # The following was in post_config_initialization
514 514 self.init_inspector()
515 515 self.raw_input_original = input
516 516 self.init_completer()
517 517 # TODO: init_io() needs to happen before init_traceback handlers
518 518 # because the traceback handlers hardcode the stdout/stderr streams.
519 519 # This logic in in debugger.Pdb and should eventually be changed.
520 520 self.init_io()
521 521 self.init_traceback_handlers(custom_exceptions)
522 522 self.init_prompts()
523 523 self.init_display_formatter()
524 524 self.init_display_pub()
525 525 self.init_data_pub()
526 526 self.init_displayhook()
527 527 self.init_magics()
528 528 self.init_alias()
529 529 self.init_logstart()
530 530 self.init_pdb()
531 531 self.init_extension_manager()
532 532 self.init_payload()
533 533 self.init_deprecation_warnings()
534 534 self.hooks.late_startup_hook()
535 535 self.events.trigger('shell_initialized', self)
536 536 atexit.register(self.atexit_operations)
537 537
538 538 def get_ipython(self):
539 539 """Return the currently running IPython instance."""
540 540 return self
541 541
542 542 #-------------------------------------------------------------------------
543 543 # Trait changed handlers
544 544 #-------------------------------------------------------------------------
545 545 @observe('ipython_dir')
546 546 def _ipython_dir_changed(self, change):
547 547 ensure_dir_exists(change['new'])
548 548
549 549 def set_autoindent(self,value=None):
550 550 """Set the autoindent flag.
551 551
552 552 If called with no arguments, it acts as a toggle."""
553 553 if value is None:
554 554 self.autoindent = not self.autoindent
555 555 else:
556 556 self.autoindent = value
557 557
558 558 #-------------------------------------------------------------------------
559 559 # init_* methods called by __init__
560 560 #-------------------------------------------------------------------------
561 561
562 562 def init_ipython_dir(self, ipython_dir):
563 563 if ipython_dir is not None:
564 564 self.ipython_dir = ipython_dir
565 565 return
566 566
567 567 self.ipython_dir = get_ipython_dir()
568 568
569 569 def init_profile_dir(self, profile_dir):
570 570 if profile_dir is not None:
571 571 self.profile_dir = profile_dir
572 572 return
573 573 self.profile_dir =\
574 574 ProfileDir.create_profile_dir_by_name(self.ipython_dir, 'default')
575 575
576 576 def init_instance_attrs(self):
577 577 self.more = False
578 578
579 579 # command compiler
580 580 self.compile = CachingCompiler()
581 581
582 582 # Make an empty namespace, which extension writers can rely on both
583 583 # existing and NEVER being used by ipython itself. This gives them a
584 584 # convenient location for storing additional information and state
585 585 # their extensions may require, without fear of collisions with other
586 586 # ipython names that may develop later.
587 587 self.meta = Struct()
588 588
589 589 # Temporary files used for various purposes. Deleted at exit.
590 590 self.tempfiles = []
591 591 self.tempdirs = []
592 592
593 593 # keep track of where we started running (mainly for crash post-mortem)
594 594 # This is not being used anywhere currently.
595 595 self.starting_dir = os.getcwd()
596 596
597 597 # Indentation management
598 598 self.indent_current_nsp = 0
599 599
600 600 # Dict to track post-execution functions that have been registered
601 601 self._post_execute = {}
602 602
603 603 def init_environment(self):
604 604 """Any changes we need to make to the user's environment."""
605 605 pass
606 606
607 607 def init_encoding(self):
608 608 # Get system encoding at startup time. Certain terminals (like Emacs
609 609 # under Win32 have it set to None, and we need to have a known valid
610 610 # encoding to use in the raw_input() method
611 611 try:
612 612 self.stdin_encoding = sys.stdin.encoding or 'ascii'
613 613 except AttributeError:
614 614 self.stdin_encoding = 'ascii'
615 615
616 616
617 617 @observe('colors')
618 618 def init_syntax_highlighting(self, changes=None):
619 619 # Python source parser/formatter for syntax highlighting
620 620 pyformat = PyColorize.Parser(style=self.colors, parent=self).format
621 621 self.pycolorize = lambda src: pyformat(src,'str')
622 622
623 623 def refresh_style(self):
624 624 # No-op here, used in subclass
625 625 pass
626 626
627 627 def init_pushd_popd_magic(self):
628 628 # for pushd/popd management
629 629 self.home_dir = get_home_dir()
630 630
631 631 self.dir_stack = []
632 632
633 633 def init_logger(self):
634 634 self.logger = Logger(self.home_dir, logfname='ipython_log.py',
635 635 logmode='rotate')
636 636
637 637 def init_logstart(self):
638 638 """Initialize logging in case it was requested at the command line.
639 639 """
640 640 if self.logappend:
641 641 self.magic('logstart %s append' % self.logappend)
642 642 elif self.logfile:
643 643 self.magic('logstart %s' % self.logfile)
644 644 elif self.logstart:
645 645 self.magic('logstart')
646 646
647 647 def init_deprecation_warnings(self):
648 648 """
649 649 register default filter for deprecation warning.
650 650
651 651 This will allow deprecation warning of function used interactively to show
652 652 warning to users, and still hide deprecation warning from libraries import.
653 653 """
654 654 warnings.filterwarnings("default", category=DeprecationWarning, module=self.user_ns.get("__name__"))
655 655
656 656 def init_builtins(self):
657 657 # A single, static flag that we set to True. Its presence indicates
658 658 # that an IPython shell has been created, and we make no attempts at
659 659 # removing on exit or representing the existence of more than one
660 660 # IPython at a time.
661 661 builtin_mod.__dict__['__IPYTHON__'] = True
662 662 builtin_mod.__dict__['display'] = display
663 663
664 664 self.builtin_trap = BuiltinTrap(shell=self)
665 665
666 666 @observe('colors')
667 667 def init_inspector(self, changes=None):
668 668 # Object inspector
669 669 self.inspector = oinspect.Inspector(oinspect.InspectColors,
670 670 PyColorize.ANSICodeColors,
671 671 self.colors,
672 672 self.object_info_string_level)
673 673
674 674 def init_io(self):
675 675 # This will just use sys.stdout and sys.stderr. If you want to
676 676 # override sys.stdout and sys.stderr themselves, you need to do that
677 677 # *before* instantiating this class, because io holds onto
678 678 # references to the underlying streams.
679 679 # io.std* are deprecated, but don't show our own deprecation warnings
680 680 # during initialization of the deprecated API.
681 681 with warnings.catch_warnings():
682 682 warnings.simplefilter('ignore', DeprecationWarning)
683 683 io.stdout = io.IOStream(sys.stdout)
684 684 io.stderr = io.IOStream(sys.stderr)
685 685
686 686 def init_prompts(self):
687 687 # Set system prompts, so that scripts can decide if they are running
688 688 # interactively.
689 689 sys.ps1 = 'In : '
690 690 sys.ps2 = '...: '
691 691 sys.ps3 = 'Out: '
692 692
693 693 def init_display_formatter(self):
694 694 self.display_formatter = DisplayFormatter(parent=self)
695 695 self.configurables.append(self.display_formatter)
696 696
697 697 def init_display_pub(self):
698 698 self.display_pub = self.display_pub_class(parent=self)
699 699 self.configurables.append(self.display_pub)
700 700
701 701 def init_data_pub(self):
702 702 if not self.data_pub_class:
703 703 self.data_pub = None
704 704 return
705 705 self.data_pub = self.data_pub_class(parent=self)
706 706 self.configurables.append(self.data_pub)
707 707
708 708 def init_displayhook(self):
709 709 # Initialize displayhook, set in/out prompts and printing system
710 710 self.displayhook = self.displayhook_class(
711 711 parent=self,
712 712 shell=self,
713 713 cache_size=self.cache_size,
714 714 )
715 715 self.configurables.append(self.displayhook)
716 716 # This is a context manager that installs/revmoes the displayhook at
717 717 # the appropriate time.
718 718 self.display_trap = DisplayTrap(hook=self.displayhook)
719 719
720 720 def init_virtualenv(self):
721 721 """Add a virtualenv to sys.path so the user can import modules from it.
722 722 This isn't perfect: it doesn't use the Python interpreter with which the
723 723 virtualenv was built, and it ignores the --no-site-packages option. A
724 724 warning will appear suggesting the user installs IPython in the
725 725 virtualenv, but for many cases, it probably works well enough.
726 726
727 727 Adapted from code snippets online.
728 728
729 729 http://blog.ufsoft.org/2009/1/29/ipython-and-virtualenv
730 730 """
731 731 if 'VIRTUAL_ENV' not in os.environ:
732 732 # Not in a virtualenv
733 733 return
734 734
735 735 # venv detection:
736 736 # stdlib venv may symlink sys.executable, so we can't use realpath.
737 737 # but others can symlink *to* the venv Python, so we can't just use sys.executable.
738 738 # So we just check every item in the symlink tree (generally <= 3)
739 739 p = os.path.normcase(sys.executable)
740 740 paths = [p]
741 741 while os.path.islink(p):
742 742 p = os.path.normcase(os.path.join(os.path.dirname(p), os.readlink(p)))
743 743 paths.append(p)
744 744 p_venv = os.path.normcase(os.environ['VIRTUAL_ENV'])
745 745
746 746 # In Cygwin paths like "c:\..." and '\cygdrive\c\...' are possible
747 747 if p_venv.startswith('\\cygdrive'):
748 748 p_venv = p_venv[11:]
749 749 elif len(p_venv) >= 2 and p_venv[1] == ':':
750 750 p_venv = p_venv[2:]
751 751
752 752 if any(p_venv in p for p in paths):
753 753 # Running properly in the virtualenv, don't need to do anything
754 754 return
755 755
756 756 warn("Attempting to work in a virtualenv. If you encounter problems, please "
757 757 "install IPython inside the virtualenv.")
758 758 if sys.platform == "win32":
759 759 virtual_env = os.path.join(os.environ['VIRTUAL_ENV'], 'Lib', 'site-packages')
760 760 else:
761 761 virtual_env = os.path.join(os.environ['VIRTUAL_ENV'], 'lib',
762 762 'python%d.%d' % sys.version_info[:2], 'site-packages')
763 763
764 764 import site
765 765 sys.path.insert(0, virtual_env)
766 766 site.addsitedir(virtual_env)
767 767
768 768 #-------------------------------------------------------------------------
769 769 # Things related to injections into the sys module
770 770 #-------------------------------------------------------------------------
771 771
772 772 def save_sys_module_state(self):
773 773 """Save the state of hooks in the sys module.
774 774
775 775 This has to be called after self.user_module is created.
776 776 """
777 777 self._orig_sys_module_state = {'stdin': sys.stdin,
778 778 'stdout': sys.stdout,
779 779 'stderr': sys.stderr,
780 780 'excepthook': sys.excepthook}
781 781 self._orig_sys_modules_main_name = self.user_module.__name__
782 782 self._orig_sys_modules_main_mod = sys.modules.get(self.user_module.__name__)
783 783
784 784 def restore_sys_module_state(self):
785 785 """Restore the state of the sys module."""
786 786 try:
787 787 for k, v in self._orig_sys_module_state.items():
788 788 setattr(sys, k, v)
789 789 except AttributeError:
790 790 pass
791 791 # Reset what what done in self.init_sys_modules
792 792 if self._orig_sys_modules_main_mod is not None:
793 793 sys.modules[self._orig_sys_modules_main_name] = self._orig_sys_modules_main_mod
794 794
795 795 #-------------------------------------------------------------------------
796 796 # Things related to the banner
797 797 #-------------------------------------------------------------------------
798 798
799 799 @property
800 800 def banner(self):
801 801 banner = self.banner1
802 802 if self.profile and self.profile != 'default':
803 803 banner += '\nIPython profile: %s\n' % self.profile
804 804 if self.banner2:
805 805 banner += '\n' + self.banner2
806 806 return banner
807 807
808 808 def show_banner(self, banner=None):
809 809 if banner is None:
810 810 banner = self.banner
811 811 sys.stdout.write(banner)
812 812
813 813 #-------------------------------------------------------------------------
814 814 # Things related to hooks
815 815 #-------------------------------------------------------------------------
816 816
817 817 def init_hooks(self):
818 818 # hooks holds pointers used for user-side customizations
819 819 self.hooks = Struct()
820 820
821 821 self.strdispatchers = {}
822 822
823 823 # Set all default hooks, defined in the IPython.hooks module.
824 824 hooks = IPython.core.hooks
825 825 for hook_name in hooks.__all__:
826 826 # default hooks have priority 100, i.e. low; user hooks should have
827 827 # 0-100 priority
828 828 self.set_hook(hook_name,getattr(hooks,hook_name), 100, _warn_deprecated=False)
829 829
830 830 if self.display_page:
831 831 self.set_hook('show_in_pager', page.as_hook(page.display_page), 90)
832 832
833 833 def set_hook(self,name,hook, priority=50, str_key=None, re_key=None,
834 834 _warn_deprecated=True):
835 835 """set_hook(name,hook) -> sets an internal IPython hook.
836 836
837 837 IPython exposes some of its internal API as user-modifiable hooks. By
838 838 adding your function to one of these hooks, you can modify IPython's
839 839 behavior to call at runtime your own routines."""
840 840
841 841 # At some point in the future, this should validate the hook before it
842 842 # accepts it. Probably at least check that the hook takes the number
843 843 # of args it's supposed to.
844 844
845 845 f = types.MethodType(hook,self)
846 846
847 847 # check if the hook is for strdispatcher first
848 848 if str_key is not None:
849 849 sdp = self.strdispatchers.get(name, StrDispatch())
850 850 sdp.add_s(str_key, f, priority )
851 851 self.strdispatchers[name] = sdp
852 852 return
853 853 if re_key is not None:
854 854 sdp = self.strdispatchers.get(name, StrDispatch())
855 855 sdp.add_re(re.compile(re_key), f, priority )
856 856 self.strdispatchers[name] = sdp
857 857 return
858 858
859 859 dp = getattr(self.hooks, name, None)
860 860 if name not in IPython.core.hooks.__all__:
861 861 print("Warning! Hook '%s' is not one of %s" % \
862 862 (name, IPython.core.hooks.__all__ ))
863 863
864 864 if _warn_deprecated and (name in IPython.core.hooks.deprecated):
865 865 alternative = IPython.core.hooks.deprecated[name]
866 866 warn("Hook {} is deprecated. Use {} instead.".format(name, alternative), stacklevel=2)
867 867
868 868 if not dp:
869 869 dp = IPython.core.hooks.CommandChainDispatcher()
870 870
871 871 try:
872 872 dp.add(f,priority)
873 873 except AttributeError:
874 874 # it was not commandchain, plain old func - replace
875 875 dp = f
876 876
877 877 setattr(self.hooks,name, dp)
878 878
879 879 #-------------------------------------------------------------------------
880 880 # Things related to events
881 881 #-------------------------------------------------------------------------
882 882
883 883 def init_events(self):
884 884 self.events = EventManager(self, available_events)
885 885
886 886 self.events.register("pre_execute", self._clear_warning_registry)
887 887
888 888 def register_post_execute(self, func):
889 889 """DEPRECATED: Use ip.events.register('post_run_cell', func)
890 890
891 891 Register a function for calling after code execution.
892 892 """
893 893 warn("ip.register_post_execute is deprecated, use "
894 894 "ip.events.register('post_run_cell', func) instead.", stacklevel=2)
895 895 self.events.register('post_run_cell', func)
896 896
897 897 def _clear_warning_registry(self):
898 898 # clear the warning registry, so that different code blocks with
899 899 # overlapping line number ranges don't cause spurious suppression of
900 900 # warnings (see gh-6611 for details)
901 901 if "__warningregistry__" in self.user_global_ns:
902 902 del self.user_global_ns["__warningregistry__"]
903 903
904 904 #-------------------------------------------------------------------------
905 905 # Things related to the "main" module
906 906 #-------------------------------------------------------------------------
907 907
908 908 def new_main_mod(self, filename, modname):
909 909 """Return a new 'main' module object for user code execution.
910 910
911 911 ``filename`` should be the path of the script which will be run in the
912 912 module. Requests with the same filename will get the same module, with
913 913 its namespace cleared.
914 914
915 915 ``modname`` should be the module name - normally either '__main__' or
916 916 the basename of the file without the extension.
917 917
918 918 When scripts are executed via %run, we must keep a reference to their
919 919 __main__ module around so that Python doesn't
920 920 clear it, rendering references to module globals useless.
921 921
922 922 This method keeps said reference in a private dict, keyed by the
923 923 absolute path of the script. This way, for multiple executions of the
924 924 same script we only keep one copy of the namespace (the last one),
925 925 thus preventing memory leaks from old references while allowing the
926 926 objects from the last execution to be accessible.
927 927 """
928 928 filename = os.path.abspath(filename)
929 929 try:
930 930 main_mod = self._main_mod_cache[filename]
931 931 except KeyError:
932 932 main_mod = self._main_mod_cache[filename] = types.ModuleType(
933 933 modname,
934 934 doc="Module created for script run in IPython")
935 935 else:
936 936 main_mod.__dict__.clear()
937 937 main_mod.__name__ = modname
938 938
939 939 main_mod.__file__ = filename
940 940 # It seems pydoc (and perhaps others) needs any module instance to
941 941 # implement a __nonzero__ method
942 942 main_mod.__nonzero__ = lambda : True
943 943
944 944 return main_mod
945 945
946 946 def clear_main_mod_cache(self):
947 947 """Clear the cache of main modules.
948 948
949 949 Mainly for use by utilities like %reset.
950 950
951 951 Examples
952 952 --------
953 953
954 954 In [15]: import IPython
955 955
956 956 In [16]: m = _ip.new_main_mod(IPython.__file__, 'IPython')
957 957
958 958 In [17]: len(_ip._main_mod_cache) > 0
959 959 Out[17]: True
960 960
961 961 In [18]: _ip.clear_main_mod_cache()
962 962
963 963 In [19]: len(_ip._main_mod_cache) == 0
964 964 Out[19]: True
965 965 """
966 966 self._main_mod_cache.clear()
967 967
968 968 #-------------------------------------------------------------------------
969 969 # Things related to debugging
970 970 #-------------------------------------------------------------------------
971 971
972 972 def init_pdb(self):
973 973 # Set calling of pdb on exceptions
974 974 # self.call_pdb is a property
975 975 self.call_pdb = self.pdb
976 976
977 977 def _get_call_pdb(self):
978 978 return self._call_pdb
979 979
980 980 def _set_call_pdb(self,val):
981 981
982 982 if val not in (0,1,False,True):
983 983 raise ValueError('new call_pdb value must be boolean')
984 984
985 985 # store value in instance
986 986 self._call_pdb = val
987 987
988 988 # notify the actual exception handlers
989 989 self.InteractiveTB.call_pdb = val
990 990
991 991 call_pdb = property(_get_call_pdb,_set_call_pdb,None,
992 992 'Control auto-activation of pdb at exceptions')
993 993
994 994 def debugger(self,force=False):
995 995 """Call the pdb debugger.
996 996
997 997 Keywords:
998 998
999 999 - force(False): by default, this routine checks the instance call_pdb
1000 1000 flag and does not actually invoke the debugger if the flag is false.
1001 1001 The 'force' option forces the debugger to activate even if the flag
1002 1002 is false.
1003 1003 """
1004 1004
1005 1005 if not (force or self.call_pdb):
1006 1006 return
1007 1007
1008 1008 if not hasattr(sys,'last_traceback'):
1009 1009 error('No traceback has been produced, nothing to debug.')
1010 1010 return
1011 1011
1012 1012 self.InteractiveTB.debugger(force=True)
1013 1013
1014 1014 #-------------------------------------------------------------------------
1015 1015 # Things related to IPython's various namespaces
1016 1016 #-------------------------------------------------------------------------
1017 1017 default_user_namespaces = True
1018 1018
1019 1019 def init_create_namespaces(self, user_module=None, user_ns=None):
1020 1020 # Create the namespace where the user will operate. user_ns is
1021 1021 # normally the only one used, and it is passed to the exec calls as
1022 1022 # the locals argument. But we do carry a user_global_ns namespace
1023 1023 # given as the exec 'globals' argument, This is useful in embedding
1024 1024 # situations where the ipython shell opens in a context where the
1025 1025 # distinction between locals and globals is meaningful. For
1026 1026 # non-embedded contexts, it is just the same object as the user_ns dict.
1027 1027
1028 1028 # FIXME. For some strange reason, __builtins__ is showing up at user
1029 1029 # level as a dict instead of a module. This is a manual fix, but I
1030 1030 # should really track down where the problem is coming from. Alex
1031 1031 # Schmolck reported this problem first.
1032 1032
1033 1033 # A useful post by Alex Martelli on this topic:
1034 1034 # Re: inconsistent value from __builtins__
1035 1035 # Von: Alex Martelli <aleaxit@yahoo.com>
1036 1036 # Datum: Freitag 01 Oktober 2004 04:45:34 nachmittags/abends
1037 1037 # Gruppen: comp.lang.python
1038 1038
1039 1039 # Michael Hohn <hohn@hooknose.lbl.gov> wrote:
1040 1040 # > >>> print type(builtin_check.get_global_binding('__builtins__'))
1041 1041 # > <type 'dict'>
1042 1042 # > >>> print type(__builtins__)
1043 1043 # > <type 'module'>
1044 1044 # > Is this difference in return value intentional?
1045 1045
1046 1046 # Well, it's documented that '__builtins__' can be either a dictionary
1047 1047 # or a module, and it's been that way for a long time. Whether it's
1048 1048 # intentional (or sensible), I don't know. In any case, the idea is
1049 1049 # that if you need to access the built-in namespace directly, you
1050 1050 # should start with "import __builtin__" (note, no 's') which will
1051 1051 # definitely give you a module. Yeah, it's somewhat confusing:-(.
1052 1052
1053 1053 # These routines return a properly built module and dict as needed by
1054 1054 # the rest of the code, and can also be used by extension writers to
1055 1055 # generate properly initialized namespaces.
1056 1056 if (user_ns is not None) or (user_module is not None):
1057 1057 self.default_user_namespaces = False
1058 1058 self.user_module, self.user_ns = self.prepare_user_module(user_module, user_ns)
1059 1059
1060 1060 # A record of hidden variables we have added to the user namespace, so
1061 1061 # we can list later only variables defined in actual interactive use.
1062 1062 self.user_ns_hidden = {}
1063 1063
1064 1064 # Now that FakeModule produces a real module, we've run into a nasty
1065 1065 # problem: after script execution (via %run), the module where the user
1066 1066 # code ran is deleted. Now that this object is a true module (needed
1067 1067 # so doctest and other tools work correctly), the Python module
1068 1068 # teardown mechanism runs over it, and sets to None every variable
1069 1069 # present in that module. Top-level references to objects from the
1070 1070 # script survive, because the user_ns is updated with them. However,
1071 1071 # calling functions defined in the script that use other things from
1072 1072 # the script will fail, because the function's closure had references
1073 1073 # to the original objects, which are now all None. So we must protect
1074 1074 # these modules from deletion by keeping a cache.
1075 1075 #
1076 1076 # To avoid keeping stale modules around (we only need the one from the
1077 1077 # last run), we use a dict keyed with the full path to the script, so
1078 1078 # only the last version of the module is held in the cache. Note,
1079 1079 # however, that we must cache the module *namespace contents* (their
1080 1080 # __dict__). Because if we try to cache the actual modules, old ones
1081 1081 # (uncached) could be destroyed while still holding references (such as
1082 1082 # those held by GUI objects that tend to be long-lived)>
1083 1083 #
1084 1084 # The %reset command will flush this cache. See the cache_main_mod()
1085 1085 # and clear_main_mod_cache() methods for details on use.
1086 1086
1087 1087 # This is the cache used for 'main' namespaces
1088 1088 self._main_mod_cache = {}
1089 1089
1090 1090 # A table holding all the namespaces IPython deals with, so that
1091 1091 # introspection facilities can search easily.
1092 1092 self.ns_table = {'user_global':self.user_module.__dict__,
1093 1093 'user_local':self.user_ns,
1094 1094 'builtin':builtin_mod.__dict__
1095 1095 }
1096 1096
1097 1097 @property
1098 1098 def user_global_ns(self):
1099 1099 return self.user_module.__dict__
1100 1100
1101 1101 def prepare_user_module(self, user_module=None, user_ns=None):
1102 1102 """Prepare the module and namespace in which user code will be run.
1103 1103
1104 1104 When IPython is started normally, both parameters are None: a new module
1105 1105 is created automatically, and its __dict__ used as the namespace.
1106 1106
1107 1107 If only user_module is provided, its __dict__ is used as the namespace.
1108 1108 If only user_ns is provided, a dummy module is created, and user_ns
1109 1109 becomes the global namespace. If both are provided (as they may be
1110 1110 when embedding), user_ns is the local namespace, and user_module
1111 1111 provides the global namespace.
1112 1112
1113 1113 Parameters
1114 1114 ----------
1115 1115 user_module : module, optional
1116 1116 The current user module in which IPython is being run. If None,
1117 1117 a clean module will be created.
1118 1118 user_ns : dict, optional
1119 1119 A namespace in which to run interactive commands.
1120 1120
1121 1121 Returns
1122 1122 -------
1123 1123 A tuple of user_module and user_ns, each properly initialised.
1124 1124 """
1125 1125 if user_module is None and user_ns is not None:
1126 1126 user_ns.setdefault("__name__", "__main__")
1127 1127 user_module = DummyMod()
1128 1128 user_module.__dict__ = user_ns
1129 1129
1130 1130 if user_module is None:
1131 1131 user_module = types.ModuleType("__main__",
1132 1132 doc="Automatically created module for IPython interactive environment")
1133 1133
1134 1134 # We must ensure that __builtin__ (without the final 's') is always
1135 1135 # available and pointing to the __builtin__ *module*. For more details:
1136 1136 # http://mail.python.org/pipermail/python-dev/2001-April/014068.html
1137 1137 user_module.__dict__.setdefault('__builtin__', builtin_mod)
1138 1138 user_module.__dict__.setdefault('__builtins__', builtin_mod)
1139 1139
1140 1140 if user_ns is None:
1141 1141 user_ns = user_module.__dict__
1142 1142
1143 1143 return user_module, user_ns
1144 1144
1145 1145 def init_sys_modules(self):
1146 1146 # We need to insert into sys.modules something that looks like a
1147 1147 # module but which accesses the IPython namespace, for shelve and
1148 1148 # pickle to work interactively. Normally they rely on getting
1149 1149 # everything out of __main__, but for embedding purposes each IPython
1150 1150 # instance has its own private namespace, so we can't go shoving
1151 1151 # everything into __main__.
1152 1152
1153 1153 # note, however, that we should only do this for non-embedded
1154 1154 # ipythons, which really mimic the __main__.__dict__ with their own
1155 1155 # namespace. Embedded instances, on the other hand, should not do
1156 1156 # this because they need to manage the user local/global namespaces
1157 1157 # only, but they live within a 'normal' __main__ (meaning, they
1158 1158 # shouldn't overtake the execution environment of the script they're
1159 1159 # embedded in).
1160 1160
1161 1161 # This is overridden in the InteractiveShellEmbed subclass to a no-op.
1162 1162 main_name = self.user_module.__name__
1163 1163 sys.modules[main_name] = self.user_module
1164 1164
1165 1165 def init_user_ns(self):
1166 1166 """Initialize all user-visible namespaces to their minimum defaults.
1167 1167
1168 1168 Certain history lists are also initialized here, as they effectively
1169 1169 act as user namespaces.
1170 1170
1171 1171 Notes
1172 1172 -----
1173 1173 All data structures here are only filled in, they are NOT reset by this
1174 1174 method. If they were not empty before, data will simply be added to
1175 1175 therm.
1176 1176 """
1177 1177 # This function works in two parts: first we put a few things in
1178 1178 # user_ns, and we sync that contents into user_ns_hidden so that these
1179 1179 # initial variables aren't shown by %who. After the sync, we add the
1180 1180 # rest of what we *do* want the user to see with %who even on a new
1181 1181 # session (probably nothing, so they really only see their own stuff)
1182 1182
1183 1183 # The user dict must *always* have a __builtin__ reference to the
1184 1184 # Python standard __builtin__ namespace, which must be imported.
1185 1185 # This is so that certain operations in prompt evaluation can be
1186 1186 # reliably executed with builtins. Note that we can NOT use
1187 1187 # __builtins__ (note the 's'), because that can either be a dict or a
1188 1188 # module, and can even mutate at runtime, depending on the context
1189 1189 # (Python makes no guarantees on it). In contrast, __builtin__ is
1190 1190 # always a module object, though it must be explicitly imported.
1191 1191
1192 1192 # For more details:
1193 1193 # http://mail.python.org/pipermail/python-dev/2001-April/014068.html
1194 1194 ns = {}
1195 1195
1196 1196 # make global variables for user access to the histories
1197 1197 ns['_ih'] = self.history_manager.input_hist_parsed
1198 1198 ns['_oh'] = self.history_manager.output_hist
1199 1199 ns['_dh'] = self.history_manager.dir_hist
1200 1200
1201 1201 # user aliases to input and output histories. These shouldn't show up
1202 1202 # in %who, as they can have very large reprs.
1203 1203 ns['In'] = self.history_manager.input_hist_parsed
1204 1204 ns['Out'] = self.history_manager.output_hist
1205 1205
1206 1206 # Store myself as the public api!!!
1207 1207 ns['get_ipython'] = self.get_ipython
1208 1208
1209 1209 ns['exit'] = self.exiter
1210 1210 ns['quit'] = self.exiter
1211 1211
1212 1212 # Sync what we've added so far to user_ns_hidden so these aren't seen
1213 1213 # by %who
1214 1214 self.user_ns_hidden.update(ns)
1215 1215
1216 1216 # Anything put into ns now would show up in %who. Think twice before
1217 1217 # putting anything here, as we really want %who to show the user their
1218 1218 # stuff, not our variables.
1219 1219
1220 1220 # Finally, update the real user's namespace
1221 1221 self.user_ns.update(ns)
1222 1222
1223 1223 @property
1224 1224 def all_ns_refs(self):
1225 1225 """Get a list of references to all the namespace dictionaries in which
1226 1226 IPython might store a user-created object.
1227 1227
1228 1228 Note that this does not include the displayhook, which also caches
1229 1229 objects from the output."""
1230 1230 return [self.user_ns, self.user_global_ns, self.user_ns_hidden] + \
1231 1231 [m.__dict__ for m in self._main_mod_cache.values()]
1232 1232
1233 1233 def reset(self, new_session=True):
1234 1234 """Clear all internal namespaces, and attempt to release references to
1235 1235 user objects.
1236 1236
1237 1237 If new_session is True, a new history session will be opened.
1238 1238 """
1239 1239 # Clear histories
1240 1240 self.history_manager.reset(new_session)
1241 1241 # Reset counter used to index all histories
1242 1242 if new_session:
1243 1243 self.execution_count = 1
1244 1244
1245 1245 # Reset last execution result
1246 1246 self.last_execution_succeeded = True
1247 1247 self.last_execution_result = None
1248 1248
1249 1249 # Flush cached output items
1250 1250 if self.displayhook.do_full_cache:
1251 1251 self.displayhook.flush()
1252 1252
1253 1253 # The main execution namespaces must be cleared very carefully,
1254 1254 # skipping the deletion of the builtin-related keys, because doing so
1255 1255 # would cause errors in many object's __del__ methods.
1256 1256 if self.user_ns is not self.user_global_ns:
1257 1257 self.user_ns.clear()
1258 1258 ns = self.user_global_ns
1259 1259 drop_keys = set(ns.keys())
1260 1260 drop_keys.discard('__builtin__')
1261 1261 drop_keys.discard('__builtins__')
1262 1262 drop_keys.discard('__name__')
1263 1263 for k in drop_keys:
1264 1264 del ns[k]
1265 1265
1266 1266 self.user_ns_hidden.clear()
1267 1267
1268 1268 # Restore the user namespaces to minimal usability
1269 1269 self.init_user_ns()
1270 1270
1271 1271 # Restore the default and user aliases
1272 1272 self.alias_manager.clear_aliases()
1273 1273 self.alias_manager.init_aliases()
1274 1274
1275 1275 # Flush the private list of module references kept for script
1276 1276 # execution protection
1277 1277 self.clear_main_mod_cache()
1278 1278
1279 1279 def del_var(self, varname, by_name=False):
1280 1280 """Delete a variable from the various namespaces, so that, as
1281 1281 far as possible, we're not keeping any hidden references to it.
1282 1282
1283 1283 Parameters
1284 1284 ----------
1285 1285 varname : str
1286 1286 The name of the variable to delete.
1287 1287 by_name : bool
1288 1288 If True, delete variables with the given name in each
1289 1289 namespace. If False (default), find the variable in the user
1290 1290 namespace, and delete references to it.
1291 1291 """
1292 1292 if varname in ('__builtin__', '__builtins__'):
1293 1293 raise ValueError("Refusing to delete %s" % varname)
1294 1294
1295 1295 ns_refs = self.all_ns_refs
1296 1296
1297 1297 if by_name: # Delete by name
1298 1298 for ns in ns_refs:
1299 1299 try:
1300 1300 del ns[varname]
1301 1301 except KeyError:
1302 1302 pass
1303 1303 else: # Delete by object
1304 1304 try:
1305 1305 obj = self.user_ns[varname]
1306 1306 except KeyError:
1307 1307 raise NameError("name '%s' is not defined" % varname)
1308 1308 # Also check in output history
1309 1309 ns_refs.append(self.history_manager.output_hist)
1310 1310 for ns in ns_refs:
1311 1311 to_delete = [n for n, o in ns.items() if o is obj]
1312 1312 for name in to_delete:
1313 1313 del ns[name]
1314 1314
1315 1315 # Ensure it is removed from the last execution result
1316 1316 if self.last_execution_result.result is obj:
1317 1317 self.last_execution_result = None
1318 1318
1319 1319 # displayhook keeps extra references, but not in a dictionary
1320 1320 for name in ('_', '__', '___'):
1321 1321 if getattr(self.displayhook, name) is obj:
1322 1322 setattr(self.displayhook, name, None)
1323 1323
1324 1324 def reset_selective(self, regex=None):
1325 1325 """Clear selective variables from internal namespaces based on a
1326 1326 specified regular expression.
1327 1327
1328 1328 Parameters
1329 1329 ----------
1330 1330 regex : string or compiled pattern, optional
1331 1331 A regular expression pattern that will be used in searching
1332 1332 variable names in the users namespaces.
1333 1333 """
1334 1334 if regex is not None:
1335 1335 try:
1336 1336 m = re.compile(regex)
1337 1337 except TypeError:
1338 1338 raise TypeError('regex must be a string or compiled pattern')
1339 1339 # Search for keys in each namespace that match the given regex
1340 1340 # If a match is found, delete the key/value pair.
1341 1341 for ns in self.all_ns_refs:
1342 1342 for var in ns:
1343 1343 if m.search(var):
1344 1344 del ns[var]
1345 1345
1346 1346 def push(self, variables, interactive=True):
1347 1347 """Inject a group of variables into the IPython user namespace.
1348 1348
1349 1349 Parameters
1350 1350 ----------
1351 1351 variables : dict, str or list/tuple of str
1352 1352 The variables to inject into the user's namespace. If a dict, a
1353 1353 simple update is done. If a str, the string is assumed to have
1354 1354 variable names separated by spaces. A list/tuple of str can also
1355 1355 be used to give the variable names. If just the variable names are
1356 1356 give (list/tuple/str) then the variable values looked up in the
1357 1357 callers frame.
1358 1358 interactive : bool
1359 1359 If True (default), the variables will be listed with the ``who``
1360 1360 magic.
1361 1361 """
1362 1362 vdict = None
1363 1363
1364 1364 # We need a dict of name/value pairs to do namespace updates.
1365 1365 if isinstance(variables, dict):
1366 1366 vdict = variables
1367 1367 elif isinstance(variables, (str, list, tuple)):
1368 1368 if isinstance(variables, str):
1369 1369 vlist = variables.split()
1370 1370 else:
1371 1371 vlist = variables
1372 1372 vdict = {}
1373 1373 cf = sys._getframe(1)
1374 1374 for name in vlist:
1375 1375 try:
1376 1376 vdict[name] = eval(name, cf.f_globals, cf.f_locals)
1377 1377 except:
1378 1378 print('Could not get variable %s from %s' %
1379 1379 (name,cf.f_code.co_name))
1380 1380 else:
1381 1381 raise ValueError('variables must be a dict/str/list/tuple')
1382 1382
1383 1383 # Propagate variables to user namespace
1384 1384 self.user_ns.update(vdict)
1385 1385
1386 1386 # And configure interactive visibility
1387 1387 user_ns_hidden = self.user_ns_hidden
1388 1388 if interactive:
1389 1389 for name in vdict:
1390 1390 user_ns_hidden.pop(name, None)
1391 1391 else:
1392 1392 user_ns_hidden.update(vdict)
1393 1393
1394 1394 def drop_by_id(self, variables):
1395 1395 """Remove a dict of variables from the user namespace, if they are the
1396 1396 same as the values in the dictionary.
1397 1397
1398 1398 This is intended for use by extensions: variables that they've added can
1399 1399 be taken back out if they are unloaded, without removing any that the
1400 1400 user has overwritten.
1401 1401
1402 1402 Parameters
1403 1403 ----------
1404 1404 variables : dict
1405 1405 A dictionary mapping object names (as strings) to the objects.
1406 1406 """
1407 1407 for name, obj in variables.items():
1408 1408 if name in self.user_ns and self.user_ns[name] is obj:
1409 1409 del self.user_ns[name]
1410 1410 self.user_ns_hidden.pop(name, None)
1411 1411
1412 1412 #-------------------------------------------------------------------------
1413 1413 # Things related to object introspection
1414 1414 #-------------------------------------------------------------------------
1415 1415
1416 1416 def _ofind(self, oname, namespaces=None):
1417 1417 """Find an object in the available namespaces.
1418 1418
1419 1419 self._ofind(oname) -> dict with keys: found,obj,ospace,ismagic
1420 1420
1421 1421 Has special code to detect magic functions.
1422 1422 """
1423 1423 oname = oname.strip()
1424 1424 if not oname.startswith(ESC_MAGIC) and \
1425 1425 not oname.startswith(ESC_MAGIC2) and \
1426 1426 not all(a.isidentifier() for a in oname.split(".")):
1427 1427 return {'found': False}
1428 1428
1429 1429 if namespaces is None:
1430 1430 # Namespaces to search in:
1431 1431 # Put them in a list. The order is important so that we
1432 1432 # find things in the same order that Python finds them.
1433 1433 namespaces = [ ('Interactive', self.user_ns),
1434 1434 ('Interactive (global)', self.user_global_ns),
1435 1435 ('Python builtin', builtin_mod.__dict__),
1436 1436 ]
1437 1437
1438 1438 ismagic = False
1439 1439 isalias = False
1440 1440 found = False
1441 1441 ospace = None
1442 1442 parent = None
1443 1443 obj = None
1444 1444
1445 1445 # Look for the given name by splitting it in parts. If the head is
1446 1446 # found, then we look for all the remaining parts as members, and only
1447 1447 # declare success if we can find them all.
1448 1448 oname_parts = oname.split('.')
1449 1449 oname_head, oname_rest = oname_parts[0],oname_parts[1:]
1450 1450 for nsname,ns in namespaces:
1451 1451 try:
1452 1452 obj = ns[oname_head]
1453 1453 except KeyError:
1454 1454 continue
1455 1455 else:
1456 1456 for idx, part in enumerate(oname_rest):
1457 1457 try:
1458 1458 parent = obj
1459 1459 # The last part is looked up in a special way to avoid
1460 1460 # descriptor invocation as it may raise or have side
1461 1461 # effects.
1462 1462 if idx == len(oname_rest) - 1:
1463 1463 obj = self._getattr_property(obj, part)
1464 1464 else:
1465 1465 obj = getattr(obj, part)
1466 1466 except:
1467 1467 # Blanket except b/c some badly implemented objects
1468 1468 # allow __getattr__ to raise exceptions other than
1469 1469 # AttributeError, which then crashes IPython.
1470 1470 break
1471 1471 else:
1472 1472 # If we finish the for loop (no break), we got all members
1473 1473 found = True
1474 1474 ospace = nsname
1475 1475 break # namespace loop
1476 1476
1477 1477 # Try to see if it's magic
1478 1478 if not found:
1479 1479 obj = None
1480 1480 if oname.startswith(ESC_MAGIC2):
1481 1481 oname = oname.lstrip(ESC_MAGIC2)
1482 1482 obj = self.find_cell_magic(oname)
1483 1483 elif oname.startswith(ESC_MAGIC):
1484 1484 oname = oname.lstrip(ESC_MAGIC)
1485 1485 obj = self.find_line_magic(oname)
1486 1486 else:
1487 1487 # search without prefix, so run? will find %run?
1488 1488 obj = self.find_line_magic(oname)
1489 1489 if obj is None:
1490 1490 obj = self.find_cell_magic(oname)
1491 1491 if obj is not None:
1492 1492 found = True
1493 1493 ospace = 'IPython internal'
1494 1494 ismagic = True
1495 1495 isalias = isinstance(obj, Alias)
1496 1496
1497 1497 # Last try: special-case some literals like '', [], {}, etc:
1498 1498 if not found and oname_head in ["''",'""','[]','{}','()']:
1499 1499 obj = eval(oname_head)
1500 1500 found = True
1501 1501 ospace = 'Interactive'
1502 1502
1503 1503 return {
1504 1504 'obj':obj,
1505 1505 'found':found,
1506 1506 'parent':parent,
1507 1507 'ismagic':ismagic,
1508 1508 'isalias':isalias,
1509 1509 'namespace':ospace
1510 1510 }
1511 1511
1512 1512 @staticmethod
1513 1513 def _getattr_property(obj, attrname):
1514 1514 """Property-aware getattr to use in object finding.
1515 1515
1516 1516 If attrname represents a property, return it unevaluated (in case it has
1517 1517 side effects or raises an error.
1518 1518
1519 1519 """
1520 1520 if not isinstance(obj, type):
1521 1521 try:
1522 1522 # `getattr(type(obj), attrname)` is not guaranteed to return
1523 1523 # `obj`, but does so for property:
1524 1524 #
1525 1525 # property.__get__(self, None, cls) -> self
1526 1526 #
1527 1527 # The universal alternative is to traverse the mro manually
1528 1528 # searching for attrname in class dicts.
1529 1529 attr = getattr(type(obj), attrname)
1530 1530 except AttributeError:
1531 1531 pass
1532 1532 else:
1533 1533 # This relies on the fact that data descriptors (with both
1534 1534 # __get__ & __set__ magic methods) take precedence over
1535 1535 # instance-level attributes:
1536 1536 #
1537 1537 # class A(object):
1538 1538 # @property
1539 1539 # def foobar(self): return 123
1540 1540 # a = A()
1541 1541 # a.__dict__['foobar'] = 345
1542 1542 # a.foobar # == 123
1543 1543 #
1544 1544 # So, a property may be returned right away.
1545 1545 if isinstance(attr, property):
1546 1546 return attr
1547 1547
1548 1548 # Nothing helped, fall back.
1549 1549 return getattr(obj, attrname)
1550 1550
1551 1551 def _object_find(self, oname, namespaces=None):
1552 1552 """Find an object and return a struct with info about it."""
1553 1553 return Struct(self._ofind(oname, namespaces))
1554 1554
1555 1555 def _inspect(self, meth, oname, namespaces=None, **kw):
1556 1556 """Generic interface to the inspector system.
1557 1557
1558 1558 This function is meant to be called by pdef, pdoc & friends.
1559 1559 """
1560 1560 info = self._object_find(oname, namespaces)
1561 1561 docformat = sphinxify if self.sphinxify_docstring else None
1562 1562 if info.found:
1563 1563 pmethod = getattr(self.inspector, meth)
1564 1564 # TODO: only apply format_screen to the plain/text repr of the mime
1565 1565 # bundle.
1566 1566 formatter = format_screen if info.ismagic else docformat
1567 1567 if meth == 'pdoc':
1568 1568 pmethod(info.obj, oname, formatter)
1569 1569 elif meth == 'pinfo':
1570 1570 pmethod(info.obj, oname, formatter, info,
1571 1571 enable_html_pager=self.enable_html_pager, **kw)
1572 1572 else:
1573 1573 pmethod(info.obj, oname)
1574 1574 else:
1575 1575 print('Object `%s` not found.' % oname)
1576 1576 return 'not found' # so callers can take other action
1577 1577
1578 1578 def object_inspect(self, oname, detail_level=0):
1579 1579 """Get object info about oname"""
1580 1580 with self.builtin_trap:
1581 1581 info = self._object_find(oname)
1582 1582 if info.found:
1583 1583 return self.inspector.info(info.obj, oname, info=info,
1584 1584 detail_level=detail_level
1585 1585 )
1586 1586 else:
1587 1587 return oinspect.object_info(name=oname, found=False)
1588 1588
1589 1589 def object_inspect_text(self, oname, detail_level=0):
1590 1590 """Get object info as formatted text"""
1591 1591 return self.object_inspect_mime(oname, detail_level)['text/plain']
1592 1592
1593 1593 def object_inspect_mime(self, oname, detail_level=0):
1594 1594 """Get object info as a mimebundle of formatted representations.
1595 1595
1596 1596 A mimebundle is a dictionary, keyed by mime-type.
1597 1597 It must always have the key `'text/plain'`.
1598 1598 """
1599 1599 with self.builtin_trap:
1600 1600 info = self._object_find(oname)
1601 1601 if info.found:
1602 1602 return self.inspector._get_info(info.obj, oname, info=info,
1603 1603 detail_level=detail_level
1604 1604 )
1605 1605 else:
1606 1606 raise KeyError(oname)
1607 1607
1608 1608 #-------------------------------------------------------------------------
1609 1609 # Things related to history management
1610 1610 #-------------------------------------------------------------------------
1611 1611
1612 1612 def init_history(self):
1613 1613 """Sets up the command history, and starts regular autosaves."""
1614 1614 self.history_manager = HistoryManager(shell=self, parent=self)
1615 1615 self.configurables.append(self.history_manager)
1616 1616
1617 1617 #-------------------------------------------------------------------------
1618 1618 # Things related to exception handling and tracebacks (not debugging)
1619 1619 #-------------------------------------------------------------------------
1620 1620
1621 1621 debugger_cls = Pdb
1622 1622
1623 1623 def init_traceback_handlers(self, custom_exceptions):
1624 1624 # Syntax error handler.
1625 1625 self.SyntaxTB = ultratb.SyntaxTB(color_scheme='NoColor', parent=self)
1626 1626
1627 1627 # The interactive one is initialized with an offset, meaning we always
1628 1628 # want to remove the topmost item in the traceback, which is our own
1629 1629 # internal code. Valid modes: ['Plain','Context','Verbose']
1630 1630 self.InteractiveTB = ultratb.AutoFormattedTB(mode = 'Plain',
1631 1631 color_scheme='NoColor',
1632 1632 tb_offset = 1,
1633 1633 check_cache=check_linecache_ipython,
1634 1634 debugger_cls=self.debugger_cls, parent=self)
1635 1635
1636 1636 # The instance will store a pointer to the system-wide exception hook,
1637 1637 # so that runtime code (such as magics) can access it. This is because
1638 1638 # during the read-eval loop, it may get temporarily overwritten.
1639 1639 self.sys_excepthook = sys.excepthook
1640 1640
1641 1641 # and add any custom exception handlers the user may have specified
1642 1642 self.set_custom_exc(*custom_exceptions)
1643 1643
1644 1644 # Set the exception mode
1645 1645 self.InteractiveTB.set_mode(mode=self.xmode)
1646 1646
1647 1647 def set_custom_exc(self, exc_tuple, handler):
1648 1648 """set_custom_exc(exc_tuple, handler)
1649 1649
1650 1650 Set a custom exception handler, which will be called if any of the
1651 1651 exceptions in exc_tuple occur in the mainloop (specifically, in the
1652 1652 run_code() method).
1653 1653
1654 1654 Parameters
1655 1655 ----------
1656 1656
1657 1657 exc_tuple : tuple of exception classes
1658 1658 A *tuple* of exception classes, for which to call the defined
1659 1659 handler. It is very important that you use a tuple, and NOT A
1660 1660 LIST here, because of the way Python's except statement works. If
1661 1661 you only want to trap a single exception, use a singleton tuple::
1662 1662
1663 1663 exc_tuple == (MyCustomException,)
1664 1664
1665 1665 handler : callable
1666 1666 handler must have the following signature::
1667 1667
1668 1668 def my_handler(self, etype, value, tb, tb_offset=None):
1669 1669 ...
1670 1670 return structured_traceback
1671 1671
1672 1672 Your handler must return a structured traceback (a list of strings),
1673 1673 or None.
1674 1674
1675 1675 This will be made into an instance method (via types.MethodType)
1676 1676 of IPython itself, and it will be called if any of the exceptions
1677 1677 listed in the exc_tuple are caught. If the handler is None, an
1678 1678 internal basic one is used, which just prints basic info.
1679 1679
1680 1680 To protect IPython from crashes, if your handler ever raises an
1681 1681 exception or returns an invalid result, it will be immediately
1682 1682 disabled.
1683 1683
1684 1684 WARNING: by putting in your own exception handler into IPython's main
1685 1685 execution loop, you run a very good chance of nasty crashes. This
1686 1686 facility should only be used if you really know what you are doing."""
1687 1687 if not isinstance(exc_tuple, tuple):
1688 1688 raise TypeError("The custom exceptions must be given as a tuple.")
1689 1689
1690 1690 def dummy_handler(self, etype, value, tb, tb_offset=None):
1691 1691 print('*** Simple custom exception handler ***')
1692 1692 print('Exception type :', etype)
1693 1693 print('Exception value:', value)
1694 1694 print('Traceback :', tb)
1695 1695
1696 1696 def validate_stb(stb):
1697 1697 """validate structured traceback return type
1698 1698
1699 1699 return type of CustomTB *should* be a list of strings, but allow
1700 1700 single strings or None, which are harmless.
1701 1701
1702 1702 This function will *always* return a list of strings,
1703 1703 and will raise a TypeError if stb is inappropriate.
1704 1704 """
1705 1705 msg = "CustomTB must return list of strings, not %r" % stb
1706 1706 if stb is None:
1707 1707 return []
1708 1708 elif isinstance(stb, str):
1709 1709 return [stb]
1710 1710 elif not isinstance(stb, list):
1711 1711 raise TypeError(msg)
1712 1712 # it's a list
1713 1713 for line in stb:
1714 1714 # check every element
1715 1715 if not isinstance(line, str):
1716 1716 raise TypeError(msg)
1717 1717 return stb
1718 1718
1719 1719 if handler is None:
1720 1720 wrapped = dummy_handler
1721 1721 else:
1722 1722 def wrapped(self,etype,value,tb,tb_offset=None):
1723 1723 """wrap CustomTB handler, to protect IPython from user code
1724 1724
1725 1725 This makes it harder (but not impossible) for custom exception
1726 1726 handlers to crash IPython.
1727 1727 """
1728 1728 try:
1729 1729 stb = handler(self,etype,value,tb,tb_offset=tb_offset)
1730 1730 return validate_stb(stb)
1731 1731 except:
1732 1732 # clear custom handler immediately
1733 1733 self.set_custom_exc((), None)
1734 1734 print("Custom TB Handler failed, unregistering", file=sys.stderr)
1735 1735 # show the exception in handler first
1736 1736 stb = self.InteractiveTB.structured_traceback(*sys.exc_info())
1737 1737 print(self.InteractiveTB.stb2text(stb))
1738 1738 print("The original exception:")
1739 1739 stb = self.InteractiveTB.structured_traceback(
1740 1740 (etype,value,tb), tb_offset=tb_offset
1741 1741 )
1742 1742 return stb
1743 1743
1744 1744 self.CustomTB = types.MethodType(wrapped,self)
1745 1745 self.custom_exceptions = exc_tuple
1746 1746
1747 1747 def excepthook(self, etype, value, tb):
1748 1748 """One more defense for GUI apps that call sys.excepthook.
1749 1749
1750 1750 GUI frameworks like wxPython trap exceptions and call
1751 1751 sys.excepthook themselves. I guess this is a feature that
1752 1752 enables them to keep running after exceptions that would
1753 1753 otherwise kill their mainloop. This is a bother for IPython
1754 1754 which excepts to catch all of the program exceptions with a try:
1755 1755 except: statement.
1756 1756
1757 1757 Normally, IPython sets sys.excepthook to a CrashHandler instance, so if
1758 1758 any app directly invokes sys.excepthook, it will look to the user like
1759 1759 IPython crashed. In order to work around this, we can disable the
1760 1760 CrashHandler and replace it with this excepthook instead, which prints a
1761 1761 regular traceback using our InteractiveTB. In this fashion, apps which
1762 1762 call sys.excepthook will generate a regular-looking exception from
1763 1763 IPython, and the CrashHandler will only be triggered by real IPython
1764 1764 crashes.
1765 1765
1766 1766 This hook should be used sparingly, only in places which are not likely
1767 1767 to be true IPython errors.
1768 1768 """
1769 1769 self.showtraceback((etype, value, tb), tb_offset=0)
1770 1770
1771 1771 def _get_exc_info(self, exc_tuple=None):
1772 1772 """get exc_info from a given tuple, sys.exc_info() or sys.last_type etc.
1773 1773
1774 1774 Ensures sys.last_type,value,traceback hold the exc_info we found,
1775 1775 from whichever source.
1776 1776
1777 1777 raises ValueError if none of these contain any information
1778 1778 """
1779 1779 if exc_tuple is None:
1780 1780 etype, value, tb = sys.exc_info()
1781 1781 else:
1782 1782 etype, value, tb = exc_tuple
1783 1783
1784 1784 if etype is None:
1785 1785 if hasattr(sys, 'last_type'):
1786 1786 etype, value, tb = sys.last_type, sys.last_value, \
1787 1787 sys.last_traceback
1788 1788
1789 1789 if etype is None:
1790 1790 raise ValueError("No exception to find")
1791 1791
1792 1792 # Now store the exception info in sys.last_type etc.
1793 1793 # WARNING: these variables are somewhat deprecated and not
1794 1794 # necessarily safe to use in a threaded environment, but tools
1795 1795 # like pdb depend on their existence, so let's set them. If we
1796 1796 # find problems in the field, we'll need to revisit their use.
1797 1797 sys.last_type = etype
1798 1798 sys.last_value = value
1799 1799 sys.last_traceback = tb
1800 1800
1801 1801 return etype, value, tb
1802 1802
1803 1803 def show_usage_error(self, exc):
1804 1804 """Show a short message for UsageErrors
1805 1805
1806 1806 These are special exceptions that shouldn't show a traceback.
1807 1807 """
1808 1808 print("UsageError: %s" % exc, file=sys.stderr)
1809 1809
1810 1810 def get_exception_only(self, exc_tuple=None):
1811 1811 """
1812 1812 Return as a string (ending with a newline) the exception that
1813 1813 just occurred, without any traceback.
1814 1814 """
1815 1815 etype, value, tb = self._get_exc_info(exc_tuple)
1816 1816 msg = traceback.format_exception_only(etype, value)
1817 1817 return ''.join(msg)
1818 1818
1819 1819 def showtraceback(self, exc_tuple=None, filename=None, tb_offset=None,
1820 1820 exception_only=False, running_compiled_code=False):
1821 1821 """Display the exception that just occurred.
1822 1822
1823 1823 If nothing is known about the exception, this is the method which
1824 1824 should be used throughout the code for presenting user tracebacks,
1825 1825 rather than directly invoking the InteractiveTB object.
1826 1826
1827 1827 A specific showsyntaxerror() also exists, but this method can take
1828 1828 care of calling it if needed, so unless you are explicitly catching a
1829 1829 SyntaxError exception, don't try to analyze the stack manually and
1830 1830 simply call this method."""
1831 1831
1832 1832 try:
1833 1833 try:
1834 1834 etype, value, tb = self._get_exc_info(exc_tuple)
1835 1835 except ValueError:
1836 1836 print('No traceback available to show.', file=sys.stderr)
1837 1837 return
1838 1838
1839 1839 if issubclass(etype, SyntaxError):
1840 1840 # Though this won't be called by syntax errors in the input
1841 1841 # line, there may be SyntaxError cases with imported code.
1842 1842 self.showsyntaxerror(filename, running_compiled_code)
1843 1843 elif etype is UsageError:
1844 1844 self.show_usage_error(value)
1845 1845 else:
1846 1846 if exception_only:
1847 1847 stb = ['An exception has occurred, use %tb to see '
1848 1848 'the full traceback.\n']
1849 1849 stb.extend(self.InteractiveTB.get_exception_only(etype,
1850 1850 value))
1851 1851 else:
1852 1852 try:
1853 1853 # Exception classes can customise their traceback - we
1854 1854 # use this in IPython.parallel for exceptions occurring
1855 1855 # in the engines. This should return a list of strings.
1856 1856 stb = value._render_traceback_()
1857 1857 except Exception:
1858 1858 stb = self.InteractiveTB.structured_traceback(etype,
1859 1859 value, tb, tb_offset=tb_offset)
1860 1860
1861 1861 self._showtraceback(etype, value, stb)
1862 1862 if self.call_pdb:
1863 1863 # drop into debugger
1864 1864 self.debugger(force=True)
1865 1865 return
1866 1866
1867 1867 # Actually show the traceback
1868 1868 self._showtraceback(etype, value, stb)
1869 1869
1870 1870 except KeyboardInterrupt:
1871 1871 print('\n' + self.get_exception_only(), file=sys.stderr)
1872 1872
1873 1873 def _showtraceback(self, etype, evalue, stb):
1874 1874 """Actually show a traceback.
1875 1875
1876 1876 Subclasses may override this method to put the traceback on a different
1877 1877 place, like a side channel.
1878 1878 """
1879 1879 print(self.InteractiveTB.stb2text(stb))
1880 1880
1881 1881 def showsyntaxerror(self, filename=None, running_compiled_code=False):
1882 1882 """Display the syntax error that just occurred.
1883 1883
1884 1884 This doesn't display a stack trace because there isn't one.
1885 1885
1886 1886 If a filename is given, it is stuffed in the exception instead
1887 1887 of what was there before (because Python's parser always uses
1888 1888 "<string>" when reading from a string).
1889 1889
1890 1890 If the syntax error occurred when running a compiled code (i.e. running_compile_code=True),
1891 1891 longer stack trace will be displayed.
1892 1892 """
1893 1893 etype, value, last_traceback = self._get_exc_info()
1894 1894
1895 1895 if filename and issubclass(etype, SyntaxError):
1896 1896 try:
1897 1897 value.filename = filename
1898 1898 except:
1899 1899 # Not the format we expect; leave it alone
1900 1900 pass
1901 1901
1902 # If the error occured when executing compiled code, we should provide full stacktrace.
1902 # If the error occurred when executing compiled code, we should provide full stacktrace.
1903 1903 elist = traceback.extract_tb(last_traceback) if running_compiled_code else []
1904 1904 stb = self.SyntaxTB.structured_traceback(etype, value, elist)
1905 1905 self._showtraceback(etype, value, stb)
1906 1906
1907 1907 # This is overridden in TerminalInteractiveShell to show a message about
1908 1908 # the %paste magic.
1909 1909 def showindentationerror(self):
1910 1910 """Called by _run_cell when there's an IndentationError in code entered
1911 1911 at the prompt.
1912 1912
1913 1913 This is overridden in TerminalInteractiveShell to show a message about
1914 1914 the %paste magic."""
1915 1915 self.showsyntaxerror()
1916 1916
1917 1917 #-------------------------------------------------------------------------
1918 1918 # Things related to readline
1919 1919 #-------------------------------------------------------------------------
1920 1920
1921 1921 def init_readline(self):
1922 1922 """DEPRECATED
1923 1923
1924 1924 Moved to terminal subclass, here only to simplify the init logic."""
1925 1925 # Set a number of methods that depend on readline to be no-op
1926 1926 warnings.warn('`init_readline` is no-op since IPython 5.0 and is Deprecated',
1927 1927 DeprecationWarning, stacklevel=2)
1928 1928 self.set_custom_completer = no_op
1929 1929
1930 1930 @skip_doctest
1931 1931 def set_next_input(self, s, replace=False):
1932 1932 """ Sets the 'default' input string for the next command line.
1933 1933
1934 1934 Example::
1935 1935
1936 1936 In [1]: _ip.set_next_input("Hello Word")
1937 1937 In [2]: Hello Word_ # cursor is here
1938 1938 """
1939 1939 self.rl_next_input = s
1940 1940
1941 1941 def _indent_current_str(self):
1942 1942 """return the current level of indentation as a string"""
1943 1943 return self.input_splitter.get_indent_spaces() * ' '
1944 1944
1945 1945 #-------------------------------------------------------------------------
1946 1946 # Things related to text completion
1947 1947 #-------------------------------------------------------------------------
1948 1948
1949 1949 def init_completer(self):
1950 1950 """Initialize the completion machinery.
1951 1951
1952 1952 This creates completion machinery that can be used by client code,
1953 1953 either interactively in-process (typically triggered by the readline
1954 1954 library), programmatically (such as in test suites) or out-of-process
1955 1955 (typically over the network by remote frontends).
1956 1956 """
1957 1957 from IPython.core.completer import IPCompleter
1958 1958 from IPython.core.completerlib import (module_completer,
1959 1959 magic_run_completer, cd_completer, reset_completer)
1960 1960
1961 1961 self.Completer = IPCompleter(shell=self,
1962 1962 namespace=self.user_ns,
1963 1963 global_namespace=self.user_global_ns,
1964 1964 parent=self,
1965 1965 )
1966 1966 self.configurables.append(self.Completer)
1967 1967
1968 1968 # Add custom completers to the basic ones built into IPCompleter
1969 1969 sdisp = self.strdispatchers.get('complete_command', StrDispatch())
1970 1970 self.strdispatchers['complete_command'] = sdisp
1971 1971 self.Completer.custom_completers = sdisp
1972 1972
1973 1973 self.set_hook('complete_command', module_completer, str_key = 'import')
1974 1974 self.set_hook('complete_command', module_completer, str_key = 'from')
1975 1975 self.set_hook('complete_command', module_completer, str_key = '%aimport')
1976 1976 self.set_hook('complete_command', magic_run_completer, str_key = '%run')
1977 1977 self.set_hook('complete_command', cd_completer, str_key = '%cd')
1978 1978 self.set_hook('complete_command', reset_completer, str_key = '%reset')
1979 1979
1980 1980
1981 1981 def complete(self, text, line=None, cursor_pos=None):
1982 1982 """Return the completed text and a list of completions.
1983 1983
1984 1984 Parameters
1985 1985 ----------
1986 1986
1987 1987 text : string
1988 1988 A string of text to be completed on. It can be given as empty and
1989 1989 instead a line/position pair are given. In this case, the
1990 1990 completer itself will split the line like readline does.
1991 1991
1992 1992 line : string, optional
1993 1993 The complete line that text is part of.
1994 1994
1995 1995 cursor_pos : int, optional
1996 1996 The position of the cursor on the input line.
1997 1997
1998 1998 Returns
1999 1999 -------
2000 2000 text : string
2001 2001 The actual text that was completed.
2002 2002
2003 2003 matches : list
2004 2004 A sorted list with all possible completions.
2005 2005
2006 2006 The optional arguments allow the completion to take more context into
2007 2007 account, and are part of the low-level completion API.
2008 2008
2009 2009 This is a wrapper around the completion mechanism, similar to what
2010 2010 readline does at the command line when the TAB key is hit. By
2011 2011 exposing it as a method, it can be used by other non-readline
2012 2012 environments (such as GUIs) for text completion.
2013 2013
2014 2014 Simple usage example:
2015 2015
2016 2016 In [1]: x = 'hello'
2017 2017
2018 2018 In [2]: _ip.complete('x.l')
2019 2019 Out[2]: ('x.l', ['x.ljust', 'x.lower', 'x.lstrip'])
2020 2020 """
2021 2021
2022 2022 # Inject names into __builtin__ so we can complete on the added names.
2023 2023 with self.builtin_trap:
2024 2024 return self.Completer.complete(text, line, cursor_pos)
2025 2025
2026 2026 def set_custom_completer(self, completer, pos=0):
2027 2027 """Adds a new custom completer function.
2028 2028
2029 2029 The position argument (defaults to 0) is the index in the completers
2030 2030 list where you want the completer to be inserted."""
2031 2031
2032 2032 newcomp = types.MethodType(completer,self.Completer)
2033 2033 self.Completer.matchers.insert(pos,newcomp)
2034 2034
2035 2035 def set_completer_frame(self, frame=None):
2036 2036 """Set the frame of the completer."""
2037 2037 if frame:
2038 2038 self.Completer.namespace = frame.f_locals
2039 2039 self.Completer.global_namespace = frame.f_globals
2040 2040 else:
2041 2041 self.Completer.namespace = self.user_ns
2042 2042 self.Completer.global_namespace = self.user_global_ns
2043 2043
2044 2044 #-------------------------------------------------------------------------
2045 2045 # Things related to magics
2046 2046 #-------------------------------------------------------------------------
2047 2047
2048 2048 def init_magics(self):
2049 2049 from IPython.core import magics as m
2050 2050 self.magics_manager = magic.MagicsManager(shell=self,
2051 2051 parent=self,
2052 2052 user_magics=m.UserMagics(self))
2053 2053 self.configurables.append(self.magics_manager)
2054 2054
2055 2055 # Expose as public API from the magics manager
2056 2056 self.register_magics = self.magics_manager.register
2057 2057
2058 2058 self.register_magics(m.AutoMagics, m.BasicMagics, m.CodeMagics,
2059 2059 m.ConfigMagics, m.DisplayMagics, m.ExecutionMagics,
2060 2060 m.ExtensionMagics, m.HistoryMagics, m.LoggingMagics,
2061 2061 m.NamespaceMagics, m.OSMagics, m.PylabMagics, m.ScriptMagics,
2062 2062 )
2063 2063
2064 2064 # Register Magic Aliases
2065 2065 mman = self.magics_manager
2066 2066 # FIXME: magic aliases should be defined by the Magics classes
2067 2067 # or in MagicsManager, not here
2068 2068 mman.register_alias('ed', 'edit')
2069 2069 mman.register_alias('hist', 'history')
2070 2070 mman.register_alias('rep', 'recall')
2071 2071 mman.register_alias('SVG', 'svg', 'cell')
2072 2072 mman.register_alias('HTML', 'html', 'cell')
2073 2073 mman.register_alias('file', 'writefile', 'cell')
2074 2074
2075 2075 # FIXME: Move the color initialization to the DisplayHook, which
2076 2076 # should be split into a prompt manager and displayhook. We probably
2077 2077 # even need a centralize colors management object.
2078 2078 self.run_line_magic('colors', self.colors)
2079 2079
2080 2080 # Defined here so that it's included in the documentation
2081 2081 @functools.wraps(magic.MagicsManager.register_function)
2082 2082 def register_magic_function(self, func, magic_kind='line', magic_name=None):
2083 2083 self.magics_manager.register_function(func,
2084 2084 magic_kind=magic_kind, magic_name=magic_name)
2085 2085
2086 2086 def run_line_magic(self, magic_name, line, _stack_depth=1):
2087 2087 """Execute the given line magic.
2088 2088
2089 2089 Parameters
2090 2090 ----------
2091 2091 magic_name : str
2092 2092 Name of the desired magic function, without '%' prefix.
2093 2093
2094 2094 line : str
2095 2095 The rest of the input line as a single string.
2096 2096
2097 2097 _stack_depth : int
2098 2098 If run_line_magic() is called from magic() then _stack_depth=2.
2099 2099 This is added to ensure backward compatibility for use of 'get_ipython().magic()'
2100 2100 """
2101 2101 fn = self.find_line_magic(magic_name)
2102 2102 if fn is None:
2103 2103 cm = self.find_cell_magic(magic_name)
2104 2104 etpl = "Line magic function `%%%s` not found%s."
2105 2105 extra = '' if cm is None else (' (But cell magic `%%%%%s` exists, '
2106 2106 'did you mean that instead?)' % magic_name )
2107 2107 raise UsageError(etpl % (magic_name, extra))
2108 2108 else:
2109 2109 # Note: this is the distance in the stack to the user's frame.
2110 2110 # This will need to be updated if the internal calling logic gets
2111 2111 # refactored, or else we'll be expanding the wrong variables.
2112 2112
2113 2113 # Determine stack_depth depending on where run_line_magic() has been called
2114 2114 stack_depth = _stack_depth
2115 2115 magic_arg_s = self.var_expand(line, stack_depth)
2116 2116 # Put magic args in a list so we can call with f(*a) syntax
2117 2117 args = [magic_arg_s]
2118 2118 kwargs = {}
2119 2119 # Grab local namespace if we need it:
2120 2120 if getattr(fn, "needs_local_scope", False):
2121 2121 kwargs['local_ns'] = sys._getframe(stack_depth).f_locals
2122 2122 with self.builtin_trap:
2123 2123 result = fn(*args,**kwargs)
2124 2124 return result
2125 2125
2126 2126 def run_cell_magic(self, magic_name, line, cell):
2127 2127 """Execute the given cell magic.
2128 2128
2129 2129 Parameters
2130 2130 ----------
2131 2131 magic_name : str
2132 2132 Name of the desired magic function, without '%' prefix.
2133 2133
2134 2134 line : str
2135 2135 The rest of the first input line as a single string.
2136 2136
2137 2137 cell : str
2138 2138 The body of the cell as a (possibly multiline) string.
2139 2139 """
2140 2140 fn = self.find_cell_magic(magic_name)
2141 2141 if fn is None:
2142 2142 lm = self.find_line_magic(magic_name)
2143 2143 etpl = "Cell magic `%%{0}` not found{1}."
2144 2144 extra = '' if lm is None else (' (But line magic `%{0}` exists, '
2145 2145 'did you mean that instead?)'.format(magic_name))
2146 2146 raise UsageError(etpl.format(magic_name, extra))
2147 2147 elif cell == '':
2148 2148 message = '%%{0} is a cell magic, but the cell body is empty.'.format(magic_name)
2149 2149 if self.find_line_magic(magic_name) is not None:
2150 2150 message += ' Did you mean the line magic %{0} (single %)?'.format(magic_name)
2151 2151 raise UsageError(message)
2152 2152 else:
2153 2153 # Note: this is the distance in the stack to the user's frame.
2154 2154 # This will need to be updated if the internal calling logic gets
2155 2155 # refactored, or else we'll be expanding the wrong variables.
2156 2156 stack_depth = 2
2157 2157 magic_arg_s = self.var_expand(line, stack_depth)
2158 2158 with self.builtin_trap:
2159 2159 result = fn(magic_arg_s, cell)
2160 2160 return result
2161 2161
2162 2162 def find_line_magic(self, magic_name):
2163 2163 """Find and return a line magic by name.
2164 2164
2165 2165 Returns None if the magic isn't found."""
2166 2166 return self.magics_manager.magics['line'].get(magic_name)
2167 2167
2168 2168 def find_cell_magic(self, magic_name):
2169 2169 """Find and return a cell magic by name.
2170 2170
2171 2171 Returns None if the magic isn't found."""
2172 2172 return self.magics_manager.magics['cell'].get(magic_name)
2173 2173
2174 2174 def find_magic(self, magic_name, magic_kind='line'):
2175 2175 """Find and return a magic of the given type by name.
2176 2176
2177 2177 Returns None if the magic isn't found."""
2178 2178 return self.magics_manager.magics[magic_kind].get(magic_name)
2179 2179
2180 2180 def magic(self, arg_s):
2181 2181 """DEPRECATED. Use run_line_magic() instead.
2182 2182
2183 2183 Call a magic function by name.
2184 2184
2185 2185 Input: a string containing the name of the magic function to call and
2186 2186 any additional arguments to be passed to the magic.
2187 2187
2188 2188 magic('name -opt foo bar') is equivalent to typing at the ipython
2189 2189 prompt:
2190 2190
2191 2191 In[1]: %name -opt foo bar
2192 2192
2193 2193 To call a magic without arguments, simply use magic('name').
2194 2194
2195 2195 This provides a proper Python function to call IPython's magics in any
2196 2196 valid Python code you can type at the interpreter, including loops and
2197 2197 compound statements.
2198 2198 """
2199 2199 # TODO: should we issue a loud deprecation warning here?
2200 2200 magic_name, _, magic_arg_s = arg_s.partition(' ')
2201 2201 magic_name = magic_name.lstrip(prefilter.ESC_MAGIC)
2202 2202 return self.run_line_magic(magic_name, magic_arg_s, _stack_depth=2)
2203 2203
2204 2204 #-------------------------------------------------------------------------
2205 2205 # Things related to macros
2206 2206 #-------------------------------------------------------------------------
2207 2207
2208 2208 def define_macro(self, name, themacro):
2209 2209 """Define a new macro
2210 2210
2211 2211 Parameters
2212 2212 ----------
2213 2213 name : str
2214 2214 The name of the macro.
2215 2215 themacro : str or Macro
2216 2216 The action to do upon invoking the macro. If a string, a new
2217 2217 Macro object is created by passing the string to it.
2218 2218 """
2219 2219
2220 2220 from IPython.core import macro
2221 2221
2222 2222 if isinstance(themacro, str):
2223 2223 themacro = macro.Macro(themacro)
2224 2224 if not isinstance(themacro, macro.Macro):
2225 2225 raise ValueError('A macro must be a string or a Macro instance.')
2226 2226 self.user_ns[name] = themacro
2227 2227
2228 2228 #-------------------------------------------------------------------------
2229 2229 # Things related to the running of system commands
2230 2230 #-------------------------------------------------------------------------
2231 2231
2232 2232 def system_piped(self, cmd):
2233 2233 """Call the given cmd in a subprocess, piping stdout/err
2234 2234
2235 2235 Parameters
2236 2236 ----------
2237 2237 cmd : str
2238 2238 Command to execute (can not end in '&', as background processes are
2239 2239 not supported. Should not be a command that expects input
2240 2240 other than simple text.
2241 2241 """
2242 2242 if cmd.rstrip().endswith('&'):
2243 2243 # this is *far* from a rigorous test
2244 2244 # We do not support backgrounding processes because we either use
2245 2245 # pexpect or pipes to read from. Users can always just call
2246 2246 # os.system() or use ip.system=ip.system_raw
2247 2247 # if they really want a background process.
2248 2248 raise OSError("Background processes not supported.")
2249 2249
2250 2250 # we explicitly do NOT return the subprocess status code, because
2251 2251 # a non-None value would trigger :func:`sys.displayhook` calls.
2252 2252 # Instead, we store the exit_code in user_ns.
2253 2253 self.user_ns['_exit_code'] = system(self.var_expand(cmd, depth=1))
2254 2254
2255 2255 def system_raw(self, cmd):
2256 2256 """Call the given cmd in a subprocess using os.system on Windows or
2257 2257 subprocess.call using the system shell on other platforms.
2258 2258
2259 2259 Parameters
2260 2260 ----------
2261 2261 cmd : str
2262 2262 Command to execute.
2263 2263 """
2264 2264 cmd = self.var_expand(cmd, depth=1)
2265 2265 # protect os.system from UNC paths on Windows, which it can't handle:
2266 2266 if sys.platform == 'win32':
2267 2267 from IPython.utils._process_win32 import AvoidUNCPath
2268 2268 with AvoidUNCPath() as path:
2269 2269 if path is not None:
2270 2270 cmd = '"pushd %s &&"%s' % (path, cmd)
2271 2271 try:
2272 2272 ec = os.system(cmd)
2273 2273 except KeyboardInterrupt:
2274 2274 print('\n' + self.get_exception_only(), file=sys.stderr)
2275 2275 ec = -2
2276 2276 else:
2277 2277 # For posix the result of the subprocess.call() below is an exit
2278 2278 # code, which by convention is zero for success, positive for
2279 2279 # program failure. Exit codes above 128 are reserved for signals,
2280 2280 # and the formula for converting a signal to an exit code is usually
2281 2281 # signal_number+128. To more easily differentiate between exit
2282 2282 # codes and signals, ipython uses negative numbers. For instance
2283 2283 # since control-c is signal 2 but exit code 130, ipython's
2284 2284 # _exit_code variable will read -2. Note that some shells like
2285 2285 # csh and fish don't follow sh/bash conventions for exit codes.
2286 2286 executable = os.environ.get('SHELL', None)
2287 2287 try:
2288 2288 # Use env shell instead of default /bin/sh
2289 2289 ec = subprocess.call(cmd, shell=True, executable=executable)
2290 2290 except KeyboardInterrupt:
2291 2291 # intercept control-C; a long traceback is not useful here
2292 2292 print('\n' + self.get_exception_only(), file=sys.stderr)
2293 2293 ec = 130
2294 2294 if ec > 128:
2295 2295 ec = -(ec - 128)
2296 2296
2297 2297 # We explicitly do NOT return the subprocess status code, because
2298 2298 # a non-None value would trigger :func:`sys.displayhook` calls.
2299 2299 # Instead, we store the exit_code in user_ns. Note the semantics
2300 2300 # of _exit_code: for control-c, _exit_code == -signal.SIGNIT,
2301 2301 # but raising SystemExit(_exit_code) will give status 254!
2302 2302 self.user_ns['_exit_code'] = ec
2303 2303
2304 2304 # use piped system by default, because it is better behaved
2305 2305 system = system_piped
2306 2306
2307 2307 def getoutput(self, cmd, split=True, depth=0):
2308 2308 """Get output (possibly including stderr) from a subprocess.
2309 2309
2310 2310 Parameters
2311 2311 ----------
2312 2312 cmd : str
2313 2313 Command to execute (can not end in '&', as background processes are
2314 2314 not supported.
2315 2315 split : bool, optional
2316 2316 If True, split the output into an IPython SList. Otherwise, an
2317 2317 IPython LSString is returned. These are objects similar to normal
2318 2318 lists and strings, with a few convenience attributes for easier
2319 2319 manipulation of line-based output. You can use '?' on them for
2320 2320 details.
2321 2321 depth : int, optional
2322 2322 How many frames above the caller are the local variables which should
2323 2323 be expanded in the command string? The default (0) assumes that the
2324 2324 expansion variables are in the stack frame calling this function.
2325 2325 """
2326 2326 if cmd.rstrip().endswith('&'):
2327 2327 # this is *far* from a rigorous test
2328 2328 raise OSError("Background processes not supported.")
2329 2329 out = getoutput(self.var_expand(cmd, depth=depth+1))
2330 2330 if split:
2331 2331 out = SList(out.splitlines())
2332 2332 else:
2333 2333 out = LSString(out)
2334 2334 return out
2335 2335
2336 2336 #-------------------------------------------------------------------------
2337 2337 # Things related to aliases
2338 2338 #-------------------------------------------------------------------------
2339 2339
2340 2340 def init_alias(self):
2341 2341 self.alias_manager = AliasManager(shell=self, parent=self)
2342 2342 self.configurables.append(self.alias_manager)
2343 2343
2344 2344 #-------------------------------------------------------------------------
2345 2345 # Things related to extensions
2346 2346 #-------------------------------------------------------------------------
2347 2347
2348 2348 def init_extension_manager(self):
2349 2349 self.extension_manager = ExtensionManager(shell=self, parent=self)
2350 2350 self.configurables.append(self.extension_manager)
2351 2351
2352 2352 #-------------------------------------------------------------------------
2353 2353 # Things related to payloads
2354 2354 #-------------------------------------------------------------------------
2355 2355
2356 2356 def init_payload(self):
2357 2357 self.payload_manager = PayloadManager(parent=self)
2358 2358 self.configurables.append(self.payload_manager)
2359 2359
2360 2360 #-------------------------------------------------------------------------
2361 2361 # Things related to the prefilter
2362 2362 #-------------------------------------------------------------------------
2363 2363
2364 2364 def init_prefilter(self):
2365 2365 self.prefilter_manager = PrefilterManager(shell=self, parent=self)
2366 2366 self.configurables.append(self.prefilter_manager)
2367 2367 # Ultimately this will be refactored in the new interpreter code, but
2368 2368 # for now, we should expose the main prefilter method (there's legacy
2369 2369 # code out there that may rely on this).
2370 2370 self.prefilter = self.prefilter_manager.prefilter_lines
2371 2371
2372 2372 def auto_rewrite_input(self, cmd):
2373 2373 """Print to the screen the rewritten form of the user's command.
2374 2374
2375 2375 This shows visual feedback by rewriting input lines that cause
2376 2376 automatic calling to kick in, like::
2377 2377
2378 2378 /f x
2379 2379
2380 2380 into::
2381 2381
2382 2382 ------> f(x)
2383 2383
2384 2384 after the user's input prompt. This helps the user understand that the
2385 2385 input line was transformed automatically by IPython.
2386 2386 """
2387 2387 if not self.show_rewritten_input:
2388 2388 return
2389 2389
2390 2390 # This is overridden in TerminalInteractiveShell to use fancy prompts
2391 2391 print("------> " + cmd)
2392 2392
2393 2393 #-------------------------------------------------------------------------
2394 2394 # Things related to extracting values/expressions from kernel and user_ns
2395 2395 #-------------------------------------------------------------------------
2396 2396
2397 2397 def _user_obj_error(self):
2398 2398 """return simple exception dict
2399 2399
2400 2400 for use in user_expressions
2401 2401 """
2402 2402
2403 2403 etype, evalue, tb = self._get_exc_info()
2404 2404 stb = self.InteractiveTB.get_exception_only(etype, evalue)
2405 2405
2406 2406 exc_info = {
2407 2407 u'status' : 'error',
2408 2408 u'traceback' : stb,
2409 2409 u'ename' : etype.__name__,
2410 2410 u'evalue' : py3compat.safe_unicode(evalue),
2411 2411 }
2412 2412
2413 2413 return exc_info
2414 2414
2415 2415 def _format_user_obj(self, obj):
2416 2416 """format a user object to display dict
2417 2417
2418 2418 for use in user_expressions
2419 2419 """
2420 2420
2421 2421 data, md = self.display_formatter.format(obj)
2422 2422 value = {
2423 2423 'status' : 'ok',
2424 2424 'data' : data,
2425 2425 'metadata' : md,
2426 2426 }
2427 2427 return value
2428 2428
2429 2429 def user_expressions(self, expressions):
2430 2430 """Evaluate a dict of expressions in the user's namespace.
2431 2431
2432 2432 Parameters
2433 2433 ----------
2434 2434 expressions : dict
2435 2435 A dict with string keys and string values. The expression values
2436 2436 should be valid Python expressions, each of which will be evaluated
2437 2437 in the user namespace.
2438 2438
2439 2439 Returns
2440 2440 -------
2441 2441 A dict, keyed like the input expressions dict, with the rich mime-typed
2442 2442 display_data of each value.
2443 2443 """
2444 2444 out = {}
2445 2445 user_ns = self.user_ns
2446 2446 global_ns = self.user_global_ns
2447 2447
2448 2448 for key, expr in expressions.items():
2449 2449 try:
2450 2450 value = self._format_user_obj(eval(expr, global_ns, user_ns))
2451 2451 except:
2452 2452 value = self._user_obj_error()
2453 2453 out[key] = value
2454 2454 return out
2455 2455
2456 2456 #-------------------------------------------------------------------------
2457 2457 # Things related to the running of code
2458 2458 #-------------------------------------------------------------------------
2459 2459
2460 2460 def ex(self, cmd):
2461 2461 """Execute a normal python statement in user namespace."""
2462 2462 with self.builtin_trap:
2463 2463 exec(cmd, self.user_global_ns, self.user_ns)
2464 2464
2465 2465 def ev(self, expr):
2466 2466 """Evaluate python expression expr in user namespace.
2467 2467
2468 2468 Returns the result of evaluation
2469 2469 """
2470 2470 with self.builtin_trap:
2471 2471 return eval(expr, self.user_global_ns, self.user_ns)
2472 2472
2473 2473 def safe_execfile(self, fname, *where, exit_ignore=False, raise_exceptions=False, shell_futures=False):
2474 2474 """A safe version of the builtin execfile().
2475 2475
2476 2476 This version will never throw an exception, but instead print
2477 2477 helpful error messages to the screen. This only works on pure
2478 2478 Python files with the .py extension.
2479 2479
2480 2480 Parameters
2481 2481 ----------
2482 2482 fname : string
2483 2483 The name of the file to be executed.
2484 2484 where : tuple
2485 2485 One or two namespaces, passed to execfile() as (globals,locals).
2486 2486 If only one is given, it is passed as both.
2487 2487 exit_ignore : bool (False)
2488 2488 If True, then silence SystemExit for non-zero status (it is always
2489 2489 silenced for zero status, as it is so common).
2490 2490 raise_exceptions : bool (False)
2491 2491 If True raise exceptions everywhere. Meant for testing.
2492 2492 shell_futures : bool (False)
2493 2493 If True, the code will share future statements with the interactive
2494 2494 shell. It will both be affected by previous __future__ imports, and
2495 2495 any __future__ imports in the code will affect the shell. If False,
2496 2496 __future__ imports are not shared in either direction.
2497 2497
2498 2498 """
2499 2499 fname = os.path.abspath(os.path.expanduser(fname))
2500 2500
2501 2501 # Make sure we can open the file
2502 2502 try:
2503 2503 with open(fname):
2504 2504 pass
2505 2505 except:
2506 2506 warn('Could not open file <%s> for safe execution.' % fname)
2507 2507 return
2508 2508
2509 2509 # Find things also in current directory. This is needed to mimic the
2510 2510 # behavior of running a script from the system command line, where
2511 2511 # Python inserts the script's directory into sys.path
2512 2512 dname = os.path.dirname(fname)
2513 2513
2514 2514 with prepended_to_syspath(dname), self.builtin_trap:
2515 2515 try:
2516 2516 glob, loc = (where + (None, ))[:2]
2517 2517 py3compat.execfile(
2518 2518 fname, glob, loc,
2519 2519 self.compile if shell_futures else None)
2520 2520 except SystemExit as status:
2521 2521 # If the call was made with 0 or None exit status (sys.exit(0)
2522 2522 # or sys.exit() ), don't bother showing a traceback, as both of
2523 2523 # these are considered normal by the OS:
2524 2524 # > python -c'import sys;sys.exit(0)'; echo $?
2525 2525 # 0
2526 2526 # > python -c'import sys;sys.exit()'; echo $?
2527 2527 # 0
2528 2528 # For other exit status, we show the exception unless
2529 2529 # explicitly silenced, but only in short form.
2530 2530 if status.code:
2531 2531 if raise_exceptions:
2532 2532 raise
2533 2533 if not exit_ignore:
2534 2534 self.showtraceback(exception_only=True)
2535 2535 except:
2536 2536 if raise_exceptions:
2537 2537 raise
2538 2538 # tb offset is 2 because we wrap execfile
2539 2539 self.showtraceback(tb_offset=2)
2540 2540
2541 2541 def safe_execfile_ipy(self, fname, shell_futures=False, raise_exceptions=False):
2542 2542 """Like safe_execfile, but for .ipy or .ipynb files with IPython syntax.
2543 2543
2544 2544 Parameters
2545 2545 ----------
2546 2546 fname : str
2547 2547 The name of the file to execute. The filename must have a
2548 2548 .ipy or .ipynb extension.
2549 2549 shell_futures : bool (False)
2550 2550 If True, the code will share future statements with the interactive
2551 2551 shell. It will both be affected by previous __future__ imports, and
2552 2552 any __future__ imports in the code will affect the shell. If False,
2553 2553 __future__ imports are not shared in either direction.
2554 2554 raise_exceptions : bool (False)
2555 2555 If True raise exceptions everywhere. Meant for testing.
2556 2556 """
2557 2557 fname = os.path.abspath(os.path.expanduser(fname))
2558 2558
2559 2559 # Make sure we can open the file
2560 2560 try:
2561 2561 with open(fname):
2562 2562 pass
2563 2563 except:
2564 2564 warn('Could not open file <%s> for safe execution.' % fname)
2565 2565 return
2566 2566
2567 2567 # Find things also in current directory. This is needed to mimic the
2568 2568 # behavior of running a script from the system command line, where
2569 2569 # Python inserts the script's directory into sys.path
2570 2570 dname = os.path.dirname(fname)
2571 2571
2572 2572 def get_cells():
2573 2573 """generator for sequence of code blocks to run"""
2574 2574 if fname.endswith('.ipynb'):
2575 2575 from nbformat import read
2576 2576 nb = read(fname, as_version=4)
2577 2577 if not nb.cells:
2578 2578 return
2579 2579 for cell in nb.cells:
2580 2580 if cell.cell_type == 'code':
2581 2581 yield cell.source
2582 2582 else:
2583 2583 with open(fname) as f:
2584 2584 yield f.read()
2585 2585
2586 2586 with prepended_to_syspath(dname):
2587 2587 try:
2588 2588 for cell in get_cells():
2589 2589 result = self.run_cell(cell, silent=True, shell_futures=shell_futures)
2590 2590 if raise_exceptions:
2591 2591 result.raise_error()
2592 2592 elif not result.success:
2593 2593 break
2594 2594 except:
2595 2595 if raise_exceptions:
2596 2596 raise
2597 2597 self.showtraceback()
2598 2598 warn('Unknown failure executing file: <%s>' % fname)
2599 2599
2600 2600 def safe_run_module(self, mod_name, where):
2601 2601 """A safe version of runpy.run_module().
2602 2602
2603 2603 This version will never throw an exception, but instead print
2604 2604 helpful error messages to the screen.
2605 2605
2606 2606 `SystemExit` exceptions with status code 0 or None are ignored.
2607 2607
2608 2608 Parameters
2609 2609 ----------
2610 2610 mod_name : string
2611 2611 The name of the module to be executed.
2612 2612 where : dict
2613 2613 The globals namespace.
2614 2614 """
2615 2615 try:
2616 2616 try:
2617 2617 where.update(
2618 2618 runpy.run_module(str(mod_name), run_name="__main__",
2619 2619 alter_sys=True)
2620 2620 )
2621 2621 except SystemExit as status:
2622 2622 if status.code:
2623 2623 raise
2624 2624 except:
2625 2625 self.showtraceback()
2626 2626 warn('Unknown failure executing module: <%s>' % mod_name)
2627 2627
2628 2628 def run_cell(self, raw_cell, store_history=False, silent=False, shell_futures=True):
2629 2629 """Run a complete IPython cell.
2630 2630
2631 2631 Parameters
2632 2632 ----------
2633 2633 raw_cell : str
2634 2634 The code (including IPython code such as %magic functions) to run.
2635 2635 store_history : bool
2636 2636 If True, the raw and translated cell will be stored in IPython's
2637 2637 history. For user code calling back into IPython's machinery, this
2638 2638 should be set to False.
2639 2639 silent : bool
2640 2640 If True, avoid side-effects, such as implicit displayhooks and
2641 2641 and logging. silent=True forces store_history=False.
2642 2642 shell_futures : bool
2643 2643 If True, the code will share future statements with the interactive
2644 2644 shell. It will both be affected by previous __future__ imports, and
2645 2645 any __future__ imports in the code will affect the shell. If False,
2646 2646 __future__ imports are not shared in either direction.
2647 2647
2648 2648 Returns
2649 2649 -------
2650 2650 result : :class:`ExecutionResult`
2651 2651 """
2652 2652 try:
2653 2653 result = self._run_cell(
2654 2654 raw_cell, store_history, silent, shell_futures)
2655 2655 finally:
2656 2656 self.events.trigger('post_execute')
2657 2657 if not silent:
2658 2658 self.events.trigger('post_run_cell', result)
2659 2659 return result
2660 2660
2661 2661 def _run_cell(self, raw_cell, store_history, silent, shell_futures):
2662 2662 """Internal method to run a complete IPython cell.
2663 2663
2664 2664 Parameters
2665 2665 ----------
2666 2666 raw_cell : str
2667 2667 store_history : bool
2668 2668 silent : bool
2669 2669 shell_futures : bool
2670 2670
2671 2671 Returns
2672 2672 -------
2673 2673 result : :class:`ExecutionResult`
2674 2674 """
2675 2675 info = ExecutionInfo(
2676 2676 raw_cell, store_history, silent, shell_futures)
2677 2677 result = ExecutionResult(info)
2678 2678
2679 2679 if (not raw_cell) or raw_cell.isspace():
2680 2680 self.last_execution_succeeded = True
2681 2681 self.last_execution_result = result
2682 2682 return result
2683 2683
2684 2684 if silent:
2685 2685 store_history = False
2686 2686
2687 2687 if store_history:
2688 2688 result.execution_count = self.execution_count
2689 2689
2690 2690 def error_before_exec(value):
2691 2691 result.error_before_exec = value
2692 2692 self.last_execution_succeeded = False
2693 2693 self.last_execution_result = result
2694 2694 return result
2695 2695
2696 2696 self.events.trigger('pre_execute')
2697 2697 if not silent:
2698 2698 self.events.trigger('pre_run_cell', info)
2699 2699
2700 2700 # If any of our input transformation (input_transformer_manager or
2701 2701 # prefilter_manager) raises an exception, we store it in this variable
2702 2702 # so that we can display the error after logging the input and storing
2703 2703 # it in the history.
2704 2704 preprocessing_exc_tuple = None
2705 2705 try:
2706 2706 # Static input transformations
2707 2707 cell = self.input_transformer_manager.transform_cell(raw_cell)
2708 2708 except SyntaxError:
2709 2709 preprocessing_exc_tuple = sys.exc_info()
2710 2710 cell = raw_cell # cell has to exist so it can be stored/logged
2711 2711 else:
2712 2712 if len(cell.splitlines()) == 1:
2713 2713 # Dynamic transformations - only applied for single line commands
2714 2714 with self.builtin_trap:
2715 2715 try:
2716 2716 # use prefilter_lines to handle trailing newlines
2717 2717 # restore trailing newline for ast.parse
2718 2718 cell = self.prefilter_manager.prefilter_lines(cell) + '\n'
2719 2719 except Exception:
2720 2720 # don't allow prefilter errors to crash IPython
2721 2721 preprocessing_exc_tuple = sys.exc_info()
2722 2722
2723 2723 # Store raw and processed history
2724 2724 if store_history:
2725 2725 self.history_manager.store_inputs(self.execution_count,
2726 2726 cell, raw_cell)
2727 2727 if not silent:
2728 2728 self.logger.log(cell, raw_cell)
2729 2729
2730 2730 # Display the exception if input processing failed.
2731 2731 if preprocessing_exc_tuple is not None:
2732 2732 self.showtraceback(preprocessing_exc_tuple)
2733 2733 if store_history:
2734 2734 self.execution_count += 1
2735 2735 return error_before_exec(preprocessing_exc_tuple[2])
2736 2736
2737 2737 # Our own compiler remembers the __future__ environment. If we want to
2738 2738 # run code with a separate __future__ environment, use the default
2739 2739 # compiler
2740 2740 compiler = self.compile if shell_futures else CachingCompiler()
2741 2741
2742 2742 with self.builtin_trap:
2743 2743 cell_name = self.compile.cache(cell, self.execution_count)
2744 2744
2745 2745 with self.display_trap:
2746 2746 # Compile to bytecode
2747 2747 try:
2748 2748 code_ast = compiler.ast_parse(cell, filename=cell_name)
2749 2749 except self.custom_exceptions as e:
2750 2750 etype, value, tb = sys.exc_info()
2751 2751 self.CustomTB(etype, value, tb)
2752 2752 return error_before_exec(e)
2753 2753 except IndentationError as e:
2754 2754 self.showindentationerror()
2755 2755 if store_history:
2756 2756 self.execution_count += 1
2757 2757 return error_before_exec(e)
2758 2758 except (OverflowError, SyntaxError, ValueError, TypeError,
2759 2759 MemoryError) as e:
2760 2760 self.showsyntaxerror()
2761 2761 if store_history:
2762 2762 self.execution_count += 1
2763 2763 return error_before_exec(e)
2764 2764
2765 2765 # Apply AST transformations
2766 2766 try:
2767 2767 code_ast = self.transform_ast(code_ast)
2768 2768 except InputRejected as e:
2769 2769 self.showtraceback()
2770 2770 if store_history:
2771 2771 self.execution_count += 1
2772 2772 return error_before_exec(e)
2773 2773
2774 2774 # Give the displayhook a reference to our ExecutionResult so it
2775 2775 # can fill in the output value.
2776 2776 self.displayhook.exec_result = result
2777 2777
2778 2778 # Execute the user code
2779 2779 interactivity = 'none' if silent else self.ast_node_interactivity
2780 2780 has_raised = self.run_ast_nodes(code_ast.body, cell_name,
2781 2781 interactivity=interactivity, compiler=compiler, result=result)
2782 2782
2783 2783 self.last_execution_succeeded = not has_raised
2784 2784 self.last_execution_result = result
2785 2785
2786 2786 # Reset this so later displayed values do not modify the
2787 2787 # ExecutionResult
2788 2788 self.displayhook.exec_result = None
2789 2789
2790 2790 if store_history:
2791 2791 # Write output to the database. Does nothing unless
2792 2792 # history output logging is enabled.
2793 2793 self.history_manager.store_output(self.execution_count)
2794 2794 # Each cell is a *single* input, regardless of how many lines it has
2795 2795 self.execution_count += 1
2796 2796
2797 2797 return result
2798 2798
2799 2799 def transform_ast(self, node):
2800 2800 """Apply the AST transformations from self.ast_transformers
2801 2801
2802 2802 Parameters
2803 2803 ----------
2804 2804 node : ast.Node
2805 2805 The root node to be transformed. Typically called with the ast.Module
2806 2806 produced by parsing user input.
2807 2807
2808 2808 Returns
2809 2809 -------
2810 2810 An ast.Node corresponding to the node it was called with. Note that it
2811 2811 may also modify the passed object, so don't rely on references to the
2812 2812 original AST.
2813 2813 """
2814 2814 for transformer in self.ast_transformers:
2815 2815 try:
2816 2816 node = transformer.visit(node)
2817 2817 except InputRejected:
2818 2818 # User-supplied AST transformers can reject an input by raising
2819 2819 # an InputRejected. Short-circuit in this case so that we
2820 2820 # don't unregister the transform.
2821 2821 raise
2822 2822 except Exception:
2823 2823 warn("AST transformer %r threw an error. It will be unregistered." % transformer)
2824 2824 self.ast_transformers.remove(transformer)
2825 2825
2826 2826 if self.ast_transformers:
2827 2827 ast.fix_missing_locations(node)
2828 2828 return node
2829 2829
2830 2830
2831 2831 def run_ast_nodes(self, nodelist:ListType[AST], cell_name:str, interactivity='last_expr',
2832 2832 compiler=compile, result=None):
2833 2833 """Run a sequence of AST nodes. The execution mode depends on the
2834 2834 interactivity parameter.
2835 2835
2836 2836 Parameters
2837 2837 ----------
2838 2838 nodelist : list
2839 2839 A sequence of AST nodes to run.
2840 2840 cell_name : str
2841 2841 Will be passed to the compiler as the filename of the cell. Typically
2842 2842 the value returned by ip.compile.cache(cell).
2843 2843 interactivity : str
2844 2844 'all', 'last', 'last_expr' , 'last_expr_or_assign' or 'none',
2845 2845 specifying which nodes should be run interactively (displaying output
2846 2846 from expressions). 'last_expr' will run the last node interactively
2847 2847 only if it is an expression (i.e. expressions in loops or other blocks
2848 2848 are not displayed) 'last_expr_or_assign' will run the last expression
2849 2849 or the last assignment. Other values for this parameter will raise a
2850 2850 ValueError.
2851 2851 compiler : callable
2852 2852 A function with the same interface as the built-in compile(), to turn
2853 2853 the AST nodes into code objects. Default is the built-in compile().
2854 2854 result : ExecutionResult, optional
2855 2855 An object to store exceptions that occur during execution.
2856 2856
2857 2857 Returns
2858 2858 -------
2859 2859 True if an exception occurred while running code, False if it finished
2860 2860 running.
2861 2861 """
2862 2862 if not nodelist:
2863 2863 return
2864 2864
2865 2865 if interactivity == 'last_expr_or_assign':
2866 2866 if isinstance(nodelist[-1], _assign_nodes):
2867 2867 asg = nodelist[-1]
2868 2868 if isinstance(asg, ast.Assign) and len(asg.targets) == 1:
2869 2869 target = asg.targets[0]
2870 2870 elif isinstance(asg, _single_targets_nodes):
2871 2871 target = asg.target
2872 2872 else:
2873 2873 target = None
2874 2874 if isinstance(target, ast.Name):
2875 2875 nnode = ast.Expr(ast.Name(target.id, ast.Load()))
2876 2876 ast.fix_missing_locations(nnode)
2877 2877 nodelist.append(nnode)
2878 2878 interactivity = 'last_expr'
2879 2879
2880 2880 if interactivity == 'last_expr':
2881 2881 if isinstance(nodelist[-1], ast.Expr):
2882 2882 interactivity = "last"
2883 2883 else:
2884 2884 interactivity = "none"
2885 2885
2886 2886 if interactivity == 'none':
2887 2887 to_run_exec, to_run_interactive = nodelist, []
2888 2888 elif interactivity == 'last':
2889 2889 to_run_exec, to_run_interactive = nodelist[:-1], nodelist[-1:]
2890 2890 elif interactivity == 'all':
2891 2891 to_run_exec, to_run_interactive = [], nodelist
2892 2892 else:
2893 2893 raise ValueError("Interactivity was %r" % interactivity)
2894 2894
2895 2895 try:
2896 2896 for i, node in enumerate(to_run_exec):
2897 2897 mod = ast.Module([node])
2898 2898 code = compiler(mod, cell_name, "exec")
2899 2899 if self.run_code(code, result):
2900 2900 return True
2901 2901
2902 2902 for i, node in enumerate(to_run_interactive):
2903 2903 mod = ast.Interactive([node])
2904 2904 code = compiler(mod, cell_name, "single")
2905 2905 if self.run_code(code, result):
2906 2906 return True
2907 2907
2908 2908 # Flush softspace
2909 2909 if softspace(sys.stdout, 0):
2910 2910 print()
2911 2911
2912 2912 except:
2913 2913 # It's possible to have exceptions raised here, typically by
2914 2914 # compilation of odd code (such as a naked 'return' outside a
2915 2915 # function) that did parse but isn't valid. Typically the exception
2916 2916 # is a SyntaxError, but it's safest just to catch anything and show
2917 2917 # the user a traceback.
2918 2918
2919 2919 # We do only one try/except outside the loop to minimize the impact
2920 2920 # on runtime, and also because if any node in the node list is
2921 2921 # broken, we should stop execution completely.
2922 2922 if result:
2923 2923 result.error_before_exec = sys.exc_info()[1]
2924 2924 self.showtraceback()
2925 2925 return True
2926 2926
2927 2927 return False
2928 2928
2929 2929 def run_code(self, code_obj, result=None):
2930 2930 """Execute a code object.
2931 2931
2932 2932 When an exception occurs, self.showtraceback() is called to display a
2933 2933 traceback.
2934 2934
2935 2935 Parameters
2936 2936 ----------
2937 2937 code_obj : code object
2938 2938 A compiled code object, to be executed
2939 2939 result : ExecutionResult, optional
2940 2940 An object to store exceptions that occur during execution.
2941 2941
2942 2942 Returns
2943 2943 -------
2944 2944 False : successful execution.
2945 2945 True : an error occurred.
2946 2946 """
2947 2947 # Set our own excepthook in case the user code tries to call it
2948 2948 # directly, so that the IPython crash handler doesn't get triggered
2949 2949 old_excepthook, sys.excepthook = sys.excepthook, self.excepthook
2950 2950
2951 2951 # we save the original sys.excepthook in the instance, in case config
2952 2952 # code (such as magics) needs access to it.
2953 2953 self.sys_excepthook = old_excepthook
2954 2954 outflag = True # happens in more places, so it's easier as default
2955 2955 try:
2956 2956 try:
2957 2957 self.hooks.pre_run_code_hook()
2958 2958 #rprint('Running code', repr(code_obj)) # dbg
2959 2959 exec(code_obj, self.user_global_ns, self.user_ns)
2960 2960 finally:
2961 2961 # Reset our crash handler in place
2962 2962 sys.excepthook = old_excepthook
2963 2963 except SystemExit as e:
2964 2964 if result is not None:
2965 2965 result.error_in_exec = e
2966 2966 self.showtraceback(exception_only=True)
2967 2967 warn("To exit: use 'exit', 'quit', or Ctrl-D.", stacklevel=1)
2968 2968 except self.custom_exceptions:
2969 2969 etype, value, tb = sys.exc_info()
2970 2970 if result is not None:
2971 2971 result.error_in_exec = value
2972 2972 self.CustomTB(etype, value, tb)
2973 2973 except:
2974 2974 if result is not None:
2975 2975 result.error_in_exec = sys.exc_info()[1]
2976 2976 self.showtraceback(running_compiled_code=True)
2977 2977 else:
2978 2978 outflag = False
2979 2979 return outflag
2980 2980
2981 2981 # For backwards compatibility
2982 2982 runcode = run_code
2983 2983
2984 2984 #-------------------------------------------------------------------------
2985 2985 # Things related to GUI support and pylab
2986 2986 #-------------------------------------------------------------------------
2987 2987
2988 2988 active_eventloop = None
2989 2989
2990 2990 def enable_gui(self, gui=None):
2991 2991 raise NotImplementedError('Implement enable_gui in a subclass')
2992 2992
2993 2993 def enable_matplotlib(self, gui=None):
2994 2994 """Enable interactive matplotlib and inline figure support.
2995 2995
2996 2996 This takes the following steps:
2997 2997
2998 2998 1. select the appropriate eventloop and matplotlib backend
2999 2999 2. set up matplotlib for interactive use with that backend
3000 3000 3. configure formatters for inline figure display
3001 3001 4. enable the selected gui eventloop
3002 3002
3003 3003 Parameters
3004 3004 ----------
3005 3005 gui : optional, string
3006 3006 If given, dictates the choice of matplotlib GUI backend to use
3007 3007 (should be one of IPython's supported backends, 'qt', 'osx', 'tk',
3008 3008 'gtk', 'wx' or 'inline'), otherwise we use the default chosen by
3009 3009 matplotlib (as dictated by the matplotlib build-time options plus the
3010 3010 user's matplotlibrc configuration file). Note that not all backends
3011 3011 make sense in all contexts, for example a terminal ipython can't
3012 3012 display figures inline.
3013 3013 """
3014 3014 from IPython.core import pylabtools as pt
3015 3015 gui, backend = pt.find_gui_and_backend(gui, self.pylab_gui_select)
3016 3016
3017 3017 if gui != 'inline':
3018 3018 # If we have our first gui selection, store it
3019 3019 if self.pylab_gui_select is None:
3020 3020 self.pylab_gui_select = gui
3021 3021 # Otherwise if they are different
3022 3022 elif gui != self.pylab_gui_select:
3023 3023 print('Warning: Cannot change to a different GUI toolkit: %s.'
3024 3024 ' Using %s instead.' % (gui, self.pylab_gui_select))
3025 3025 gui, backend = pt.find_gui_and_backend(self.pylab_gui_select)
3026 3026
3027 3027 pt.activate_matplotlib(backend)
3028 3028 pt.configure_inline_support(self, backend)
3029 3029
3030 3030 # Now we must activate the gui pylab wants to use, and fix %run to take
3031 3031 # plot updates into account
3032 3032 self.enable_gui(gui)
3033 3033 self.magics_manager.registry['ExecutionMagics'].default_runner = \
3034 3034 pt.mpl_runner(self.safe_execfile)
3035 3035
3036 3036 return gui, backend
3037 3037
3038 3038 def enable_pylab(self, gui=None, import_all=True, welcome_message=False):
3039 3039 """Activate pylab support at runtime.
3040 3040
3041 3041 This turns on support for matplotlib, preloads into the interactive
3042 3042 namespace all of numpy and pylab, and configures IPython to correctly
3043 3043 interact with the GUI event loop. The GUI backend to be used can be
3044 3044 optionally selected with the optional ``gui`` argument.
3045 3045
3046 3046 This method only adds preloading the namespace to InteractiveShell.enable_matplotlib.
3047 3047
3048 3048 Parameters
3049 3049 ----------
3050 3050 gui : optional, string
3051 3051 If given, dictates the choice of matplotlib GUI backend to use
3052 3052 (should be one of IPython's supported backends, 'qt', 'osx', 'tk',
3053 3053 'gtk', 'wx' or 'inline'), otherwise we use the default chosen by
3054 3054 matplotlib (as dictated by the matplotlib build-time options plus the
3055 3055 user's matplotlibrc configuration file). Note that not all backends
3056 3056 make sense in all contexts, for example a terminal ipython can't
3057 3057 display figures inline.
3058 3058 import_all : optional, bool, default: True
3059 3059 Whether to do `from numpy import *` and `from pylab import *`
3060 3060 in addition to module imports.
3061 3061 welcome_message : deprecated
3062 3062 This argument is ignored, no welcome message will be displayed.
3063 3063 """
3064 3064 from IPython.core.pylabtools import import_pylab
3065 3065
3066 3066 gui, backend = self.enable_matplotlib(gui)
3067 3067
3068 3068 # We want to prevent the loading of pylab to pollute the user's
3069 3069 # namespace as shown by the %who* magics, so we execute the activation
3070 3070 # code in an empty namespace, and we update *both* user_ns and
3071 3071 # user_ns_hidden with this information.
3072 3072 ns = {}
3073 3073 import_pylab(ns, import_all)
3074 3074 # warn about clobbered names
3075 3075 ignored = {"__builtins__"}
3076 3076 both = set(ns).intersection(self.user_ns).difference(ignored)
3077 3077 clobbered = [ name for name in both if self.user_ns[name] is not ns[name] ]
3078 3078 self.user_ns.update(ns)
3079 3079 self.user_ns_hidden.update(ns)
3080 3080 return gui, backend, clobbered
3081 3081
3082 3082 #-------------------------------------------------------------------------
3083 3083 # Utilities
3084 3084 #-------------------------------------------------------------------------
3085 3085
3086 3086 def var_expand(self, cmd, depth=0, formatter=DollarFormatter()):
3087 3087 """Expand python variables in a string.
3088 3088
3089 3089 The depth argument indicates how many frames above the caller should
3090 3090 be walked to look for the local namespace where to expand variables.
3091 3091
3092 3092 The global namespace for expansion is always the user's interactive
3093 3093 namespace.
3094 3094 """
3095 3095 ns = self.user_ns.copy()
3096 3096 try:
3097 3097 frame = sys._getframe(depth+1)
3098 3098 except ValueError:
3099 3099 # This is thrown if there aren't that many frames on the stack,
3100 3100 # e.g. if a script called run_line_magic() directly.
3101 3101 pass
3102 3102 else:
3103 3103 ns.update(frame.f_locals)
3104 3104
3105 3105 try:
3106 3106 # We have to use .vformat() here, because 'self' is a valid and common
3107 3107 # name, and expanding **ns for .format() would make it collide with
3108 3108 # the 'self' argument of the method.
3109 3109 cmd = formatter.vformat(cmd, args=[], kwargs=ns)
3110 3110 except Exception:
3111 3111 # if formatter couldn't format, just let it go untransformed
3112 3112 pass
3113 3113 return cmd
3114 3114
3115 3115 def mktempfile(self, data=None, prefix='ipython_edit_'):
3116 3116 """Make a new tempfile and return its filename.
3117 3117
3118 3118 This makes a call to tempfile.mkstemp (created in a tempfile.mkdtemp),
3119 3119 but it registers the created filename internally so ipython cleans it up
3120 3120 at exit time.
3121 3121
3122 3122 Optional inputs:
3123 3123
3124 3124 - data(None): if data is given, it gets written out to the temp file
3125 3125 immediately, and the file is closed again."""
3126 3126
3127 3127 dirname = tempfile.mkdtemp(prefix=prefix)
3128 3128 self.tempdirs.append(dirname)
3129 3129
3130 3130 handle, filename = tempfile.mkstemp('.py', prefix, dir=dirname)
3131 3131 os.close(handle) # On Windows, there can only be one open handle on a file
3132 3132 self.tempfiles.append(filename)
3133 3133
3134 3134 if data:
3135 3135 tmp_file = open(filename,'w')
3136 3136 tmp_file.write(data)
3137 3137 tmp_file.close()
3138 3138 return filename
3139 3139
3140 3140 @undoc
3141 3141 def write(self,data):
3142 3142 """DEPRECATED: Write a string to the default output"""
3143 3143 warn('InteractiveShell.write() is deprecated, use sys.stdout instead',
3144 3144 DeprecationWarning, stacklevel=2)
3145 3145 sys.stdout.write(data)
3146 3146
3147 3147 @undoc
3148 3148 def write_err(self,data):
3149 3149 """DEPRECATED: Write a string to the default error output"""
3150 3150 warn('InteractiveShell.write_err() is deprecated, use sys.stderr instead',
3151 3151 DeprecationWarning, stacklevel=2)
3152 3152 sys.stderr.write(data)
3153 3153
3154 3154 def ask_yes_no(self, prompt, default=None, interrupt=None):
3155 3155 if self.quiet:
3156 3156 return True
3157 3157 return ask_yes_no(prompt,default,interrupt)
3158 3158
3159 3159 def show_usage(self):
3160 3160 """Show a usage message"""
3161 3161 page.page(IPython.core.usage.interactive_usage)
3162 3162
3163 3163 def extract_input_lines(self, range_str, raw=False):
3164 3164 """Return as a string a set of input history slices.
3165 3165
3166 3166 Parameters
3167 3167 ----------
3168 3168 range_str : string
3169 3169 The set of slices is given as a string, like "~5/6-~4/2 4:8 9",
3170 3170 since this function is for use by magic functions which get their
3171 3171 arguments as strings. The number before the / is the session
3172 3172 number: ~n goes n back from the current session.
3173 3173
3174 3174 raw : bool, optional
3175 3175 By default, the processed input is used. If this is true, the raw
3176 3176 input history is used instead.
3177 3177
3178 3178 Notes
3179 3179 -----
3180 3180
3181 3181 Slices can be described with two notations:
3182 3182
3183 3183 * ``N:M`` -> standard python form, means including items N...(M-1).
3184 3184 * ``N-M`` -> include items N..M (closed endpoint).
3185 3185 """
3186 3186 lines = self.history_manager.get_range_by_str(range_str, raw=raw)
3187 3187 return "\n".join(x for _, _, x in lines)
3188 3188
3189 3189 def find_user_code(self, target, raw=True, py_only=False, skip_encoding_cookie=True, search_ns=False):
3190 3190 """Get a code string from history, file, url, or a string or macro.
3191 3191
3192 3192 This is mainly used by magic functions.
3193 3193
3194 3194 Parameters
3195 3195 ----------
3196 3196
3197 3197 target : str
3198 3198
3199 3199 A string specifying code to retrieve. This will be tried respectively
3200 3200 as: ranges of input history (see %history for syntax), url,
3201 3201 corresponding .py file, filename, or an expression evaluating to a
3202 3202 string or Macro in the user namespace.
3203 3203
3204 3204 raw : bool
3205 3205 If true (default), retrieve raw history. Has no effect on the other
3206 3206 retrieval mechanisms.
3207 3207
3208 3208 py_only : bool (default False)
3209 3209 Only try to fetch python code, do not try alternative methods to decode file
3210 3210 if unicode fails.
3211 3211
3212 3212 Returns
3213 3213 -------
3214 3214 A string of code.
3215 3215
3216 3216 ValueError is raised if nothing is found, and TypeError if it evaluates
3217 3217 to an object of another type. In each case, .args[0] is a printable
3218 3218 message.
3219 3219 """
3220 3220 code = self.extract_input_lines(target, raw=raw) # Grab history
3221 3221 if code:
3222 3222 return code
3223 3223 try:
3224 3224 if target.startswith(('http://', 'https://')):
3225 3225 return openpy.read_py_url(target, skip_encoding_cookie=skip_encoding_cookie)
3226 3226 except UnicodeDecodeError:
3227 3227 if not py_only :
3228 3228 # Deferred import
3229 3229 from urllib.request import urlopen
3230 3230 response = urlopen(target)
3231 3231 return response.read().decode('latin1')
3232 3232 raise ValueError(("'%s' seem to be unreadable.") % target)
3233 3233
3234 3234 potential_target = [target]
3235 3235 try :
3236 3236 potential_target.insert(0,get_py_filename(target))
3237 3237 except IOError:
3238 3238 pass
3239 3239
3240 3240 for tgt in potential_target :
3241 3241 if os.path.isfile(tgt): # Read file
3242 3242 try :
3243 3243 return openpy.read_py_file(tgt, skip_encoding_cookie=skip_encoding_cookie)
3244 3244 except UnicodeDecodeError :
3245 3245 if not py_only :
3246 3246 with io_open(tgt,'r', encoding='latin1') as f :
3247 3247 return f.read()
3248 3248 raise ValueError(("'%s' seem to be unreadable.") % target)
3249 3249 elif os.path.isdir(os.path.expanduser(tgt)):
3250 3250 raise ValueError("'%s' is a directory, not a regular file." % target)
3251 3251
3252 3252 if search_ns:
3253 3253 # Inspect namespace to load object source
3254 3254 object_info = self.object_inspect(target, detail_level=1)
3255 3255 if object_info['found'] and object_info['source']:
3256 3256 return object_info['source']
3257 3257
3258 3258 try: # User namespace
3259 3259 codeobj = eval(target, self.user_ns)
3260 3260 except Exception:
3261 3261 raise ValueError(("'%s' was not found in history, as a file, url, "
3262 3262 "nor in the user namespace.") % target)
3263 3263
3264 3264 if isinstance(codeobj, str):
3265 3265 return codeobj
3266 3266 elif isinstance(codeobj, Macro):
3267 3267 return codeobj.value
3268 3268
3269 3269 raise TypeError("%s is neither a string nor a macro." % target,
3270 3270 codeobj)
3271 3271
3272 3272 #-------------------------------------------------------------------------
3273 3273 # Things related to IPython exiting
3274 3274 #-------------------------------------------------------------------------
3275 3275 def atexit_operations(self):
3276 3276 """This will be executed at the time of exit.
3277 3277
3278 3278 Cleanup operations and saving of persistent data that is done
3279 3279 unconditionally by IPython should be performed here.
3280 3280
3281 3281 For things that may depend on startup flags or platform specifics (such
3282 3282 as having readline or not), register a separate atexit function in the
3283 3283 code that has the appropriate information, rather than trying to
3284 3284 clutter
3285 3285 """
3286 3286 # Close the history session (this stores the end time and line count)
3287 3287 # this must be *before* the tempfile cleanup, in case of temporary
3288 3288 # history db
3289 3289 self.history_manager.end_session()
3290 3290
3291 3291 # Cleanup all tempfiles and folders left around
3292 3292 for tfile in self.tempfiles:
3293 3293 try:
3294 3294 os.unlink(tfile)
3295 3295 except OSError:
3296 3296 pass
3297 3297
3298 3298 for tdir in self.tempdirs:
3299 3299 try:
3300 3300 os.rmdir(tdir)
3301 3301 except OSError:
3302 3302 pass
3303 3303
3304 3304 # Clear all user namespaces to release all references cleanly.
3305 3305 self.reset(new_session=False)
3306 3306
3307 3307 # Run user hooks
3308 3308 self.hooks.shutdown_hook()
3309 3309
3310 3310 def cleanup(self):
3311 3311 self.restore_sys_module_state()
3312 3312
3313 3313
3314 3314 # Overridden in terminal subclass to change prompts
3315 3315 def switch_doctest_mode(self, mode):
3316 3316 pass
3317 3317
3318 3318
3319 3319 class InteractiveShellABC(metaclass=abc.ABCMeta):
3320 3320 """An abstract base class for InteractiveShell."""
3321 3321
3322 3322 InteractiveShellABC.register(InteractiveShell)
@@ -1,614 +1,614 b''
1 1 """Implementation of basic magic functions."""
2 2
3 3
4 4 import argparse
5 5 import textwrap
6 6 import io
7 7 import sys
8 8 from pprint import pformat
9 9
10 10 from IPython.core import magic_arguments, page
11 11 from IPython.core.error import UsageError
12 12 from IPython.core.magic import Magics, magics_class, line_magic, magic_escapes
13 13 from IPython.utils.text import format_screen, dedent, indent
14 14 from IPython.testing.skipdoctest import skip_doctest
15 15 from IPython.utils.ipstruct import Struct
16 16 from warnings import warn
17 17 from logging import error
18 18
19 19
20 20 class MagicsDisplay(object):
21 21 def __init__(self, magics_manager, ignore=None):
22 22 self.ignore = ignore if ignore else []
23 23 self.magics_manager = magics_manager
24 24
25 25 def _lsmagic(self):
26 26 """The main implementation of the %lsmagic"""
27 27 mesc = magic_escapes['line']
28 28 cesc = magic_escapes['cell']
29 29 mman = self.magics_manager
30 30 magics = mman.lsmagic()
31 31 out = ['Available line magics:',
32 32 mesc + (' '+mesc).join(sorted([m for m,v in magics['line'].items() if (v not in self.ignore)])),
33 33 '',
34 34 'Available cell magics:',
35 35 cesc + (' '+cesc).join(sorted([m for m,v in magics['cell'].items() if (v not in self.ignore)])),
36 36 '',
37 37 mman.auto_status()]
38 38 return '\n'.join(out)
39 39
40 40 def _repr_pretty_(self, p, cycle):
41 41 p.text(self._lsmagic())
42 42
43 43 def __str__(self):
44 44 return self._lsmagic()
45 45
46 46 def _jsonable(self):
47 47 """turn magics dict into jsonable dict of the same structure
48 48
49 49 replaces object instances with their class names as strings
50 50 """
51 51 magic_dict = {}
52 52 mman = self.magics_manager
53 53 magics = mman.lsmagic()
54 54 for key, subdict in magics.items():
55 55 d = {}
56 56 magic_dict[key] = d
57 57 for name, obj in subdict.items():
58 58 try:
59 59 classname = obj.__self__.__class__.__name__
60 60 except AttributeError:
61 61 classname = 'Other'
62 62
63 63 d[name] = classname
64 64 return magic_dict
65 65
66 66 def _repr_json_(self):
67 67 return self._jsonable()
68 68
69 69
70 70 @magics_class
71 71 class BasicMagics(Magics):
72 72 """Magics that provide central IPython functionality.
73 73
74 74 These are various magics that don't fit into specific categories but that
75 75 are all part of the base 'IPython experience'."""
76 76
77 77 @magic_arguments.magic_arguments()
78 78 @magic_arguments.argument(
79 79 '-l', '--line', action='store_true',
80 80 help="""Create a line magic alias."""
81 81 )
82 82 @magic_arguments.argument(
83 83 '-c', '--cell', action='store_true',
84 84 help="""Create a cell magic alias."""
85 85 )
86 86 @magic_arguments.argument(
87 87 'name',
88 88 help="""Name of the magic to be created."""
89 89 )
90 90 @magic_arguments.argument(
91 91 'target',
92 92 help="""Name of the existing line or cell magic."""
93 93 )
94 94 @magic_arguments.argument(
95 95 '-p', '--params', default=None,
96 96 help="""Parameters passed to the magic function."""
97 97 )
98 98 @line_magic
99 99 def alias_magic(self, line=''):
100 100 """Create an alias for an existing line or cell magic.
101 101
102 102 Examples
103 103 --------
104 104 ::
105 105
106 106 In [1]: %alias_magic t timeit
107 107 Created `%t` as an alias for `%timeit`.
108 108 Created `%%t` as an alias for `%%timeit`.
109 109
110 110 In [2]: %t -n1 pass
111 111 1 loops, best of 3: 954 ns per loop
112 112
113 113 In [3]: %%t -n1
114 114 ...: pass
115 115 ...:
116 116 1 loops, best of 3: 954 ns per loop
117 117
118 118 In [4]: %alias_magic --cell whereami pwd
119 119 UsageError: Cell magic function `%%pwd` not found.
120 120 In [5]: %alias_magic --line whereami pwd
121 121 Created `%whereami` as an alias for `%pwd`.
122 122
123 123 In [6]: %whereami
124 124 Out[6]: u'/home/testuser'
125 125
126 126 In [7]: %alias_magic h history -p "-l 30" --line
127 127 Created `%h` as an alias for `%history -l 30`.
128 128 """
129 129
130 130 args = magic_arguments.parse_argstring(self.alias_magic, line)
131 131 shell = self.shell
132 132 mman = self.shell.magics_manager
133 133 escs = ''.join(magic_escapes.values())
134 134
135 135 target = args.target.lstrip(escs)
136 136 name = args.name.lstrip(escs)
137 137
138 138 params = args.params
139 139 if (params and
140 140 ((params.startswith('"') and params.endswith('"'))
141 141 or (params.startswith("'") and params.endswith("'")))):
142 142 params = params[1:-1]
143 143
144 144 # Find the requested magics.
145 145 m_line = shell.find_magic(target, 'line')
146 146 m_cell = shell.find_magic(target, 'cell')
147 147 if args.line and m_line is None:
148 148 raise UsageError('Line magic function `%s%s` not found.' %
149 149 (magic_escapes['line'], target))
150 150 if args.cell and m_cell is None:
151 151 raise UsageError('Cell magic function `%s%s` not found.' %
152 152 (magic_escapes['cell'], target))
153 153
154 154 # If --line and --cell are not specified, default to the ones
155 155 # that are available.
156 156 if not args.line and not args.cell:
157 157 if not m_line and not m_cell:
158 158 raise UsageError(
159 159 'No line or cell magic with name `%s` found.' % target
160 160 )
161 161 args.line = bool(m_line)
162 162 args.cell = bool(m_cell)
163 163
164 164 params_str = "" if params is None else " " + params
165 165
166 166 if args.line:
167 167 mman.register_alias(name, target, 'line', params)
168 168 print('Created `%s%s` as an alias for `%s%s%s`.' % (
169 169 magic_escapes['line'], name,
170 170 magic_escapes['line'], target, params_str))
171 171
172 172 if args.cell:
173 173 mman.register_alias(name, target, 'cell', params)
174 174 print('Created `%s%s` as an alias for `%s%s%s`.' % (
175 175 magic_escapes['cell'], name,
176 176 magic_escapes['cell'], target, params_str))
177 177
178 178 @line_magic
179 179 def lsmagic(self, parameter_s=''):
180 180 """List currently available magic functions."""
181 181 return MagicsDisplay(self.shell.magics_manager, ignore=[self.pip])
182 182
183 183 def _magic_docs(self, brief=False, rest=False):
184 184 """Return docstrings from magic functions."""
185 185 mman = self.shell.magics_manager
186 186 docs = mman.lsmagic_docs(brief, missing='No documentation')
187 187
188 188 if rest:
189 189 format_string = '**%s%s**::\n\n%s\n\n'
190 190 else:
191 191 format_string = '%s%s:\n%s\n'
192 192
193 193 return ''.join(
194 194 [format_string % (magic_escapes['line'], fname,
195 195 indent(dedent(fndoc)))
196 196 for fname, fndoc in sorted(docs['line'].items())]
197 197 +
198 198 [format_string % (magic_escapes['cell'], fname,
199 199 indent(dedent(fndoc)))
200 200 for fname, fndoc in sorted(docs['cell'].items())]
201 201 )
202 202
203 203 @line_magic
204 204 def magic(self, parameter_s=''):
205 205 """Print information about the magic function system.
206 206
207 207 Supported formats: -latex, -brief, -rest
208 208 """
209 209
210 210 mode = ''
211 211 try:
212 212 mode = parameter_s.split()[0][1:]
213 213 except IndexError:
214 214 pass
215 215
216 216 brief = (mode == 'brief')
217 217 rest = (mode == 'rest')
218 218 magic_docs = self._magic_docs(brief, rest)
219 219
220 220 if mode == 'latex':
221 221 print(self.format_latex(magic_docs))
222 222 return
223 223 else:
224 224 magic_docs = format_screen(magic_docs)
225 225
226 226 out = ["""
227 227 IPython's 'magic' functions
228 228 ===========================
229 229
230 230 The magic function system provides a series of functions which allow you to
231 231 control the behavior of IPython itself, plus a lot of system-type
232 232 features. There are two kinds of magics, line-oriented and cell-oriented.
233 233
234 234 Line magics are prefixed with the % character and work much like OS
235 235 command-line calls: they get as an argument the rest of the line, where
236 236 arguments are passed without parentheses or quotes. For example, this will
237 237 time the given statement::
238 238
239 239 %timeit range(1000)
240 240
241 241 Cell magics are prefixed with a double %%, and they are functions that get as
242 242 an argument not only the rest of the line, but also the lines below it in a
243 243 separate argument. These magics are called with two arguments: the rest of the
244 244 call line and the body of the cell, consisting of the lines below the first.
245 245 For example::
246 246
247 247 %%timeit x = numpy.random.randn((100, 100))
248 248 numpy.linalg.svd(x)
249 249
250 250 will time the execution of the numpy svd routine, running the assignment of x
251 251 as part of the setup phase, which is not timed.
252 252
253 253 In a line-oriented client (the terminal or Qt console IPython), starting a new
254 254 input with %% will automatically enter cell mode, and IPython will continue
255 255 reading input until a blank line is given. In the notebook, simply type the
256 256 whole cell as one entity, but keep in mind that the %% escape can only be at
257 257 the very start of the cell.
258 258
259 259 NOTE: If you have 'automagic' enabled (via the command line option or with the
260 260 %automagic function), you don't need to type in the % explicitly for line
261 261 magics; cell magics always require an explicit '%%' escape. By default,
262 262 IPython ships with automagic on, so you should only rarely need the % escape.
263 263
264 264 Example: typing '%cd mydir' (without the quotes) changes your working directory
265 265 to 'mydir', if it exists.
266 266
267 267 For a list of the available magic functions, use %lsmagic. For a description
268 268 of any of them, type %magic_name?, e.g. '%cd?'.
269 269
270 270 Currently the magic system has the following functions:""",
271 271 magic_docs,
272 272 "Summary of magic functions (from %slsmagic):" % magic_escapes['line'],
273 273 str(self.lsmagic()),
274 274 ]
275 275 page.page('\n'.join(out))
276 276
277 277
278 278 @line_magic
279 279 def page(self, parameter_s=''):
280 280 """Pretty print the object and display it through a pager.
281 281
282 282 %page [options] OBJECT
283 283
284 284 If no object is given, use _ (last output).
285 285
286 286 Options:
287 287
288 288 -r: page str(object), don't pretty-print it."""
289 289
290 290 # After a function contributed by Olivier Aubert, slightly modified.
291 291
292 292 # Process options/args
293 293 opts, args = self.parse_options(parameter_s, 'r')
294 294 raw = 'r' in opts
295 295
296 296 oname = args and args or '_'
297 297 info = self.shell._ofind(oname)
298 298 if info['found']:
299 299 txt = (raw and str or pformat)( info['obj'] )
300 300 page.page(txt)
301 301 else:
302 302 print('Object `%s` not found' % oname)
303 303
304 304 @line_magic
305 305 def profile(self, parameter_s=''):
306 306 """DEPRECATED since IPython 2.0.
307 307
308 308 Raise `UsageError`. To profile code use the :magic:`prun` magic.
309 309
310 310
311 311 See Also
312 312 --------
313 313 prun : run code using the Python profiler (:magic:`prun`)
314 314 """
315 315 raise UsageError("The `%profile` magic has been deprecated since IPython 2.0. "
316 316 "and removed in IPython 6.0. Please use the value of `get_ipython().profile` instead "
317 317 "to see current profile in use. Perhaps you meant to use `%prun` to profile code?")
318 318
319 319 @line_magic
320 320 def pprint(self, parameter_s=''):
321 321 """Toggle pretty printing on/off."""
322 322 ptformatter = self.shell.display_formatter.formatters['text/plain']
323 323 ptformatter.pprint = bool(1 - ptformatter.pprint)
324 324 print('Pretty printing has been turned',
325 325 ['OFF','ON'][ptformatter.pprint])
326 326
327 327 @line_magic
328 328 def colors(self, parameter_s=''):
329 329 """Switch color scheme for prompts, info system and exception handlers.
330 330
331 331 Currently implemented schemes: NoColor, Linux, LightBG.
332 332
333 333 Color scheme names are not case-sensitive.
334 334
335 335 Examples
336 336 --------
337 337 To get a plain black and white terminal::
338 338
339 339 %colors nocolor
340 340 """
341 341 def color_switch_err(name):
342 342 warn('Error changing %s color schemes.\n%s' %
343 343 (name, sys.exc_info()[1]), stacklevel=2)
344 344
345 345
346 346 new_scheme = parameter_s.strip()
347 347 if not new_scheme:
348 348 raise UsageError(
349 349 "%colors: you must specify a color scheme. See '%colors?'")
350 350 # local shortcut
351 351 shell = self.shell
352 352
353 353 # Set shell colour scheme
354 354 try:
355 355 shell.colors = new_scheme
356 356 shell.refresh_style()
357 357 except:
358 358 color_switch_err('shell')
359 359
360 360 # Set exception colors
361 361 try:
362 362 shell.InteractiveTB.set_colors(scheme = new_scheme)
363 363 shell.SyntaxTB.set_colors(scheme = new_scheme)
364 364 except:
365 365 color_switch_err('exception')
366 366
367 367 # Set info (for 'object?') colors
368 368 if shell.color_info:
369 369 try:
370 370 shell.inspector.set_active_scheme(new_scheme)
371 371 except:
372 372 color_switch_err('object inspector')
373 373 else:
374 374 shell.inspector.set_active_scheme('NoColor')
375 375
376 376 @line_magic
377 377 def xmode(self, parameter_s=''):
378 378 """Switch modes for the exception handlers.
379 379
380 380 Valid modes: Plain, Context and Verbose.
381 381
382 382 If called without arguments, acts as a toggle."""
383 383
384 384 def xmode_switch_err(name):
385 385 warn('Error changing %s exception modes.\n%s' %
386 386 (name,sys.exc_info()[1]))
387 387
388 388 shell = self.shell
389 389 new_mode = parameter_s.strip().capitalize()
390 390 try:
391 391 shell.InteractiveTB.set_mode(mode=new_mode)
392 392 print('Exception reporting mode:',shell.InteractiveTB.mode)
393 393 except:
394 394 xmode_switch_err('user')
395 395
396 396 @line_magic
397 397 def pip(self, args=''):
398 398 """
399 399 Intercept usage of ``pip`` in IPython and direct user to run command outside of IPython.
400 400 """
401 401 print(textwrap.dedent('''
402 402 The following command must be run outside of the IPython shell:
403 403
404 404 $ pip {args}
405 405
406 406 The Python package manager (pip) can only be used from outside of IPython.
407 407 Please reissue the `pip` command in a separate terminal or command prompt.
408 408
409 See the Python documentation for more informations on how to install packages:
409 See the Python documentation for more information on how to install packages:
410 410
411 411 https://docs.python.org/3/installing/'''.format(args=args)))
412 412
413 413 @line_magic
414 414 def quickref(self, arg):
415 415 """ Show a quick reference sheet """
416 416 from IPython.core.usage import quick_reference
417 417 qr = quick_reference + self._magic_docs(brief=True)
418 418 page.page(qr)
419 419
420 420 @line_magic
421 421 def doctest_mode(self, parameter_s=''):
422 422 """Toggle doctest mode on and off.
423 423
424 424 This mode is intended to make IPython behave as much as possible like a
425 425 plain Python shell, from the perspective of how its prompts, exceptions
426 426 and output look. This makes it easy to copy and paste parts of a
427 427 session into doctests. It does so by:
428 428
429 429 - Changing the prompts to the classic ``>>>`` ones.
430 430 - Changing the exception reporting mode to 'Plain'.
431 431 - Disabling pretty-printing of output.
432 432
433 433 Note that IPython also supports the pasting of code snippets that have
434 434 leading '>>>' and '...' prompts in them. This means that you can paste
435 435 doctests from files or docstrings (even if they have leading
436 436 whitespace), and the code will execute correctly. You can then use
437 437 '%history -t' to see the translated history; this will give you the
438 438 input after removal of all the leading prompts and whitespace, which
439 439 can be pasted back into an editor.
440 440
441 441 With these features, you can switch into this mode easily whenever you
442 442 need to do testing and changes to doctests, without having to leave
443 443 your existing IPython session.
444 444 """
445 445
446 446 # Shorthands
447 447 shell = self.shell
448 448 meta = shell.meta
449 449 disp_formatter = self.shell.display_formatter
450 450 ptformatter = disp_formatter.formatters['text/plain']
451 451 # dstore is a data store kept in the instance metadata bag to track any
452 452 # changes we make, so we can undo them later.
453 453 dstore = meta.setdefault('doctest_mode',Struct())
454 454 save_dstore = dstore.setdefault
455 455
456 456 # save a few values we'll need to recover later
457 457 mode = save_dstore('mode',False)
458 458 save_dstore('rc_pprint',ptformatter.pprint)
459 459 save_dstore('xmode',shell.InteractiveTB.mode)
460 460 save_dstore('rc_separate_out',shell.separate_out)
461 461 save_dstore('rc_separate_out2',shell.separate_out2)
462 462 save_dstore('rc_separate_in',shell.separate_in)
463 463 save_dstore('rc_active_types',disp_formatter.active_types)
464 464
465 465 if not mode:
466 466 # turn on
467 467
468 468 # Prompt separators like plain python
469 469 shell.separate_in = ''
470 470 shell.separate_out = ''
471 471 shell.separate_out2 = ''
472 472
473 473
474 474 ptformatter.pprint = False
475 475 disp_formatter.active_types = ['text/plain']
476 476
477 477 shell.magic('xmode Plain')
478 478 else:
479 479 # turn off
480 480 shell.separate_in = dstore.rc_separate_in
481 481
482 482 shell.separate_out = dstore.rc_separate_out
483 483 shell.separate_out2 = dstore.rc_separate_out2
484 484
485 485 ptformatter.pprint = dstore.rc_pprint
486 486 disp_formatter.active_types = dstore.rc_active_types
487 487
488 488 shell.magic('xmode ' + dstore.xmode)
489 489
490 490 # mode here is the state before we switch; switch_doctest_mode takes
491 491 # the mode we're switching to.
492 492 shell.switch_doctest_mode(not mode)
493 493
494 494 # Store new mode and inform
495 495 dstore.mode = bool(not mode)
496 496 mode_label = ['OFF','ON'][dstore.mode]
497 497 print('Doctest mode is:', mode_label)
498 498
499 499 @line_magic
500 500 def gui(self, parameter_s=''):
501 501 """Enable or disable IPython GUI event loop integration.
502 502
503 503 %gui [GUINAME]
504 504
505 505 This magic replaces IPython's threaded shells that were activated
506 506 using the (pylab/wthread/etc.) command line flags. GUI toolkits
507 507 can now be enabled at runtime and keyboard
508 508 interrupts should work without any problems. The following toolkits
509 509 are supported: wxPython, PyQt4, PyGTK, Tk and Cocoa (OSX)::
510 510
511 511 %gui wx # enable wxPython event loop integration
512 512 %gui qt4|qt # enable PyQt4 event loop integration
513 513 %gui qt5 # enable PyQt5 event loop integration
514 514 %gui gtk # enable PyGTK event loop integration
515 515 %gui gtk3 # enable Gtk3 event loop integration
516 516 %gui tk # enable Tk event loop integration
517 517 %gui osx # enable Cocoa event loop integration
518 518 # (requires %matplotlib 1.1)
519 519 %gui # disable all event loop integration
520 520
521 521 WARNING: after any of these has been called you can simply create
522 522 an application object, but DO NOT start the event loop yourself, as
523 523 we have already handled that.
524 524 """
525 525 opts, arg = self.parse_options(parameter_s, '')
526 526 if arg=='': arg = None
527 527 try:
528 528 return self.shell.enable_gui(arg)
529 529 except Exception as e:
530 530 # print simple error message, rather than traceback if we can't
531 531 # hook up the GUI
532 532 error(str(e))
533 533
534 534 @skip_doctest
535 535 @line_magic
536 536 def precision(self, s=''):
537 537 """Set floating point precision for pretty printing.
538 538
539 539 Can set either integer precision or a format string.
540 540
541 541 If numpy has been imported and precision is an int,
542 542 numpy display precision will also be set, via ``numpy.set_printoptions``.
543 543
544 544 If no argument is given, defaults will be restored.
545 545
546 546 Examples
547 547 --------
548 548 ::
549 549
550 550 In [1]: from math import pi
551 551
552 552 In [2]: %precision 3
553 553 Out[2]: u'%.3f'
554 554
555 555 In [3]: pi
556 556 Out[3]: 3.142
557 557
558 558 In [4]: %precision %i
559 559 Out[4]: u'%i'
560 560
561 561 In [5]: pi
562 562 Out[5]: 3
563 563
564 564 In [6]: %precision %e
565 565 Out[6]: u'%e'
566 566
567 567 In [7]: pi**10
568 568 Out[7]: 9.364805e+04
569 569
570 570 In [8]: %precision
571 571 Out[8]: u'%r'
572 572
573 573 In [9]: pi**10
574 574 Out[9]: 93648.047476082982
575 575 """
576 576 ptformatter = self.shell.display_formatter.formatters['text/plain']
577 577 ptformatter.float_precision = s
578 578 return ptformatter.float_format
579 579
580 580 @magic_arguments.magic_arguments()
581 581 @magic_arguments.argument(
582 582 '-e', '--export', action='store_true', default=False,
583 583 help=argparse.SUPPRESS
584 584 )
585 585 @magic_arguments.argument(
586 586 'filename', type=str,
587 587 help='Notebook name or filename'
588 588 )
589 589 @line_magic
590 590 def notebook(self, s):
591 591 """Export and convert IPython notebooks.
592 592
593 593 This function can export the current IPython history to a notebook file.
594 594 For example, to export the history to "foo.ipynb" do "%notebook foo.ipynb".
595 595
596 596 The -e or --export flag is deprecated in IPython 5.2, and will be
597 597 removed in the future.
598 598 """
599 599 args = magic_arguments.parse_argstring(self.notebook, s)
600 600
601 601 from nbformat import write, v4
602 602
603 603 cells = []
604 604 hist = list(self.shell.history_manager.get_range())
605 605 if(len(hist)<=1):
606 606 raise ValueError('History is empty, cannot export')
607 607 for session, execution_count, source in hist[:-1]:
608 608 cells.append(v4.new_code_cell(
609 609 execution_count=execution_count,
610 610 source=source
611 611 ))
612 612 nb = v4.new_notebook(cells=cells)
613 613 with io.open(args.filename, 'w', encoding='utf-8') as f:
614 614 write(nb, f, version=4)
@@ -1,740 +1,740 b''
1 1 """Implementation of code management magic functions.
2 2 """
3 3 #-----------------------------------------------------------------------------
4 4 # Copyright (c) 2012 The IPython Development Team.
5 5 #
6 6 # Distributed under the terms of the Modified BSD License.
7 7 #
8 8 # The full license is in the file COPYING.txt, distributed with this software.
9 9 #-----------------------------------------------------------------------------
10 10
11 11 #-----------------------------------------------------------------------------
12 12 # Imports
13 13 #-----------------------------------------------------------------------------
14 14
15 15 # Stdlib
16 16 import inspect
17 17 import io
18 18 import os
19 19 import re
20 20 import sys
21 21 import ast
22 22 from itertools import chain
23 23
24 24 # Our own packages
25 25 from IPython.core.error import TryNext, StdinNotImplementedError, UsageError
26 26 from IPython.core.macro import Macro
27 27 from IPython.core.magic import Magics, magics_class, line_magic
28 28 from IPython.core.oinspect import find_file, find_source_lines
29 29 from IPython.testing.skipdoctest import skip_doctest
30 30 from IPython.utils import py3compat
31 31 from IPython.utils.contexts import preserve_keys
32 32 from IPython.utils.path import get_py_filename
33 33 from warnings import warn
34 34 from logging import error
35 35 from IPython.utils.text import get_text_list
36 36
37 37 #-----------------------------------------------------------------------------
38 38 # Magic implementation classes
39 39 #-----------------------------------------------------------------------------
40 40
41 41 # Used for exception handling in magic_edit
42 42 class MacroToEdit(ValueError): pass
43 43
44 44 ipython_input_pat = re.compile(r"<ipython\-input\-(\d+)-[a-z\d]+>$")
45 45
46 46 # To match, e.g. 8-10 1:5 :10 3-
47 47 range_re = re.compile(r"""
48 48 (?P<start>\d+)?
49 49 ((?P<sep>[\-:])
50 50 (?P<end>\d+)?)?
51 51 $""", re.VERBOSE)
52 52
53 53
54 54 def extract_code_ranges(ranges_str):
55 55 """Turn a string of range for %%load into 2-tuples of (start, stop)
56 56 ready to use as a slice of the content splitted by lines.
57 57
58 58 Examples
59 59 --------
60 60 list(extract_input_ranges("5-10 2"))
61 61 [(4, 10), (1, 2)]
62 62 """
63 63 for range_str in ranges_str.split():
64 64 rmatch = range_re.match(range_str)
65 65 if not rmatch:
66 66 continue
67 67 sep = rmatch.group("sep")
68 68 start = rmatch.group("start")
69 69 end = rmatch.group("end")
70 70
71 71 if sep == '-':
72 72 start = int(start) - 1 if start else None
73 73 end = int(end) if end else None
74 74 elif sep == ':':
75 75 start = int(start) - 1 if start else None
76 76 end = int(end) - 1 if end else None
77 77 else:
78 78 end = int(start)
79 79 start = int(start) - 1
80 80 yield (start, end)
81 81
82 82
83 83 def extract_symbols(code, symbols):
84 84 """
85 85 Return a tuple (blocks, not_found)
86 86 where ``blocks`` is a list of code fragments
87 87 for each symbol parsed from code, and ``not_found`` are
88 88 symbols not found in the code.
89 89
90 90 For example::
91 91
92 92 In [1]: code = '''a = 10
93 93 ...: def b(): return 42
94 94 ...: class A: pass'''
95 95
96 96 In [2]: extract_symbols(code, 'A,b,z')
97 97 Out[2]: (['class A: pass\\n', 'def b(): return 42\\n'], ['z'])
98 98 """
99 99 symbols = symbols.split(',')
100 100
101 101 # this will raise SyntaxError if code isn't valid Python
102 102 py_code = ast.parse(code)
103 103
104 104 marks = [(getattr(s, 'name', None), s.lineno) for s in py_code.body]
105 105 code = code.split('\n')
106 106
107 107 symbols_lines = {}
108 108
109 109 # we already know the start_lineno of each symbol (marks).
110 110 # To find each end_lineno, we traverse in reverse order until each
111 111 # non-blank line
112 112 end = len(code)
113 113 for name, start in reversed(marks):
114 114 while not code[end - 1].strip():
115 115 end -= 1
116 116 if name:
117 117 symbols_lines[name] = (start - 1, end)
118 118 end = start - 1
119 119
120 120 # Now symbols_lines is a map
121 121 # {'symbol_name': (start_lineno, end_lineno), ...}
122 122
123 123 # fill a list with chunks of codes for each requested symbol
124 124 blocks = []
125 125 not_found = []
126 126 for symbol in symbols:
127 127 if symbol in symbols_lines:
128 128 start, end = symbols_lines[symbol]
129 129 blocks.append('\n'.join(code[start:end]) + '\n')
130 130 else:
131 131 not_found.append(symbol)
132 132
133 133 return blocks, not_found
134 134
135 135 def strip_initial_indent(lines):
136 136 """For %load, strip indent from lines until finding an unindented line.
137 137
138 138 https://github.com/ipython/ipython/issues/9775
139 139 """
140 140 indent_re = re.compile(r'\s+')
141 141
142 142 it = iter(lines)
143 143 first_line = next(it)
144 144 indent_match = indent_re.match(first_line)
145 145
146 146 if indent_match:
147 147 # First line was indented
148 148 indent = indent_match.group()
149 149 yield first_line[len(indent):]
150 150
151 151 for line in it:
152 152 if line.startswith(indent):
153 153 yield line[len(indent):]
154 154 else:
155 155 # Less indented than the first line - stop dedenting
156 156 yield line
157 157 break
158 158 else:
159 159 yield first_line
160 160
161 161 # Pass the remaining lines through without dedenting
162 162 for line in it:
163 163 yield line
164 164
165 165
166 166 class InteractivelyDefined(Exception):
167 167 """Exception for interactively defined variable in magic_edit"""
168 168 def __init__(self, index):
169 169 self.index = index
170 170
171 171
172 172 @magics_class
173 173 class CodeMagics(Magics):
174 174 """Magics related to code management (loading, saving, editing, ...)."""
175 175
176 176 def __init__(self, *args, **kwargs):
177 177 self._knowntemps = set()
178 178 super(CodeMagics, self).__init__(*args, **kwargs)
179 179
180 180 @line_magic
181 181 def save(self, parameter_s=''):
182 182 """Save a set of lines or a macro to a given filename.
183 183
184 184 Usage:\\
185 185 %save [options] filename n1-n2 n3-n4 ... n5 .. n6 ...
186 186
187 187 Options:
188 188
189 189 -r: use 'raw' input. By default, the 'processed' history is used,
190 190 so that magics are loaded in their transformed version to valid
191 191 Python. If this option is given, the raw input as typed as the
192 192 command line is used instead.
193 193
194 194 -f: force overwrite. If file exists, %save will prompt for overwrite
195 195 unless -f is given.
196 196
197 197 -a: append to the file instead of overwriting it.
198 198
199 199 This function uses the same syntax as %history for input ranges,
200 200 then saves the lines to the filename you specify.
201 201
202 202 It adds a '.py' extension to the file if you don't do so yourself, and
203 203 it asks for confirmation before overwriting existing files.
204 204
205 205 If `-r` option is used, the default extension is `.ipy`.
206 206 """
207 207
208 208 opts,args = self.parse_options(parameter_s,'fra',mode='list')
209 209 if not args:
210 210 raise UsageError('Missing filename.')
211 211 raw = 'r' in opts
212 212 force = 'f' in opts
213 213 append = 'a' in opts
214 214 mode = 'a' if append else 'w'
215 215 ext = u'.ipy' if raw else u'.py'
216 216 fname, codefrom = args[0], " ".join(args[1:])
217 217 if not fname.endswith((u'.py',u'.ipy')):
218 218 fname += ext
219 219 file_exists = os.path.isfile(fname)
220 220 if file_exists and not force and not append:
221 221 try:
222 222 overwrite = self.shell.ask_yes_no('File `%s` exists. Overwrite (y/[N])? ' % fname, default='n')
223 223 except StdinNotImplementedError:
224 224 print("File `%s` exists. Use `%%save -f %s` to force overwrite" % (fname, parameter_s))
225 225 return
226 226 if not overwrite :
227 227 print('Operation cancelled.')
228 228 return
229 229 try:
230 230 cmds = self.shell.find_user_code(codefrom,raw)
231 231 except (TypeError, ValueError) as e:
232 232 print(e.args[0])
233 233 return
234 234 out = py3compat.cast_unicode(cmds)
235 235 with io.open(fname, mode, encoding="utf-8") as f:
236 236 if not file_exists or not append:
237 237 f.write(u"# coding: utf-8\n")
238 238 f.write(out)
239 239 # make sure we end on a newline
240 240 if not out.endswith(u'\n'):
241 241 f.write(u'\n')
242 242 print('The following commands were written to file `%s`:' % fname)
243 243 print(cmds)
244 244
245 245 @line_magic
246 246 def pastebin(self, parameter_s=''):
247 247 """Upload code to Github's Gist paste bin, returning the URL.
248 248
249 249 Usage:\\
250 250 %pastebin [-d "Custom description"] 1-7
251 251
252 252 The argument can be an input history range, a filename, or the name of a
253 253 string or macro.
254 254
255 255 Options:
256 256
257 257 -d: Pass a custom description for the gist. The default will say
258 258 "Pasted from IPython".
259 259 """
260 260 opts, args = self.parse_options(parameter_s, 'd:')
261 261
262 262 try:
263 263 code = self.shell.find_user_code(args)
264 264 except (ValueError, TypeError) as e:
265 265 print(e.args[0])
266 266 return
267 267
268 268 # Deferred import
269 269 try:
270 270 from urllib.request import urlopen # Py 3
271 271 except ImportError:
272 272 from urllib2 import urlopen
273 273 import json
274 274 post_data = json.dumps({
275 275 "description": opts.get('d', "Pasted from IPython"),
276 276 "public": True,
277 277 "files": {
278 278 "file1.py": {
279 279 "content": code
280 280 }
281 281 }
282 282 }).encode('utf-8')
283 283
284 284 response = urlopen("https://api.github.com/gists", post_data)
285 285 response_data = json.loads(response.read().decode('utf-8'))
286 286 return response_data['html_url']
287 287
288 288 @line_magic
289 289 def loadpy(self, arg_s):
290 290 """Alias of `%load`
291 291
292 292 `%loadpy` has gained some flexibility and dropped the requirement of a `.py`
293 293 extension. So it has been renamed simply into %load. You can look at
294 294 `%load`'s docstring for more info.
295 295 """
296 296 self.load(arg_s)
297 297
298 298 @line_magic
299 299 def load(self, arg_s):
300 300 """Load code into the current frontend.
301 301
302 302 Usage:\\
303 303 %load [options] source
304 304
305 305 where source can be a filename, URL, input history range, macro, or
306 306 element in the user namespace
307 307
308 308 Options:
309 309
310 310 -r <lines>: Specify lines or ranges of lines to load from the source.
311 311 Ranges could be specified as x-y (x..y) or in python-style x:y
312 312 (x..(y-1)). Both limits x and y can be left blank (meaning the
313 313 beginning and end of the file, respectively).
314 314
315 315 -s <symbols>: Specify function or classes to load from python source.
316 316
317 317 -y : Don't ask confirmation for loading source above 200 000 characters.
318 318
319 319 -n : Include the user's namespace when searching for source code.
320 320
321 321 This magic command can either take a local filename, a URL, an history
322 322 range (see %history) or a macro as argument, it will prompt for
323 323 confirmation before loading source with more than 200 000 characters, unless
324 324 -y flag is passed or if the frontend does not support raw_input::
325 325
326 326 %load myscript.py
327 327 %load 7-27
328 328 %load myMacro
329 329 %load http://www.example.com/myscript.py
330 330 %load -r 5-10 myscript.py
331 331 %load -r 10-20,30,40: foo.py
332 332 %load -s MyClass,wonder_function myscript.py
333 333 %load -n MyClass
334 334 %load -n my_module.wonder_function
335 335 """
336 336 opts,args = self.parse_options(arg_s,'yns:r:')
337 337
338 338 if not args:
339 339 raise UsageError('Missing filename, URL, input history range, '
340 340 'macro, or element in the user namespace.')
341 341
342 342 search_ns = 'n' in opts
343 343
344 344 contents = self.shell.find_user_code(args, search_ns=search_ns)
345 345
346 346 if 's' in opts:
347 347 try:
348 348 blocks, not_found = extract_symbols(contents, opts['s'])
349 349 except SyntaxError:
350 350 # non python code
351 351 error("Unable to parse the input as valid Python code")
352 352 return
353 353
354 354 if len(not_found) == 1:
355 355 warn('The symbol `%s` was not found' % not_found[0])
356 356 elif len(not_found) > 1:
357 357 warn('The symbols %s were not found' % get_text_list(not_found,
358 358 wrap_item_with='`')
359 359 )
360 360
361 361 contents = '\n'.join(blocks)
362 362
363 363 if 'r' in opts:
364 364 ranges = opts['r'].replace(',', ' ')
365 365 lines = contents.split('\n')
366 366 slices = extract_code_ranges(ranges)
367 367 contents = [lines[slice(*slc)] for slc in slices]
368 368 contents = '\n'.join(strip_initial_indent(chain.from_iterable(contents)))
369 369
370 370 l = len(contents)
371 371
372 # 200 000 is ~ 2500 full 80 caracter lines
372 # 200 000 is ~ 2500 full 80 character lines
373 373 # so in average, more than 5000 lines
374 374 if l > 200000 and 'y' not in opts:
375 375 try:
376 376 ans = self.shell.ask_yes_no(("The text you're trying to load seems pretty big"\
377 377 " (%d characters). Continue (y/[N]) ?" % l), default='n' )
378 378 except StdinNotImplementedError:
379 #asume yes if raw input not implemented
379 #assume yes if raw input not implemented
380 380 ans = True
381 381
382 382 if ans is False :
383 383 print('Operation cancelled.')
384 384 return
385 385
386 386 contents = "# %load {}\n".format(arg_s) + contents
387 387
388 388 self.shell.set_next_input(contents, replace=True)
389 389
390 390 @staticmethod
391 391 def _find_edit_target(shell, args, opts, last_call):
392 392 """Utility method used by magic_edit to find what to edit."""
393 393
394 394 def make_filename(arg):
395 395 "Make a filename from the given args"
396 396 try:
397 397 filename = get_py_filename(arg)
398 398 except IOError:
399 399 # If it ends with .py but doesn't already exist, assume we want
400 400 # a new file.
401 401 if arg.endswith('.py'):
402 402 filename = arg
403 403 else:
404 404 filename = None
405 405 return filename
406 406
407 407 # Set a few locals from the options for convenience:
408 408 opts_prev = 'p' in opts
409 409 opts_raw = 'r' in opts
410 410
411 411 # custom exceptions
412 412 class DataIsObject(Exception): pass
413 413
414 414 # Default line number value
415 415 lineno = opts.get('n',None)
416 416
417 417 if opts_prev:
418 418 args = '_%s' % last_call[0]
419 419 if args not in shell.user_ns:
420 420 args = last_call[1]
421 421
422 422 # by default this is done with temp files, except when the given
423 423 # arg is a filename
424 424 use_temp = True
425 425
426 426 data = ''
427 427
428 428 # First, see if the arguments should be a filename.
429 429 filename = make_filename(args)
430 430 if filename:
431 431 use_temp = False
432 432 elif args:
433 433 # Mode where user specifies ranges of lines, like in %macro.
434 434 data = shell.extract_input_lines(args, opts_raw)
435 435 if not data:
436 436 try:
437 437 # Load the parameter given as a variable. If not a string,
438 438 # process it as an object instead (below)
439 439
440 440 #print '*** args',args,'type',type(args) # dbg
441 441 data = eval(args, shell.user_ns)
442 442 if not isinstance(data, str):
443 443 raise DataIsObject
444 444
445 445 except (NameError,SyntaxError):
446 446 # given argument is not a variable, try as a filename
447 447 filename = make_filename(args)
448 448 if filename is None:
449 449 warn("Argument given (%s) can't be found as a variable "
450 450 "or as a filename." % args)
451 451 return (None, None, None)
452 452 use_temp = False
453 453
454 454 except DataIsObject:
455 455 # macros have a special edit function
456 456 if isinstance(data, Macro):
457 457 raise MacroToEdit(data)
458 458
459 459 # For objects, try to edit the file where they are defined
460 460 filename = find_file(data)
461 461 if filename:
462 462 if 'fakemodule' in filename.lower() and \
463 463 inspect.isclass(data):
464 464 # class created by %edit? Try to find source
465 465 # by looking for method definitions instead, the
466 466 # __module__ in those classes is FakeModule.
467 467 attrs = [getattr(data, aname) for aname in dir(data)]
468 468 for attr in attrs:
469 469 if not inspect.ismethod(attr):
470 470 continue
471 471 filename = find_file(attr)
472 472 if filename and \
473 473 'fakemodule' not in filename.lower():
474 474 # change the attribute to be the edit
475 475 # target instead
476 476 data = attr
477 477 break
478 478
479 479 m = ipython_input_pat.match(os.path.basename(filename))
480 480 if m:
481 481 raise InteractivelyDefined(int(m.groups()[0]))
482 482
483 483 datafile = 1
484 484 if filename is None:
485 485 filename = make_filename(args)
486 486 datafile = 1
487 487 if filename is not None:
488 488 # only warn about this if we get a real name
489 489 warn('Could not find file where `%s` is defined.\n'
490 490 'Opening a file named `%s`' % (args, filename))
491 491 # Now, make sure we can actually read the source (if it was
492 492 # in a temp file it's gone by now).
493 493 if datafile:
494 494 if lineno is None:
495 495 lineno = find_source_lines(data)
496 496 if lineno is None:
497 497 filename = make_filename(args)
498 498 if filename is None:
499 499 warn('The file where `%s` was defined '
500 500 'cannot be read or found.' % data)
501 501 return (None, None, None)
502 502 use_temp = False
503 503
504 504 if use_temp:
505 505 filename = shell.mktempfile(data)
506 506 print('IPython will make a temporary file named:',filename)
507 507
508 508 # use last_call to remember the state of the previous call, but don't
509 509 # let it be clobbered by successive '-p' calls.
510 510 try:
511 511 last_call[0] = shell.displayhook.prompt_count
512 512 if not opts_prev:
513 513 last_call[1] = args
514 514 except:
515 515 pass
516 516
517 517
518 518 return filename, lineno, use_temp
519 519
520 520 def _edit_macro(self,mname,macro):
521 521 """open an editor with the macro data in a file"""
522 522 filename = self.shell.mktempfile(macro.value)
523 523 self.shell.hooks.editor(filename)
524 524
525 525 # and make a new macro object, to replace the old one
526 526 with open(filename) as mfile:
527 527 mvalue = mfile.read()
528 528 self.shell.user_ns[mname] = Macro(mvalue)
529 529
530 530 @skip_doctest
531 531 @line_magic
532 532 def edit(self, parameter_s='',last_call=['','']):
533 533 """Bring up an editor and execute the resulting code.
534 534
535 535 Usage:
536 536 %edit [options] [args]
537 537
538 538 %edit runs IPython's editor hook. The default version of this hook is
539 539 set to call the editor specified by your $EDITOR environment variable.
540 540 If this isn't found, it will default to vi under Linux/Unix and to
541 541 notepad under Windows. See the end of this docstring for how to change
542 542 the editor hook.
543 543
544 544 You can also set the value of this editor via the
545 545 ``TerminalInteractiveShell.editor`` option in your configuration file.
546 546 This is useful if you wish to use a different editor from your typical
547 547 default with IPython (and for Windows users who typically don't set
548 548 environment variables).
549 549
550 550 This command allows you to conveniently edit multi-line code right in
551 551 your IPython session.
552 552
553 553 If called without arguments, %edit opens up an empty editor with a
554 554 temporary file and will execute the contents of this file when you
555 555 close it (don't forget to save it!).
556 556
557 557
558 558 Options:
559 559
560 560 -n <number>: open the editor at a specified line number. By default,
561 561 the IPython editor hook uses the unix syntax 'editor +N filename', but
562 562 you can configure this by providing your own modified hook if your
563 563 favorite editor supports line-number specifications with a different
564 564 syntax.
565 565
566 566 -p: this will call the editor with the same data as the previous time
567 567 it was used, regardless of how long ago (in your current session) it
568 568 was.
569 569
570 570 -r: use 'raw' input. This option only applies to input taken from the
571 571 user's history. By default, the 'processed' history is used, so that
572 572 magics are loaded in their transformed version to valid Python. If
573 573 this option is given, the raw input as typed as the command line is
574 574 used instead. When you exit the editor, it will be executed by
575 575 IPython's own processor.
576 576
577 577 -x: do not execute the edited code immediately upon exit. This is
578 578 mainly useful if you are editing programs which need to be called with
579 579 command line arguments, which you can then do using %run.
580 580
581 581
582 582 Arguments:
583 583
584 584 If arguments are given, the following possibilities exist:
585 585
586 586 - If the argument is a filename, IPython will load that into the
587 587 editor. It will execute its contents with execfile() when you exit,
588 588 loading any code in the file into your interactive namespace.
589 589
590 590 - The arguments are ranges of input history, e.g. "7 ~1/4-6".
591 591 The syntax is the same as in the %history magic.
592 592
593 593 - If the argument is a string variable, its contents are loaded
594 594 into the editor. You can thus edit any string which contains
595 595 python code (including the result of previous edits).
596 596
597 597 - If the argument is the name of an object (other than a string),
598 598 IPython will try to locate the file where it was defined and open the
599 599 editor at the point where it is defined. You can use `%edit function`
600 600 to load an editor exactly at the point where 'function' is defined,
601 601 edit it and have the file be executed automatically.
602 602
603 603 - If the object is a macro (see %macro for details), this opens up your
604 604 specified editor with a temporary file containing the macro's data.
605 605 Upon exit, the macro is reloaded with the contents of the file.
606 606
607 607 Note: opening at an exact line is only supported under Unix, and some
608 608 editors (like kedit and gedit up to Gnome 2.8) do not understand the
609 609 '+NUMBER' parameter necessary for this feature. Good editors like
610 610 (X)Emacs, vi, jed, pico and joe all do.
611 611
612 612 After executing your code, %edit will return as output the code you
613 613 typed in the editor (except when it was an existing file). This way
614 614 you can reload the code in further invocations of %edit as a variable,
615 615 via _<NUMBER> or Out[<NUMBER>], where <NUMBER> is the prompt number of
616 616 the output.
617 617
618 618 Note that %edit is also available through the alias %ed.
619 619
620 620 This is an example of creating a simple function inside the editor and
621 621 then modifying it. First, start up the editor::
622 622
623 623 In [1]: edit
624 624 Editing... done. Executing edited code...
625 625 Out[1]: 'def foo():\\n print "foo() was defined in an editing
626 626 session"\\n'
627 627
628 628 We can then call the function foo()::
629 629
630 630 In [2]: foo()
631 631 foo() was defined in an editing session
632 632
633 633 Now we edit foo. IPython automatically loads the editor with the
634 634 (temporary) file where foo() was previously defined::
635 635
636 636 In [3]: edit foo
637 637 Editing... done. Executing edited code...
638 638
639 639 And if we call foo() again we get the modified version::
640 640
641 641 In [4]: foo()
642 642 foo() has now been changed!
643 643
644 644 Here is an example of how to edit a code snippet successive
645 645 times. First we call the editor::
646 646
647 647 In [5]: edit
648 648 Editing... done. Executing edited code...
649 649 hello
650 650 Out[5]: "print 'hello'\\n"
651 651
652 652 Now we call it again with the previous output (stored in _)::
653 653
654 654 In [6]: edit _
655 655 Editing... done. Executing edited code...
656 656 hello world
657 657 Out[6]: "print 'hello world'\\n"
658 658
659 659 Now we call it with the output #8 (stored in _8, also as Out[8])::
660 660
661 661 In [7]: edit _8
662 662 Editing... done. Executing edited code...
663 663 hello again
664 664 Out[7]: "print 'hello again'\\n"
665 665
666 666
667 667 Changing the default editor hook:
668 668
669 669 If you wish to write your own editor hook, you can put it in a
670 670 configuration file which you load at startup time. The default hook
671 671 is defined in the IPython.core.hooks module, and you can use that as a
672 672 starting example for further modifications. That file also has
673 673 general instructions on how to set a new hook for use once you've
674 674 defined it."""
675 675 opts,args = self.parse_options(parameter_s,'prxn:')
676 676
677 677 try:
678 678 filename, lineno, is_temp = self._find_edit_target(self.shell,
679 679 args, opts, last_call)
680 680 except MacroToEdit as e:
681 681 self._edit_macro(args, e.args[0])
682 682 return
683 683 except InteractivelyDefined as e:
684 684 print("Editing In[%i]" % e.index)
685 685 args = str(e.index)
686 686 filename, lineno, is_temp = self._find_edit_target(self.shell,
687 687 args, opts, last_call)
688 688 if filename is None:
689 689 # nothing was found, warnings have already been issued,
690 690 # just give up.
691 691 return
692 692
693 693 if is_temp:
694 694 self._knowntemps.add(filename)
695 695 elif (filename in self._knowntemps):
696 696 is_temp = True
697 697
698 698
699 699 # do actual editing here
700 700 print('Editing...', end=' ')
701 701 sys.stdout.flush()
702 702 try:
703 703 # Quote filenames that may have spaces in them
704 704 if ' ' in filename:
705 705 filename = "'%s'" % filename
706 706 self.shell.hooks.editor(filename,lineno)
707 707 except TryNext:
708 708 warn('Could not open editor')
709 709 return
710 710
711 711 # XXX TODO: should this be generalized for all string vars?
712 712 # For now, this is special-cased to blocks created by cpaste
713 713 if args.strip() == 'pasted_block':
714 714 with open(filename, 'r') as f:
715 715 self.shell.user_ns['pasted_block'] = f.read()
716 716
717 717 if 'x' in opts: # -x prevents actual execution
718 718 print()
719 719 else:
720 720 print('done. Executing edited code...')
721 721 with preserve_keys(self.shell.user_ns, '__file__'):
722 722 if not is_temp:
723 723 self.shell.user_ns['__file__'] = filename
724 724 if 'r' in opts: # Untranslated IPython code
725 725 with open(filename, 'r') as f:
726 726 source = f.read()
727 727 self.shell.run_cell(source, store_history=False)
728 728 else:
729 729 self.shell.safe_execfile(filename, self.shell.user_ns,
730 730 self.shell.user_ns)
731 731
732 732 if is_temp:
733 733 try:
734 734 return open(filename).read()
735 735 except IOError as msg:
736 736 if msg.filename == filename:
737 737 warn('File not found. Did you forget to save?')
738 738 return
739 739 else:
740 740 self.shell.showtraceback()
@@ -1,996 +1,996 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Tools for inspecting Python objects.
3 3
4 4 Uses syntax highlighting for presenting the various information elements.
5 5
6 6 Similar in spirit to the inspect module, but all calls take a name argument to
7 7 reference the name under which an object is being read.
8 8 """
9 9
10 10 # Copyright (c) IPython Development Team.
11 11 # Distributed under the terms of the Modified BSD License.
12 12
13 13 __all__ = ['Inspector','InspectColors']
14 14
15 15 # stdlib modules
16 16 import inspect
17 17 from inspect import signature
18 18 import linecache
19 19 import warnings
20 20 import os
21 21 from textwrap import dedent
22 22 import types
23 23 import io as stdlib_io
24 24 from itertools import zip_longest
25 25
26 26 # IPython's own
27 27 from IPython.core import page
28 28 from IPython.lib.pretty import pretty
29 29 from IPython.testing.skipdoctest import skip_doctest
30 30 from IPython.utils import PyColorize
31 31 from IPython.utils import openpy
32 32 from IPython.utils import py3compat
33 33 from IPython.utils.dir2 import safe_hasattr
34 34 from IPython.utils.path import compress_user
35 35 from IPython.utils.text import indent
36 36 from IPython.utils.wildcard import list_namespace
37 37 from IPython.utils.coloransi import TermColors, ColorScheme, ColorSchemeTable
38 38 from IPython.utils.py3compat import cast_unicode
39 39 from IPython.utils.colorable import Colorable
40 40 from IPython.utils.decorators import undoc
41 41
42 42 from pygments import highlight
43 43 from pygments.lexers import PythonLexer
44 44 from pygments.formatters import HtmlFormatter
45 45
46 46 def pylight(code):
47 47 return highlight(code, PythonLexer(), HtmlFormatter(noclasses=True))
48 48
49 49 # builtin docstrings to ignore
50 50 _func_call_docstring = types.FunctionType.__call__.__doc__
51 51 _object_init_docstring = object.__init__.__doc__
52 52 _builtin_type_docstrings = {
53 53 inspect.getdoc(t) for t in (types.ModuleType, types.MethodType,
54 54 types.FunctionType, property)
55 55 }
56 56
57 57 _builtin_func_type = type(all)
58 58 _builtin_meth_type = type(str.upper) # Bound methods have the same type as builtin functions
59 59 #****************************************************************************
60 60 # Builtin color schemes
61 61
62 62 Colors = TermColors # just a shorthand
63 63
64 64 InspectColors = PyColorize.ANSICodeColors
65 65
66 66 #****************************************************************************
67 67 # Auxiliary functions and objects
68 68
69 69 # See the messaging spec for the definition of all these fields. This list
70 70 # effectively defines the order of display
71 71 info_fields = ['type_name', 'base_class', 'string_form', 'namespace',
72 72 'length', 'file', 'definition', 'docstring', 'source',
73 73 'init_definition', 'class_docstring', 'init_docstring',
74 74 'call_def', 'call_docstring',
75 75 # These won't be printed but will be used to determine how to
76 76 # format the object
77 77 'ismagic', 'isalias', 'isclass', 'argspec', 'found', 'name'
78 78 ]
79 79
80 80
81 81 def object_info(**kw):
82 82 """Make an object info dict with all fields present."""
83 83 infodict = dict(zip_longest(info_fields, [None]))
84 84 infodict.update(kw)
85 85 return infodict
86 86
87 87
88 88 def get_encoding(obj):
89 89 """Get encoding for python source file defining obj
90 90
91 91 Returns None if obj is not defined in a sourcefile.
92 92 """
93 93 ofile = find_file(obj)
94 94 # run contents of file through pager starting at line where the object
95 95 # is defined, as long as the file isn't binary and is actually on the
96 96 # filesystem.
97 97 if ofile is None:
98 98 return None
99 99 elif ofile.endswith(('.so', '.dll', '.pyd')):
100 100 return None
101 101 elif not os.path.isfile(ofile):
102 102 return None
103 103 else:
104 104 # Print only text files, not extension binaries. Note that
105 105 # getsourcelines returns lineno with 1-offset and page() uses
106 106 # 0-offset, so we must adjust.
107 107 with stdlib_io.open(ofile, 'rb') as buffer: # Tweaked to use io.open for Python 2
108 108 encoding, lines = openpy.detect_encoding(buffer.readline)
109 109 return encoding
110 110
111 111 def getdoc(obj):
112 112 """Stable wrapper around inspect.getdoc.
113 113
114 114 This can't crash because of attribute problems.
115 115
116 116 It also attempts to call a getdoc() method on the given object. This
117 117 allows objects which provide their docstrings via non-standard mechanisms
118 118 (like Pyro proxies) to still be inspected by ipython's ? system.
119 119 """
120 120 # Allow objects to offer customized documentation via a getdoc method:
121 121 try:
122 122 ds = obj.getdoc()
123 123 except Exception:
124 124 pass
125 125 else:
126 126 if isinstance(ds, str):
127 127 return inspect.cleandoc(ds)
128 128 docstr = inspect.getdoc(obj)
129 129 encoding = get_encoding(obj)
130 130 return py3compat.cast_unicode(docstr, encoding=encoding)
131 131
132 132
133 133 def getsource(obj, oname=''):
134 134 """Wrapper around inspect.getsource.
135 135
136 136 This can be modified by other projects to provide customized source
137 137 extraction.
138 138
139 139 Parameters
140 140 ----------
141 141 obj : object
142 142 an object whose source code we will attempt to extract
143 143 oname : str
144 144 (optional) a name under which the object is known
145 145
146 146 Returns
147 147 -------
148 148 src : unicode or None
149 149
150 150 """
151 151
152 152 if isinstance(obj, property):
153 153 sources = []
154 154 for attrname in ['fget', 'fset', 'fdel']:
155 155 fn = getattr(obj, attrname)
156 156 if fn is not None:
157 157 encoding = get_encoding(fn)
158 158 oname_prefix = ('%s.' % oname) if oname else ''
159 159 sources.append(cast_unicode(
160 160 ''.join(('# ', oname_prefix, attrname)),
161 161 encoding=encoding))
162 162 if inspect.isfunction(fn):
163 163 sources.append(dedent(getsource(fn)))
164 164 else:
165 165 # Default str/repr only prints function name,
166 166 # pretty.pretty prints module name too.
167 167 sources.append(cast_unicode(
168 168 '%s%s = %s\n' % (
169 169 oname_prefix, attrname, pretty(fn)),
170 170 encoding=encoding))
171 171 if sources:
172 172 return '\n'.join(sources)
173 173 else:
174 174 return None
175 175
176 176 else:
177 177 # Get source for non-property objects.
178 178
179 179 obj = _get_wrapped(obj)
180 180
181 181 try:
182 182 src = inspect.getsource(obj)
183 183 except TypeError:
184 184 # The object itself provided no meaningful source, try looking for
185 185 # its class definition instead.
186 186 if hasattr(obj, '__class__'):
187 187 try:
188 188 src = inspect.getsource(obj.__class__)
189 189 except TypeError:
190 190 return None
191 191
192 192 encoding = get_encoding(obj)
193 193 return cast_unicode(src, encoding=encoding)
194 194
195 195
196 196 def is_simple_callable(obj):
197 197 """True if obj is a function ()"""
198 198 return (inspect.isfunction(obj) or inspect.ismethod(obj) or \
199 199 isinstance(obj, _builtin_func_type) or isinstance(obj, _builtin_meth_type))
200 200
201 201
202 202 def getargspec(obj):
203 203 """Wrapper around :func:`inspect.getfullargspec` on Python 3, and
204 204 :func:inspect.getargspec` on Python 2.
205 205
206 206 In addition to functions and methods, this can also handle objects with a
207 207 ``__call__`` attribute.
208 208 """
209 209 if safe_hasattr(obj, '__call__') and not is_simple_callable(obj):
210 210 obj = obj.__call__
211 211
212 212 return inspect.getfullargspec(obj)
213 213
214 214
215 215 def format_argspec(argspec):
216 216 """Format argspect, convenience wrapper around inspect's.
217 217
218 218 This takes a dict instead of ordered arguments and calls
219 219 inspect.format_argspec with the arguments in the necessary order.
220 220 """
221 221 return inspect.formatargspec(argspec['args'], argspec['varargs'],
222 222 argspec['varkw'], argspec['defaults'])
223 223
224 224 @undoc
225 225 def call_tip(oinfo, format_call=True):
226 226 """DEPRECATED. Extract call tip data from an oinfo dict.
227 227 """
228 228 warnings.warn('`call_tip` function is deprecated as of IPython 6.0'
229 229 'and will be removed in future versions.', DeprecationWarning, stacklevel=2)
230 230 # Get call definition
231 231 argspec = oinfo.get('argspec')
232 232 if argspec is None:
233 233 call_line = None
234 234 else:
235 235 # Callable objects will have 'self' as their first argument, prune
236 236 # it out if it's there for clarity (since users do *not* pass an
237 237 # extra first argument explicitly).
238 238 try:
239 239 has_self = argspec['args'][0] == 'self'
240 240 except (KeyError, IndexError):
241 241 pass
242 242 else:
243 243 if has_self:
244 244 argspec['args'] = argspec['args'][1:]
245 245
246 246 call_line = oinfo['name']+format_argspec(argspec)
247 247
248 248 # Now get docstring.
249 249 # The priority is: call docstring, constructor docstring, main one.
250 250 doc = oinfo.get('call_docstring')
251 251 if doc is None:
252 252 doc = oinfo.get('init_docstring')
253 253 if doc is None:
254 254 doc = oinfo.get('docstring','')
255 255
256 256 return call_line, doc
257 257
258 258
259 259 def _get_wrapped(obj):
260 260 """Get the original object if wrapped in one or more @decorators
261 261
262 262 Some objects automatically construct similar objects on any unrecognised
263 263 attribute access (e.g. unittest.mock.call). To protect against infinite loops,
264 264 this will arbitrarily cut off after 100 levels of obj.__wrapped__
265 265 attribute access. --TK, Jan 2016
266 266 """
267 267 orig_obj = obj
268 268 i = 0
269 269 while safe_hasattr(obj, '__wrapped__'):
270 270 obj = obj.__wrapped__
271 271 i += 1
272 272 if i > 100:
273 273 # __wrapped__ is probably a lie, so return the thing we started with
274 274 return orig_obj
275 275 return obj
276 276
277 277 def find_file(obj):
278 278 """Find the absolute path to the file where an object was defined.
279 279
280 280 This is essentially a robust wrapper around `inspect.getabsfile`.
281 281
282 282 Returns None if no file can be found.
283 283
284 284 Parameters
285 285 ----------
286 286 obj : any Python object
287 287
288 288 Returns
289 289 -------
290 290 fname : str
291 291 The absolute path to the file where the object was defined.
292 292 """
293 293 obj = _get_wrapped(obj)
294 294
295 295 fname = None
296 296 try:
297 297 fname = inspect.getabsfile(obj)
298 298 except TypeError:
299 299 # For an instance, the file that matters is where its class was
300 300 # declared.
301 301 if hasattr(obj, '__class__'):
302 302 try:
303 303 fname = inspect.getabsfile(obj.__class__)
304 304 except TypeError:
305 305 # Can happen for builtins
306 306 pass
307 307 except:
308 308 pass
309 309 return cast_unicode(fname)
310 310
311 311
312 312 def find_source_lines(obj):
313 313 """Find the line number in a file where an object was defined.
314 314
315 315 This is essentially a robust wrapper around `inspect.getsourcelines`.
316 316
317 317 Returns None if no file can be found.
318 318
319 319 Parameters
320 320 ----------
321 321 obj : any Python object
322 322
323 323 Returns
324 324 -------
325 325 lineno : int
326 326 The line number where the object definition starts.
327 327 """
328 328 obj = _get_wrapped(obj)
329 329
330 330 try:
331 331 try:
332 332 lineno = inspect.getsourcelines(obj)[1]
333 333 except TypeError:
334 334 # For instances, try the class object like getsource() does
335 335 if hasattr(obj, '__class__'):
336 336 lineno = inspect.getsourcelines(obj.__class__)[1]
337 337 else:
338 338 lineno = None
339 339 except:
340 340 return None
341 341
342 342 return lineno
343 343
344 344 class Inspector(Colorable):
345 345
346 346 def __init__(self, color_table=InspectColors,
347 347 code_color_table=PyColorize.ANSICodeColors,
348 348 scheme=None,
349 349 str_detail_level=0,
350 350 parent=None, config=None):
351 351 super(Inspector, self).__init__(parent=parent, config=config)
352 352 self.color_table = color_table
353 353 self.parser = PyColorize.Parser(out='str', parent=self, style=scheme)
354 354 self.format = self.parser.format
355 355 self.str_detail_level = str_detail_level
356 356 self.set_active_scheme(scheme)
357 357
358 358 def _getdef(self,obj,oname=''):
359 359 """Return the call signature for any callable object.
360 360
361 361 If any exception is generated, None is returned instead and the
362 362 exception is suppressed."""
363 363 try:
364 364 hdef = oname + str(signature(obj))
365 365 return cast_unicode(hdef)
366 366 except:
367 367 return None
368 368
369 369 def __head(self,h):
370 370 """Return a header string with proper colors."""
371 371 return '%s%s%s' % (self.color_table.active_colors.header,h,
372 372 self.color_table.active_colors.normal)
373 373
374 374 def set_active_scheme(self, scheme):
375 375 if scheme is not None:
376 376 self.color_table.set_active_scheme(scheme)
377 377 self.parser.color_table.set_active_scheme(scheme)
378 378
379 379 def noinfo(self, msg, oname):
380 380 """Generic message when no information is found."""
381 381 print('No %s found' % msg, end=' ')
382 382 if oname:
383 383 print('for %s' % oname)
384 384 else:
385 385 print()
386 386
387 387 def pdef(self, obj, oname=''):
388 388 """Print the call signature for any callable object.
389 389
390 390 If the object is a class, print the constructor information."""
391 391
392 392 if not callable(obj):
393 393 print('Object is not callable.')
394 394 return
395 395
396 396 header = ''
397 397
398 398 if inspect.isclass(obj):
399 399 header = self.__head('Class constructor information:\n')
400 400
401 401
402 402 output = self._getdef(obj,oname)
403 403 if output is None:
404 404 self.noinfo('definition header',oname)
405 405 else:
406 406 print(header,self.format(output), end=' ')
407 407
408 408 # In Python 3, all classes are new-style, so they all have __init__.
409 409 @skip_doctest
410 410 def pdoc(self, obj, oname='', formatter=None):
411 411 """Print the docstring for any object.
412 412
413 413 Optional:
414 414 -formatter: a function to run the docstring through for specially
415 415 formatted docstrings.
416 416
417 417 Examples
418 418 --------
419 419
420 420 In [1]: class NoInit:
421 421 ...: pass
422 422
423 423 In [2]: class NoDoc:
424 424 ...: def __init__(self):
425 425 ...: pass
426 426
427 427 In [3]: %pdoc NoDoc
428 428 No documentation found for NoDoc
429 429
430 430 In [4]: %pdoc NoInit
431 431 No documentation found for NoInit
432 432
433 433 In [5]: obj = NoInit()
434 434
435 435 In [6]: %pdoc obj
436 436 No documentation found for obj
437 437
438 438 In [5]: obj2 = NoDoc()
439 439
440 440 In [6]: %pdoc obj2
441 441 No documentation found for obj2
442 442 """
443 443
444 444 head = self.__head # For convenience
445 445 lines = []
446 446 ds = getdoc(obj)
447 447 if formatter:
448 448 ds = formatter(ds).get('plain/text', ds)
449 449 if ds:
450 450 lines.append(head("Class docstring:"))
451 451 lines.append(indent(ds))
452 452 if inspect.isclass(obj) and hasattr(obj, '__init__'):
453 453 init_ds = getdoc(obj.__init__)
454 454 if init_ds is not None:
455 455 lines.append(head("Init docstring:"))
456 456 lines.append(indent(init_ds))
457 457 elif hasattr(obj,'__call__'):
458 458 call_ds = getdoc(obj.__call__)
459 459 if call_ds:
460 460 lines.append(head("Call docstring:"))
461 461 lines.append(indent(call_ds))
462 462
463 463 if not lines:
464 464 self.noinfo('documentation',oname)
465 465 else:
466 466 page.page('\n'.join(lines))
467 467
468 468 def psource(self, obj, oname=''):
469 469 """Print the source code for an object."""
470 470
471 471 # Flush the source cache because inspect can return out-of-date source
472 472 linecache.checkcache()
473 473 try:
474 474 src = getsource(obj, oname=oname)
475 475 except Exception:
476 476 src = None
477 477
478 478 if src is None:
479 479 self.noinfo('source', oname)
480 480 else:
481 481 page.page(self.format(src))
482 482
483 483 def pfile(self, obj, oname=''):
484 484 """Show the whole file where an object was defined."""
485 485
486 486 lineno = find_source_lines(obj)
487 487 if lineno is None:
488 488 self.noinfo('file', oname)
489 489 return
490 490
491 491 ofile = find_file(obj)
492 492 # run contents of file through pager starting at line where the object
493 493 # is defined, as long as the file isn't binary and is actually on the
494 494 # filesystem.
495 495 if ofile.endswith(('.so', '.dll', '.pyd')):
496 496 print('File %r is binary, not printing.' % ofile)
497 497 elif not os.path.isfile(ofile):
498 498 print('File %r does not exist, not printing.' % ofile)
499 499 else:
500 500 # Print only text files, not extension binaries. Note that
501 501 # getsourcelines returns lineno with 1-offset and page() uses
502 502 # 0-offset, so we must adjust.
503 503 page.page(self.format(openpy.read_py_file(ofile, skip_encoding_cookie=False)), lineno - 1)
504 504
505 505 def _format_fields(self, fields, title_width=0):
506 506 """Formats a list of fields for display.
507 507
508 508 Parameters
509 509 ----------
510 510 fields : list
511 511 A list of 2-tuples: (field_title, field_content)
512 512 title_width : int
513 513 How many characters to pad titles to. Default to longest title.
514 514 """
515 515 out = []
516 516 header = self.__head
517 517 if title_width == 0:
518 518 title_width = max(len(title) + 2 for title, _ in fields)
519 519 for title, content in fields:
520 520 if len(content.splitlines()) > 1:
521 521 title = header(title + ':') + '\n'
522 522 else:
523 523 title = header((title + ':').ljust(title_width))
524 524 out.append(cast_unicode(title) + cast_unicode(content))
525 525 return "\n".join(out)
526 526
527 527 def _mime_format(self, text, formatter=None):
528 528 """Return a mime bundle representation of the input text.
529 529
530 530 - if `formatter` is None, the returned mime bundle has
531 531 a `text/plain` field, with the input text.
532 532 a `text/html` field with a `<pre>` tag containing the input text.
533 533
534 534 - if `formatter` is not None, it must be a callable transforming the
535 535 input text into a mime bundle. Default values for `text/plain` and
536 536 `text/html` representations are the ones described above.
537 537
538 538 Note:
539 539
540 540 Formatters returning strings are supported but this behavior is deprecated.
541 541
542 542 """
543 543 text = cast_unicode(text)
544 544 defaults = {
545 545 'text/plain': text,
546 546 'text/html': '<pre>' + text + '</pre>'
547 547 }
548 548
549 549 if formatter is None:
550 550 return defaults
551 551 else:
552 552 formatted = formatter(text)
553 553
554 554 if not isinstance(formatted, dict):
555 555 # Handle the deprecated behavior of a formatter returning
556 556 # a string instead of a mime bundle.
557 557 return {
558 558 'text/plain': formatted,
559 559 'text/html': '<pre>' + formatted + '</pre>'
560 560 }
561 561
562 562 else:
563 563 return dict(defaults, **formatted)
564 564
565 565
566 566 def format_mime(self, bundle):
567 567
568 568 text_plain = bundle['text/plain']
569 569
570 570 text = ''
571 571 heads, bodies = list(zip(*text_plain))
572 572 _len = max(len(h) for h in heads)
573 573
574 574 for head, body in zip(heads, bodies):
575 575 body = body.strip('\n')
576 576 delim = '\n' if '\n' in body else ' '
577 577 text += self.__head(head+':') + (_len - len(head))*' ' +delim + body +'\n'
578 578
579 579 bundle['text/plain'] = text
580 580 return bundle
581 581
582 582 def _get_info(self, obj, oname='', formatter=None, info=None, detail_level=0):
583 583 """Retrieve an info dict and format it.
584 584
585 585 Parameters
586 586 ==========
587 587
588 588 obj: any
589 589 Object to inspect and return info from
590 590 oname: str (default: ''):
591 591 Name of the variable pointing to `obj`.
592 592 formatter: callable
593 593 info:
594 already computed informations
594 already computed information
595 595 detail_level: integer
596 Granularity of detail level, if set to 1, give more informations.
596 Granularity of detail level, if set to 1, give more information.
597 597 """
598 598
599 599 info = self._info(obj, oname=oname, info=info, detail_level=detail_level)
600 600
601 601 _mime = {
602 602 'text/plain': [],
603 603 'text/html': '',
604 604 }
605 605
606 606 def append_field(bundle, title, key, formatter=None):
607 607 field = info[key]
608 608 if field is not None:
609 609 formatted_field = self._mime_format(field, formatter)
610 610 bundle['text/plain'].append((title, formatted_field['text/plain']))
611 611 bundle['text/html'] += '<h1>' + title + '</h1>\n' + formatted_field['text/html'] + '\n'
612 612
613 613 def code_formatter(text):
614 614 return {
615 615 'text/plain': self.format(text),
616 616 'text/html': pylight(text)
617 617 }
618 618
619 619 if info['isalias']:
620 620 append_field(_mime, 'Repr', 'string_form')
621 621
622 622 elif info['ismagic']:
623 623 if detail_level > 0:
624 624 append_field(_mime, 'Source', 'source', code_formatter)
625 625 else:
626 626 append_field(_mime, 'Docstring', 'docstring', formatter)
627 627 append_field(_mime, 'File', 'file')
628 628
629 629 elif info['isclass'] or is_simple_callable(obj):
630 630 # Functions, methods, classes
631 631 append_field(_mime, 'Signature', 'definition', code_formatter)
632 632 append_field(_mime, 'Init signature', 'init_definition', code_formatter)
633 633 if detail_level > 0 and info['source']:
634 634 append_field(_mime, 'Source', 'source', code_formatter)
635 635 else:
636 636 append_field(_mime, 'Docstring', 'docstring', formatter)
637 637 append_field(_mime, 'Init docstring', 'init_docstring', formatter)
638 638
639 639 append_field(_mime, 'File', 'file')
640 640 append_field(_mime, 'Type', 'type_name')
641 641
642 642 else:
643 643 # General Python objects
644 644 append_field(_mime, 'Signature', 'definition', code_formatter)
645 645 append_field(_mime, 'Call signature', 'call_def', code_formatter)
646 646 append_field(_mime, 'Type', 'type_name')
647 647 append_field(_mime, 'String form', 'string_form')
648 648
649 649 # Namespace
650 650 if info['namespace'] != 'Interactive':
651 651 append_field(_mime, 'Namespace', 'namespace')
652 652
653 653 append_field(_mime, 'Length', 'length')
654 654 append_field(_mime, 'File', 'file')
655 655
656 656 # Source or docstring, depending on detail level and whether
657 657 # source found.
658 658 if detail_level > 0 and info['source']:
659 659 append_field(_mime, 'Source', 'source', code_formatter)
660 660 else:
661 661 append_field(_mime, 'Docstring', 'docstring', formatter)
662 662
663 663 append_field(_mime, 'Class docstring', 'class_docstring', formatter)
664 664 append_field(_mime, 'Init docstring', 'init_docstring', formatter)
665 665 append_field(_mime, 'Call docstring', 'call_docstring', formatter)
666 666
667 667
668 668 return self.format_mime(_mime)
669 669
670 670 def pinfo(self, obj, oname='', formatter=None, info=None, detail_level=0, enable_html_pager=True):
671 671 """Show detailed information about an object.
672 672
673 673 Optional arguments:
674 674
675 675 - oname: name of the variable pointing to the object.
676 676
677 677 - formatter: callable (optional)
678 678 A special formatter for docstrings.
679 679
680 680 The formatter is a callable that takes a string as an input
681 681 and returns either a formatted string or a mime type bundle
682 in the form of a dictionnary.
682 in the form of a dictionary.
683 683
684 684 Although the support of custom formatter returning a string
685 685 instead of a mime type bundle is deprecated.
686 686
687 687 - info: a structure with some information fields which may have been
688 688 precomputed already.
689 689
690 690 - detail_level: if set to 1, more information is given.
691 691 """
692 692 info = self._get_info(obj, oname, formatter, info, detail_level)
693 693 if not enable_html_pager:
694 694 del info['text/html']
695 695 page.page(info)
696 696
697 697 def info(self, obj, oname='', formatter=None, info=None, detail_level=0):
698 698 """DEPRECATED. Compute a dict with detailed information about an object.
699 699 """
700 700 if formatter is not None:
701 701 warnings.warn('The `formatter` keyword argument to `Inspector.info`'
702 702 'is deprecated as of IPython 5.0 and will have no effects.',
703 703 DeprecationWarning, stacklevel=2)
704 704 return self._info(obj, oname=oname, info=info, detail_level=detail_level)
705 705
706 706 def _info(self, obj, oname='', info=None, detail_level=0) -> dict:
707 707 """Compute a dict with detailed information about an object.
708 708
709 709 Parameters
710 710 ==========
711 711
712 712 obj: any
713 713 An object to find information about
714 714 oname: str (default: ''):
715 715 Name of the variable pointing to `obj`.
716 716 info: (default: None)
717 717 A struct (dict like with attr access) with some information fields
718 718 which may have been precomputed already.
719 719 detail_level: int (default:0)
720 720 If set to 1, more information is given.
721 721
722 722 Returns
723 723 =======
724 724
725 725 An object info dict with known fields from `info_fields`.
726 726 """
727 727
728 728 if info is None:
729 729 ismagic = False
730 730 isalias = False
731 731 ospace = ''
732 732 else:
733 733 ismagic = info.ismagic
734 734 isalias = info.isalias
735 735 ospace = info.namespace
736 736
737 737 # Get docstring, special-casing aliases:
738 738 if isalias:
739 739 if not callable(obj):
740 740 try:
741 741 ds = "Alias to the system command:\n %s" % obj[1]
742 742 except:
743 743 ds = "Alias: " + str(obj)
744 744 else:
745 745 ds = "Alias to " + str(obj)
746 746 if obj.__doc__:
747 747 ds += "\nDocstring:\n" + obj.__doc__
748 748 else:
749 749 ds = getdoc(obj)
750 750 if ds is None:
751 751 ds = '<no docstring>'
752 752
753 753 # store output in a dict, we initialize it here and fill it as we go
754 754 out = dict(name=oname, found=True, isalias=isalias, ismagic=ismagic)
755 755
756 756 string_max = 200 # max size of strings to show (snipped if longer)
757 757 shalf = int((string_max - 5) / 2)
758 758
759 759 if ismagic:
760 760 out['type_name'] = 'Magic function'
761 761 elif isalias:
762 762 out['type_name'] = 'System alias'
763 763 else:
764 764 out['type_name'] = type(obj).__name__
765 765
766 766 try:
767 767 bclass = obj.__class__
768 768 out['base_class'] = str(bclass)
769 769 except:
770 770 pass
771 771
772 772 # String form, but snip if too long in ? form (full in ??)
773 773 if detail_level >= self.str_detail_level:
774 774 try:
775 775 ostr = str(obj)
776 776 str_head = 'string_form'
777 777 if not detail_level and len(ostr)>string_max:
778 778 ostr = ostr[:shalf] + ' <...> ' + ostr[-shalf:]
779 779 ostr = ("\n" + " " * len(str_head.expandtabs())).\
780 780 join(q.strip() for q in ostr.split("\n"))
781 781 out[str_head] = ostr
782 782 except:
783 783 pass
784 784
785 785 if ospace:
786 786 out['namespace'] = ospace
787 787
788 788 # Length (for strings and lists)
789 789 try:
790 790 out['length'] = str(len(obj))
791 791 except Exception:
792 792 pass
793 793
794 794 # Filename where object was defined
795 795 binary_file = False
796 796 fname = find_file(obj)
797 797 if fname is None:
798 798 # if anything goes wrong, we don't want to show source, so it's as
799 799 # if the file was binary
800 800 binary_file = True
801 801 else:
802 802 if fname.endswith(('.so', '.dll', '.pyd')):
803 803 binary_file = True
804 804 elif fname.endswith('<string>'):
805 805 fname = 'Dynamically generated function. No source code available.'
806 806 out['file'] = compress_user(fname)
807 807
808 808 # Original source code for a callable, class or property.
809 809 if detail_level:
810 810 # Flush the source cache because inspect can return out-of-date
811 811 # source
812 812 linecache.checkcache()
813 813 try:
814 814 if isinstance(obj, property) or not binary_file:
815 815 src = getsource(obj, oname)
816 816 if src is not None:
817 817 src = src.rstrip()
818 818 out['source'] = src
819 819
820 820 except Exception:
821 821 pass
822 822
823 823 # Add docstring only if no source is to be shown (avoid repetitions).
824 824 if ds and out.get('source', None) is None:
825 825 out['docstring'] = ds
826 826
827 827 # Constructor docstring for classes
828 828 if inspect.isclass(obj):
829 829 out['isclass'] = True
830 830
831 831 # get the init signature:
832 832 try:
833 833 init_def = self._getdef(obj, oname)
834 834 except AttributeError:
835 835 init_def = None
836 836
837 837 # get the __init__ docstring
838 838 try:
839 839 obj_init = obj.__init__
840 840 except AttributeError:
841 841 init_ds = None
842 842 else:
843 843 if init_def is None:
844 844 # Get signature from init if top-level sig failed.
845 845 # Can happen for built-in types (list, etc.).
846 846 try:
847 847 init_def = self._getdef(obj_init, oname)
848 848 except AttributeError:
849 849 pass
850 850 init_ds = getdoc(obj_init)
851 851 # Skip Python's auto-generated docstrings
852 852 if init_ds == _object_init_docstring:
853 853 init_ds = None
854 854
855 855 if init_def:
856 856 out['init_definition'] = init_def
857 857
858 858 if init_ds:
859 859 out['init_docstring'] = init_ds
860 860
861 861 # and class docstring for instances:
862 862 else:
863 863 # reconstruct the function definition and print it:
864 864 defln = self._getdef(obj, oname)
865 865 if defln:
866 866 out['definition'] = defln
867 867
868 868 # First, check whether the instance docstring is identical to the
869 869 # class one, and print it separately if they don't coincide. In
870 870 # most cases they will, but it's nice to print all the info for
871 871 # objects which use instance-customized docstrings.
872 872 if ds:
873 873 try:
874 874 cls = getattr(obj,'__class__')
875 875 except:
876 876 class_ds = None
877 877 else:
878 878 class_ds = getdoc(cls)
879 879 # Skip Python's auto-generated docstrings
880 880 if class_ds in _builtin_type_docstrings:
881 881 class_ds = None
882 882 if class_ds and ds != class_ds:
883 883 out['class_docstring'] = class_ds
884 884
885 885 # Next, try to show constructor docstrings
886 886 try:
887 887 init_ds = getdoc(obj.__init__)
888 888 # Skip Python's auto-generated docstrings
889 889 if init_ds == _object_init_docstring:
890 890 init_ds = None
891 891 except AttributeError:
892 892 init_ds = None
893 893 if init_ds:
894 894 out['init_docstring'] = init_ds
895 895
896 896 # Call form docstring for callable instances
897 897 if safe_hasattr(obj, '__call__') and not is_simple_callable(obj):
898 898 call_def = self._getdef(obj.__call__, oname)
899 899 if call_def and (call_def != out.get('definition')):
900 900 # it may never be the case that call def and definition differ,
901 901 # but don't include the same signature twice
902 902 out['call_def'] = call_def
903 903 call_ds = getdoc(obj.__call__)
904 904 # Skip Python's auto-generated docstrings
905 905 if call_ds == _func_call_docstring:
906 906 call_ds = None
907 907 if call_ds:
908 908 out['call_docstring'] = call_ds
909 909
910 910 # Compute the object's argspec as a callable. The key is to decide
911 911 # whether to pull it from the object itself, from its __init__ or
912 912 # from its __call__ method.
913 913
914 914 if inspect.isclass(obj):
915 915 # Old-style classes need not have an __init__
916 916 callable_obj = getattr(obj, "__init__", None)
917 917 elif callable(obj):
918 918 callable_obj = obj
919 919 else:
920 920 callable_obj = None
921 921
922 922 if callable_obj is not None:
923 923 try:
924 924 argspec = getargspec(callable_obj)
925 925 except Exception:
926 926 # For extensions/builtins we can't retrieve the argspec
927 927 pass
928 928 else:
929 929 # named tuples' _asdict() method returns an OrderedDict, but we
930 930 # we want a normal
931 931 out['argspec'] = argspec_dict = dict(argspec._asdict())
932 932 # We called this varkw before argspec became a named tuple.
933 933 # With getfullargspec it's also called varkw.
934 934 if 'varkw' not in argspec_dict:
935 935 argspec_dict['varkw'] = argspec_dict.pop('keywords')
936 936
937 937 return object_info(**out)
938 938
939 939 def psearch(self,pattern,ns_table,ns_search=[],
940 940 ignore_case=False,show_all=False):
941 941 """Search namespaces with wildcards for objects.
942 942
943 943 Arguments:
944 944
945 945 - pattern: string containing shell-like wildcards to use in namespace
946 946 searches and optionally a type specification to narrow the search to
947 947 objects of that type.
948 948
949 949 - ns_table: dict of name->namespaces for search.
950 950
951 951 Optional arguments:
952 952
953 953 - ns_search: list of namespace names to include in search.
954 954
955 955 - ignore_case(False): make the search case-insensitive.
956 956
957 957 - show_all(False): show all names, including those starting with
958 958 underscores.
959 959 """
960 960 #print 'ps pattern:<%r>' % pattern # dbg
961 961
962 962 # defaults
963 963 type_pattern = 'all'
964 964 filter = ''
965 965
966 966 cmds = pattern.split()
967 967 len_cmds = len(cmds)
968 968 if len_cmds == 1:
969 969 # Only filter pattern given
970 970 filter = cmds[0]
971 971 elif len_cmds == 2:
972 972 # Both filter and type specified
973 973 filter,type_pattern = cmds
974 974 else:
975 975 raise ValueError('invalid argument string for psearch: <%s>' %
976 976 pattern)
977 977
978 978 # filter search namespaces
979 979 for name in ns_search:
980 980 if name not in ns_table:
981 981 raise ValueError('invalid namespace <%s>. Valid names: %s' %
982 982 (name,ns_table.keys()))
983 983
984 984 #print 'type_pattern:',type_pattern # dbg
985 985 search_result, namespaces_seen = set(), set()
986 986 for ns_name in ns_search:
987 987 ns = ns_table[ns_name]
988 988 # Normally, locals and globals are the same, so we just check one.
989 989 if id(ns) in namespaces_seen:
990 990 continue
991 991 namespaces_seen.add(id(ns))
992 992 tmp_res = list_namespace(ns, type_pattern, filter,
993 993 ignore_case=ignore_case, show_all=show_all)
994 994 search_result.update(tmp_res)
995 995
996 996 page.page('\n'.join(sorted(search_result)))
@@ -1,709 +1,709 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
9 9 # Copyright (c) IPython Development Team.
10 10 # Distributed under the terms of the Modified BSD License.
11 11
12 12 from keyword import iskeyword
13 13 import re
14 14
15 15 from IPython.core.autocall import IPyAutocall
16 16 from traitlets.config.configurable import Configurable
17 17 from IPython.core.inputsplitter import (
18 18 ESC_MAGIC,
19 19 ESC_QUOTE,
20 20 ESC_QUOTE2,
21 21 ESC_PAREN,
22 22 )
23 23 from IPython.core.macro import Macro
24 24 from IPython.core.splitinput import LineInfo
25 25
26 26 from traitlets import (
27 27 List, Integer, Unicode, Bool, Instance, CRegExp
28 28 )
29 29
30 30 #-----------------------------------------------------------------------------
31 31 # Global utilities, errors and constants
32 32 #-----------------------------------------------------------------------------
33 33
34 34
35 35 class PrefilterError(Exception):
36 36 pass
37 37
38 38
39 39 # RegExp to identify potential function names
40 40 re_fun_name = re.compile(r'[a-zA-Z_]([a-zA-Z0-9_.]*) *$')
41 41
42 42 # RegExp to exclude strings with this start from autocalling. In
43 43 # particular, all binary operators should be excluded, so that if foo is
44 44 # callable, foo OP bar doesn't become foo(OP bar), which is invalid. The
45 45 # characters '!=()' don't need to be checked for, as the checkPythonChars
46 # routine explicitely does so, to catch direct calls and rebindings of
46 # routine explicitly does so, to catch direct calls and rebindings of
47 47 # existing names.
48 48
49 49 # Warning: the '-' HAS TO BE AT THE END of the first group, otherwise
50 50 # it affects the rest of the group in square brackets.
51 51 re_exclude_auto = re.compile(r'^[,&^\|\*/\+-]'
52 52 r'|^is |^not |^in |^and |^or ')
53 53
54 54 # try to catch also methods for stuff in lists/tuples/dicts: off
55 55 # (experimental). For this to work, the line_split regexp would need
56 56 # to be modified so it wouldn't break things at '['. That line is
57 57 # nasty enough that I shouldn't change it until I can test it _well_.
58 58 #self.re_fun_name = re.compile (r'[a-zA-Z_]([a-zA-Z0-9_.\[\]]*) ?$')
59 59
60 60
61 61 # Handler Check Utilities
62 62 def is_shadowed(identifier, ip):
63 63 """Is the given identifier defined in one of the namespaces which shadow
64 64 the alias and magic namespaces? Note that an identifier is different
65 65 than ifun, because it can not contain a '.' character."""
66 66 # This is much safer than calling ofind, which can change state
67 67 return (identifier in ip.user_ns \
68 68 or identifier in ip.user_global_ns \
69 69 or identifier in ip.ns_table['builtin']\
70 70 or iskeyword(identifier))
71 71
72 72
73 73 #-----------------------------------------------------------------------------
74 74 # Main Prefilter manager
75 75 #-----------------------------------------------------------------------------
76 76
77 77
78 78 class PrefilterManager(Configurable):
79 79 """Main prefilter component.
80 80
81 81 The IPython prefilter is run on all user input before it is run. The
82 82 prefilter consumes lines of input and produces transformed lines of
83 83 input.
84 84
85 85 The iplementation consists of two phases:
86 86
87 87 1. Transformers
88 88 2. Checkers and handlers
89 89
90 90 Over time, we plan on deprecating the checkers and handlers and doing
91 91 everything in the transformers.
92 92
93 93 The transformers are instances of :class:`PrefilterTransformer` and have
94 94 a single method :meth:`transform` that takes a line and returns a
95 95 transformed line. The transformation can be accomplished using any
96 96 tool, but our current ones use regular expressions for speed.
97 97
98 98 After all the transformers have been run, the line is fed to the checkers,
99 99 which are instances of :class:`PrefilterChecker`. The line is passed to
100 100 the :meth:`check` method, which either returns `None` or a
101 101 :class:`PrefilterHandler` instance. If `None` is returned, the other
102 102 checkers are tried. If an :class:`PrefilterHandler` instance is returned,
103 103 the line is passed to the :meth:`handle` method of the returned
104 104 handler and no further checkers are tried.
105 105
106 106 Both transformers and checkers have a `priority` attribute, that determines
107 107 the order in which they are called. Smaller priorities are tried first.
108 108
109 109 Both transformers and checkers also have `enabled` attribute, which is
110 110 a boolean that determines if the instance is used.
111 111
112 112 Users or developers can change the priority or enabled attribute of
113 113 transformers or checkers, but they must call the :meth:`sort_checkers`
114 114 or :meth:`sort_transformers` method after changing the priority.
115 115 """
116 116
117 117 multi_line_specials = Bool(True).tag(config=True)
118 118 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
119 119
120 120 def __init__(self, shell=None, **kwargs):
121 121 super(PrefilterManager, self).__init__(shell=shell, **kwargs)
122 122 self.shell = shell
123 123 self.init_transformers()
124 124 self.init_handlers()
125 125 self.init_checkers()
126 126
127 127 #-------------------------------------------------------------------------
128 128 # API for managing transformers
129 129 #-------------------------------------------------------------------------
130 130
131 131 def init_transformers(self):
132 132 """Create the default transformers."""
133 133 self._transformers = []
134 134 for transformer_cls in _default_transformers:
135 135 transformer_cls(
136 136 shell=self.shell, prefilter_manager=self, parent=self
137 137 )
138 138
139 139 def sort_transformers(self):
140 140 """Sort the transformers by priority.
141 141
142 142 This must be called after the priority of a transformer is changed.
143 143 The :meth:`register_transformer` method calls this automatically.
144 144 """
145 145 self._transformers.sort(key=lambda x: x.priority)
146 146
147 147 @property
148 148 def transformers(self):
149 149 """Return a list of checkers, sorted by priority."""
150 150 return self._transformers
151 151
152 152 def register_transformer(self, transformer):
153 153 """Register a transformer instance."""
154 154 if transformer not in self._transformers:
155 155 self._transformers.append(transformer)
156 156 self.sort_transformers()
157 157
158 158 def unregister_transformer(self, transformer):
159 159 """Unregister a transformer instance."""
160 160 if transformer in self._transformers:
161 161 self._transformers.remove(transformer)
162 162
163 163 #-------------------------------------------------------------------------
164 164 # API for managing checkers
165 165 #-------------------------------------------------------------------------
166 166
167 167 def init_checkers(self):
168 168 """Create the default checkers."""
169 169 self._checkers = []
170 170 for checker in _default_checkers:
171 171 checker(
172 172 shell=self.shell, prefilter_manager=self, parent=self
173 173 )
174 174
175 175 def sort_checkers(self):
176 176 """Sort the checkers by priority.
177 177
178 178 This must be called after the priority of a checker is changed.
179 179 The :meth:`register_checker` method calls this automatically.
180 180 """
181 181 self._checkers.sort(key=lambda x: x.priority)
182 182
183 183 @property
184 184 def checkers(self):
185 185 """Return a list of checkers, sorted by priority."""
186 186 return self._checkers
187 187
188 188 def register_checker(self, checker):
189 189 """Register a checker instance."""
190 190 if checker not in self._checkers:
191 191 self._checkers.append(checker)
192 192 self.sort_checkers()
193 193
194 194 def unregister_checker(self, checker):
195 195 """Unregister a checker instance."""
196 196 if checker in self._checkers:
197 197 self._checkers.remove(checker)
198 198
199 199 #-------------------------------------------------------------------------
200 200 # API for managing handlers
201 201 #-------------------------------------------------------------------------
202 202
203 203 def init_handlers(self):
204 204 """Create the default handlers."""
205 205 self._handlers = {}
206 206 self._esc_handlers = {}
207 207 for handler in _default_handlers:
208 208 handler(
209 209 shell=self.shell, prefilter_manager=self, parent=self
210 210 )
211 211
212 212 @property
213 213 def handlers(self):
214 214 """Return a dict of all the handlers."""
215 215 return self._handlers
216 216
217 217 def register_handler(self, name, handler, esc_strings):
218 218 """Register a handler instance by name with esc_strings."""
219 219 self._handlers[name] = handler
220 220 for esc_str in esc_strings:
221 221 self._esc_handlers[esc_str] = handler
222 222
223 223 def unregister_handler(self, name, handler, esc_strings):
224 224 """Unregister a handler instance by name with esc_strings."""
225 225 try:
226 226 del self._handlers[name]
227 227 except KeyError:
228 228 pass
229 229 for esc_str in esc_strings:
230 230 h = self._esc_handlers.get(esc_str)
231 231 if h is handler:
232 232 del self._esc_handlers[esc_str]
233 233
234 234 def get_handler_by_name(self, name):
235 235 """Get a handler by its name."""
236 236 return self._handlers.get(name)
237 237
238 238 def get_handler_by_esc(self, esc_str):
239 239 """Get a handler by its escape string."""
240 240 return self._esc_handlers.get(esc_str)
241 241
242 242 #-------------------------------------------------------------------------
243 243 # Main prefiltering API
244 244 #-------------------------------------------------------------------------
245 245
246 246 def prefilter_line_info(self, line_info):
247 247 """Prefilter a line that has been converted to a LineInfo object.
248 248
249 249 This implements the checker/handler part of the prefilter pipe.
250 250 """
251 251 # print "prefilter_line_info: ", line_info
252 252 handler = self.find_handler(line_info)
253 253 return handler.handle(line_info)
254 254
255 255 def find_handler(self, line_info):
256 256 """Find a handler for the line_info by trying checkers."""
257 257 for checker in self.checkers:
258 258 if checker.enabled:
259 259 handler = checker.check(line_info)
260 260 if handler:
261 261 return handler
262 262 return self.get_handler_by_name('normal')
263 263
264 264 def transform_line(self, line, continue_prompt):
265 265 """Calls the enabled transformers in order of increasing priority."""
266 266 for transformer in self.transformers:
267 267 if transformer.enabled:
268 268 line = transformer.transform(line, continue_prompt)
269 269 return line
270 270
271 271 def prefilter_line(self, line, continue_prompt=False):
272 272 """Prefilter a single input line as text.
273 273
274 274 This method prefilters a single line of text by calling the
275 275 transformers and then the checkers/handlers.
276 276 """
277 277
278 278 # print "prefilter_line: ", line, continue_prompt
279 279 # All handlers *must* return a value, even if it's blank ('').
280 280
281 281 # save the line away in case we crash, so the post-mortem handler can
282 282 # record it
283 283 self.shell._last_input_line = line
284 284
285 285 if not line:
286 286 # Return immediately on purely empty lines, so that if the user
287 287 # previously typed some whitespace that started a continuation
288 288 # prompt, he can break out of that loop with just an empty line.
289 289 # This is how the default python prompt works.
290 290 return ''
291 291
292 292 # At this point, we invoke our transformers.
293 293 if not continue_prompt or (continue_prompt and self.multi_line_specials):
294 294 line = self.transform_line(line, continue_prompt)
295 295
296 296 # Now we compute line_info for the checkers and handlers
297 297 line_info = LineInfo(line, continue_prompt)
298 298
299 299 # the input history needs to track even empty lines
300 300 stripped = line.strip()
301 301
302 302 normal_handler = self.get_handler_by_name('normal')
303 303 if not stripped:
304 304 return normal_handler.handle(line_info)
305 305
306 306 # special handlers are only allowed for single line statements
307 307 if continue_prompt and not self.multi_line_specials:
308 308 return normal_handler.handle(line_info)
309 309
310 310 prefiltered = self.prefilter_line_info(line_info)
311 311 # print "prefiltered line: %r" % prefiltered
312 312 return prefiltered
313 313
314 314 def prefilter_lines(self, lines, continue_prompt=False):
315 315 """Prefilter multiple input lines of text.
316 316
317 317 This is the main entry point for prefiltering multiple lines of
318 318 input. This simply calls :meth:`prefilter_line` for each line of
319 319 input.
320 320
321 321 This covers cases where there are multiple lines in the user entry,
322 322 which is the case when the user goes back to a multiline history
323 323 entry and presses enter.
324 324 """
325 325 llines = lines.rstrip('\n').split('\n')
326 326 # We can get multiple lines in one shot, where multiline input 'blends'
327 327 # into one line, in cases like recalling from the readline history
328 328 # buffer. We need to make sure that in such cases, we correctly
329 329 # communicate downstream which line is first and which are continuation
330 330 # ones.
331 331 if len(llines) > 1:
332 332 out = '\n'.join([self.prefilter_line(line, lnum>0)
333 333 for lnum, line in enumerate(llines) ])
334 334 else:
335 335 out = self.prefilter_line(llines[0], continue_prompt)
336 336
337 337 return out
338 338
339 339 #-----------------------------------------------------------------------------
340 340 # Prefilter transformers
341 341 #-----------------------------------------------------------------------------
342 342
343 343
344 344 class PrefilterTransformer(Configurable):
345 345 """Transform a line of user input."""
346 346
347 347 priority = Integer(100).tag(config=True)
348 348 # Transformers don't currently use shell or prefilter_manager, but as we
349 349 # move away from checkers and handlers, they will need them.
350 350 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
351 351 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager', allow_none=True)
352 352 enabled = Bool(True).tag(config=True)
353 353
354 354 def __init__(self, shell=None, prefilter_manager=None, **kwargs):
355 355 super(PrefilterTransformer, self).__init__(
356 356 shell=shell, prefilter_manager=prefilter_manager, **kwargs
357 357 )
358 358 self.prefilter_manager.register_transformer(self)
359 359
360 360 def transform(self, line, continue_prompt):
361 361 """Transform a line, returning the new one."""
362 362 return None
363 363
364 364 def __repr__(self):
365 365 return "<%s(priority=%r, enabled=%r)>" % (
366 366 self.__class__.__name__, self.priority, self.enabled)
367 367
368 368
369 369 #-----------------------------------------------------------------------------
370 370 # Prefilter checkers
371 371 #-----------------------------------------------------------------------------
372 372
373 373
374 374 class PrefilterChecker(Configurable):
375 375 """Inspect an input line and return a handler for that line."""
376 376
377 377 priority = Integer(100).tag(config=True)
378 378 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
379 379 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager', allow_none=True)
380 380 enabled = Bool(True).tag(config=True)
381 381
382 382 def __init__(self, shell=None, prefilter_manager=None, **kwargs):
383 383 super(PrefilterChecker, self).__init__(
384 384 shell=shell, prefilter_manager=prefilter_manager, **kwargs
385 385 )
386 386 self.prefilter_manager.register_checker(self)
387 387
388 388 def check(self, line_info):
389 389 """Inspect line_info and return a handler instance or None."""
390 390 return None
391 391
392 392 def __repr__(self):
393 393 return "<%s(priority=%r, enabled=%r)>" % (
394 394 self.__class__.__name__, self.priority, self.enabled)
395 395
396 396
397 397 class EmacsChecker(PrefilterChecker):
398 398
399 399 priority = Integer(100).tag(config=True)
400 400 enabled = Bool(False).tag(config=True)
401 401
402 402 def check(self, line_info):
403 403 "Emacs ipython-mode tags certain input lines."
404 404 if line_info.line.endswith('# PYTHON-MODE'):
405 405 return self.prefilter_manager.get_handler_by_name('emacs')
406 406 else:
407 407 return None
408 408
409 409
410 410 class MacroChecker(PrefilterChecker):
411 411
412 412 priority = Integer(250).tag(config=True)
413 413
414 414 def check(self, line_info):
415 415 obj = self.shell.user_ns.get(line_info.ifun)
416 416 if isinstance(obj, Macro):
417 417 return self.prefilter_manager.get_handler_by_name('macro')
418 418 else:
419 419 return None
420 420
421 421
422 422 class IPyAutocallChecker(PrefilterChecker):
423 423
424 424 priority = Integer(300).tag(config=True)
425 425
426 426 def check(self, line_info):
427 427 "Instances of IPyAutocall in user_ns get autocalled immediately"
428 428 obj = self.shell.user_ns.get(line_info.ifun, None)
429 429 if isinstance(obj, IPyAutocall):
430 430 obj.set_ip(self.shell)
431 431 return self.prefilter_manager.get_handler_by_name('auto')
432 432 else:
433 433 return None
434 434
435 435
436 436 class AssignmentChecker(PrefilterChecker):
437 437
438 438 priority = Integer(600).tag(config=True)
439 439
440 440 def check(self, line_info):
441 441 """Check to see if user is assigning to a var for the first time, in
442 442 which case we want to avoid any sort of automagic / autocall games.
443 443
444 444 This allows users to assign to either alias or magic names true python
445 445 variables (the magic/alias systems always take second seat to true
446 446 python code). E.g. ls='hi', or ls,that=1,2"""
447 447 if line_info.the_rest:
448 448 if line_info.the_rest[0] in '=,':
449 449 return self.prefilter_manager.get_handler_by_name('normal')
450 450 else:
451 451 return None
452 452
453 453
454 454 class AutoMagicChecker(PrefilterChecker):
455 455
456 456 priority = Integer(700).tag(config=True)
457 457
458 458 def check(self, line_info):
459 459 """If the ifun is magic, and automagic is on, run it. Note: normal,
460 460 non-auto magic would already have been triggered via '%' in
461 461 check_esc_chars. This just checks for automagic. Also, before
462 462 triggering the magic handler, make sure that there is nothing in the
463 463 user namespace which could shadow it."""
464 464 if not self.shell.automagic or not self.shell.find_magic(line_info.ifun):
465 465 return None
466 466
467 467 # We have a likely magic method. Make sure we should actually call it.
468 468 if line_info.continue_prompt and not self.prefilter_manager.multi_line_specials:
469 469 return None
470 470
471 471 head = line_info.ifun.split('.',1)[0]
472 472 if is_shadowed(head, self.shell):
473 473 return None
474 474
475 475 return self.prefilter_manager.get_handler_by_name('magic')
476 476
477 477
478 478 class PythonOpsChecker(PrefilterChecker):
479 479
480 480 priority = Integer(900).tag(config=True)
481 481
482 482 def check(self, line_info):
483 483 """If the 'rest' of the line begins with a function call or pretty much
484 484 any python operator, we should simply execute the line (regardless of
485 485 whether or not there's a possible autocall expansion). This avoids
486 486 spurious (and very confusing) geattr() accesses."""
487 487 if line_info.the_rest and line_info.the_rest[0] in '!=()<>,+*/%^&|':
488 488 return self.prefilter_manager.get_handler_by_name('normal')
489 489 else:
490 490 return None
491 491
492 492
493 493 class AutocallChecker(PrefilterChecker):
494 494
495 495 priority = Integer(1000).tag(config=True)
496 496
497 497 function_name_regexp = CRegExp(re_fun_name,
498 498 help="RegExp to identify potential function names."
499 499 ).tag(config=True)
500 500 exclude_regexp = CRegExp(re_exclude_auto,
501 501 help="RegExp to exclude strings with this start from autocalling."
502 502 ).tag(config=True)
503 503
504 504 def check(self, line_info):
505 505 "Check if the initial word/function is callable and autocall is on."
506 506 if not self.shell.autocall:
507 507 return None
508 508
509 509 oinfo = line_info.ofind(self.shell) # This can mutate state via getattr
510 510 if not oinfo['found']:
511 511 return None
512 512
513 513 ignored_funs = ['b', 'f', 'r', 'u', 'br', 'rb', 'fr', 'rf']
514 514 ifun = line_info.ifun
515 515 line = line_info.line
516 516 if ifun.lower() in ignored_funs and (line.startswith(ifun + "'") or line.startswith(ifun + '"')):
517 517 return None
518 518
519 519 if callable(oinfo['obj']) \
520 520 and (not self.exclude_regexp.match(line_info.the_rest)) \
521 521 and self.function_name_regexp.match(line_info.ifun):
522 522 return self.prefilter_manager.get_handler_by_name('auto')
523 523 else:
524 524 return None
525 525
526 526
527 527 #-----------------------------------------------------------------------------
528 528 # Prefilter handlers
529 529 #-----------------------------------------------------------------------------
530 530
531 531
532 532 class PrefilterHandler(Configurable):
533 533
534 534 handler_name = Unicode('normal')
535 535 esc_strings = List([])
536 536 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
537 537 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager', allow_none=True)
538 538
539 539 def __init__(self, shell=None, prefilter_manager=None, **kwargs):
540 540 super(PrefilterHandler, self).__init__(
541 541 shell=shell, prefilter_manager=prefilter_manager, **kwargs
542 542 )
543 543 self.prefilter_manager.register_handler(
544 544 self.handler_name,
545 545 self,
546 546 self.esc_strings
547 547 )
548 548
549 549 def handle(self, line_info):
550 550 # print "normal: ", line_info
551 551 """Handle normal input lines. Use as a template for handlers."""
552 552
553 553 # With autoindent on, we need some way to exit the input loop, and I
554 554 # don't want to force the user to have to backspace all the way to
555 555 # clear the line. The rule will be in this case, that either two
556 556 # lines of pure whitespace in a row, or a line of pure whitespace but
557 557 # of a size different to the indent level, will exit the input loop.
558 558 line = line_info.line
559 559 continue_prompt = line_info.continue_prompt
560 560
561 561 if (continue_prompt and
562 562 self.shell.autoindent and
563 563 line.isspace() and
564 564 0 < abs(len(line) - self.shell.indent_current_nsp) <= 2):
565 565 line = ''
566 566
567 567 return line
568 568
569 569 def __str__(self):
570 570 return "<%s(name=%s)>" % (self.__class__.__name__, self.handler_name)
571 571
572 572
573 573 class MacroHandler(PrefilterHandler):
574 574 handler_name = Unicode("macro")
575 575
576 576 def handle(self, line_info):
577 577 obj = self.shell.user_ns.get(line_info.ifun)
578 578 pre_space = line_info.pre_whitespace
579 579 line_sep = "\n" + pre_space
580 580 return pre_space + line_sep.join(obj.value.splitlines())
581 581
582 582
583 583 class MagicHandler(PrefilterHandler):
584 584
585 585 handler_name = Unicode('magic')
586 586 esc_strings = List([ESC_MAGIC])
587 587
588 588 def handle(self, line_info):
589 589 """Execute magic functions."""
590 590 ifun = line_info.ifun
591 591 the_rest = line_info.the_rest
592 592 #Prepare arguments for get_ipython().run_line_magic(magic_name, magic_args)
593 593 t_arg_s = ifun + " " + the_rest
594 594 t_magic_name, _, t_magic_arg_s = t_arg_s.partition(' ')
595 595 t_magic_name = t_magic_name.lstrip(ESC_MAGIC)
596 596 cmd = '%sget_ipython().run_line_magic(%r, %r)' % (line_info.pre_whitespace, t_magic_name, t_magic_arg_s)
597 597 return cmd
598 598
599 599
600 600 class AutoHandler(PrefilterHandler):
601 601
602 602 handler_name = Unicode('auto')
603 603 esc_strings = List([ESC_PAREN, ESC_QUOTE, ESC_QUOTE2])
604 604
605 605 def handle(self, line_info):
606 606 """Handle lines which can be auto-executed, quoting if requested."""
607 607 line = line_info.line
608 608 ifun = line_info.ifun
609 609 the_rest = line_info.the_rest
610 610 esc = line_info.esc
611 611 continue_prompt = line_info.continue_prompt
612 612 obj = line_info.ofind(self.shell)['obj']
613 613
614 614 # This should only be active for single-line input!
615 615 if continue_prompt:
616 616 return line
617 617
618 618 force_auto = isinstance(obj, IPyAutocall)
619 619
620 620 # User objects sometimes raise exceptions on attribute access other
621 621 # than AttributeError (we've seen it in the past), so it's safest to be
622 622 # ultra-conservative here and catch all.
623 623 try:
624 624 auto_rewrite = obj.rewrite
625 625 except Exception:
626 626 auto_rewrite = True
627 627
628 628 if esc == ESC_QUOTE:
629 629 # Auto-quote splitting on whitespace
630 630 newcmd = '%s("%s")' % (ifun,'", "'.join(the_rest.split()) )
631 631 elif esc == ESC_QUOTE2:
632 632 # Auto-quote whole string
633 633 newcmd = '%s("%s")' % (ifun,the_rest)
634 634 elif esc == ESC_PAREN:
635 635 newcmd = '%s(%s)' % (ifun,",".join(the_rest.split()))
636 636 else:
637 637 # Auto-paren.
638 638 if force_auto:
639 639 # Don't rewrite if it is already a call.
640 640 do_rewrite = not the_rest.startswith('(')
641 641 else:
642 642 if not the_rest:
643 643 # We only apply it to argument-less calls if the autocall
644 644 # parameter is set to 2.
645 645 do_rewrite = (self.shell.autocall >= 2)
646 646 elif the_rest.startswith('[') and hasattr(obj, '__getitem__'):
647 647 # Don't autocall in this case: item access for an object
648 648 # which is BOTH callable and implements __getitem__.
649 649 do_rewrite = False
650 650 else:
651 651 do_rewrite = True
652 652
653 653 # Figure out the rewritten command
654 654 if do_rewrite:
655 655 if the_rest.endswith(';'):
656 656 newcmd = '%s(%s);' % (ifun.rstrip(),the_rest[:-1])
657 657 else:
658 658 newcmd = '%s(%s)' % (ifun.rstrip(), the_rest)
659 659 else:
660 660 normal_handler = self.prefilter_manager.get_handler_by_name('normal')
661 661 return normal_handler.handle(line_info)
662 662
663 663 # Display the rewritten call
664 664 if auto_rewrite:
665 665 self.shell.auto_rewrite_input(newcmd)
666 666
667 667 return newcmd
668 668
669 669
670 670 class EmacsHandler(PrefilterHandler):
671 671
672 672 handler_name = Unicode('emacs')
673 673 esc_strings = List([])
674 674
675 675 def handle(self, line_info):
676 676 """Handle input lines marked by python-mode."""
677 677
678 678 # Currently, nothing is done. Later more functionality can be added
679 679 # here if needed.
680 680
681 681 # The input cache shouldn't be updated
682 682 return line_info.line
683 683
684 684
685 685 #-----------------------------------------------------------------------------
686 686 # Defaults
687 687 #-----------------------------------------------------------------------------
688 688
689 689
690 690 _default_transformers = [
691 691 ]
692 692
693 693 _default_checkers = [
694 694 EmacsChecker,
695 695 MacroChecker,
696 696 IPyAutocallChecker,
697 697 AssignmentChecker,
698 698 AutoMagicChecker,
699 699 PythonOpsChecker,
700 700 AutocallChecker
701 701 ]
702 702
703 703 _default_handlers = [
704 704 PrefilterHandler,
705 705 MacroHandler,
706 706 MagicHandler,
707 707 AutoHandler,
708 708 EmacsHandler
709 709 ]
@@ -1,103 +1,103 b''
1 1 from IPython.testing.tools import AssertPrints, AssertNotPrints
2 2
3 3 ip = get_ipython()
4 4
5 5 def test_output_displayed():
6 6 """Checking to make sure that output is displayed"""
7 7
8 8 with AssertPrints('2'):
9 9 ip.run_cell('1+1', store_history=True)
10 10
11 11 with AssertPrints('2'):
12 12 ip.run_cell('1+1 # comment with a semicolon;', store_history=True)
13 13
14 14 with AssertPrints('2'):
15 15 ip.run_cell('1+1\n#commented_out_function();', store_history=True)
16 16
17 17
18 18 def test_output_quiet():
19 19 """Checking to make sure that output is quiet"""
20 20
21 21 with AssertNotPrints('2'):
22 22 ip.run_cell('1+1;', store_history=True)
23 23
24 24 with AssertNotPrints('2'):
25 25 ip.run_cell('1+1; # comment with a semicolon', store_history=True)
26 26
27 27 with AssertNotPrints('2'):
28 28 ip.run_cell('1+1;\n#commented_out_function()', store_history=True)
29 29
30 30 def test_underscore_no_overrite_user():
31 31 ip.run_cell('_ = 42', store_history=True)
32 32 ip.run_cell('1+1', store_history=True)
33 33
34 34 with AssertPrints('42'):
35 35 ip.run_cell('print(_)', store_history=True)
36 36
37 37 ip.run_cell('del _', store_history=True)
38 38 ip.run_cell('6+6', store_history=True)
39 39 with AssertPrints('12'):
40 40 ip.run_cell('_', store_history=True)
41 41
42 42
43 43 def test_underscore_no_overrite_builtins():
44 44 ip.run_cell("import gettext ; gettext.install('foo')", store_history=True)
45 45 ip.run_cell('3+3', store_history=True)
46 46
47 47 with AssertPrints('gettext'):
48 48 ip.run_cell('print(_)', store_history=True)
49 49
50 50 ip.run_cell('_ = "userset"', store_history=True)
51 51
52 52 with AssertPrints('userset'):
53 53 ip.run_cell('print(_)', store_history=True)
54 54 ip.run_cell('import builtins; del builtins._')
55 55
56 56
57 57 def test_interactivehooks_ast_modes():
58 58 """
59 Test that ast nodes can be triggerd with different modes
59 Test that ast nodes can be triggered with different modes
60 60 """
61 61 saved_mode = ip.ast_node_interactivity
62 62 ip.ast_node_interactivity = 'last_expr_or_assign'
63 63
64 64 try:
65 65 with AssertPrints('2'):
66 66 ip.run_cell('a = 1+1', store_history=True)
67 67
68 68 with AssertPrints('9'):
69 69 ip.run_cell('b = 1+8 # comment with a semicolon;', store_history=False)
70 70
71 71 with AssertPrints('7'):
72 72 ip.run_cell('c = 1+6\n#commented_out_function();', store_history=True)
73 73
74 74 ip.run_cell('d = 11', store_history=True)
75 75 with AssertPrints('12'):
76 76 ip.run_cell('d += 1', store_history=True)
77 77
78 78 with AssertNotPrints('42'):
79 79 ip.run_cell('(u,v) = (41+1, 43-1)')
80 80
81 81 finally:
82 82 ip.ast_node_interactivity = saved_mode
83 83
84 84 def test_interactivehooks_ast_modes_semi_supress():
85 85 """
86 Test that ast nodes can be triggerd with different modes and supressed
86 Test that ast nodes can be triggered with different modes and suppressed
87 87 by semicolon
88 88 """
89 89 saved_mode = ip.ast_node_interactivity
90 90 ip.ast_node_interactivity = 'last_expr_or_assign'
91 91
92 92 try:
93 93 with AssertNotPrints('2'):
94 94 ip.run_cell('x = 1+1;', store_history=True)
95 95
96 96 with AssertNotPrints('7'):
97 97 ip.run_cell('y = 1+6; # comment with a semicolon', store_history=True)
98 98
99 99 with AssertNotPrints('9'):
100 100 ip.run_cell('z = 1+8;\n#commented_out_function()', store_history=True)
101 101
102 102 finally:
103 103 ip.ast_node_interactivity = saved_mode
@@ -1,1073 +1,1073 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Tests for various magic functions.
3 3
4 4 Needs to be run by nose (to make ipython session available).
5 5 """
6 6
7 7 import io
8 8 import os
9 9 import re
10 10 import sys
11 11 import warnings
12 12 from unittest import TestCase
13 13 from importlib import invalidate_caches
14 14 from io import StringIO
15 15
16 16 import nose.tools as nt
17 17
18 18 import shlex
19 19
20 20 from IPython import get_ipython
21 21 from IPython.core import magic
22 22 from IPython.core.error import UsageError
23 23 from IPython.core.magic import (Magics, magics_class, line_magic,
24 24 cell_magic,
25 25 register_line_magic, register_cell_magic)
26 26 from IPython.core.magics import execution, script, code, logging
27 27 from IPython.testing import decorators as dec
28 28 from IPython.testing import tools as tt
29 29 from IPython.utils import py3compat
30 30 from IPython.utils.io import capture_output
31 31 from IPython.utils.tempdir import TemporaryDirectory
32 32 from IPython.utils.process import find_cmd
33 33
34 34
35 35
36 36 _ip = get_ipython()
37 37
38 38 @magic.magics_class
39 39 class DummyMagics(magic.Magics): pass
40 40
41 41 def test_extract_code_ranges():
42 42 instr = "1 3 5-6 7-9 10:15 17: :10 10- -13 :"
43 43 expected = [(0, 1),
44 44 (2, 3),
45 45 (4, 6),
46 46 (6, 9),
47 47 (9, 14),
48 48 (16, None),
49 49 (None, 9),
50 50 (9, None),
51 51 (None, 13),
52 52 (None, None)]
53 53 actual = list(code.extract_code_ranges(instr))
54 54 nt.assert_equal(actual, expected)
55 55
56 56 def test_extract_symbols():
57 57 source = """import foo\na = 10\ndef b():\n return 42\n\n\nclass A: pass\n\n\n"""
58 58 symbols_args = ["a", "b", "A", "A,b", "A,a", "z"]
59 59 expected = [([], ['a']),
60 60 (["def b():\n return 42\n"], []),
61 61 (["class A: pass\n"], []),
62 62 (["class A: pass\n", "def b():\n return 42\n"], []),
63 63 (["class A: pass\n"], ['a']),
64 64 ([], ['z'])]
65 65 for symbols, exp in zip(symbols_args, expected):
66 66 nt.assert_equal(code.extract_symbols(source, symbols), exp)
67 67
68 68
69 69 def test_extract_symbols_raises_exception_with_non_python_code():
70 70 source = ("=begin A Ruby program :)=end\n"
71 71 "def hello\n"
72 72 "puts 'Hello world'\n"
73 73 "end")
74 74 with nt.assert_raises(SyntaxError):
75 75 code.extract_symbols(source, "hello")
76 76
77 77
78 78 def test_magic_not_found():
79 79 # magic not found raises UsageError
80 80 with nt.assert_raises(UsageError):
81 81 _ip.magic('doesntexist')
82 82
83 83 # ensure result isn't success when a magic isn't found
84 84 result = _ip.run_cell('%doesntexist')
85 85 assert isinstance(result.error_in_exec, UsageError)
86 86
87 87
88 88 def test_cell_magic_not_found():
89 89 # magic not found raises UsageError
90 90 with nt.assert_raises(UsageError):
91 91 _ip.run_cell_magic('doesntexist', 'line', 'cell')
92 92
93 93 # ensure result isn't success when a magic isn't found
94 94 result = _ip.run_cell('%%doesntexist')
95 95 assert isinstance(result.error_in_exec, UsageError)
96 96
97 97
98 98 def test_magic_error_status():
99 99 def fail(shell):
100 100 1/0
101 101 _ip.register_magic_function(fail)
102 102 result = _ip.run_cell('%fail')
103 103 assert isinstance(result.error_in_exec, ZeroDivisionError)
104 104
105 105
106 106 def test_config():
107 107 """ test that config magic does not raise
108 108 can happen if Configurable init is moved too early into
109 Magics.__init__ as then a Config object will be registerd as a
109 Magics.__init__ as then a Config object will be registered as a
110 110 magic.
111 111 """
112 112 ## should not raise.
113 113 _ip.magic('config')
114 114
115 115 def test_config_available_configs():
116 116 """ test that config magic prints available configs in unique and
117 117 sorted order. """
118 118 with capture_output() as captured:
119 119 _ip.magic('config')
120 120
121 121 stdout = captured.stdout
122 122 config_classes = stdout.strip().split('\n')[1:]
123 123 nt.assert_list_equal(config_classes, sorted(set(config_classes)))
124 124
125 125 def test_config_print_class():
126 126 """ test that config with a classname prints the class's options. """
127 127 with capture_output() as captured:
128 128 _ip.magic('config TerminalInteractiveShell')
129 129
130 130 stdout = captured.stdout
131 131 if not re.match("TerminalInteractiveShell.* options", stdout.splitlines()[0]):
132 132 print(stdout)
133 133 raise AssertionError("1st line of stdout not like "
134 134 "'TerminalInteractiveShell.* options'")
135 135
136 136 def test_rehashx():
137 137 # clear up everything
138 138 _ip.alias_manager.clear_aliases()
139 139 del _ip.db['syscmdlist']
140 140
141 141 _ip.magic('rehashx')
142 142 # Practically ALL ipython development systems will have more than 10 aliases
143 143
144 144 nt.assert_true(len(_ip.alias_manager.aliases) > 10)
145 145 for name, cmd in _ip.alias_manager.aliases:
146 146 # we must strip dots from alias names
147 147 nt.assert_not_in('.', name)
148 148
149 149 # rehashx must fill up syscmdlist
150 150 scoms = _ip.db['syscmdlist']
151 151 nt.assert_true(len(scoms) > 10)
152 152
153 153
154 154 def test_magic_parse_options():
155 155 """Test that we don't mangle paths when parsing magic options."""
156 156 ip = get_ipython()
157 157 path = 'c:\\x'
158 158 m = DummyMagics(ip)
159 159 opts = m.parse_options('-f %s' % path,'f:')[0]
160 160 # argv splitting is os-dependent
161 161 if os.name == 'posix':
162 162 expected = 'c:x'
163 163 else:
164 164 expected = path
165 165 nt.assert_equal(opts['f'], expected)
166 166
167 167 def test_magic_parse_long_options():
168 168 """Magic.parse_options can handle --foo=bar long options"""
169 169 ip = get_ipython()
170 170 m = DummyMagics(ip)
171 171 opts, _ = m.parse_options('--foo --bar=bubble', 'a', 'foo', 'bar=')
172 172 nt.assert_in('foo', opts)
173 173 nt.assert_in('bar', opts)
174 174 nt.assert_equal(opts['bar'], "bubble")
175 175
176 176
177 177 @dec.skip_without('sqlite3')
178 178 def doctest_hist_f():
179 179 """Test %hist -f with temporary filename.
180 180
181 181 In [9]: import tempfile
182 182
183 183 In [10]: tfile = tempfile.mktemp('.py','tmp-ipython-')
184 184
185 185 In [11]: %hist -nl -f $tfile 3
186 186
187 187 In [13]: import os; os.unlink(tfile)
188 188 """
189 189
190 190
191 191 @dec.skip_without('sqlite3')
192 192 def doctest_hist_r():
193 193 """Test %hist -r
194 194
195 195 XXX - This test is not recording the output correctly. For some reason, in
196 196 testing mode the raw history isn't getting populated. No idea why.
197 197 Disabling the output checking for now, though at least we do run it.
198 198
199 199 In [1]: 'hist' in _ip.lsmagic()
200 200 Out[1]: True
201 201
202 202 In [2]: x=1
203 203
204 204 In [3]: %hist -rl 2
205 205 x=1 # random
206 206 %hist -r 2
207 207 """
208 208
209 209
210 210 @dec.skip_without('sqlite3')
211 211 def doctest_hist_op():
212 212 """Test %hist -op
213 213
214 214 In [1]: class b(float):
215 215 ...: pass
216 216 ...:
217 217
218 218 In [2]: class s(object):
219 219 ...: def __str__(self):
220 220 ...: return 's'
221 221 ...:
222 222
223 223 In [3]:
224 224
225 225 In [4]: class r(b):
226 226 ...: def __repr__(self):
227 227 ...: return 'r'
228 228 ...:
229 229
230 230 In [5]: class sr(s,r): pass
231 231 ...:
232 232
233 233 In [6]:
234 234
235 235 In [7]: bb=b()
236 236
237 237 In [8]: ss=s()
238 238
239 239 In [9]: rr=r()
240 240
241 241 In [10]: ssrr=sr()
242 242
243 243 In [11]: 4.5
244 244 Out[11]: 4.5
245 245
246 246 In [12]: str(ss)
247 247 Out[12]: 's'
248 248
249 249 In [13]:
250 250
251 251 In [14]: %hist -op
252 252 >>> class b:
253 253 ... pass
254 254 ...
255 255 >>> class s(b):
256 256 ... def __str__(self):
257 257 ... return 's'
258 258 ...
259 259 >>>
260 260 >>> class r(b):
261 261 ... def __repr__(self):
262 262 ... return 'r'
263 263 ...
264 264 >>> class sr(s,r): pass
265 265 >>>
266 266 >>> bb=b()
267 267 >>> ss=s()
268 268 >>> rr=r()
269 269 >>> ssrr=sr()
270 270 >>> 4.5
271 271 4.5
272 272 >>> str(ss)
273 273 's'
274 274 >>>
275 275 """
276 276
277 277 def test_hist_pof():
278 278 ip = get_ipython()
279 279 ip.run_cell(u"1+2", store_history=True)
280 280 #raise Exception(ip.history_manager.session_number)
281 281 #raise Exception(list(ip.history_manager._get_range_session()))
282 282 with TemporaryDirectory() as td:
283 283 tf = os.path.join(td, 'hist.py')
284 284 ip.run_line_magic('history', '-pof %s' % tf)
285 285 assert os.path.isfile(tf)
286 286
287 287
288 288 @dec.skip_without('sqlite3')
289 289 def test_macro():
290 290 ip = get_ipython()
291 291 ip.history_manager.reset() # Clear any existing history.
292 292 cmds = ["a=1", "def b():\n return a**2", "print(a,b())"]
293 293 for i, cmd in enumerate(cmds, start=1):
294 294 ip.history_manager.store_inputs(i, cmd)
295 295 ip.magic("macro test 1-3")
296 296 nt.assert_equal(ip.user_ns["test"].value, "\n".join(cmds)+"\n")
297 297
298 298 # List macros
299 299 nt.assert_in("test", ip.magic("macro"))
300 300
301 301
302 302 @dec.skip_without('sqlite3')
303 303 def test_macro_run():
304 304 """Test that we can run a multi-line macro successfully."""
305 305 ip = get_ipython()
306 306 ip.history_manager.reset()
307 307 cmds = ["a=10", "a+=1", py3compat.doctest_refactor_print("print a"),
308 308 "%macro test 2-3"]
309 309 for cmd in cmds:
310 310 ip.run_cell(cmd, store_history=True)
311 311 nt.assert_equal(ip.user_ns["test"].value,
312 312 py3compat.doctest_refactor_print("a+=1\nprint a\n"))
313 313 with tt.AssertPrints("12"):
314 314 ip.run_cell("test")
315 315 with tt.AssertPrints("13"):
316 316 ip.run_cell("test")
317 317
318 318
319 319 def test_magic_magic():
320 320 """Test %magic"""
321 321 ip = get_ipython()
322 322 with capture_output() as captured:
323 323 ip.magic("magic")
324 324
325 325 stdout = captured.stdout
326 326 nt.assert_in('%magic', stdout)
327 327 nt.assert_in('IPython', stdout)
328 328 nt.assert_in('Available', stdout)
329 329
330 330
331 331 @dec.skipif_not_numpy
332 332 def test_numpy_reset_array_undec():
333 333 "Test '%reset array' functionality"
334 334 _ip.ex('import numpy as np')
335 335 _ip.ex('a = np.empty(2)')
336 336 nt.assert_in('a', _ip.user_ns)
337 337 _ip.magic('reset -f array')
338 338 nt.assert_not_in('a', _ip.user_ns)
339 339
340 340 def test_reset_out():
341 341 "Test '%reset out' magic"
342 342 _ip.run_cell("parrot = 'dead'", store_history=True)
343 343 # test '%reset -f out', make an Out prompt
344 344 _ip.run_cell("parrot", store_history=True)
345 345 nt.assert_true('dead' in [_ip.user_ns[x] for x in ('_','__','___')])
346 346 _ip.magic('reset -f out')
347 347 nt.assert_false('dead' in [_ip.user_ns[x] for x in ('_','__','___')])
348 348 nt.assert_equal(len(_ip.user_ns['Out']), 0)
349 349
350 350 def test_reset_in():
351 351 "Test '%reset in' magic"
352 352 # test '%reset -f in'
353 353 _ip.run_cell("parrot", store_history=True)
354 354 nt.assert_true('parrot' in [_ip.user_ns[x] for x in ('_i','_ii','_iii')])
355 355 _ip.magic('%reset -f in')
356 356 nt.assert_false('parrot' in [_ip.user_ns[x] for x in ('_i','_ii','_iii')])
357 357 nt.assert_equal(len(set(_ip.user_ns['In'])), 1)
358 358
359 359 def test_reset_dhist():
360 360 "Test '%reset dhist' magic"
361 361 _ip.run_cell("tmp = [d for d in _dh]") # copy before clearing
362 362 _ip.magic('cd ' + os.path.dirname(nt.__file__))
363 363 _ip.magic('cd -')
364 364 nt.assert_true(len(_ip.user_ns['_dh']) > 0)
365 365 _ip.magic('reset -f dhist')
366 366 nt.assert_equal(len(_ip.user_ns['_dh']), 0)
367 367 _ip.run_cell("_dh = [d for d in tmp]") #restore
368 368
369 369 def test_reset_in_length():
370 370 "Test that '%reset in' preserves In[] length"
371 371 _ip.run_cell("print 'foo'")
372 372 _ip.run_cell("reset -f in")
373 373 nt.assert_equal(len(_ip.user_ns['In']), _ip.displayhook.prompt_count+1)
374 374
375 375 def test_tb_syntaxerror():
376 376 """test %tb after a SyntaxError"""
377 377 ip = get_ipython()
378 378 ip.run_cell("for")
379 379
380 380 # trap and validate stdout
381 381 save_stdout = sys.stdout
382 382 try:
383 383 sys.stdout = StringIO()
384 384 ip.run_cell("%tb")
385 385 out = sys.stdout.getvalue()
386 386 finally:
387 387 sys.stdout = save_stdout
388 388 # trim output, and only check the last line
389 389 last_line = out.rstrip().splitlines()[-1].strip()
390 390 nt.assert_equal(last_line, "SyntaxError: invalid syntax")
391 391
392 392
393 393 def test_time():
394 394 ip = get_ipython()
395 395
396 396 with tt.AssertPrints("Wall time: "):
397 397 ip.run_cell("%time None")
398 398
399 399 ip.run_cell("def f(kmjy):\n"
400 400 " %time print (2*kmjy)")
401 401
402 402 with tt.AssertPrints("Wall time: "):
403 403 with tt.AssertPrints("hihi", suppress=False):
404 404 ip.run_cell("f('hi')")
405 405
406 406
407 407 @dec.skip_win32
408 408 def test_time2():
409 409 ip = get_ipython()
410 410
411 411 with tt.AssertPrints("CPU times: user "):
412 412 ip.run_cell("%time None")
413 413
414 414 def test_time3():
415 415 """Erroneous magic function calls, issue gh-3334"""
416 416 ip = get_ipython()
417 417 ip.user_ns.pop('run', None)
418 418
419 419 with tt.AssertNotPrints("not found", channel='stderr'):
420 420 ip.run_cell("%%time\n"
421 421 "run = 0\n"
422 422 "run += 1")
423 423
424 424 def test_doctest_mode():
425 425 "Toggle doctest_mode twice, it should be a no-op and run without error"
426 426 _ip.magic('doctest_mode')
427 427 _ip.magic('doctest_mode')
428 428
429 429
430 430 def test_parse_options():
431 431 """Tests for basic options parsing in magics."""
432 432 # These are only the most minimal of tests, more should be added later. At
433 433 # the very least we check that basic text/unicode calls work OK.
434 434 m = DummyMagics(_ip)
435 435 nt.assert_equal(m.parse_options('foo', '')[1], 'foo')
436 436 nt.assert_equal(m.parse_options(u'foo', '')[1], u'foo')
437 437
438 438
439 439 def test_dirops():
440 440 """Test various directory handling operations."""
441 441 # curpath = lambda :os.path.splitdrive(os.getcwd())[1].replace('\\','/')
442 442 curpath = os.getcwd
443 443 startdir = os.getcwd()
444 444 ipdir = os.path.realpath(_ip.ipython_dir)
445 445 try:
446 446 _ip.magic('cd "%s"' % ipdir)
447 447 nt.assert_equal(curpath(), ipdir)
448 448 _ip.magic('cd -')
449 449 nt.assert_equal(curpath(), startdir)
450 450 _ip.magic('pushd "%s"' % ipdir)
451 451 nt.assert_equal(curpath(), ipdir)
452 452 _ip.magic('popd')
453 453 nt.assert_equal(curpath(), startdir)
454 454 finally:
455 455 os.chdir(startdir)
456 456
457 457
458 458 def test_xmode():
459 459 # Calling xmode three times should be a no-op
460 460 xmode = _ip.InteractiveTB.mode
461 461 for i in range(3):
462 462 _ip.magic("xmode")
463 463 nt.assert_equal(_ip.InteractiveTB.mode, xmode)
464 464
465 465 def test_reset_hard():
466 466 monitor = []
467 467 class A(object):
468 468 def __del__(self):
469 469 monitor.append(1)
470 470 def __repr__(self):
471 471 return "<A instance>"
472 472
473 473 _ip.user_ns["a"] = A()
474 474 _ip.run_cell("a")
475 475
476 476 nt.assert_equal(monitor, [])
477 477 _ip.magic("reset -f")
478 478 nt.assert_equal(monitor, [1])
479 479
480 480 class TestXdel(tt.TempFileMixin):
481 481 def test_xdel(self):
482 482 """Test that references from %run are cleared by xdel."""
483 483 src = ("class A(object):\n"
484 484 " monitor = []\n"
485 485 " def __del__(self):\n"
486 486 " self.monitor.append(1)\n"
487 487 "a = A()\n")
488 488 self.mktmp(src)
489 489 # %run creates some hidden references...
490 490 _ip.magic("run %s" % self.fname)
491 491 # ... as does the displayhook.
492 492 _ip.run_cell("a")
493 493
494 494 monitor = _ip.user_ns["A"].monitor
495 495 nt.assert_equal(monitor, [])
496 496
497 497 _ip.magic("xdel a")
498 498
499 499 # Check that a's __del__ method has been called.
500 500 nt.assert_equal(monitor, [1])
501 501
502 502 def doctest_who():
503 503 """doctest for %who
504 504
505 505 In [1]: %reset -f
506 506
507 507 In [2]: alpha = 123
508 508
509 509 In [3]: beta = 'beta'
510 510
511 511 In [4]: %who int
512 512 alpha
513 513
514 514 In [5]: %who str
515 515 beta
516 516
517 517 In [6]: %whos
518 518 Variable Type Data/Info
519 519 ----------------------------
520 520 alpha int 123
521 521 beta str beta
522 522
523 523 In [7]: %who_ls
524 524 Out[7]: ['alpha', 'beta']
525 525 """
526 526
527 527 def test_whos():
528 528 """Check that whos is protected against objects where repr() fails."""
529 529 class A(object):
530 530 def __repr__(self):
531 531 raise Exception()
532 532 _ip.user_ns['a'] = A()
533 533 _ip.magic("whos")
534 534
535 535 @py3compat.u_format
536 536 def doctest_precision():
537 537 """doctest for %precision
538 538
539 539 In [1]: f = get_ipython().display_formatter.formatters['text/plain']
540 540
541 541 In [2]: %precision 5
542 542 Out[2]: '%.5f'
543 543
544 544 In [3]: f.float_format
545 545 Out[3]: '%.5f'
546 546
547 547 In [4]: %precision %e
548 548 Out[4]: '%e'
549 549
550 550 In [5]: f(3.1415927)
551 551 Out[5]: '3.141593e+00'
552 552 """
553 553
554 554 def test_psearch():
555 555 with tt.AssertPrints("dict.fromkeys"):
556 556 _ip.run_cell("dict.fr*?")
557 557
558 558 def test_timeit_shlex():
559 559 """test shlex issues with timeit (#1109)"""
560 560 _ip.ex("def f(*a,**kw): pass")
561 561 _ip.magic('timeit -n1 "this is a bug".count(" ")')
562 562 _ip.magic('timeit -r1 -n1 f(" ", 1)')
563 563 _ip.magic('timeit -r1 -n1 f(" ", 1, " ", 2, " ")')
564 564 _ip.magic('timeit -r1 -n1 ("a " + "b")')
565 565 _ip.magic('timeit -r1 -n1 f("a " + "b")')
566 566 _ip.magic('timeit -r1 -n1 f("a " + "b ")')
567 567
568 568
569 569 def test_timeit_arguments():
570 570 "Test valid timeit arguments, should not cause SyntaxError (GH #1269)"
571 571 _ip.magic("timeit ('#')")
572 572
573 573
574 574 def test_timeit_special_syntax():
575 575 "Test %%timeit with IPython special syntax"
576 576 @register_line_magic
577 577 def lmagic(line):
578 578 ip = get_ipython()
579 579 ip.user_ns['lmagic_out'] = line
580 580
581 581 # line mode test
582 582 _ip.run_line_magic('timeit', '-n1 -r1 %lmagic my line')
583 583 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line')
584 584 # cell mode test
585 585 _ip.run_cell_magic('timeit', '-n1 -r1', '%lmagic my line2')
586 586 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line2')
587 587
588 588 def test_timeit_return():
589 589 """
590 test wether timeit -o return object
590 test whether timeit -o return object
591 591 """
592 592
593 593 res = _ip.run_line_magic('timeit','-n10 -r10 -o 1')
594 594 assert(res is not None)
595 595
596 596 def test_timeit_quiet():
597 597 """
598 598 test quiet option of timeit magic
599 599 """
600 600 with tt.AssertNotPrints("loops"):
601 601 _ip.run_cell("%timeit -n1 -r1 -q 1")
602 602
603 603 def test_timeit_return_quiet():
604 604 with tt.AssertNotPrints("loops"):
605 605 res = _ip.run_line_magic('timeit', '-n1 -r1 -q -o 1')
606 606 assert (res is not None)
607 607
608 608 def test_timeit_invalid_return():
609 609 with nt.assert_raises_regex(SyntaxError, "outside function"):
610 610 _ip.run_line_magic('timeit', 'return')
611 611
612 612 @dec.skipif(execution.profile is None)
613 613 def test_prun_special_syntax():
614 614 "Test %%prun with IPython special syntax"
615 615 @register_line_magic
616 616 def lmagic(line):
617 617 ip = get_ipython()
618 618 ip.user_ns['lmagic_out'] = line
619 619
620 620 # line mode test
621 621 _ip.run_line_magic('prun', '-q %lmagic my line')
622 622 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line')
623 623 # cell mode test
624 624 _ip.run_cell_magic('prun', '-q', '%lmagic my line2')
625 625 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line2')
626 626
627 627 @dec.skipif(execution.profile is None)
628 628 def test_prun_quotes():
629 629 "Test that prun does not clobber string escapes (GH #1302)"
630 630 _ip.magic(r"prun -q x = '\t'")
631 631 nt.assert_equal(_ip.user_ns['x'], '\t')
632 632
633 633 def test_extension():
634 634 # Debugging information for failures of this test
635 635 print('sys.path:')
636 636 for p in sys.path:
637 637 print(' ', p)
638 638 print('CWD', os.getcwd())
639 639
640 640 nt.assert_raises(ImportError, _ip.magic, "load_ext daft_extension")
641 641 daft_path = os.path.join(os.path.dirname(__file__), "daft_extension")
642 642 sys.path.insert(0, daft_path)
643 643 try:
644 644 _ip.user_ns.pop('arq', None)
645 645 invalidate_caches() # Clear import caches
646 646 _ip.magic("load_ext daft_extension")
647 647 nt.assert_equal(_ip.user_ns['arq'], 185)
648 648 _ip.magic("unload_ext daft_extension")
649 649 assert 'arq' not in _ip.user_ns
650 650 finally:
651 651 sys.path.remove(daft_path)
652 652
653 653
654 654 def test_notebook_export_json():
655 655 _ip = get_ipython()
656 656 _ip.history_manager.reset() # Clear any existing history.
657 657 cmds = [u"a=1", u"def b():\n return a**2", u"print('noël, été', b())"]
658 658 for i, cmd in enumerate(cmds, start=1):
659 659 _ip.history_manager.store_inputs(i, cmd)
660 660 with TemporaryDirectory() as td:
661 661 outfile = os.path.join(td, "nb.ipynb")
662 662 _ip.magic("notebook -e %s" % outfile)
663 663
664 664
665 665 class TestEnv(TestCase):
666 666
667 667 def test_env(self):
668 668 env = _ip.magic("env")
669 669 self.assertTrue(isinstance(env, dict))
670 670
671 671 def test_env_get_set_simple(self):
672 672 env = _ip.magic("env var val1")
673 673 self.assertEqual(env, None)
674 674 self.assertEqual(os.environ['var'], 'val1')
675 675 self.assertEqual(_ip.magic("env var"), 'val1')
676 676 env = _ip.magic("env var=val2")
677 677 self.assertEqual(env, None)
678 678 self.assertEqual(os.environ['var'], 'val2')
679 679
680 680 def test_env_get_set_complex(self):
681 681 env = _ip.magic("env var 'val1 '' 'val2")
682 682 self.assertEqual(env, None)
683 683 self.assertEqual(os.environ['var'], "'val1 '' 'val2")
684 684 self.assertEqual(_ip.magic("env var"), "'val1 '' 'val2")
685 685 env = _ip.magic('env var=val2 val3="val4')
686 686 self.assertEqual(env, None)
687 687 self.assertEqual(os.environ['var'], 'val2 val3="val4')
688 688
689 689 def test_env_set_bad_input(self):
690 690 self.assertRaises(UsageError, lambda: _ip.magic("set_env var"))
691 691
692 692 def test_env_set_whitespace(self):
693 693 self.assertRaises(UsageError, lambda: _ip.magic("env var A=B"))
694 694
695 695
696 696 class CellMagicTestCase(TestCase):
697 697
698 698 def check_ident(self, magic):
699 699 # Manually called, we get the result
700 700 out = _ip.run_cell_magic(magic, 'a', 'b')
701 701 nt.assert_equal(out, ('a','b'))
702 702 # Via run_cell, it goes into the user's namespace via displayhook
703 703 _ip.run_cell('%%' + magic +' c\nd')
704 704 nt.assert_equal(_ip.user_ns['_'], ('c','d'))
705 705
706 706 def test_cell_magic_func_deco(self):
707 707 "Cell magic using simple decorator"
708 708 @register_cell_magic
709 709 def cellm(line, cell):
710 710 return line, cell
711 711
712 712 self.check_ident('cellm')
713 713
714 714 def test_cell_magic_reg(self):
715 715 "Cell magic manually registered"
716 716 def cellm(line, cell):
717 717 return line, cell
718 718
719 719 _ip.register_magic_function(cellm, 'cell', 'cellm2')
720 720 self.check_ident('cellm2')
721 721
722 722 def test_cell_magic_class(self):
723 723 "Cell magics declared via a class"
724 724 @magics_class
725 725 class MyMagics(Magics):
726 726
727 727 @cell_magic
728 728 def cellm3(self, line, cell):
729 729 return line, cell
730 730
731 731 _ip.register_magics(MyMagics)
732 732 self.check_ident('cellm3')
733 733
734 734 def test_cell_magic_class2(self):
735 735 "Cell magics declared via a class, #2"
736 736 @magics_class
737 737 class MyMagics2(Magics):
738 738
739 739 @cell_magic('cellm4')
740 740 def cellm33(self, line, cell):
741 741 return line, cell
742 742
743 743 _ip.register_magics(MyMagics2)
744 744 self.check_ident('cellm4')
745 745 # Check that nothing is registered as 'cellm33'
746 746 c33 = _ip.find_cell_magic('cellm33')
747 747 nt.assert_equal(c33, None)
748 748
749 749 def test_file():
750 750 """Basic %%file"""
751 751 ip = get_ipython()
752 752 with TemporaryDirectory() as td:
753 753 fname = os.path.join(td, 'file1')
754 754 ip.run_cell_magic("file", fname, u'\n'.join([
755 755 'line1',
756 756 'line2',
757 757 ]))
758 758 with open(fname) as f:
759 759 s = f.read()
760 760 nt.assert_in('line1\n', s)
761 761 nt.assert_in('line2', s)
762 762
763 763 def test_file_var_expand():
764 764 """%%file $filename"""
765 765 ip = get_ipython()
766 766 with TemporaryDirectory() as td:
767 767 fname = os.path.join(td, 'file1')
768 768 ip.user_ns['filename'] = fname
769 769 ip.run_cell_magic("file", '$filename', u'\n'.join([
770 770 'line1',
771 771 'line2',
772 772 ]))
773 773 with open(fname) as f:
774 774 s = f.read()
775 775 nt.assert_in('line1\n', s)
776 776 nt.assert_in('line2', s)
777 777
778 778 def test_file_unicode():
779 779 """%%file with unicode cell"""
780 780 ip = get_ipython()
781 781 with TemporaryDirectory() as td:
782 782 fname = os.path.join(td, 'file1')
783 783 ip.run_cell_magic("file", fname, u'\n'.join([
784 784 u'liné1',
785 785 u'liné2',
786 786 ]))
787 787 with io.open(fname, encoding='utf-8') as f:
788 788 s = f.read()
789 789 nt.assert_in(u'liné1\n', s)
790 790 nt.assert_in(u'liné2', s)
791 791
792 792 def test_file_amend():
793 793 """%%file -a amends files"""
794 794 ip = get_ipython()
795 795 with TemporaryDirectory() as td:
796 796 fname = os.path.join(td, 'file2')
797 797 ip.run_cell_magic("file", fname, u'\n'.join([
798 798 'line1',
799 799 'line2',
800 800 ]))
801 801 ip.run_cell_magic("file", "-a %s" % fname, u'\n'.join([
802 802 'line3',
803 803 'line4',
804 804 ]))
805 805 with open(fname) as f:
806 806 s = f.read()
807 807 nt.assert_in('line1\n', s)
808 808 nt.assert_in('line3\n', s)
809 809
810 810
811 811 def test_script_config():
812 812 ip = get_ipython()
813 813 ip.config.ScriptMagics.script_magics = ['whoda']
814 814 sm = script.ScriptMagics(shell=ip)
815 815 nt.assert_in('whoda', sm.magics['cell'])
816 816
817 817 @dec.skip_win32
818 818 def test_script_out():
819 819 ip = get_ipython()
820 820 ip.run_cell_magic("script", "--out output sh", "echo 'hi'")
821 821 nt.assert_equal(ip.user_ns['output'], 'hi\n')
822 822
823 823 @dec.skip_win32
824 824 def test_script_err():
825 825 ip = get_ipython()
826 826 ip.run_cell_magic("script", "--err error sh", "echo 'hello' >&2")
827 827 nt.assert_equal(ip.user_ns['error'], 'hello\n')
828 828
829 829 @dec.skip_win32
830 830 def test_script_out_err():
831 831 ip = get_ipython()
832 832 ip.run_cell_magic("script", "--out output --err error sh", "echo 'hi'\necho 'hello' >&2")
833 833 nt.assert_equal(ip.user_ns['output'], 'hi\n')
834 834 nt.assert_equal(ip.user_ns['error'], 'hello\n')
835 835
836 836 @dec.skip_win32
837 837 def test_script_bg_out():
838 838 ip = get_ipython()
839 839 ip.run_cell_magic("script", "--bg --out output sh", "echo 'hi'")
840 840 nt.assert_equal(ip.user_ns['output'].read(), b'hi\n')
841 841
842 842 @dec.skip_win32
843 843 def test_script_bg_err():
844 844 ip = get_ipython()
845 845 ip.run_cell_magic("script", "--bg --err error sh", "echo 'hello' >&2")
846 846 nt.assert_equal(ip.user_ns['error'].read(), b'hello\n')
847 847
848 848 @dec.skip_win32
849 849 def test_script_bg_out_err():
850 850 ip = get_ipython()
851 851 ip.run_cell_magic("script", "--bg --out output --err error sh", "echo 'hi'\necho 'hello' >&2")
852 852 nt.assert_equal(ip.user_ns['output'].read(), b'hi\n')
853 853 nt.assert_equal(ip.user_ns['error'].read(), b'hello\n')
854 854
855 855 def test_script_defaults():
856 856 ip = get_ipython()
857 857 for cmd in ['sh', 'bash', 'perl', 'ruby']:
858 858 try:
859 859 find_cmd(cmd)
860 860 except Exception:
861 861 pass
862 862 else:
863 863 nt.assert_in(cmd, ip.magics_manager.magics['cell'])
864 864
865 865
866 866 @magics_class
867 867 class FooFoo(Magics):
868 868 """class with both %foo and %%foo magics"""
869 869 @line_magic('foo')
870 870 def line_foo(self, line):
871 871 "I am line foo"
872 872 pass
873 873
874 874 @cell_magic("foo")
875 875 def cell_foo(self, line, cell):
876 876 "I am cell foo, not line foo"
877 877 pass
878 878
879 879 def test_line_cell_info():
880 880 """%%foo and %foo magics are distinguishable to inspect"""
881 881 ip = get_ipython()
882 882 ip.magics_manager.register(FooFoo)
883 883 oinfo = ip.object_inspect('foo')
884 884 nt.assert_true(oinfo['found'])
885 885 nt.assert_true(oinfo['ismagic'])
886 886
887 887 oinfo = ip.object_inspect('%%foo')
888 888 nt.assert_true(oinfo['found'])
889 889 nt.assert_true(oinfo['ismagic'])
890 890 nt.assert_equal(oinfo['docstring'], FooFoo.cell_foo.__doc__)
891 891
892 892 oinfo = ip.object_inspect('%foo')
893 893 nt.assert_true(oinfo['found'])
894 894 nt.assert_true(oinfo['ismagic'])
895 895 nt.assert_equal(oinfo['docstring'], FooFoo.line_foo.__doc__)
896 896
897 897 def test_multiple_magics():
898 898 ip = get_ipython()
899 899 foo1 = FooFoo(ip)
900 900 foo2 = FooFoo(ip)
901 901 mm = ip.magics_manager
902 902 mm.register(foo1)
903 903 nt.assert_true(mm.magics['line']['foo'].__self__ is foo1)
904 904 mm.register(foo2)
905 905 nt.assert_true(mm.magics['line']['foo'].__self__ is foo2)
906 906
907 907 def test_alias_magic():
908 908 """Test %alias_magic."""
909 909 ip = get_ipython()
910 910 mm = ip.magics_manager
911 911
912 912 # Basic operation: both cell and line magics are created, if possible.
913 913 ip.run_line_magic('alias_magic', 'timeit_alias timeit')
914 914 nt.assert_in('timeit_alias', mm.magics['line'])
915 915 nt.assert_in('timeit_alias', mm.magics['cell'])
916 916
917 917 # --cell is specified, line magic not created.
918 918 ip.run_line_magic('alias_magic', '--cell timeit_cell_alias timeit')
919 919 nt.assert_not_in('timeit_cell_alias', mm.magics['line'])
920 920 nt.assert_in('timeit_cell_alias', mm.magics['cell'])
921 921
922 922 # Test that line alias is created successfully.
923 923 ip.run_line_magic('alias_magic', '--line env_alias env')
924 924 nt.assert_equal(ip.run_line_magic('env', ''),
925 925 ip.run_line_magic('env_alias', ''))
926 926
927 927 # Test that line alias with parameters passed in is created successfully.
928 928 ip.run_line_magic('alias_magic', '--line history_alias history --params ' + shlex.quote('3'))
929 929 nt.assert_in('history_alias', mm.magics['line'])
930 930
931 931
932 932 def test_save():
933 933 """Test %save."""
934 934 ip = get_ipython()
935 935 ip.history_manager.reset() # Clear any existing history.
936 936 cmds = [u"a=1", u"def b():\n return a**2", u"print(a, b())"]
937 937 for i, cmd in enumerate(cmds, start=1):
938 938 ip.history_manager.store_inputs(i, cmd)
939 939 with TemporaryDirectory() as tmpdir:
940 940 file = os.path.join(tmpdir, "testsave.py")
941 941 ip.run_line_magic("save", "%s 1-10" % file)
942 942 with open(file) as f:
943 943 content = f.read()
944 944 nt.assert_equal(content.count(cmds[0]), 1)
945 945 nt.assert_in('coding: utf-8', content)
946 946 ip.run_line_magic("save", "-a %s 1-10" % file)
947 947 with open(file) as f:
948 948 content = f.read()
949 949 nt.assert_equal(content.count(cmds[0]), 2)
950 950 nt.assert_in('coding: utf-8', content)
951 951
952 952
953 953 def test_store():
954 954 """Test %store."""
955 955 ip = get_ipython()
956 956 ip.run_line_magic('load_ext', 'storemagic')
957 957
958 958 # make sure the storage is empty
959 959 ip.run_line_magic('store', '-z')
960 960 ip.user_ns['var'] = 42
961 961 ip.run_line_magic('store', 'var')
962 962 ip.user_ns['var'] = 39
963 963 ip.run_line_magic('store', '-r')
964 964 nt.assert_equal(ip.user_ns['var'], 42)
965 965
966 966 ip.run_line_magic('store', '-d var')
967 967 ip.user_ns['var'] = 39
968 968 ip.run_line_magic('store' , '-r')
969 969 nt.assert_equal(ip.user_ns['var'], 39)
970 970
971 971
972 972 def _run_edit_test(arg_s, exp_filename=None,
973 973 exp_lineno=-1,
974 974 exp_contents=None,
975 975 exp_is_temp=None):
976 976 ip = get_ipython()
977 977 M = code.CodeMagics(ip)
978 978 last_call = ['','']
979 979 opts,args = M.parse_options(arg_s,'prxn:')
980 980 filename, lineno, is_temp = M._find_edit_target(ip, args, opts, last_call)
981 981
982 982 if exp_filename is not None:
983 983 nt.assert_equal(exp_filename, filename)
984 984 if exp_contents is not None:
985 985 with io.open(filename, 'r', encoding='utf-8') as f:
986 986 contents = f.read()
987 987 nt.assert_equal(exp_contents, contents)
988 988 if exp_lineno != -1:
989 989 nt.assert_equal(exp_lineno, lineno)
990 990 if exp_is_temp is not None:
991 991 nt.assert_equal(exp_is_temp, is_temp)
992 992
993 993
994 994 def test_edit_interactive():
995 995 """%edit on interactively defined objects"""
996 996 ip = get_ipython()
997 997 n = ip.execution_count
998 998 ip.run_cell(u"def foo(): return 1", store_history=True)
999 999
1000 1000 try:
1001 1001 _run_edit_test("foo")
1002 1002 except code.InteractivelyDefined as e:
1003 1003 nt.assert_equal(e.index, n)
1004 1004 else:
1005 1005 raise AssertionError("Should have raised InteractivelyDefined")
1006 1006
1007 1007
1008 1008 def test_edit_cell():
1009 1009 """%edit [cell id]"""
1010 1010 ip = get_ipython()
1011 1011
1012 1012 ip.run_cell(u"def foo(): return 1", store_history=True)
1013 1013
1014 1014 # test
1015 1015 _run_edit_test("1", exp_contents=ip.user_ns['In'][1], exp_is_temp=True)
1016 1016
1017 1017 def test_bookmark():
1018 1018 ip = get_ipython()
1019 1019 ip.run_line_magic('bookmark', 'bmname')
1020 1020 with tt.AssertPrints('bmname'):
1021 1021 ip.run_line_magic('bookmark', '-l')
1022 1022 ip.run_line_magic('bookmark', '-d bmname')
1023 1023
1024 1024 def test_ls_magic():
1025 1025 ip = get_ipython()
1026 1026 json_formatter = ip.display_formatter.formatters['application/json']
1027 1027 json_formatter.enabled = True
1028 1028 lsmagic = ip.magic('lsmagic')
1029 1029 with warnings.catch_warnings(record=True) as w:
1030 1030 j = json_formatter(lsmagic)
1031 1031 nt.assert_equal(sorted(j), ['cell', 'line'])
1032 1032 nt.assert_equal(w, []) # no warnings
1033 1033
1034 1034 def test_strip_initial_indent():
1035 1035 def sii(s):
1036 1036 lines = s.splitlines()
1037 1037 return '\n'.join(code.strip_initial_indent(lines))
1038 1038
1039 1039 nt.assert_equal(sii(" a = 1\nb = 2"), "a = 1\nb = 2")
1040 1040 nt.assert_equal(sii(" a\n b\nc"), "a\n b\nc")
1041 1041 nt.assert_equal(sii("a\n b"), "a\n b")
1042 1042
1043 1043 def test_logging_magic_quiet_from_arg():
1044 1044 _ip.config.LoggingMagics.quiet = False
1045 1045 lm = logging.LoggingMagics(shell=_ip)
1046 1046 with TemporaryDirectory() as td:
1047 1047 try:
1048 1048 with tt.AssertNotPrints(re.compile("Activating.*")):
1049 1049 lm.logstart('-q {}'.format(
1050 1050 os.path.join(td, "quiet_from_arg.log")))
1051 1051 finally:
1052 1052 _ip.logger.logstop()
1053 1053
1054 1054 def test_logging_magic_quiet_from_config():
1055 1055 _ip.config.LoggingMagics.quiet = True
1056 1056 lm = logging.LoggingMagics(shell=_ip)
1057 1057 with TemporaryDirectory() as td:
1058 1058 try:
1059 1059 with tt.AssertNotPrints(re.compile("Activating.*")):
1060 1060 lm.logstart(os.path.join(td, "quiet_from_config.log"))
1061 1061 finally:
1062 1062 _ip.logger.logstop()
1063 1063
1064 1064 def test_logging_magic_not_quiet():
1065 1065 _ip.config.LoggingMagics.quiet = False
1066 1066 lm = logging.LoggingMagics(shell=_ip)
1067 1067 with TemporaryDirectory() as td:
1068 1068 try:
1069 1069 with tt.AssertPrints(re.compile("Activating.*")):
1070 1070 lm.logstart(os.path.join(td, "not_quiet.log"))
1071 1071 finally:
1072 1072 _ip.logger.logstop()
1073 1073
@@ -1,348 +1,348 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Usage information for the main IPython applications.
3 3 """
4 4 #-----------------------------------------------------------------------------
5 5 # Copyright (C) 2008-2011 The IPython Development Team
6 6 # Copyright (C) 2001-2007 Fernando Perez. <fperez@colorado.edu>
7 7 #
8 8 # Distributed under the terms of the BSD License. The full license is in
9 9 # the file COPYING, distributed as part of this software.
10 10 #-----------------------------------------------------------------------------
11 11
12 12 import sys
13 13 from IPython.core import release
14 14
15 15 cl_usage = """\
16 16 =========
17 17 IPython
18 18 =========
19 19
20 20 Tools for Interactive Computing in Python
21 21 =========================================
22 22
23 23 A Python shell with automatic history (input and output), dynamic object
24 24 introspection, easier configuration, command completion, access to the
25 25 system shell and more. IPython can also be embedded in running programs.
26 26
27 27
28 28 Usage
29 29
30 30 ipython [subcommand] [options] [-c cmd | -m mod | file] [--] [arg] ...
31 31
32 32 If invoked with no options, it executes the file and exits, passing the
33 33 remaining arguments to the script, just as if you had specified the same
34 34 command with python. You may need to specify `--` before args to be passed
35 35 to the script, to prevent IPython from attempting to parse them. If you
36 36 specify the option `-i` before the filename, it will enter an interactive
37 37 IPython session after running the script, rather than exiting. Files ending
38 38 in .py will be treated as normal Python, but files ending in .ipy can
39 39 contain special IPython syntax (magic commands, shell expansions, etc.).
40 40
41 41 Almost all configuration in IPython is available via the command-line. Do
42 42 `ipython --help-all` to see all available options. For persistent
43 43 configuration, look into your `ipython_config.py` configuration file for
44 44 details.
45 45
46 46 This file is typically installed in the `IPYTHONDIR` directory, and there
47 47 is a separate configuration directory for each profile. The default profile
48 48 directory will be located in $IPYTHONDIR/profile_default. IPYTHONDIR
49 49 defaults to to `$HOME/.ipython`. For Windows users, $HOME resolves to
50 50 C:\\Users\\YourUserName in most instances.
51 51
52 52 To initialize a profile with the default configuration file, do::
53 53
54 54 $> ipython profile create
55 55
56 56 and start editing `IPYTHONDIR/profile_default/ipython_config.py`
57 57
58 58 In IPython's documentation, we will refer to this directory as
59 59 `IPYTHONDIR`, you can change its default location by creating an
60 60 environment variable with this name and setting it to the desired path.
61 61
62 62 For more information, see the manual available in HTML and PDF in your
63 63 installation, or online at http://ipython.org/documentation.html.
64 64 """
65 65
66 66 interactive_usage = """
67 67 IPython -- An enhanced Interactive Python
68 68 =========================================
69 69
70 70 IPython offers a fully compatible replacement for the standard Python
71 71 interpreter, with convenient shell features, special commands, command
72 72 history mechanism and output results caching.
73 73
74 74 At your system command line, type 'ipython -h' to see the command line
75 75 options available. This document only describes interactive features.
76 76
77 77 GETTING HELP
78 78 ------------
79 79
80 80 Within IPython you have various way to access help:
81 81
82 82 ? -> Introduction and overview of IPython's features (this screen).
83 83 object? -> Details about 'object'.
84 84 object?? -> More detailed, verbose information about 'object'.
85 85 %quickref -> Quick reference of all IPython specific syntax and magics.
86 86 help -> Access Python's own help system.
87 87
88 88 If you are in terminal IPython you can quit this screen by pressing `q`.
89 89
90 90
91 91 MAIN FEATURES
92 92 -------------
93 93
94 94 * Access to the standard Python help with object docstrings and the Python
95 95 manuals. Simply type 'help' (no quotes) to invoke it.
96 96
97 97 * Magic commands: type %magic for information on the magic subsystem.
98 98
99 99 * System command aliases, via the %alias command or the configuration file(s).
100 100
101 101 * Dynamic object information:
102 102
103 103 Typing ?word or word? prints detailed information about an object. Certain
104 104 long strings (code, etc.) get snipped in the center for brevity.
105 105
106 106 Typing ??word or word?? gives access to the full information without
107 107 snipping long strings. Strings that are longer than the screen are printed
108 108 through the less pager.
109 109
110 110 The ?/?? system gives access to the full source code for any object (if
111 111 available), shows function prototypes and other useful information.
112 112
113 113 If you just want to see an object's docstring, type '%pdoc object' (without
114 114 quotes, and without % if you have automagic on).
115 115
116 116 * Tab completion in the local namespace:
117 117
118 118 At any time, hitting tab will complete any available python commands or
119 119 variable names, and show you a list of the possible completions if there's
120 120 no unambiguous one. It will also complete filenames in the current directory.
121 121
122 122 * Search previous command history in multiple ways:
123 123
124 124 - Start typing, and then use arrow keys up/down or (Ctrl-p/Ctrl-n) to search
125 125 through the history items that match what you've typed so far.
126 126
127 127 - Hit Ctrl-r: opens a search prompt. Begin typing and the system searches
128 128 your history for lines that match what you've typed so far, completing as
129 129 much as it can.
130 130
131 131 - %hist: search history by index.
132 132
133 133 * Persistent command history across sessions.
134 134
135 135 * Logging of input with the ability to save and restore a working session.
136 136
137 137 * System shell with !. Typing !ls will run 'ls' in the current directory.
138 138
139 139 * The reload command does a 'deep' reload of a module: changes made to the
140 140 module since you imported will actually be available without having to exit.
141 141
142 142 * Verbose and colored exception traceback printouts. See the magic xmode and
143 143 xcolor functions for details (just type %magic).
144 144
145 145 * Input caching system:
146 146
147 147 IPython offers numbered prompts (In/Out) with input and output caching. All
148 148 input is saved and can be retrieved as variables (besides the usual arrow
149 149 key recall).
150 150
151 151 The following GLOBAL variables always exist (so don't overwrite them!):
152 152 _i: stores previous input.
153 153 _ii: next previous.
154 154 _iii: next-next previous.
155 155 _ih : a list of all input _ih[n] is the input from line n.
156 156
157 157 Additionally, global variables named _i<n> are dynamically created (<n>
158 158 being the prompt counter), such that _i<n> == _ih[<n>]
159 159
160 160 For example, what you typed at prompt 14 is available as _i14 and _ih[14].
161 161
162 162 You can create macros which contain multiple input lines from this history,
163 163 for later re-execution, with the %macro function.
164 164
165 165 The history function %hist allows you to see any part of your input history
166 166 by printing a range of the _i variables. Note that inputs which contain
167 167 magic functions (%) appear in the history with a prepended comment. This is
168 168 because they aren't really valid Python code, so you can't exec them.
169 169
170 170 * Output caching system:
171 171
172 172 For output that is returned from actions, a system similar to the input
173 173 cache exists but using _ instead of _i. Only actions that produce a result
174 174 (NOT assignments, for example) are cached. If you are familiar with
175 175 Mathematica, IPython's _ variables behave exactly like Mathematica's %
176 176 variables.
177 177
178 178 The following GLOBAL variables always exist (so don't overwrite them!):
179 179 _ (one underscore): previous output.
180 180 __ (two underscores): next previous.
181 181 ___ (three underscores): next-next previous.
182 182
183 183 Global variables named _<n> are dynamically created (<n> being the prompt
184 184 counter), such that the result of output <n> is always available as _<n>.
185 185
186 186 Finally, a global dictionary named _oh exists with entries for all lines
187 187 which generated output.
188 188
189 189 * Directory history:
190 190
191 191 Your history of visited directories is kept in the global list _dh, and the
192 192 magic %cd command can be used to go to any entry in that list.
193 193
194 194 * Auto-parentheses and auto-quotes (adapted from Nathan Gray's LazyPython)
195 195
196 196 1. Auto-parentheses
197 197
198 198 Callable objects (i.e. functions, methods, etc) can be invoked like
199 199 this (notice the commas between the arguments)::
200 200
201 201 In [1]: callable_ob arg1, arg2, arg3
202 202
203 203 and the input will be translated to this::
204 204
205 205 callable_ob(arg1, arg2, arg3)
206 206
207 207 This feature is off by default (in rare cases it can produce
208 208 undesirable side-effects), but you can activate it at the command-line
209 209 by starting IPython with `--autocall 1`, set it permanently in your
210 210 configuration file, or turn on at runtime with `%autocall 1`.
211 211
212 212 You can force auto-parentheses by using '/' as the first character
213 213 of a line. For example::
214 214
215 215 In [1]: /globals # becomes 'globals()'
216 216
217 217 Note that the '/' MUST be the first character on the line! This
218 218 won't work::
219 219
220 220 In [2]: print /globals # syntax error
221 221
222 222 In most cases the automatic algorithm should work, so you should
223 223 rarely need to explicitly invoke /. One notable exception is if you
224 224 are trying to call a function with a list of tuples as arguments (the
225 225 parenthesis will confuse IPython)::
226 226
227 227 In [1]: zip (1,2,3),(4,5,6) # won't work
228 228
229 229 but this will work::
230 230
231 231 In [2]: /zip (1,2,3),(4,5,6)
232 232 ------> zip ((1,2,3),(4,5,6))
233 233 Out[2]= [(1, 4), (2, 5), (3, 6)]
234 234
235 235 IPython tells you that it has altered your command line by
236 236 displaying the new command line preceded by -->. e.g.::
237 237
238 238 In [18]: callable list
239 239 -------> callable (list)
240 240
241 241 2. Auto-Quoting
242 242
243 243 You can force auto-quoting of a function's arguments by using ',' as
244 244 the first character of a line. For example::
245 245
246 246 In [1]: ,my_function /home/me # becomes my_function("/home/me")
247 247
248 248 If you use ';' instead, the whole argument is quoted as a single
249 249 string (while ',' splits on whitespace)::
250 250
251 251 In [2]: ,my_function a b c # becomes my_function("a","b","c")
252 252 In [3]: ;my_function a b c # becomes my_function("a b c")
253 253
254 254 Note that the ',' MUST be the first character on the line! This
255 255 won't work::
256 256
257 257 In [4]: x = ,my_function /home/me # syntax error
258 258 """
259 259
260 260 interactive_usage_min = """\
261 261 An enhanced console for Python.
262 262 Some of its features are:
263 263 - Tab completion in the local namespace.
264 264 - Logging of input, see command-line options.
265 265 - System shell escape via ! , eg !ls.
266 266 - Magic commands, starting with a % (like %ls, %pwd, %cd, etc.)
267 267 - Keeps track of locally defined variables via %who, %whos.
268 268 - Show object information with a ? eg ?x or x? (use ?? for more info).
269 269 """
270 270
271 271 quick_reference = r"""
272 272 IPython -- An enhanced Interactive Python - Quick Reference Card
273 273 ================================================================
274 274
275 275 obj?, obj?? : Get help, or more help for object (also works as
276 276 ?obj, ??obj).
277 277 ?foo.*abc* : List names in 'foo' containing 'abc' in them.
278 278 %magic : Information about IPython's 'magic' % functions.
279 279
280 280 Magic functions are prefixed by % or %%, and typically take their arguments
281 281 without parentheses, quotes or even commas for convenience. Line magics take a
282 282 single % and cell magics are prefixed with two %%.
283 283
284 284 Example magic function calls:
285 285
286 286 %alias d ls -F : 'd' is now an alias for 'ls -F'
287 287 alias d ls -F : Works if 'alias' not a python name
288 288 alist = %alias : Get list of aliases to 'alist'
289 289 cd /usr/share : Obvious. cd -<tab> to choose from visited dirs.
290 290 %cd?? : See help AND source for magic %cd
291 291 %timeit x=10 : time the 'x=10' statement with high precision.
292 292 %%timeit x=2**100
293 293 x**100 : time 'x**100' with a setup of 'x=2**100'; setup code is not
294 294 counted. This is an example of a cell magic.
295 295
296 296 System commands:
297 297
298 298 !cp a.txt b/ : System command escape, calls os.system()
299 299 cp a.txt b/ : after %rehashx, most system commands work without !
300 300 cp ${f}.txt $bar : Variable expansion in magics and system commands
301 files = !ls /usr : Capture sytem command output
301 files = !ls /usr : Capture system command output
302 302 files.s, files.l, files.n: "a b c", ['a','b','c'], 'a\nb\nc'
303 303
304 304 History:
305 305
306 306 _i, _ii, _iii : Previous, next previous, next next previous input
307 307 _i4, _ih[2:5] : Input history line 4, lines 2-4
308 308 exec _i81 : Execute input history line #81 again
309 309 %rep 81 : Edit input history line #81
310 310 _, __, ___ : previous, next previous, next next previous output
311 311 _dh : Directory history
312 312 _oh : Output history
313 313 %hist : Command history of current session.
314 314 %hist -g foo : Search command history of (almost) all sessions for 'foo'.
315 315 %hist -g : Command history of (almost) all sessions.
316 316 %hist 1/2-8 : Command history containing lines 2-8 of session 1.
317 317 %hist 1/ ~2/ : Command history of session 1 and 2 sessions before current.
318 318 %hist ~8/1-~6/5 : Command history from line 1 of 8 sessions ago to
319 319 line 5 of 6 sessions ago.
320 320 %edit 0/ : Open editor to execute code with history of current session.
321 321
322 322 Autocall:
323 323
324 324 f 1,2 : f(1,2) # Off by default, enable with %autocall magic.
325 325 /f 1,2 : f(1,2) (forced autoparen)
326 326 ,f 1 2 : f("1","2")
327 327 ;f 1 2 : f("1 2")
328 328
329 329 Remember: TAB completion works in many contexts, not just file names
330 330 or python names.
331 331
332 332 The following magic functions are currently available:
333 333
334 334 """
335 335
336 336 default_banner_parts = ["Python %s\n"%sys.version.split("\n")[0],
337 337 "Type 'copyright', 'credits' or 'license' for more information\n" ,
338 338 "IPython {version} -- An enhanced Interactive Python. Type '?' for help.\n".format(version=release.version),
339 339 ]
340 340
341 341 default_banner = ''.join(default_banner_parts)
342 342
343 343 # deprecated GUI banner
344 344
345 345 default_gui_banner = '\n'.join([
346 346 'DEPRECATED: IPython.core.usage.default_gui_banner is deprecated and will be removed',
347 347 default_banner,
348 348 ])
@@ -1,347 +1,347 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 Provides a reload() function that acts recursively.
4 4
5 5 Python's normal :func:`python:reload` function only reloads the module that it's
6 6 passed. The :func:`reload` function in this module also reloads everything
7 7 imported from that module, which is useful when you're changing files deep
8 8 inside a package.
9 9
10 10 To use this as your default reload function, type this for Python 2::
11 11
12 12 import __builtin__
13 13 from IPython.lib import deepreload
14 14 __builtin__.reload = deepreload.reload
15 15
16 16 Or this for Python 3::
17 17
18 18 import builtins
19 19 from IPython.lib import deepreload
20 20 builtins.reload = deepreload.reload
21 21
22 22 A reference to the original :func:`python:reload` is stored in this module as
23 23 :data:`original_reload`, so you can restore it later.
24 24
25 25 This code is almost entirely based on knee.py, which is a Python
26 26 re-implementation of hierarchical module import.
27 27 """
28 28 #*****************************************************************************
29 29 # Copyright (C) 2001 Nathaniel Gray <n8gray@caltech.edu>
30 30 #
31 31 # Distributed under the terms of the BSD License. The full license is in
32 32 # the file COPYING, distributed as part of this software.
33 33 #*****************************************************************************
34 34
35 35 import builtins as builtin_mod
36 36 from contextlib import contextmanager
37 37 import imp
38 38 import sys
39 39
40 40 from types import ModuleType
41 41 from warnings import warn
42 42 import types
43 43
44 44 original_import = builtin_mod.__import__
45 45
46 46 @contextmanager
47 47 def replace_import_hook(new_import):
48 48 saved_import = builtin_mod.__import__
49 49 builtin_mod.__import__ = new_import
50 50 try:
51 51 yield
52 52 finally:
53 53 builtin_mod.__import__ = saved_import
54 54
55 55 def get_parent(globals, level):
56 56 """
57 57 parent, name = get_parent(globals, level)
58 58
59 59 Return the package that an import is being performed in. If globals comes
60 60 from the module foo.bar.bat (not itself a package), this returns the
61 61 sys.modules entry for foo.bar. If globals is from a package's __init__.py,
62 62 the package's entry in sys.modules is returned.
63 63
64 64 If globals doesn't come from a package or a module in a package, or a
65 65 corresponding entry is not found in sys.modules, None is returned.
66 66 """
67 67 orig_level = level
68 68
69 69 if not level or not isinstance(globals, dict):
70 70 return None, ''
71 71
72 72 pkgname = globals.get('__package__', None)
73 73
74 74 if pkgname is not None:
75 75 # __package__ is set, so use it
76 76 if not hasattr(pkgname, 'rindex'):
77 77 raise ValueError('__package__ set to non-string')
78 78 if len(pkgname) == 0:
79 79 if level > 0:
80 80 raise ValueError('Attempted relative import in non-package')
81 81 return None, ''
82 82 name = pkgname
83 83 else:
84 84 # __package__ not set, so figure it out and set it
85 85 if '__name__' not in globals:
86 86 return None, ''
87 87 modname = globals['__name__']
88 88
89 89 if '__path__' in globals:
90 90 # __path__ is set, so modname is already the package name
91 91 globals['__package__'] = name = modname
92 92 else:
93 93 # Normal module, so work out the package name if any
94 94 lastdot = modname.rfind('.')
95 95 if lastdot < 0 < level:
96 96 raise ValueError("Attempted relative import in non-package")
97 97 if lastdot < 0:
98 98 globals['__package__'] = None
99 99 return None, ''
100 100 globals['__package__'] = name = modname[:lastdot]
101 101
102 102 dot = len(name)
103 103 for x in range(level, 1, -1):
104 104 try:
105 105 dot = name.rindex('.', 0, dot)
106 106 except ValueError:
107 107 raise ValueError("attempted relative import beyond top-level "
108 108 "package")
109 109 name = name[:dot]
110 110
111 111 try:
112 112 parent = sys.modules[name]
113 113 except:
114 114 if orig_level < 1:
115 115 warn("Parent module '%.200s' not found while handling absolute "
116 116 "import" % name)
117 117 parent = None
118 118 else:
119 119 raise SystemError("Parent module '%.200s' not loaded, cannot "
120 120 "perform relative import" % name)
121 121
122 122 # We expect, but can't guarantee, if parent != None, that:
123 123 # - parent.__name__ == name
124 124 # - parent.__dict__ is globals
125 125 # If this is violated... Who cares?
126 126 return parent, name
127 127
128 128 def load_next(mod, altmod, name, buf):
129 129 """
130 130 mod, name, buf = load_next(mod, altmod, name, buf)
131 131
132 132 altmod is either None or same as mod
133 133 """
134 134
135 135 if len(name) == 0:
136 136 # completely empty module name should only happen in
137 137 # 'from . import' (or '__import__("")')
138 138 return mod, None, buf
139 139
140 140 dot = name.find('.')
141 141 if dot == 0:
142 142 raise ValueError('Empty module name')
143 143
144 144 if dot < 0:
145 145 subname = name
146 146 next = None
147 147 else:
148 148 subname = name[:dot]
149 149 next = name[dot+1:]
150 150
151 151 if buf != '':
152 152 buf += '.'
153 153 buf += subname
154 154
155 155 result = import_submodule(mod, subname, buf)
156 156 if result is None and mod != altmod:
157 157 result = import_submodule(altmod, subname, subname)
158 158 if result is not None:
159 159 buf = subname
160 160
161 161 if result is None:
162 162 raise ImportError("No module named %.200s" % name)
163 163
164 164 return result, next, buf
165 165
166 166
167 167 # Need to keep track of what we've already reloaded to prevent cyclic evil
168 168 found_now = {}
169 169
170 170 def import_submodule(mod, subname, fullname):
171 171 """m = import_submodule(mod, subname, fullname)"""
172 172 # Require:
173 173 # if mod == None: subname == fullname
174 174 # else: mod.__name__ + "." + subname == fullname
175 175
176 176 global found_now
177 177 if fullname in found_now and fullname in sys.modules:
178 178 m = sys.modules[fullname]
179 179 else:
180 180 print('Reloading', fullname)
181 181 found_now[fullname] = 1
182 182 oldm = sys.modules.get(fullname, None)
183 183
184 184 if mod is None:
185 185 path = None
186 186 elif hasattr(mod, '__path__'):
187 187 path = mod.__path__
188 188 else:
189 189 return None
190 190
191 191 try:
192 192 # This appears to be necessary on Python 3, because imp.find_module()
193 193 # tries to import standard libraries (like io) itself, and we don't
194 194 # want them to be processed by our deep_import_hook.
195 195 with replace_import_hook(original_import):
196 196 fp, filename, stuff = imp.find_module(subname, path)
197 197 except ImportError:
198 198 return None
199 199
200 200 try:
201 201 m = imp.load_module(fullname, fp, filename, stuff)
202 202 except:
203 203 # load_module probably removed name from modules because of
204 204 # the error. Put back the original module object.
205 205 if oldm:
206 206 sys.modules[fullname] = oldm
207 207 raise
208 208 finally:
209 209 if fp: fp.close()
210 210
211 211 add_submodule(mod, m, fullname, subname)
212 212
213 213 return m
214 214
215 215 def add_submodule(mod, submod, fullname, subname):
216 216 """mod.{subname} = submod"""
217 217 if mod is None:
218 218 return #Nothing to do here.
219 219
220 220 if submod is None:
221 221 submod = sys.modules[fullname]
222 222
223 223 setattr(mod, subname, submod)
224 224
225 225 return
226 226
227 227 def ensure_fromlist(mod, fromlist, buf, recursive):
228 228 """Handle 'from module import a, b, c' imports."""
229 229 if not hasattr(mod, '__path__'):
230 230 return
231 231 for item in fromlist:
232 232 if not hasattr(item, 'rindex'):
233 233 raise TypeError("Item in ``from list'' not a string")
234 234 if item == '*':
235 235 if recursive:
236 236 continue # avoid endless recursion
237 237 try:
238 238 all = mod.__all__
239 239 except AttributeError:
240 240 pass
241 241 else:
242 242 ret = ensure_fromlist(mod, all, buf, 1)
243 243 if not ret:
244 244 return 0
245 245 elif not hasattr(mod, item):
246 246 import_submodule(mod, item, buf + '.' + item)
247 247
248 248 def deep_import_hook(name, globals=None, locals=None, fromlist=None, level=-1):
249 249 """Replacement for __import__()"""
250 250 parent, buf = get_parent(globals, level)
251 251
252 252 head, name, buf = load_next(parent, None if level < 0 else parent, name, buf)
253 253
254 254 tail = head
255 255 while name:
256 256 tail, name, buf = load_next(tail, tail, name, buf)
257 257
258 258 # If tail is None, both get_parent and load_next found
259 259 # an empty module name: someone called __import__("") or
260 260 # doctored faulty bytecode
261 261 if tail is None:
262 262 raise ValueError('Empty module name')
263 263
264 264 if not fromlist:
265 265 return head
266 266
267 267 ensure_fromlist(tail, fromlist, buf, 0)
268 268 return tail
269 269
270 270 modules_reloading = {}
271 271
272 272 def deep_reload_hook(m):
273 273 """Replacement for reload()."""
274 274 # Hardcode this one as it would raise a NotImplemeentedError from the
275 275 # bowels of Python and screw up the import machinery after.
276 # unlike other imports the `exclude` list aleady in place is not enough.
276 # unlike other imports the `exclude` list already in place is not enough.
277 277
278 278 if m is types:
279 279 return m
280 280 if not isinstance(m, ModuleType):
281 281 raise TypeError("reload() argument must be module")
282 282
283 283 name = m.__name__
284 284
285 285 if name not in sys.modules:
286 286 raise ImportError("reload(): module %.200s not in sys.modules" % name)
287 287
288 288 global modules_reloading
289 289 try:
290 290 return modules_reloading[name]
291 291 except:
292 292 modules_reloading[name] = m
293 293
294 294 dot = name.rfind('.')
295 295 if dot < 0:
296 296 subname = name
297 297 path = None
298 298 else:
299 299 try:
300 300 parent = sys.modules[name[:dot]]
301 301 except KeyError:
302 302 modules_reloading.clear()
303 303 raise ImportError("reload(): parent %.200s not in sys.modules" % name[:dot])
304 304 subname = name[dot+1:]
305 305 path = getattr(parent, "__path__", None)
306 306
307 307 try:
308 308 # This appears to be necessary on Python 3, because imp.find_module()
309 309 # tries to import standard libraries (like io) itself, and we don't
310 310 # want them to be processed by our deep_import_hook.
311 311 with replace_import_hook(original_import):
312 312 fp, filename, stuff = imp.find_module(subname, path)
313 313 finally:
314 314 modules_reloading.clear()
315 315
316 316 try:
317 317 newm = imp.load_module(name, fp, filename, stuff)
318 318 except:
319 319 # load_module probably removed name from modules because of
320 320 # the error. Put back the original module object.
321 321 sys.modules[name] = m
322 322 raise
323 323 finally:
324 324 if fp: fp.close()
325 325
326 326 modules_reloading.clear()
327 327 return newm
328 328
329 329 # Save the original hooks
330 330 original_reload = imp.reload
331 331
332 332 # Replacement for reload()
333 333 def reload(module, exclude=('sys', 'os.path', 'builtins', '__main__',
334 334 'numpy', 'numpy._globals')):
335 335 """Recursively reload all modules used in the given module. Optionally
336 336 takes a list of modules to exclude from reloading. The default exclude
337 337 list contains sys, __main__, and __builtin__, to prevent, e.g., resetting
338 338 display, exception, and io hooks.
339 339 """
340 340 global found_now
341 341 for i in exclude:
342 342 found_now[i] = 1
343 343 try:
344 344 with replace_import_hook(deep_import_hook):
345 345 return deep_reload_hook(module)
346 346 finally:
347 347 found_now = {}
@@ -1,667 +1,667 b''
1 1 """Module for interactive demos using IPython.
2 2
3 3 This module implements a few classes for running Python scripts interactively
4 4 in IPython for demonstrations. With very simple markup (a few tags in
5 5 comments), you can control points where the script stops executing and returns
6 6 control to IPython.
7 7
8 8
9 9 Provided classes
10 10 ----------------
11 11
12 12 The classes are (see their docstrings for further details):
13 13
14 14 - Demo: pure python demos
15 15
16 16 - IPythonDemo: demos with input to be processed by IPython as if it had been
17 17 typed interactively (so magics work, as well as any other special syntax you
18 18 may have added via input prefilters).
19 19
20 20 - LineDemo: single-line version of the Demo class. These demos are executed
21 21 one line at a time, and require no markup.
22 22
23 23 - IPythonLineDemo: IPython version of the LineDemo class (the demo is
24 24 executed a line at a time, but processed via IPython).
25 25
26 26 - ClearMixin: mixin to make Demo classes with less visual clutter. It
27 27 declares an empty marquee and a pre_cmd that clears the screen before each
28 28 block (see Subclassing below).
29 29
30 30 - ClearDemo, ClearIPDemo: mixin-enabled versions of the Demo and IPythonDemo
31 31 classes.
32 32
33 33 Inheritance diagram:
34 34
35 35 .. inheritance-diagram:: IPython.lib.demo
36 36 :parts: 3
37 37
38 38 Subclassing
39 39 -----------
40 40
41 41 The classes here all include a few methods meant to make customization by
42 42 subclassing more convenient. Their docstrings below have some more details:
43 43
44 44 - highlight(): format every block and optionally highlight comments and
45 45 docstring content.
46 46
47 47 - marquee(): generates a marquee to provide visible on-screen markers at each
48 48 block start and end.
49 49
50 50 - pre_cmd(): run right before the execution of each block.
51 51
52 52 - post_cmd(): run right after the execution of each block. If the block
53 53 raises an exception, this is NOT called.
54 54
55 55
56 56 Operation
57 57 ---------
58 58
59 59 The file is run in its own empty namespace (though you can pass it a string of
60 60 arguments as if in a command line environment, and it will see those as
61 61 sys.argv). But at each stop, the global IPython namespace is updated with the
62 62 current internal demo namespace, so you can work interactively with the data
63 63 accumulated so far.
64 64
65 65 By default, each block of code is printed (with syntax highlighting) before
66 66 executing it and you have to confirm execution. This is intended to show the
67 67 code to an audience first so you can discuss it, and only proceed with
68 68 execution once you agree. There are a few tags which allow you to modify this
69 69 behavior.
70 70
71 71 The supported tags are:
72 72
73 73 # <demo> stop
74 74
75 75 Defines block boundaries, the points where IPython stops execution of the
76 76 file and returns to the interactive prompt.
77 77
78 78 You can optionally mark the stop tag with extra dashes before and after the
79 79 word 'stop', to help visually distinguish the blocks in a text editor:
80 80
81 81 # <demo> --- stop ---
82 82
83 83
84 84 # <demo> silent
85 85
86 86 Make a block execute silently (and hence automatically). Typically used in
87 87 cases where you have some boilerplate or initialization code which you need
88 88 executed but do not want to be seen in the demo.
89 89
90 90 # <demo> auto
91 91
92 92 Make a block execute automatically, but still being printed. Useful for
93 93 simple code which does not warrant discussion, since it avoids the extra
94 94 manual confirmation.
95 95
96 96 # <demo> auto_all
97 97
98 98 This tag can _only_ be in the first block, and if given it overrides the
99 99 individual auto tags to make the whole demo fully automatic (no block asks
100 100 for confirmation). It can also be given at creation time (or the attribute
101 101 set later) to override what's in the file.
102 102
103 103 While _any_ python file can be run as a Demo instance, if there are no stop
104 104 tags the whole file will run in a single block (no different that calling
105 105 first %pycat and then %run). The minimal markup to make this useful is to
106 106 place a set of stop tags; the other tags are only there to let you fine-tune
107 107 the execution.
108 108
109 109 This is probably best explained with the simple example file below. You can
110 110 copy this into a file named ex_demo.py, and try running it via::
111 111
112 112 from IPython.lib.demo import Demo
113 113 d = Demo('ex_demo.py')
114 114 d()
115 115
116 116 Each time you call the demo object, it runs the next block. The demo object
117 117 has a few useful methods for navigation, like again(), edit(), jump(), seek()
118 118 and back(). It can be reset for a new run via reset() or reloaded from disk
119 119 (in case you've edited the source) via reload(). See their docstrings below.
120 120
121 121 Note: To make this simpler to explore, a file called "demo-exercizer.py" has
122 122 been added to the "docs/examples/core" directory. Just cd to this directory in
123 123 an IPython session, and type::
124 124
125 125 %run demo-exercizer.py
126 126
127 127 and then follow the directions.
128 128
129 129 Example
130 130 -------
131 131
132 132 The following is a very simple example of a valid demo file.
133 133
134 134 ::
135 135
136 136 #################### EXAMPLE DEMO <ex_demo.py> ###############################
137 137 '''A simple interactive demo to illustrate the use of IPython's Demo class.'''
138 138
139 139 print 'Hello, welcome to an interactive IPython demo.'
140 140
141 141 # The mark below defines a block boundary, which is a point where IPython will
142 142 # stop execution and return to the interactive prompt. The dashes are actually
143 143 # optional and used only as a visual aid to clearly separate blocks while
144 144 # editing the demo code.
145 145 # <demo> stop
146 146
147 147 x = 1
148 148 y = 2
149 149
150 150 # <demo> stop
151 151
152 152 # the mark below makes this block as silent
153 153 # <demo> silent
154 154
155 155 print 'This is a silent block, which gets executed but not printed.'
156 156
157 157 # <demo> stop
158 158 # <demo> auto
159 159 print 'This is an automatic block.'
160 160 print 'It is executed without asking for confirmation, but printed.'
161 161 z = x+y
162 162
163 163 print 'z=',x
164 164
165 165 # <demo> stop
166 166 # This is just another normal block.
167 167 print 'z is now:', z
168 168
169 169 print 'bye!'
170 170 ################### END EXAMPLE DEMO <ex_demo.py> ############################
171 171 """
172 172
173 173
174 174 #*****************************************************************************
175 175 # Copyright (C) 2005-2006 Fernando Perez. <Fernando.Perez@colorado.edu>
176 176 #
177 177 # Distributed under the terms of the BSD License. The full license is in
178 178 # the file COPYING, distributed as part of this software.
179 179 #
180 180 #*****************************************************************************
181 181
182 182 import os
183 183 import re
184 184 import shlex
185 185 import sys
186 186 import pygments
187 187
188 188 from IPython.utils.text import marquee
189 189 from IPython.utils import openpy
190 190 from IPython.utils import py3compat
191 191 __all__ = ['Demo','IPythonDemo','LineDemo','IPythonLineDemo','DemoError']
192 192
193 193 class DemoError(Exception): pass
194 194
195 195 def re_mark(mark):
196 196 return re.compile(r'^\s*#\s+<demo>\s+%s\s*$' % mark,re.MULTILINE)
197 197
198 198 class Demo(object):
199 199
200 200 re_stop = re_mark('-*\s?stop\s?-*')
201 201 re_silent = re_mark('silent')
202 202 re_auto = re_mark('auto')
203 203 re_auto_all = re_mark('auto_all')
204 204
205 205 def __init__(self,src,title='',arg_str='',auto_all=None, format_rst=False,
206 206 formatter='terminal', style='default'):
207 207 """Make a new demo object. To run the demo, simply call the object.
208 208
209 209 See the module docstring for full details and an example (you can use
210 210 IPython.Demo? in IPython to see it).
211 211
212 212 Inputs:
213 213
214 214 - src is either a file, or file-like object, or a
215 215 string that can be resolved to a filename.
216 216
217 217 Optional inputs:
218 218
219 219 - title: a string to use as the demo name. Of most use when the demo
220 220 you are making comes from an object that has no filename, or if you
221 221 want an alternate denotation distinct from the filename.
222 222
223 223 - arg_str(''): a string of arguments, internally converted to a list
224 224 just like sys.argv, so the demo script can see a similar
225 225 environment.
226 226
227 227 - auto_all(None): global flag to run all blocks automatically without
228 228 confirmation. This attribute overrides the block-level tags and
229 229 applies to the whole demo. It is an attribute of the object, and
230 230 can be changed at runtime simply by reassigning it to a boolean
231 231 value.
232 232
233 233 - format_rst(False): a bool to enable comments and doc strings
234 formating with pygments rst lexer
234 formatting with pygments rst lexer
235 235
236 236 - formatter('terminal'): a string of pygments formatter name to be
237 237 used. Useful values for terminals: terminal, terminal256,
238 238 terminal16m
239 239
240 240 - style('default'): a string of pygments style name to be used.
241 241 """
242 242 if hasattr(src, "read"):
243 243 # It seems to be a file or a file-like object
244 244 self.fname = "from a file-like object"
245 245 if title == '':
246 246 self.title = "from a file-like object"
247 247 else:
248 248 self.title = title
249 249 else:
250 250 # Assume it's a string or something that can be converted to one
251 251 self.fname = src
252 252 if title == '':
253 253 (filepath, filename) = os.path.split(src)
254 254 self.title = filename
255 255 else:
256 256 self.title = title
257 257 self.sys_argv = [src] + shlex.split(arg_str)
258 258 self.auto_all = auto_all
259 259 self.src = src
260 260
261 261 self.inside_ipython = "get_ipython" in globals()
262 262 if self.inside_ipython:
263 263 # get a few things from ipython. While it's a bit ugly design-wise,
264 264 # it ensures that things like color scheme and the like are always in
265 265 # sync with the ipython mode being used. This class is only meant to
266 266 # be used inside ipython anyways, so it's OK.
267 267 ip = get_ipython() # this is in builtins whenever IPython is running
268 268 self.ip_ns = ip.user_ns
269 269 self.ip_colorize = ip.pycolorize
270 270 self.ip_showtb = ip.showtraceback
271 271 self.ip_run_cell = ip.run_cell
272 272 self.shell = ip
273 273
274 274 self.formatter = pygments.formatters.get_formatter_by_name(formatter,
275 275 style=style)
276 276 self.python_lexer = pygments.lexers.get_lexer_by_name("py3")
277 277 self.format_rst = format_rst
278 278 if format_rst:
279 279 self.rst_lexer = pygments.lexers.get_lexer_by_name("rst")
280 280
281 281 # load user data and initialize data structures
282 282 self.reload()
283 283
284 284 def fload(self):
285 285 """Load file object."""
286 286 # read data and parse into blocks
287 287 if hasattr(self, 'fobj') and self.fobj is not None:
288 288 self.fobj.close()
289 289 if hasattr(self.src, "read"):
290 290 # It seems to be a file or a file-like object
291 291 self.fobj = self.src
292 292 else:
293 293 # Assume it's a string or something that can be converted to one
294 294 self.fobj = openpy.open(self.fname)
295 295
296 296 def reload(self):
297 297 """Reload source from disk and initialize state."""
298 298 self.fload()
299 299
300 300 self.src = "".join(openpy.strip_encoding_cookie(self.fobj))
301 301 src_b = [b.strip() for b in self.re_stop.split(self.src) if b]
302 302 self._silent = [bool(self.re_silent.findall(b)) for b in src_b]
303 303 self._auto = [bool(self.re_auto.findall(b)) for b in src_b]
304 304
305 305 # if auto_all is not given (def. None), we read it from the file
306 306 if self.auto_all is None:
307 307 self.auto_all = bool(self.re_auto_all.findall(src_b[0]))
308 308 else:
309 309 self.auto_all = bool(self.auto_all)
310 310
311 311 # Clean the sources from all markup so it doesn't get displayed when
312 312 # running the demo
313 313 src_blocks = []
314 314 auto_strip = lambda s: self.re_auto.sub('',s)
315 315 for i,b in enumerate(src_b):
316 316 if self._auto[i]:
317 317 src_blocks.append(auto_strip(b))
318 318 else:
319 319 src_blocks.append(b)
320 320 # remove the auto_all marker
321 321 src_blocks[0] = self.re_auto_all.sub('',src_blocks[0])
322 322
323 323 self.nblocks = len(src_blocks)
324 324 self.src_blocks = src_blocks
325 325
326 326 # also build syntax-highlighted source
327 327 self.src_blocks_colored = list(map(self.highlight,self.src_blocks))
328 328
329 329 # ensure clean namespace and seek offset
330 330 self.reset()
331 331
332 332 def reset(self):
333 333 """Reset the namespace and seek pointer to restart the demo"""
334 334 self.user_ns = {}
335 335 self.finished = False
336 336 self.block_index = 0
337 337
338 338 def _validate_index(self,index):
339 339 if index<0 or index>=self.nblocks:
340 340 raise ValueError('invalid block index %s' % index)
341 341
342 342 def _get_index(self,index):
343 343 """Get the current block index, validating and checking status.
344 344
345 345 Returns None if the demo is finished"""
346 346
347 347 if index is None:
348 348 if self.finished:
349 349 print('Demo finished. Use <demo_name>.reset() if you want to rerun it.')
350 350 return None
351 351 index = self.block_index
352 352 else:
353 353 self._validate_index(index)
354 354 return index
355 355
356 356 def seek(self,index):
357 357 """Move the current seek pointer to the given block.
358 358
359 359 You can use negative indices to seek from the end, with identical
360 360 semantics to those of Python lists."""
361 361 if index<0:
362 362 index = self.nblocks + index
363 363 self._validate_index(index)
364 364 self.block_index = index
365 365 self.finished = False
366 366
367 367 def back(self,num=1):
368 368 """Move the seek pointer back num blocks (default is 1)."""
369 369 self.seek(self.block_index-num)
370 370
371 371 def jump(self,num=1):
372 372 """Jump a given number of blocks relative to the current one.
373 373
374 374 The offset can be positive or negative, defaults to 1."""
375 375 self.seek(self.block_index+num)
376 376
377 377 def again(self):
378 378 """Move the seek pointer back one block and re-execute."""
379 379 self.back(1)
380 380 self()
381 381
382 382 def edit(self,index=None):
383 383 """Edit a block.
384 384
385 385 If no number is given, use the last block executed.
386 386
387 387 This edits the in-memory copy of the demo, it does NOT modify the
388 388 original source file. If you want to do that, simply open the file in
389 389 an editor and use reload() when you make changes to the file. This
390 390 method is meant to let you change a block during a demonstration for
391 391 explanatory purposes, without damaging your original script."""
392 392
393 393 index = self._get_index(index)
394 394 if index is None:
395 395 return
396 396 # decrease the index by one (unless we're at the very beginning), so
397 397 # that the default demo.edit() call opens up the sblock we've last run
398 398 if index>0:
399 399 index -= 1
400 400
401 401 filename = self.shell.mktempfile(self.src_blocks[index])
402 402 self.shell.hooks.editor(filename,1)
403 403 with open(filename, 'r') as f:
404 404 new_block = f.read()
405 405 # update the source and colored block
406 406 self.src_blocks[index] = new_block
407 407 self.src_blocks_colored[index] = self.highlight(new_block)
408 408 self.block_index = index
409 409 # call to run with the newly edited index
410 410 self()
411 411
412 412 def show(self,index=None):
413 413 """Show a single block on screen"""
414 414
415 415 index = self._get_index(index)
416 416 if index is None:
417 417 return
418 418
419 419 print(self.marquee('<%s> block # %s (%s remaining)' %
420 420 (self.title,index,self.nblocks-index-1)))
421 421 print(self.src_blocks_colored[index])
422 422 sys.stdout.flush()
423 423
424 424 def show_all(self):
425 425 """Show entire demo on screen, block by block"""
426 426
427 427 fname = self.title
428 428 title = self.title
429 429 nblocks = self.nblocks
430 430 silent = self._silent
431 431 marquee = self.marquee
432 432 for index,block in enumerate(self.src_blocks_colored):
433 433 if silent[index]:
434 434 print(marquee('<%s> SILENT block # %s (%s remaining)' %
435 435 (title,index,nblocks-index-1)))
436 436 else:
437 437 print(marquee('<%s> block # %s (%s remaining)' %
438 438 (title,index,nblocks-index-1)))
439 439 print(block, end=' ')
440 440 sys.stdout.flush()
441 441
442 442 def run_cell(self,source):
443 443 """Execute a string with one or more lines of code"""
444 444
445 445 exec(source, self.user_ns)
446 446
447 447 def __call__(self,index=None):
448 448 """run a block of the demo.
449 449
450 450 If index is given, it should be an integer >=1 and <= nblocks. This
451 451 means that the calling convention is one off from typical Python
452 452 lists. The reason for the inconsistency is that the demo always
453 453 prints 'Block n/N, and N is the total, so it would be very odd to use
454 454 zero-indexing here."""
455 455
456 456 index = self._get_index(index)
457 457 if index is None:
458 458 return
459 459 try:
460 460 marquee = self.marquee
461 461 next_block = self.src_blocks[index]
462 462 self.block_index += 1
463 463 if self._silent[index]:
464 464 print(marquee('Executing silent block # %s (%s remaining)' %
465 465 (index,self.nblocks-index-1)))
466 466 else:
467 467 self.pre_cmd()
468 468 self.show(index)
469 469 if self.auto_all or self._auto[index]:
470 470 print(marquee('output:'))
471 471 else:
472 472 print(marquee('Press <q> to quit, <Enter> to execute...'), end=' ')
473 473 ans = py3compat.input().strip()
474 474 if ans:
475 475 print(marquee('Block NOT executed'))
476 476 return
477 477 try:
478 478 save_argv = sys.argv
479 479 sys.argv = self.sys_argv
480 480 self.run_cell(next_block)
481 481 self.post_cmd()
482 482 finally:
483 483 sys.argv = save_argv
484 484
485 485 except:
486 486 if self.inside_ipython:
487 487 self.ip_showtb(filename=self.fname)
488 488 else:
489 489 if self.inside_ipython:
490 490 self.ip_ns.update(self.user_ns)
491 491
492 492 if self.block_index == self.nblocks:
493 493 mq1 = self.marquee('END OF DEMO')
494 494 if mq1:
495 495 # avoid spurious print if empty marquees are used
496 496 print()
497 497 print(mq1)
498 498 print(self.marquee('Use <demo_name>.reset() if you want to rerun it.'))
499 499 self.finished = True
500 500
501 501 # These methods are meant to be overridden by subclasses who may wish to
502 502 # customize the behavior of of their demos.
503 503 def marquee(self,txt='',width=78,mark='*'):
504 504 """Return the input string centered in a 'marquee'."""
505 505 return marquee(txt,width,mark)
506 506
507 507 def pre_cmd(self):
508 508 """Method called before executing each block."""
509 509 pass
510 510
511 511 def post_cmd(self):
512 512 """Method called after executing each block."""
513 513 pass
514 514
515 515 def highlight(self, block):
516 516 """Method called on each block to highlight it content"""
517 517 tokens = pygments.lex(block, self.python_lexer)
518 518 if self.format_rst:
519 519 from pygments.token import Token
520 520 toks = []
521 521 for token in tokens:
522 522 if token[0] == Token.String.Doc and len(token[1]) > 6:
523 523 toks += pygments.lex(token[1][:3], self.python_lexer)
524 524 # parse doc string content by rst lexer
525 525 toks += pygments.lex(token[1][3:-3], self.rst_lexer)
526 526 toks += pygments.lex(token[1][-3:], self.python_lexer)
527 527 elif token[0] == Token.Comment.Single:
528 528 toks.append((Token.Comment.Single, token[1][0]))
529 529 # parse comment content by rst lexer
530 530 # remove the extrat newline added by rst lexer
531 531 toks += list(pygments.lex(token[1][1:], self.rst_lexer))[:-1]
532 532 else:
533 533 toks.append(token)
534 534 tokens = toks
535 535 return pygments.format(tokens, self.formatter)
536 536
537 537
538 538 class IPythonDemo(Demo):
539 539 """Class for interactive demos with IPython's input processing applied.
540 540
541 541 This subclasses Demo, but instead of executing each block by the Python
542 542 interpreter (via exec), it actually calls IPython on it, so that any input
543 543 filters which may be in place are applied to the input block.
544 544
545 545 If you have an interactive environment which exposes special input
546 546 processing, you can use this class instead to write demo scripts which
547 547 operate exactly as if you had typed them interactively. The default Demo
548 548 class requires the input to be valid, pure Python code.
549 549 """
550 550
551 551 def run_cell(self,source):
552 552 """Execute a string with one or more lines of code"""
553 553
554 554 self.shell.run_cell(source)
555 555
556 556 class LineDemo(Demo):
557 557 """Demo where each line is executed as a separate block.
558 558
559 559 The input script should be valid Python code.
560 560
561 561 This class doesn't require any markup at all, and it's meant for simple
562 562 scripts (with no nesting or any kind of indentation) which consist of
563 563 multiple lines of input to be executed, one at a time, as if they had been
564 564 typed in the interactive prompt.
565 565
566 566 Note: the input can not have *any* indentation, which means that only
567 567 single-lines of input are accepted, not even function definitions are
568 568 valid."""
569 569
570 570 def reload(self):
571 571 """Reload source from disk and initialize state."""
572 572 # read data and parse into blocks
573 573 self.fload()
574 574 lines = self.fobj.readlines()
575 575 src_b = [l for l in lines if l.strip()]
576 576 nblocks = len(src_b)
577 577 self.src = ''.join(lines)
578 578 self._silent = [False]*nblocks
579 579 self._auto = [True]*nblocks
580 580 self.auto_all = True
581 581 self.nblocks = nblocks
582 582 self.src_blocks = src_b
583 583
584 584 # also build syntax-highlighted source
585 585 self.src_blocks_colored = list(map(self.highlight,self.src_blocks))
586 586
587 587 # ensure clean namespace and seek offset
588 588 self.reset()
589 589
590 590
591 591 class IPythonLineDemo(IPythonDemo,LineDemo):
592 592 """Variant of the LineDemo class whose input is processed by IPython."""
593 593 pass
594 594
595 595
596 596 class ClearMixin(object):
597 597 """Use this mixin to make Demo classes with less visual clutter.
598 598
599 599 Demos using this mixin will clear the screen before every block and use
600 600 blank marquees.
601 601
602 602 Note that in order for the methods defined here to actually override those
603 603 of the classes it's mixed with, it must go /first/ in the inheritance
604 604 tree. For example:
605 605
606 606 class ClearIPDemo(ClearMixin,IPythonDemo): pass
607 607
608 608 will provide an IPythonDemo class with the mixin's features.
609 609 """
610 610
611 611 def marquee(self,txt='',width=78,mark='*'):
612 612 """Blank marquee that returns '' no matter what the input."""
613 613 return ''
614 614
615 615 def pre_cmd(self):
616 616 """Method called before executing each block.
617 617
618 618 This one simply clears the screen."""
619 619 from IPython.utils.terminal import _term_clear
620 620 _term_clear()
621 621
622 622 class ClearDemo(ClearMixin,Demo):
623 623 pass
624 624
625 625
626 626 class ClearIPDemo(ClearMixin,IPythonDemo):
627 627 pass
628 628
629 629
630 630 def slide(file_path, noclear=False, format_rst=True, formatter="terminal",
631 631 style="native", auto_all=False, delimiter='...'):
632 632 if noclear:
633 633 demo_class = Demo
634 634 else:
635 635 demo_class = ClearDemo
636 636 demo = demo_class(file_path, format_rst=format_rst, formatter=formatter,
637 637 style=style, auto_all=auto_all)
638 638 while not demo.finished:
639 639 demo()
640 640 try:
641 641 py3compat.input('\n' + delimiter)
642 642 except KeyboardInterrupt:
643 643 exit(1)
644 644
645 645 if __name__ == '__main__':
646 646 import argparse
647 647 parser = argparse.ArgumentParser(description='Run python demos')
648 648 parser.add_argument('--noclear', '-C', action='store_true',
649 649 help='Do not clear terminal on each slide')
650 650 parser.add_argument('--rst', '-r', action='store_true',
651 651 help='Highlight comments and dostrings as rst')
652 652 parser.add_argument('--formatter', '-f', default='terminal',
653 653 help='pygments formatter name could be: terminal, '
654 654 'terminal256, terminal16m')
655 655 parser.add_argument('--style', '-s', default='default',
656 656 help='pygments style name')
657 657 parser.add_argument('--auto', '-a', action='store_true',
658 658 help='Run all blocks automatically without'
659 659 'confirmation')
660 660 parser.add_argument('--delimiter', '-d', default='...',
661 661 help='slides delimiter added after each slide run')
662 662 parser.add_argument('file', nargs=1,
663 663 help='python demo file')
664 664 args = parser.parse_args()
665 665 slide(args.file[0], noclear=args.noclear, format_rst=args.rst,
666 666 formatter=args.formatter, style=args.style, auto_all=args.auto,
667 667 delimiter=args.delimiter)
@@ -1,557 +1,557 b''
1 1 """Various display related classes.
2 2
3 3 Authors : MinRK, gregcaporaso, dannystaple
4 4 """
5 5 from os.path import exists, isfile, splitext, abspath, join, isdir
6 6 from os import walk, sep
7 7
8 8 from IPython.core.display import DisplayObject
9 9
10 10 __all__ = ['Audio', 'IFrame', 'YouTubeVideo', 'VimeoVideo', 'ScribdDocument',
11 11 'FileLink', 'FileLinks']
12 12
13 13
14 14 class Audio(DisplayObject):
15 15 """Create an audio object.
16 16
17 17 When this object is returned by an input cell or passed to the
18 18 display function, it will result in Audio controls being displayed
19 19 in the frontend (only works in the notebook).
20 20
21 21 Parameters
22 22 ----------
23 23 data : numpy array, list, unicode, str or bytes
24 24 Can be one of
25 25
26 26 * Numpy 1d array containing the desired waveform (mono)
27 27 * Numpy 2d array containing waveforms for each channel.
28 28 Shape=(NCHAN, NSAMPLES). For the standard channel order, see
29 29 http://msdn.microsoft.com/en-us/library/windows/hardware/dn653308(v=vs.85).aspx
30 30 * List of float or integer representing the waveform (mono)
31 31 * String containing the filename
32 32 * Bytestring containing raw PCM data or
33 33 * URL pointing to a file on the web.
34 34
35 35 If the array option is used the waveform will be normalized.
36 36
37 37 If a filename or url is used the format support will be browser
38 38 dependent.
39 39 url : unicode
40 40 A URL to download the data from.
41 41 filename : unicode
42 42 Path to a local file to load the data from.
43 43 embed : boolean
44 44 Should the audio data be embedded using a data URI (True) or should
45 45 the original source be referenced. Set this to True if you want the
46 46 audio to playable later with no internet connection in the notebook.
47 47
48 48 Default is `True`, unless the keyword argument `url` is set, then
49 49 default value is `False`.
50 50 rate : integer
51 51 The sampling rate of the raw data.
52 52 Only required when data parameter is being used as an array
53 53 autoplay : bool
54 54 Set to True if the audio should immediately start playing.
55 55 Default is `False`.
56 56
57 57 Examples
58 58 --------
59 59 ::
60 60
61 61 # Generate a sound
62 62 import numpy as np
63 63 framerate = 44100
64 64 t = np.linspace(0,5,framerate*5)
65 65 data = np.sin(2*np.pi*220*t) + np.sin(2*np.pi*224*t))
66 66 Audio(data,rate=framerate)
67 67
68 68 # Can also do stereo or more channels
69 69 dataleft = np.sin(2*np.pi*220*t)
70 70 dataright = np.sin(2*np.pi*224*t)
71 71 Audio([dataleft, dataright],rate=framerate)
72 72
73 73 Audio("http://www.nch.com.au/acm/8k16bitpcm.wav") # From URL
74 74 Audio(url="http://www.w3schools.com/html/horse.ogg")
75 75
76 76 Audio('/path/to/sound.wav') # From file
77 77 Audio(filename='/path/to/sound.ogg')
78 78
79 79 Audio(b'RAW_WAV_DATA..) # From bytes
80 80 Audio(data=b'RAW_WAV_DATA..)
81 81
82 82 """
83 83 _read_flags = 'rb'
84 84
85 85 def __init__(self, data=None, filename=None, url=None, embed=None, rate=None, autoplay=False):
86 86 if filename is None and url is None and data is None:
87 87 raise ValueError("No image data found. Expecting filename, url, or data.")
88 88 if embed is False and url is None:
89 89 raise ValueError("No url found. Expecting url when embed=False")
90 90
91 91 if url is not None and embed is not True:
92 92 self.embed = False
93 93 else:
94 94 self.embed = True
95 95 self.autoplay = autoplay
96 96 super(Audio, self).__init__(data=data, url=url, filename=filename)
97 97
98 98 if self.data is not None and not isinstance(self.data, bytes):
99 99 self.data = self._make_wav(data,rate)
100 100
101 101 def reload(self):
102 102 """Reload the raw data from file or URL."""
103 103 import mimetypes
104 104 if self.embed:
105 105 super(Audio, self).reload()
106 106
107 107 if self.filename is not None:
108 108 self.mimetype = mimetypes.guess_type(self.filename)[0]
109 109 elif self.url is not None:
110 110 self.mimetype = mimetypes.guess_type(self.url)[0]
111 111 else:
112 112 self.mimetype = "audio/wav"
113 113
114 114 def _make_wav(self, data, rate):
115 115 """ Transform a numpy array to a PCM bytestring """
116 116 import struct
117 117 from io import BytesIO
118 118 import wave
119 119
120 120 try:
121 121 import numpy as np
122 122
123 123 data = np.array(data, dtype=float)
124 124 if len(data.shape) == 1:
125 125 nchan = 1
126 126 elif len(data.shape) == 2:
127 127 # In wave files,channels are interleaved. E.g.,
128 128 # "L1R1L2R2..." for stereo. See
129 129 # http://msdn.microsoft.com/en-us/library/windows/hardware/dn653308(v=vs.85).aspx
130 130 # for channel ordering
131 131 nchan = data.shape[0]
132 132 data = data.T.ravel()
133 133 else:
134 134 raise ValueError('Array audio input must be a 1D or 2D array')
135 135 scaled = np.int16(data/np.max(np.abs(data))*32767).tolist()
136 136 except ImportError:
137 137 # check that it is a "1D" list
138 138 idata = iter(data) # fails if not an iterable
139 139 try:
140 140 iter(idata.next())
141 141 raise TypeError('Only lists of mono audio are '
142 142 'supported if numpy is not installed')
143 143 except TypeError:
144 144 # this means it's not a nested list, which is what we want
145 145 pass
146 146 maxabsvalue = float(max([abs(x) for x in data]))
147 147 scaled = [int(x/maxabsvalue*32767) for x in data]
148 148 nchan = 1
149 149
150 150 fp = BytesIO()
151 151 waveobj = wave.open(fp,mode='wb')
152 152 waveobj.setnchannels(nchan)
153 153 waveobj.setframerate(rate)
154 154 waveobj.setsampwidth(2)
155 155 waveobj.setcomptype('NONE','NONE')
156 156 waveobj.writeframes(b''.join([struct.pack('<h',x) for x in scaled]))
157 157 val = fp.getvalue()
158 158 waveobj.close()
159 159
160 160 return val
161 161
162 162 def _data_and_metadata(self):
163 163 """shortcut for returning metadata with url information, if defined"""
164 164 md = {}
165 165 if self.url:
166 166 md['url'] = self.url
167 167 if md:
168 168 return self.data, md
169 169 else:
170 170 return self.data
171 171
172 172 def _repr_html_(self):
173 173 src = """
174 174 <audio controls="controls" {autoplay}>
175 175 <source src="{src}" type="{type}" />
176 176 Your browser does not support the audio element.
177 177 </audio>
178 178 """
179 179 return src.format(src=self.src_attr(),type=self.mimetype, autoplay=self.autoplay_attr())
180 180
181 181 def src_attr(self):
182 182 import base64
183 183 if self.embed and (self.data is not None):
184 184 data = base64=base64.b64encode(self.data).decode('ascii')
185 185 return """data:{type};base64,{base64}""".format(type=self.mimetype,
186 186 base64=data)
187 187 elif self.url is not None:
188 188 return self.url
189 189 else:
190 190 return ""
191 191
192 192 def autoplay_attr(self):
193 193 if(self.autoplay):
194 194 return 'autoplay="autoplay"'
195 195 else:
196 196 return ''
197 197
198 198 class IFrame(object):
199 199 """
200 200 Generic class to embed an iframe in an IPython notebook
201 201 """
202 202
203 203 iframe = """
204 204 <iframe
205 205 width="{width}"
206 206 height="{height}"
207 207 src="{src}{params}"
208 208 frameborder="0"
209 209 allowfullscreen
210 210 ></iframe>
211 211 """
212 212
213 213 def __init__(self, src, width, height, **kwargs):
214 214 self.src = src
215 215 self.width = width
216 216 self.height = height
217 217 self.params = kwargs
218 218
219 219 def _repr_html_(self):
220 220 """return the embed iframe"""
221 221 if self.params:
222 222 try:
223 223 from urllib.parse import urlencode # Py 3
224 224 except ImportError:
225 225 from urllib import urlencode
226 226 params = "?" + urlencode(self.params)
227 227 else:
228 228 params = ""
229 229 return self.iframe.format(src=self.src,
230 230 width=self.width,
231 231 height=self.height,
232 232 params=params)
233 233
234 234 class YouTubeVideo(IFrame):
235 235 """Class for embedding a YouTube Video in an IPython session, based on its video id.
236 236
237 237 e.g. to embed the video from https://www.youtube.com/watch?v=foo , you would
238 238 do::
239 239
240 240 vid = YouTubeVideo("foo")
241 241 display(vid)
242 242
243 243 To start from 30 seconds::
244 244
245 245 vid = YouTubeVideo("abc", start=30)
246 246 display(vid)
247 247
248 248 To calculate seconds from time as hours, minutes, seconds use
249 249 :class:`datetime.timedelta`::
250 250
251 251 start=int(timedelta(hours=1, minutes=46, seconds=40).total_seconds())
252 252
253 253 Other parameters can be provided as documented at
254 254 https://developers.google.com/youtube/player_parameters#Parameters
255 255
256 256 When converting the notebook using nbconvert, a jpeg representation of the video
257 257 will be inserted in the document.
258 258 """
259 259
260 260 def __init__(self, id, width=400, height=300, **kwargs):
261 261 self.id=id
262 262 src = "https://www.youtube.com/embed/{0}".format(id)
263 263 super(YouTubeVideo, self).__init__(src, width, height, **kwargs)
264 264
265 265 def _repr_jpeg_(self):
266 266 # Deferred import
267 267 from urllib.request import urlopen
268 268
269 269 try:
270 270 return urlopen("https://img.youtube.com/vi/{id}/hqdefault.jpg".format(id=self.id)).read()
271 271 except IOError:
272 272 return None
273 273
274 274 class VimeoVideo(IFrame):
275 275 """
276 276 Class for embedding a Vimeo video in an IPython session, based on its video id.
277 277 """
278 278
279 279 def __init__(self, id, width=400, height=300, **kwargs):
280 280 src="https://player.vimeo.com/video/{0}".format(id)
281 281 super(VimeoVideo, self).__init__(src, width, height, **kwargs)
282 282
283 283 class ScribdDocument(IFrame):
284 284 """
285 285 Class for embedding a Scribd document in an IPython session
286 286
287 287 Use the start_page params to specify a starting point in the document
288 288 Use the view_mode params to specify display type one off scroll | slideshow | book
289 289
290 290 e.g to Display Wes' foundational paper about PANDAS in book mode from page 3
291 291
292 292 ScribdDocument(71048089, width=800, height=400, start_page=3, view_mode="book")
293 293 """
294 294
295 295 def __init__(self, id, width=400, height=300, **kwargs):
296 296 src="https://www.scribd.com/embeds/{0}/content".format(id)
297 297 super(ScribdDocument, self).__init__(src, width, height, **kwargs)
298 298
299 299 class FileLink(object):
300 300 """Class for embedding a local file link in an IPython session, based on path
301 301
302 302 e.g. to embed a link that was generated in the IPython notebook as my/data.txt
303 303
304 304 you would do::
305 305
306 306 local_file = FileLink("my/data.txt")
307 307 display(local_file)
308 308
309 309 or in the HTML notebook, just::
310 310
311 311 FileLink("my/data.txt")
312 312 """
313 313
314 314 html_link_str = "<a href='%s' target='_blank'>%s</a>"
315 315
316 316 def __init__(self,
317 317 path,
318 318 url_prefix='',
319 319 result_html_prefix='',
320 320 result_html_suffix='<br>'):
321 321 """
322 322 Parameters
323 323 ----------
324 324 path : str
325 325 path to the file or directory that should be formatted
326 326 url_prefix : str
327 327 prefix to be prepended to all files to form a working link [default:
328 328 '']
329 329 result_html_prefix : str
330 330 text to append to beginning to link [default: '']
331 331 result_html_suffix : str
332 332 text to append at the end of link [default: '<br>']
333 333 """
334 334 if isdir(path):
335 335 raise ValueError("Cannot display a directory using FileLink. "
336 336 "Use FileLinks to display '%s'." % path)
337 337 self.path = path
338 338 self.url_prefix = url_prefix
339 339 self.result_html_prefix = result_html_prefix
340 340 self.result_html_suffix = result_html_suffix
341 341
342 342 def _format_path(self):
343 343 fp = ''.join([self.url_prefix,self.path])
344 344 return ''.join([self.result_html_prefix,
345 345 self.html_link_str % (fp, self.path),
346 346 self.result_html_suffix])
347 347
348 348 def _repr_html_(self):
349 349 """return html link to file
350 350 """
351 351 if not exists(self.path):
352 352 return ("Path (<tt>%s</tt>) doesn't exist. "
353 353 "It may still be in the process of "
354 354 "being generated, or you may have the "
355 355 "incorrect path." % self.path)
356 356
357 357 return self._format_path()
358 358
359 359 def __repr__(self):
360 360 """return absolute path to file
361 361 """
362 362 return abspath(self.path)
363 363
364 364 class FileLinks(FileLink):
365 365 """Class for embedding local file links in an IPython session, based on path
366 366
367 367 e.g. to embed links to files that were generated in the IPython notebook
368 368 under ``my/data``, you would do::
369 369
370 370 local_files = FileLinks("my/data")
371 371 display(local_files)
372 372
373 373 or in the HTML notebook, just::
374 374
375 375 FileLinks("my/data")
376 376 """
377 377 def __init__(self,
378 378 path,
379 379 url_prefix='',
380 380 included_suffixes=None,
381 381 result_html_prefix='',
382 382 result_html_suffix='<br>',
383 383 notebook_display_formatter=None,
384 384 terminal_display_formatter=None,
385 385 recursive=True):
386 386 """
387 387 See :class:`FileLink` for the ``path``, ``url_prefix``,
388 388 ``result_html_prefix`` and ``result_html_suffix`` parameters.
389 389
390 390 included_suffixes : list
391 391 Filename suffixes to include when formatting output [default: include
392 392 all files]
393 393
394 394 notebook_display_formatter : function
395 395 Used to format links for display in the notebook. See discussion of
396 396 formatter functions below.
397 397
398 398 terminal_display_formatter : function
399 399 Used to format links for display in the terminal. See discussion of
400 400 formatter functions below.
401 401
402 402 Formatter functions must be of the form::
403 403
404 404 f(dirname, fnames, included_suffixes)
405 405
406 406 dirname : str
407 407 The name of a directory
408 408 fnames : list
409 409 The files in that directory
410 410 included_suffixes : list
411 411 The file suffixes that should be included in the output (passing None
412 412 meansto include all suffixes in the output in the built-in formatters)
413 413 recursive : boolean
414 414 Whether to recurse into subdirectories. Default is True.
415 415
416 416 The function should return a list of lines that will be printed in the
417 417 notebook (if passing notebook_display_formatter) or the terminal (if
418 418 passing terminal_display_formatter). This function is iterated over for
419 419 each directory in self.path. Default formatters are in place, can be
420 420 passed here to support alternative formatting.
421 421
422 422 """
423 423 if isfile(path):
424 424 raise ValueError("Cannot display a file using FileLinks. "
425 425 "Use FileLink to display '%s'." % path)
426 426 self.included_suffixes = included_suffixes
427 427 # remove trailing slashs for more consistent output formatting
428 428 path = path.rstrip('/')
429 429
430 430 self.path = path
431 431 self.url_prefix = url_prefix
432 432 self.result_html_prefix = result_html_prefix
433 433 self.result_html_suffix = result_html_suffix
434 434
435 435 self.notebook_display_formatter = \
436 436 notebook_display_formatter or self._get_notebook_display_formatter()
437 437 self.terminal_display_formatter = \
438 438 terminal_display_formatter or self._get_terminal_display_formatter()
439 439
440 440 self.recursive = recursive
441 441
442 442 def _get_display_formatter(self,
443 443 dirname_output_format,
444 444 fname_output_format,
445 445 fp_format,
446 446 fp_cleaner=None):
447 447 """ generate built-in formatter function
448 448
449 449 this is used to define both the notebook and terminal built-in
450 450 formatters as they only differ by some wrapper text for each entry
451 451
452 452 dirname_output_format: string to use for formatting directory
453 453 names, dirname will be substituted for a single "%s" which
454 454 must appear in this string
455 455 fname_output_format: string to use for formatting file names,
456 456 if a single "%s" appears in the string, fname will be substituted
457 457 if two "%s" appear in the string, the path to fname will be
458 458 substituted for the first and fname will be substituted for the
459 459 second
460 460 fp_format: string to use for formatting filepaths, must contain
461 461 exactly two "%s" and the dirname will be subsituted for the first
462 462 and fname will be substituted for the second
463 463 """
464 464 def f(dirname, fnames, included_suffixes=None):
465 465 result = []
466 466 # begin by figuring out which filenames, if any,
467 467 # are going to be displayed
468 468 display_fnames = []
469 469 for fname in fnames:
470 470 if (isfile(join(dirname,fname)) and
471 471 (included_suffixes is None or
472 472 splitext(fname)[1] in included_suffixes)):
473 473 display_fnames.append(fname)
474 474
475 475 if len(display_fnames) == 0:
476 476 # if there are no filenames to display, don't print anything
477 477 # (not even the directory name)
478 478 pass
479 479 else:
480 480 # otherwise print the formatted directory name followed by
481 481 # the formatted filenames
482 482 dirname_output_line = dirname_output_format % dirname
483 483 result.append(dirname_output_line)
484 484 for fname in display_fnames:
485 485 fp = fp_format % (dirname,fname)
486 486 if fp_cleaner is not None:
487 487 fp = fp_cleaner(fp)
488 488 try:
489 489 # output can include both a filepath and a filename...
490 490 fname_output_line = fname_output_format % (fp, fname)
491 491 except TypeError:
492 492 # ... or just a single filepath
493 493 fname_output_line = fname_output_format % fname
494 494 result.append(fname_output_line)
495 495 return result
496 496 return f
497 497
498 498 def _get_notebook_display_formatter(self,
499 499 spacer="&nbsp;&nbsp;"):
500 500 """ generate function to use for notebook formatting
501 501 """
502 502 dirname_output_format = \
503 503 self.result_html_prefix + "%s/" + self.result_html_suffix
504 504 fname_output_format = \
505 505 self.result_html_prefix + spacer + self.html_link_str + self.result_html_suffix
506 506 fp_format = self.url_prefix + '%s/%s'
507 507 if sep == "\\":
508 508 # Working on a platform where the path separator is "\", so
509 509 # must convert these to "/" for generating a URI
510 510 def fp_cleaner(fp):
511 # Replace all occurences of backslash ("\") with a forward
511 # Replace all occurrences of backslash ("\") with a forward
512 512 # slash ("/") - this is necessary on windows when a path is
513 513 # provided as input, but we must link to a URI
514 514 return fp.replace('\\','/')
515 515 else:
516 516 fp_cleaner = None
517 517
518 518 return self._get_display_formatter(dirname_output_format,
519 519 fname_output_format,
520 520 fp_format,
521 521 fp_cleaner)
522 522
523 523 def _get_terminal_display_formatter(self,
524 524 spacer=" "):
525 525 """ generate function to use for terminal formatting
526 526 """
527 527 dirname_output_format = "%s/"
528 528 fname_output_format = spacer + "%s"
529 529 fp_format = '%s/%s'
530 530
531 531 return self._get_display_formatter(dirname_output_format,
532 532 fname_output_format,
533 533 fp_format)
534 534
535 535 def _format_path(self):
536 536 result_lines = []
537 537 if self.recursive:
538 538 walked_dir = list(walk(self.path))
539 539 else:
540 540 walked_dir = [next(walk(self.path))]
541 541 walked_dir.sort()
542 542 for dirname, subdirs, fnames in walked_dir:
543 543 result_lines += self.notebook_display_formatter(dirname, fnames, self.included_suffixes)
544 544 return '\n'.join(result_lines)
545 545
546 546 def __repr__(self):
547 547 """return newline-separated absolute paths
548 548 """
549 549 result_lines = []
550 550 if self.recursive:
551 551 walked_dir = list(walk(self.path))
552 552 else:
553 553 walked_dir = [next(walk(self.path))]
554 554 walked_dir.sort()
555 555 for dirname, subdirs, fnames in walked_dir:
556 556 result_lines += self.terminal_display_formatter(dirname, fnames, self.included_suffixes)
557 557 return '\n'.join(result_lines)
@@ -1,128 +1,128 b''
1 1 """ 'editor' hooks for common editors that work well with ipython
2 2
3 3 They should honor the line number argument, at least.
4 4
5 5 Contributions are *very* welcome.
6 6 """
7 7
8 8 import os
9 9 import pipes
10 10 import shlex
11 11 import subprocess
12 12 import sys
13 13
14 14 from IPython import get_ipython
15 15 from IPython.core.error import TryNext
16 16 from IPython.utils import py3compat
17 17
18 18
19 19 def install_editor(template, wait=False):
20 20 """Installs the editor that is called by IPython for the %edit magic.
21 21
22 22 This overrides the default editor, which is generally set by your EDITOR
23 23 environment variable or is notepad (windows) or vi (linux). By supplying a
24 24 template string `run_template`, you can control how the editor is invoked
25 25 by IPython -- (e.g. the format in which it accepts command line options)
26 26
27 27 Parameters
28 28 ----------
29 29 template : basestring
30 30 run_template acts as a template for how your editor is invoked by
31 31 the shell. It should contain '{filename}', which will be replaced on
32 32 invokation with the file name, and '{line}', $line by line number
33 33 (or 0) to invoke the file with.
34 34 wait : bool
35 35 If `wait` is true, wait until the user presses enter before returning,
36 36 to facilitate non-blocking editors that exit immediately after
37 37 the call.
38 38 """
39 39
40 40 # not all editors support $line, so we'll leave out this check
41 41 # for substitution in ['$file', '$line']:
42 42 # if not substitution in run_template:
43 43 # raise ValueError(('run_template should contain %s'
44 44 # ' for string substitution. You supplied "%s"' % (substitution,
45 45 # run_template)))
46 46
47 47 def call_editor(self, filename, line=0):
48 48 if line is None:
49 49 line = 0
50 50 cmd = template.format(filename=pipes.quote(filename), line=line)
51 51 print(">", cmd)
52 52 # pipes.quote doesn't work right on Windows, but it does after splitting
53 53 if sys.platform.startswith('win'):
54 54 cmd = shlex.split(cmd)
55 55 proc = subprocess.Popen(cmd, shell=True)
56 56 if proc.wait() != 0:
57 57 raise TryNext()
58 58 if wait:
59 59 py3compat.input("Press Enter when done editing:")
60 60
61 61 get_ipython().set_hook('editor', call_editor)
62 62 get_ipython().editor = template
63 63
64 64
65 65 # in these, exe is always the path/name of the executable. Useful
66 66 # if you don't have the editor directory in your path
67 67 def komodo(exe=u'komodo'):
68 68 """ Activestate Komodo [Edit] """
69 69 install_editor(exe + u' -l {line} {filename}', wait=True)
70 70
71 71
72 72 def scite(exe=u"scite"):
73 73 """ SciTE or Sc1 """
74 74 install_editor(exe + u' {filename} -goto:{line}')
75 75
76 76
77 77 def notepadplusplus(exe=u'notepad++'):
78 78 """ Notepad++ http://notepad-plus.sourceforge.net """
79 79 install_editor(exe + u' -n{line} {filename}')
80 80
81 81
82 82 def jed(exe=u'jed'):
83 83 """ JED, the lightweight emacsish editor """
84 84 install_editor(exe + u' +{line} {filename}')
85 85
86 86
87 87 def idle(exe=u'idle'):
88 88 """ Idle, the editor bundled with python
89 89
90 90 Parameters
91 91 ----------
92 92 exe : str, None
93 93 If none, should be pretty smart about finding the executable.
94 94 """
95 95 if exe is None:
96 96 import idlelib
97 97 p = os.path.dirname(idlelib.__filename__)
98 98 # i'm not sure if this actually works. Is this idle.py script
99 # guarenteed to be executable?
99 # guaranteed to be executable?
100 100 exe = os.path.join(p, 'idle.py')
101 101 install_editor(exe + u' {filename}')
102 102
103 103
104 104 def mate(exe=u'mate'):
105 105 """ TextMate, the missing editor"""
106 106 # wait=True is not required since we're using the -w flag to mate
107 107 install_editor(exe + u' -w -l {line} {filename}')
108 108
109 109
110 110 # ##########################################
111 111 # these are untested, report any problems
112 112 # ##########################################
113 113
114 114
115 115 def emacs(exe=u'emacs'):
116 116 install_editor(exe + u' +{line} {filename}')
117 117
118 118
119 119 def gnuclient(exe=u'gnuclient'):
120 120 install_editor(exe + u' -nw +{line} {filename}')
121 121
122 122
123 123 def crimson_editor(exe=u'cedt.exe'):
124 124 install_editor(exe + u' /L:{line} {filename}')
125 125
126 126
127 127 def kate(exe=u'kate'):
128 128 install_editor(exe + u' -u -l {line} {filename}')
@@ -1,90 +1,90 b''
1 1 # Code borrowed from ptpython
2 2 # https://github.com/jonathanslenders/ptpython/blob/86b71a89626114b18898a0af463978bdb32eeb70/ptpython/eventloop.py
3 3
4 4 # Copyright (c) 2015, Jonathan Slenders
5 5 # All rights reserved.
6 6 #
7 7 # Redistribution and use in source and binary forms, with or without modification,
8 8 # are permitted provided that the following conditions are met:
9 9 #
10 10 # * Redistributions of source code must retain the above copyright notice, this
11 11 # list of conditions and the following disclaimer.
12 12 #
13 13 # * Redistributions in binary form must reproduce the above copyright notice, this
14 14 # list of conditions and the following disclaimer in the documentation and/or
15 15 # other materials provided with the distribution.
16 16 #
17 17 # * Neither the name of the {organization} nor the names of its
18 18 # contributors may be used to endorse or promote products derived from
19 19 # this software without specific prior written permission.
20 20 #
21 21 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
22 22 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 23 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 24 # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
25 25 # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 26 # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 27 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
28 28 # ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 29 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 30 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 31
32 32 """
33 33 Wrapper around the eventloop that gives some time to the Tkinter GUI to process
34 34 events when it's loaded and while we are waiting for input at the REPL. This
35 35 way we don't block the UI of for instance ``turtle`` and other Tk libraries.
36 36
37 (Normally Tkinter registeres it's callbacks in ``PyOS_InputHook`` to integrate
37 (Normally Tkinter registers it's callbacks in ``PyOS_InputHook`` to integrate
38 38 in readline. ``prompt-toolkit`` doesn't understand that input hook, but this
39 39 will fix it for Tk.)
40 40 """
41 41 import time
42 42
43 43 import _tkinter
44 44 import tkinter
45 45
46 46 def inputhook(inputhook_context):
47 47 """
48 48 Inputhook for Tk.
49 49 Run the Tk eventloop until prompt-toolkit needs to process the next input.
50 50 """
51 51 # Get the current TK application.
52 52 root = tkinter._default_root
53 53
54 54 def wait_using_filehandler():
55 55 """
56 56 Run the TK eventloop until the file handler that we got from the
57 57 inputhook becomes readable.
58 58 """
59 59 # Add a handler that sets the stop flag when `prompt-toolkit` has input
60 60 # to process.
61 61 stop = [False]
62 62 def done(*a):
63 63 stop[0] = True
64 64
65 65 root.createfilehandler(inputhook_context.fileno(), _tkinter.READABLE, done)
66 66
67 67 # Run the TK event loop as long as we don't receive input.
68 68 while root.dooneevent(_tkinter.ALL_EVENTS):
69 69 if stop[0]:
70 70 break
71 71
72 72 root.deletefilehandler(inputhook_context.fileno())
73 73
74 74 def wait_using_polling():
75 75 """
76 76 Windows TK doesn't support 'createfilehandler'.
77 77 So, run the TK eventloop and poll until input is ready.
78 78 """
79 79 while not inputhook_context.input_is_ready():
80 80 while root.dooneevent(_tkinter.ALL_EVENTS | _tkinter.DONT_WAIT):
81 81 pass
82 82 # Sleep to make the CPU idle, but not too long, so that the UI
83 83 # stays responsive.
84 84 time.sleep(.01)
85 85
86 86 if root is not None:
87 87 if hasattr(root, 'createfilehandler'):
88 88 wait_using_filehandler()
89 89 else:
90 90 wait_using_polling()
@@ -1,176 +1,176 b''
1 1 """Experimental code for cleaner support of IPython syntax with unittest.
2 2
3 3 In IPython up until 0.10, we've used very hacked up nose machinery for running
4 4 tests with IPython special syntax, and this has proved to be extremely slow.
5 5 This module provides decorators to try a different approach, stemming from a
6 6 conversation Brian and I (FP) had about this problem Sept/09.
7 7
8 8 The goal is to be able to easily write simple functions that can be seen by
9 9 unittest as tests, and ultimately for these to support doctests with full
10 10 IPython syntax. Nose already offers this based on naming conventions and our
11 11 hackish plugins, but we are seeking to move away from nose dependencies if
12 12 possible.
13 13
14 14 This module follows a different approach, based on decorators.
15 15
16 16 - A decorator called @ipdoctest can mark any function as having a docstring
17 17 that should be viewed as a doctest, but after syntax conversion.
18 18
19 19 Authors
20 20 -------
21 21
22 22 - Fernando Perez <Fernando.Perez@berkeley.edu>
23 23 """
24 24
25 25
26 26 #-----------------------------------------------------------------------------
27 27 # Copyright (C) 2009-2011 The IPython Development Team
28 28 #
29 29 # Distributed under the terms of the BSD License. The full license is in
30 30 # the file COPYING, distributed as part of this software.
31 31 #-----------------------------------------------------------------------------
32 32
33 33 #-----------------------------------------------------------------------------
34 34 # Imports
35 35 #-----------------------------------------------------------------------------
36 36
37 37 # Stdlib
38 38 import re
39 39 import unittest
40 40 from doctest import DocTestFinder, DocTestRunner, TestResults
41 41
42 42 #-----------------------------------------------------------------------------
43 43 # Classes and functions
44 44 #-----------------------------------------------------------------------------
45 45
46 46 def count_failures(runner):
47 47 """Count number of failures in a doctest runner.
48 48
49 49 Code modeled after the summarize() method in doctest.
50 50 """
51 51 return [TestResults(f, t) for f, t in runner._name2ft.values() if f > 0 ]
52 52
53 53
54 54 class IPython2PythonConverter(object):
55 55 """Convert IPython 'syntax' to valid Python.
56 56
57 57 Eventually this code may grow to be the full IPython syntax conversion
58 implementation, but for now it only does prompt convertion."""
58 implementation, but for now it only does prompt conversion."""
59 59
60 60 def __init__(self):
61 61 self.rps1 = re.compile(r'In\ \[\d+\]: ')
62 62 self.rps2 = re.compile(r'\ \ \ \.\.\.+: ')
63 63 self.rout = re.compile(r'Out\[\d+\]: \s*?\n?')
64 64 self.pyps1 = '>>> '
65 65 self.pyps2 = '... '
66 66 self.rpyps1 = re.compile ('(\s*%s)(.*)$' % self.pyps1)
67 67 self.rpyps2 = re.compile ('(\s*%s)(.*)$' % self.pyps2)
68 68
69 69 def __call__(self, ds):
70 70 """Convert IPython prompts to python ones in a string."""
71 71 from . import globalipapp
72 72
73 73 pyps1 = '>>> '
74 74 pyps2 = '... '
75 75 pyout = ''
76 76
77 77 dnew = ds
78 78 dnew = self.rps1.sub(pyps1, dnew)
79 79 dnew = self.rps2.sub(pyps2, dnew)
80 80 dnew = self.rout.sub(pyout, dnew)
81 81 ip = globalipapp.get_ipython()
82 82
83 83 # Convert input IPython source into valid Python.
84 84 out = []
85 85 newline = out.append
86 86 for line in dnew.splitlines():
87 87
88 88 mps1 = self.rpyps1.match(line)
89 89 if mps1 is not None:
90 90 prompt, text = mps1.groups()
91 91 newline(prompt+ip.prefilter(text, False))
92 92 continue
93 93
94 94 mps2 = self.rpyps2.match(line)
95 95 if mps2 is not None:
96 96 prompt, text = mps2.groups()
97 97 newline(prompt+ip.prefilter(text, True))
98 98 continue
99 99
100 100 newline(line)
101 101 newline('') # ensure a closing newline, needed by doctest
102 102 #print "PYSRC:", '\n'.join(out) # dbg
103 103 return '\n'.join(out)
104 104
105 105 #return dnew
106 106
107 107
108 108 class Doc2UnitTester(object):
109 109 """Class whose instances act as a decorator for docstring testing.
110 110
111 111 In practice we're only likely to need one instance ever, made below (though
112 112 no attempt is made at turning it into a singleton, there is no need for
113 113 that).
114 114 """
115 115 def __init__(self, verbose=False):
116 116 """New decorator.
117 117
118 118 Parameters
119 119 ----------
120 120
121 121 verbose : boolean, optional (False)
122 122 Passed to the doctest finder and runner to control verbosity.
123 123 """
124 124 self.verbose = verbose
125 125 # We can reuse the same finder for all instances
126 126 self.finder = DocTestFinder(verbose=verbose, recurse=False)
127 127
128 128 def __call__(self, func):
129 129 """Use as a decorator: doctest a function's docstring as a unittest.
130 130
131 131 This version runs normal doctests, but the idea is to make it later run
132 132 ipython syntax instead."""
133 133
134 134 # Capture the enclosing instance with a different name, so the new
135 135 # class below can see it without confusion regarding its own 'self'
136 136 # that will point to the test instance at runtime
137 137 d2u = self
138 138
139 139 # Rewrite the function's docstring to have python syntax
140 140 if func.__doc__ is not None:
141 141 func.__doc__ = ip2py(func.__doc__)
142 142
143 143 # Now, create a tester object that is a real unittest instance, so
144 144 # normal unittest machinery (or Nose, or Trial) can find it.
145 145 class Tester(unittest.TestCase):
146 146 def test(self):
147 147 # Make a new runner per function to be tested
148 148 runner = DocTestRunner(verbose=d2u.verbose)
149 149 map(runner.run, d2u.finder.find(func, func.__name__))
150 150 failed = count_failures(runner)
151 151 if failed:
152 152 # Since we only looked at a single function's docstring,
153 153 # failed should contain at most one item. More than that
154 154 # is a case we can't handle and should error out on
155 155 if len(failed) > 1:
156 156 err = "Invalid number of test results:" % failed
157 157 raise ValueError(err)
158 158 # Report a normal failure.
159 159 self.fail('failed doctests: %s' % str(failed[0]))
160 160
161 161 # Rename it so test reports have the original signature.
162 162 Tester.__name__ = func.__name__
163 163 return Tester
164 164
165 165
166 166 def ipdocstring(func):
167 167 """Change the function docstring via ip2py.
168 168 """
169 169 if func.__doc__ is not None:
170 170 func.__doc__ = ip2py(func.__doc__)
171 171 return func
172 172
173 173
174 174 # Make an instance of the classes for public use
175 175 ipdoctest = Doc2UnitTester()
176 176 ip2py = IPython2PythonConverter()
@@ -1,191 +1,191 b''
1 1 """Windows-specific implementation of process utilities.
2 2
3 3 This file is only meant to be imported by process.py, not by end-users.
4 4 """
5 5
6 6 #-----------------------------------------------------------------------------
7 7 # Copyright (C) 2010-2011 The IPython Development Team
8 8 #
9 9 # Distributed under the terms of the BSD License. The full license is in
10 10 # the file COPYING, distributed as part of this software.
11 11 #-----------------------------------------------------------------------------
12 12
13 13 #-----------------------------------------------------------------------------
14 14 # Imports
15 15 #-----------------------------------------------------------------------------
16 16
17 17 # stdlib
18 18 import os
19 19 import sys
20 20 import ctypes
21 21
22 22 from ctypes import c_int, POINTER
23 23 from ctypes.wintypes import LPCWSTR, HLOCAL
24 24 from subprocess import STDOUT
25 25
26 26 # our own imports
27 27 from ._process_common import read_no_interrupt, process_handler, arg_split as py_arg_split
28 28 from . import py3compat
29 29 from .encoding import DEFAULT_ENCODING
30 30
31 31 #-----------------------------------------------------------------------------
32 32 # Function definitions
33 33 #-----------------------------------------------------------------------------
34 34
35 35 class AvoidUNCPath(object):
36 36 """A context manager to protect command execution from UNC paths.
37 37
38 38 In the Win32 API, commands can't be invoked with the cwd being a UNC path.
39 39 This context manager temporarily changes directory to the 'C:' drive on
40 40 entering, and restores the original working directory on exit.
41 41
42 42 The context manager returns the starting working directory *if* it made a
43 43 change and None otherwise, so that users can apply the necessary adjustment
44 44 to their system calls in the event of a change.
45 45
46 46 Examples
47 47 --------
48 48 ::
49 49 cmd = 'dir'
50 50 with AvoidUNCPath() as path:
51 51 if path is not None:
52 52 cmd = '"pushd %s &&"%s' % (path, cmd)
53 53 os.system(cmd)
54 54 """
55 55 def __enter__(self):
56 56 self.path = os.getcwd()
57 57 self.is_unc_path = self.path.startswith(r"\\")
58 58 if self.is_unc_path:
59 59 # change to c drive (as cmd.exe cannot handle UNC addresses)
60 60 os.chdir("C:")
61 61 return self.path
62 62 else:
63 63 # We return None to signal that there was no change in the working
64 64 # directory
65 65 return None
66 66
67 67 def __exit__(self, exc_type, exc_value, traceback):
68 68 if self.is_unc_path:
69 69 os.chdir(self.path)
70 70
71 71
72 72 def _find_cmd(cmd):
73 73 """Find the full path to a .bat or .exe using the win32api module."""
74 74 try:
75 75 from win32api import SearchPath
76 76 except ImportError:
77 77 raise ImportError('you need to have pywin32 installed for this to work')
78 78 else:
79 79 PATH = os.environ['PATH']
80 80 extensions = ['.exe', '.com', '.bat', '.py']
81 81 path = None
82 82 for ext in extensions:
83 83 try:
84 84 path = SearchPath(PATH, cmd, ext)[0]
85 85 except:
86 86 pass
87 87 if path is None:
88 88 raise OSError("command %r not found" % cmd)
89 89 else:
90 90 return path
91 91
92 92
93 93 def _system_body(p):
94 94 """Callback for _system."""
95 95 enc = DEFAULT_ENCODING
96 96 for line in read_no_interrupt(p.stdout).splitlines():
97 97 line = line.decode(enc, 'replace')
98 98 print(line, file=sys.stdout)
99 99 for line in read_no_interrupt(p.stderr).splitlines():
100 100 line = line.decode(enc, 'replace')
101 101 print(line, file=sys.stderr)
102 102
103 103 # Wait to finish for returncode
104 104 return p.wait()
105 105
106 106
107 107 def system(cmd):
108 108 """Win32 version of os.system() that works with network shares.
109 109
110 110 Note that this implementation returns None, as meant for use in IPython.
111 111
112 112 Parameters
113 113 ----------
114 114 cmd : str or list
115 115 A command to be executed in the system shell.
116 116
117 117 Returns
118 118 -------
119 119 None : we explicitly do NOT return the subprocess status code, as this
120 120 utility is meant to be used extensively in IPython, where any return value
121 121 would trigger :func:`sys.displayhook` calls.
122 122 """
123 123 # The controller provides interactivity with both
124 124 # stdin and stdout
125 125 #import _process_win32_controller
126 126 #_process_win32_controller.system(cmd)
127 127
128 128 with AvoidUNCPath() as path:
129 129 if path is not None:
130 130 cmd = '"pushd %s &&"%s' % (path, cmd)
131 131 return process_handler(cmd, _system_body)
132 132
133 133 def getoutput(cmd):
134 134 """Return standard output of executing cmd in a shell.
135 135
136 136 Accepts the same arguments as os.system().
137 137
138 138 Parameters
139 139 ----------
140 140 cmd : str or list
141 141 A command to be executed in the system shell.
142 142
143 143 Returns
144 144 -------
145 145 stdout : str
146 146 """
147 147
148 148 with AvoidUNCPath() as path:
149 149 if path is not None:
150 150 cmd = '"pushd %s &&"%s' % (path, cmd)
151 151 out = process_handler(cmd, lambda p: p.communicate()[0], STDOUT)
152 152
153 153 if out is None:
154 154 out = b''
155 155 return py3compat.decode(out)
156 156
157 157 try:
158 158 CommandLineToArgvW = ctypes.windll.shell32.CommandLineToArgvW
159 159 CommandLineToArgvW.arg_types = [LPCWSTR, POINTER(c_int)]
160 160 CommandLineToArgvW.restype = POINTER(LPCWSTR)
161 161 LocalFree = ctypes.windll.kernel32.LocalFree
162 162 LocalFree.res_type = HLOCAL
163 163 LocalFree.arg_types = [HLOCAL]
164 164
165 165 def arg_split(commandline, posix=False, strict=True):
166 166 """Split a command line's arguments in a shell-like manner.
167 167
168 168 This is a special version for windows that use a ctypes call to CommandLineToArgvW
169 to do the argv splitting. The posix paramter is ignored.
169 to do the argv splitting. The posix parameter is ignored.
170 170
171 171 If strict=False, process_common.arg_split(...strict=False) is used instead.
172 172 """
173 173 #CommandLineToArgvW returns path to executable if called with empty string.
174 174 if commandline.strip() == "":
175 175 return []
176 176 if not strict:
177 177 # not really a cl-arg, fallback on _process_common
178 178 return py_arg_split(commandline, posix=posix, strict=strict)
179 179 argvn = c_int()
180 180 result_pointer = CommandLineToArgvW(py3compat.cast_unicode(commandline.lstrip()), ctypes.byref(argvn))
181 181 result_array_type = LPCWSTR * argvn.value
182 182 result = [arg for arg in result_array_type.from_address(ctypes.addressof(result_pointer.contents))]
183 183 retval = LocalFree(result_pointer)
184 184 return result
185 185 except AttributeError:
186 186 arg_split = py_arg_split
187 187
188 188 def check_pid(pid):
189 189 # OpenProcess returns 0 if no such process (of ours) exists
190 190 # positive int otherwise
191 191 return bool(ctypes.windll.kernel32.OpenProcess(1,0,pid))
@@ -1,438 +1,438 b''
1 1 # encoding: utf-8
2 2 """
3 3 Utilities for path handling.
4 4 """
5 5
6 6 # Copyright (c) IPython Development Team.
7 7 # Distributed under the terms of the Modified BSD License.
8 8
9 9 import os
10 10 import sys
11 11 import errno
12 12 import shutil
13 13 import random
14 14 import glob
15 15 from warnings import warn
16 16
17 17 from IPython.utils.process import system
18 18 from IPython.utils import py3compat
19 19 from IPython.utils.decorators import undoc
20 20
21 21 #-----------------------------------------------------------------------------
22 22 # Code
23 23 #-----------------------------------------------------------------------------
24 24
25 25 fs_encoding = sys.getfilesystemencoding()
26 26
27 27 def _writable_dir(path):
28 28 """Whether `path` is a directory, to which the user has write access."""
29 29 return os.path.isdir(path) and os.access(path, os.W_OK)
30 30
31 31 if sys.platform == 'win32':
32 32 def _get_long_path_name(path):
33 33 """Get a long path name (expand ~) on Windows using ctypes.
34 34
35 35 Examples
36 36 --------
37 37
38 38 >>> get_long_path_name('c:\\docume~1')
39 39 'c:\\\\Documents and Settings'
40 40
41 41 """
42 42 try:
43 43 import ctypes
44 44 except ImportError:
45 45 raise ImportError('you need to have ctypes installed for this to work')
46 46 _GetLongPathName = ctypes.windll.kernel32.GetLongPathNameW
47 47 _GetLongPathName.argtypes = [ctypes.c_wchar_p, ctypes.c_wchar_p,
48 48 ctypes.c_uint ]
49 49
50 50 buf = ctypes.create_unicode_buffer(260)
51 51 rv = _GetLongPathName(path, buf, 260)
52 52 if rv == 0 or rv > 260:
53 53 return path
54 54 else:
55 55 return buf.value
56 56 else:
57 57 def _get_long_path_name(path):
58 58 """Dummy no-op."""
59 59 return path
60 60
61 61
62 62
63 63 def get_long_path_name(path):
64 64 """Expand a path into its long form.
65 65
66 66 On Windows this expands any ~ in the paths. On other platforms, it is
67 67 a null operation.
68 68 """
69 69 return _get_long_path_name(path)
70 70
71 71
72 72 def unquote_filename(name, win32=(sys.platform=='win32')):
73 73 """ On Windows, remove leading and trailing quotes from filenames.
74 74
75 75 This function has been deprecated and should not be used any more:
76 76 unquoting is now taken care of by :func:`IPython.utils.process.arg_split`.
77 77 """
78 78 warn("'unquote_filename' is deprecated since IPython 5.0 and should not "
79 79 "be used anymore", DeprecationWarning, stacklevel=2)
80 80 if win32:
81 81 if name.startswith(("'", '"')) and name.endswith(("'", '"')):
82 82 name = name[1:-1]
83 83 return name
84 84
85 85
86 86 def compress_user(path):
87 87 """Reverse of :func:`os.path.expanduser`
88 88 """
89 89 home = os.path.expanduser('~')
90 90 if path.startswith(home):
91 91 path = "~" + path[len(home):]
92 92 return path
93 93
94 94 def get_py_filename(name, force_win32=None):
95 95 """Return a valid python filename in the current directory.
96 96
97 97 If the given name is not a file, it adds '.py' and searches again.
98 98 Raises IOError with an informative message if the file isn't found.
99 99 """
100 100
101 101 name = os.path.expanduser(name)
102 102 if force_win32 is not None:
103 103 warn("The 'force_win32' argument to 'get_py_filename' is deprecated "
104 104 "since IPython 5.0 and should not be used anymore",
105 105 DeprecationWarning, stacklevel=2)
106 106 if not os.path.isfile(name) and not name.endswith('.py'):
107 107 name += '.py'
108 108 if os.path.isfile(name):
109 109 return name
110 110 else:
111 111 raise IOError('File `%r` not found.' % name)
112 112
113 113
114 114 def filefind(filename, path_dirs=None):
115 115 """Find a file by looking through a sequence of paths.
116 116
117 117 This iterates through a sequence of paths looking for a file and returns
118 the full, absolute path of the first occurence of the file. If no set of
118 the full, absolute path of the first occurrence of the file. If no set of
119 119 path dirs is given, the filename is tested as is, after running through
120 120 :func:`expandvars` and :func:`expanduser`. Thus a simple call::
121 121
122 122 filefind('myfile.txt')
123 123
124 124 will find the file in the current working dir, but::
125 125
126 126 filefind('~/myfile.txt')
127 127
128 128 Will find the file in the users home directory. This function does not
129 129 automatically try any paths, such as the cwd or the user's home directory.
130 130
131 131 Parameters
132 132 ----------
133 133 filename : str
134 134 The filename to look for.
135 135 path_dirs : str, None or sequence of str
136 136 The sequence of paths to look for the file in. If None, the filename
137 137 need to be absolute or be in the cwd. If a string, the string is
138 138 put into a sequence and the searched. If a sequence, walk through
139 139 each element and join with ``filename``, calling :func:`expandvars`
140 140 and :func:`expanduser` before testing for existence.
141 141
142 142 Returns
143 143 -------
144 144 Raises :exc:`IOError` or returns absolute path to file.
145 145 """
146 146
147 147 # If paths are quoted, abspath gets confused, strip them...
148 148 filename = filename.strip('"').strip("'")
149 149 # If the input is an absolute path, just check it exists
150 150 if os.path.isabs(filename) and os.path.isfile(filename):
151 151 return filename
152 152
153 153 if path_dirs is None:
154 154 path_dirs = ("",)
155 155 elif isinstance(path_dirs, str):
156 156 path_dirs = (path_dirs,)
157 157
158 158 for path in path_dirs:
159 159 if path == '.': path = os.getcwd()
160 160 testname = expand_path(os.path.join(path, filename))
161 161 if os.path.isfile(testname):
162 162 return os.path.abspath(testname)
163 163
164 164 raise IOError("File %r does not exist in any of the search paths: %r" %
165 165 (filename, path_dirs) )
166 166
167 167
168 168 class HomeDirError(Exception):
169 169 pass
170 170
171 171
172 172 def get_home_dir(require_writable=False):
173 173 """Return the 'home' directory, as a unicode string.
174 174
175 175 Uses os.path.expanduser('~'), and checks for writability.
176 176
177 177 See stdlib docs for how this is determined.
178 178 $HOME is first priority on *ALL* platforms.
179 179
180 180 Parameters
181 181 ----------
182 182
183 183 require_writable : bool [default: False]
184 184 if True:
185 185 guarantees the return value is a writable directory, otherwise
186 186 raises HomeDirError
187 187 if False:
188 188 The path is resolved, but it is not guaranteed to exist or be writable.
189 189 """
190 190
191 191 homedir = os.path.expanduser('~')
192 192 # Next line will make things work even when /home/ is a symlink to
193 193 # /usr/home as it is on FreeBSD, for example
194 194 homedir = os.path.realpath(homedir)
195 195
196 196 if not _writable_dir(homedir) and os.name == 'nt':
197 197 # expanduser failed, use the registry to get the 'My Documents' folder.
198 198 try:
199 199 try:
200 200 import winreg as wreg # Py 3
201 201 except ImportError:
202 202 import _winreg as wreg # Py 2
203 203 key = wreg.OpenKey(
204 204 wreg.HKEY_CURRENT_USER,
205 205 "Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders"
206 206 )
207 207 homedir = wreg.QueryValueEx(key,'Personal')[0]
208 208 key.Close()
209 209 except:
210 210 pass
211 211
212 212 if (not require_writable) or _writable_dir(homedir):
213 213 return py3compat.cast_unicode(homedir, fs_encoding)
214 214 else:
215 215 raise HomeDirError('%s is not a writable dir, '
216 216 'set $HOME environment variable to override' % homedir)
217 217
218 218 def get_xdg_dir():
219 219 """Return the XDG_CONFIG_HOME, if it is defined and exists, else None.
220 220
221 221 This is only for non-OS X posix (Linux,Unix,etc.) systems.
222 222 """
223 223
224 224 env = os.environ
225 225
226 226 if os.name == 'posix' and sys.platform != 'darwin':
227 227 # Linux, Unix, AIX, etc.
228 228 # use ~/.config if empty OR not set
229 229 xdg = env.get("XDG_CONFIG_HOME", None) or os.path.join(get_home_dir(), '.config')
230 230 if xdg and _writable_dir(xdg):
231 231 return py3compat.cast_unicode(xdg, fs_encoding)
232 232
233 233 return None
234 234
235 235
236 236 def get_xdg_cache_dir():
237 237 """Return the XDG_CACHE_HOME, if it is defined and exists, else None.
238 238
239 239 This is only for non-OS X posix (Linux,Unix,etc.) systems.
240 240 """
241 241
242 242 env = os.environ
243 243
244 244 if os.name == 'posix' and sys.platform != 'darwin':
245 245 # Linux, Unix, AIX, etc.
246 246 # use ~/.cache if empty OR not set
247 247 xdg = env.get("XDG_CACHE_HOME", None) or os.path.join(get_home_dir(), '.cache')
248 248 if xdg and _writable_dir(xdg):
249 249 return py3compat.cast_unicode(xdg, fs_encoding)
250 250
251 251 return None
252 252
253 253
254 254 @undoc
255 255 def get_ipython_dir():
256 256 warn("get_ipython_dir has moved to the IPython.paths module since IPython 4.0.", stacklevel=2)
257 257 from IPython.paths import get_ipython_dir
258 258 return get_ipython_dir()
259 259
260 260 @undoc
261 261 def get_ipython_cache_dir():
262 262 warn("get_ipython_cache_dir has moved to the IPython.paths module since IPython 4.0.", stacklevel=2)
263 263 from IPython.paths import get_ipython_cache_dir
264 264 return get_ipython_cache_dir()
265 265
266 266 @undoc
267 267 def get_ipython_package_dir():
268 268 warn("get_ipython_package_dir has moved to the IPython.paths module since IPython 4.0.", stacklevel=2)
269 269 from IPython.paths import get_ipython_package_dir
270 270 return get_ipython_package_dir()
271 271
272 272 @undoc
273 273 def get_ipython_module_path(module_str):
274 274 warn("get_ipython_module_path has moved to the IPython.paths module since IPython 4.0.", stacklevel=2)
275 275 from IPython.paths import get_ipython_module_path
276 276 return get_ipython_module_path(module_str)
277 277
278 278 @undoc
279 279 def locate_profile(profile='default'):
280 280 warn("locate_profile has moved to the IPython.paths module since IPython 4.0.", stacklevel=2)
281 281 from IPython.paths import locate_profile
282 282 return locate_profile(profile=profile)
283 283
284 284 def expand_path(s):
285 285 """Expand $VARS and ~names in a string, like a shell
286 286
287 287 :Examples:
288 288
289 289 In [2]: os.environ['FOO']='test'
290 290
291 291 In [3]: expand_path('variable FOO is $FOO')
292 292 Out[3]: 'variable FOO is test'
293 293 """
294 294 # This is a pretty subtle hack. When expand user is given a UNC path
295 295 # on Windows (\\server\share$\%username%), os.path.expandvars, removes
296 296 # the $ to get (\\server\share\%username%). I think it considered $
297 297 # alone an empty var. But, we need the $ to remains there (it indicates
298 298 # a hidden share).
299 299 if os.name=='nt':
300 300 s = s.replace('$\\', 'IPYTHON_TEMP')
301 301 s = os.path.expandvars(os.path.expanduser(s))
302 302 if os.name=='nt':
303 303 s = s.replace('IPYTHON_TEMP', '$\\')
304 304 return s
305 305
306 306
307 307 def unescape_glob(string):
308 308 """Unescape glob pattern in `string`."""
309 309 def unescape(s):
310 310 for pattern in '*[]!?':
311 311 s = s.replace(r'\{0}'.format(pattern), pattern)
312 312 return s
313 313 return '\\'.join(map(unescape, string.split('\\\\')))
314 314
315 315
316 316 def shellglob(args):
317 317 """
318 318 Do glob expansion for each element in `args` and return a flattened list.
319 319
320 320 Unmatched glob pattern will remain as-is in the returned list.
321 321
322 322 """
323 323 expanded = []
324 324 # Do not unescape backslash in Windows as it is interpreted as
325 325 # path separator:
326 326 unescape = unescape_glob if sys.platform != 'win32' else lambda x: x
327 327 for a in args:
328 328 expanded.extend(glob.glob(a) or [unescape(a)])
329 329 return expanded
330 330
331 331
332 332 def target_outdated(target,deps):
333 333 """Determine whether a target is out of date.
334 334
335 335 target_outdated(target,deps) -> 1/0
336 336
337 337 deps: list of filenames which MUST exist.
338 338 target: single filename which may or may not exist.
339 339
340 340 If target doesn't exist or is older than any file listed in deps, return
341 341 true, otherwise return false.
342 342 """
343 343 try:
344 344 target_time = os.path.getmtime(target)
345 345 except os.error:
346 346 return 1
347 347 for dep in deps:
348 348 dep_time = os.path.getmtime(dep)
349 349 if dep_time > target_time:
350 350 #print "For target",target,"Dep failed:",dep # dbg
351 351 #print "times (dep,tar):",dep_time,target_time # dbg
352 352 return 1
353 353 return 0
354 354
355 355
356 356 def target_update(target,deps,cmd):
357 357 """Update a target with a given command given a list of dependencies.
358 358
359 359 target_update(target,deps,cmd) -> runs cmd if target is outdated.
360 360
361 361 This is just a wrapper around target_outdated() which calls the given
362 362 command if target is outdated."""
363 363
364 364 if target_outdated(target,deps):
365 365 system(cmd)
366 366
367 367
368 368 ENOLINK = 1998
369 369
370 370 def link(src, dst):
371 371 """Hard links ``src`` to ``dst``, returning 0 or errno.
372 372
373 373 Note that the special errno ``ENOLINK`` will be returned if ``os.link`` isn't
374 374 supported by the operating system.
375 375 """
376 376
377 377 if not hasattr(os, "link"):
378 378 return ENOLINK
379 379 link_errno = 0
380 380 try:
381 381 os.link(src, dst)
382 382 except OSError as e:
383 383 link_errno = e.errno
384 384 return link_errno
385 385
386 386
387 387 def link_or_copy(src, dst):
388 388 """Attempts to hardlink ``src`` to ``dst``, copying if the link fails.
389 389
390 390 Attempts to maintain the semantics of ``shutil.copy``.
391 391
392 392 Because ``os.link`` does not overwrite files, a unique temporary file
393 393 will be used if the target already exists, then that file will be moved
394 394 into place.
395 395 """
396 396
397 397 if os.path.isdir(dst):
398 398 dst = os.path.join(dst, os.path.basename(src))
399 399
400 400 link_errno = link(src, dst)
401 401 if link_errno == errno.EEXIST:
402 402 if os.stat(src).st_ino == os.stat(dst).st_ino:
403 403 # dst is already a hard link to the correct file, so we don't need
404 404 # to do anything else. If we try to link and rename the file
405 405 # anyway, we get duplicate files - see http://bugs.python.org/issue21876
406 406 return
407 407
408 408 new_dst = dst + "-temp-%04X" %(random.randint(1, 16**4), )
409 409 try:
410 410 link_or_copy(src, new_dst)
411 411 except:
412 412 try:
413 413 os.remove(new_dst)
414 414 except OSError:
415 415 pass
416 416 raise
417 417 os.rename(new_dst, dst)
418 418 elif link_errno != 0:
419 419 # Either link isn't supported, or the filesystem doesn't support
420 420 # linking, or 'src' and 'dst' are on different filesystems.
421 421 shutil.copy(src, dst)
422 422
423 423 def ensure_dir_exists(path, mode=0o755):
424 424 """ensure that a directory exists
425 425
426 426 If it doesn't exist, try to create it and protect against a race condition
427 427 if another process is doing the same.
428 428
429 429 The default permissions are 755, which differ from os.makedirs default of 777.
430 430 """
431 431 if not os.path.exists(path):
432 432 try:
433 433 os.makedirs(path, mode=mode)
434 434 except OSError as e:
435 435 if e.errno != errno.EEXIST:
436 436 raise
437 437 elif not os.path.isdir(path):
438 438 raise IOError("%r exists but is not a directory" % path)
@@ -1,481 +1,481 b''
1 1 # encoding: utf-8
2 2 """Tests for IPython.utils.path.py"""
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 import shutil
9 9 import sys
10 10 import tempfile
11 11 import unittest
12 12 from contextlib import contextmanager
13 13 from unittest.mock import patch
14 14 from os.path import join, abspath
15 15 from imp import reload
16 16
17 17 from nose import SkipTest, with_setup
18 18 import nose.tools as nt
19 19
20 20 import IPython
21 21 from IPython import paths
22 22 from IPython.testing import decorators as dec
23 23 from IPython.testing.decorators import (skip_if_not_win32, skip_win32,
24 24 onlyif_unicode_paths,)
25 25 from IPython.testing.tools import make_tempfile, AssertPrints
26 26 from IPython.utils import path
27 27 from IPython.utils.tempdir import TemporaryDirectory
28 28
29 29 # Platform-dependent imports
30 30 try:
31 31 import winreg as wreg
32 32 except ImportError:
33 33 #Fake _winreg module on non-windows platforms
34 34 import types
35 35 wr_name = "winreg"
36 36 sys.modules[wr_name] = types.ModuleType(wr_name)
37 37 try:
38 38 import winreg as wreg
39 39 except ImportError:
40 40 import _winreg as wreg
41 41 #Add entries that needs to be stubbed by the testing code
42 42 (wreg.OpenKey, wreg.QueryValueEx,) = (None, None)
43 43
44 44 #-----------------------------------------------------------------------------
45 45 # Globals
46 46 #-----------------------------------------------------------------------------
47 47 env = os.environ
48 48 TMP_TEST_DIR = tempfile.mkdtemp()
49 49 HOME_TEST_DIR = join(TMP_TEST_DIR, "home_test_dir")
50 50 #
51 51 # Setup/teardown functions/decorators
52 52 #
53 53
54 54 def setup():
55 55 """Setup testenvironment for the module:
56 56
57 57 - Adds dummy home dir tree
58 58 """
59 59 # Do not mask exceptions here. In particular, catching WindowsError is a
60 60 # problem because that exception is only defined on Windows...
61 61 os.makedirs(os.path.join(HOME_TEST_DIR, 'ipython'))
62 62
63 63
64 64 def teardown():
65 65 """Teardown testenvironment for the module:
66 66
67 67 - Remove dummy home dir tree
68 68 """
69 69 # Note: we remove the parent test dir, which is the root of all test
70 70 # subdirs we may have created. Use shutil instead of os.removedirs, so
71 71 # that non-empty directories are all recursively removed.
72 72 shutil.rmtree(TMP_TEST_DIR)
73 73
74 74
75 75 def setup_environment():
76 76 """Setup testenvironment for some functions that are tested
77 77 in this module. In particular this functions stores attributes
78 78 and other things that we need to stub in some test functions.
79 79 This needs to be done on a function level and not module level because
80 80 each testfunction needs a pristine environment.
81 81 """
82 82 global oldstuff, platformstuff
83 83 oldstuff = (env.copy(), os.name, sys.platform, path.get_home_dir, IPython.__file__, os.getcwd())
84 84
85 85 def teardown_environment():
86 86 """Restore things that were remembered by the setup_environment function
87 87 """
88 88 (oldenv, os.name, sys.platform, path.get_home_dir, IPython.__file__, old_wd) = oldstuff
89 89 os.chdir(old_wd)
90 90 reload(path)
91 91
92 92 for key in list(env):
93 93 if key not in oldenv:
94 94 del env[key]
95 95 env.update(oldenv)
96 96 if hasattr(sys, 'frozen'):
97 97 del sys.frozen
98 98
99 99 # Build decorator that uses the setup_environment/setup_environment
100 100 with_environment = with_setup(setup_environment, teardown_environment)
101 101
102 102 @skip_if_not_win32
103 103 @with_environment
104 104 def test_get_home_dir_1():
105 105 """Testcase for py2exe logic, un-compressed lib
106 106 """
107 107 unfrozen = path.get_home_dir()
108 108 sys.frozen = True
109 109
110 110 #fake filename for IPython.__init__
111 111 IPython.__file__ = abspath(join(HOME_TEST_DIR, "Lib/IPython/__init__.py"))
112 112
113 113 home_dir = path.get_home_dir()
114 114 nt.assert_equal(home_dir, unfrozen)
115 115
116 116
117 117 @skip_if_not_win32
118 118 @with_environment
119 119 def test_get_home_dir_2():
120 120 """Testcase for py2exe logic, compressed lib
121 121 """
122 122 unfrozen = path.get_home_dir()
123 123 sys.frozen = True
124 124 #fake filename for IPython.__init__
125 125 IPython.__file__ = abspath(join(HOME_TEST_DIR, "Library.zip/IPython/__init__.py")).lower()
126 126
127 127 home_dir = path.get_home_dir(True)
128 128 nt.assert_equal(home_dir, unfrozen)
129 129
130 130
131 131 @with_environment
132 132 def test_get_home_dir_3():
133 133 """get_home_dir() uses $HOME if set"""
134 134 env["HOME"] = HOME_TEST_DIR
135 135 home_dir = path.get_home_dir(True)
136 136 # get_home_dir expands symlinks
137 137 nt.assert_equal(home_dir, os.path.realpath(env["HOME"]))
138 138
139 139
140 140 @with_environment
141 141 def test_get_home_dir_4():
142 142 """get_home_dir() still works if $HOME is not set"""
143 143
144 144 if 'HOME' in env: del env['HOME']
145 145 # this should still succeed, but we don't care what the answer is
146 146 home = path.get_home_dir(False)
147 147
148 148 @with_environment
149 149 def test_get_home_dir_5():
150 150 """raise HomeDirError if $HOME is specified, but not a writable dir"""
151 151 env['HOME'] = abspath(HOME_TEST_DIR+'garbage')
152 152 # set os.name = posix, to prevent My Documents fallback on Windows
153 153 os.name = 'posix'
154 154 nt.assert_raises(path.HomeDirError, path.get_home_dir, True)
155 155
156 156 # Should we stub wreg fully so we can run the test on all platforms?
157 157 @skip_if_not_win32
158 158 @with_environment
159 159 def test_get_home_dir_8():
160 160 """Using registry hack for 'My Documents', os=='nt'
161 161
162 162 HOMESHARE, HOMEDRIVE, HOMEPATH, USERPROFILE and others are missing.
163 163 """
164 164 os.name = 'nt'
165 165 # Remove from stub environment all keys that may be set
166 166 for key in ['HOME', 'HOMESHARE', 'HOMEDRIVE', 'HOMEPATH', 'USERPROFILE']:
167 167 env.pop(key, None)
168 168
169 169 class key:
170 170 def Close(self):
171 171 pass
172 172
173 173 with patch.object(wreg, 'OpenKey', return_value=key()), \
174 174 patch.object(wreg, 'QueryValueEx', return_value=[abspath(HOME_TEST_DIR)]):
175 175 home_dir = path.get_home_dir()
176 176 nt.assert_equal(home_dir, abspath(HOME_TEST_DIR))
177 177
178 178 @with_environment
179 179 def test_get_xdg_dir_0():
180 180 """test_get_xdg_dir_0, check xdg_dir"""
181 181 reload(path)
182 182 path._writable_dir = lambda path: True
183 183 path.get_home_dir = lambda : 'somewhere'
184 184 os.name = "posix"
185 185 sys.platform = "linux2"
186 186 env.pop('IPYTHON_DIR', None)
187 187 env.pop('IPYTHONDIR', None)
188 188 env.pop('XDG_CONFIG_HOME', None)
189 189
190 190 nt.assert_equal(path.get_xdg_dir(), os.path.join('somewhere', '.config'))
191 191
192 192
193 193 @with_environment
194 194 def test_get_xdg_dir_1():
195 """test_get_xdg_dir_1, check nonexistant xdg_dir"""
195 """test_get_xdg_dir_1, check nonexistent xdg_dir"""
196 196 reload(path)
197 197 path.get_home_dir = lambda : HOME_TEST_DIR
198 198 os.name = "posix"
199 199 sys.platform = "linux2"
200 200 env.pop('IPYTHON_DIR', None)
201 201 env.pop('IPYTHONDIR', None)
202 202 env.pop('XDG_CONFIG_HOME', None)
203 203 nt.assert_equal(path.get_xdg_dir(), None)
204 204
205 205 @with_environment
206 206 def test_get_xdg_dir_2():
207 207 """test_get_xdg_dir_2, check xdg_dir default to ~/.config"""
208 208 reload(path)
209 209 path.get_home_dir = lambda : HOME_TEST_DIR
210 210 os.name = "posix"
211 211 sys.platform = "linux2"
212 212 env.pop('IPYTHON_DIR', None)
213 213 env.pop('IPYTHONDIR', None)
214 214 env.pop('XDG_CONFIG_HOME', None)
215 215 cfgdir=os.path.join(path.get_home_dir(), '.config')
216 216 if not os.path.exists(cfgdir):
217 217 os.makedirs(cfgdir)
218 218
219 219 nt.assert_equal(path.get_xdg_dir(), cfgdir)
220 220
221 221 @with_environment
222 222 def test_get_xdg_dir_3():
223 223 """test_get_xdg_dir_3, check xdg_dir not used on OS X"""
224 224 reload(path)
225 225 path.get_home_dir = lambda : HOME_TEST_DIR
226 226 os.name = "posix"
227 227 sys.platform = "darwin"
228 228 env.pop('IPYTHON_DIR', None)
229 229 env.pop('IPYTHONDIR', None)
230 230 env.pop('XDG_CONFIG_HOME', None)
231 231 cfgdir=os.path.join(path.get_home_dir(), '.config')
232 232 if not os.path.exists(cfgdir):
233 233 os.makedirs(cfgdir)
234 234
235 235 nt.assert_equal(path.get_xdg_dir(), None)
236 236
237 237 def test_filefind():
238 238 """Various tests for filefind"""
239 239 f = tempfile.NamedTemporaryFile()
240 240 # print 'fname:',f.name
241 241 alt_dirs = paths.get_ipython_dir()
242 242 t = path.filefind(f.name, alt_dirs)
243 243 # print 'found:',t
244 244
245 245
246 246 @dec.skip_if_not_win32
247 247 def test_get_long_path_name_win32():
248 248 with TemporaryDirectory() as tmpdir:
249 249
250 250 # Make a long path. Expands the path of tmpdir prematurely as it may already have a long
251 251 # path component, so ensure we include the long form of it
252 252 long_path = os.path.join(path.get_long_path_name(tmpdir), 'this is my long path name')
253 253 os.makedirs(long_path)
254 254
255 255 # Test to see if the short path evaluates correctly.
256 256 short_path = os.path.join(tmpdir, 'THISIS~1')
257 257 evaluated_path = path.get_long_path_name(short_path)
258 258 nt.assert_equal(evaluated_path.lower(), long_path.lower())
259 259
260 260
261 261 @dec.skip_win32
262 262 def test_get_long_path_name():
263 263 p = path.get_long_path_name('/usr/local')
264 264 nt.assert_equal(p,'/usr/local')
265 265
266 266 @dec.skip_win32 # can't create not-user-writable dir on win
267 267 @with_environment
268 268 def test_not_writable_ipdir():
269 269 tmpdir = tempfile.mkdtemp()
270 270 os.name = "posix"
271 271 env.pop('IPYTHON_DIR', None)
272 272 env.pop('IPYTHONDIR', None)
273 273 env.pop('XDG_CONFIG_HOME', None)
274 274 env['HOME'] = tmpdir
275 275 ipdir = os.path.join(tmpdir, '.ipython')
276 276 os.mkdir(ipdir, 0o555)
277 277 try:
278 278 open(os.path.join(ipdir, "_foo_"), 'w').close()
279 279 except IOError:
280 280 pass
281 281 else:
282 282 # I can still write to an unwritable dir,
283 283 # assume I'm root and skip the test
284 284 raise SkipTest("I can't create directories that I can't write to")
285 285 with AssertPrints('is not a writable location', channel='stderr'):
286 286 ipdir = paths.get_ipython_dir()
287 287 env.pop('IPYTHON_DIR', None)
288 288
289 289 @with_environment
290 290 def test_get_py_filename():
291 291 os.chdir(TMP_TEST_DIR)
292 292 with make_tempfile('foo.py'):
293 293 nt.assert_equal(path.get_py_filename('foo.py'), 'foo.py')
294 294 nt.assert_equal(path.get_py_filename('foo'), 'foo.py')
295 295 with make_tempfile('foo'):
296 296 nt.assert_equal(path.get_py_filename('foo'), 'foo')
297 297 nt.assert_raises(IOError, path.get_py_filename, 'foo.py')
298 298 nt.assert_raises(IOError, path.get_py_filename, 'foo')
299 299 nt.assert_raises(IOError, path.get_py_filename, 'foo.py')
300 300 true_fn = 'foo with spaces.py'
301 301 with make_tempfile(true_fn):
302 302 nt.assert_equal(path.get_py_filename('foo with spaces'), true_fn)
303 303 nt.assert_equal(path.get_py_filename('foo with spaces.py'), true_fn)
304 304 nt.assert_raises(IOError, path.get_py_filename, '"foo with spaces.py"')
305 305 nt.assert_raises(IOError, path.get_py_filename, "'foo with spaces.py'")
306 306
307 307 @onlyif_unicode_paths
308 308 def test_unicode_in_filename():
309 309 """When a file doesn't exist, the exception raised should be safe to call
310 310 str() on - i.e. in Python 2 it must only have ASCII characters.
311 311
312 312 https://github.com/ipython/ipython/issues/875
313 313 """
314 314 try:
315 315 # these calls should not throw unicode encode exceptions
316 316 path.get_py_filename('fooéè.py', force_win32=False)
317 317 except IOError as ex:
318 318 str(ex)
319 319
320 320
321 321 class TestShellGlob(unittest.TestCase):
322 322
323 323 @classmethod
324 324 def setUpClass(cls):
325 325 cls.filenames_start_with_a = ['a0', 'a1', 'a2']
326 326 cls.filenames_end_with_b = ['0b', '1b', '2b']
327 327 cls.filenames = cls.filenames_start_with_a + cls.filenames_end_with_b
328 328 cls.tempdir = TemporaryDirectory()
329 329 td = cls.tempdir.name
330 330
331 331 with cls.in_tempdir():
332 332 # Create empty files
333 333 for fname in cls.filenames:
334 334 open(os.path.join(td, fname), 'w').close()
335 335
336 336 @classmethod
337 337 def tearDownClass(cls):
338 338 cls.tempdir.cleanup()
339 339
340 340 @classmethod
341 341 @contextmanager
342 342 def in_tempdir(cls):
343 343 save = os.getcwd()
344 344 try:
345 345 os.chdir(cls.tempdir.name)
346 346 yield
347 347 finally:
348 348 os.chdir(save)
349 349
350 350 def check_match(self, patterns, matches):
351 351 with self.in_tempdir():
352 352 # glob returns unordered list. that's why sorted is required.
353 353 nt.assert_equal(sorted(path.shellglob(patterns)),
354 354 sorted(matches))
355 355
356 356 def common_cases(self):
357 357 return [
358 358 (['*'], self.filenames),
359 359 (['a*'], self.filenames_start_with_a),
360 360 (['*c'], ['*c']),
361 361 (['*', 'a*', '*b', '*c'], self.filenames
362 362 + self.filenames_start_with_a
363 363 + self.filenames_end_with_b
364 364 + ['*c']),
365 365 (['a[012]'], self.filenames_start_with_a),
366 366 ]
367 367
368 368 @skip_win32
369 369 def test_match_posix(self):
370 370 for (patterns, matches) in self.common_cases() + [
371 371 ([r'\*'], ['*']),
372 372 ([r'a\*', 'a*'], ['a*'] + self.filenames_start_with_a),
373 373 ([r'a\[012]'], ['a[012]']),
374 374 ]:
375 375 yield (self.check_match, patterns, matches)
376 376
377 377 @skip_if_not_win32
378 378 def test_match_windows(self):
379 379 for (patterns, matches) in self.common_cases() + [
380 380 # In windows, backslash is interpreted as path
381 381 # separator. Therefore, you can't escape glob
382 382 # using it.
383 383 ([r'a\*', 'a*'], [r'a\*'] + self.filenames_start_with_a),
384 384 ([r'a\[012]'], [r'a\[012]']),
385 385 ]:
386 386 yield (self.check_match, patterns, matches)
387 387
388 388
389 389 def test_unescape_glob():
390 390 nt.assert_equal(path.unescape_glob(r'\*\[\!\]\?'), '*[!]?')
391 391 nt.assert_equal(path.unescape_glob(r'\\*'), r'\*')
392 392 nt.assert_equal(path.unescape_glob(r'\\\*'), r'\*')
393 393 nt.assert_equal(path.unescape_glob(r'\\a'), r'\a')
394 394 nt.assert_equal(path.unescape_glob(r'\a'), r'\a')
395 395
396 396
397 397 @onlyif_unicode_paths
398 398 def test_ensure_dir_exists():
399 399 with TemporaryDirectory() as td:
400 400 d = os.path.join(td, '∂ir')
401 401 path.ensure_dir_exists(d) # create it
402 402 assert os.path.isdir(d)
403 403 path.ensure_dir_exists(d) # no-op
404 404 f = os.path.join(td, 'ƒile')
405 405 open(f, 'w').close() # touch
406 406 with nt.assert_raises(IOError):
407 407 path.ensure_dir_exists(f)
408 408
409 409 class TestLinkOrCopy(object):
410 410 def setUp(self):
411 411 self.tempdir = TemporaryDirectory()
412 412 self.src = self.dst("src")
413 413 with open(self.src, "w") as f:
414 414 f.write("Hello, world!")
415 415
416 416 def tearDown(self):
417 417 self.tempdir.cleanup()
418 418
419 419 def dst(self, *args):
420 420 return os.path.join(self.tempdir.name, *args)
421 421
422 422 def assert_inode_not_equal(self, a, b):
423 423 nt.assert_not_equal(os.stat(a).st_ino, os.stat(b).st_ino,
424 424 "%r and %r do reference the same indoes" %(a, b))
425 425
426 426 def assert_inode_equal(self, a, b):
427 427 nt.assert_equal(os.stat(a).st_ino, os.stat(b).st_ino,
428 428 "%r and %r do not reference the same indoes" %(a, b))
429 429
430 430 def assert_content_equal(self, a, b):
431 431 with open(a) as a_f:
432 432 with open(b) as b_f:
433 433 nt.assert_equal(a_f.read(), b_f.read())
434 434
435 435 @skip_win32
436 436 def test_link_successful(self):
437 437 dst = self.dst("target")
438 438 path.link_or_copy(self.src, dst)
439 439 self.assert_inode_equal(self.src, dst)
440 440
441 441 @skip_win32
442 442 def test_link_into_dir(self):
443 443 dst = self.dst("some_dir")
444 444 os.mkdir(dst)
445 445 path.link_or_copy(self.src, dst)
446 446 expected_dst = self.dst("some_dir", os.path.basename(self.src))
447 447 self.assert_inode_equal(self.src, expected_dst)
448 448
449 449 @skip_win32
450 450 def test_target_exists(self):
451 451 dst = self.dst("target")
452 452 open(dst, "w").close()
453 453 path.link_or_copy(self.src, dst)
454 454 self.assert_inode_equal(self.src, dst)
455 455
456 456 @skip_win32
457 457 def test_no_link(self):
458 458 real_link = os.link
459 459 try:
460 460 del os.link
461 461 dst = self.dst("target")
462 462 path.link_or_copy(self.src, dst)
463 463 self.assert_content_equal(self.src, dst)
464 464 self.assert_inode_not_equal(self.src, dst)
465 465 finally:
466 466 os.link = real_link
467 467
468 468 @skip_if_not_win32
469 469 def test_windows(self):
470 470 dst = self.dst("target")
471 471 path.link_or_copy(self.src, dst)
472 472 self.assert_content_equal(self.src, dst)
473 473
474 474 def test_link_twice(self):
475 475 # Linking the same file twice shouldn't leave duplicates around.
476 476 # See https://github.com/ipython/ipython/issues/6450
477 477 dst = self.dst('target')
478 478 path.link_or_copy(self.src, dst)
479 479 path.link_or_copy(self.src, dst)
480 480 self.assert_inode_equal(self.src, dst)
481 481 nt.assert_equal(sorted(os.listdir(self.tempdir.name)), ['src', 'target'])
@@ -1,776 +1,776 b''
1 1 # encoding: utf-8
2 2 """
3 3 Utilities for working with strings and text.
4 4
5 5 Inheritance diagram:
6 6
7 7 .. inheritance-diagram:: IPython.utils.text
8 8 :parts: 3
9 9 """
10 10
11 11 import os
12 12 import re
13 13 import sys
14 14 import textwrap
15 15 from string import Formatter
16 16 try:
17 17 from pathlib import Path
18 18 except ImportError:
19 19 # for Python 3.3
20 20 from pathlib2 import Path
21 21
22 22 from IPython.utils import py3compat
23 23
24 24 # datetime.strftime date format for ipython
25 25 if sys.platform == 'win32':
26 26 date_format = "%B %d, %Y"
27 27 else:
28 28 date_format = "%B %-d, %Y"
29 29
30 30 class LSString(str):
31 31 """String derivative with a special access attributes.
32 32
33 33 These are normal strings, but with the special attributes:
34 34
35 35 .l (or .list) : value as list (split on newlines).
36 36 .n (or .nlstr): original value (the string itself).
37 37 .s (or .spstr): value as whitespace-separated string.
38 38 .p (or .paths): list of path objects (requires path.py package)
39 39
40 40 Any values which require transformations are computed only once and
41 41 cached.
42 42
43 43 Such strings are very useful to efficiently interact with the shell, which
44 44 typically only understands whitespace-separated options for commands."""
45 45
46 46 def get_list(self):
47 47 try:
48 48 return self.__list
49 49 except AttributeError:
50 50 self.__list = self.split('\n')
51 51 return self.__list
52 52
53 53 l = list = property(get_list)
54 54
55 55 def get_spstr(self):
56 56 try:
57 57 return self.__spstr
58 58 except AttributeError:
59 59 self.__spstr = self.replace('\n',' ')
60 60 return self.__spstr
61 61
62 62 s = spstr = property(get_spstr)
63 63
64 64 def get_nlstr(self):
65 65 return self
66 66
67 67 n = nlstr = property(get_nlstr)
68 68
69 69 def get_paths(self):
70 70 try:
71 71 return self.__paths
72 72 except AttributeError:
73 73 self.__paths = [Path(p) for p in self.split('\n') if os.path.exists(p)]
74 74 return self.__paths
75 75
76 76 p = paths = property(get_paths)
77 77
78 78 # FIXME: We need to reimplement type specific displayhook and then add this
79 79 # back as a custom printer. This should also be moved outside utils into the
80 80 # core.
81 81
82 82 # def print_lsstring(arg):
83 83 # """ Prettier (non-repr-like) and more informative printer for LSString """
84 84 # print "LSString (.p, .n, .l, .s available). Value:"
85 85 # print arg
86 86 #
87 87 #
88 88 # print_lsstring = result_display.when_type(LSString)(print_lsstring)
89 89
90 90
91 91 class SList(list):
92 92 """List derivative with a special access attributes.
93 93
94 94 These are normal lists, but with the special attributes:
95 95
96 96 * .l (or .list) : value as list (the list itself).
97 97 * .n (or .nlstr): value as a string, joined on newlines.
98 98 * .s (or .spstr): value as a string, joined on spaces.
99 99 * .p (or .paths): list of path objects (requires path.py package)
100 100
101 101 Any values which require transformations are computed only once and
102 102 cached."""
103 103
104 104 def get_list(self):
105 105 return self
106 106
107 107 l = list = property(get_list)
108 108
109 109 def get_spstr(self):
110 110 try:
111 111 return self.__spstr
112 112 except AttributeError:
113 113 self.__spstr = ' '.join(self)
114 114 return self.__spstr
115 115
116 116 s = spstr = property(get_spstr)
117 117
118 118 def get_nlstr(self):
119 119 try:
120 120 return self.__nlstr
121 121 except AttributeError:
122 122 self.__nlstr = '\n'.join(self)
123 123 return self.__nlstr
124 124
125 125 n = nlstr = property(get_nlstr)
126 126
127 127 def get_paths(self):
128 128 try:
129 129 return self.__paths
130 130 except AttributeError:
131 131 self.__paths = [Path(p) for p in self if os.path.exists(p)]
132 132 return self.__paths
133 133
134 134 p = paths = property(get_paths)
135 135
136 136 def grep(self, pattern, prune = False, field = None):
137 137 """ Return all strings matching 'pattern' (a regex or callable)
138 138
139 139 This is case-insensitive. If prune is true, return all items
140 140 NOT matching the pattern.
141 141
142 142 If field is specified, the match must occur in the specified
143 143 whitespace-separated field.
144 144
145 145 Examples::
146 146
147 147 a.grep( lambda x: x.startswith('C') )
148 148 a.grep('Cha.*log', prune=1)
149 149 a.grep('chm', field=-1)
150 150 """
151 151
152 152 def match_target(s):
153 153 if field is None:
154 154 return s
155 155 parts = s.split()
156 156 try:
157 157 tgt = parts[field]
158 158 return tgt
159 159 except IndexError:
160 160 return ""
161 161
162 162 if isinstance(pattern, str):
163 163 pred = lambda x : re.search(pattern, x, re.IGNORECASE)
164 164 else:
165 165 pred = pattern
166 166 if not prune:
167 167 return SList([el for el in self if pred(match_target(el))])
168 168 else:
169 169 return SList([el for el in self if not pred(match_target(el))])
170 170
171 171 def fields(self, *fields):
172 172 """ Collect whitespace-separated fields from string list
173 173
174 174 Allows quick awk-like usage of string lists.
175 175
176 176 Example data (in var a, created by 'a = !ls -l')::
177 177
178 178 -rwxrwxrwx 1 ville None 18 Dec 14 2006 ChangeLog
179 179 drwxrwxrwx+ 6 ville None 0 Oct 24 18:05 IPython
180 180
181 181 * ``a.fields(0)`` is ``['-rwxrwxrwx', 'drwxrwxrwx+']``
182 182 * ``a.fields(1,0)`` is ``['1 -rwxrwxrwx', '6 drwxrwxrwx+']``
183 183 (note the joining by space).
184 184 * ``a.fields(-1)`` is ``['ChangeLog', 'IPython']``
185 185
186 186 IndexErrors are ignored.
187 187
188 188 Without args, fields() just split()'s the strings.
189 189 """
190 190 if len(fields) == 0:
191 191 return [el.split() for el in self]
192 192
193 193 res = SList()
194 194 for el in [f.split() for f in self]:
195 195 lineparts = []
196 196
197 197 for fd in fields:
198 198 try:
199 199 lineparts.append(el[fd])
200 200 except IndexError:
201 201 pass
202 202 if lineparts:
203 203 res.append(" ".join(lineparts))
204 204
205 205 return res
206 206
207 207 def sort(self,field= None, nums = False):
208 208 """ sort by specified fields (see fields())
209 209
210 210 Example::
211 211
212 212 a.sort(1, nums = True)
213 213
214 214 Sorts a by second field, in numerical order (so that 21 > 3)
215 215
216 216 """
217 217
218 218 #decorate, sort, undecorate
219 219 if field is not None:
220 220 dsu = [[SList([line]).fields(field), line] for line in self]
221 221 else:
222 222 dsu = [[line, line] for line in self]
223 223 if nums:
224 224 for i in range(len(dsu)):
225 225 numstr = "".join([ch for ch in dsu[i][0] if ch.isdigit()])
226 226 try:
227 227 n = int(numstr)
228 228 except ValueError:
229 229 n = 0
230 230 dsu[i][0] = n
231 231
232 232
233 233 dsu.sort()
234 234 return SList([t[1] for t in dsu])
235 235
236 236
237 237 # FIXME: We need to reimplement type specific displayhook and then add this
238 238 # back as a custom printer. This should also be moved outside utils into the
239 239 # core.
240 240
241 241 # def print_slist(arg):
242 242 # """ Prettier (non-repr-like) and more informative printer for SList """
243 243 # print "SList (.p, .n, .l, .s, .grep(), .fields(), sort() available):"
244 244 # if hasattr(arg, 'hideonce') and arg.hideonce:
245 245 # arg.hideonce = False
246 246 # return
247 247 #
248 248 # nlprint(arg) # This was a nested list printer, now removed.
249 249 #
250 250 # print_slist = result_display.when_type(SList)(print_slist)
251 251
252 252
253 253 def indent(instr,nspaces=4, ntabs=0, flatten=False):
254 254 """Indent a string a given number of spaces or tabstops.
255 255
256 256 indent(str,nspaces=4,ntabs=0) -> indent str by ntabs+nspaces.
257 257
258 258 Parameters
259 259 ----------
260 260
261 261 instr : basestring
262 262 The string to be indented.
263 263 nspaces : int (default: 4)
264 264 The number of spaces to be indented.
265 265 ntabs : int (default: 0)
266 266 The number of tabs to be indented.
267 267 flatten : bool (default: False)
268 268 Whether to scrub existing indentation. If True, all lines will be
269 269 aligned to the same indentation. If False, existing indentation will
270 270 be strictly increased.
271 271
272 272 Returns
273 273 -------
274 274
275 275 str|unicode : string indented by ntabs and nspaces.
276 276
277 277 """
278 278 if instr is None:
279 279 return
280 280 ind = '\t'*ntabs+' '*nspaces
281 281 if flatten:
282 282 pat = re.compile(r'^\s*', re.MULTILINE)
283 283 else:
284 284 pat = re.compile(r'^', re.MULTILINE)
285 285 outstr = re.sub(pat, ind, instr)
286 286 if outstr.endswith(os.linesep+ind):
287 287 return outstr[:-len(ind)]
288 288 else:
289 289 return outstr
290 290
291 291
292 292 def list_strings(arg):
293 293 """Always return a list of strings, given a string or list of strings
294 294 as input.
295 295
296 296 Examples
297 297 --------
298 298 ::
299 299
300 300 In [7]: list_strings('A single string')
301 301 Out[7]: ['A single string']
302 302
303 303 In [8]: list_strings(['A single string in a list'])
304 304 Out[8]: ['A single string in a list']
305 305
306 306 In [9]: list_strings(['A','list','of','strings'])
307 307 Out[9]: ['A', 'list', 'of', 'strings']
308 308 """
309 309
310 310 if isinstance(arg, str):
311 311 return [arg]
312 312 else:
313 313 return arg
314 314
315 315
316 316 def marquee(txt='',width=78,mark='*'):
317 317 """Return the input string centered in a 'marquee'.
318 318
319 319 Examples
320 320 --------
321 321 ::
322 322
323 323 In [16]: marquee('A test',40)
324 324 Out[16]: '**************** A test ****************'
325 325
326 326 In [17]: marquee('A test',40,'-')
327 327 Out[17]: '---------------- A test ----------------'
328 328
329 329 In [18]: marquee('A test',40,' ')
330 330 Out[18]: ' A test '
331 331
332 332 """
333 333 if not txt:
334 334 return (mark*width)[:width]
335 335 nmark = (width-len(txt)-2)//len(mark)//2
336 336 if nmark < 0: nmark =0
337 337 marks = mark*nmark
338 338 return '%s %s %s' % (marks,txt,marks)
339 339
340 340
341 341 ini_spaces_re = re.compile(r'^(\s+)')
342 342
343 343 def num_ini_spaces(strng):
344 344 """Return the number of initial spaces in a string"""
345 345
346 346 ini_spaces = ini_spaces_re.match(strng)
347 347 if ini_spaces:
348 348 return ini_spaces.end()
349 349 else:
350 350 return 0
351 351
352 352
353 353 def format_screen(strng):
354 354 """Format a string for screen printing.
355 355
356 356 This removes some latex-type format codes."""
357 357 # Paragraph continue
358 358 par_re = re.compile(r'\\$',re.MULTILINE)
359 359 strng = par_re.sub('',strng)
360 360 return strng
361 361
362 362
363 363 def dedent(text):
364 364 """Equivalent of textwrap.dedent that ignores unindented first line.
365 365
366 366 This means it will still dedent strings like:
367 367 '''foo
368 368 is a bar
369 369 '''
370 370
371 371 For use in wrap_paragraphs.
372 372 """
373 373
374 374 if text.startswith('\n'):
375 375 # text starts with blank line, don't ignore the first line
376 376 return textwrap.dedent(text)
377 377
378 378 # split first line
379 379 splits = text.split('\n',1)
380 380 if len(splits) == 1:
381 381 # only one line
382 382 return textwrap.dedent(text)
383 383
384 384 first, rest = splits
385 385 # dedent everything but the first line
386 386 rest = textwrap.dedent(rest)
387 387 return '\n'.join([first, rest])
388 388
389 389
390 390 def wrap_paragraphs(text, ncols=80):
391 391 """Wrap multiple paragraphs to fit a specified width.
392 392
393 393 This is equivalent to textwrap.wrap, but with support for multiple
394 394 paragraphs, as separated by empty lines.
395 395
396 396 Returns
397 397 -------
398 398
399 399 list of complete paragraphs, wrapped to fill `ncols` columns.
400 400 """
401 401 paragraph_re = re.compile(r'\n(\s*\n)+', re.MULTILINE)
402 402 text = dedent(text).strip()
403 403 paragraphs = paragraph_re.split(text)[::2] # every other entry is space
404 404 out_ps = []
405 405 indent_re = re.compile(r'\n\s+', re.MULTILINE)
406 406 for p in paragraphs:
407 407 # presume indentation that survives dedent is meaningful formatting,
408 408 # so don't fill unless text is flush.
409 409 if indent_re.search(p) is None:
410 410 # wrap paragraph
411 411 p = textwrap.fill(p, ncols)
412 412 out_ps.append(p)
413 413 return out_ps
414 414
415 415
416 416 def long_substr(data):
417 417 """Return the longest common substring in a list of strings.
418 418
419 419 Credit: http://stackoverflow.com/questions/2892931/longest-common-substring-from-more-than-two-strings-python
420 420 """
421 421 substr = ''
422 422 if len(data) > 1 and len(data[0]) > 0:
423 423 for i in range(len(data[0])):
424 424 for j in range(len(data[0])-i+1):
425 425 if j > len(substr) and all(data[0][i:i+j] in x for x in data):
426 426 substr = data[0][i:i+j]
427 427 elif len(data) == 1:
428 428 substr = data[0]
429 429 return substr
430 430
431 431
432 432 def strip_email_quotes(text):
433 433 """Strip leading email quotation characters ('>').
434 434
435 435 Removes any combination of leading '>' interspersed with whitespace that
436 436 appears *identically* in all lines of the input text.
437 437
438 438 Parameters
439 439 ----------
440 440 text : str
441 441
442 442 Examples
443 443 --------
444 444
445 445 Simple uses::
446 446
447 447 In [2]: strip_email_quotes('> > text')
448 448 Out[2]: 'text'
449 449
450 450 In [3]: strip_email_quotes('> > text\\n> > more')
451 451 Out[3]: 'text\\nmore'
452 452
453 453 Note how only the common prefix that appears in all lines is stripped::
454 454
455 455 In [4]: strip_email_quotes('> > text\\n> > more\\n> more...')
456 456 Out[4]: '> text\\n> more\\nmore...'
457 457
458 458 So if any line has no quote marks ('>') , then none are stripped from any
459 459 of them ::
460 460
461 461 In [5]: strip_email_quotes('> > text\\n> > more\\nlast different')
462 462 Out[5]: '> > text\\n> > more\\nlast different'
463 463 """
464 464 lines = text.splitlines()
465 465 matches = set()
466 466 for line in lines:
467 467 prefix = re.match(r'^(\s*>[ >]*)', line)
468 468 if prefix:
469 469 matches.add(prefix.group(1))
470 470 else:
471 471 break
472 472 else:
473 473 prefix = long_substr(list(matches))
474 474 if prefix:
475 475 strip = len(prefix)
476 476 text = '\n'.join([ ln[strip:] for ln in lines])
477 477 return text
478 478
479 479 def strip_ansi(source):
480 480 """
481 481 Remove ansi escape codes from text.
482 482
483 483 Parameters
484 484 ----------
485 485 source : str
486 486 Source to remove the ansi from
487 487 """
488 488 return re.sub(r'\033\[(\d|;)+?m', '', source)
489 489
490 490
491 491 class EvalFormatter(Formatter):
492 492 """A String Formatter that allows evaluation of simple expressions.
493 493
494 494 Note that this version interprets a : as specifying a format string (as per
495 495 standard string formatting), so if slicing is required, you must explicitly
496 496 create a slice.
497 497
498 498 This is to be used in templating cases, such as the parallel batch
499 499 script templates, where simple arithmetic on arguments is useful.
500 500
501 501 Examples
502 502 --------
503 503 ::
504 504
505 505 In [1]: f = EvalFormatter()
506 506 In [2]: f.format('{n//4}', n=8)
507 507 Out[2]: '2'
508 508
509 509 In [3]: f.format("{greeting[slice(2,4)]}", greeting="Hello")
510 510 Out[3]: 'll'
511 511 """
512 512 def get_field(self, name, args, kwargs):
513 513 v = eval(name, kwargs)
514 514 return v, name
515 515
516 516 #XXX: As of Python 3.4, the format string parsing no longer splits on a colon
517 517 # inside [], so EvalFormatter can handle slicing. Once we only support 3.4 and
518 518 # above, it should be possible to remove FullEvalFormatter.
519 519
520 520 class FullEvalFormatter(Formatter):
521 521 """A String Formatter that allows evaluation of simple expressions.
522 522
523 523 Any time a format key is not found in the kwargs,
524 524 it will be tried as an expression in the kwargs namespace.
525 525
526 526 Note that this version allows slicing using [1:2], so you cannot specify
527 527 a format string. Use :class:`EvalFormatter` to permit format strings.
528 528
529 529 Examples
530 530 --------
531 531 ::
532 532
533 533 In [1]: f = FullEvalFormatter()
534 534 In [2]: f.format('{n//4}', n=8)
535 535 Out[2]: '2'
536 536
537 537 In [3]: f.format('{list(range(5))[2:4]}')
538 538 Out[3]: '[2, 3]'
539 539
540 540 In [4]: f.format('{3*2}')
541 541 Out[4]: '6'
542 542 """
543 543 # copied from Formatter._vformat with minor changes to allow eval
544 544 # and replace the format_spec code with slicing
545 545 def vformat(self, format_string, args, kwargs):
546 546 result = []
547 547 for literal_text, field_name, format_spec, conversion in \
548 548 self.parse(format_string):
549 549
550 550 # output the literal text
551 551 if literal_text:
552 552 result.append(literal_text)
553 553
554 554 # if there's a field, output it
555 555 if field_name is not None:
556 556 # this is some markup, find the object and do
557 557 # the formatting
558 558
559 559 if format_spec:
560 560 # override format spec, to allow slicing:
561 561 field_name = ':'.join([field_name, format_spec])
562 562
563 563 # eval the contents of the field for the object
564 564 # to be formatted
565 565 obj = eval(field_name, kwargs)
566 566
567 567 # do any conversion on the resulting object
568 568 obj = self.convert_field(obj, conversion)
569 569
570 570 # format the object and append to the result
571 571 result.append(self.format_field(obj, ''))
572 572
573 573 return ''.join(py3compat.cast_unicode(s) for s in result)
574 574
575 575
576 576 class DollarFormatter(FullEvalFormatter):
577 577 """Formatter allowing Itpl style $foo replacement, for names and attribute
578 578 access only. Standard {foo} replacement also works, and allows full
579 579 evaluation of its arguments.
580 580
581 581 Examples
582 582 --------
583 583 ::
584 584
585 585 In [1]: f = DollarFormatter()
586 586 In [2]: f.format('{n//4}', n=8)
587 587 Out[2]: '2'
588 588
589 589 In [3]: f.format('23 * 76 is $result', result=23*76)
590 590 Out[3]: '23 * 76 is 1748'
591 591
592 592 In [4]: f.format('$a or {b}', a=1, b=2)
593 593 Out[4]: '1 or 2'
594 594 """
595 595 _dollar_pattern_ignore_single_quote = re.compile("(.*?)\$(\$?[\w\.]+)(?=([^']*'[^']*')*[^']*$)")
596 596 def parse(self, fmt_string):
597 597 for literal_txt, field_name, format_spec, conversion \
598 598 in Formatter.parse(self, fmt_string):
599 599
600 600 # Find $foo patterns in the literal text.
601 601 continue_from = 0
602 602 txt = ""
603 603 for m in self._dollar_pattern_ignore_single_quote.finditer(literal_txt):
604 604 new_txt, new_field = m.group(1,2)
605 605 # $$foo --> $foo
606 606 if new_field.startswith("$"):
607 607 txt += new_txt + new_field
608 608 else:
609 609 yield (txt + new_txt, new_field, "", None)
610 610 txt = ""
611 611 continue_from = m.end()
612 612
613 613 # Re-yield the {foo} style pattern
614 614 yield (txt + literal_txt[continue_from:], field_name, format_spec, conversion)
615 615
616 616 #-----------------------------------------------------------------------------
617 617 # Utils to columnize a list of string
618 618 #-----------------------------------------------------------------------------
619 619
620 620 def _col_chunks(l, max_rows, row_first=False):
621 621 """Yield successive max_rows-sized column chunks from l."""
622 622 if row_first:
623 623 ncols = (len(l) // max_rows) + (len(l) % max_rows > 0)
624 624 for i in range(ncols):
625 625 yield [l[j] for j in range(i, len(l), ncols)]
626 626 else:
627 627 for i in range(0, len(l), max_rows):
628 628 yield l[i:(i + max_rows)]
629 629
630 630
631 631 def _find_optimal(rlist, row_first=False, separator_size=2, displaywidth=80):
632 632 """Calculate optimal info to columnize a list of string"""
633 633 for max_rows in range(1, len(rlist) + 1):
634 634 col_widths = list(map(max, _col_chunks(rlist, max_rows, row_first)))
635 635 sumlength = sum(col_widths)
636 636 ncols = len(col_widths)
637 637 if sumlength + separator_size * (ncols - 1) <= displaywidth:
638 638 break
639 639 return {'num_columns': ncols,
640 640 'optimal_separator_width': (displaywidth - sumlength) // (ncols - 1) if (ncols - 1) else 0,
641 641 'max_rows': max_rows,
642 642 'column_widths': col_widths
643 643 }
644 644
645 645
646 646 def _get_or_default(mylist, i, default=None):
647 647 """return list item number, or default if don't exist"""
648 648 if i >= len(mylist):
649 649 return default
650 650 else :
651 651 return mylist[i]
652 652
653 653
654 654 def compute_item_matrix(items, row_first=False, empty=None, *args, **kwargs) :
655 655 """Returns a nested list, and info to columnize items
656 656
657 657 Parameters
658 658 ----------
659 659
660 660 items
661 661 list of strings to columize
662 662 row_first : (default False)
663 663 Whether to compute columns for a row-first matrix instead of
664 664 column-first (default).
665 665 empty : (default None)
666 666 default value to fill list if needed
667 667 separator_size : int (default=2)
668 668 How much caracters will be used as a separation between each columns.
669 669 displaywidth : int (default=80)
670 The width of the area onto wich the columns should enter
670 The width of the area onto which the columns should enter
671 671
672 672 Returns
673 673 -------
674 674
675 675 strings_matrix
676 676
677 677 nested list of string, the outer most list contains as many list as
678 rows, the innermost lists have each as many element as colums. If the
678 rows, the innermost lists have each as many element as columns. If the
679 679 total number of elements in `items` does not equal the product of
680 680 rows*columns, the last element of some lists are filled with `None`.
681 681
682 682 dict_info
683 683 some info to make columnize easier:
684 684
685 685 num_columns
686 686 number of columns
687 687 max_rows
688 688 maximum number of rows (final number may be less)
689 689 column_widths
690 690 list of with of each columns
691 691 optimal_separator_width
692 692 best separator width between columns
693 693
694 694 Examples
695 695 --------
696 696 ::
697 697
698 698 In [1]: l = ['aaa','b','cc','d','eeeee','f','g','h','i','j','k','l']
699 699 In [2]: list, info = compute_item_matrix(l, displaywidth=12)
700 700 In [3]: list
701 701 Out[3]: [['aaa', 'f', 'k'], ['b', 'g', 'l'], ['cc', 'h', None], ['d', 'i', None], ['eeeee', 'j', None]]
702 702 In [4]: ideal = {'num_columns': 3, 'column_widths': [5, 1, 1], 'optimal_separator_width': 2, 'max_rows': 5}
703 703 In [5]: all((info[k] == ideal[k] for k in ideal.keys()))
704 704 Out[5]: True
705 705 """
706 706 info = _find_optimal(list(map(len, items)), row_first, *args, **kwargs)
707 707 nrow, ncol = info['max_rows'], info['num_columns']
708 708 if row_first:
709 709 return ([[_get_or_default(items, r * ncol + c, default=empty) for c in range(ncol)] for r in range(nrow)], info)
710 710 else:
711 711 return ([[_get_or_default(items, c * nrow + r, default=empty) for c in range(ncol)] for r in range(nrow)], info)
712 712
713 713
714 714 def columnize(items, row_first=False, separator=' ', displaywidth=80, spread=False):
715 715 """ Transform a list of strings into a single string with columns.
716 716
717 717 Parameters
718 718 ----------
719 719 items : sequence of strings
720 720 The strings to process.
721 721
722 722 row_first : (default False)
723 723 Whether to compute columns for a row-first matrix instead of
724 724 column-first (default).
725 725
726 726 separator : str, optional [default is two spaces]
727 727 The string that separates columns.
728 728
729 729 displaywidth : int, optional [default is 80]
730 730 Width of the display in number of characters.
731 731
732 732 Returns
733 733 -------
734 734 The formatted string.
735 735 """
736 736 if not items:
737 737 return '\n'
738 738 matrix, info = compute_item_matrix(items, row_first=row_first, separator_size=len(separator), displaywidth=displaywidth)
739 739 if spread:
740 740 separator = separator.ljust(int(info['optimal_separator_width']))
741 741 fmatrix = [filter(None, x) for x in matrix]
742 742 sjoin = lambda x : separator.join([ y.ljust(w, ' ') for y, w in zip(x, info['column_widths'])])
743 743 return '\n'.join(map(sjoin, fmatrix))+'\n'
744 744
745 745
746 746 def get_text_list(list_, last_sep=' and ', sep=", ", wrap_item_with=""):
747 747 """
748 748 Return a string with a natural enumeration of items
749 749
750 750 >>> get_text_list(['a', 'b', 'c', 'd'])
751 751 'a, b, c and d'
752 752 >>> get_text_list(['a', 'b', 'c'], ' or ')
753 753 'a, b or c'
754 754 >>> get_text_list(['a', 'b', 'c'], ', ')
755 755 'a, b, c'
756 756 >>> get_text_list(['a', 'b'], ' or ')
757 757 'a or b'
758 758 >>> get_text_list(['a'])
759 759 'a'
760 760 >>> get_text_list([])
761 761 ''
762 762 >>> get_text_list(['a', 'b'], wrap_item_with="`")
763 763 '`a` and `b`'
764 764 >>> get_text_list(['a', 'b', 'c', 'd'], " = ", sep=" + ")
765 765 'a + b + c = d'
766 766 """
767 767 if len(list_) == 0:
768 768 return ''
769 769 if wrap_item_with:
770 770 list_ = ['%s%s%s' % (wrap_item_with, item, wrap_item_with) for
771 771 item in list_]
772 772 if len(list_) == 1:
773 773 return list_[0]
774 774 return '%s%s%s' % (
775 775 sep.join(i for i in list_[:-1]),
776 776 last_sep, list_[-1])
@@ -1,106 +1,106 b''
1 1 .. _kernel_install:
2 2
3 3 Installing the IPython kernel
4 4 =============================
5 5
6 6 .. seealso::
7 7
8 8 :ref:`Installing Jupyter <jupyter:install>`
9 9 The IPython kernel is the Python execution backend for Jupyter.
10 10
11 11 The Jupyter Notebook and other frontends automatically ensure that the IPython kernel is available.
12 12 However, if you want to use a kernel with a different version of Python, or in a virtualenv or conda environment,
13 13 you'll need to install that manually.
14 14
15 15 Kernels for Python 2 and 3
16 16 --------------------------
17 17
18 18 If you're running Jupyter on Python 3, you can set up a Python 2 kernel after
19 19 checking your version of pip is greater than 9.0::
20 20
21 21 python2 -m pip --version
22 22
23 23 Then install with ::
24 24
25 25 python2 -m pip install ipykernel
26 26 python2 -m ipykernel install --user
27 27
28 28 Or using conda, create a Python 2 environment::
29 29
30 30 conda create -n ipykernel_py2 python=2 ipykernel
31 31 source activate ipykernel_py2 # On Windows, remove the word 'source'
32 32 python -m ipykernel install --user
33 33
34 34 .. note::
35 35
36 36 IPython 6.0 stopped support for Python 2, so
37 37 installing IPython on Python 2 will give you an older version (5.x series).
38 38
39 39 If you're running Jupyter on Python 2 and want to set up a Python 3 kernel,
40 40 follow the same steps, replacing ``2`` with ``3``.
41 41
42 42 The last command installs a :ref:`kernel spec <jupyterclient:kernelspecs>` file
43 43 for the current python installation. Kernel spec files are JSON files, which
44 44 can be viewed and changed with a normal text editor.
45 45
46 46 .. _multiple_kernel_install:
47 47
48 48 Kernels for different environments
49 49 ----------------------------------
50 50
51 51 If you want to have multiple IPython kernels for different virtualenvs or conda
52 52 environments, you will need to specify unique names for the kernelspecs.
53 53
54 54 Make sure you have ipykernel installed in your environement. If you are using
55 55 ``pip`` to install ``ipykernel`` in a conda env, make sure ``pip`` is
56 56 installed:
57 57
58 58 .. sourcecode:: bash
59 59
60 60 source activate myenv
61 61 conda install pip
62 62 conda install ipykernel # or pip install ipykernel
63 63
64 64 For example, using conda environments, install a ``Python (myenv)`` Kernel in a first
65 65 environment:
66 66
67 67 .. sourcecode:: bash
68 68
69 69 source activate myenv
70 70 python -m ipykernel install --user --name myenv --display-name "Python (myenv)"
71 71
72 72 And in a second environment, after making sure ipykernel is installed in it:
73 73
74 74 .. sourcecode:: bash
75 75
76 76 source activate other-env
77 77 python -m ipykernel install --user --name other-env --display-name "Python (other-env)"
78 78
79 79 The ``--name`` value is used by Jupyter internally. These commands will overwrite
80 80 any existing kernel with the same name. ``--display-name`` is what you see in
81 81 the notebook menus.
82 82
83 83 Using virtualenv or conda envs, you can make your IPython kernel in one env available to Jupyter in a different env. To do so, run ipykernel install from the kernel's env, with --prefix pointing to the Jupyter env:
84 84
85 85 .. sourcecode:: bash
86 86
87 87 /path/to/kernel/env/bin/python -m ipykernel install --prefix=/path/to/jupyter/env --name 'python-my-env'
88 88
89 Note that this command will create a new configuration for the kernel in one of the prefered location (see ``jupyter --paths`` command for more details):
89 Note that this command will create a new configuration for the kernel in one of the preferred location (see ``jupyter --paths`` command for more details):
90 90
91 91 * system-wide (e.g. /usr/local/share),
92 92 * in Jupyter's env (sys.prefix/share),
93 93 * per-user (~/.local/share or ~/Library/share)
94 94
95 95 If you want to edit the kernelspec before installing it, you can do so in two steps.
96 96 First, ask IPython to write its spec to a temporary location:
97 97
98 98 .. sourcecode:: bash
99 99
100 100 ipython kernel install --prefix /tmp
101 101
102 102 edit the files in /tmp/share/jupyter/kernels/python3 to your liking, then when you are ready, tell Jupyter to install it (this will copy the files into a place Jupyter will look):
103 103
104 104 .. sourcecode:: bash
105 105
106 106 jupyter kernelspec install /tmp/share/jupyter/kernels/python3
@@ -1,528 +1,528 b''
1 1 .. _issues_list_011:
2 2
3 3 Issues closed in the 0.11 development cycle
4 4 ===========================================
5 5
6 6 In this cycle, we closed a total of 511 issues, 226 pull requests and 285
7 7 regular issues; this is the full list (generated with the script
8 8 `tools/github_stats.py`). We should note that a few of these were made on the
9 9 0.10.x series, but we have no automatic way of filtering the issues by branch,
10 10 so this reflects all of our development over the last two years, including work
11 11 already released in 0.10.2:
12 12
13 13 Pull requests (226):
14 14
15 15 * `620 <https://github.com/ipython/ipython/issues/620>`_: Release notes and updates to GUI support docs for 0.11
16 16 * `642 <https://github.com/ipython/ipython/issues/642>`_: fix typo in docs/examples/vim/README.rst
17 17 * `631 <https://github.com/ipython/ipython/issues/631>`_: two-way vim-ipython integration
18 18 * `637 <https://github.com/ipython/ipython/issues/637>`_: print is a function, this allows to properly exit ipython
19 19 * `635 <https://github.com/ipython/ipython/issues/635>`_: support html representations in the notebook frontend
20 20 * `639 <https://github.com/ipython/ipython/issues/639>`_: Updating the credits file
21 21 * `628 <https://github.com/ipython/ipython/issues/628>`_: import pexpect from IPython.external in irunner
22 22 * `596 <https://github.com/ipython/ipython/issues/596>`_: Irunner
23 23 * `598 <https://github.com/ipython/ipython/issues/598>`_: Fix templates for CrashHandler
24 24 * `590 <https://github.com/ipython/ipython/issues/590>`_: Desktop
25 25 * `600 <https://github.com/ipython/ipython/issues/600>`_: Fix bug with non-ascii reprs inside pretty-printed lists.
26 26 * `618 <https://github.com/ipython/ipython/issues/618>`_: I617
27 27 * `599 <https://github.com/ipython/ipython/issues/599>`_: Gui Qt example and docs
28 28 * `619 <https://github.com/ipython/ipython/issues/619>`_: manpage update
29 29 * `582 <https://github.com/ipython/ipython/issues/582>`_: Updating sympy profile to match the exec_lines of isympy.
30 30 * `578 <https://github.com/ipython/ipython/issues/578>`_: Check to see if correct source for decorated functions can be displayed
31 31 * `589 <https://github.com/ipython/ipython/issues/589>`_: issue 588
32 32 * `591 <https://github.com/ipython/ipython/issues/591>`_: simulate shell expansion on %run arguments, at least tilde expansion
33 33 * `576 <https://github.com/ipython/ipython/issues/576>`_: Show message about %paste magic on an IndentationError
34 34 * `574 <https://github.com/ipython/ipython/issues/574>`_: Getcwdu
35 35 * `565 <https://github.com/ipython/ipython/issues/565>`_: don't move old config files, keep nagging the user
36 36 * `575 <https://github.com/ipython/ipython/issues/575>`_: Added more docstrings to IPython.zmq.session.
37 * `567 <https://github.com/ipython/ipython/issues/567>`_: fix trailing whitespace from reseting indentation
37 * `567 <https://github.com/ipython/ipython/issues/567>`_: fix trailing whitespace from resetting indentation
38 38 * `564 <https://github.com/ipython/ipython/issues/564>`_: Command line args in docs
39 39 * `560 <https://github.com/ipython/ipython/issues/560>`_: reorder qt support in kernel
40 40 * `561 <https://github.com/ipython/ipython/issues/561>`_: command-line suggestions
41 41 * `556 <https://github.com/ipython/ipython/issues/556>`_: qt_for_kernel: use matplotlib rcParams to decide between PyQt4 and PySide
42 42 * `557 <https://github.com/ipython/ipython/issues/557>`_: Update usage.py to newapp
43 43 * `555 <https://github.com/ipython/ipython/issues/555>`_: Rm default old config
44 44 * `552 <https://github.com/ipython/ipython/issues/552>`_: update parallel code for py3k
45 45 * `504 <https://github.com/ipython/ipython/issues/504>`_: Updating string formatting
46 46 * `551 <https://github.com/ipython/ipython/issues/551>`_: Make pylab import all configurable
47 47 * `496 <https://github.com/ipython/ipython/issues/496>`_: Qt editing keybindings
48 48 * `550 <https://github.com/ipython/ipython/issues/550>`_: Support v2 PyQt4 APIs and PySide in kernel's GUI support
49 49 * `546 <https://github.com/ipython/ipython/issues/546>`_: doc update
50 50 * `548 <https://github.com/ipython/ipython/issues/548>`_: Fix sympy profile to work with sympy 0.7.
51 51 * `542 <https://github.com/ipython/ipython/issues/542>`_: issue 440
52 52 * `533 <https://github.com/ipython/ipython/issues/533>`_: Remove unused configobj and validate libraries from externals.
53 53 * `538 <https://github.com/ipython/ipython/issues/538>`_: fix various tests on Windows
54 54 * `540 <https://github.com/ipython/ipython/issues/540>`_: support `-pylab` flag with deprecation warning
55 55 * `537 <https://github.com/ipython/ipython/issues/537>`_: Docs update
56 56 * `536 <https://github.com/ipython/ipython/issues/536>`_: `setup.py install` depends on setuptools on Windows
57 57 * `480 <https://github.com/ipython/ipython/issues/480>`_: Get help mid-command
58 58 * `462 <https://github.com/ipython/ipython/issues/462>`_: Str and Bytes traitlets
59 59 * `534 <https://github.com/ipython/ipython/issues/534>`_: Handle unicode properly in IPython.zmq.iostream
60 60 * `527 <https://github.com/ipython/ipython/issues/527>`_: ZMQ displayhook
61 61 * `526 <https://github.com/ipython/ipython/issues/526>`_: Handle asynchronous output in Qt console
62 62 * `528 <https://github.com/ipython/ipython/issues/528>`_: Do not import deprecated functions from external decorators library.
63 63 * `454 <https://github.com/ipython/ipython/issues/454>`_: New BaseIPythonApplication
64 64 * `532 <https://github.com/ipython/ipython/issues/532>`_: Zmq unicode
65 65 * `531 <https://github.com/ipython/ipython/issues/531>`_: Fix Parallel test
66 66 * `525 <https://github.com/ipython/ipython/issues/525>`_: fallback on lsof if otool not found in libedit detection
67 67 * `517 <https://github.com/ipython/ipython/issues/517>`_: Merge IPython.parallel.streamsession into IPython.zmq.session
68 68 * `521 <https://github.com/ipython/ipython/issues/521>`_: use dict.get(key) instead of dict[key] for safety from KeyErrors
69 69 * `492 <https://github.com/ipython/ipython/issues/492>`_: add QtConsoleApp using newapplication
70 70 * `485 <https://github.com/ipython/ipython/issues/485>`_: terminal IPython with newapp
71 71 * `486 <https://github.com/ipython/ipython/issues/486>`_: Use newapp in parallel code
72 72 * `511 <https://github.com/ipython/ipython/issues/511>`_: Add a new line before displaying multiline strings in the Qt console.
73 73 * `509 <https://github.com/ipython/ipython/issues/509>`_: i508
74 74 * `501 <https://github.com/ipython/ipython/issues/501>`_: ignore EINTR in channel loops
75 75 * `495 <https://github.com/ipython/ipython/issues/495>`_: Better selection of Qt bindings when QT_API is not specified
76 76 * `498 <https://github.com/ipython/ipython/issues/498>`_: Check for .pyd as extension for binary files.
77 77 * `494 <https://github.com/ipython/ipython/issues/494>`_: QtConsole zoom adjustments
78 78 * `490 <https://github.com/ipython/ipython/issues/490>`_: fix UnicodeEncodeError writing SVG string to .svg file, fixes #489
79 79 * `491 <https://github.com/ipython/ipython/issues/491>`_: add QtConsoleApp using newapplication
80 80 * `479 <https://github.com/ipython/ipython/issues/479>`_: embed() doesn't load default config
81 81 * `483 <https://github.com/ipython/ipython/issues/483>`_: Links launchpad -> github
82 82 * `419 <https://github.com/ipython/ipython/issues/419>`_: %xdel magic
83 83 * `477 <https://github.com/ipython/ipython/issues/477>`_: Add \n to lines in the log
84 84 * `459 <https://github.com/ipython/ipython/issues/459>`_: use os.system for shell.system in Terminal frontend
85 85 * `475 <https://github.com/ipython/ipython/issues/475>`_: i473
86 86 * `471 <https://github.com/ipython/ipython/issues/471>`_: Add test decorator onlyif_unicode_paths.
87 87 * `474 <https://github.com/ipython/ipython/issues/474>`_: Fix support for raw GTK and WX matplotlib backends.
88 88 * `472 <https://github.com/ipython/ipython/issues/472>`_: Kernel event loop is robust against random SIGINT.
89 89 * `460 <https://github.com/ipython/ipython/issues/460>`_: Share code for magic_edit
90 90 * `469 <https://github.com/ipython/ipython/issues/469>`_: Add exit code when running all tests with iptest.
91 91 * `464 <https://github.com/ipython/ipython/issues/464>`_: Add home directory expansion to IPYTHON_DIR environment variables.
92 92 * `455 <https://github.com/ipython/ipython/issues/455>`_: Bugfix with logger
93 93 * `448 <https://github.com/ipython/ipython/issues/448>`_: Separate out skip_doctest decorator
94 94 * `453 <https://github.com/ipython/ipython/issues/453>`_: Draft of new main BaseIPythonApplication.
95 95 * `452 <https://github.com/ipython/ipython/issues/452>`_: Use list/tuple/dict/set subclass's overridden __repr__ instead of the pretty
96 96 * `398 <https://github.com/ipython/ipython/issues/398>`_: allow toggle of svg/png inline figure format
97 97 * `381 <https://github.com/ipython/ipython/issues/381>`_: Support inline PNGs of matplotlib plots
98 98 * `413 <https://github.com/ipython/ipython/issues/413>`_: Retries and Resubmit (#411 and #412)
99 99 * `370 <https://github.com/ipython/ipython/issues/370>`_: Fixes to the display system
100 100 * `449 <https://github.com/ipython/ipython/issues/449>`_: Fix issue 447 - inspecting old-style classes.
101 101 * `423 <https://github.com/ipython/ipython/issues/423>`_: Allow type checking on elements of List,Tuple,Set traits
102 102 * `400 <https://github.com/ipython/ipython/issues/400>`_: Config5
103 103 * `421 <https://github.com/ipython/ipython/issues/421>`_: Generalise mechanism to put text at the next prompt in the Qt console.
104 104 * `443 <https://github.com/ipython/ipython/issues/443>`_: pinfo code duplication
105 105 * `429 <https://github.com/ipython/ipython/issues/429>`_: add check_pid, and handle stale PID info in ipcluster.
106 106 * `431 <https://github.com/ipython/ipython/issues/431>`_: Fix error message in test_irunner
107 107 * `427 <https://github.com/ipython/ipython/issues/427>`_: handle different SyntaxError messages in test_irunner
108 108 * `424 <https://github.com/ipython/ipython/issues/424>`_: Irunner test failure
109 109 * `430 <https://github.com/ipython/ipython/issues/430>`_: Small parallel doc typo
110 110 * `422 <https://github.com/ipython/ipython/issues/422>`_: Make ipython-qtconsole a GUI script
111 111 * `420 <https://github.com/ipython/ipython/issues/420>`_: Permit kernel std* to be redirected
112 112 * `408 <https://github.com/ipython/ipython/issues/408>`_: History request
113 113 * `388 <https://github.com/ipython/ipython/issues/388>`_: Add Emacs-style kill ring to Qt console
114 114 * `414 <https://github.com/ipython/ipython/issues/414>`_: Warn on old config files
115 115 * `415 <https://github.com/ipython/ipython/issues/415>`_: Prevent prefilter from crashing IPython
116 116 * `418 <https://github.com/ipython/ipython/issues/418>`_: Minor configuration doc fixes
117 117 * `407 <https://github.com/ipython/ipython/issues/407>`_: Update What's new documentation
118 118 * `410 <https://github.com/ipython/ipython/issues/410>`_: Install notebook frontend
119 119 * `406 <https://github.com/ipython/ipython/issues/406>`_: install IPython.zmq.gui
120 120 * `393 <https://github.com/ipython/ipython/issues/393>`_: ipdir unicode
121 121 * `397 <https://github.com/ipython/ipython/issues/397>`_: utils.io.Term.cin/out/err -> utils.io.stdin/out/err
122 122 * `389 <https://github.com/ipython/ipython/issues/389>`_: DB fixes and Scheduler HWM
123 123 * `374 <https://github.com/ipython/ipython/issues/374>`_: Various Windows-related fixes to IPython.parallel
124 124 * `362 <https://github.com/ipython/ipython/issues/362>`_: fallback on defaultencoding if filesystemencoding is None
125 125 * `382 <https://github.com/ipython/ipython/issues/382>`_: Shell's reset method clears namespace from last %run command.
126 126 * `385 <https://github.com/ipython/ipython/issues/385>`_: Update iptest exclusions (fix #375)
127 127 * `383 <https://github.com/ipython/ipython/issues/383>`_: Catch errors in querying readline which occur with pyreadline.
128 128 * `373 <https://github.com/ipython/ipython/issues/373>`_: Remove runlines etc.
129 129 * `364 <https://github.com/ipython/ipython/issues/364>`_: Single output
130 130 * `372 <https://github.com/ipython/ipython/issues/372>`_: Multiline input push
131 131 * `363 <https://github.com/ipython/ipython/issues/363>`_: Issue 125
132 132 * `361 <https://github.com/ipython/ipython/issues/361>`_: don't rely on setuptools for readline dependency check
133 133 * `349 <https://github.com/ipython/ipython/issues/349>`_: Fix %autopx magic
134 134 * `355 <https://github.com/ipython/ipython/issues/355>`_: History save thread
135 135 * `356 <https://github.com/ipython/ipython/issues/356>`_: Usability improvements to history in Qt console
136 136 * `357 <https://github.com/ipython/ipython/issues/357>`_: Exit autocall
137 137 * `353 <https://github.com/ipython/ipython/issues/353>`_: Rewrite quit()/exit()/Quit()/Exit() calls as magic
138 138 * `354 <https://github.com/ipython/ipython/issues/354>`_: Cell tweaks
139 139 * `345 <https://github.com/ipython/ipython/issues/345>`_: Attempt to address (partly) issue ipython/#342 by rewriting quit(), exit(), etc.
140 140 * `352 <https://github.com/ipython/ipython/issues/352>`_: #342: Try to recover as intelligently as possible if user calls magic().
141 141 * `346 <https://github.com/ipython/ipython/issues/346>`_: Dedent prefix bugfix + tests: #142
142 142 * `348 <https://github.com/ipython/ipython/issues/348>`_: %reset doesn't reset prompt number.
143 143 * `347 <https://github.com/ipython/ipython/issues/347>`_: Make ip.reset() work the same in interactive or non-interactive code.
144 144 * `343 <https://github.com/ipython/ipython/issues/343>`_: make readline a dependency on OSX
145 145 * `344 <https://github.com/ipython/ipython/issues/344>`_: restore auto debug behavior
146 146 * `339 <https://github.com/ipython/ipython/issues/339>`_: fix for issue 337: incorrect/phantom tooltips for magics
147 147 * `254 <https://github.com/ipython/ipython/issues/254>`_: newparallel branch (add zmq.parallel submodule)
148 148 * `334 <https://github.com/ipython/ipython/issues/334>`_: Hard reset
149 149 * `316 <https://github.com/ipython/ipython/issues/316>`_: Unicode win process
150 150 * `332 <https://github.com/ipython/ipython/issues/332>`_: AST splitter
151 151 * `325 <https://github.com/ipython/ipython/issues/325>`_: Removetwisted
152 152 * `330 <https://github.com/ipython/ipython/issues/330>`_: Magic pastebin
153 153 * `309 <https://github.com/ipython/ipython/issues/309>`_: Bug tests for GH Issues 238, 284, 306, 307. Skip module machinery if not installed. Known failures reported as 'K'
154 154 * `331 <https://github.com/ipython/ipython/issues/331>`_: Tweak config loader for PyPy compatibility.
155 155 * `319 <https://github.com/ipython/ipython/issues/319>`_: Rewrite code to restore readline history after an action
156 156 * `329 <https://github.com/ipython/ipython/issues/329>`_: Do not store file contents in history when running a .ipy file.
157 157 * `179 <https://github.com/ipython/ipython/issues/179>`_: Html notebook
158 158 * `323 <https://github.com/ipython/ipython/issues/323>`_: Add missing external.pexpect to packages
159 159 * `295 <https://github.com/ipython/ipython/issues/295>`_: Magic local scope
160 160 * `315 <https://github.com/ipython/ipython/issues/315>`_: Unicode magic args
161 161 * `310 <https://github.com/ipython/ipython/issues/310>`_: allow Unicode Command-Line options
162 162 * `313 <https://github.com/ipython/ipython/issues/313>`_: Readline shortcuts
163 163 * `311 <https://github.com/ipython/ipython/issues/311>`_: Qtconsole exit
164 164 * `312 <https://github.com/ipython/ipython/issues/312>`_: History memory
165 165 * `294 <https://github.com/ipython/ipython/issues/294>`_: Issue 290
166 166 * `292 <https://github.com/ipython/ipython/issues/292>`_: Issue 31
167 167 * `252 <https://github.com/ipython/ipython/issues/252>`_: Unicode issues
168 168 * `235 <https://github.com/ipython/ipython/issues/235>`_: Fix history magic command's bugs wrt to full history and add -O option to display full history
169 169 * `236 <https://github.com/ipython/ipython/issues/236>`_: History minus p flag
170 170 * `261 <https://github.com/ipython/ipython/issues/261>`_: Adapt magic commands to new history system.
171 171 * `282 <https://github.com/ipython/ipython/issues/282>`_: SQLite history
172 172 * `191 <https://github.com/ipython/ipython/issues/191>`_: Unbundle external libraries
173 173 * `199 <https://github.com/ipython/ipython/issues/199>`_: Magic arguments
174 174 * `204 <https://github.com/ipython/ipython/issues/204>`_: Emacs completion bugfix
175 175 * `293 <https://github.com/ipython/ipython/issues/293>`_: Issue 133
176 176 * `249 <https://github.com/ipython/ipython/issues/249>`_: Writing unicode characters to a log file. (IPython 0.10.2.git)
177 177 * `283 <https://github.com/ipython/ipython/issues/283>`_: Support for 256-color escape sequences in Qt console
178 178 * `281 <https://github.com/ipython/ipython/issues/281>`_: Refactored and improved Qt console's HTML export facility
179 179 * `237 <https://github.com/ipython/ipython/issues/237>`_: Fix185 (take two)
180 180 * `251 <https://github.com/ipython/ipython/issues/251>`_: Issue 129
181 181 * `278 <https://github.com/ipython/ipython/issues/278>`_: add basic XDG_CONFIG_HOME support
182 182 * `275 <https://github.com/ipython/ipython/issues/275>`_: inline pylab cuts off labels on log plots
183 183 * `280 <https://github.com/ipython/ipython/issues/280>`_: Add %precision magic
184 184 * `259 <https://github.com/ipython/ipython/issues/259>`_: Pyside support
185 185 * `193 <https://github.com/ipython/ipython/issues/193>`_: Make ipython cProfile-able
186 186 * `272 <https://github.com/ipython/ipython/issues/272>`_: Magic examples
187 187 * `219 <https://github.com/ipython/ipython/issues/219>`_: Doc magic pycat
188 188 * `221 <https://github.com/ipython/ipython/issues/221>`_: Doc magic alias
189 189 * `230 <https://github.com/ipython/ipython/issues/230>`_: Doc magic edit
190 190 * `224 <https://github.com/ipython/ipython/issues/224>`_: Doc magic cpaste
191 191 * `229 <https://github.com/ipython/ipython/issues/229>`_: Doc magic pdef
192 192 * `273 <https://github.com/ipython/ipython/issues/273>`_: Docs build
193 193 * `228 <https://github.com/ipython/ipython/issues/228>`_: Doc magic who
194 194 * `233 <https://github.com/ipython/ipython/issues/233>`_: Doc magic cd
195 195 * `226 <https://github.com/ipython/ipython/issues/226>`_: Doc magic pwd
196 196 * `218 <https://github.com/ipython/ipython/issues/218>`_: Doc magic history
197 197 * `231 <https://github.com/ipython/ipython/issues/231>`_: Doc magic reset
198 198 * `225 <https://github.com/ipython/ipython/issues/225>`_: Doc magic save
199 199 * `222 <https://github.com/ipython/ipython/issues/222>`_: Doc magic timeit
200 200 * `223 <https://github.com/ipython/ipython/issues/223>`_: Doc magic colors
201 201 * `203 <https://github.com/ipython/ipython/issues/203>`_: Small typos in zmq/blockingkernelmanager.py
202 202 * `227 <https://github.com/ipython/ipython/issues/227>`_: Doc magic logon
203 203 * `232 <https://github.com/ipython/ipython/issues/232>`_: Doc magic profile
204 204 * `264 <https://github.com/ipython/ipython/issues/264>`_: Kernel logging
205 205 * `220 <https://github.com/ipython/ipython/issues/220>`_: Doc magic edit
206 206 * `268 <https://github.com/ipython/ipython/issues/268>`_: PyZMQ >= 2.0.10
207 207 * `267 <https://github.com/ipython/ipython/issues/267>`_: GitHub Pages (again)
208 208 * `266 <https://github.com/ipython/ipython/issues/266>`_: OSX-specific fixes to the Qt console
209 209 * `255 <https://github.com/ipython/ipython/issues/255>`_: Gitwash typo
210 210 * `265 <https://github.com/ipython/ipython/issues/265>`_: Fix string input2
211 211 * `260 <https://github.com/ipython/ipython/issues/260>`_: Kernel crash with empty history
212 212 * `243 <https://github.com/ipython/ipython/issues/243>`_: New display system
213 213 * `242 <https://github.com/ipython/ipython/issues/242>`_: Fix terminal exit
214 214 * `250 <https://github.com/ipython/ipython/issues/250>`_: always use Session.send
215 215 * `239 <https://github.com/ipython/ipython/issues/239>`_: Makefile command & script for GitHub Pages
216 216 * `244 <https://github.com/ipython/ipython/issues/244>`_: My exit
217 217 * `234 <https://github.com/ipython/ipython/issues/234>`_: Timed history save
218 218 * `217 <https://github.com/ipython/ipython/issues/217>`_: Doc magic lsmagic
219 219 * `215 <https://github.com/ipython/ipython/issues/215>`_: History fix
220 220 * `195 <https://github.com/ipython/ipython/issues/195>`_: Formatters
221 221 * `192 <https://github.com/ipython/ipython/issues/192>`_: Ready colorize bug
222 222 * `198 <https://github.com/ipython/ipython/issues/198>`_: Windows workdir
223 223 * `174 <https://github.com/ipython/ipython/issues/174>`_: Whitespace cleanup
224 224 * `188 <https://github.com/ipython/ipython/issues/188>`_: Version info: update our version management system to use git.
225 225 * `158 <https://github.com/ipython/ipython/issues/158>`_: Ready for merge
226 226 * `187 <https://github.com/ipython/ipython/issues/187>`_: Resolved Print shortcut collision with ctrl-P emacs binding
227 227 * `183 <https://github.com/ipython/ipython/issues/183>`_: cleanup of exit/quit commands for qt console
228 228 * `184 <https://github.com/ipython/ipython/issues/184>`_: Logo added to sphinx docs
229 229 * `180 <https://github.com/ipython/ipython/issues/180>`_: Cleanup old code
230 230 * `171 <https://github.com/ipython/ipython/issues/171>`_: Expose Pygments styles as options
231 231 * `170 <https://github.com/ipython/ipython/issues/170>`_: HTML Fixes
232 232 * `172 <https://github.com/ipython/ipython/issues/172>`_: Fix del method exit test
233 233 * `164 <https://github.com/ipython/ipython/issues/164>`_: Qt frontend shutdown behavior fixes and enhancements
234 234 * `167 <https://github.com/ipython/ipython/issues/167>`_: Added HTML export
235 235 * `163 <https://github.com/ipython/ipython/issues/163>`_: Execution refactor
236 236 * `159 <https://github.com/ipython/ipython/issues/159>`_: Ipy3 preparation
237 237 * `155 <https://github.com/ipython/ipython/issues/155>`_: Ready startup fix
238 238 * `152 <https://github.com/ipython/ipython/issues/152>`_: 0.10.1 sge
239 239 * `151 <https://github.com/ipython/ipython/issues/151>`_: mk_object_info -> object_info
240 240 * `149 <https://github.com/ipython/ipython/issues/149>`_: Simple bug-fix
241 241
242 242 Regular issues (285):
243 243
244 244 * `630 <https://github.com/ipython/ipython/issues/630>`_: new.py in pwd prevents ipython from starting
245 245 * `623 <https://github.com/ipython/ipython/issues/623>`_: Execute DirectView commands while running LoadBalancedView tasks
246 246 * `437 <https://github.com/ipython/ipython/issues/437>`_: Users should have autocompletion in the notebook
247 247 * `583 <https://github.com/ipython/ipython/issues/583>`_: update manpages
248 248 * `594 <https://github.com/ipython/ipython/issues/594>`_: irunner command line options defer to file extensions
249 249 * `603 <https://github.com/ipython/ipython/issues/603>`_: Users should see colored text in tracebacks and the pager
250 250 * `597 <https://github.com/ipython/ipython/issues/597>`_: UnicodeDecodeError: 'ascii' codec can't decode byte 0xc2
251 251 * `608 <https://github.com/ipython/ipython/issues/608>`_: Organize and layout buttons in the notebook panel sections
252 252 * `609 <https://github.com/ipython/ipython/issues/609>`_: Implement controls in the Kernel panel section
253 253 * `611 <https://github.com/ipython/ipython/issues/611>`_: Add kernel status widget back to notebook
254 254 * `610 <https://github.com/ipython/ipython/issues/610>`_: Implement controls in the Cell section panel
255 255 * `612 <https://github.com/ipython/ipython/issues/612>`_: Implement Help panel section
256 256 * `621 <https://github.com/ipython/ipython/issues/621>`_: [qtconsole] on windows xp, cannot PageUp more than once
257 257 * `616 <https://github.com/ipython/ipython/issues/616>`_: Store exit status of last command
258 258 * `605 <https://github.com/ipython/ipython/issues/605>`_: Users should be able to open different notebooks in the cwd
259 259 * `302 <https://github.com/ipython/ipython/issues/302>`_: Users should see a consistent behavior in the Out prompt in the html notebook
260 260 * `435 <https://github.com/ipython/ipython/issues/435>`_: Notebook should not import anything by default
261 261 * `595 <https://github.com/ipython/ipython/issues/595>`_: qtconsole command issue
262 262 * `588 <https://github.com/ipython/ipython/issues/588>`_: ipython-qtconsole uses 100% CPU
263 263 * `586 <https://github.com/ipython/ipython/issues/586>`_: ? + plot() Command B0rks QTConsole Strangely
264 264 * `585 <https://github.com/ipython/ipython/issues/585>`_: %pdoc throws Errors for classes without __init__ or docstring
265 265 * `584 <https://github.com/ipython/ipython/issues/584>`_: %pdoc throws TypeError
266 266 * `580 <https://github.com/ipython/ipython/issues/580>`_: Client instantiation AssertionError
267 267 * `569 <https://github.com/ipython/ipython/issues/569>`_: UnicodeDecodeError during startup
268 268 * `572 <https://github.com/ipython/ipython/issues/572>`_: Indented command hits error
269 269 * `573 <https://github.com/ipython/ipython/issues/573>`_: -wthread breaks indented top-level statements
270 270 * `570 <https://github.com/ipython/ipython/issues/570>`_: "--pylab inline" vs. "--pylab=inline"
271 271 * `566 <https://github.com/ipython/ipython/issues/566>`_: Can't use exec_file in config file
272 272 * `562 <https://github.com/ipython/ipython/issues/562>`_: update docs to reflect '--args=values'
273 273 * `558 <https://github.com/ipython/ipython/issues/558>`_: triple quote and %s at beginning of line
274 274 * `554 <https://github.com/ipython/ipython/issues/554>`_: Update 0.11 docs to explain Qt console and how to do a clean install
275 275 * `553 <https://github.com/ipython/ipython/issues/553>`_: embed() fails if config files not installed
276 276 * `8 <https://github.com/ipython/ipython/issues/8>`_: Ensure %gui qt works with new Mayavi and pylab
277 277 * `269 <https://github.com/ipython/ipython/issues/269>`_: Provide compatibility api for IPython.Shell().start().mainloop()
278 278 * `66 <https://github.com/ipython/ipython/issues/66>`_: Update the main What's New document to reflect work on 0.11
279 279 * `549 <https://github.com/ipython/ipython/issues/549>`_: Don't check for 'linux2' value in sys.platform
280 280 * `505 <https://github.com/ipython/ipython/issues/505>`_: Qt windows created within imported functions won't show()
281 281 * `545 <https://github.com/ipython/ipython/issues/545>`_: qtconsole ignores exec_lines
282 282 * `371 <https://github.com/ipython/ipython/issues/371>`_: segfault in qtconsole when kernel quits
283 283 * `377 <https://github.com/ipython/ipython/issues/377>`_: Failure: error (nothing to repeat)
284 284 * `544 <https://github.com/ipython/ipython/issues/544>`_: Ipython qtconsole pylab config issue.
285 285 * `543 <https://github.com/ipython/ipython/issues/543>`_: RuntimeError in completer
286 286 * `440 <https://github.com/ipython/ipython/issues/440>`_: %run filename autocompletion "The kernel heartbeat has been inactive ... " error
287 287 * `541 <https://github.com/ipython/ipython/issues/541>`_: log_level is broken in the ipython Application
288 288 * `369 <https://github.com/ipython/ipython/issues/369>`_: windows source install doesn't create scripts correctly
289 289 * `351 <https://github.com/ipython/ipython/issues/351>`_: Make sure that the Windows installer handles the top-level IPython scripts.
290 290 * `512 <https://github.com/ipython/ipython/issues/512>`_: Two displayhooks in zmq
291 291 * `340 <https://github.com/ipython/ipython/issues/340>`_: Make sure that the Windows HPC scheduler support is working for 0.11
292 292 * `98 <https://github.com/ipython/ipython/issues/98>`_: Should be able to get help on an object mid-command
293 293 * `529 <https://github.com/ipython/ipython/issues/529>`_: unicode problem in qtconsole for windows
294 294 * `476 <https://github.com/ipython/ipython/issues/476>`_: Separate input area in Qt Console
295 295 * `175 <https://github.com/ipython/ipython/issues/175>`_: Qt console needs configuration support
296 296 * `156 <https://github.com/ipython/ipython/issues/156>`_: Key history lost when debugging program crash
297 297 * `470 <https://github.com/ipython/ipython/issues/470>`_: decorator: uses deprecated features
298 298 * `30 <https://github.com/ipython/ipython/issues/30>`_: readline in OS X does not have correct key bindings
299 299 * `503 <https://github.com/ipython/ipython/issues/503>`_: merge IPython.parallel.streamsession and IPython.zmq.session
300 300 * `456 <https://github.com/ipython/ipython/issues/456>`_: pathname in document punctuated by dots not slashes
301 301 * `451 <https://github.com/ipython/ipython/issues/451>`_: Allow switching the default image format for inline mpl backend
302 302 * `79 <https://github.com/ipython/ipython/issues/79>`_: Implement more robust handling of config stages in Application
303 303 * `522 <https://github.com/ipython/ipython/issues/522>`_: Encoding problems
304 304 * `524 <https://github.com/ipython/ipython/issues/524>`_: otool should not be unconditionally called on osx
305 305 * `523 <https://github.com/ipython/ipython/issues/523>`_: Get profile and config file inheritance working
306 306 * `519 <https://github.com/ipython/ipython/issues/519>`_: qtconsole --pure: "TypeError: string indices must be integers, not str"
307 307 * `516 <https://github.com/ipython/ipython/issues/516>`_: qtconsole --pure: "KeyError: 'ismagic'"
308 308 * `520 <https://github.com/ipython/ipython/issues/520>`_: qtconsole --pure: "TypeError: string indices must be integers, not str"
309 309 * `450 <https://github.com/ipython/ipython/issues/450>`_: resubmitted tasks sometimes stuck as pending
310 310 * `518 <https://github.com/ipython/ipython/issues/518>`_: JSON serialization problems with ObjectId type (MongoDB)
311 311 * `178 <https://github.com/ipython/ipython/issues/178>`_: Channels should be named for their function, not their socket type
312 312 * `515 <https://github.com/ipython/ipython/issues/515>`_: [ipcluster] termination on os x
313 313 * `510 <https://github.com/ipython/ipython/issues/510>`_: qtconsole: indentation problem printing numpy arrays
314 314 * `508 <https://github.com/ipython/ipython/issues/508>`_: "AssertionError: Missing message part." in ipython-qtconsole --pure
315 315 * `499 <https://github.com/ipython/ipython/issues/499>`_: "ZMQError: Interrupted system call" when saving inline figure
316 316 * `426 <https://github.com/ipython/ipython/issues/426>`_: %edit magic fails in qtconsole
317 317 * `497 <https://github.com/ipython/ipython/issues/497>`_: Don't show info from .pyd files
318 318 * `493 <https://github.com/ipython/ipython/issues/493>`_: QFont::setPointSize: Point size <= 0 (0), must be greater than 0
319 319 * `489 <https://github.com/ipython/ipython/issues/489>`_: UnicodeEncodeError in qt.svg.save_svg
320 320 * `458 <https://github.com/ipython/ipython/issues/458>`_: embed() doesn't load default config
321 321 * `488 <https://github.com/ipython/ipython/issues/488>`_: Using IPython with RubyPython leads to problems with IPython.parallel.client.client.Client.__init()
322 322 * `401 <https://github.com/ipython/ipython/issues/401>`_: Race condition when running lbview.apply() fast multiple times in loop
323 323 * `168 <https://github.com/ipython/ipython/issues/168>`_: Scrub Launchpad links from code, docs
324 324 * `141 <https://github.com/ipython/ipython/issues/141>`_: garbage collection problem (revisited)
325 325 * `59 <https://github.com/ipython/ipython/issues/59>`_: test_magic.test_obj_del fails on win32
326 326 * `457 <https://github.com/ipython/ipython/issues/457>`_: Backgrounded Tasks not Allowed? (but easy to slip by . . .)
327 327 * `297 <https://github.com/ipython/ipython/issues/297>`_: Shouldn't use pexpect for subprocesses in in-process terminal frontend
328 328 * `110 <https://github.com/ipython/ipython/issues/110>`_: magic to return exit status
329 329 * `473 <https://github.com/ipython/ipython/issues/473>`_: OSX readline detection fails in the debugger
330 330 * `466 <https://github.com/ipython/ipython/issues/466>`_: tests fail without unicode filename support
331 331 * `468 <https://github.com/ipython/ipython/issues/468>`_: iptest script has 0 exit code even when tests fail
332 332 * `465 <https://github.com/ipython/ipython/issues/465>`_: client.db_query() behaves different with SQLite and MongoDB
333 333 * `467 <https://github.com/ipython/ipython/issues/467>`_: magic_install_default_config test fails when there is no .ipython directory
334 334 * `463 <https://github.com/ipython/ipython/issues/463>`_: IPYTHON_DIR (and IPYTHONDIR) don't expand tilde to '~' directory
335 335 * `446 <https://github.com/ipython/ipython/issues/446>`_: Test machinery is imported at normal runtime
336 336 * `438 <https://github.com/ipython/ipython/issues/438>`_: Users should be able to use Up/Down for cell navigation
337 337 * `439 <https://github.com/ipython/ipython/issues/439>`_: Users should be able to copy notebook input and output
338 338 * `291 <https://github.com/ipython/ipython/issues/291>`_: Rename special display methods and put them lower in priority than display functions
339 339 * `447 <https://github.com/ipython/ipython/issues/447>`_: Instantiating classes without __init__ function causes kernel to crash
340 340 * `444 <https://github.com/ipython/ipython/issues/444>`_: Ctrl + t in WxIPython Causes Unexpected Behavior
341 341 * `445 <https://github.com/ipython/ipython/issues/445>`_: qt and console Based Startup Errors
342 342 * `428 <https://github.com/ipython/ipython/issues/428>`_: ipcluster doesn't handle stale pid info well
343 343 * `434 <https://github.com/ipython/ipython/issues/434>`_: 10.0.2 seg fault with rpy2
344 344 * `441 <https://github.com/ipython/ipython/issues/441>`_: Allow running a block of code in a file
345 345 * `432 <https://github.com/ipython/ipython/issues/432>`_: Silent request fails
346 346 * `409 <https://github.com/ipython/ipython/issues/409>`_: Test failure in IPython.lib
347 347 * `402 <https://github.com/ipython/ipython/issues/402>`_: History section of messaging spec is incorrect
348 348 * `88 <https://github.com/ipython/ipython/issues/88>`_: Error when inputting UTF8 CJK characters
349 349 * `366 <https://github.com/ipython/ipython/issues/366>`_: Ctrl-K should kill line and store it, so that Ctrl-y can yank it back
350 350 * `425 <https://github.com/ipython/ipython/issues/425>`_: typo in %gui magic help
351 351 * `304 <https://github.com/ipython/ipython/issues/304>`_: Persistent warnings if old configuration files exist
352 352 * `216 <https://github.com/ipython/ipython/issues/216>`_: crash of ipython when alias is used with %s and echo
353 353 * `412 <https://github.com/ipython/ipython/issues/412>`_: add support to automatic retry of tasks
354 354 * `411 <https://github.com/ipython/ipython/issues/411>`_: add support to continue tasks
355 355 * `417 <https://github.com/ipython/ipython/issues/417>`_: IPython should display things unsorted if it can't sort them
356 356 * `416 <https://github.com/ipython/ipython/issues/416>`_: wrong encode when printing unicode string
357 357 * `376 <https://github.com/ipython/ipython/issues/376>`_: Failing InputsplitterTest
358 358 * `405 <https://github.com/ipython/ipython/issues/405>`_: TraitError in traitlets.py(332) on any input
359 359 * `392 <https://github.com/ipython/ipython/issues/392>`_: UnicodeEncodeError on start
360 360 * `137 <https://github.com/ipython/ipython/issues/137>`_: sys.getfilesystemencoding return value not checked
361 361 * `300 <https://github.com/ipython/ipython/issues/300>`_: Users should be able to manage kernels and kernel sessions from the notebook UI
362 362 * `301 <https://github.com/ipython/ipython/issues/301>`_: Users should have access to working Kernel, Tabs, Edit, Help menus in the notebook
363 363 * `396 <https://github.com/ipython/ipython/issues/396>`_: cursor move triggers a lot of IO access
364 364 * `379 <https://github.com/ipython/ipython/issues/379>`_: Minor doc nit: --paging argument
365 365 * `399 <https://github.com/ipython/ipython/issues/399>`_: Add task queue limit in engine when load-balancing
366 366 * `78 <https://github.com/ipython/ipython/issues/78>`_: StringTask won't take unicode code strings
367 367 * `391 <https://github.com/ipython/ipython/issues/391>`_: MongoDB.add_record() does not work in 0.11dev
368 368 * `365 <https://github.com/ipython/ipython/issues/365>`_: newparallel on Windows
369 369 * `386 <https://github.com/ipython/ipython/issues/386>`_: FAIL: test that pushed functions have access to globals
370 370 * `387 <https://github.com/ipython/ipython/issues/387>`_: Interactively defined functions can't access user namespace
371 371 * `118 <https://github.com/ipython/ipython/issues/118>`_: Snow Leopard ipy_vimserver POLL error
372 372 * `394 <https://github.com/ipython/ipython/issues/394>`_: System escape interpreted in multi-line string
373 373 * `26 <https://github.com/ipython/ipython/issues/26>`_: find_job_cmd is too hasty to fail on Windows
374 374 * `368 <https://github.com/ipython/ipython/issues/368>`_: Installation instructions in dev docs are completely wrong
375 375 * `380 <https://github.com/ipython/ipython/issues/380>`_: qtconsole pager RST - HTML not happening consistently
376 376 * `367 <https://github.com/ipython/ipython/issues/367>`_: Qt console doesn't support ibus input method
377 377 * `375 <https://github.com/ipython/ipython/issues/375>`_: Missing libraries cause ImportError in tests
378 378 * `71 <https://github.com/ipython/ipython/issues/71>`_: temp file errors in iptest IPython.core
379 379 * `350 <https://github.com/ipython/ipython/issues/350>`_: Decide how to handle displayhook being triggered multiple times
380 380 * `360 <https://github.com/ipython/ipython/issues/360>`_: Remove `runlines` method
381 381 * `125 <https://github.com/ipython/ipython/issues/125>`_: Exec lines in config should not contribute to line numbering or history
382 382 * `20 <https://github.com/ipython/ipython/issues/20>`_: Robust readline support on OS X's builtin Python
383 383 * `147 <https://github.com/ipython/ipython/issues/147>`_: On Windows, %page is being too restrictive to split line by \r\n only
384 384 * `326 <https://github.com/ipython/ipython/issues/326>`_: Update docs and examples for parallel stuff to reflect movement away from Twisted
385 385 * `341 <https://github.com/ipython/ipython/issues/341>`_: FIx Parallel Magics for newparallel
386 386 * `338 <https://github.com/ipython/ipython/issues/338>`_: Usability improvements to Qt console
387 387 * `142 <https://github.com/ipython/ipython/issues/142>`_: unexpected auto-indenting when varibles names that start with 'pass'
388 388 * `296 <https://github.com/ipython/ipython/issues/296>`_: Automatic PDB via %pdb doesn't work
389 389 * `337 <https://github.com/ipython/ipython/issues/337>`_: exit( and quit( in Qt console produces phantom signature/docstring popup, even though quit() or exit() raises NameError
390 390 * `318 <https://github.com/ipython/ipython/issues/318>`_: %debug broken in master: invokes missing save_history() method
391 391 * `307 <https://github.com/ipython/ipython/issues/307>`_: lines ending with semicolon should not go to cache
392 392 * `104 <https://github.com/ipython/ipython/issues/104>`_: have ipengine run start-up scripts before registering with the controller
393 393 * `33 <https://github.com/ipython/ipython/issues/33>`_: The skip_doctest decorator is failing to work on Shell.MatplotlibShellBase.magic_run
394 394 * `336 <https://github.com/ipython/ipython/issues/336>`_: Missing figure development/figs/iopubfade.png for docs
395 395 * `49 <https://github.com/ipython/ipython/issues/49>`_: %clear should also delete _NN references and Out[NN] ones
396 396 * `335 <https://github.com/ipython/ipython/issues/335>`_: using setuptools installs every script twice
397 397 * `306 <https://github.com/ipython/ipython/issues/306>`_: multiline strings at end of input cause noop
398 398 * `327 <https://github.com/ipython/ipython/issues/327>`_: PyPy compatibility
399 399 * `328 <https://github.com/ipython/ipython/issues/328>`_: %run script.ipy raises "ERROR! Session/line number was not unique in database."
400 400 * `7 <https://github.com/ipython/ipython/issues/7>`_: Update the changes doc to reflect the kernel config work
401 401 * `303 <https://github.com/ipython/ipython/issues/303>`_: Users should be able to scroll a notebook w/o moving the menu/buttons
402 402 * `322 <https://github.com/ipython/ipython/issues/322>`_: Embedding an interactive IPython shell
403 403 * `321 <https://github.com/ipython/ipython/issues/321>`_: %debug broken in master
404 404 * `287 <https://github.com/ipython/ipython/issues/287>`_: Crash when using %macros in sqlite-history branch
405 405 * `55 <https://github.com/ipython/ipython/issues/55>`_: Can't edit files whose names begin with numbers
406 406 * `284 <https://github.com/ipython/ipython/issues/284>`_: In variable no longer works in 0.11
407 407 * `92 <https://github.com/ipython/ipython/issues/92>`_: Using multiprocessing module crashes parallel iPython
408 408 * `262 <https://github.com/ipython/ipython/issues/262>`_: Fail to recover history after force-kill.
409 409 * `320 <https://github.com/ipython/ipython/issues/320>`_: Tab completing re.search objects crashes IPython
410 410 * `317 <https://github.com/ipython/ipython/issues/317>`_: IPython.kernel: parallel map issues
411 411 * `197 <https://github.com/ipython/ipython/issues/197>`_: ipython-qtconsole unicode problem in magic ls
412 412 * `305 <https://github.com/ipython/ipython/issues/305>`_: more readline shortcuts in qtconsole
413 413 * `314 <https://github.com/ipython/ipython/issues/314>`_: Multi-line, multi-block cells can't be executed.
414 414 * `308 <https://github.com/ipython/ipython/issues/308>`_: Test suite should set sqlite history to work in :memory:
415 415 * `202 <https://github.com/ipython/ipython/issues/202>`_: Matplotlib native 'MacOSX' backend broken in '-pylab' mode
416 416 * `196 <https://github.com/ipython/ipython/issues/196>`_: IPython can't deal with unicode file name.
417 417 * `25 <https://github.com/ipython/ipython/issues/25>`_: unicode bug - encoding input
418 418 * `290 <https://github.com/ipython/ipython/issues/290>`_: try/except/else clauses can't be typed, code input stops too early.
419 419 * `43 <https://github.com/ipython/ipython/issues/43>`_: Implement SSH support in ipcluster
420 420 * `6 <https://github.com/ipython/ipython/issues/6>`_: Update the Sphinx docs for the new ipcluster
421 421 * `9 <https://github.com/ipython/ipython/issues/9>`_: Getting "DeadReferenceError: Calling Stale Broker" after ipcontroller restart
422 422 * `132 <https://github.com/ipython/ipython/issues/132>`_: Ipython prevent south from working
423 423 * `27 <https://github.com/ipython/ipython/issues/27>`_: generics.complete_object broken
424 424 * `60 <https://github.com/ipython/ipython/issues/60>`_: Improve absolute import management for iptest.py
425 425 * `31 <https://github.com/ipython/ipython/issues/31>`_: Issues in magic_whos code
426 426 * `52 <https://github.com/ipython/ipython/issues/52>`_: Document testing process better
427 427 * `44 <https://github.com/ipython/ipython/issues/44>`_: Merge history from multiple sessions
428 428 * `182 <https://github.com/ipython/ipython/issues/182>`_: ipython q4thread in version 10.1 not starting properly
429 429 * `143 <https://github.com/ipython/ipython/issues/143>`_: Ipython.gui.wx.ipython_view.IPShellWidget: ignores user*_ns arguments
430 430 * `127 <https://github.com/ipython/ipython/issues/127>`_: %edit does not work on filenames consisted of pure numbers
431 431 * `126 <https://github.com/ipython/ipython/issues/126>`_: Can't transfer command line argument to script
432 432 * `28 <https://github.com/ipython/ipython/issues/28>`_: Offer finer control for initialization of input streams
433 433 * `58 <https://github.com/ipython/ipython/issues/58>`_: ipython change char '0xe9' to 4 spaces
434 434 * `68 <https://github.com/ipython/ipython/issues/68>`_: Problems with Control-C stopping ipcluster on Windows/Python2.6
435 435 * `24 <https://github.com/ipython/ipython/issues/24>`_: ipcluster does not start all the engines
436 436 * `240 <https://github.com/ipython/ipython/issues/240>`_: Incorrect method displayed in %psource
437 437 * `120 <https://github.com/ipython/ipython/issues/120>`_: inspect.getsource fails for functions defined on command line
438 438 * `212 <https://github.com/ipython/ipython/issues/212>`_: IPython ignores exceptions in the first evaulation of class attrs
439 439 * `108 <https://github.com/ipython/ipython/issues/108>`_: ipython disables python logger
440 440 * `100 <https://github.com/ipython/ipython/issues/100>`_: Overzealous introspection
441 441 * `18 <https://github.com/ipython/ipython/issues/18>`_: %cpaste freeze sync frontend
442 442 * `200 <https://github.com/ipython/ipython/issues/200>`_: Unicode error when starting ipython in a folder with non-ascii path
443 443 * `130 <https://github.com/ipython/ipython/issues/130>`_: Deadlock when importing a module that creates an IPython client
444 444 * `134 <https://github.com/ipython/ipython/issues/134>`_: multline block scrolling
445 445 * `46 <https://github.com/ipython/ipython/issues/46>`_: Input to %timeit is not preparsed
446 446 * `285 <https://github.com/ipython/ipython/issues/285>`_: ipcluster local -n 4 fails
447 447 * `205 <https://github.com/ipython/ipython/issues/205>`_: In the Qt console, Tab should insert 4 spaces when not completing
448 * `145 <https://github.com/ipython/ipython/issues/145>`_: Bug on MSW sytems: idle can not be set as default IPython editor. Fix Suggested.
448 * `145 <https://github.com/ipython/ipython/issues/145>`_: Bug on MSW systems: idle can not be set as default IPython editor. Fix Suggested.
449 449 * `77 <https://github.com/ipython/ipython/issues/77>`_: ipython oops in cygwin
450 450 * `121 <https://github.com/ipython/ipython/issues/121>`_: If plot windows are closed via window controls, no more plotting is possible.
451 451 * `111 <https://github.com/ipython/ipython/issues/111>`_: Iterator version of TaskClient.map() that returns results as they become available
452 452 * `109 <https://github.com/ipython/ipython/issues/109>`_: WinHPCLauncher is a hard dependency that causes errors in the test suite
453 453 * `86 <https://github.com/ipython/ipython/issues/86>`_: Make IPython work with multiprocessing
454 454 * `15 <https://github.com/ipython/ipython/issues/15>`_: Implement SGE support in ipcluster
455 455 * `3 <https://github.com/ipython/ipython/issues/3>`_: Implement PBS support in ipcluster
456 456 * `53 <https://github.com/ipython/ipython/issues/53>`_: Internal Python error in the inspect module
457 457 * `74 <https://github.com/ipython/ipython/issues/74>`_: Manager() [from multiprocessing module] hangs ipythonx but not ipython
458 458 * `51 <https://github.com/ipython/ipython/issues/51>`_: Out not working with ipythonx
459 459 * `201 <https://github.com/ipython/ipython/issues/201>`_: use session.send throughout zmq code
460 460 * `115 <https://github.com/ipython/ipython/issues/115>`_: multiline specials not defined in 0.11 branch
461 461 * `93 <https://github.com/ipython/ipython/issues/93>`_: when looping, cursor appears at leftmost point in newline
462 462 * `133 <https://github.com/ipython/ipython/issues/133>`_: whitespace after Source introspection
463 463 * `50 <https://github.com/ipython/ipython/issues/50>`_: Ctrl-C with -gthread on Windows, causes uncaught IOError
464 464 * `65 <https://github.com/ipython/ipython/issues/65>`_: Do not use .message attributes in exceptions, deprecated in 2.6
465 465 * `76 <https://github.com/ipython/ipython/issues/76>`_: syntax error when raise is inside except process
466 466 * `107 <https://github.com/ipython/ipython/issues/107>`_: bdist_rpm causes traceback looking for a non-existant file
467 467 * `113 <https://github.com/ipython/ipython/issues/113>`_: initial magic ? (question mark) fails before wildcard
468 468 * `128 <https://github.com/ipython/ipython/issues/128>`_: Pdb instance has no attribute 'curframe'
469 469 * `139 <https://github.com/ipython/ipython/issues/139>`_: running with -pylab pollutes namespace
470 470 * `140 <https://github.com/ipython/ipython/issues/140>`_: malloc error during tab completion of numpy array member functions starting with 'c'
471 471 * `153 <https://github.com/ipython/ipython/issues/153>`_: ipy_vimserver traceback on Windows
472 472 * `154 <https://github.com/ipython/ipython/issues/154>`_: using ipython in Slicer3 show how os.environ['HOME'] is not defined
473 473 * `185 <https://github.com/ipython/ipython/issues/185>`_: show() blocks in pylab mode with ipython 0.10.1
474 474 * `189 <https://github.com/ipython/ipython/issues/189>`_: Crash on tab completion
475 475 * `274 <https://github.com/ipython/ipython/issues/274>`_: bashism in sshx.sh
476 476 * `276 <https://github.com/ipython/ipython/issues/276>`_: Calling `sip.setapi` does not work if app has already imported from PyQt4
477 477 * `277 <https://github.com/ipython/ipython/issues/277>`_: matplotlib.image imgshow from 10.1 segfault
478 478 * `288 <https://github.com/ipython/ipython/issues/288>`_: Incorrect docstring in zmq/kernelmanager.py
479 479 * `286 <https://github.com/ipython/ipython/issues/286>`_: Fix IPython.Shell compatibility layer
480 480 * `99 <https://github.com/ipython/ipython/issues/99>`_: blank lines in history
481 481 * `129 <https://github.com/ipython/ipython/issues/129>`_: psearch: TypeError: expected string or buffer
482 482 * `190 <https://github.com/ipython/ipython/issues/190>`_: Add option to format float point output
483 483 * `246 <https://github.com/ipython/ipython/issues/246>`_: Application not conforms XDG Base Directory Specification
484 484 * `48 <https://github.com/ipython/ipython/issues/48>`_: IPython should follow the XDG Base Directory spec for configuration
485 485 * `176 <https://github.com/ipython/ipython/issues/176>`_: Make client-side history persistence readline-independent
486 486 * `279 <https://github.com/ipython/ipython/issues/279>`_: Backtraces when using ipdb do not respect -colour LightBG setting
487 487 * `119 <https://github.com/ipython/ipython/issues/119>`_: Broken type filter in magic_who_ls
488 488 * `271 <https://github.com/ipython/ipython/issues/271>`_: Intermittent problem with print output in Qt console.
489 489 * `270 <https://github.com/ipython/ipython/issues/270>`_: Small typo in IPython developer’s guide
490 490 * `166 <https://github.com/ipython/ipython/issues/166>`_: Add keyboard accelerators to Qt close dialog
491 491 * `173 <https://github.com/ipython/ipython/issues/173>`_: asymmetrical ctrl-A/ctrl-E behavior in multiline
492 492 * `45 <https://github.com/ipython/ipython/issues/45>`_: Autosave history for robustness
493 493 * `162 <https://github.com/ipython/ipython/issues/162>`_: make command history persist in ipythonqt
494 494 * `161 <https://github.com/ipython/ipython/issues/161>`_: make ipythonqt exit without dialog when exit() is called
495 495 * `263 <https://github.com/ipython/ipython/issues/263>`_: [ipython + numpy] Some test errors
496 496 * `256 <https://github.com/ipython/ipython/issues/256>`_: reset docstring ipython 0.10
497 * `258 <https://github.com/ipython/ipython/issues/258>`_: allow caching to avoid matplotlib object referrences
497 * `258 <https://github.com/ipython/ipython/issues/258>`_: allow caching to avoid matplotlib object references
498 498 * `248 <https://github.com/ipython/ipython/issues/248>`_: Can't open and read files after upgrade from 0.10 to 0.10.0
499 499 * `247 <https://github.com/ipython/ipython/issues/247>`_: ipython + Stackless
500 500 * `245 <https://github.com/ipython/ipython/issues/245>`_: Magic save and macro missing newlines, line ranges don't match prompt numbers.
501 501 * `241 <https://github.com/ipython/ipython/issues/241>`_: "exit" hangs on terminal version of IPython
502 502 * `213 <https://github.com/ipython/ipython/issues/213>`_: ipython -pylab no longer plots interactively on 0.10.1
503 503 * `4 <https://github.com/ipython/ipython/issues/4>`_: wx frontend don't display well commands output
504 504 * `5 <https://github.com/ipython/ipython/issues/5>`_: ls command not supported in ipythonx wx frontend
505 505 * `1 <https://github.com/ipython/ipython/issues/1>`_: Document winhpcjob.py and launcher.py
506 506 * `83 <https://github.com/ipython/ipython/issues/83>`_: Usage of testing.util.DeferredTestCase should be replace with twisted.trial.unittest.TestCase
507 507 * `117 <https://github.com/ipython/ipython/issues/117>`_: Redesign how Component instances are tracked and queried
508 508 * `47 <https://github.com/ipython/ipython/issues/47>`_: IPython.kernel.client cannot be imported inside an engine
509 509 * `105 <https://github.com/ipython/ipython/issues/105>`_: Refactor the task dependencies system
510 510 * `210 <https://github.com/ipython/ipython/issues/210>`_: 0.10.1 doc mistake - New IPython Sphinx directive error
511 511 * `209 <https://github.com/ipython/ipython/issues/209>`_: can't activate IPython parallel magics
512 512 * `206 <https://github.com/ipython/ipython/issues/206>`_: Buggy linewrap in Mac OSX Terminal
513 513 * `194 <https://github.com/ipython/ipython/issues/194>`_: !sudo <command> displays password in plain text
514 514 * `186 <https://github.com/ipython/ipython/issues/186>`_: %edit issue under OS X 10.5 - IPython 0.10.1
515 515 * `11 <https://github.com/ipython/ipython/issues/11>`_: Create a daily build PPA for ipython
516 516 * `144 <https://github.com/ipython/ipython/issues/144>`_: logo missing from sphinx docs
517 517 * `181 <https://github.com/ipython/ipython/issues/181>`_: cls command does not work on windows
518 518 * `169 <https://github.com/ipython/ipython/issues/169>`_: Kernel can only be bound to localhost
519 519 * `36 <https://github.com/ipython/ipython/issues/36>`_: tab completion does not escape ()
520 520 * `177 <https://github.com/ipython/ipython/issues/177>`_: Report tracebacks of interactively entered input
521 521 * `148 <https://github.com/ipython/ipython/issues/148>`_: dictionary having multiple keys having frozenset fails to print on iPython
522 522 * `160 <https://github.com/ipython/ipython/issues/160>`_: magic_gui throws TypeError when gui magic is used
523 523 * `150 <https://github.com/ipython/ipython/issues/150>`_: History entries ending with parentheses corrupt command line on OS X 10.6.4
524 524 * `146 <https://github.com/ipython/ipython/issues/146>`_: -ipythondir - using an alternative .ipython dir for rc type stuff
525 525 * `114 <https://github.com/ipython/ipython/issues/114>`_: Interactive strings get mangled with "_ip.magic"
526 526 * `135 <https://github.com/ipython/ipython/issues/135>`_: crash on invalid print
527 527 * `69 <https://github.com/ipython/ipython/issues/69>`_: Usage of "mycluster" profile in docs and examples
528 528 * `37 <https://github.com/ipython/ipython/issues/37>`_: Fix colors in output of ResultList on Windows
@@ -1,621 +1,621 b''
1 1 .. _issues_list_012:
2 2
3 3 Issues closed in the 0.12 development cycle
4 4 ===========================================
5 5
6 6 Issues closed in 0.12.1
7 7 -----------------------
8 8
9 9 GitHub stats for bugfix release 0.12.1 (12/28/2011-04/16/2012), backporting
10 10 pull requests from 0.13.
11 11
12 12 We closed a total of 71 issues: 44 pull requests and 27 issues; this is the
13 13 full list (generated with the script `tools/github_stats.py`).
14 14
15 15 This list is automatically generated, and may be incomplete:
16 16
17 17 Pull Requests (44):
18 18
19 19 * :ghpull:`1175`: core.completer: Clean up excessive and unused code.
20 20 * :ghpull:`1187`: misc notebook: connection file cleanup, first heartbeat, startup flush
21 21 * :ghpull:`1190`: Fix link to Chris Fonnesbeck blog post about 0.11 highlights.
22 22 * :ghpull:`1196`: docs: looks like a file path might have been accidentally pasted in the middle of a word
23 23 * :ghpull:`1206`: don't preserve fixConsole output in json
24 24 * :ghpull:`1207`: fix loadpy duplicating newlines
25 25 * :ghpull:`1213`: BUG: Minor typo in history_console_widget.py
26 26 * :ghpull:`1218`: Added -q option to %prun for suppression of the output, along with editing the dochelp string.
27 27 * :ghpull:`1222`: allow Reference as callable in map/apply
28 28 * :ghpull:`1229`: Fix display of SyntaxError in Python 3
29 29 * :ghpull:`1246`: Skip tests that require X, when importing pylab results in RuntimeError.
30 30 * :ghpull:`1253`: set auto_create flag for notebook apps
31 31 * :ghpull:`1257`: use self.kernel_manager_class in qtconsoleapp
32 32 * :ghpull:`1262`: Heartbeat no longer shares the app's Context
33 33 * :ghpull:`1283`: HeartMonitor.period should be an Integer
34 34 * :ghpull:`1284`: a fix for GH 1269
35 35 * :ghpull:`1289`: Make autoreload extension work on Python 3.
36 36 * :ghpull:`1306`: Fix %prun input parsing for escaped characters (closes #1302)
37 37 * :ghpull:`1312`: minor heartbeat tweaks
38 38 * :ghpull:`1318`: make Ctrl-D in qtconsole act same as in terminal (ready to merge)
39 39 * :ghpull:`1341`: Don't attempt to tokenize binary files for tracebacks
40 40 * :ghpull:`1353`: Save notebook as script using unicode file handle.
41 41 * :ghpull:`1363`: Fix some minor color/style config issues in the qtconsole
42 42 * :ghpull:`1364`: avoid jsonlib returning Decimal
43 43 * :ghpull:`1369`: load header with engine id when engine dies in TaskScheduler
44 44 * :ghpull:`1370`: allow draft76 websockets (Safari)
45 45 * :ghpull:`1374`: remove calls to meaningless ZMQStream.on_err
46 46 * :ghpull:`1377`: Saving non-ascii history
47 47 * :ghpull:`1396`: Fix for %tb magic.
48 48 * :ghpull:`1402`: fix symlinked /home issue for FreeBSD
49 49 * :ghpull:`1413`: get_home_dir expands symlinks, adjust test accordingly
50 50 * :ghpull:`1414`: ignore errors in shell.var_expand
51 51 * :ghpull:`1430`: Fix for tornado check for tornado < 1.1.0
52 52 * :ghpull:`1445`: Don't build sphinx docs for sdists
53 53 * :ghpull:`1463`: Fix completion when importing modules in the cwd.
54 54 * :ghpull:`1477`: fix dangling `buffer` in IPython.parallel.util
55 55 * :ghpull:`1495`: BUG: Fix pretty-printing for overzealous objects
56 56 * :ghpull:`1496`: BUG: LBYL when clearing the output history on shutdown.
57 57 * :ghpull:`1514`: DOC: Fix references to IPython.lib.pretty instead of the old location
58 58 * :ghpull:`1517`: Fix indentation bug in IPython/lib/pretty.py
59 59 * :ghpull:`1538`: store git commit hash in utils._sysinfo instead of hidden data file
60 60 * :ghpull:`1599`: Fix for %run -d in Python 3
61 61 * :ghpull:`1602`: Fix %env for Python 3
62 62 * :ghpull:`1607`: cleanup sqlitedb temporary db file after tests
63 63
64 64 Issues (27):
65 65
66 66 * :ghissue:`676`: IPython.embed() from ipython crashes twice on exit
67 67 * :ghissue:`846`: Autoreload extension doesn't work with Python 3.2
68 68 * :ghissue:`1187`: misc notebook: connection file cleanup, first heartbeat, startup flush
69 69 * :ghissue:`1191`: profile/startup files not executed with "notebook"
70 70 * :ghissue:`1197`: Interactive shell trying to: from ... import history
71 71 * :ghissue:`1198`: Kernel Has Died error in Notebook
72 72 * :ghissue:`1201`: %env magic fails with Python 3.2
73 73 * :ghissue:`1204`: double newline from %loadpy in python notebook (at least on mac)
74 74 * :ghissue:`1208`: should dv.sync_import print failed imports ?
75 75 * :ghissue:`1225`: SyntaxError display broken in Python 3
76 76 * :ghissue:`1232`: Dead kernel loop
77 77 * :ghissue:`1241`: When our debugger class is used standalone `_oh` key errors are thrown
78 78 * :ghissue:`1254`: typo in notebooklist.js breaks links
79 79 * :ghissue:`1260`: heartbeat failure on long gil-holding operation
80 80 * :ghissue:`1268`: notebook %reset magic fails with StdinNotImplementedError
81 81 * :ghissue:`1269`: Another strange input handling error
82 82 * :ghissue:`1281`: in Hub: registration_timeout must be an integer, but heartmonitor.period is CFloat
83 83 * :ghissue:`1302`: Input parsing with %prun clobbers escapes
84 84 * :ghissue:`1304`: controller/server load can disrupt heartbeat
85 85 * :ghissue:`1317`: Very slow traceback construction from Cython extension
86 86 * :ghissue:`1345`: notebook can't save unicode as script
87 87 * :ghissue:`1375`: %history -g -f file encoding issue
88 88 * :ghissue:`1401`: numpy arrays cannot be used with View.apply() in Python 3
89 89 * :ghissue:`1408`: test_get_home_dir_3 failed on Mac OS X
90 90 * :ghissue:`1412`: Input parsing issue with %prun
91 91 * :ghissue:`1421`: ipython32 %run -d breaks with NameError name 'execfile' is not defined
92 92 * :ghissue:`1484`: unhide .git_commit_info.ini
93 93
94 94
95 95 Issues closed in 0.12
96 96 ---------------------
97 97
98 98 In this cycle, from August 1 to December 28 2011, we closed a total of 515
99 99 issues, 257 pull requests and 258 regular issues; this is the full list
100 100 (generated with the script `tools/github_stats.py`).
101 101
102 102 Pull requests (257):
103 103
104 104 * `1174 <https://github.com/ipython/ipython/issues/1174>`_: Remove %install_default_config and %install_profiles
105 105 * `1178 <https://github.com/ipython/ipython/issues/1178>`_: Correct string type casting in pinfo.
106 106 * `1096 <https://github.com/ipython/ipython/issues/1096>`_: Show class init and call tooltips in notebook
107 107 * `1176 <https://github.com/ipython/ipython/issues/1176>`_: Modifications to profile list
108 108 * `1173 <https://github.com/ipython/ipython/issues/1173>`_: don't load gui/pylab in console frontend
109 109 * `1168 <https://github.com/ipython/ipython/issues/1168>`_: Add --script flag as shorthand for notebook save_script option.
110 110 * `1165 <https://github.com/ipython/ipython/issues/1165>`_: encode image_tag as utf8 in [x]html export
111 111 * `1161 <https://github.com/ipython/ipython/issues/1161>`_: Allow %loadpy to load remote URLs that don't end in .py
112 112 * `1158 <https://github.com/ipython/ipython/issues/1158>`_: Add coding header when notebook exported to .py file.
113 113 * `1160 <https://github.com/ipython/ipython/issues/1160>`_: don't ignore ctrl-C during `%gui qt`
114 114 * `1159 <https://github.com/ipython/ipython/issues/1159>`_: Add encoding header to Python files downloaded from notebooks.
115 115 * `1155 <https://github.com/ipython/ipython/issues/1155>`_: minor post-execute fixes (#1154)
116 116 * `1153 <https://github.com/ipython/ipython/issues/1153>`_: Pager tearing bug
117 117 * `1152 <https://github.com/ipython/ipython/issues/1152>`_: Add support for displaying maptlotlib axes directly.
118 118 * `1079 <https://github.com/ipython/ipython/issues/1079>`_: Login/out button cleanups
119 119 * `1151 <https://github.com/ipython/ipython/issues/1151>`_: allow access to user_ns in prompt_manager
120 120 * `1120 <https://github.com/ipython/ipython/issues/1120>`_: updated vim-ipython (pending)
121 121 * `1150 <https://github.com/ipython/ipython/issues/1150>`_: BUG: Scrolling pager in vsplit on Mac OSX tears.
122 122 * `1149 <https://github.com/ipython/ipython/issues/1149>`_: #1148 (win32 arg_split)
123 123 * `1147 <https://github.com/ipython/ipython/issues/1147>`_: Put qtconsole forground when launching
124 124 * `1146 <https://github.com/ipython/ipython/issues/1146>`_: allow saving notebook.py next to notebook.ipynb
125 125 * `1128 <https://github.com/ipython/ipython/issues/1128>`_: fix pylab StartMenu item
126 126 * `1140 <https://github.com/ipython/ipython/issues/1140>`_: Namespaces for embedding
127 127 * `1132 <https://github.com/ipython/ipython/issues/1132>`_: [notebook] read-only: disable name field
128 128 * `1125 <https://github.com/ipython/ipython/issues/1125>`_: notebook : update logo
129 129 * `1135 <https://github.com/ipython/ipython/issues/1135>`_: allow customized template and static file paths for the notebook web app
130 130 * `1122 <https://github.com/ipython/ipython/issues/1122>`_: BUG: Issue #755 qt IPythonWidget.execute_file fails if filename contains...
131 131 * `1137 <https://github.com/ipython/ipython/issues/1137>`_: rename MPIExecLaunchers to MPILaunchers
132 132 * `1130 <https://github.com/ipython/ipython/issues/1130>`_: optionally ignore shlex's ValueError in arg_split
133 133 * `1116 <https://github.com/ipython/ipython/issues/1116>`_: Shlex unicode
134 134 * `1073 <https://github.com/ipython/ipython/issues/1073>`_: Storemagic plugin
135 135 * `1143 <https://github.com/ipython/ipython/issues/1143>`_: Add post_install script to create start menu entries in Python 3
136 136 * `1138 <https://github.com/ipython/ipython/issues/1138>`_: Fix tests to work when ~/.config/ipython contains a symlink.
137 137 * `1121 <https://github.com/ipython/ipython/issues/1121>`_: Don't transform function calls on IPyAutocall objects
138 138 * `1118 <https://github.com/ipython/ipython/issues/1118>`_: protect CRLF from carriage-return action
139 139 * `1105 <https://github.com/ipython/ipython/issues/1105>`_: Fix for prompts containing newlines.
140 140 * `1126 <https://github.com/ipython/ipython/issues/1126>`_: Totally remove pager when read only (notebook)
141 141 * `1091 <https://github.com/ipython/ipython/issues/1091>`_: qtconsole : allow copy with shortcut in pager
142 142 * `1114 <https://github.com/ipython/ipython/issues/1114>`_: fix magics history in two-process ipython console
143 143 * `1113 <https://github.com/ipython/ipython/issues/1113>`_: Fixing #1112 removing failing asserts for test_carriage_return and test_beep
144 144 * `1089 <https://github.com/ipython/ipython/issues/1089>`_: Support carriage return ('\r') and beep ('\b') characters in the qtconsole
145 145 * `1108 <https://github.com/ipython/ipython/issues/1108>`_: Completer usability 2 (rebased of pr #1082)
146 146 * `864 <https://github.com/ipython/ipython/issues/864>`_: Two-process terminal frontend (ipython core branch)
147 147 * `1082 <https://github.com/ipython/ipython/issues/1082>`_: usability and cross browser compat for completer
148 148 * `1053 <https://github.com/ipython/ipython/issues/1053>`_: minor improvements to text placement in qtconsole
149 149 * `1106 <https://github.com/ipython/ipython/issues/1106>`_: Fix display of errors in compiled code on Python 3
150 150 * `1077 <https://github.com/ipython/ipython/issues/1077>`_: allow the notebook to run without MathJax
151 151 * `1072 <https://github.com/ipython/ipython/issues/1072>`_: If object has a getdoc() method, override its normal docstring.
152 152 * `1059 <https://github.com/ipython/ipython/issues/1059>`_: Switch to simple `__IPYTHON__` global
153 153 * `1070 <https://github.com/ipython/ipython/issues/1070>`_: Execution count after SyntaxError
154 154 * `1098 <https://github.com/ipython/ipython/issues/1098>`_: notebook: config section UI
155 155 * `1101 <https://github.com/ipython/ipython/issues/1101>`_: workaround spawnb missing from pexpect.__all__
156 156 * `1097 <https://github.com/ipython/ipython/issues/1097>`_: typo, should fix #1095
157 157 * `1099 <https://github.com/ipython/ipython/issues/1099>`_: qtconsole export xhtml/utf8
158 158 * `1083 <https://github.com/ipython/ipython/issues/1083>`_: Prompts
159 159 * `1081 <https://github.com/ipython/ipython/issues/1081>`_: Fix wildcard search for updated namespaces
160 160 * `1084 <https://github.com/ipython/ipython/issues/1084>`_: write busy in notebook window title...
161 161 * `1078 <https://github.com/ipython/ipython/issues/1078>`_: PromptManager fixes
162 162 * `1064 <https://github.com/ipython/ipython/issues/1064>`_: Win32 shlex
163 163 * `1069 <https://github.com/ipython/ipython/issues/1069>`_: As you type completer, fix on Firefox
164 164 * `1039 <https://github.com/ipython/ipython/issues/1039>`_: Base of an as you type completer.
165 165 * `1065 <https://github.com/ipython/ipython/issues/1065>`_: Qtconsole fix racecondition
166 166 * `507 <https://github.com/ipython/ipython/issues/507>`_: Prompt manager
167 167 * `1056 <https://github.com/ipython/ipython/issues/1056>`_: Warning in code. qtconsole ssh -X
168 168 * `1036 <https://github.com/ipython/ipython/issues/1036>`_: Clean up javascript based on js2-mode feedback.
169 169 * `1052 <https://github.com/ipython/ipython/issues/1052>`_: Pylab fix
170 170 * `648 <https://github.com/ipython/ipython/issues/648>`_: Usermod
171 171 * `969 <https://github.com/ipython/ipython/issues/969>`_: Pexpect-u
172 172 * `1007 <https://github.com/ipython/ipython/issues/1007>`_: Fix paste/cpaste bug and refactor/cleanup that code a lot.
173 173 * `506 <https://github.com/ipython/ipython/issues/506>`_: make ENTER on a previous input field replace current input buffer
174 174 * `1040 <https://github.com/ipython/ipython/issues/1040>`_: json/jsonapi cleanup
175 175 * `1042 <https://github.com/ipython/ipython/issues/1042>`_: fix firefox (windows) break line on empty prompt number
176 176 * `1015 <https://github.com/ipython/ipython/issues/1015>`_: emacs freezes when tab is hit in ipython with latest python-mode
177 177 * `1023 <https://github.com/ipython/ipython/issues/1023>`_: flush stdout/stderr at the end of kernel init
178 178 * `956 <https://github.com/ipython/ipython/issues/956>`_: Generate "All magics..." menu live
179 179 * `1038 <https://github.com/ipython/ipython/issues/1038>`_: Notebook: don't change cell when selecting code using shift+up/down.
180 180 * `987 <https://github.com/ipython/ipython/issues/987>`_: Add Tooltip to notebook.
181 181 * `1028 <https://github.com/ipython/ipython/issues/1028>`_: Cleaner minimum version comparison
182 182 * `998 <https://github.com/ipython/ipython/issues/998>`_: defer to stdlib for path.get_home_dir()
183 183 * `1033 <https://github.com/ipython/ipython/issues/1033>`_: update copyright to 2011/20xx-2011
184 184 * `1032 <https://github.com/ipython/ipython/issues/1032>`_: Intercept <esc> avoid closing websocket on Firefox
185 185 * `1030 <https://github.com/ipython/ipython/issues/1030>`_: use pyzmq tools where appropriate
186 186 * `1029 <https://github.com/ipython/ipython/issues/1029>`_: Restore pspersistence, including %store magic, as an extension.
187 187 * `1025 <https://github.com/ipython/ipython/issues/1025>`_: Dollar escape
188 188 * `999 <https://github.com/ipython/ipython/issues/999>`_: Fix issue #880 - more useful message to user when %paste fails
189 189 * `938 <https://github.com/ipython/ipython/issues/938>`_: changes to get ipython.el to work with the latest python-mode.el
190 190 * `1012 <https://github.com/ipython/ipython/issues/1012>`_: Add logout button.
191 191 * `1020 <https://github.com/ipython/ipython/issues/1020>`_: Dollar formatter for ! shell calls
192 192 * `1019 <https://github.com/ipython/ipython/issues/1019>`_: Use repr() to make quoted strings
193 193 * `1008 <https://github.com/ipython/ipython/issues/1008>`_: don't use crash_handler by default
194 194 * `1003 <https://github.com/ipython/ipython/issues/1003>`_: Drop consecutive duplicates when refilling readline history
195 195 * `997 <https://github.com/ipython/ipython/issues/997>`_: don't unregister interrupted post-exec functions
196 196 * `996 <https://github.com/ipython/ipython/issues/996>`_: add Integer traitlet
197 197 * `1016 <https://github.com/ipython/ipython/issues/1016>`_: Fix password hashing for Python 3
198 198 * `1014 <https://github.com/ipython/ipython/issues/1014>`_: escape minus signs in manpages
199 199 * `1013 <https://github.com/ipython/ipython/issues/1013>`_: [NumPyExampleDocstring] link was pointing to raw file
200 200 * `1011 <https://github.com/ipython/ipython/issues/1011>`_: Add hashed password support.
201 201 * `1005 <https://github.com/ipython/ipython/issues/1005>`_: Quick fix for os.system requiring str parameter
202 202 * `994 <https://github.com/ipython/ipython/issues/994>`_: Allow latex formulas in HTML output
203 203 * `955 <https://github.com/ipython/ipython/issues/955>`_: Websocket Adjustments
204 204 * `979 <https://github.com/ipython/ipython/issues/979>`_: use system_raw in terminal, even on Windows
205 205 * `989 <https://github.com/ipython/ipython/issues/989>`_: fix arguments for commands in _process_posix
206 206 * `991 <https://github.com/ipython/ipython/issues/991>`_: Show traceback, continuing to start kernel if pylab init fails
207 207 * `981 <https://github.com/ipython/ipython/issues/981>`_: Split likely multiline text when writing JSON notebooks
208 208 * `957 <https://github.com/ipython/ipython/issues/957>`_: allow change of png DPI in inline backend
209 209 * `968 <https://github.com/ipython/ipython/issues/968>`_: add wantDirectory to ipdoctest, so that directories will be checked for e
210 210 * `984 <https://github.com/ipython/ipython/issues/984>`_: Do not expose variables defined at startup to %who etc.
211 211 * `985 <https://github.com/ipython/ipython/issues/985>`_: Fixes for parallel code on Python 3
212 212 * `963 <https://github.com/ipython/ipython/issues/963>`_: disable calltips in PySide < 1.0.7 to prevent segfault
213 213 * `976 <https://github.com/ipython/ipython/issues/976>`_: Getting started on what's new
214 214 * `929 <https://github.com/ipython/ipython/issues/929>`_: Multiline history
215 215 * `964 <https://github.com/ipython/ipython/issues/964>`_: Default profile
216 216 * `961 <https://github.com/ipython/ipython/issues/961>`_: Disable the pager for the test suite
217 217 * `953 <https://github.com/ipython/ipython/issues/953>`_: Physics extension
218 218 * `950 <https://github.com/ipython/ipython/issues/950>`_: Add directory for startup files
219 219 * `940 <https://github.com/ipython/ipython/issues/940>`_: allow setting HistoryManager.hist_file with config
220 220 * `948 <https://github.com/ipython/ipython/issues/948>`_: Monkeypatch Tornado 2.1.1 so it works with Google Chrome 16.
221 221 * `916 <https://github.com/ipython/ipython/issues/916>`_: Run p ( https://github.com/ipython/ipython/pull/901 )
222 222 * `923 <https://github.com/ipython/ipython/issues/923>`_: %config magic
223 223 * `920 <https://github.com/ipython/ipython/issues/920>`_: unordered iteration of AsyncMapResults (+ a couple fixes)
224 224 * `941 <https://github.com/ipython/ipython/issues/941>`_: Follow-up to 387dcd6a, `_rl.__doc__` is `None` with pyreadline
225 225 * `931 <https://github.com/ipython/ipython/issues/931>`_: read-only notebook mode
226 226 * `921 <https://github.com/ipython/ipython/issues/921>`_: Show invalid config message on TraitErrors during init
227 227 * `815 <https://github.com/ipython/ipython/issues/815>`_: Fix #481 using custom qt4 input hook
228 228 * `936 <https://github.com/ipython/ipython/issues/936>`_: Start webbrowser in a thread. Prevents lockup with Chrome.
229 229 * `937 <https://github.com/ipython/ipython/issues/937>`_: add dirty trick for readline import on OSX
230 230 * `913 <https://github.com/ipython/ipython/issues/913>`_: Py3 tests2
231 231 * `933 <https://github.com/ipython/ipython/issues/933>`_: Cancel in qt console closeevent should trigger event.ignore()
232 232 * `930 <https://github.com/ipython/ipython/issues/930>`_: read-only notebook mode
233 233 * `910 <https://github.com/ipython/ipython/issues/910>`_: Make import checks more explicit in %whos
234 234 * `926 <https://github.com/ipython/ipython/issues/926>`_: reincarnate -V cmdline option
235 235 * `928 <https://github.com/ipython/ipython/issues/928>`_: BUG: Set context for font size change shortcuts in ConsoleWidget
236 236 * `901 <https://github.com/ipython/ipython/issues/901>`_: - There is a bug when running the profiler in the magic command (prun) with python3
237 237 * `912 <https://github.com/ipython/ipython/issues/912>`_: Add magic for cls on windows. Fix for #181.
238 238 * `905 <https://github.com/ipython/ipython/issues/905>`_: enable %gui/%pylab magics in the Kernel
239 239 * `909 <https://github.com/ipython/ipython/issues/909>`_: Allow IPython to run without sqlite3
240 240 * `887 <https://github.com/ipython/ipython/issues/887>`_: Qtconsole menu
241 241 * `895 <https://github.com/ipython/ipython/issues/895>`_: notebook download implies save
242 242 * `896 <https://github.com/ipython/ipython/issues/896>`_: Execfile
243 243 * `899 <https://github.com/ipython/ipython/issues/899>`_: Brian's Notebook work
244 244 * `892 <https://github.com/ipython/ipython/issues/892>`_: don't close figures every cycle with inline matplotlib backend
245 245 * `893 <https://github.com/ipython/ipython/issues/893>`_: Adding clear_output to kernel and HTML notebook
246 246 * `789 <https://github.com/ipython/ipython/issues/789>`_: Adding clear_output to kernel and HTML notebook.
247 247 * `898 <https://github.com/ipython/ipython/issues/898>`_: Don't pass unicode sys.argv with %run or `ipython script.py`
248 248 * `897 <https://github.com/ipython/ipython/issues/897>`_: Add tooltips to the notebook via 'title' attr.
249 249 * `877 <https://github.com/ipython/ipython/issues/877>`_: partial fix for issue #678
250 250 * `838 <https://github.com/ipython/ipython/issues/838>`_: reenable multiline history for terminals
251 251 * `872 <https://github.com/ipython/ipython/issues/872>`_: The constructor of Client() checks for AssertionError in validate_url to open a file instead of connection to a URL if it fails.
252 252 * `884 <https://github.com/ipython/ipython/issues/884>`_: Notebook usability fixes
253 253 * `883 <https://github.com/ipython/ipython/issues/883>`_: User notification if notebook saving fails
254 254 * `889 <https://github.com/ipython/ipython/issues/889>`_: Add drop_by_id method to shell, to remove variables added by extensions.
255 255 * `891 <https://github.com/ipython/ipython/issues/891>`_: Ability to open the notebook in a browser when it starts
256 256 * `813 <https://github.com/ipython/ipython/issues/813>`_: Create menu bar for qtconsole
257 257 * `876 <https://github.com/ipython/ipython/issues/876>`_: protect IPython from bad custom exception handlers
258 258 * `856 <https://github.com/ipython/ipython/issues/856>`_: Backgroundjobs
259 259 * `868 <https://github.com/ipython/ipython/issues/868>`_: Warn user if MathJax can't be fetched from notebook closes #744
260 260 * `878 <https://github.com/ipython/ipython/issues/878>`_: store_history=False default for run_cell
261 261 * `824 <https://github.com/ipython/ipython/issues/824>`_: History access
262 262 * `850 <https://github.com/ipython/ipython/issues/850>`_: Update codemirror to 2.15 and make the code internally more version-agnostic
263 263 * `861 <https://github.com/ipython/ipython/issues/861>`_: Fix for issue #56
264 264 * `819 <https://github.com/ipython/ipython/issues/819>`_: Adding -m option to %run, similar to -m for python interpreter.
265 265 * `855 <https://github.com/ipython/ipython/issues/855>`_: promote aliases and flags, to ensure they have priority over config files
266 266 * `862 <https://github.com/ipython/ipython/issues/862>`_: BUG: Completion widget position and pager focus.
267 267 * `847 <https://github.com/ipython/ipython/issues/847>`_: Allow connection to kernels by files
268 268 * `708 <https://github.com/ipython/ipython/issues/708>`_: Two-process terminal frontend
269 269 * `857 <https://github.com/ipython/ipython/issues/857>`_: make sdist flags work again (e.g. --manifest-only)
270 270 * `835 <https://github.com/ipython/ipython/issues/835>`_: Add Tab key to list of keys that scroll down the paging widget.
271 271 * `859 <https://github.com/ipython/ipython/issues/859>`_: Fix for issue #800
272 272 * `848 <https://github.com/ipython/ipython/issues/848>`_: Python3 setup.py install failiure
273 273 * `845 <https://github.com/ipython/ipython/issues/845>`_: Tests on Python 3
274 274 * `802 <https://github.com/ipython/ipython/issues/802>`_: DOC: extensions: add documentation for the bundled extensions
275 275 * `830 <https://github.com/ipython/ipython/issues/830>`_: contiguous stdout/stderr in notebook
276 276 * `761 <https://github.com/ipython/ipython/issues/761>`_: Windows: test runner fails if repo path (e.g. home dir) contains spaces
277 277 * `801 <https://github.com/ipython/ipython/issues/801>`_: Py3 notebook
278 278 * `809 <https://github.com/ipython/ipython/issues/809>`_: use CFRunLoop directly in `ipython kernel --pylab osx`
279 279 * `841 <https://github.com/ipython/ipython/issues/841>`_: updated old scipy.org links, other minor doc fixes
280 280 * `837 <https://github.com/ipython/ipython/issues/837>`_: remove all trailling spaces
281 281 * `834 <https://github.com/ipython/ipython/issues/834>`_: Issue https://github.com/ipython/ipython/issues/832 resolution
282 282 * `746 <https://github.com/ipython/ipython/issues/746>`_: ENH: extensions: port autoreload to current API
283 283 * `828 <https://github.com/ipython/ipython/issues/828>`_: fixed permissions (sub-modules should not be executable) + added shebang for run_ipy_in_profiler.py
284 284 * `798 <https://github.com/ipython/ipython/issues/798>`_: pexpect & Python 3
285 285 * `804 <https://github.com/ipython/ipython/issues/804>`_: Magic 'range' crash if greater than len(input_hist)
286 286 * `821 <https://github.com/ipython/ipython/issues/821>`_: update tornado dependency to 2.1
287 * `807 <https://github.com/ipython/ipython/issues/807>`_: Faciliate ssh tunnel sharing by announcing ports
287 * `807 <https://github.com/ipython/ipython/issues/807>`_: Facilitate ssh tunnel sharing by announcing ports
288 288 * `795 <https://github.com/ipython/ipython/issues/795>`_: Add cluster-id for multiple cluster instances per profile
289 289 * `742 <https://github.com/ipython/ipython/issues/742>`_: Glut
290 290 * `668 <https://github.com/ipython/ipython/issues/668>`_: Greedy completer
291 291 * `776 <https://github.com/ipython/ipython/issues/776>`_: Reworking qtconsole shortcut, add fullscreen
292 292 * `790 <https://github.com/ipython/ipython/issues/790>`_: TST: add future unicode_literals test (#786)
293 293 * `775 <https://github.com/ipython/ipython/issues/775>`_: redirect_in/redirect_out should be constrained to windows only
294 294 * `793 <https://github.com/ipython/ipython/issues/793>`_: Don't use readline in the ZMQShell
295 295 * `743 <https://github.com/ipython/ipython/issues/743>`_: Pyglet
296 296 * `774 <https://github.com/ipython/ipython/issues/774>`_: basic/initial .mailmap for nice shortlog summaries
297 297 * `770 <https://github.com/ipython/ipython/issues/770>`_: #769 (reopened)
298 298 * `784 <https://github.com/ipython/ipython/issues/784>`_: Parse user code to AST using compiler flags.
299 299 * `783 <https://github.com/ipython/ipython/issues/783>`_: always use StringIO, never cStringIO
300 300 * `782 <https://github.com/ipython/ipython/issues/782>`_: flush stdout/stderr on displayhook call
301 301 * `622 <https://github.com/ipython/ipython/issues/622>`_: Make pylab import all configurable
302 302 * `745 <https://github.com/ipython/ipython/issues/745>`_: Don't assume history requests succeed in qtconsole
303 303 * `725 <https://github.com/ipython/ipython/issues/725>`_: don't assume cursor.selectedText() is a string
304 304 * `778 <https://github.com/ipython/ipython/issues/778>`_: don't override execfile on Python 2
305 305 * `663 <https://github.com/ipython/ipython/issues/663>`_: Python 3 compatilibility work
306 306 * `762 <https://github.com/ipython/ipython/issues/762>`_: qtconsole ipython widget's execute_file fails if filename contains spaces or quotes
307 307 * `763 <https://github.com/ipython/ipython/issues/763>`_: Set context for shortcuts in ConsoleWidget
308 308 * `722 <https://github.com/ipython/ipython/issues/722>`_: PyPy compatibility
309 309 * `757 <https://github.com/ipython/ipython/issues/757>`_: ipython.el is broken in 0.11
310 310 * `764 <https://github.com/ipython/ipython/issues/764>`_: fix "--colors=<color>" option in py-python-command-args.
311 311 * `758 <https://github.com/ipython/ipython/issues/758>`_: use ROUTER/DEALER socket names instead of XREP/XREQ
312 312 * `736 <https://github.com/ipython/ipython/issues/736>`_: enh: added authentication ability for webapp
313 313 * `748 <https://github.com/ipython/ipython/issues/748>`_: Check for tornado before running frontend.html tests.
314 314 * `754 <https://github.com/ipython/ipython/issues/754>`_: restore msg_id/msg_type aliases in top level of msg dict
315 315 * `769 <https://github.com/ipython/ipython/issues/769>`_: Don't treat bytes objects as json-safe
316 316 * `753 <https://github.com/ipython/ipython/issues/753>`_: DOC: msg['msg_type'] removed
317 317 * `766 <https://github.com/ipython/ipython/issues/766>`_: fix "--colors=<color>" option in py-python-command-args.
318 318 * `765 <https://github.com/ipython/ipython/issues/765>`_: fix "--colors=<color>" option in py-python-command-args.
319 319 * `741 <https://github.com/ipython/ipython/issues/741>`_: Run PyOs_InputHook in pager to keep plot windows interactive.
320 320 * `664 <https://github.com/ipython/ipython/issues/664>`_: Remove ipythonrc references from documentation
321 321 * `750 <https://github.com/ipython/ipython/issues/750>`_: Tiny doc fixes
322 322 * `433 <https://github.com/ipython/ipython/issues/433>`_: ZMQ terminal frontend
323 323 * `734 <https://github.com/ipython/ipython/issues/734>`_: Allow %magic argument filenames with spaces to be specified with quotes under win32
324 324 * `731 <https://github.com/ipython/ipython/issues/731>`_: respect encoding of display data from urls
325 325 * `730 <https://github.com/ipython/ipython/issues/730>`_: doc improvements for running notebook via secure protocol
326 326 * `729 <https://github.com/ipython/ipython/issues/729>`_: use null char to start markdown cell placeholder
327 327 * `727 <https://github.com/ipython/ipython/issues/727>`_: Minor fixes to the htmlnotebook
328 328 * `726 <https://github.com/ipython/ipython/issues/726>`_: use bundled argparse if system argparse is < 1.1
329 329 * `705 <https://github.com/ipython/ipython/issues/705>`_: Htmlnotebook
330 330 * `723 <https://github.com/ipython/ipython/issues/723>`_: Add 'import time' to IPython/parallel/apps/launcher.py as time.sleep is called without time being imported
331 331 * `714 <https://github.com/ipython/ipython/issues/714>`_: Install mathjax for offline use
332 332 * `718 <https://github.com/ipython/ipython/issues/718>`_: Underline keyboard shortcut characters on appropriate buttons
333 333 * `717 <https://github.com/ipython/ipython/issues/717>`_: Add source highlighting to markdown snippets
334 334 * `716 <https://github.com/ipython/ipython/issues/716>`_: update EvalFormatter to allow arbitrary expressions
335 335 * `712 <https://github.com/ipython/ipython/issues/712>`_: Reset execution counter after cache is cleared
336 336 * `713 <https://github.com/ipython/ipython/issues/713>`_: Align colons in html notebook help dialog
337 337 * `709 <https://github.com/ipython/ipython/issues/709>`_: Allow usage of '.' in notebook names
338 338 * `706 <https://github.com/ipython/ipython/issues/706>`_: Implement static publishing of HTML notebook
339 339 * `674 <https://github.com/ipython/ipython/issues/674>`_: use argparse to parse aliases & flags
340 340 * `679 <https://github.com/ipython/ipython/issues/679>`_: HistoryManager.get_session_info()
341 341 * `696 <https://github.com/ipython/ipython/issues/696>`_: Fix columnize bug, where tab completion with very long filenames would crash Qt console
342 342 * `686 <https://github.com/ipython/ipython/issues/686>`_: add ssh tunnel support to qtconsole
343 343 * `685 <https://github.com/ipython/ipython/issues/685>`_: Add SSH tunneling to engines
344 344 * `384 <https://github.com/ipython/ipython/issues/384>`_: Allow pickling objects defined interactively.
345 345 * `647 <https://github.com/ipython/ipython/issues/647>`_: My fix rpmlint
346 346 * `587 <https://github.com/ipython/ipython/issues/587>`_: don't special case for py3k+numpy
347 347 * `703 <https://github.com/ipython/ipython/issues/703>`_: make config-loading debug messages more explicit
348 348 * `699 <https://github.com/ipython/ipython/issues/699>`_: make calltips configurable in qtconsole
349 349 * `666 <https://github.com/ipython/ipython/issues/666>`_: parallel tests & extra readline escapes
350 350 * `683 <https://github.com/ipython/ipython/issues/683>`_: BF - allow nose with-doctest setting in environment
351 351 * `689 <https://github.com/ipython/ipython/issues/689>`_: Protect ipkernel from bad messages
352 352 * `702 <https://github.com/ipython/ipython/issues/702>`_: Prevent ipython.py launcher from being imported.
353 353 * `701 <https://github.com/ipython/ipython/issues/701>`_: Prevent ipython.py from being imported by accident
354 354 * `670 <https://github.com/ipython/ipython/issues/670>`_: check for writable dirs, not just existence, in utils.path
355 355 * `579 <https://github.com/ipython/ipython/issues/579>`_: Sessionwork
356 356 * `687 <https://github.com/ipython/ipython/issues/687>`_: add `ipython kernel` for starting just a kernel
357 357 * `627 <https://github.com/ipython/ipython/issues/627>`_: Qt Console history search
358 358 * `646 <https://github.com/ipython/ipython/issues/646>`_: Generate package list automatically in find_packages
359 359 * `660 <https://github.com/ipython/ipython/issues/660>`_: i658
360 360 * `659 <https://github.com/ipython/ipython/issues/659>`_: don't crash on bad config files
361 361
362 362 Regular issues (258):
363 363
364 364 * `1177 <https://github.com/ipython/ipython/issues/1177>`_: UnicodeDecodeError in py3compat from "xlrd??"
365 365 * `1094 <https://github.com/ipython/ipython/issues/1094>`_: Tooltip doesn't show constructor docstrings
366 366 * `1170 <https://github.com/ipython/ipython/issues/1170>`_: double pylab greeting with c.InteractiveShellApp.pylab = "tk" in zmqconsole
367 367 * `1166 <https://github.com/ipython/ipython/issues/1166>`_: E-mail cpaste broken
368 368 * `1164 <https://github.com/ipython/ipython/issues/1164>`_: IPython qtconsole (0.12) can't export to html with external png
369 369 * `1103 <https://github.com/ipython/ipython/issues/1103>`_: %loadpy should cut out encoding declaration
370 370 * `1156 <https://github.com/ipython/ipython/issues/1156>`_: Notebooks downloaded as Python files require a header stating the encoding
371 371 * `1157 <https://github.com/ipython/ipython/issues/1157>`_: Ctrl-C not working when GUI/pylab integration is active
372 372 * `1154 <https://github.com/ipython/ipython/issues/1154>`_: We should be less aggressive in de-registering post-execution functions
373 373 * `1134 <https://github.com/ipython/ipython/issues/1134>`_: "select-all, kill" leaves qtconsole in unusable state
374 374 * `1148 <https://github.com/ipython/ipython/issues/1148>`_: A lot of testerrors
375 375 * `803 <https://github.com/ipython/ipython/issues/803>`_: Make doctests work with Python 3
376 376 * `1119 <https://github.com/ipython/ipython/issues/1119>`_: Start menu shortcuts not created in Python 3
377 377 * `1136 <https://github.com/ipython/ipython/issues/1136>`_: The embedding machinery ignores user_ns
378 378 * `607 <https://github.com/ipython/ipython/issues/607>`_: Use the new IPython logo/font in the notebook header
379 379 * `755 <https://github.com/ipython/ipython/issues/755>`_: qtconsole ipython widget's execute_file fails if filename contains spaces or quotes
380 380 * `1115 <https://github.com/ipython/ipython/issues/1115>`_: shlex_split should return unicode
381 381 * `1109 <https://github.com/ipython/ipython/issues/1109>`_: timeit with string ending in space gives "ValueError: No closing quotation"
382 382 * `1142 <https://github.com/ipython/ipython/issues/1142>`_: Install problems
383 383 * `700 <https://github.com/ipython/ipython/issues/700>`_: Some SVG images render incorrectly in htmlnotebook
384 384 * `1117 <https://github.com/ipython/ipython/issues/1117>`_: quit() doesn't work in terminal
385 385 * `1111 <https://github.com/ipython/ipython/issues/1111>`_: ls broken after merge of #1089
386 386 * `1104 <https://github.com/ipython/ipython/issues/1104>`_: Prompt spacing weird
387 387 * `1124 <https://github.com/ipython/ipython/issues/1124>`_: Seg Fault 11 when calling PySide using "run" command
388 388 * `1088 <https://github.com/ipython/ipython/issues/1088>`_: QtConsole : can't copy from pager
389 389 * `568 <https://github.com/ipython/ipython/issues/568>`_: Test error and failure in IPython.core on windows
390 390 * `1112 <https://github.com/ipython/ipython/issues/1112>`_: testfailure in IPython.frontend on windows
391 391 * `1102 <https://github.com/ipython/ipython/issues/1102>`_: magic in IPythonDemo fails when not located at top of demo file
392 392 * `629 <https://github.com/ipython/ipython/issues/629>`_: \r and \b in qtconsole don't behave as expected
393 393 * `1080 <https://github.com/ipython/ipython/issues/1080>`_: Notebook: tab completion should close on "("
394 394 * `973 <https://github.com/ipython/ipython/issues/973>`_: Qt Console close dialog and on-top Qt Console
395 395 * `1087 <https://github.com/ipython/ipython/issues/1087>`_: QtConsole xhtml/Svg export broken ?
396 396 * `1067 <https://github.com/ipython/ipython/issues/1067>`_: Parallel test suite hangs on Python 3
397 397 * `1018 <https://github.com/ipython/ipython/issues/1018>`_: Local mathjax breaks install
398 398 * `993 <https://github.com/ipython/ipython/issues/993>`_: `raw_input` redirection to foreign kernels is extremely brittle
399 399 * `1100 <https://github.com/ipython/ipython/issues/1100>`_: ipython3 traceback unicode issue from extensions
400 400 * `1071 <https://github.com/ipython/ipython/issues/1071>`_: Large html-notebooks hang on load on a slow machine
401 401 * `89 <https://github.com/ipython/ipython/issues/89>`_: %pdoc np.ma.compress shows docstring twice
402 402 * `22 <https://github.com/ipython/ipython/issues/22>`_: Include improvements from anythingipython.el
403 403 * `633 <https://github.com/ipython/ipython/issues/633>`_: Execution count & SyntaxError
404 404 * `1095 <https://github.com/ipython/ipython/issues/1095>`_: Uncaught TypeError: Object has no method 'remove_and_cancell_tooltip'
405 405 * `1075 <https://github.com/ipython/ipython/issues/1075>`_: We're ignoring prompt customizations
406 406 * `1086 <https://github.com/ipython/ipython/issues/1086>`_: Can't open qtconsole from outside source tree
407 407 * `1076 <https://github.com/ipython/ipython/issues/1076>`_: namespace changes broke `foo.*bar*?` syntax
408 408 * `1074 <https://github.com/ipython/ipython/issues/1074>`_: pprinting old-style class objects fails (TypeError: 'tuple' object is not callable)
409 409 * `1063 <https://github.com/ipython/ipython/issues/1063>`_: IPython.utils test error due to missing unicodedata module
410 410 * `592 <https://github.com/ipython/ipython/issues/592>`_: Bug in argument parsing for %run
411 411 * `378 <https://github.com/ipython/ipython/issues/378>`_: Windows path escape issues
412 412 * `1068 <https://github.com/ipython/ipython/issues/1068>`_: Notebook tab completion broken in Firefox
413 413 * `75 <https://github.com/ipython/ipython/issues/75>`_: No tab completion after "/
414 414 * `103 <https://github.com/ipython/ipython/issues/103>`_: customizable cpaste
415 415 * `324 <https://github.com/ipython/ipython/issues/324>`_: Remove code in IPython.testing that is not being used
416 416 * `131 <https://github.com/ipython/ipython/issues/131>`_: Global variables not seen by cprofile.run()
417 417 * `851 <https://github.com/ipython/ipython/issues/851>`_: IPython shell swallows exceptions in certain circumstances
418 418 * `882 <https://github.com/ipython/ipython/issues/882>`_: ipython freezes at start if IPYTHONDIR is on an NFS mount
419 419 * `1057 <https://github.com/ipython/ipython/issues/1057>`_: Blocker: Qt console broken after "all magics" menu became dynamic
420 420 * `1027 <https://github.com/ipython/ipython/issues/1027>`_: ipython does not like white space at end of file
421 421 * `1058 <https://github.com/ipython/ipython/issues/1058>`_: New bug: Notebook asks for confirmation to leave even saved pages.
422 422 * `1061 <https://github.com/ipython/ipython/issues/1061>`_: rep (magic recall) under pypy
423 423 * `1047 <https://github.com/ipython/ipython/issues/1047>`_: Document the notebook format
424 424 * `102 <https://github.com/ipython/ipython/issues/102>`_: Properties accessed twice for classes defined interactively
425 425 * `16 <https://github.com/ipython/ipython/issues/16>`_: %store raises exception when storing compiled regex
426 426 * `67 <https://github.com/ipython/ipython/issues/67>`_: tab expansion should only take one directory level at the time
427 427 * `62 <https://github.com/ipython/ipython/issues/62>`_: Global variables undefined in interactive use of embedded ipython shell
428 428 * `57 <https://github.com/ipython/ipython/issues/57>`_: debugging with ipython does not work well outside ipython
429 429 * `38 <https://github.com/ipython/ipython/issues/38>`_: Line entry edge case error
430 430 * `980 <https://github.com/ipython/ipython/issues/980>`_: Update parallel docs for new parallel architecture
431 431 * `1017 <https://github.com/ipython/ipython/issues/1017>`_: Add small example about ipcluster/ssh startup
432 432 * `1041 <https://github.com/ipython/ipython/issues/1041>`_: Proxy Issues
433 433 * `967 <https://github.com/ipython/ipython/issues/967>`_: KernelManagers don't use zmq eventloop properly
434 434 * `1055 <https://github.com/ipython/ipython/issues/1055>`_: "All Magics" display on Ubuntu
435 435 * `1054 <https://github.com/ipython/ipython/issues/1054>`_: ipython explodes on syntax error
436 436 * `1051 <https://github.com/ipython/ipython/issues/1051>`_: ipython3 set_next_input() failure
437 437 * `693 <https://github.com/ipython/ipython/issues/693>`_: "run -i" no longer works after %reset in terminal
438 438 * `29 <https://github.com/ipython/ipython/issues/29>`_: cPickle works in standard interpreter, but not in IPython
439 439 * `1050 <https://github.com/ipython/ipython/issues/1050>`_: ipython3 broken by commit 8bb887c8c2c447bf7
440 440 * `1048 <https://github.com/ipython/ipython/issues/1048>`_: Update docs on notebook password
441 441 * `1046 <https://github.com/ipython/ipython/issues/1046>`_: Searies of questions/issues?
442 442 * `1045 <https://github.com/ipython/ipython/issues/1045>`_: crash when exiting - previously launched embedded sub-shell
443 443 * `1043 <https://github.com/ipython/ipython/issues/1043>`_: pylab doesn't work in qtconsole
444 444 * `1044 <https://github.com/ipython/ipython/issues/1044>`_: run -p doesn't work in python 3
445 445 * `1010 <https://github.com/ipython/ipython/issues/1010>`_: emacs freezes when ipython-complete is called
446 446 * `82 <https://github.com/ipython/ipython/issues/82>`_: Update devel docs with discussion about good changelogs
447 447 * `116 <https://github.com/ipython/ipython/issues/116>`_: Update release management scipts and release.revision for git
448 448 * `1022 <https://github.com/ipython/ipython/issues/1022>`_: Pylab banner shows up with first cell to execute
449 449 * `787 <https://github.com/ipython/ipython/issues/787>`_: Keyboard selection of multiple lines in the notebook behaves inconsistently
450 450 * `1037 <https://github.com/ipython/ipython/issues/1037>`_: notepad + jsonlib: TypeError: Only whitespace may be used for indentation.
451 451 * `970 <https://github.com/ipython/ipython/issues/970>`_: Default home not writable, %HOME% does not help (windows)
452 452 * `747 <https://github.com/ipython/ipython/issues/747>`_: HOMESHARE not a good choice for "writable homedir" on Windows
453 453 * `810 <https://github.com/ipython/ipython/issues/810>`_: cleanup utils.path.get_home_dir
454 454 * `2 <https://github.com/ipython/ipython/issues/2>`_: Fix the copyright statement in source code files to be accurate
455 455 * `1031 <https://github.com/ipython/ipython/issues/1031>`_: <esc> on Firefox crash websocket
456 456 * `684 <https://github.com/ipython/ipython/issues/684>`_: %Store eliminated in configuration and magic commands in 0.11
457 457 * `1026 <https://github.com/ipython/ipython/issues/1026>`_: BUG: wrong default parameter in ask_yes_no
458 458 * `880 <https://github.com/ipython/ipython/issues/880>`_: Better error message if %paste fails
459 459 * `1024 <https://github.com/ipython/ipython/issues/1024>`_: autopx magic broken
460 460 * `822 <https://github.com/ipython/ipython/issues/822>`_: Unicode bug in Itpl when expanding shell variables in syscalls with !
461 461 * `1009 <https://github.com/ipython/ipython/issues/1009>`_: Windows: regression in cd magic handling of paths
462 462 * `833 <https://github.com/ipython/ipython/issues/833>`_: Crash python with matplotlib and unequal length arrays
463 463 * `695 <https://github.com/ipython/ipython/issues/695>`_: Crash handler initialization is too aggressive
464 464 * `1000 <https://github.com/ipython/ipython/issues/1000>`_: Remove duplicates when refilling readline history
465 465 * `992 <https://github.com/ipython/ipython/issues/992>`_: Interrupting certain matplotlib operations leaves the inline backend 'wedged'
466 466 * `942 <https://github.com/ipython/ipython/issues/942>`_: number traits should cast if value doesn't change
467 467 * `1006 <https://github.com/ipython/ipython/issues/1006>`_: ls crashes when run on a UNC path or with non-ascii args
468 468 * `944 <https://github.com/ipython/ipython/issues/944>`_: Decide the default image format for inline figures: SVG or PNG?
469 469 * `842 <https://github.com/ipython/ipython/issues/842>`_: Python 3 on Windows (pyreadline) - expected an object with the buffer interface
470 470 * `1002 <https://github.com/ipython/ipython/issues/1002>`_: ImportError due to incorrect version checking
471 471 * `1001 <https://github.com/ipython/ipython/issues/1001>`_: Ipython "source" command?
472 472 * `954 <https://github.com/ipython/ipython/issues/954>`_: IPython embed doesn't respect namespaces
473 473 * `681 <https://github.com/ipython/ipython/issues/681>`_: pdb freezes inside qtconsole
474 474 * `698 <https://github.com/ipython/ipython/issues/698>`_: crash report "TypeError: can only concatenate list (not "unicode") to list"
475 475 * `978 <https://github.com/ipython/ipython/issues/978>`_: ipython 0.11 buffers external command output till the cmd is done
476 476 * `952 <https://github.com/ipython/ipython/issues/952>`_: Need user-facing warning in the browser if websocket connection fails
477 477 * `988 <https://github.com/ipython/ipython/issues/988>`_: Error using idlsave
478 478 * `990 <https://github.com/ipython/ipython/issues/990>`_: ipython notebook - kernel dies if matplotlib is not installed
479 479 * `752 <https://github.com/ipython/ipython/issues/752>`_: Matplotlib figures showed only once in notebook
480 480 * `54 <https://github.com/ipython/ipython/issues/54>`_: Exception hook should be optional for embedding IPython in GUIs
481 481 * `918 <https://github.com/ipython/ipython/issues/918>`_: IPython.frontend tests fail without tornado
482 482 * `986 <https://github.com/ipython/ipython/issues/986>`_: Views created with c.direct_view() fail
483 483 * `697 <https://github.com/ipython/ipython/issues/697>`_: Filter out from %who names loaded at initialization time
484 484 * `932 <https://github.com/ipython/ipython/issues/932>`_: IPython 0.11 quickref card has superfluous "%recall and"
485 485 * `982 <https://github.com/ipython/ipython/issues/982>`_: png files with executable permissions
486 486 * `914 <https://github.com/ipython/ipython/issues/914>`_: Simpler system for running code after InteractiveShell is initialised
487 487 * `911 <https://github.com/ipython/ipython/issues/911>`_: ipython crashes on startup if readline is missing
488 488 * `971 <https://github.com/ipython/ipython/issues/971>`_: bookmarks created in 0.11 are corrupt in 0.12
489 489 * `974 <https://github.com/ipython/ipython/issues/974>`_: object feature tab-completion crash
490 490 * `939 <https://github.com/ipython/ipython/issues/939>`_: ZMQShell always uses default profile
491 491 * `946 <https://github.com/ipython/ipython/issues/946>`_: Multi-tab Close action should offer option to leave all kernels alone
492 492 * `949 <https://github.com/ipython/ipython/issues/949>`_: Test suite must not require any manual interaction
493 493 * `643 <https://github.com/ipython/ipython/issues/643>`_: enable gui eventloop integration in ipkernel
494 494 * `965 <https://github.com/ipython/ipython/issues/965>`_: ipython is crashed without launch.(python3.2)
495 495 * `958 <https://github.com/ipython/ipython/issues/958>`_: Can't use os X clipboard on with qtconsole
496 496 * `962 <https://github.com/ipython/ipython/issues/962>`_: Don't require tornado in the tests
497 497 * `960 <https://github.com/ipython/ipython/issues/960>`_: crash on syntax error on Windows XP
498 498 * `934 <https://github.com/ipython/ipython/issues/934>`_: The latest ipython branch doesn't work in Chrome
499 499 * `870 <https://github.com/ipython/ipython/issues/870>`_: zmq version detection
500 500 * `943 <https://github.com/ipython/ipython/issues/943>`_: HISTIGNORE for IPython
501 501 * `947 <https://github.com/ipython/ipython/issues/947>`_: qtconsole segfaults at startup
502 502 * `903 <https://github.com/ipython/ipython/issues/903>`_: Expose a magic to control config of the inline pylab backend
503 503 * `908 <https://github.com/ipython/ipython/issues/908>`_: bad user config shouldn't crash IPython
504 504 * `935 <https://github.com/ipython/ipython/issues/935>`_: Typing `break` causes IPython to crash.
505 505 * `869 <https://github.com/ipython/ipython/issues/869>`_: Tab completion of `~/` shows no output post 0.10.x
506 506 * `904 <https://github.com/ipython/ipython/issues/904>`_: whos under pypy1.6
507 507 * `773 <https://github.com/ipython/ipython/issues/773>`_: check_security_dir() and check_pid_dir() fail on network filesystem
508 508 * `915 <https://github.com/ipython/ipython/issues/915>`_: OS X Lion Terminal.app line wrap problem
509 509 * `886 <https://github.com/ipython/ipython/issues/886>`_: Notebook kernel crash when specifying --notebook-dir on commandline
510 510 * `636 <https://github.com/ipython/ipython/issues/636>`_: debugger.py: pydb broken
511 511 * `808 <https://github.com/ipython/ipython/issues/808>`_: Ctrl+C during %reset confirm message crash Qtconsole
512 512 * `927 <https://github.com/ipython/ipython/issues/927>`_: Using return outside a function crashes ipython
513 513 * `919 <https://github.com/ipython/ipython/issues/919>`_: Pop-up segfault when moving cursor out of qtconsole window
514 514 * `181 <https://github.com/ipython/ipython/issues/181>`_: cls command does not work on windows
515 515 * `917 <https://github.com/ipython/ipython/issues/917>`_: documentation typos
516 516 * `818 <https://github.com/ipython/ipython/issues/818>`_: %run does not work with non-ascii characeters in path
517 517 * `907 <https://github.com/ipython/ipython/issues/907>`_: Errors in custom completer functions can crash IPython
518 518 * `867 <https://github.com/ipython/ipython/issues/867>`_: doc: notebook password authentication howto
519 519 * `211 <https://github.com/ipython/ipython/issues/211>`_: paste command not working
520 520 * `900 <https://github.com/ipython/ipython/issues/900>`_: Tab key should insert 4 spaces in qt console
521 521 * `513 <https://github.com/ipython/ipython/issues/513>`_: [Qt console] cannot insert new lines into console functions using tab
522 522 * `906 <https://github.com/ipython/ipython/issues/906>`_: qtconsoleapp 'parse_command_line' doen't like --existing anymore
523 523 * `638 <https://github.com/ipython/ipython/issues/638>`_: Qt console --pylab=inline and getfigs(), etc.
524 524 * `710 <https://github.com/ipython/ipython/issues/710>`_: unwanted unicode passed to args
525 525 * `436 <https://github.com/ipython/ipython/issues/436>`_: Users should see tooltips for all buttons in the notebook UI
526 526 * `207 <https://github.com/ipython/ipython/issues/207>`_: ipython crashes if atexit handler raises exception
527 527 * `692 <https://github.com/ipython/ipython/issues/692>`_: use of Tracer() when debugging works but gives error messages
528 528 * `690 <https://github.com/ipython/ipython/issues/690>`_: debugger does not print error message by default in 0.11
529 529 * `571 <https://github.com/ipython/ipython/issues/571>`_: history of multiline entries
530 530 * `749 <https://github.com/ipython/ipython/issues/749>`_: IPython.parallel test failure under Windows 7 and XP
531 531 * `890 <https://github.com/ipython/ipython/issues/890>`_: ipclusterapp.py - helep
532 532 * `885 <https://github.com/ipython/ipython/issues/885>`_: `ws-hostname` alias not recognized by notebook
533 533 * `881 <https://github.com/ipython/ipython/issues/881>`_: Missing manual.pdf?
534 534 * `744 <https://github.com/ipython/ipython/issues/744>`_: cannot create notebook in offline mode if mathjax not installed
535 535 * `865 <https://github.com/ipython/ipython/issues/865>`_: Make tracebacks from %paste show the code
536 536 * `535 <https://github.com/ipython/ipython/issues/535>`_: exception unicode handling in %run is faulty in qtconsole
537 537 * `817 <https://github.com/ipython/ipython/issues/817>`_: iPython crashed
538 538 * `799 <https://github.com/ipython/ipython/issues/799>`_: %edit magic not working on windows xp in qtconsole
539 539 * `732 <https://github.com/ipython/ipython/issues/732>`_: QTConsole wrongly promotes the index of the input line on which user presses Enter
540 540 * `662 <https://github.com/ipython/ipython/issues/662>`_: ipython test failures on Mac OS X Lion
541 541 * `650 <https://github.com/ipython/ipython/issues/650>`_: Handle bad config files better
542 542 * `829 <https://github.com/ipython/ipython/issues/829>`_: We should not insert new lines after all print statements in the notebook
543 543 * `874 <https://github.com/ipython/ipython/issues/874>`_: ipython-qtconsole: pyzmq Version Comparison
544 544 * `640 <https://github.com/ipython/ipython/issues/640>`_: matplotlib macosx windows don't respond in qtconsole
545 545 * `624 <https://github.com/ipython/ipython/issues/624>`_: ipython intermittently segfaults when figure is closed (Mac OS X)
546 546 * `871 <https://github.com/ipython/ipython/issues/871>`_: Notebook crashes if a profile is used
547 547 * `56 <https://github.com/ipython/ipython/issues/56>`_: Have %cpaste accept also Ctrl-D as a termination marker
548 548 * `849 <https://github.com/ipython/ipython/issues/849>`_: Command line options to not override profile options
549 549 * `806 <https://github.com/ipython/ipython/issues/806>`_: Provide single-port connection to kernels
550 550 * `691 <https://github.com/ipython/ipython/issues/691>`_: [wishlist] Automatically find existing kernel
551 551 * `688 <https://github.com/ipython/ipython/issues/688>`_: local security vulnerability: all ports visible to any local user.
552 552 * `866 <https://github.com/ipython/ipython/issues/866>`_: DistributionNotFound on running ipython 0.11 on Windows XP x86
553 553 * `673 <https://github.com/ipython/ipython/issues/673>`_: raw_input appears to be round-robin for qtconsole
554 554 * `863 <https://github.com/ipython/ipython/issues/863>`_: Graceful degradation when home directory not writable
555 555 * `800 <https://github.com/ipython/ipython/issues/800>`_: Timing scripts with run -t -N <N> fails on report output
556 556 * `858 <https://github.com/ipython/ipython/issues/858>`_: Typing 'continue' makes ipython0.11 crash
557 557 * `840 <https://github.com/ipython/ipython/issues/840>`_: all processes run on one CPU core
558 558 * `843 <https://github.com/ipython/ipython/issues/843>`_: "import braces" crashes ipython
559 559 * `836 <https://github.com/ipython/ipython/issues/836>`_: Strange Output after IPython Install
560 560 * `839 <https://github.com/ipython/ipython/issues/839>`_: Qtconsole segfaults when mouse exits window with active tooltip
561 561 * `827 <https://github.com/ipython/ipython/issues/827>`_: Add support for checking several limits before running task on engine
562 562 * `826 <https://github.com/ipython/ipython/issues/826>`_: Add support for creation of parallel task when no engine is running
563 563 * `832 <https://github.com/ipython/ipython/issues/832>`_: Improve error message for %logstop
564 564 * `831 <https://github.com/ipython/ipython/issues/831>`_: %logstart in read-only directory forbid any further command
565 565 * `814 <https://github.com/ipython/ipython/issues/814>`_: ipython does not start -- DistributionNotFound
566 566 * `794 <https://github.com/ipython/ipython/issues/794>`_: Allow >1 controller per profile
567 567 * `820 <https://github.com/ipython/ipython/issues/820>`_: Tab Completion feature
568 568 * `812 <https://github.com/ipython/ipython/issues/812>`_: Qt console crashes on Ubuntu 11.10
569 569 * `816 <https://github.com/ipython/ipython/issues/816>`_: Import error using Python 2.7 and dateutil2.0 No module named _thread
570 570 * `756 <https://github.com/ipython/ipython/issues/756>`_: qtconsole Windows fails to print error message for '%run nonexistent_file'
571 571 * `651 <https://github.com/ipython/ipython/issues/651>`_: Completion doesn't work on element of a list
572 572 * `617 <https://github.com/ipython/ipython/issues/617>`_: [qtconsole] %hist doesn't show anything in qtconsole
573 573 * `786 <https://github.com/ipython/ipython/issues/786>`_: from __future__ import unicode_literals does not work
574 574 * `779 <https://github.com/ipython/ipython/issues/779>`_: Using irunner from virtual evn uses systemwide ipython
575 575 * `768 <https://github.com/ipython/ipython/issues/768>`_: codepage handling of output from scripts and shellcommands are not handled properly by qtconsole
576 576 * `785 <https://github.com/ipython/ipython/issues/785>`_: Don't strip leading whitespace in repr() in notebook
577 577 * `737 <https://github.com/ipython/ipython/issues/737>`_: in pickleshare.py line52 should be "if not os.path.isdir(self.root):"?
578 578 * `738 <https://github.com/ipython/ipython/issues/738>`_: in ipthon_win_post_install.py line 38
579 579 * `777 <https://github.com/ipython/ipython/issues/777>`_: print(…, sep=…) raises SyntaxError
580 580 * `728 <https://github.com/ipython/ipython/issues/728>`_: ipcontroller crash with MPI
581 581 * `780 <https://github.com/ipython/ipython/issues/780>`_: qtconsole Out value prints before the print statements that precede it
582 582 * `632 <https://github.com/ipython/ipython/issues/632>`_: IPython Crash Report (0.10.2)
583 583 * `253 <https://github.com/ipython/ipython/issues/253>`_: Unable to install ipython on windows
584 584 * `80 <https://github.com/ipython/ipython/issues/80>`_: Split IPClusterApp into multiple Application subclasses for each subcommand
585 585 * `34 <https://github.com/ipython/ipython/issues/34>`_: non-blocking pendingResult partial results
586 586 * `739 <https://github.com/ipython/ipython/issues/739>`_: Tests fail if tornado not installed
587 587 * `719 <https://github.com/ipython/ipython/issues/719>`_: Better support Pypy
588 588 * `667 <https://github.com/ipython/ipython/issues/667>`_: qtconsole problem with default pylab profile
589 589 * `661 <https://github.com/ipython/ipython/issues/661>`_: ipythonrc referenced in magic command in 0.11
590 590 * `665 <https://github.com/ipython/ipython/issues/665>`_: Source introspection with ?? is broken
591 591 * `724 <https://github.com/ipython/ipython/issues/724>`_: crash - ipython qtconsole, %quickref
592 592 * `655 <https://github.com/ipython/ipython/issues/655>`_: ipython with qtconsole crashes
593 593 * `593 <https://github.com/ipython/ipython/issues/593>`_: HTML Notebook Prompt can be deleted . . .
594 594 * `563 <https://github.com/ipython/ipython/issues/563>`_: use argparse instead of kvloader for flags&aliases
595 595 * `751 <https://github.com/ipython/ipython/issues/751>`_: Tornado version greater than 2.0 needed for firefox 6
596 596 * `720 <https://github.com/ipython/ipython/issues/720>`_: Crash report when importing easter egg
597 597 * `740 <https://github.com/ipython/ipython/issues/740>`_: Ctrl-Enter clears line in notebook
598 598 * `772 <https://github.com/ipython/ipython/issues/772>`_: ipengine fails on Windows with "XXX lineno: 355, opcode: 0"
599 599 * `771 <https://github.com/ipython/ipython/issues/771>`_: Add python 3 tag to setup.py
600 600 * `767 <https://github.com/ipython/ipython/issues/767>`_: non-ascii in __doc__ string crashes qtconsole kernel when showing tooltip
601 601 * `733 <https://github.com/ipython/ipython/issues/733>`_: In Windows, %run fails to strip quotes from filename
602 602 * `721 <https://github.com/ipython/ipython/issues/721>`_: no completion in emacs by ipython(ipython.el)
603 603 * `669 <https://github.com/ipython/ipython/issues/669>`_: Do not accept an ipython_dir that's not writeable
604 604 * `711 <https://github.com/ipython/ipython/issues/711>`_: segfault on mac os x
605 605 * `500 <https://github.com/ipython/ipython/issues/500>`_: "RuntimeError: Cannot change input buffer during execution" in console_widget.py
606 606 * `707 <https://github.com/ipython/ipython/issues/707>`_: Copy and paste keyboard shortcuts do not work in Qt Console on OS X
607 607 * `478 <https://github.com/ipython/ipython/issues/478>`_: PyZMQ's use of memoryviews breaks reconstruction of numpy arrays
608 608 * `694 <https://github.com/ipython/ipython/issues/694>`_: Turning off callout tips in qtconsole
609 609 * `704 <https://github.com/ipython/ipython/issues/704>`_: return kills IPython
610 610 * `442 <https://github.com/ipython/ipython/issues/442>`_: Users should have intelligent autoindenting in the notebook
611 611 * `615 <https://github.com/ipython/ipython/issues/615>`_: Wireframe and implement a project dashboard page
612 612 * `614 <https://github.com/ipython/ipython/issues/614>`_: Wireframe and implement a notebook dashboard page
613 613 * `606 <https://github.com/ipython/ipython/issues/606>`_: Users should be able to use the notebook to import/export a notebook to .py or .rst
614 614 * `604 <https://github.com/ipython/ipython/issues/604>`_: A user should be able to leave a kernel running in the notebook and reconnect
615 615 * `298 <https://github.com/ipython/ipython/issues/298>`_: Users should be able to save a notebook and then later reload it
616 616 * `649 <https://github.com/ipython/ipython/issues/649>`_: ipython qtconsole (v0.11): setting "c.IPythonWidget.in_prompt = '>>> ' crashes
617 617 * `672 <https://github.com/ipython/ipython/issues/672>`_: What happened to Exit?
618 618 * `658 <https://github.com/ipython/ipython/issues/658>`_: Put the InteractiveShellApp section first in the auto-generated config files
619 619 * `656 <https://github.com/ipython/ipython/issues/656>`_: [suggestion] dependency checking for pyqt for Windows installer
620 620 * `654 <https://github.com/ipython/ipython/issues/654>`_: broken documentation link on download page
621 621 * `653 <https://github.com/ipython/ipython/issues/653>`_: Test failures in IPython.parallel
@@ -1,1883 +1,1883 b''
1 1 .. _issues_list_100:
2 2
3 3 Issues closed in the 1.0 development cycle
4 4 ==========================================
5 5
6 6
7 7 Issues closed in 1.2
8 8 --------------------
9 9
10 10 GitHub stats for 2013/09/09 - 2014/02/21
11 11
12 12 These lists are automatically generated, and may be incomplete or contain duplicates.
13 13
14 14 The following 13 authors contributed 84 commits.
15 15
16 16 * Benjamin Ragan-Kelley
17 17 * Daryl Herzmann
18 18 * Doug Blank
19 19 * Fernando Perez
20 20 * James Porter
21 21 * Juergen Hasch
22 22 * Julian Taylor
23 23 * Kyle Kelley
24 24 * Lawrence Fu
25 25 * Matthias Bussonnier
26 26 * Paul Ivanov
27 27 * Pascal Schetelat
28 28 * Puneeth Chaganti
29 29 * Takeshi Kanmae
30 30 * Thomas Kluyver
31 31
32 32 We closed a total of 55 issues, 38 pull requests and 17 regular issues;
33 33 this is the full list (generated with the script :file:`tools/github_stats.py`):
34 34
35 35 Pull Requests (38):
36 36
37 37 1.2.1:
38 38
39 39 * :ghpull:`4372`: Don't assume that SyntaxTB is always called with a SyntaxError
40 40 * :ghpull:`5166`: remove mktemp usage
41 41 * :ghpull:`5163`: Simplify implementation of TemporaryWorkingDirectory.
42 42 * :ghpull:`5105`: add index to format to support py2.6
43 43
44 44 1.2.0:
45 45
46 46 * :ghpull:`4972`: Work around problem in doctest discovery in Python 3.4 with PyQt
47 47 * :ghpull:`4934`: `ipython profile create` respects `--ipython-dir`
48 48 * :ghpull:`4845`: Add Origin Checking.
49 49 * :ghpull:`4928`: use importlib.machinery when available
50 50 * :ghpull:`4849`: Various unicode fixes (mostly on Windows)
51 51 * :ghpull:`4880`: set profile name from profile_dir
52 52 * :ghpull:`4908`: detect builtin docstrings in oinspect
53 53 * :ghpull:`4909`: sort dictionary keys before comparison, ordering is not guaranteed
54 54 * :ghpull:`4903`: use https for all embeds
55 55 * :ghpull:`4868`: Static path fixes
56 56 * :ghpull:`4820`: fix regex for cleaning old logs with ipcluster
57 57 * :ghpull:`4840`: Error in Session.send_raw()
58 58 * :ghpull:`4762`: whitelist alphanumeric characters for cookie_name
59 59 * :ghpull:`4748`: fix race condition in profiledir creation.
60 60 * :ghpull:`4720`: never use ssh multiplexer in tunnels
61 61 * :ghpull:`4738`: don't inject help into user_ns
62 62 * :ghpull:`4722`: allow purging local results as long as they are not outstanding
63 63 * :ghpull:`4668`: Make non-ASCII docstring unicode
64 64 * :ghpull:`4639`: Minor import fix to get qtconsole with --pylab=qt working
65 65 * :ghpull:`4453`: Play nice with App Nap
66 66 * :ghpull:`4609`: Fix bytes regex for Python 3.
67 67 * :ghpull:`4488`: fix typo in message spec doc
68 68 * :ghpull:`4346`: getpass() on Windows & Python 2 needs bytes prompt
69 69 * :ghpull:`4230`: Switch correctly to the user's default matplotlib backend after inline.
70 70 * :ghpull:`4214`: engine ID metadata should be unicode, not bytes
71 71 * :ghpull:`4232`: no highlight if no language specified
72 72 * :ghpull:`4218`: Fix display of SyntaxError when .py file is modified
73 73 * :ghpull:`4217`: avoid importing numpy at the module level
74 74 * :ghpull:`4213`: fixed dead link in examples/notebooks readme to Part 3
75 75 * :ghpull:`4183`: ESC should be handled by CM if tooltip is not on
76 76 * :ghpull:`4193`: Update for #3549: Append Firefox overflow-x fix
77 77 * :ghpull:`4205`: use TextIOWrapper when communicating with pandoc subprocess
78 78 * :ghpull:`4204`: remove some extraneous print statements from IPython.parallel
79 79 * :ghpull:`4201`: HeadingCells cannot be split or merged
80 80
81 81 1.2.1:
82 82
83 83 * :ghissue:`5101`: IPython 1.2.0: notebook fail with "500 Internal Server Error"
84 84
85 85 1.2.0:
86 86
87 87 * :ghissue:`4892`: IPython.qt test failure with python3.4
88 88 * :ghissue:`4810`: ipcluster bug in clean_logs flag
89 89 * :ghissue:`4765`: missing build script for highlight.js
90 90 * :ghissue:`4761`: ipv6 address triggers cookie exception
91 91 * :ghissue:`4721`: purge_results with jobid crashing - looking for insight
92 92 * :ghissue:`4602`: "ipcluster stop" fails after "ipcluster start --daemonize" using python3.3
93 93 * :ghissue:`3386`: Magic %paste not working in Python 3.3.2. TypeError: Type str doesn't support the buffer API
94 94 * :ghissue:`4485`: Incorrect info in "Messaging in IPython" documentation.
95 95 * :ghissue:`4351`: /parallel/apps/launcher.py error
96 96 * :ghissue:`4334`: NotebookApp.webapp_settings static_url_prefix causes crash
97 97 * :ghissue:`4039`: Celltoolbar example issue
98 98 * :ghissue:`4256`: IPython no longer handles unicode file names
99 99 * :ghissue:`4122`: Nbconvert [windows]: Inconsistent line endings in markdown cells exported to latex
100 100 * :ghissue:`3819`: nbconvert add extra blank line to code block on Windows.
101 101 * :ghissue:`4203`: remove spurious print statement from parallel annoted functions
102 102 * :ghissue:`4200`: Notebook: merging a heading cell and markdown cell cannot be undone
103 103
104 104
105 105 Issues closed in 1.1
106 106 --------------------
107 107
108 108 GitHub stats for 2013/08/08 - 2013/09/09 (since 1.0)
109 109
110 110 These lists are automatically generated, and may be incomplete or contain duplicates.
111 111
112 112 The following 25 authors contributed 337 commits.
113 113
114 114 * Benjamin Ragan-Kelley
115 115 * Bing Xia
116 116 * Bradley M. Froehle
117 117 * Brian E. Granger
118 118 * Damián Avila
119 119 * dhirschfeld
120 120 * Dražen Lučanin
121 121 * gmbecker
122 122 * Jake Vanderplas
123 123 * Jason Grout
124 124 * Jonathan Frederic
125 125 * Kevin Burke
126 126 * Kyle Kelley
127 127 * Matt Henderson
128 128 * Matthew Brett
129 129 * Matthias Bussonnier
130 130 * Pankaj Pandey
131 131 * Paul Ivanov
132 132 * rossant
133 133 * Samuel Ainsworth
134 134 * Stephan Rave
135 135 * stonebig
136 136 * Thomas Kluyver
137 137 * Yaroslav Halchenko
138 138 * Zachary Sailer
139 139
140 140
141 141 We closed a total of 76 issues, 58 pull requests and 18 regular issues;
142 142 this is the full list (generated with the script :file:`tools/github_stats.py`):
143 143
144 144 Pull Requests (58):
145 145
146 146 * :ghpull:`4188`: Allow user_ns trait to be None
147 147 * :ghpull:`4189`: always fire LOCAL_IPS.extend(PUBLIC_IPS)
148 148 * :ghpull:`4174`: various issues in markdown and rst templates
149 149 * :ghpull:`4178`: add missing data_javascript
150 150 * :ghpull:`4181`: nbconvert: Fix, sphinx template not removing new lines from headers
151 151 * :ghpull:`4043`: don't 'restore_bytes' in from_JSON
152 152 * :ghpull:`4163`: Fix for incorrect default encoding on Windows.
153 153 * :ghpull:`4136`: catch javascript errors in any output
154 154 * :ghpull:`4171`: add nbconvert config file when creating profiles
155 155 * :ghpull:`4125`: Basic exercise of `ipython [subcommand] -h` and help-all
156 156 * :ghpull:`4085`: nbconvert: Fix sphinx preprocessor date format string for Windows
157 157 * :ghpull:`4159`: don't split `.cell` and `div.cell` CSS
158 158 * :ghpull:`4158`: generate choices for `--gui` configurable from real mapping
159 159 * :ghpull:`4065`: do not include specific css in embedable one
160 160 * :ghpull:`4092`: nbconvert: Fix for unicode html headers, Windows + Python 2.x
161 161 * :ghpull:`4074`: close Client sockets if connection fails
162 162 * :ghpull:`4064`: Store default codemirror mode in only 1 place
163 163 * :ghpull:`4104`: Add way to install MathJax to a particular profile
164 164 * :ghpull:`4144`: help_end transformer shouldn't pick up ? in multiline string
165 165 * :ghpull:`4143`: update example custom.js
166 166 * :ghpull:`4142`: DOC: unwrap openssl line in public_server doc
167 167 * :ghpull:`4141`: add files with a separate `add` call in backport_pr
168 168 * :ghpull:`4137`: Restore autorestore option for storemagic
169 169 * :ghpull:`4098`: pass profile-dir instead of profile name to Kernel
170 170 * :ghpull:`4120`: support `input` in Python 2 kernels
171 171 * :ghpull:`4088`: nbconvert: Fix coalescestreams line with incorrect nesting causing strange behavior
172 172 * :ghpull:`4060`: only strip continuation prompts if regular prompts seen first
173 173 * :ghpull:`4132`: Fixed name error bug in function safe_unicode in module py3compat.
174 174 * :ghpull:`4121`: move test_kernel from IPython.zmq to IPython.kernel
175 175 * :ghpull:`4118`: ZMQ heartbeat channel: catch EINTR exceptions and continue.
176 176 * :ghpull:`4054`: use unicode for HTML export
177 177 * :ghpull:`4106`: fix a couple of default block values
178 178 * :ghpull:`4115`: Update docs on declaring a magic function
179 179 * :ghpull:`4101`: restore accidentally removed EngineError
180 180 * :ghpull:`4096`: minor docs changes
181 181 * :ghpull:`4056`: respect `pylab_import_all` when `--pylab` specified at the command-line
182 182 * :ghpull:`4091`: Make Qt console banner configurable
183 183 * :ghpull:`4086`: fix missing errno import
184 184 * :ghpull:`4030`: exclude `.git` in MANIFEST.in
185 185 * :ghpull:`4047`: Use istype() when checking if canned object is a dict
186 186 * :ghpull:`4031`: don't close_fds on Windows
187 187 * :ghpull:`4029`: bson.Binary moved
188 188 * :ghpull:`4035`: Fixed custom jinja2 templates being ignored when setting template_path
189 189 * :ghpull:`4026`: small doc fix in nbconvert
190 190 * :ghpull:`4016`: Fix IPython.start_* functions
191 191 * :ghpull:`4021`: Fix parallel.client.View map() on numpy arrays
192 192 * :ghpull:`4022`: DOC: fix links to matplotlib, notebook docs
193 193 * :ghpull:`4018`: Fix warning when running IPython.kernel tests
194 194 * :ghpull:`4019`: Test skipping without unicode paths
195 195 * :ghpull:`4008`: Transform code before %prun/%%prun runs
196 196 * :ghpull:`4014`: Fix typo in ipapp
197 197 * :ghpull:`3987`: get files list in backport_pr
198 198 * :ghpull:`3974`: nbconvert: Fix app tests on Window7 w/ Python 3.3
199 199 * :ghpull:`3978`: fix `--existing` with non-localhost IP
200 200 * :ghpull:`3939`: minor checkpoint cleanup
201 201 * :ghpull:`3981`: BF: fix nbconvert rst input prompt spacing
202 202 * :ghpull:`3960`: Don't make sphinx a dependency for importing nbconvert
203 203 * :ghpull:`3973`: logging.Formatter is not new-style in 2.6
204 204
205 205 Issues (18):
206 206
207 207 * :ghissue:`4024`: nbconvert markdown issues
208 208 * :ghissue:`4095`: Catch js error in append html in stream/pyerr
209 209 * :ghissue:`4156`: Specifying --gui=tk at the command line
210 210 * :ghissue:`3818`: nbconvert can't handle Heading with Chinese characters on Japanese Windows OS.
211 211 * :ghissue:`4134`: multi-line parser fails on ''' in comment, qtconsole and notebook.
212 212 * :ghissue:`3998`: sample custom.js needs to be updated
213 213 * :ghissue:`4078`: StoreMagic.autorestore not working in 1.0.0
214 214 * :ghissue:`3990`: Buitlin `input` doesn't work over zmq
215 215 * :ghissue:`4015`: nbconvert fails to convert all the content of a notebook
216 216 * :ghissue:`4059`: Issues with Ellipsis literal in Python 3
217 217 * :ghissue:`4103`: Wrong default argument of DirectView.clear
218 218 * :ghissue:`4100`: parallel.client.client references undefined error.EngineError
219 219 * :ghissue:`4005`: IPython.start_kernel doesn't work.
220 220 * :ghissue:`4020`: IPython parallel map fails on numpy arrays
221 221 * :ghissue:`3945`: nbconvert: commandline tests fail Win7x64 Py3.3
222 222 * :ghissue:`3977`: unable to complete remote connections for two-process
223 223 * :ghissue:`3980`: nbconvert rst output lacks needed blank lines
224 224 * :ghissue:`3968`: TypeError: super() argument 1 must be type, not classobj (Python 2.6.6)
225 225
226 226 Issues closed in 1.0
227 227 --------------------
228 228
229 229 GitHub stats for 2012/06/30 - 2013/08/08 (since 0.13)
230 230
231 231 These lists are automatically generated, and may be incomplete or contain duplicates.
232 232
233 233 The following 155 authors contributed 4258 commits.
234 234
235 235 * Aaron Meurer
236 236 * Adam Davis
237 237 * Ahmet Bakan
238 238 * Alberto Valverde
239 239 * Allen Riddell
240 240 * Anders Hovmöller
241 241 * Andrea Bedini
242 242 * Andrew Spiers
243 243 * Andrew Vandever
244 244 * Anthony Scopatz
245 245 * Anton Akhmerov
246 246 * Anton I. Sipos
247 247 * Antony Lee
248 248 * Aron Ahmadia
249 249 * Benedikt Sauer
250 250 * Benjamin Jones
251 251 * Benjamin Ragan-Kelley
252 252 * Benjie Chen
253 253 * Boris de Laage
254 254 * Brad Reisfeld
255 255 * Bradley M. Froehle
256 256 * Brian E. Granger
257 257 * Cameron Bates
258 258 * Cavendish McKay
259 259 * chapmanb
260 260 * Chris Beaumont
261 261 * Chris Laumann
262 262 * Christoph Gohlke
263 263 * codebraker
264 264 * codespaced
265 265 * Corran Webster
266 266 * DamianHeard
267 267 * Damián Avila
268 268 * Dan Kilman
269 269 * Dan McDougall
270 270 * Danny Staple
271 271 * David Hirschfeld
272 272 * David P. Sanders
273 273 * David Warde-Farley
274 274 * David Wolever
275 275 * David Wyde
276 276 * debjan
277 277 * Diane Trout
278 278 * dkua
279 279 * Dominik Dabrowski
280 280 * Donald Curtis
281 281 * Dražen Lučanin
282 282 * drevicko
283 283 * Eric O. LEBIGOT
284 284 * Erik M. Bray
285 285 * Erik Tollerud
286 286 * Eugene Van den Bulke
287 287 * Evan Patterson
288 288 * Fernando Perez
289 289 * Francesco Montesano
290 290 * Frank Murphy
291 291 * Greg Caporaso
292 292 * Guy Haskin Fernald
293 293 * guziy
294 294 * Hans Meine
295 295 * Harry Moreno
296 296 * henryiii
297 297 * Ivan Djokic
298 298 * Jack Feser
299 299 * Jake Vanderplas
300 300 * jakobgager
301 301 * James Booth
302 302 * Jan Schulz
303 303 * Jason Grout
304 304 * Jeff Knisley
305 305 * Jens Hedegaard Nielsen
306 306 * jeremiahbuddha
307 307 * Jerry Fowler
308 308 * Jessica B. Hamrick
309 309 * Jez Ng
310 310 * John Zwinck
311 311 * Jonathan Frederic
312 312 * Jonathan Taylor
313 313 * Joon Ro
314 314 * Joseph Lansdowne
315 315 * Juergen Hasch
316 316 * Julian Taylor
317 317 * Jussi Sainio
318 318 * Jörgen Stenarson
319 319 * kevin
320 320 * klonuo
321 321 * Konrad Hinsen
322 322 * Kyle Kelley
323 323 * Lars Solberg
324 324 * Lessandro Mariano
325 325 * Mark Sienkiewicz at STScI
326 326 * Martijn Vermaat
327 327 * Martin Spacek
328 328 * Matthias Bussonnier
329 329 * Maxim Grechkin
330 330 * Maximilian Albert
331 331 * MercuryRising
332 332 * Michael Droettboom
333 333 * Michael Shuffett
334 334 * Michał Górny
335 335 * Mikhail Korobov
336 336 * mr.Shu
337 337 * Nathan Goldbaum
338 338 * ocefpaf
339 339 * Ohad Ravid
340 340 * Olivier Grisel
341 341 * Olivier Verdier
342 342 * Owen Healy
343 343 * Pankaj Pandey
344 344 * Paul Ivanov
345 345 * Pawel Jasinski
346 346 * Pietro Berkes
347 347 * Piti Ongmongkolkul
348 348 * Puneeth Chaganti
349 349 * Rich Wareham
350 350 * Richard Everson
351 351 * Rick Lupton
352 352 * Rob Young
353 353 * Robert Kern
354 354 * Robert Marchman
355 355 * Robert McGibbon
356 356 * Rui Pereira
357 357 * Rustam Safin
358 358 * Ryan May
359 359 * s8weber
360 360 * Samuel Ainsworth
361 361 * Sean Vig
362 362 * Siyu Zhang
363 363 * Skylar Saveland
364 364 * slojo404
365 365 * smithj1
366 366 * Stefan Karpinski
367 367 * Stefan van der Walt
368 368 * Steven Silvester
369 369 * Takafumi Arakaki
370 370 * Takeshi Kanmae
371 371 * tcmulcahy
372 372 * teegaar
373 373 * Thomas Kluyver
374 374 * Thomas Robitaille
375 375 * Thomas Spura
376 376 * Thomas Weißschuh
377 377 * Timothy O'Donnell
378 378 * Tom Dimiduk
379 379 * ugurthemaster
380 380 * urielshaolin
381 381 * v923z
382 382 * Valentin Haenel
383 383 * Victor Zverovich
384 384 * W. Trevor King
385 385 * y-p
386 386 * Yoav Ram
387 387 * Zbigniew Jędrzejewski-Szmek
388 388 * Zoltán Vörös
389 389
390 390
391 391 We closed a total of 1484 issues, 793 pull requests and 691 regular issues;
392 392 this is the full list (generated with the script
393 393 :file:`tools/github_stats.py`):
394 394
395 395 Pull Requests (793):
396 396
397 397 * :ghpull:`3958`: doc update
398 398 * :ghpull:`3965`: Fix ansi color code for background yellow
399 399 * :ghpull:`3964`: Fix casing of message.
400 400 * :ghpull:`3942`: Pass on install docs
401 401 * :ghpull:`3962`: exclude IPython.lib.kernel in iptest
402 402 * :ghpull:`3961`: Longpath test fix
403 403 * :ghpull:`3905`: Remove references to 0.11 and 0.12 from config/overview.rst
404 404 * :ghpull:`3951`: nbconvert: fixed latex characters not escaped properly in nbconvert
405 405 * :ghpull:`3949`: log fatal error when PDF conversion fails
406 406 * :ghpull:`3947`: nbconvert: Make writer & post-processor aliases case insensitive.
407 407 * :ghpull:`3938`: Recompile css.
408 408 * :ghpull:`3948`: sphinx and PDF tweaks
409 409 * :ghpull:`3943`: nbconvert: Serve post-processor Windows fix
410 410 * :ghpull:`3934`: nbconvert: fix logic of verbose flag in PDF post processor
411 411 * :ghpull:`3929`: swallow enter event in rename dialog
412 412 * :ghpull:`3924`: nbconvert: Backport fixes
413 413 * :ghpull:`3925`: Replace --pylab flag with --matplotlib in usage
414 414 * :ghpull:`3910`: Added explicit error message for missing configuration arguments.
415 415 * :ghpull:`3913`: grffile to support spaces in notebook names
416 416 * :ghpull:`3918`: added check_for_tornado, closes #3916
417 417 * :ghpull:`3917`: change docs/examples refs to be just examples
418 418 * :ghpull:`3908`: what's new tweaks
419 419 * :ghpull:`3896`: two column quickhelp dialog, closes #3895
420 420 * :ghpull:`3911`: explicitly load python mode before IPython mode
421 421 * :ghpull:`3901`: don't force . relative path, fix #3897
422 422 * :ghpull:`3891`: fix #3889
423 423 * :ghpull:`3892`: Fix documentation of Kernel.stop_channels
424 424 * :ghpull:`3888`: posixify paths for Windows latex
425 425 * :ghpull:`3882`: quick fix for #3881
426 426 * :ghpull:`3877`: don't use `shell=True` in PDF export
427 427 * :ghpull:`3878`: minor template loading cleanup
428 428 * :ghpull:`3855`: nbconvert: Filter tests
429 429 * :ghpull:`3879`: finish 3870
430 430 * :ghpull:`3870`: Fix for converting notebooks that contain unicode characters.
431 431 * :ghpull:`3876`: Update parallel_winhpc.rst
432 432 * :ghpull:`3872`: removing vim-ipython, since it has it's own repo
433 433 * :ghpull:`3871`: updating docs
434 434 * :ghpull:`3873`: remove old examples
435 435 * :ghpull:`3868`: update CodeMirror component to 3.15
436 436 * :ghpull:`3865`: Escape filename for pdflatex in nbconvert
437 437 * :ghpull:`3861`: remove old external.js
438 438 * :ghpull:`3864`: add keyboard shortcut to docs
439 439 * :ghpull:`3834`: This PR fixes a few issues with nbconvert tests
440 440 * :ghpull:`3840`: prevent profile_dir from being undefined
441 441 * :ghpull:`3859`: Add "An Afternoon Hack" to docs
442 442 * :ghpull:`3854`: Catch errors filling readline history on startup
443 443 * :ghpull:`3857`: Delete extra auto
444 444 * :ghpull:`3845`: nbconvert: Serve from original build directory
445 445 * :ghpull:`3846`: Add basic logging to nbconvert
446 446 * :ghpull:`3850`: add missing store_history key to Notebook execute_requests
447 447 * :ghpull:`3844`: update payload source
448 448 * :ghpull:`3830`: mention metadata / display_data similarity in pyout spec
449 449 * :ghpull:`3848`: fix incorrect `empty-docstring`
450 450 * :ghpull:`3836`: Parse markdown correctly when mathjax is disabled
451 451 * :ghpull:`3849`: skip a failing test on windows
452 452 * :ghpull:`3828`: signature_scheme lives in Session
453 453 * :ghpull:`3831`: update nbconvert doc with new CLI
454 454 * :ghpull:`3822`: add output flag to nbconvert
455 455 * :ghpull:`3780`: Added serving the output directory if html-based format are selected.
456 456 * :ghpull:`3764`: Cleanup nbconvert templates
457 457 * :ghpull:`3829`: remove now-duplicate 'this is dev' note
458 458 * :ghpull:`3814`: add `ConsoleWidget.execute_on_complete_input` flag
459 459 * :ghpull:`3826`: try rtfd
460 460 * :ghpull:`3821`: add sphinx prolog
461 461 * :ghpull:`3817`: relax timeouts in terminal console and tests
462 462 * :ghpull:`3825`: fix more tests that fail when pandoc is missing
463 463 * :ghpull:`3824`: don't set target on internal markdown links
464 464 * :ghpull:`3816`: s/pylab/matplotlib in docs
465 465 * :ghpull:`3812`: Describe differences between start_ipython and embed
466 466 * :ghpull:`3805`: Print View has been removed
467 467 * :ghpull:`3820`: Make it clear that 1.0 is not released yet
468 468 * :ghpull:`3784`: nbconvert: Export flavors & PDF writer (ipy dev meeting)
469 469 * :ghpull:`3800`: semantic-versionify version number for non-releases
470 470 * :ghpull:`3802`: Documentation .txt to .rst
471 471 * :ghpull:`3765`: cleanup terminal console iopub handling
472 472 * :ghpull:`3720`: Fix for #3719
473 473 * :ghpull:`3787`: re-raise KeyboardInterrupt in raw_input
474 474 * :ghpull:`3770`: Organizing reveal's templates.
475 475 * :ghpull:`3751`: Use link(2) when possible in nbconvert
476 476 * :ghpull:`3792`: skip tests that require pandoc
477 477 * :ghpull:`3782`: add Importing Notebooks example
478 478 * :ghpull:`3752`: nbconvert: Add cwd to sys.path
479 479 * :ghpull:`3789`: fix raw_input in qtconsole
480 480 * :ghpull:`3756`: document the wire protocol
481 481 * :ghpull:`3749`: convert IPython syntax to Python syntax in nbconvert python template
482 482 * :ghpull:`3793`: Closes #3788
483 483 * :ghpull:`3794`: Change logo link to ipython.org
484 484 * :ghpull:`3746`: Raise a named exception when pandoc is missing
485 485 * :ghpull:`3781`: comply with the message spec in the notebook
486 486 * :ghpull:`3779`: remove bad `if logged_in` preventing new-notebook without login
487 487 * :ghpull:`3743`: remove notebook read-only view
488 488 * :ghpull:`3732`: add delay to autosave in beforeunload
489 489 * :ghpull:`3761`: Added rm_math_space to markdown cells in the basichtml.tpl to be rendered ok by mathjax after the nbconvertion.
490 490 * :ghpull:`3758`: nbconvert: Filter names cleanup
491 491 * :ghpull:`3769`: Add configurability to tabcompletion timeout
492 492 * :ghpull:`3771`: Update px pylab test to match new output of pylab
493 493 * :ghpull:`3741`: better message when notebook format is not supported
494 494 * :ghpull:`3753`: document Ctrl-C not working in ipython kernel
495 495 * :ghpull:`3766`: handle empty metadata in pyout messages more gracefully.
496 496 * :ghpull:`3736`: my attempt to fix #3735
497 497 * :ghpull:`3759`: nbconvert: Provide a more useful error for invalid use case.
498 498 * :ghpull:`3760`: nbconvert: Allow notebook filenames without their extensions
499 499 * :ghpull:`3750`: nbconvert: Add cwd to default templates search path.
500 500 * :ghpull:`3748`: Update nbconvert docs
501 501 * :ghpull:`3734`: Nbconvert: Export extracted files into `nbname_files` subdirectory
502 502 * :ghpull:`3733`: Nicer message when pandoc is missing, closes #3730
503 503 * :ghpull:`3722`: fix two failing test in IPython.lib
504 504 * :ghpull:`3704`: Start what's new for 1.0
505 505 * :ghpull:`3705`: Complete rewrite of IPython Notebook documentation: docs/source/interactive/htmlnotebook.txt
506 506 * :ghpull:`3709`: Docs cleanup
507 507 * :ghpull:`3716`: raw_input fixes for kernel restarts
508 508 * :ghpull:`3683`: use `%matplotlib` in example notebooks
509 509 * :ghpull:`3686`: remove quarantine
510 510 * :ghpull:`3699`: svg2pdf unicode fix
511 511 * :ghpull:`3695`: fix SVG2PDF
512 512 * :ghpull:`3685`: fix Pager.detach
513 513 * :ghpull:`3675`: document new dependencies
514 514 * :ghpull:`3690`: Fixing some css minors in full_html and reveal.
515 515 * :ghpull:`3671`: nbconvert tests
516 516 * :ghpull:`3692`: Fix rename notebook - show error with invalid name
517 517 * :ghpull:`3409`: Prevent qtconsole frontend freeze on lots of output.
518 518 * :ghpull:`3660`: refocus active cell on dialog close
519 519 * :ghpull:`3598`: Statelessify mathjaxutils
520 520 * :ghpull:`3673`: enable comment/uncomment selection
521 521 * :ghpull:`3677`: remove special-case in get_home_dir for frozen dists
522 522 * :ghpull:`3674`: add CONTRIBUTING.md
523 523 * :ghpull:`3670`: use Popen command list for ipexec
524 524 * :ghpull:`3568`: pylab import adjustments
525 525 * :ghpull:`3559`: add create.Cell and delete.Cell js events
526 526 * :ghpull:`3606`: push cell magic to the head of the transformer line
527 527 * :ghpull:`3607`: NbConvert: Writers, No YAML, and stuff...
528 528 * :ghpull:`3665`: Pywin32 skips
529 529 * :ghpull:`3669`: set default client_class for QtKernelManager
530 530 * :ghpull:`3662`: add strip_encoding_cookie transformer
531 531 * :ghpull:`3641`: increase patience for slow kernel startup in tests
532 532 * :ghpull:`3651`: remove a bunch of unused `default_config_file` assignments
533 533 * :ghpull:`3630`: CSS adjustments
534 534 * :ghpull:`3645`: Don't require HistoryManager to have a shell
535 535 * :ghpull:`3643`: don't assume tested ipython is on the PATH
536 536 * :ghpull:`3654`: fix single-result AsyncResults
537 537 * :ghpull:`3601`: Markdown in heading cells (take 2)
538 538 * :ghpull:`3652`: Remove old `docs/examples`
539 539 * :ghpull:`3621`: catch any exception appending output
540 540 * :ghpull:`3585`: don't blacklist builtin names
541 541 * :ghpull:`3647`: Fix `frontend` deprecation warnings in several examples
542 542 * :ghpull:`3649`: fix AsyncResult.get_dict for single result
543 543 * :ghpull:`3648`: Fix store magic test
544 544 * :ghpull:`3650`: Fix, config_file_name was ignored
545 545 * :ghpull:`3640`: Gcf.get_active() can return None
546 546 * :ghpull:`3571`: Added shorcuts to split cell, merge cell above and merge cell below.
547 547 * :ghpull:`3635`: Added missing slash to print-pdf call.
548 548 * :ghpull:`3487`: Drop patch for compatibility with pyreadline 1.5
549 549 * :ghpull:`3338`: Allow filename with extension in find_cmd in Windows.
550 550 * :ghpull:`3628`: Fix test for Python 3 on Windows.
551 551 * :ghpull:`3642`: Fix typo in docs
552 552 * :ghpull:`3627`: use DEFAULT_STATIC_FILES_PATH in a test instead of package dir
553 553 * :ghpull:`3624`: fix some unicode in zmqhandlers
554 554 * :ghpull:`3460`: Set calling program to UNKNOWN, when argv not in sys
555 555 * :ghpull:`3632`: Set calling program to UNKNOWN, when argv not in sys (take #2)
556 556 * :ghpull:`3629`: Use new entry point for python -m IPython
557 557 * :ghpull:`3626`: passing cell to showInPager, closes #3625
558 558 * :ghpull:`3618`: expand terminal color support
559 559 * :ghpull:`3623`: raise UsageError for unsupported GUI backends
560 560 * :ghpull:`3071`: Add magic function %drun to run code in debugger
561 561 * :ghpull:`3608`: a nicer error message when using %pylab magic
562 562 * :ghpull:`3592`: add extra_config_file
563 563 * :ghpull:`3612`: updated .mailmap
564 564 * :ghpull:`3616`: Add examples for interactive use of MPI.
565 565 * :ghpull:`3615`: fix regular expression for ANSI escapes
566 566 * :ghpull:`3586`: Corrected a typo in the format string for strftime the sphinx.py transformer of nbconvert
567 567 * :ghpull:`3611`: check for markdown no longer needed, closes #3610
568 568 * :ghpull:`3555`: Simplify caching of modules with %run
569 569 * :ghpull:`3583`: notebook small things
570 570 * :ghpull:`3594`: Fix duplicate completion in notebook
571 571 * :ghpull:`3600`: parallel: Improved logging for errors during BatchSystemLauncher.stop
572 572 * :ghpull:`3595`: Revert "allow markdown in heading cells"
573 573 * :ghpull:`3538`: add IPython.start_ipython
574 574 * :ghpull:`3562`: Allow custom nbconvert template loaders
575 575 * :ghpull:`3582`: pandoc adjustments
576 576 * :ghpull:`3560`: Remove max_msg_size
577 577 * :ghpull:`3591`: Refer to Setuptools instead of Distribute
578 578 * :ghpull:`3590`: IPython.sphinxext needs an __init__.py
579 579 * :ghpull:`3581`: Added the possibility to read a custom.css file for tweaking the final html in full_html and reveal templates.
580 580 * :ghpull:`3576`: Added support for markdown in heading cells when they are nbconverted.
581 581 * :ghpull:`3575`: tweak `run -d` message to 'continue execution'
582 582 * :ghpull:`3569`: add PYTHONSTARTUP to startup files
583 583 * :ghpull:`3567`: Trigger a single event on js app initilized
584 * :ghpull:`3565`: style.min.css shoudl always exist...
584 * :ghpull:`3565`: style.min.css should always exist...
585 585 * :ghpull:`3531`: allow markdown in heading cells
586 586 * :ghpull:`3577`: Simplify codemirror ipython-mode
587 587 * :ghpull:`3495`: Simplified regexp, and suggestions for clearer regexps.
588 588 * :ghpull:`3578`: Use adjustbox to specify figure size in nbconvert -> latex
589 589 * :ghpull:`3572`: Skip import irunner test on Windows.
590 590 * :ghpull:`3574`: correct static path for CM modes autoload
591 591 * :ghpull:`3558`: Add IPython.sphinxext
592 592 * :ghpull:`3561`: mention double-control-C to stop notebook server
593 593 * :ghpull:`3566`: fix event names
594 594 * :ghpull:`3564`: Remove trivial nbconvert example
595 595 * :ghpull:`3540`: allow cython cache dir to be deleted
596 596 * :ghpull:`3527`: cleanup stale, unused exceptions in parallel.error
597 597 * :ghpull:`3529`: ensure raw_input returns str in zmq shell
598 598 * :ghpull:`3541`: respect image size metadata in qtconsole
599 599 * :ghpull:`3550`: Fixing issue preventing the correct read of images by full_html and reveal exporters.
600 600 * :ghpull:`3557`: open markdown links in new tabs
601 601 * :ghpull:`3556`: remove mention of nonexistent `_margv` in macro
602 602 * :ghpull:`3552`: set overflow-x: hidden on Firefox only
603 603 * :ghpull:`3554`: Fix missing import os in latex exporter.
604 604 * :ghpull:`3546`: Don't hardcode **latex** posix paths in nbconvert
605 605 * :ghpull:`3551`: fix path prefix in nbconvert
606 606 * :ghpull:`3533`: Use a CDN to get reveal.js library.
607 607 * :ghpull:`3498`: When a notebook is written to file, name the metadata name u''.
608 608 * :ghpull:`3548`: Change to standard save icon in Notebook toolbar
609 609 * :ghpull:`3539`: Don't hardcode posix paths in nbconvert
610 610 * :ghpull:`3508`: notebook supports raw_input and %debug now
611 611 * :ghpull:`3526`: ensure 'default' is first in cluster profile list
612 612 * :ghpull:`3525`: basic timezone info
613 613 * :ghpull:`3532`: include nbconvert templates in installation
614 614 * :ghpull:`3515`: update CodeMirror component to 3.14
615 615 * :ghpull:`3513`: add 'No Checkpoints' to Revert menu
616 616 * :ghpull:`3536`: format positions are required in Python 2.6.x
617 617 * :ghpull:`3521`: Nbconvert fix, silent fail if template doesn't exist
618 618 * :ghpull:`3530`: update %store magic docstring
619 619 * :ghpull:`3528`: fix local mathjax with custom base_project_url
620 620 * :ghpull:`3518`: Clear up unused imports
621 621 * :ghpull:`3506`: %store -r restores saved aliases and directory history, as well as variables
622 622 * :ghpull:`3516`: make css highlight style configurable
623 623 * :ghpull:`3523`: Exclude frontend shim from docs build
624 624 * :ghpull:`3514`: use bootstrap `disabled` instead of `ui-state-disabled`
625 625 * :ghpull:`3520`: Added relative import of RevealExporter to __init__.py inside exporters module
626 626 * :ghpull:`3507`: fix HTML capitalization in nbconvert exporter classes
627 627 * :ghpull:`3512`: fix nbconvert filter validation
628 628 * :ghpull:`3511`: Get Tracer working after ipapi.get replaced with get_ipython
629 629 * :ghpull:`3510`: use `window.onbeforeunload=` for nav-away warning
630 630 * :ghpull:`3504`: don't use parent=self in handlers
631 631 * :ghpull:`3500`: Merge nbconvert into IPython
632 632 * :ghpull:`3478`: restore "unsaved changes" warning on unload
633 633 * :ghpull:`3493`: add a dialog when the kernel is auto-restarted
634 634 * :ghpull:`3488`: Add test suite for autoreload extension
635 635 * :ghpull:`3484`: Catch some pathological cases inside oinspect
636 636 * :ghpull:`3481`: Display R errors without Python traceback
637 637 * :ghpull:`3468`: fix `%magic` output
638 638 * :ghpull:`3430`: add parent to Configurable
639 639 * :ghpull:`3491`: Remove unexpected keyword parameter to remove_kernel
640 640 * :ghpull:`3485`: SymPy has changed its recommended way to initialize printing
641 641 * :ghpull:`3486`: Add test for non-ascii characters in docstrings
642 642 * :ghpull:`3483`: Inputtransformer: Allow classic prompts without space
643 643 * :ghpull:`3482`: Use an absolute path to iptest, because the tests are not always run from $IPYTHONDIR.
644 644 * :ghpull:`3381`: enable 2x (retina) display
645 645 * :ghpull:`3450`: Flatten IPython.frontend
646 646 * :ghpull:`3477`: pass config to subapps
647 647 * :ghpull:`3466`: Kernel fails to start when username has non-ascii characters
648 648 * :ghpull:`3465`: Add HTCondor bindings to IPython.parallel
649 649 * :ghpull:`3463`: fix typo, closes #3462
650 650 * :ghpull:`3456`: Notice for users who disable javascript
651 651 * :ghpull:`3453`: fix cell execution in firefox, closes #3447
652 652 * :ghpull:`3393`: [WIP] bootstrapify
653 653 * :ghpull:`3440`: Fix installing mathjax from downloaded file via command line
654 654 * :ghpull:`3431`: Provide means for starting the Qt console maximized and with the menu bar hidden
655 655 * :ghpull:`3425`: base IPClusterApp inherits from BaseIPythonApp
656 656 * :ghpull:`3433`: Update IPython\external\path\__init__.py
657 657 * :ghpull:`3298`: Some fixes in IPython Sphinx directive
658 658 * :ghpull:`3428`: process escapes in mathjax
659 659 * :ghpull:`3420`: thansk -> thanks
660 660 * :ghpull:`3416`: Fix doc: "principle" not "principal"
661 661 * :ghpull:`3413`: more unique filename for test
662 662 * :ghpull:`3364`: Inject requirejs in notebook and start using it.
663 663 * :ghpull:`3390`: Fix %paste with blank lines
664 664 * :ghpull:`3403`: fix creating config objects from dicts
665 665 * :ghpull:`3401`: rollback #3358
666 666 * :ghpull:`3373`: make cookie_secret configurable
667 667 * :ghpull:`3307`: switch default ws_url logic to js side
668 668 * :ghpull:`3392`: Restore anchor link on h2-h6
669 * :ghpull:`3369`: Use different treshold for (auto)scroll in output
669 * :ghpull:`3369`: Use different threshold for (auto)scroll in output
670 670 * :ghpull:`3370`: normalize unicode notebook filenames
671 671 * :ghpull:`3372`: base default cookie name on request host+port
672 672 * :ghpull:`3378`: disable CodeMirror drag/drop on Safari
673 673 * :ghpull:`3358`: workaround spurious CodeMirror scrollbars
674 674 * :ghpull:`3371`: make setting the notebook dirty flag an event
675 675 * :ghpull:`3366`: remove long-dead zmq frontend.py and completer.py
676 676 * :ghpull:`3382`: cull Session digest history
677 677 * :ghpull:`3330`: Fix get_ipython_dir when $HOME is /
678 678 * :ghpull:`3319`: IPEP 13: user-expressions and user-variables
679 679 * :ghpull:`3384`: comments in tools/gitwash_dumper.py changed (''' to """)
680 680 * :ghpull:`3387`: Make submodule checks work under Python 3.
681 681 * :ghpull:`3357`: move anchor-link off of heading text
682 682 * :ghpull:`3351`: start basic tests of ipcluster Launchers
683 683 * :ghpull:`3377`: allow class.__module__ to be None
684 684 * :ghpull:`3340`: skip submodule check in package managers
685 685 * :ghpull:`3328`: decode subprocess output in launchers
686 686 * :ghpull:`3368`: Reenable bracket matching
687 687 * :ghpull:`3356`: Mpr fixes
688 688 * :ghpull:`3336`: Use new input transformation API in %time magic
689 689 * :ghpull:`3325`: Organize the JS and less files by component.
690 690 * :ghpull:`3342`: fix test_find_cmd_python
691 691 * :ghpull:`3354`: catch socket.error in utils.localinterfaces
692 692 * :ghpull:`3341`: fix default cluster count
693 693 * :ghpull:`3286`: don't use `get_ipython` from builtins in library code
694 694 * :ghpull:`3333`: notebookapp: add missing whitespace to warnings
695 695 * :ghpull:`3323`: Strip prompts even if the prompt isn't present on the first line.
696 696 * :ghpull:`3321`: Reorganize the python/server side of the notebook
697 697 * :ghpull:`3320`: define `__file__` in config files
698 698 * :ghpull:`3317`: rename `%%file` to `%%writefile`
699 699 * :ghpull:`3304`: set unlimited HWM for all relay devices
700 700 * :ghpull:`3315`: Update Sympy_printing extension load
701 701 * :ghpull:`3310`: further clarify Image docstring
702 702 * :ghpull:`3285`: load extensions in builtin trap
703 703 * :ghpull:`3308`: Speed up AsyncResult._wait_for_outputs(0)
704 704 * :ghpull:`3294`: fix callbacks as optional in js kernel.execute
705 705 * :ghpull:`3276`: Fix: "python ABS/PATH/TO/ipython.py" fails
706 706 * :ghpull:`3301`: allow python3 tests without python installed
707 707 * :ghpull:`3282`: allow view.map to work with a few more things
708 708 * :ghpull:`3284`: remove `ipython.py` entry point
709 709 * :ghpull:`3281`: fix ignored IOPub messages with no parent
710 710 * :ghpull:`3275`: improve submodule messages / git hooks
711 711 * :ghpull:`3239`: Allow "x" icon and esc key to close pager in notebook
712 712 * :ghpull:`3290`: Improved heartbeat controller to engine monitoring for long running tasks
713 713 * :ghpull:`3142`: Better error message when CWD doesn't exist on startup
714 714 * :ghpull:`3066`: Add support for relative import to %run -m (fixes #2727)
715 715 * :ghpull:`3269`: protect highlight.js against unknown languages
716 716 * :ghpull:`3267`: add missing return
717 717 * :ghpull:`3101`: use marked / highlight.js instead of pagedown and prettify
718 718 * :ghpull:`3264`: use https url for submodule
719 719 * :ghpull:`3263`: fix set_last_checkpoint when no checkpoint
720 720 * :ghpull:`3258`: Fix submodule location in setup.py
721 721 * :ghpull:`3254`: fix a few URLs from previous PR
722 722 * :ghpull:`3240`: remove js components from the repo
723 723 * :ghpull:`3158`: IPEP 15: autosave the notebook
724 724 * :ghpull:`3252`: move images out of _static folder into _images
725 725 * :ghpull:`3251`: Fix for cell magics in Qt console
726 726 * :ghpull:`3250`: Added a simple __html__() method to the HTML class
727 727 * :ghpull:`3249`: remove copy of sphinx inheritance_diagram.py
728 728 * :ghpull:`3235`: Remove the unused print notebook view
729 729 * :ghpull:`3238`: Improve the design of the tab completion UI
730 730 * :ghpull:`3242`: Make changes of Application.log_format effective
731 731 * :ghpull:`3219`: Workaround so only one CTRL-C is required for a new prompt in --gui=qt
732 732 * :ghpull:`3190`: allow formatters to specify metadata
733 733 * :ghpull:`3231`: improve discovery of public IPs
734 734 * :ghpull:`3233`: check prefixes for swallowing kernel args
735 735 * :ghpull:`3234`: Removing old autogrow JS code.
736 736 * :ghpull:`3232`: Update to CodeMirror 3 and start to ship our components
737 737 * :ghpull:`3229`: The HTML output type accidentally got removed from the OutputArea.
738 738 * :ghpull:`3228`: Typo in IPython.Parallel documentation
739 739 * :ghpull:`3226`: Text in rename dialog was way too big - making it <p>.
740 740 * :ghpull:`3225`: Removing old restuctured text handler and web service.
741 741 * :ghpull:`3222`: make BlockingKernelClient the default Client
742 742 * :ghpull:`3223`: add missing mathjax_url to new settings dict
743 743 * :ghpull:`3089`: add stdin to the notebook
744 744 * :ghpull:`3221`: Remove references to HTMLCell (dead code)
745 745 * :ghpull:`3205`: add ignored ``*args`` to HasTraits constructor
746 746 * :ghpull:`3088`: cleanup IPython handler settings
747 747 * :ghpull:`3201`: use much faster regexp for ansi coloring
748 748 * :ghpull:`3220`: avoid race condition in profile creation
749 749 * :ghpull:`3011`: IPEP 12: add KernelClient
750 750 * :ghpull:`3217`: informative error when trying to load directories
751 751 * :ghpull:`3174`: Simple class
752 752 * :ghpull:`2979`: CM configurable Take 2
753 753 * :ghpull:`3215`: Updates storemagic extension to allow for specifying variable name to load
754 754 * :ghpull:`3181`: backport If-Modified-Since fix from tornado
755 755 * :ghpull:`3200`: IFrame (VimeoVideo, ScribdDocument, ...)
756 756 * :ghpull:`3186`: Fix small inconsistency in nbconvert: etype -> ename
757 757 * :ghpull:`3212`: Fix issue #2563, "core.profiledir.check_startup_dir() doesn't work inside py2exe'd installation"
758 758 * :ghpull:`3211`: Fix inheritance_diagram Sphinx extension for Sphinx 1.2
759 759 * :ghpull:`3208`: Update link to extensions index
760 760 * :ghpull:`3203`: Separate InputSplitter for transforming whole cells
761 761 * :ghpull:`3189`: Improve completer
762 762 * :ghpull:`3194`: finish up PR #3116
763 763 * :ghpull:`3188`: Add new keycodes
764 764 * :ghpull:`2695`: Key the root modules cache by sys.path entries.
765 765 * :ghpull:`3182`: clarify %%file docstring
766 766 * :ghpull:`3163`: BUG: Fix the set and frozenset pretty printer to handle the empty case correctly
767 767 * :ghpull:`3180`: better UsageError for cell magic with no body
768 768 * :ghpull:`3184`: Cython cache
769 769 * :ghpull:`3175`: Added missing s
770 770 * :ghpull:`3173`: Little bits of documentation cleanup
771 771 * :ghpull:`2635`: Improve Windows start menu shortcuts (#2)
772 772 * :ghpull:`3172`: Add missing import in IPython parallel magics example
773 773 * :ghpull:`3170`: default application logger shouldn't propagate
774 774 * :ghpull:`3159`: Autocompletion for zsh
775 775 * :ghpull:`3105`: move DEFAULT_STATIC_FILES_PATH to IPython.html
776 776 * :ghpull:`3144`: minor bower tweaks
777 777 * :ghpull:`3141`: Default color output for ls on OSX
778 778 * :ghpull:`3137`: fix dot syntax error in inheritance diagram
779 779 * :ghpull:`3072`: raise UnsupportedOperation on iostream.fileno()
780 780 * :ghpull:`3147`: Notebook support for a reverse proxy which handles SSL
781 781 * :ghpull:`3152`: make qtconsole size at startup configurable
782 782 * :ghpull:`3162`: adding stream kwarg to current.new_output
783 783 * :ghpull:`2981`: IPEP 10: kernel side filtering of display formats
784 784 * :ghpull:`3058`: add redirect handler for notebooks by name
785 785 * :ghpull:`3041`: support non-modules in @require
786 786 * :ghpull:`2447`: Stateful line transformers
787 787 * :ghpull:`3108`: fix some O(N) and O(N^2) operations in parallel.map
788 788 * :ghpull:`2791`: forward stdout from forked processes
789 789 * :ghpull:`3157`: use Python 3-style for pretty-printed sets
790 790 * :ghpull:`3148`: closes #3045, #3123 for tornado < version 3.0
791 791 * :ghpull:`3143`: minor heading-link tweaks
792 792 * :ghpull:`3136`: Strip useless ANSI escape codes in notebook
793 793 * :ghpull:`3126`: Prevent errors when pressing arrow keys in an empty notebook
794 794 * :ghpull:`3135`: quick dev installation instructions
795 795 * :ghpull:`2889`: Push pandas dataframes to R magic
796 796 * :ghpull:`3068`: Don't monkeypatch doctest during IPython startup.
797 797 * :ghpull:`3133`: fix argparse version check
798 798 * :ghpull:`3102`: set `spellcheck=false` in CodeCell inputarea
799 799 * :ghpull:`3064`: add anchors to heading cells
800 800 * :ghpull:`3097`: PyQt 4.10: use self._document = self.document()
801 801 * :ghpull:`3117`: propagate automagic change to shell
802 802 * :ghpull:`3118`: don't give up on weird os names
803 803 * :ghpull:`3115`: Fix example
804 804 * :ghpull:`2640`: fix quarantine/ipy_editors.py
805 805 * :ghpull:`3070`: Add info make target that was missing in old Sphinx
806 806 * :ghpull:`3082`: A few small patches to image handling
807 807 * :ghpull:`3078`: fix regular expression for detecting links in stdout
808 808 * :ghpull:`3054`: restore default behavior for automatic cluster size
809 809 * :ghpull:`3073`: fix ipython usage text
810 810 * :ghpull:`3083`: fix DisplayMagics.html docstring
811 811 * :ghpull:`3080`: noted sub_channel being renamed to iopub_channel
812 812 * :ghpull:`3079`: actually use IPKernelApp.kernel_class
813 813 * :ghpull:`3076`: Improve notebook.js documentation
814 814 * :ghpull:`3063`: add missing `%%html` magic
815 815 * :ghpull:`3075`: check for SIGUSR1 before using it, closes #3074
816 816 * :ghpull:`3051`: add width:100% to vbox for webkit / FF consistency
817 817 * :ghpull:`2999`: increase registration timeout
818 818 * :ghpull:`2997`: fix DictDB default size limit
819 819 * :ghpull:`3033`: on resume, print server info again
820 820 * :ghpull:`3062`: test double pyximport
821 821 * :ghpull:`3046`: cast kernel cwd to bytes on Python 2 on Windows
822 822 * :ghpull:`3038`: remove xml from notebook magic docstrings
823 823 * :ghpull:`3032`: fix time format to international time format
824 824 * :ghpull:`3022`: Fix test for Windows
825 825 * :ghpull:`3024`: changed instances of 'outout' to 'output' in alt texts
826 826 * :ghpull:`3013`: py3 workaround for reload in cythonmagic
827 827 * :ghpull:`2961`: time magic: shorten unnecessary output on windows
828 828 * :ghpull:`2987`: fix local files examples in markdown
829 829 * :ghpull:`2998`: fix css in .output_area pre
830 830 * :ghpull:`3003`: add $include /etc/inputrc to suggested ~/.inputrc
831 831 * :ghpull:`2957`: Refactor qt import logic. Fixes #2955
832 832 * :ghpull:`2994`: expanduser on %%file targets
833 833 * :ghpull:`2983`: fix run-all (that-> this)
834 834 * :ghpull:`2964`: fix count when testing composite error output
835 835 * :ghpull:`2967`: shows entire session history when only startsess is given
836 836 * :ghpull:`2942`: Move CM IPython theme out of codemirror folder
837 837 * :ghpull:`2929`: Cleanup cell insertion
838 838 * :ghpull:`2933`: Minordocupdate
839 839 * :ghpull:`2968`: fix notebook deletion.
840 840 * :ghpull:`2966`: Added assert msg to extract_hist_ranges()
841 841 * :ghpull:`2959`: Add command to trim the history database.
842 842 * :ghpull:`2681`: Don't enable pylab mode, when matplotlib is not importable
843 843 * :ghpull:`2901`: Fix inputhook_wx on osx
844 844 * :ghpull:`2871`: truncate potentially long CompositeErrors
845 845 * :ghpull:`2951`: use istype on lists/tuples
846 846 * :ghpull:`2946`: fix qtconsole history logic for end-of-line
847 847 * :ghpull:`2954`: fix logic for append_javascript
848 848 * :ghpull:`2941`: fix baseUrl
849 849 * :ghpull:`2903`: Specify toggle value on cell line number
850 850 * :ghpull:`2911`: display order in output area configurable
851 851 * :ghpull:`2897`: Dont rely on BaseProjectUrl data in body tag
852 852 * :ghpull:`2894`: Cm configurable
853 853 * :ghpull:`2927`: next release will be 1.0
854 854 * :ghpull:`2932`: Simplify using notebook static files from external code
855 855 * :ghpull:`2915`: added small config section to notebook docs page
856 856 * :ghpull:`2924`: safe_run_module: Silence SystemExit codes 0 and None.
857 857 * :ghpull:`2906`: Unpatch/Monkey patch CM
858 858 * :ghpull:`2921`: add menu item for undo delete cell
859 859 * :ghpull:`2917`: Don't add logging handler if one already exists.
860 860 * :ghpull:`2910`: Respect DB_IP and DB_PORT in mongodb tests
861 861 * :ghpull:`2926`: Don't die if stderr/stdout do not support set_parent() #2925
862 862 * :ghpull:`2885`: get monospace pager back
863 863 * :ghpull:`2876`: fix celltoolbar layout on FF
864 864 * :ghpull:`2904`: Skip remaining IPC test on Windows
865 865 * :ghpull:`2908`: fix last remaining KernelApp reference
866 866 * :ghpull:`2905`: fix a few remaining KernelApp/IPKernelApp changes
867 867 * :ghpull:`2900`: Don't assume test case for %time will finish in 0 time
868 868 * :ghpull:`2893`: exclude fabfile from tests
869 869 * :ghpull:`2884`: Correct import for kernelmanager on Windows
870 870 * :ghpull:`2882`: Utils cleanup
871 871 * :ghpull:`2883`: Don't call ast.fix_missing_locations unless the AST could have been modified
872 872 * :ghpull:`2855`: time(it) magic: Implement minutes/hour formatting and "%%time" cell magic
873 873 * :ghpull:`2874`: Empty cell warnings
874 874 * :ghpull:`2819`: tweak history prefix search (up/^p) in qtconsole
875 875 * :ghpull:`2868`: Import performance
876 876 * :ghpull:`2877`: minor css fixes
877 877 * :ghpull:`2880`: update examples docs with kernel move
878 878 * :ghpull:`2878`: Pass host environment on to kernel
879 879 * :ghpull:`2599`: func_kw_complete for builtin and cython with embededsignature=True using docstring
880 880 * :ghpull:`2792`: Add key "unique" to history_request protocol
881 881 * :ghpull:`2872`: fix payload keys
882 882 * :ghpull:`2869`: Fixing styling of toolbar selects on FF.
883 883 * :ghpull:`2708`: Less css
884 884 * :ghpull:`2854`: Move kernel code into IPython.kernel
885 885 * :ghpull:`2864`: Fix %run -t -N<N> TypeError
886 886 * :ghpull:`2852`: future pyzmq compatibility
887 887 * :ghpull:`2863`: whatsnew/version0.9.txt: Fix '~./ipython' -> '~/.ipython' typo
888 888 * :ghpull:`2861`: add missing KernelManager to ConsoleApp class list
889 889 * :ghpull:`2850`: Consolidate host IP detection in utils.localinterfaces
890 890 * :ghpull:`2859`: Correct docstring of ipython.py
891 891 * :ghpull:`2831`: avoid string version comparisons in external.qt
892 892 * :ghpull:`2844`: this should address the failure in #2732
893 893 * :ghpull:`2849`: utils/data: Use list comprehension for uniq_stable()
894 894 * :ghpull:`2839`: add jinja to install docs / setup.py
895 895 * :ghpull:`2841`: Miscellaneous docs fixes
896 896 * :ghpull:`2811`: Still more KernelManager cleanup
897 897 * :ghpull:`2820`: add '=' to greedy completer delims
898 898 * :ghpull:`2818`: log user tracebacks in the kernel (INFO-level)
899 899 * :ghpull:`2828`: Clean up notebook Javascript
900 900 * :ghpull:`2829`: avoid comparison error in dictdb hub history
901 901 * :ghpull:`2830`: BUG: Opening parenthesis after non-callable raises ValueError
902 902 * :ghpull:`2718`: try to fallback to pysqlite2.dbapi2 as sqlite3 in core.history
903 903 * :ghpull:`2816`: in %edit, don't save "last_call" unless last call succeeded
904 904 * :ghpull:`2817`: change ol format order
905 905 * :ghpull:`2537`: Organize example notebooks
906 906 * :ghpull:`2815`: update release/authors
907 907 * :ghpull:`2808`: improve patience for slow Hub in client tests
908 908 * :ghpull:`2812`: remove nonfunctional `-la` short arg in cython magic
909 909 * :ghpull:`2810`: remove dead utils.upgradedir
910 910 * :ghpull:`1671`: __future__ environments
911 911 * :ghpull:`2804`: skip ipc tests on Windows
912 912 * :ghpull:`2789`: Fixing styling issues with CellToolbar.
913 913 * :ghpull:`2805`: fix KeyError creating ZMQStreams in notebook
914 914 * :ghpull:`2775`: General cleanup of kernel manager code.
915 915 * :ghpull:`2340`: Initial Code to reduce parallel.Client caching
916 916 * :ghpull:`2799`: Exit code
917 917 * :ghpull:`2800`: use `type(obj) is cls` as switch when canning
918 918 * :ghpull:`2801`: Fix a breakpoint bug
919 919 * :ghpull:`2795`: Remove outdated code from extensions.autoreload
920 920 * :ghpull:`2796`: P3K: fix cookie parsing under Python 3.x (+ duplicate import is removed)
921 921 * :ghpull:`2724`: In-process kernel support (take 3)
922 922 * :ghpull:`2687`: [WIP] Metaui slideshow
923 923 * :ghpull:`2788`: Chrome frame awareness
924 924 * :ghpull:`2649`: Add version_request/reply messaging protocol
925 925 * :ghpull:`2753`: add `%%px --local` for local execution
926 926 * :ghpull:`2783`: Prefilter shouldn't touch execution_count
927 927 * :ghpull:`2333`: UI For Metadata
928 928 * :ghpull:`2396`: create a ipynbv3 json schema and a validator
929 929 * :ghpull:`2757`: check for complete pyside presence before trying to import
930 930 * :ghpull:`2782`: Allow the %run magic with '-b' to specify a file.
931 931 * :ghpull:`2778`: P3K: fix DeprecationWarning under Python 3.x
932 932 * :ghpull:`2776`: remove non-functional View.kill method
933 933 * :ghpull:`2755`: can interactively defined classes
934 934 * :ghpull:`2774`: Removing unused code in the notebook MappingKernelManager.
935 935 * :ghpull:`2773`: Fixed minor typo causing AttributeError to be thrown.
936 936 * :ghpull:`2609`: Add 'unique' option to history_request messaging protocol
937 937 * :ghpull:`2769`: Allow shutdown when no engines are registered
938 938 * :ghpull:`2766`: Define __file__ when we %edit a real file.
939 939 * :ghpull:`2476`: allow %edit <variable> to work when interactively defined
940 940 * :ghpull:`2763`: Reset readline delimiters after loading rmagic.
941 941 * :ghpull:`2460`: Better handling of `__file__` when running scripts.
942 942 * :ghpull:`2617`: Fix for `units` argument. Adds a `res` argument.
943 943 * :ghpull:`2738`: Unicode content crashes the pager (console)
944 944 * :ghpull:`2749`: Tell Travis CI to test on Python 3.3 as well
945 945 * :ghpull:`2744`: Don't show 'try %paste' message while using magics
946 946 * :ghpull:`2728`: shift tab for tooltip
947 947 * :ghpull:`2741`: Add note to `%cython` Black-Scholes example warning of missing erf.
948 948 * :ghpull:`2743`: BUG: Octavemagic inline plots not working on Windows: Fixed
949 949 * :ghpull:`2740`: Following #2737 this error is now a name error
950 950 * :ghpull:`2737`: Rmagic: error message when moving an non-existant variable from python to R
951 951 * :ghpull:`2723`: diverse fixes for project url
952 952 * :ghpull:`2731`: %Rpush: Look for variables in the local scope first.
953 953 * :ghpull:`2544`: Infinite loop when multiple debuggers have been attached.
954 954 * :ghpull:`2726`: Add qthelp docs creation
955 955 * :ghpull:`2730`: added blockquote CSS
956 956 * :ghpull:`2729`: Fix Read the doc build, Again
957 957 * :ghpull:`2446`: [alternate 2267] Offline mathjax
958 958 * :ghpull:`2716`: remove unexisting headings level
959 959 * :ghpull:`2717`: One liner to fix debugger printing stack traces when lines of context are larger than source.
960 960 * :ghpull:`2713`: Doc bugfix: user_ns is not an attribute of Magic objects.
961 961 * :ghpull:`2690`: Fix 'import '... completion for py3 & egg files.
962 962 * :ghpull:`2691`: Document OpenMP in %%cython magic
963 963 * :ghpull:`2699`: fix jinja2 rendering for password protected notebooks
964 964 * :ghpull:`2700`: Skip notebook testing if jinja2 is not available.
965 965 * :ghpull:`2692`: Add %%cython magics to generated documentation.
966 966 * :ghpull:`2685`: Fix pretty print of types when `__module__` is not available.
967 967 * :ghpull:`2686`: Fix tox.ini
968 968 * :ghpull:`2604`: Backslashes are misinterpreted as escape-sequences by the R-interpreter.
969 969 * :ghpull:`2689`: fix error in doc (arg->kwarg) and pep-8
970 970 * :ghpull:`2683`: for downloads, replaced window.open with window.location.assign
971 971 * :ghpull:`2659`: small bugs in js are fixed
972 972 * :ghpull:`2363`: Refactor notebook templates to use Jinja2
973 973 * :ghpull:`2662`: qtconsole: wrap argument list in tooltip to match width of text body
974 974 * :ghpull:`2328`: addition of classes to generate a link or list of links from files local to the IPython HTML notebook
975 975 * :ghpull:`2668`: pylab_not_importable: Catch all exceptions, not just RuntimeErrors.
976 976 * :ghpull:`2663`: Fix issue #2660: parsing of help and version arguments
977 977 * :ghpull:`2656`: Fix irunner tests when $PYTHONSTARTUP is set
978 978 * :ghpull:`2312`: Add bracket matching to code cells in notebook
979 979 * :ghpull:`2571`: Start to document Javascript
980 980 * :ghpull:`2641`: undefinied that -> this
981 981 * :ghpull:`2638`: Fix %paste in Python 3 on Mac
982 982 * :ghpull:`2301`: Ast transfomers
983 983 * :ghpull:`2616`: Revamp API docs
984 984 * :ghpull:`2572`: Make 'Paste Above' the default paste behavior.
985 985 * :ghpull:`2574`: Fix #2244
986 986 * :ghpull:`2582`: Fix displaying history when output cache is disabled.
987 987 * :ghpull:`2591`: Fix for Issue #2584
988 988 * :ghpull:`2526`: Don't kill paramiko tunnels when receiving ^C
989 989 * :ghpull:`2559`: Add psource, pfile, pinfo2 commands to ipdb.
990 990 * :ghpull:`2546`: use 4 Pythons to build 4 Windows installers
991 991 * :ghpull:`2561`: Fix display of plain text containing multiple carriage returns before line feed
992 992 * :ghpull:`2549`: Add a simple 'undo' for cell deletion.
993 993 * :ghpull:`2525`: Add event to kernel execution/shell reply.
994 994 * :ghpull:`2554`: Avoid stopping in ipdb until we reach the main script.
995 995 * :ghpull:`2404`: Option to limit search result in history magic command
996 996 * :ghpull:`2294`: inputhook_qt4: Use QEventLoop instead of starting up the QCoreApplication
997 997 * :ghpull:`2233`: Refactored Drag and Drop Support in Qt Console
998 998 * :ghpull:`1747`: switch between hsplit and vsplit paging (request for feedback)
999 999 * :ghpull:`2530`: Adding time offsets to the video
1000 1000 * :ghpull:`2542`: Allow starting IPython as `python -m IPython`.
1001 1001 * :ghpull:`2534`: Do not unescape backslashes in Windows (shellglob)
1002 1002 * :ghpull:`2517`: Improved MathJax, bug fixes
1003 1003 * :ghpull:`2511`: trigger default remote_profile_dir when profile_dir is set
1004 1004 * :ghpull:`2491`: color is supported in ironpython
1005 1005 * :ghpull:`2462`: Track which extensions are loaded
1006 1006 * :ghpull:`2464`: Locate URLs in text output and convert them to hyperlinks.
1007 1007 * :ghpull:`2490`: add ZMQInteractiveShell to IPEngineApp class list
1008 1008 * :ghpull:`2498`: Don't catch tab press when something selected
1009 1009 * :ghpull:`2527`: Run All Above and Run All Below
1010 1010 * :ghpull:`2513`: add GitHub uploads to release script
1011 1011 * :ghpull:`2529`: Windows aware tests for shellglob
1012 1012 * :ghpull:`2478`: Fix doctest_run_option_parser for Windows
1013 1013 * :ghpull:`2519`: clear In[ ] prompt numbers again
1014 1014 * :ghpull:`2467`: Clickable links
1015 1015 * :ghpull:`2500`: Add `encoding` attribute to `OutStream` class.
1016 1016 * :ghpull:`2349`: ENH: added StackExchange-style MathJax filtering
1017 1017 * :ghpull:`2503`: Fix traceback handling of SyntaxErrors without line numbers.
1018 1018 * :ghpull:`2492`: add missing 'qtconsole' extras_require
1019 1019 * :ghpull:`2480`: Add deprecation warnings for sympyprinting
1020 1020 * :ghpull:`2334`: Make the ipengine monitor the ipcontroller heartbeat and die if the ipcontroller goes down
1021 1021 * :ghpull:`2479`: use new _winapi instead of removed _subprocess
1022 1022 * :ghpull:`2474`: fix bootstrap name conflicts
1023 1023 * :ghpull:`2469`: Treat __init__.pyc same as __init__.py in module_list
1024 1024 * :ghpull:`2165`: Add -g option to %run to glob expand arguments
1025 1025 * :ghpull:`2468`: Tell git to ignore __pycache__ directories.
1026 1026 * :ghpull:`2421`: Some notebook tweaks.
1027 1027 * :ghpull:`2291`: Remove old plugin system
1028 1028 * :ghpull:`2127`: Ability to build toolbar in JS
1029 1029 * :ghpull:`2445`: changes for ironpython
1030 1030 * :ghpull:`2420`: Pass ipython_dir to __init__() method of TerminalInteractiveShell's superclass.
1031 1031 * :ghpull:`2432`: Revert #1831, the `__file__` injection in safe_execfile / safe_execfile_ipy.
1032 1032 * :ghpull:`2216`: Autochange highlight with cell magics
1033 1033 * :ghpull:`1946`: Add image message handler in ZMQTerminalInteractiveShell
1034 1034 * :ghpull:`2424`: skip find_cmd when setting up script magics
1035 1035 * :ghpull:`2389`: Catch sqlite DatabaseErrors in more places when reading the history database
1036 1036 * :ghpull:`2395`: Don't catch ImportError when trying to unpack module functions
1037 1037 * :ghpull:`1868`: enable IPC transport for kernels
1038 1038 * :ghpull:`2437`: don't let log cleanup prevent engine start
1039 1039 * :ghpull:`2441`: `sys.maxsize` is the maximum length of a container.
1040 1040 * :ghpull:`2442`: allow iptest to be interrupted
1041 1041 * :ghpull:`2240`: fix message built for engine dying during task
1042 1042 * :ghpull:`2369`: Block until kernel termination after sending a kill signal
1043 1043 * :ghpull:`2439`: Py3k: Octal (0777 -> 0o777)
1044 1044 * :ghpull:`2326`: Detachable pager in notebook.
1045 1045 * :ghpull:`2377`: Fix installation of man pages in Python 3
1046 1046 * :ghpull:`2407`: add IPython version to message headers
1047 1047 * :ghpull:`2408`: Fix Issue #2366
1048 1048 * :ghpull:`2405`: clarify TaskScheduler.hwm doc
1049 1049 * :ghpull:`2399`: IndentationError display
1050 1050 * :ghpull:`2400`: Add scroll_to_cell(cell_number) to the notebook
1051 1051 * :ghpull:`2401`: unmock read-the-docs modules
1052 1052 * :ghpull:`2311`: always perform requested trait assignments
1053 1053 * :ghpull:`2393`: New option `n` to limit history search hits
1054 1054 * :ghpull:`2386`: Adapt inline backend to changes in matplotlib
1055 1055 * :ghpull:`2392`: Remove suspicious double quote
1056 1056 * :ghpull:`2387`: Added -L library search path to cythonmagic cell magic
1057 1057 * :ghpull:`2370`: qtconsole: Create a prompt newline by inserting a new block (w/o formatting)
1058 1058 * :ghpull:`1715`: Fix for #1688, traceback-unicode issue
1059 1059 * :ghpull:`2378`: use Singleton.instance() for embed() instead of manual global
1060 1060 * :ghpull:`2373`: fix missing imports in core.interactiveshell
1061 1061 * :ghpull:`2368`: remove notification widget leftover
1062 1062 * :ghpull:`2327`: Parallel: Support get/set of nested objects in view (e.g. dv['a.b'])
1063 1063 * :ghpull:`2362`: Clean up ProgressBar class in example notebook
1064 1064 * :ghpull:`2346`: Extra xterm identification in set_term_title
1065 1065 * :ghpull:`2352`: Notebook: Store the username in a cookie whose name is unique.
1066 1066 * :ghpull:`2358`: add backport_pr to tools
1067 1067 * :ghpull:`2365`: fix names of notebooks for download/save
1068 1068 * :ghpull:`2364`: make clients use 'location' properly (fixes #2361)
1069 1069 * :ghpull:`2354`: Refactor notebook templates to use Jinja2
1070 1070 * :ghpull:`2339`: add bash completion example
1071 1071 * :ghpull:`2345`: Remove references to 'version' no longer in argparse. Github issue #2343.
1072 1072 * :ghpull:`2347`: adjust division error message checking to account for Python 3
1073 1073 * :ghpull:`2305`: RemoteError._render_traceback_ calls self.render_traceback
1074 1074 * :ghpull:`2338`: Normalize line endings for ipexec_validate, fix for #2315.
1075 1075 * :ghpull:`2192`: Introduce Notification Area
1076 1076 * :ghpull:`2329`: Better error messages for common magic commands.
1077 1077 * :ghpull:`2337`: ENH: added StackExchange-style MathJax filtering
1078 1078 * :ghpull:`2331`: update css for qtconsole in doc
1079 1079 * :ghpull:`2317`: adding cluster_id to parallel.Client.__init__
1080 1080 * :ghpull:`2130`: Add -l option to %R magic to allow passing in of local namespace
1081 1081 * :ghpull:`2196`: Fix for bad command line argument to latex
1082 1082 * :ghpull:`2300`: bug fix: was crashing when sqlite3 is not installed
1083 1083 * :ghpull:`2184`: Expose store_history to execute_request messages.
1084 1084 * :ghpull:`2308`: Add welcome_message option to enable_pylab
1085 1085 * :ghpull:`2302`: Fix variable expansion on 'self'
1086 1086 * :ghpull:`2299`: Remove code from prefilter that duplicates functionality in inputsplitter
1087 1087 * :ghpull:`2295`: allow pip install from github repository directly
1088 1088 * :ghpull:`2280`: fix SSH passwordless check for OpenSSH
1089 1089 * :ghpull:`2290`: nbmanager
1090 1090 * :ghpull:`2288`: s/assertEquals/assertEqual (again)
1091 1091 * :ghpull:`2287`: Removed outdated dev docs.
1092 1092 * :ghpull:`2218`: Use redirect for new notebooks
1093 1093 * :ghpull:`2277`: nb: up/down arrow keys move to begin/end of line at top/bottom of cell
1094 1094 * :ghpull:`2045`: Refactoring notebook managers and adding Azure backed storage.
1095 1095 * :ghpull:`2271`: use display instead of send_figure in inline backend hooks
1096 1096 * :ghpull:`2278`: allow disabling SQLite history
1097 1097 * :ghpull:`2225`: Add "--annotate" option to `%%cython` magic.
1098 1098 * :ghpull:`2246`: serialize individual args/kwargs rather than the containers
1099 1099 * :ghpull:`2274`: CLN: Use name to id mapping of notebooks instead of searching.
1100 1100 * :ghpull:`2270`: SSHLauncher tweaks
1101 1101 * :ghpull:`2269`: add missing location when disambiguating controller IP
1102 1102 * :ghpull:`2263`: Allow docs to build on http://readthedocs.io/
1103 1103 * :ghpull:`2256`: Adding data publication example notebook.
1104 1104 * :ghpull:`2255`: better flush iopub with AsyncResults
1105 1105 * :ghpull:`2261`: Fix: longest_substr([]) -> ''
1106 1106 * :ghpull:`2260`: fix mpr again
1107 1107 * :ghpull:`2242`: Document globbing in `%history -g <pattern>`.
1108 1108 * :ghpull:`2250`: fix html in notebook example
1109 1109 * :ghpull:`2245`: Fix regression in embed() from pull-request #2096.
1110 1110 * :ghpull:`2248`: track sha of master in test_pr messages
1111 1111 * :ghpull:`2238`: Fast tests
1112 1112 * :ghpull:`2211`: add data publication message
1113 1113 * :ghpull:`2236`: minor test_pr tweaks
1114 1114 * :ghpull:`2231`: Improve Image format validation and add html width,height
1115 1115 * :ghpull:`2232`: Reapply monkeypatch to inspect.findsource()
1116 1116 * :ghpull:`2235`: remove spurious print statement from setupbase.py
1117 1117 * :ghpull:`2222`: adjust how canning deals with import strings
1118 1118 * :ghpull:`2224`: fix css typo
1119 1119 * :ghpull:`2223`: Custom tracebacks
1120 1120 * :ghpull:`2214`: use KernelApp.exec_lines/files in IPEngineApp
1121 1121 * :ghpull:`2199`: Wrap JS published by %%javascript in try/catch
1122 1122 * :ghpull:`2212`: catch errors in markdown javascript
1123 1123 * :ghpull:`2190`: Update code mirror 2.22 to 2.32
1124 1124 * :ghpull:`2200`: documentation build broken in bb429da5b
1125 1125 * :ghpull:`2194`: clean nan/inf in json_clean
1126 1126 * :ghpull:`2198`: fix mpr for earlier git version
1127 1127 * :ghpull:`2175`: add FileFindHandler for Notebook static files
1128 1128 * :ghpull:`1990`: can func_defaults
1129 1129 * :ghpull:`2069`: start improving serialization in parallel code
1130 1130 * :ghpull:`2202`: Create a unique & temporary IPYTHONDIR for each testing group.
1131 1131 * :ghpull:`2204`: Work around lack of os.kill in win32.
1132 1132 * :ghpull:`2148`: win32 iptest: Use subprocess.Popen() instead of os.system().
1133 1133 * :ghpull:`2179`: Pylab switch
1134 1134 * :ghpull:`2124`: Add an API for registering magic aliases.
1135 1135 * :ghpull:`2169`: ipdb: pdef, pdoc, pinfo magics all broken
1136 1136 * :ghpull:`2174`: Ensure consistent indentation in `%magic`.
1137 1137 * :ghpull:`1930`: add size-limiting to the DictDB backend
1138 1138 * :ghpull:`2189`: Fix IPython.lib.latextools for Python 3
1139 1139 * :ghpull:`2186`: removed references to h5py dependence in octave magic documentation
1140 1140 * :ghpull:`2183`: Include the kernel object in the event object passed to kernel events
1141 1141 * :ghpull:`2185`: added test for %store, fixed storemagic
1142 1142 * :ghpull:`2138`: Use breqn.sty in dvipng backend if possible
1143 1143 * :ghpull:`2182`: handle undefined param in notebooklist
1144 1144 * :ghpull:`1831`: fix #1814 set __file__ when running .ipy files
1145 1145 * :ghpull:`2051`: Add a metadata attribute to messages
1146 1146 * :ghpull:`1471`: simplify IPython.parallel connections and enable Controller Resume
1147 1147 * :ghpull:`2181`: add %%javascript, %%svg, and %%latex display magics
1148 1148 * :ghpull:`2116`: different images in 00_notebook-tour
1149 1149 * :ghpull:`2092`: %prun: Restore `stats.stream` after running `print_stream`.
1150 1150 * :ghpull:`2159`: show message on notebook list if server is unreachable
1151 1151 * :ghpull:`2176`: fix git mpr
1152 1152 * :ghpull:`2152`: [qtconsole] Namespace not empty at startup
1153 1153 * :ghpull:`2177`: remove numpy install from travis/tox scripts
1154 1154 * :ghpull:`2090`: New keybinding for code cell execution + cell insertion
1155 1155 * :ghpull:`2160`: Updating the parallel options pricing example
1156 1156 * :ghpull:`2168`: expand line in cell magics
1157 1157 * :ghpull:`2170`: Fix tab completion with IPython.embed_kernel().
1158 1158 * :ghpull:`2096`: embed(): Default to the future compiler flags of the calling frame.
1159 1159 * :ghpull:`2163`: fix 'remote_profie_dir' typo in SSH launchers
1160 1160 * :ghpull:`2158`: [2to3 compat ] Tuple params in func defs
1161 1161 * :ghpull:`2089`: Fix unittest DeprecationWarnings
1162 1162 * :ghpull:`2142`: Refactor test_pr.py
1163 1163 * :ghpull:`2140`: 2to3: Apply `has_key` fixer.
1164 1164 * :ghpull:`2131`: Add option append (-a) to %save
1165 1165 * :ghpull:`2117`: use explicit url in notebook example
1166 1166 * :ghpull:`2133`: Tell git that ``*.py`` files contain Python code, for use in word-diffs.
1167 1167 * :ghpull:`2134`: Apply 2to3 `next` fix.
1168 1168 * :ghpull:`2126`: ipcluster broken with any batch launcher (PBS/LSF/SGE)
1169 1169 * :ghpull:`2104`: Windows make file for Sphinx documentation
1170 1170 * :ghpull:`2074`: Make BG color of inline plot configurable
1171 1171 * :ghpull:`2123`: BUG: Look up the `_repr_pretty_` method on the class within the MRO rath...
1172 1172 * :ghpull:`2100`: [in progress] python 2 and 3 compatibility without 2to3, second try
1173 1173 * :ghpull:`2128`: open notebook copy in different tabs
1174 1174 * :ghpull:`2073`: allows password and prefix for notebook
1175 1175 * :ghpull:`1993`: Print View
1176 1176 * :ghpull:`2086`: re-aliad %ed to %edit in qtconsole
1177 1177 * :ghpull:`2110`: Fixes and improvements to the input splitter
1178 1178 * :ghpull:`2101`: fix completer deletting newline
1179 1179 * :ghpull:`2102`: Fix logging on interactive shell.
1180 1180 * :ghpull:`2088`: Fix (some) Python 3.2 ResourceWarnings
1181 1181 * :ghpull:`2064`: conform to pep 3110
1182 1182 * :ghpull:`2076`: Skip notebook 'static' dir in test suite.
1183 1183 * :ghpull:`2063`: Remove umlauts so py3 installations on LANG=C systems succeed.
1184 1184 * :ghpull:`2068`: record sysinfo in sdist
1185 1185 * :ghpull:`2067`: update tools/release_windows.py
1186 1186 * :ghpull:`2065`: Fix parentheses typo
1187 1187 * :ghpull:`2062`: Remove duplicates and auto-generated files from repo.
1188 1188 * :ghpull:`2061`: use explicit tuple in exception
1189 1189 * :ghpull:`2060`: change minus to \- or \(hy in manpages
1190 1190
1191 1191 Issues (691):
1192 1192
1193 1193 * :ghissue:`3940`: Install process documentation overhaul
1194 1194 * :ghissue:`3946`: The PDF option for `--post` should work with lowercase
1195 1195 * :ghissue:`3957`: Notebook help page broken in Firefox
1196 1196 * :ghissue:`3894`: nbconvert test failure
1197 1197 * :ghissue:`3887`: 1.0.0a1 shows blank screen in both firefox and chrome (windows 7)
1198 1198 * :ghissue:`3703`: `nbconvert`: Output options -- names and documentataion
1199 1199 * :ghissue:`3931`: Tab completion not working during debugging in the notebook
1200 1200 * :ghissue:`3936`: Ipcluster plugin is not working with Ipython 1.0dev
1201 1201 * :ghissue:`3941`: IPython Notebook kernel crash on Win7x64
1202 1202 * :ghissue:`3926`: Ending Notebook renaming dialog with return creates new-line
1203 1203 * :ghissue:`3932`: Incorrect empty docstring
1204 1204 * :ghissue:`3928`: Passing variables to script from the workspace
1205 1205 * :ghissue:`3774`: Notebooks with spaces in their names breaks nbconvert latex graphics
1206 1206 * :ghissue:`3916`: tornado needs its own check
1207 1207 * :ghissue:`3915`: Link to Parallel examples "found on GitHub" broken in docs
1208 1208 * :ghissue:`3895`: Keyboard shortcuts box in notebook doesn't fit the screen
1209 1209 * :ghissue:`3912`: IPython.utils fails automated test for RC1 1.0.0
1210 1210 * :ghissue:`3636`: Code cell missing highlight on load
1211 1211 * :ghissue:`3897`: under Windows, "ipython3 nbconvert "C:/blabla/first_try.ipynb" --to latex --post PDF" POST processing action fails because of a bad parameter
1212 1212 * :ghissue:`3900`: python3 install syntax errors (OS X 10.8.4)
1213 1213 * :ghissue:`3899`: nbconvert to latex fails on notebooks with spaces in file name
1214 1214 * :ghissue:`3881`: Temporary Working Directory Test Fails
1215 1215 * :ghissue:`2750`: A way to freeze code cells in the notebook
1216 1216 * :ghissue:`3893`: Resize Local Image Files in Notebook doesn't work
1217 1217 * :ghissue:`3823`: nbconvert on windows: tex and paths
1218 1218 * :ghissue:`3885`: under Windows, "ipython3 nbconvert "C:/blabla/first_try.ipynb" --to latex" write "\" instead of "/" to reference file path in the .tex file
1219 1219 * :ghissue:`3889`: test_qt fails due to assertion error 'qt4' != 'qt'
1220 1220 * :ghissue:`3890`: double post, disregard this issue
1221 1221 * :ghissue:`3689`: nbconvert, remaining tests
1222 1222 * :ghissue:`3874`: Up/Down keys don't work to "Search previous command history" (besides Ctrl-p/Ctrl-n)
1223 1223 * :ghissue:`3853`: CodeMirror locks up in the notebook
1224 1224 * :ghissue:`3862`: can only connect to an ipcluster started with v1.0.0-dev (master branch) using an older ipython (v0.13.2), but cannot connect using ipython (v1.0.0-dev)
1225 1225 * :ghissue:`3869`: custom css not working.
1226 1226 * :ghissue:`2960`: Keyboard shortcuts
1227 1227 * :ghissue:`3795`: ipcontroller process goes to 100% CPU, ignores connection requests
1228 1228 * :ghissue:`3553`: Ipython and pylab crashes in windows and canopy
1229 1229 * :ghissue:`3837`: Cannot set custom mathjax url, crash notebook server.
1230 1230 * :ghissue:`3808`: "Naming" releases ?
1231 1231 * :ghissue:`2431`: TypeError: must be string without null bytes, not str
1232 1232 * :ghissue:`3856`: `?` at end of comment causes line to execute
1233 1233 * :ghissue:`3731`: nbconvert: add logging for the different steps of nbconvert
1234 1234 * :ghissue:`3835`: Markdown cells do not render correctly when mathjax is disabled
1235 1235 * :ghissue:`3843`: nbconvert to rst: leftover "In[ ]"
1236 1236 * :ghissue:`3799`: nbconvert: Ability to specify name of output file
1237 1237 * :ghissue:`3726`: Document when IPython.start_ipython() should be used versus IPython.embed()
1238 1238 * :ghissue:`3778`: Add no more readonly view in what's new
1239 1239 * :ghissue:`3754`: No Print View in Notebook in 1.0dev
1240 1240 * :ghissue:`3798`: IPython 0.12.1 Crashes on autocompleting sqlalchemy.func.row_number properties
1241 1241 * :ghissue:`3811`: Opening notebook directly from the command line with multi-directory support installed
1242 1242 * :ghissue:`3775`: Annoying behavior when clicking on cell after execution (Ctrl+Enter)
1243 1243 * :ghissue:`3809`: Possible to add some bpython features?
1244 1244 * :ghissue:`3810`: Printing the contents of an image file messes up shell text
1245 1245 * :ghissue:`3702`: `nbconvert`: Default help message should be that of --help
1246 1246 * :ghissue:`3735`: Nbconvert 1.0.0a1 does not take into account the pdf extensions in graphs
1247 1247 * :ghissue:`3719`: Bad strftime format, for windows, in nbconvert exporter
1248 1248 * :ghissue:`3786`: Zmq errors appearing with `Ctrl-C` in console/qtconsole
1249 1249 * :ghissue:`3019`: disappearing scrollbar on tooltip in Chrome 24 on Ubuntu 12.04
1250 1250 * :ghissue:`3785`: ipdb completely broken in Qt console
1251 1251 * :ghissue:`3796`: Document the meaning of milestone/issues-tags for users.
1252 1252 * :ghissue:`3788`: Do not auto show tooltip if docstring empty.
1253 1253 * :ghissue:`1366`: [Web page] No link to front page from documentation
1254 1254 * :ghissue:`3739`: nbconvert (to slideshow) misses some of the math in markdown cells
1255 1255 * :ghissue:`3768`: increase and make timeout configurable in console completion.
1256 1256 * :ghissue:`3724`: ipcluster only running on one cpu
1257 1257 * :ghissue:`1592`: better message for unsupported nbformat
1258 1258 * :ghissue:`2049`: Can not stop "ipython kernel" on windows
1259 1259 * :ghissue:`3757`: Need direct entry point to given notebook
1260 1260 * :ghissue:`3745`: ImportError: cannot import name check_linecache_ipython
1261 1261 * :ghissue:`3701`: `nbconvert`: Final output file should be in same directory as input file
1262 1262 * :ghissue:`3738`: history -o works but history with -n produces identical results
1263 1263 * :ghissue:`3740`: error when attempting to run 'make' in docs directory
1264 1264 * :ghissue:`3737`: ipython nbconvert crashes with ValueError: Invalid format string.
1265 1265 * :ghissue:`3730`: nbconvert: unhelpful error when pandoc isn't installed
1266 1266 * :ghissue:`3718`: markdown cell cursor misaligned in notebook
1267 1267 * :ghissue:`3710`: mutiple input fields for %debug in the notebook after resetting the kernel
1268 1268 * :ghissue:`3713`: PyCharm has problems with IPython working inside PyPy created by virtualenv
1269 1269 * :ghissue:`3712`: Code completion: Complete on dictionary keys
1270 1270 * :ghissue:`3680`: --pylab and --matplotlib flag
1271 1271 * :ghissue:`3698`: nbconvert: Unicode error with minus sign
1272 1272 * :ghissue:`3693`: nbconvert does not process SVGs into PDFs
1273 1273 * :ghissue:`3688`: nbconvert, figures not extracting with Python 3.x
1274 1274 * :ghissue:`3542`: note new dependencies in docs / setup.py
1275 1275 * :ghissue:`2556`: [pagedown] do not target_blank anchor link
1276 1276 * :ghissue:`3684`: bad message when %pylab fails due import *other* than matplotlib
1277 1277 * :ghissue:`3682`: ipython notebook pylab inline import_all=False
1278 1278 * :ghissue:`3596`: MathjaxUtils race condition?
1279 1279 * :ghissue:`1540`: Comment/uncomment selection in notebook
1280 1280 * :ghissue:`2702`: frozen setup: permission denied for default ipython_dir
1281 1281 * :ghissue:`3672`: allow_none on Number-like traits.
1282 1282 * :ghissue:`2411`: add CONTRIBUTING.md
1283 1283 * :ghissue:`481`: IPython terminal issue with Qt4Agg on XP SP3
1284 1284 * :ghissue:`2664`: How to preserve user variables from import clashing?
1285 1285 * :ghissue:`3436`: enable_pylab(import_all=False) still imports np
1286 1286 * :ghissue:`2630`: lib.pylabtools.figsize : NameError when using Qt4Agg backend and %pylab magic.
1287 1287 * :ghissue:`3154`: Notebook: no event triggered when a Cell is created
1288 1288 * :ghissue:`3579`: Nbconvert: SVG are not transformed to PDF anymore
1289 1289 * :ghissue:`3604`: MathJax rendering problem in `%%latex` cell
1290 1290 * :ghissue:`3668`: AttributeError: 'BlockingKernelClient' object has no attribute 'started_channels'
1291 1291 * :ghissue:`3245`: SyntaxError: encoding declaration in Unicode string
1292 1292 * :ghissue:`3639`: %pylab inline in IPYTHON notebook throws "RuntimeError: Cannot activate multiple GUI eventloops"
1293 1293 * :ghissue:`3663`: frontend deprecation warnings
1294 1294 * :ghissue:`3661`: run -m not behaving like python -m
1295 1295 * :ghissue:`3597`: re-do PR #3531 - allow markdown in Header cell
1296 1296 * :ghissue:`3053`: Markdown in header cells is not rendered
1297 1297 * :ghissue:`3655`: IPython finding its way into pasted strings.
1298 1298 * :ghissue:`3620`: uncaught errors in HTML output
1299 1299 * :ghissue:`3646`: get_dict() error
1300 1300 * :ghissue:`3004`: `%load_ext rmagic` fails when legacy ipy_user_conf.py is installed (in ipython 0.13.1 / OSX 10.8)
1301 1301 * :ghissue:`3638`: setp() issue in ipython notebook with figure references
1302 1302 * :ghissue:`3634`: nbconvert reveal to pdf conversion ignores styling, prints only a single page.
1303 1303 * :ghissue:`1307`: Remove pyreadline workarounds, we now require pyreadline >= 1.7.1
1304 1304 * :ghissue:`3316`: find_cmd test failure on Windows
1305 1305 * :ghissue:`3494`: input() in notebook doesn't work in Python 3
1306 1306 * :ghissue:`3427`: Deprecate `$` as mathjax delimiter
1307 1307 * :ghissue:`3625`: Pager does not open from button
1308 1308 * :ghissue:`3149`: Miscellaneous small nbconvert feedback
1309 1309 * :ghissue:`3617`: 256 color escapes support
1310 1310 * :ghissue:`3609`: %pylab inline blows up for single process ipython
1311 1311 * :ghissue:`2934`: Publish the Interactive MPI Demo Notebook
1312 1312 * :ghissue:`3614`: ansi escapes broken in master (ls --color)
1313 1313 * :ghissue:`3610`: If you don't have markdown, python setup.py install says no pygments
1314 1314 * :ghissue:`3547`: %run modules clobber each other
1315 1315 * :ghissue:`3602`: import_item fails when one tries to use DottedObjectName instead of a string
1316 1316 * :ghissue:`3563`: Duplicate tab completions in the notebook
1317 1317 * :ghissue:`3599`: Problems trying to run IPython on python3 without installing...
1318 1318 * :ghissue:`2937`: too long completion in notebook
1319 1319 * :ghissue:`3479`: Write empty name for the notebooks
1320 1320 * :ghissue:`3505`: nbconvert: Failure in specifying user filter
1321 1321 * :ghissue:`1537`: think a bit about namespaces
1322 1322 * :ghissue:`3124`: Long multiline strings in Notebook
1323 1323 * :ghissue:`3464`: run -d message unclear
1324 1324 * :ghissue:`2706`: IPython 0.13.1 ignoring $PYTHONSTARTUP
1325 1325 * :ghissue:`3587`: LaTeX escaping bug in nbconvert when exporting to HTML
1326 1326 * :ghissue:`3213`: Long running notebook died with a coredump
1327 1327 * :ghissue:`3580`: Running ipython with pypy on windows
1328 1328 * :ghissue:`3573`: custom.js not working
1329 1329 * :ghissue:`3544`: IPython.lib test failure on Windows
1330 1330 * :ghissue:`3352`: Install Sphinx extensions
1331 1331 * :ghissue:`2971`: [notebook]user needs to press ctrl-c twice to stop notebook server should be put into terminal window
1332 1332 * :ghissue:`2413`: ipython3 qtconsole fails to install: ipython 0.13 has no such extra feature 'qtconsole'
1333 1333 * :ghissue:`2618`: documentation is incorrect for install process
1334 1334 * :ghissue:`2595`: mac 10.8 qtconsole export history
1335 1335 * :ghissue:`2586`: cannot store aliases
1336 1336 * :ghissue:`2714`: ipython qtconsole print unittest messages in console instead his own window.
1337 1337 * :ghissue:`2669`: cython magic failing to work with openmp.
1338 1338 * :ghissue:`3256`: Vagrant pandas instance of iPython Notebook does not respect additional plotting arguments
1339 1339 * :ghissue:`3010`: cython magic fail if cache dir is deleted while in session
1340 1340 * :ghissue:`2044`: prune unused names from parallel.error
1341 1341 * :ghissue:`1145`: Online help utility broken in QtConsole
1342 1342 * :ghissue:`3439`: Markdown links no longer open in new window (with change from pagedown to marked)
1343 1343 * :ghissue:`3476`: _margv for macros seems to be missing
1344 1344 * :ghissue:`3499`: Add reveal.js library (version 2.4.0) inside IPython
1345 1345 * :ghissue:`2771`: Wiki Migration to GitHub
1346 1346 * :ghissue:`2887`: ipcontroller purging some engines during connect
1347 1347 * :ghissue:`626`: Enable Resuming Controller
1348 1348 * :ghissue:`2824`: Kernel restarting after message "Kernel XXXX failed to respond to heartbeat"
1349 1349 * :ghissue:`2823`: %%cython magic gives ImportError: dlopen(long_file_name.so, 2): image not found
1350 1350 * :ghissue:`2891`: In IPython for Python 3, system site-packages comes before user site-packages
1351 1351 * :ghissue:`2928`: Add magic "watch" function (example)
1352 1352 * :ghissue:`2931`: Problem rendering pandas dataframe in Firefox for Windows
1353 1353 * :ghissue:`2939`: [notebook] Figure legend not shown in inline backend if ouside the box of the axes
1354 1354 * :ghissue:`2972`: [notebook] in Markdown mode, press Enter key at the end of <some http link>, the next line is indented unexpectly
1355 1355 * :ghissue:`3069`: Instructions for installing IPython notebook on Windows
1356 1356 * :ghissue:`3444`: Encoding problem: cannot use if user's name is not ascii?
1357 1357 * :ghissue:`3335`: Reenable bracket matching
1358 1358 * :ghissue:`3386`: Magic %paste not working in Python 3.3.2. TypeError: Type str doesn't support the buffer API
1359 1359 * :ghissue:`3543`: Exception shutting down kernel from notebook dashboard (0.13.1)
1360 1360 * :ghissue:`3549`: Codecell size changes with selection
1361 1361 * :ghissue:`3445`: Adding newlines in %%latex cell
1362 1362 * :ghissue:`3237`: [notebook] Can't close a notebook without errors
1363 1363 * :ghissue:`2916`: colon invokes auto(un)indent in markdown cells
1364 1364 * :ghissue:`2167`: Indent and dedent in htmlnotebook
1365 1365 * :ghissue:`3545`: Notebook save button icon not clear
1366 1366 * :ghissue:`3534`: nbconvert incompatible with Windows?
1367 1367 * :ghissue:`3489`: Update example notebook that raw_input is allowed
1368 1368 * :ghissue:`3396`: Notebook checkpoint time is displayed an hour out
1369 1369 * :ghissue:`3261`: Empty revert to checkpoint menu if no checkpoint...
1370 1370 * :ghissue:`2984`: "print" magic does not work in Python 3
1371 1371 * :ghissue:`3524`: Issues with pyzmq and ipython on EPD update
1372 1372 * :ghissue:`2434`: %store magic not auto-restoring
1373 1373 * :ghissue:`2720`: base_url and static path
1374 1374 * :ghissue:`2234`: Update various low resolution graphics for retina displays
1375 1375 * :ghissue:`2842`: Remember passwords for pw-protected notebooks
1376 1376 * :ghissue:`3244`: qtconsole: ValueError('close_fds is not supported on Windows platforms if you redirect stdin/stdout/stderr',)
1377 1377 * :ghissue:`2215`: AsyncResult.wait(0) can hang waiting for the client to get results?
1378 1378 * :ghissue:`2268`: provide mean to retrieve static data path
1379 1379 * :ghissue:`1905`: Expose UI for worksheets within each notebook
1380 1380 * :ghissue:`2380`: Qt inputhook prevents modal dialog boxes from displaying
1381 1381 * :ghissue:`3185`: prettify on double //
1382 1382 * :ghissue:`2821`: Test failure: IPython.parallel.tests.test_client.test_resubmit_header
1383 1383 * :ghissue:`2475`: [Notebook] Line is deindented when typing eg a colon in markdown mode
1384 1384 * :ghissue:`2470`: Do not destroy valid notebooks
1385 1385 * :ghissue:`860`: Allow the standalone export of a notebook to HTML
1386 1386 * :ghissue:`2652`: notebook with qt backend crashes at save image location popup
1387 1387 * :ghissue:`1587`: Improve kernel restarting in the notebook
1388 1388 * :ghissue:`2710`: Saving a plot in Mac OS X backend crashes IPython
1389 1389 * :ghissue:`2596`: notebook "Last saved:" is misleading on file opening.
1390 1390 * :ghissue:`2671`: TypeError :NoneType when executed "ipython qtconsole" in windows console
1391 1391 * :ghissue:`2703`: Notebook scrolling breaks after pager is shown
1392 1392 * :ghissue:`2803`: KernelManager and KernelClient should be two separate objects
1393 1393 * :ghissue:`2693`: TerminalIPythonApp configuration fails without ipython_config.py
1394 1394 * :ghissue:`2531`: IPython 0.13.1 python 2 32-bit installer includes 64-bit ipython*.exe launchers in the scripts folder
1395 1395 * :ghissue:`2520`: Control-C kills port forwarding
1396 1396 * :ghissue:`2279`: Setting `__file__` to None breaks Mayavi import
1397 1397 * :ghissue:`2161`: When logged into notebook, long titles are incorrectly positioned
1398 1398 * :ghissue:`1292`: Notebook, Print view should not be editable...
1399 1399 * :ghissue:`1731`: test parallel launchers
1400 1400 * :ghissue:`3227`: Improve documentation of ipcontroller and possible BUG
1401 1401 * :ghissue:`2896`: IPController very unstable
1402 1402 * :ghissue:`3517`: documentation build broken in head
1403 1403 * :ghissue:`3522`: UnicodeDecodeError: 'ascii' codec can't decode byte on Pycharm on Windows
1404 1404 * :ghissue:`3448`: Please include MathJax fonts with IPython Notebook
1405 1405 * :ghissue:`3519`: IPython Parallel map mysteriously turns pandas Series into numpy ndarray
1406 1406 * :ghissue:`3345`: IPython embedded shells ask if I want to exit, but I set confirm_exit = False
1407 1407 * :ghissue:`3509`: IPython won't close without asking "Are you sure?" in Firefox
1408 1408 * :ghissue:`3471`: Notebook jinja2/markupsafe depedencies in manual
1409 1409 * :ghissue:`3502`: Notebook broken in master
1410 1410 * :ghissue:`3302`: autoreload does not work in ipython 0.13.x, python 3.3
1411 1411 * :ghissue:`3475`: no warning when leaving/closing notebook on master without saved changes
1412 1412 * :ghissue:`3490`: No obvious feedback when kernel crashes
1413 1413 * :ghissue:`1912`: Move all autoreload tests to their own group
1414 1414 * :ghissue:`2577`: sh.py and ipython for python 3.3
1415 1415 * :ghissue:`3467`: %magic doesn't work
1416 1416 * :ghissue:`3501`: Editing markdown cells that wrap has off-by-one errors in cursor positioning
1417 1417 * :ghissue:`3492`: IPython for Python3
1418 1418 * :ghissue:`3474`: unexpected keyword argument to remove_kernel
1419 1419 * :ghissue:`2283`: TypeError when using '?' after a string in a %logstart session
1420 1420 * :ghissue:`2787`: rmagic and pandas DataFrame
1421 1421 * :ghissue:`2605`: Ellipsis literal triggers AttributeError
1422 1422 * :ghissue:`1179`: Test unicode source in pinfo
1423 1423 * :ghissue:`2055`: drop Python 3.1 support
1424 1424 * :ghissue:`2293`: IPEP 2: Input transformations
1425 1425 * :ghissue:`2790`: %paste and %cpaste not removing "..." lines
1426 1426 * :ghissue:`3480`: Testing fails because iptest.py cannot be found
1427 1427 * :ghissue:`2580`: will not run within PIL build directory
1428 1428 * :ghissue:`2797`: RMagic, Dataframe Conversion Problem
1429 1429 * :ghissue:`2838`: Empty lines disappear from triple-quoted literals.
1430 1430 * :ghissue:`3050`: Broken link on IPython.core.display page
1431 1431 * :ghissue:`3473`: Config not passed down to subcommands
1432 1432 * :ghissue:`3462`: Setting log_format in config file results in error (and no format changes)
1433 1433 * :ghissue:`3311`: Notebook (occasionally) not working on windows (Sophos AV)
1434 1434 * :ghissue:`3461`: Cursor positioning off by a character in auto-wrapped lines
1435 1435 * :ghissue:`3454`: _repr_html_ error
1436 1436 * :ghissue:`3457`: Space in long Paragraph Markdown cell with Chinese or Japanese
1437 1437 * :ghissue:`3447`: Run Cell Does not Work
1438 1438 * :ghissue:`1373`: Last lines in long cells are hidden
1439 1439 * :ghissue:`1504`: Revisit serialization in IPython.parallel
1440 1440 * :ghissue:`1459`: Can't connect to 2 HTTPS notebook servers on the same host
1441 1441 * :ghissue:`678`: Input prompt stripping broken with multiline data structures
1442 1442 * :ghissue:`3001`: IPython.notebook.dirty flag is not set when a cell has unsaved changes
1443 1443 * :ghissue:`3077`: Multiprocessing semantics in parallel.view.map
1444 1444 * :ghissue:`3056`: links across notebooks
1445 1445 * :ghissue:`3120`: Tornado 3.0
1446 1446 * :ghissue:`3156`: update pretty to use Python 3 style for sets
1447 1447 * :ghissue:`3197`: Can't escape multiple dollar signs in a markdown cell
1448 1448 * :ghissue:`3309`: `Image()` signature/doc improvements
1449 1449 * :ghissue:`3415`: Bug in IPython/external/path/__init__.py
1450 1450 * :ghissue:`3446`: Feature suggestion: Download matplotlib figure to client browser
1451 1451 * :ghissue:`3295`: autoexported notebooks: only export explicitly marked cells
1452 1452 * :ghissue:`3442`: Notebook: Summary table extracted from markdown headers
1453 1453 * :ghissue:`3438`: Zooming notebook in chrome is broken in master
1454 1454 * :ghissue:`1378`: Implement autosave in notebook
1455 1455 * :ghissue:`3437`: Highlighting matching parentheses
1456 1456 * :ghissue:`3435`: module search segfault
1457 1457 * :ghissue:`3424`: ipcluster --version
1458 1458 * :ghissue:`3434`: 0.13.2 Ipython/genutils.py doesn't exist
1459 1459 * :ghissue:`3426`: Feature request: Save by cell and not by line #: IPython %save magic
1460 1460 * :ghissue:`3412`: Non Responsive Kernel: Running a Django development server from an IPython Notebook
1461 1461 * :ghissue:`3408`: Save cell toolbar and slide type metadata in notebooks
1462 1462 * :ghissue:`3246`: %paste regression with blank lines
1463 1463 * :ghissue:`3404`: Weird error with $variable and grep in command line magic (!command)
1464 1464 * :ghissue:`3405`: Key auto-completion in dictionaries?
1465 1465 * :ghissue:`3259`: Codemirror linenumber css broken
1466 1466 * :ghissue:`3397`: Vertical text misalignment in Markdown cells
1467 1467 * :ghissue:`3391`: Revert #3358 once fix integrated into CM
1468 1468 * :ghissue:`3360`: Error 500 while saving IPython notebook
1469 1469 * :ghissue:`3375`: Frequent Safari/Webkit crashes
1470 1470 * :ghissue:`3365`: zmq frontend
1471 1471 * :ghissue:`2654`: User_expression issues
1472 1472 * :ghissue:`3389`: Store history as plain text
1473 1473 * :ghissue:`3388`: Ipython parallel: open TCP connection created for each result returned from engine
1474 1474 * :ghissue:`3385`: setup.py failure on Python 3
1475 1475 * :ghissue:`3376`: Setting `__module__` to None breaks pretty printing
1476 1476 * :ghissue:`3374`: ipython qtconsole does not display the prompt on OSX
1477 1477 * :ghissue:`3380`: simple call to kernel
1478 1478 * :ghissue:`3379`: TaskRecord key 'started' not set
1479 * :ghissue:`3241`: notebook conection time out
1479 * :ghissue:`3241`: notebook connection time out
1480 1480 * :ghissue:`3334`: magic interpreter interpretes non magic commands?
1481 1481 * :ghissue:`3326`: python3.3: Type error when launching SGE cluster in IPython notebook
1482 1482 * :ghissue:`3349`: pip3 doesn't run 2to3?
1483 1483 * :ghissue:`3347`: Longlist support in ipdb
1484 1484 * :ghissue:`3343`: Make pip install / easy_install faster
1485 1485 * :ghissue:`3337`: git submodules broke nightly PPA builds
1486 1486 * :ghissue:`3206`: Copy/Paste Regression in QtConsole
1487 1487 * :ghissue:`3329`: Buggy linewrap in Mac OSX Terminal (Mountain Lion)
1488 1488 * :ghissue:`3327`: Qt version check broken
1489 1489 * :ghissue:`3303`: parallel tasks never finish under heavy load
1490 1490 * :ghissue:`1381`: '\\' for equation continuations require an extra '\' in markdown cells
1491 1491 * :ghissue:`3314`: Error launching iPython
1492 1492 * :ghissue:`3306`: Test failure when running on a Vagrant VM
1493 1493 * :ghissue:`3280`: IPython.utils.process.getoutput returns stderr
1494 1494 * :ghissue:`3299`: variables named _ or __ exhibit incorrect behavior
1495 1495 * :ghissue:`3196`: add an "x" or similar to htmlnotebook pager
1496 1496 * :ghissue:`3293`: Several 404 errors for js files Firefox
1497 1497 * :ghissue:`3292`: syntax highlighting in chrome on OSX 10.8.3
1498 1498 * :ghissue:`3288`: Latest dev version hangs on page load
1499 1499 * :ghissue:`3283`: ipython dev retains directory information after directory change
1500 1500 * :ghissue:`3279`: custom.css is not overridden in the dev IPython (1.0)
1501 1501 * :ghissue:`2727`: %run -m doesn't support relative imports
1502 1502 * :ghissue:`3268`: GFM triple backquote and unknown language
1503 1503 * :ghissue:`3273`: Suppressing all plot related outputs
1504 1504 * :ghissue:`3272`: Backspace while completing load previous page
1505 1505 * :ghissue:`3260`: Js error in savewidget
1506 1506 * :ghissue:`3247`: scrollbar in notebook when not needed?
1507 1507 * :ghissue:`3243`: notebook: option to view json source from browser
1508 1508 * :ghissue:`3265`: 404 errors when running IPython 1.0dev
1509 1509 * :ghissue:`3257`: setup.py not finding submodules
1510 1510 * :ghissue:`3253`: Incorrect Qt and PySide version comparison
1511 1511 * :ghissue:`3248`: Cell magics broken in Qt console
1512 1512 * :ghissue:`3012`: Problems with the less based style.min.css
1513 1513 * :ghissue:`2390`: Image width/height don't work in embedded images
1514 1514 * :ghissue:`3236`: cannot set TerminalIPythonApp.log_format
1515 1515 * :ghissue:`3214`: notebook kernel dies if started with invalid parameter
1516 1516 * :ghissue:`2980`: Remove HTMLCell ?
1517 1517 * :ghissue:`3128`: qtconsole hangs on importing pylab (using X forwarding)
1518 1518 * :ghissue:`3198`: Hitting recursive depth causing all notebook pages to hang
1519 1519 * :ghissue:`3218`: race conditions in profile directory creation
1520 1520 * :ghissue:`3177`: OverflowError execption in handlers.py
1521 1521 * :ghissue:`2563`: core.profiledir.check_startup_dir() doesn't work inside py2exe'd installation
1522 1522 * :ghissue:`3207`: [Feature] folders for ipython notebook dashboard
1523 1523 * :ghissue:`3178`: cell magics do not work with empty lines after #2447
1524 1524 * :ghissue:`3204`: Default plot() colors unsuitable for red-green colorblind users
1525 1525 * :ghissue:`1789`: ``:\n/*foo`` turns into ``:\n*(foo)`` in triple-quoted strings.
1526 1526 * :ghissue:`3202`: File cell magic fails with blank lines
1527 1527 * :ghissue:`3199`: %%cython -a stopped working?
1528 1528 * :ghissue:`2688`: obsolete imports in import autocompletion
1529 1529 * :ghissue:`3192`: Python2, Unhandled exception, __builtin__.True = False
1530 1530 * :ghissue:`3179`: script magic error message loop
1531 1531 * :ghissue:`3009`: use XDG_CACHE_HOME for cython objects
1532 1532 * :ghissue:`3059`: Bugs in 00_notebook_tour example.
1533 1533 * :ghissue:`3104`: Integrate a javascript file manager into the notebook front end
1534 1534 * :ghissue:`3176`: Particular equation not rendering (notebook)
1535 1535 * :ghissue:`1133`: [notebook] readonly and upload files/UI
1536 1536 * :ghissue:`2975`: [notebook] python file and cell toolbar
1537 1537 * :ghissue:`3017`: SciPy.weave broken in IPython notebook/ qtconsole
1538 1538 * :ghissue:`3161`: paste macro not reading spaces correctly
1539 1539 * :ghissue:`2835`: %paste not working on WinXpSP3/ipython-0.13.1.py2-win32-PROPER.exe/python27
1540 1540 * :ghissue:`2628`: Make transformers work for lines following decorators
1541 1541 * :ghissue:`2612`: Multiline String containing ":\n?foo\n" confuses interpreter to replace ?foo with get_ipython().magic(u'pinfo foo')
1542 1542 * :ghissue:`2539`: Request: Enable cell magics inside of .ipy scripts
1543 1543 * :ghissue:`2507`: Multiline string does not work (includes `...`) with doctest type input in IPython notebook
1544 1544 * :ghissue:`2164`: Request: Line breaks in line magic command
1545 1545 * :ghissue:`3106`: poor parallel performance with many jobs
1546 1546 * :ghissue:`2438`: print inside multiprocessing crashes Ipython kernel
1547 1547 * :ghissue:`3155`: Bad md5 hash for package 0.13.2
1548 1548 * :ghissue:`3045`: [Notebook] Ipython Kernel does not start if disconnected from internet(/network?)
1549 1549 * :ghissue:`3146`: Using celery in python 3.3
1550 1550 * :ghissue:`3145`: The notebook viewer is down
1551 1551 * :ghissue:`2385`: grep --color not working well with notebook
1552 1552 * :ghissue:`3131`: Quickly install from source in a clean virtualenv?
1553 1553 * :ghissue:`3139`: Rolling log for ipython
1554 1554 * :ghissue:`3127`: notebook with pylab=inline appears to call figure.draw twice
1555 1555 * :ghissue:`3129`: Walking up and down the call stack
1556 1556 * :ghissue:`3123`: Notebook crashed if unplugged ethernet cable
1557 1557 * :ghissue:`3121`: NB should use normalize.css? was #3049
1558 1558 * :ghissue:`3087`: Disable spellchecking in notebook
1559 1559 * :ghissue:`3084`: ipython pyqt 4.10 incompatibilty, QTextBlockUserData
1560 1560 * :ghissue:`3113`: Fails to install under Jython 2.7 beta
1561 1561 * :ghissue:`3110`: Render of h4 headers is not correct in notebook (error in renderedhtml.css)
1562 1562 * :ghissue:`3109`: BUG: read_csv: dtype={'id' : np.str}: Datatype not understood
1563 1563 * :ghissue:`3107`: Autocompletion of object attributes in arrays
1564 1564 * :ghissue:`3103`: Reset locale setting in qtconsole
1565 1565 * :ghissue:`3090`: python3.3 Entry Point not found
1566 1566 * :ghissue:`3081`: UnicodeDecodeError when using Image(data="some.jpeg")
1567 1567 * :ghissue:`2834`: url regexp only finds one link
1568 1568 * :ghissue:`3091`: qtconsole breaks doctest.testmod() in Python 3.3
1569 1569 * :ghissue:`3074`: SIGUSR1 not available on Windows
1570 1570 * :ghissue:`2996`: registration::purging stalled registration high occurrence in small clusters
1571 1571 * :ghissue:`3065`: diff-ability of notebooks
1572 1572 * :ghissue:`3067`: Crash with pygit2
1573 1573 * :ghissue:`3061`: Bug handling Ellipsis
1574 1574 * :ghissue:`3049`: NB css inconsistent behavior between ff and webkit
1575 1575 * :ghissue:`3039`: unicode errors when opening a new notebook
1576 1576 * :ghissue:`3048`: Installning ipython qtConsole should be easyer att Windows
1577 1577 * :ghissue:`3042`: Profile creation fails on 0.13.2 branch
1578 1578 * :ghissue:`3035`: docstring typo/inconsistency: mention of an xml notebook format?
1579 1579 * :ghissue:`3031`: HDF5 library segfault (possibly due to mismatching headers?)
1580 1580 * :ghissue:`2991`: In notebook importing sympy closes ipython kernel
1581 1581 * :ghissue:`3027`: f.__globals__ causes an error in Python 3.3
1582 1582 * :ghissue:`3020`: Failing test test_interactiveshell.TestAstTransform on Windows
1583 1583 * :ghissue:`3023`: alt text for "click to expand output" has typo in alt text
1584 1584 * :ghissue:`2963`: %history to print all input history of a previous session when line range is omitted
1585 1585 * :ghissue:`3018`: IPython installed within virtualenv. WARNING "Please install IPython inside the virtualtenv"
1586 1586 * :ghissue:`2484`: Completion in Emacs *Python* buffer causes prompt to be increased.
1587 1587 * :ghissue:`3014`: Ctrl-C finishes notebook immediately
1588 1588 * :ghissue:`3007`: cython_pyximport reload broken in python3
1589 1589 * :ghissue:`2955`: Incompatible Qt imports when running inprocess_qtconsole
1590 1590 * :ghissue:`3006`: [IPython 0.13.1] The check of PyQt version is wrong
1591 1591 * :ghissue:`3005`: Renaming a notebook to an existing notebook name overwrites the other file
1592 1592 * :ghissue:`2940`: Abort trap in IPython Notebook after installing matplotlib
1593 1593 * :ghissue:`3000`: issue #3000
1594 1594 * :ghissue:`2995`: ipython_directive.py fails on multiline when prompt number < 100
1595 1595 * :ghissue:`2993`: File magic (%%file) does not work with paths beginning with tilde (e.g., ~/anaconda/stuff.txt)
1596 1596 * :ghissue:`2992`: Cell-based input for console and qt frontends?
1597 1597 * :ghissue:`2425`: Liaise with Spyder devs to integrate newer IPython
1598 1598 * :ghissue:`2986`: requesting help in a loop can damage a notebook
1599 1599 * :ghissue:`2978`: v1.0-dev build errors on Arch with Python 3.
1600 1600 * :ghissue:`2557`: [refactor] Insert_cell_at_index()
1601 1601 * :ghissue:`2969`: ipython command does not work in terminal
1602 1602 * :ghissue:`2762`: OSX wxPython (osx_cocoa, 64bit) command "%gui wx" blocks the interpreter
1603 1603 * :ghissue:`2956`: Silent importing of submodules differs from standard Python3.2 interpreter's behavior
1604 1604 * :ghissue:`2943`: Up arrow key history search gets stuck in QTConsole
1605 1605 * :ghissue:`2953`: using 'nonlocal' declaration in global scope causes ipython3 crash
1606 1606 * :ghissue:`2952`: qtconsole ignores exec_lines
1607 1607 * :ghissue:`2949`: ipython crashes due to atexit()
1608 1608 * :ghissue:`2947`: From rmagic to an R console
1609 1609 * :ghissue:`2938`: docstring pane not showing in notebook
1610 1610 * :ghissue:`2936`: Tornado assumes invalid signature for parse_qs on Python 3.1
1611 1611 * :ghissue:`2935`: unable to find python after easy_install / pip install
1612 1612 * :ghissue:`2920`: Add undo-cell deletion menu
1613 1613 * :ghissue:`2914`: BUG:saving a modified .py file after loading a module kills the kernel
1614 1614 * :ghissue:`2925`: BUG: kernel dies if user sets sys.stderr or sys.stdout to a file object
1615 1615 * :ghissue:`2909`: LaTeX sometimes fails to render in markdown cells with some curly bracket + underscore combinations
1616 1616 * :ghissue:`2898`: Skip ipc tests on Windows
1617 1617 * :ghissue:`2902`: ActiveState attempt to build ipython 0.12.1 for python 3.2.2 for Mac OS failed
1618 1618 * :ghissue:`2899`: Test failure in IPython.core.tests.test_magic.test_time
1619 1619 * :ghissue:`2890`: Test failure when fabric not installed
1620 1620 * :ghissue:`2892`: IPython tab completion bug for paths
1621 1621 * :ghissue:`1340`: Allow input cells to be collapsed
1622 1622 * :ghissue:`2881`: ? command in notebook does not show help in Safari
1623 1623 * :ghissue:`2751`: %%timeit should use minutes to format running time in long running cells
1624 1624 * :ghissue:`2879`: When importing a module with a wrong name, ipython crashes
1625 1625 * :ghissue:`2862`: %%timeit should warn of empty contents
1626 1626 * :ghissue:`2485`: History navigation breaks in qtconsole
1627 1627 * :ghissue:`2785`: gevent input hook
1628 1628 * :ghissue:`2843`: Sliently running code in clipboard (with paste, cpaste and variants)
1629 1629 * :ghissue:`2784`: %run -t -N<N> error
1630 1630 * :ghissue:`2732`: Test failure with FileLinks class on Windows
1631 1631 * :ghissue:`2860`: ipython help notebook -> KeyError: 'KernelManager'
1632 1632 * :ghissue:`2858`: Where is the installed `ipython` script?
1633 1633 * :ghissue:`2856`: Edit code entered from ipython in external editor
1634 1634 * :ghissue:`2722`: IPC transport option not taking effect ?
1635 1635 * :ghissue:`2473`: Better error messages in ipengine/ipcontroller
1636 1636 * :ghissue:`2836`: Cannot send builtin module definitions to IP engines
1637 1637 * :ghissue:`2833`: Any reason not to use super() ?
1638 1638 * :ghissue:`2781`: Cannot interrupt infinite loops in the notebook
1639 1639 * :ghissue:`2150`: clippath_demo.py in matplotlib example does not work with inline backend
1640 1640 * :ghissue:`2634`: Numbered list in notebook markdown cell renders with Roman numerals instead of numbers
1641 1641 * :ghissue:`2230`: IPython crashing during startup with "AttributeError: 'NoneType' object has no attribute 'rstrip'"
1642 1642 * :ghissue:`2483`: nbviewer bug? with multi-file gists
1643 1643 * :ghissue:`2466`: mistyping `ed -p` breaks `ed -p`
1644 1644 * :ghissue:`2477`: Glob expansion tests fail on Windows
1645 1645 * :ghissue:`2622`: doc issue: notebooks that ship with Ipython .13 are written for python 2.x
1646 1646 * :ghissue:`2626`: Add "Cell -> Run All Keep Going" for notebooks
1647 1647 * :ghissue:`1223`: Show last modification date of each notebook
1648 1648 * :ghissue:`2621`: user request: put link to example notebooks in Dashboard
1649 1649 * :ghissue:`2564`: grid blanks plots in ipython pylab inline mode (interactive)
1650 1650 * :ghissue:`2532`: Django shell (IPython) gives NameError on dict comprehensions
1651 1651 * :ghissue:`2188`: ipython crashes on ctrl-c
1652 1652 * :ghissue:`2391`: Request: nbformat API to load/save without changing version
1653 1653 * :ghissue:`2355`: Restart kernel message even though kernel is perfectly alive
1654 1654 * :ghissue:`2306`: Garbled input text after reverse search on Mac OS X
1655 1655 * :ghissue:`2297`: ipdb with separate kernel/client pushing stdout to kernel process only
1656 1656 * :ghissue:`2180`: Have [kernel busy] overridden only by [kernel idle]
1657 1657 * :ghissue:`1188`: Pylab with OSX backend keyboard focus issue and hang
1658 1658 * :ghissue:`2107`: test_octavemagic.py[everything] fails
1659 1659 * :ghissue:`1212`: Better understand/document browser compatibility
1660 1660 * :ghissue:`1585`: Refactor notebook templates to use Jinja2 and make each page a separate directory
1661 1661 * :ghissue:`1443`: xticks scaling factor partially obscured with qtconsole and inline plotting
1662 1662 * :ghissue:`1209`: can't make %result work as in doc.
1663 1663 * :ghissue:`1200`: IPython 0.12 Windows install fails on Vista
1664 1664 * :ghissue:`1127`: Interactive test scripts for Qt/nb issues
1665 1665 * :ghissue:`959`: Matplotlib figures hide
1666 1666 * :ghissue:`2071`: win32 installer issue on Windows XP
1667 1667 * :ghissue:`2610`: ZMQInteractiveShell.colors being ignored
1668 1668 * :ghissue:`2505`: Markdown Cell incorrectly highlighting after "<"
1669 1669 * :ghissue:`165`: Installer fails to create Start Menu entries on Windows
1670 1670 * :ghissue:`2356`: failing traceback in terminal ipython for first exception
1671 1671 * :ghissue:`2145`: Have dashboad show when server disconect
1672 1672 * :ghissue:`2098`: Do not crash on kernel shutdow if json file is missing
1673 1673 * :ghissue:`2813`: Offline MathJax is broken on 0.14dev
1674 1674 * :ghissue:`2807`: Test failure: IPython.parallel.tests.test_client.TestClient.test_purge_everything
1675 1675 * :ghissue:`2486`: Readline's history search in ipython console does not clear properly after cancellation with Ctrl+C
1676 1676 * :ghissue:`2709`: Cython -la doesn't work
1677 1677 * :ghissue:`2767`: What is IPython.utils.upgradedir ?
1678 1678 * :ghissue:`2210`: Placing matplotlib legend outside axis bounds causes inline display to clip it
1679 1679 * :ghissue:`2553`: IPython Notebooks not robust against client failures
1680 1680 * :ghissue:`2536`: ImageDraw in Ipython notebook not drawing lines
1681 1681 * :ghissue:`2264`: Feature request: Versioning messaging protocol
1682 1682 * :ghissue:`2589`: Creation of ~300+ MPI-spawned engines causes instability in ipcluster
1683 1683 * :ghissue:`2672`: notebook: inline option without pylab
1684 1684 * :ghissue:`2673`: Indefinite Articles & Traitlets
1685 1685 * :ghissue:`2705`: Notebook crashes Safari with select and drag
1686 1686 * :ghissue:`2721`: dreload kills ipython when it hits zmq
1687 1687 * :ghissue:`2806`: ipython.parallel doesn't discover globals under Python 3.3
1688 1688 * :ghissue:`2794`: _exit_code behaves differently in terminal vs ZMQ frontends
1689 1689 * :ghissue:`2793`: IPython.parallel issue with pushing pandas TimeSeries
1690 1690 * :ghissue:`1085`: In process kernel for Qt frontend
1691 1691 * :ghissue:`2760`: IndexError: list index out of range with Python 3.2
1692 1692 * :ghissue:`2780`: Save and load notebooks from github
1693 1693 * :ghissue:`2772`: AttributeError: 'Client' object has no attribute 'kill'
1694 1694 * :ghissue:`2754`: Fail to send class definitions from interactive session to engines namespaces
1695 1695 * :ghissue:`2764`: TypeError while using 'cd'
1696 1696 * :ghissue:`2765`: name '__file__' is not defined
1697 1697 * :ghissue:`2540`: Wrap tooltip if line exceeds threshold?
1698 1698 * :ghissue:`2394`: Startup error on ipython qtconsole (version 0.13 and 0.14-dev
1699 1699 * :ghissue:`2440`: IPEP 4: Python 3 Compatibility
1700 1700 * :ghissue:`1814`: __file__ is not defined when file end with .ipy
1701 1701 * :ghissue:`2759`: R magic extension interferes with tab completion
1702 1702 * :ghissue:`2615`: Small change needed to rmagic extension.
1703 1703 * :ghissue:`2748`: collapse parts of a html notebook
1704 1704 * :ghissue:`1661`: %paste still bugs about IndentationError and says to use %paste
1705 1705 * :ghissue:`2742`: Octavemagic fails to deliver inline images in IPython (on Windows)
1706 1706 * :ghissue:`2739`: wiki.ipython.org contaminated with prescription drug spam
1707 1707 * :ghissue:`2588`: Link error while executing code from cython example notebook
1708 1708 * :ghissue:`2550`: Rpush magic doesn't find local variables and doesn't support comma separated lists of variables
1709 1709 * :ghissue:`2675`: Markdown/html blockquote need css.
1710 1710 * :ghissue:`2419`: TerminalInteractiveShell.__init__() ignores value of ipython_dir argument
1711 1711 * :ghissue:`1523`: Better LaTeX printing in the qtconsole with the sympy profile
1712 1712 * :ghissue:`2719`: ipython fails with `pkg_resources.DistributionNotFound: ipython==0.13`
1713 1713 * :ghissue:`2715`: url crashes nbviewer.ipython.org
1714 1714 * :ghissue:`2555`: "import" module completion on MacOSX
1715 1715 * :ghissue:`2707`: Problem installing the new version of IPython in Windows
1716 1716 * :ghissue:`2696`: SymPy magic bug in IPython Notebook
1717 1717 * :ghissue:`2684`: pretty print broken for types created with PyType_FromSpec
1718 1718 * :ghissue:`2533`: rmagic breaks on Windows
1719 1719 * :ghissue:`2661`: Qtconsole tooltip is too wide when the function has many arguments
1720 1720 * :ghissue:`2679`: ipython3 qtconsole via Homebrew on Mac OS X 10.8 - pyqt/pyside import error
1721 1721 * :ghissue:`2646`: pylab_not_importable
1722 1722 * :ghissue:`2587`: cython magic pops 2 CLI windows upon execution on Windows
1723 1723 * :ghissue:`2660`: Certain arguments (-h, --help, --version) never passed to scripts run with ipython
1724 1724 * :ghissue:`2665`: Missing docs for rmagic and some other extensions
1725 1725 * :ghissue:`2611`: Travis wants to drop 3.1 support
1726 1726 * :ghissue:`2658`: Incorrect parsing of raw multiline strings
1727 1727 * :ghissue:`2655`: Test fails if `from __future__ import print_function` in .pythonrc.py
1728 1728 * :ghissue:`2651`: nonlocal with no existing variable produces too many errors
1729 1729 * :ghissue:`2645`: python3 is a pain (minor unicode bug)
1730 1730 * :ghissue:`2637`: %paste in Python 3 on Mac doesn't work
1731 1731 * :ghissue:`2624`: Error on launching IPython on Win 7 and Python 2.7.3
1732 1732 * :ghissue:`2608`: disk IO activity on cursor press
1733 1733 * :ghissue:`1275`: Markdown parses LaTeX math symbols as its formatting syntax in notebook
1734 1734 * :ghissue:`2613`: display(Math(...)) doesn't render \tau correctly
1735 1735 * :ghissue:`925`: Tab-completion in Qt console needn't use pager
1736 1736 * :ghissue:`2607`: %load_ext sympy.interactive.ipythonprinting dammaging output
1737 1737 * :ghissue:`2593`: Toolbar button to open qtconsole from notebook
1738 1738 * :ghissue:`2602`: IPython html documentation for downloading
1739 1739 * :ghissue:`2598`: ipython notebook --pylab=inline replaces built-in any()
1740 1740 * :ghissue:`2244`: small issue: wrong printout
1741 1741 * :ghissue:`2590`: add easier way to execute scripts in the current directory
1742 1742 * :ghissue:`2581`: %hist does not work when InteractiveShell.cache_size = 0
1743 1743 * :ghissue:`2584`: No file COPYING
1744 1744 * :ghissue:`2578`: AttributeError: 'module' object has no attribute 'TestCase'
1745 1745 * :ghissue:`2576`: One of my notebooks won't load any more -- is there a maximum notebook size?
1746 1746 * :ghissue:`2560`: Notebook output is invisible when printing strings with \r\r\n line endings
1747 1747 * :ghissue:`2566`: if pyside partially present ipython qtconsole fails to load even if pyqt4 present
1748 1748 * :ghissue:`1308`: ipython qtconsole --ssh=server --existing ... hangs
1749 1749 * :ghissue:`1679`: List command doesn't work in ipdb debugger the first time
1750 1750 * :ghissue:`2545`: pypi win32 installer creates 64bit executibles
1751 1751 * :ghissue:`2080`: Event loop issues with IPython 0.12 and PyQt4 (``QDialog.exec_`` and more)
1752 1752 * :ghissue:`2541`: Allow `python -m IPython`
1753 1753 * :ghissue:`2508`: subplots_adjust() does not work correctly in ipython notebook
1754 1754 * :ghissue:`2289`: Incorrect mathjax rendering of certain arrays of equations
1755 1755 * :ghissue:`2487`: Selecting and indenting
1756 1756 * :ghissue:`2521`: more fine-grained 'run' controls, such as 'run from here' and 'run until here'
1757 1757 * :ghissue:`2535`: Funny bounding box when plot with text
1758 1758 * :ghissue:`2523`: History not working
1759 1759 * :ghissue:`2514`: Issue with zooming in qtconsole
1760 1760 * :ghissue:`2220`: No sys.stdout.encoding in kernel based IPython
1761 1761 * :ghissue:`2512`: ERROR: Internal Python error in the inspect module.
1762 1762 * :ghissue:`2496`: Function passwd does not work in QtConsole
1763 1763 * :ghissue:`1453`: make engines reconnect/die when controller was restarted
1764 1764 * :ghissue:`2481`: ipython notebook -- clicking in a code cell's output moves the screen to the top of the code cell
1765 1765 * :ghissue:`2488`: Undesired plot outputs in Notebook inline mode
1766 1766 * :ghissue:`2482`: ipython notebook -- download may not get the latest notebook
1767 1767 * :ghissue:`2471`: _subprocess module removed in Python 3.3
1768 1768 * :ghissue:`2374`: Issues with man pages
1769 1769 * :ghissue:`2316`: parallel.Client.__init__ should take cluster_id kwarg
1770 1770 * :ghissue:`2457`: Can a R library wrapper be created with Rmagic?
1771 1771 * :ghissue:`1575`: Fallback frontend for console when connecting pylab=inlnie -enabled kernel?
1772 1772 * :ghissue:`2097`: Do not crash if history db is corrupted
1773 1773 * :ghissue:`2435`: ipengines fail if clean_logs enabled
1774 1774 * :ghissue:`2429`: Using warnings.warn() results in TypeError
1775 1775 * :ghissue:`2422`: Multiprocessing in ipython notebook kernel crash
1776 1776 * :ghissue:`2426`: ipython crashes with the following message. I do not what went wrong. Can you help me identify the problem?
1777 1777 * :ghissue:`2423`: Docs typo?
1778 1778 * :ghissue:`2257`: pip install -e fails
1779 1779 * :ghissue:`2418`: rmagic can't run R's read.csv on data files with NA data
1780 1780 * :ghissue:`2417`: HTML notebook: Backspace sometimes deletes multiple characters
1781 1781 * :ghissue:`2275`: notebook: "Down_Arrow" on last line of cell should move to end of line
1782 1782 * :ghissue:`2414`: 0.13.1 does not work with current EPD 7.3-2
1783 1783 * :ghissue:`2409`: there is a redundant None
1784 1784 * :ghissue:`2410`: Use /usr/bin/python3 instead of /usr/bin/python
1785 1785 * :ghissue:`2366`: Notebook Dashboard --notebook-dir and fullpath
1786 1786 * :ghissue:`2406`: Inability to get docstring in debugger
1787 1787 * :ghissue:`2398`: Show line number for IndentationErrors
1788 1788 * :ghissue:`2314`: HTML lists seem to interfere with the QtConsole display
1789 1789 * :ghissue:`1688`: unicode exception when using %run with failing script
1790 1790 * :ghissue:`1884`: IPython.embed changes color on error
1791 1791 * :ghissue:`2381`: %time doesn't work for multiline statements
1792 1792 * :ghissue:`1435`: Add size keywords in Image class
1793 1793 * :ghissue:`2372`: interactiveshell.py misses urllib and io_open imports
1794 1794 * :ghissue:`2371`: iPython not working
1795 1795 * :ghissue:`2367`: Tab expansion moves to next cell in notebook
1796 1796 * :ghissue:`2359`: nbviever alters the order of print and display() output
1797 1797 * :ghissue:`2227`: print name for IPython Notebooks has become uninformative
1798 1798 * :ghissue:`2361`: client doesn't use connection file's 'location' in disambiguating 'interface'
1799 1799 * :ghissue:`2357`: failing traceback in terminal ipython for first exception
1800 1800 * :ghissue:`2343`: Installing in a python 3.3b2 or python 3.3rc1 virtual environment.
1801 1801 * :ghissue:`2315`: Failure in test: "Test we're not loading modules on startup that we shouldn't."
1802 1802 * :ghissue:`2351`: Multiple Notebook Apps: cookies not port specific, clash with each other
1803 1803 * :ghissue:`2350`: running unittest from qtconsole prints output to terminal
1804 1804 * :ghissue:`2303`: remote tracebacks broken since 952d0d6 (PR #2223)
1805 * :ghissue:`2330`: qtconsole does not hightlight tab-completion suggestion with custom stylesheet
1805 * :ghissue:`2330`: qtconsole does not highlight tab-completion suggestion with custom stylesheet
1806 1806 * :ghissue:`2325`: Parsing Tex formula fails in Notebook
1807 1807 * :ghissue:`2324`: Parsing Tex formula fails
1808 1808 * :ghissue:`1474`: Add argument to `run -n` for custom namespace
1809 1809 * :ghissue:`2318`: C-m n/p don't work in Markdown cells in the notebook
1810 1810 * :ghissue:`2309`: time.time() in ipython notebook producing impossible results
1811 1811 * :ghissue:`2307`: schedule tasks on newly arrived engines
1812 1812 * :ghissue:`2313`: Allow Notebook HTML/JS to send messages to Python code
1813 1813 * :ghissue:`2304`: ipengine throws KeyError: url
1814 1814 * :ghissue:`1878`: shell access using ! will not fill class or function scope vars
1815 1815 * :ghissue:`2253`: %paste does not retrieve clipboard contents under screen/tmux on OS X
1816 1816 * :ghissue:`1510`: Add-on (or Monkey-patch) infrastructure for HTML notebook
1817 1817 * :ghissue:`2273`: triple quote and %s at beginning of line with %paste
1818 1818 * :ghissue:`2243`: Regression in .embed()
1819 1819 * :ghissue:`2266`: SSH passwordless check with OpenSSH checks for the wrong thing
1820 1820 * :ghissue:`2217`: Change NewNotebook handler to use 30x redirect
1821 1821 * :ghissue:`2276`: config option for disabling history store
1822 1822 * :ghissue:`2239`: can't use parallel.Reference in view.map
1823 1823 * :ghissue:`2272`: Sympy piecewise messed up rendering
1824 1824 * :ghissue:`2252`: %paste throws an exception with empty clipboard
1825 1825 * :ghissue:`2259`: git-mpr is currently broken
1826 1826 * :ghissue:`2247`: Variable expansion in shell commands should work in substrings
1827 1827 * :ghissue:`2026`: Run 'fast' tests only
1828 1828 * :ghissue:`2241`: read a list of notebooks on server and bring into browser only notebook
1829 1829 * :ghissue:`2237`: please put python and text editor in the web only ipython
1830 1830 * :ghissue:`2053`: Improvements to the IPython.display.Image object
1831 1831 * :ghissue:`1456`: ERROR: Internal Python error in the inspect module.
1832 1832 * :ghissue:`2221`: Avoid importing from IPython.parallel in core
1833 1833 * :ghissue:`2213`: Can't trigger startup code in Engines
1834 1834 * :ghissue:`1464`: Strange behavior for backspace with lines ending with more than 4 spaces in notebook
1835 1835 * :ghissue:`2187`: NaN in object_info_reply JSON causes parse error
1836 1836 * :ghissue:`214`: system command requiring administrative privileges
1837 1837 * :ghissue:`2195`: Unknown option `no-edit` in git-mpr
1838 1838 * :ghissue:`2201`: Add documentation build to tools/test_pr.py
1839 1839 * :ghissue:`2205`: Command-line option for default Notebook output collapsing behavior
1840 1840 * :ghissue:`1927`: toggle between inline and floating figures
1841 1841 * :ghissue:`2171`: Can't start StarCluster after upgrading to IPython 0.13
1842 1842 * :ghissue:`2173`: oct2py v >= 0.3.1 doesn't need h5py anymore
1843 1843 * :ghissue:`2099`: storemagic needs to use self.shell
1844 1844 * :ghissue:`2166`: DirectView map_sync() with Lambdas Using Generators
1845 1845 * :ghissue:`2091`: Unable to use print_stats after %prun -r in notebook
1846 1846 * :ghissue:`2132`: Add fail-over for pastebin
1847 1847 * :ghissue:`2156`: Make it possible to install ipython without nasty gui dependencies
1848 1848 * :ghissue:`2154`: Scrolled long output should be off in print view by default
1849 1849 * :ghissue:`2162`: Tab completion does not work with IPython.embed_kernel()
1850 1850 * :ghissue:`2157`: iPython 0.13 / github-master cannot create logfile from scratch
1851 1851 * :ghissue:`2151`: missing newline when a magic is called from the qtconsole menu
1852 1852 * :ghissue:`2139`: 00_notebook_tour Image example broken on master
1853 1853 * :ghissue:`2143`: Add a %%cython_annotate magic
1854 1854 * :ghissue:`2135`: Running IPython from terminal
1855 1855 * :ghissue:`2093`: Makefile for building Sphinx documentation on Windows
1856 1856 * :ghissue:`2122`: Bug in pretty printing
1857 1857 * :ghissue:`2120`: Notebook "Make a Copy..." keeps opening duplicates in the same tab
1858 1858 * :ghissue:`1997`: password cannot be used with url prefix
1859 1859 * :ghissue:`2129`: help/doc displayed multiple times if requested in loop
1860 1860 * :ghissue:`2121`: ipdb does not support input history in qtconsole
1861 1861 * :ghissue:`2114`: %logstart doesn't log
1862 1862 * :ghissue:`2085`: %ed magic fails in qtconsole
1863 1863 * :ghissue:`2119`: iPython fails to run on MacOS Lion
1864 1864 * :ghissue:`2052`: %pylab inline magic does not work on windows
1865 1865 * :ghissue:`2111`: Ipython won't start on W7
1866 1866 * :ghissue:`2112`: Strange internal traceback
1867 1867 * :ghissue:`2108`: Backslash (\) at the end of the line behavior different from default Python
1868 1868 * :ghissue:`1425`: Ampersands can't be typed sometimes in notebook cells
1869 1869 * :ghissue:`1513`: Add expand/collapse support for long output elements like stdout and tracebacks
1870 1870 * :ghissue:`2087`: error when starting ipython
1871 1871 * :ghissue:`2103`: Ability to run notebook file from commandline
1872 1872 * :ghissue:`2082`: Qt Console output spacing
1873 1873 * :ghissue:`2083`: Test failures with Python 3.2 and PYTHONWARNINGS="d"
1874 1874 * :ghissue:`2094`: about inline
1875 1875 * :ghissue:`2077`: Starting IPython3 on the terminal
1876 1876 * :ghissue:`1760`: easy_install ipython fails on py3.2-win32
1877 1877 * :ghissue:`2075`: Local Mathjax install causes iptest3 error under python3
1878 1878 * :ghissue:`2057`: setup fails for python3 with LANG=C
1879 1879 * :ghissue:`2070`: shebang on Windows
1880 1880 * :ghissue:`2054`: sys_info missing git hash in sdists
1881 1881 * :ghissue:`2059`: duplicate and modified files in documentation
1882 1882 * :ghissue:`2056`: except-shadows-builtin osm.py:687
1883 1883 * :ghissue:`2058`: hyphen-used-as-minus-sign in manpages
@@ -1,1607 +1,1607 b''
1 1 .. _issues_list_200:
2 2
3 3 Issues closed in the 2.x development cycle
4 4 ==========================================
5 5
6 6 Issues closed in 2.4.1
7 7 ----------------------
8 8
9 9 GitHub stats for 2014/11/01 - 2015/01/30
10 10
11 11 .. note::
12 12
13 13 IPython 2.4.0 was released without a few of the backports listed below.
14 14 2.4.1 has the correct patches intended for 2.4.0.
15 15
16 16 These lists are automatically generated, and may be incomplete or contain duplicates.
17 17
18 18 The following 7 authors contributed 35 commits.
19 19
20 20 * Benjamin Ragan-Kelley
21 21 * Carlos Cordoba
22 22 * Damon Allen
23 23 * Jessica B. Hamrick
24 24 * Mateusz Paprocki
25 25 * Peter Würtz
26 26 * Thomas Kluyver
27 27
28 28 We closed 10 issues and merged 6 pull requests;
29 29 this is the full list (generated with the script
30 30 :file:`tools/github_stats.py`):
31 31
32 32 Pull Requests (10):
33 33
34 34 * :ghpull:`7106`: Changed the display order of rich output in the live notebook.
35 35 * :ghpull:`6878`: Update pygments monkeypatch for compatibility with Pygments 2.0
36 36 * :ghpull:`6778`: backport nbformat v4 to 2.x
37 37 * :ghpull:`6761`: object_info_reply field is oname, not name
38 38 * :ghpull:`6653`: Fix IPython.utils.ansispan() to ignore stray [0m
39 39 * :ghpull:`6706`: Correctly display prompt numbers that are ``None``
40 40 * :ghpull:`6634`: don't use contains in SelectWidget item_query
41 41 * :ghpull:`6593`: note how to start the qtconsole
42 42 * :ghpull:`6281`: more minor fixes to release scripts
43 43 * :ghpull:`5458`: Add support for PyQt5.
44 44
45 45 Issues (6):
46 46
47 47 * :ghissue:`7272`: qtconsole problems with pygments
48 48 * :ghissue:`7049`: Cause TypeError: 'NoneType' object is not callable in qtconsole
49 49 * :ghissue:`6877`: Qt console doesn't work with pygments 2.0rc1
50 50 * :ghissue:`6689`: Problem with string containing two or more question marks
51 51 * :ghissue:`6702`: Cell numbering after ``ClearOutput`` preprocessor
52 52 * :ghissue:`6633`: selectwidget doesn't display 1 as a selection choice when passed in as a member of values list
53 53
54 54
55 55 Issues closed in 2.3.1
56 56 ----------------------
57 57
58 58 Just one bugfix: fixed bad CRCRLF line-endings in notebooks on Windows
59 59
60 60 Pull Requests (1):
61 61
62 62 * :ghpull:`6911`: don't use text mode in mkstemp
63 63
64 64 Issues (1):
65 65
66 66 * :ghissue:`6599`: Notebook.ipynb CR+LF turned into CR+CR+LF
67 67
68 68
69 69 Issues closed in 2.3.0
70 70 ----------------------
71 71
72 72 GitHub stats for 2014/08/06 - 2014/10/01
73 73
74 74 These lists are automatically generated, and may be incomplete or contain duplicates.
75 75
76 76 The following 6 authors contributed 31 commits.
77 77
78 78 * Benjamin Ragan-Kelley
79 79 * David Hirschfeld
80 80 * Eric Firing
81 81 * Jessica B. Hamrick
82 82 * Matthias Bussonnier
83 83 * Thomas Kluyver
84 84
85 85 We closed 16 issues and merged 9 pull requests;
86 86 this is the full list (generated with the script
87 87 :file:`tools/github_stats.py`):
88 88
89 89 Pull Requests (16):
90 90
91 91 * :ghpull:`6587`: support ``%matplotlib qt5`` and ``%matplotlib nbagg``
92 92 * :ghpull:`6583`: Windows symlink test fixes
93 93 * :ghpull:`6585`: fixes :ghissue:`6473`
94 94 * :ghpull:`6581`: Properly mock winreg functions for test
95 95 * :ghpull:`6556`: Use some more informative asserts in inprocess kernel tests
96 96 * :ghpull:`6514`: Fix for copying metadata flags
97 97 * :ghpull:`6453`: Copy file metadata in atomic save
98 98 * :ghpull:`6480`: only compare host:port in Websocket.check_origin
99 99 * :ghpull:`6483`: Trim anchor link in heading cells, fixes :ghissue:`6324`
100 100 * :ghpull:`6410`: Fix relative import in appnope
101 101 * :ghpull:`6395`: update mathjax CDN url in nbconvert template
102 102 * :ghpull:`6269`: Implement atomic save
103 103 * :ghpull:`6374`: Rename ``abort_queues`` --> ``_abort_queues``
104 104 * :ghpull:`6321`: Use appnope in qt and wx gui support from the terminal; closes :ghissue:`6189`
105 105 * :ghpull:`6318`: use write_error instead of get_error_html
106 106 * :ghpull:`6303`: Fix error message when failing to load a notebook
107 107
108 108 Issues (9):
109 109
110 110 * :ghissue:`6057`: ``%matplotlib`` + qt5
111 111 * :ghissue:`6518`: Test failure in atomic save on Windows
112 112 * :ghissue:`6473`: Switching between "Raw Cell Format" and "Edit Metadata" does not work
113 113 * :ghissue:`6405`: Creating a notebook should respect directory permissions; saving should respect prior permissions
114 114 * :ghissue:`6324`: Anchors in Heading don't work.
115 115 * :ghissue:`6409`: No module named '_dummy'
116 116 * :ghissue:`6392`: Mathjax library link broken
117 117 * :ghissue:`6329`: IPython Notebook Server URL now requires "tree" at the end of the URL? (version 2.2)
118 118 * :ghissue:`6189`: ipython console freezes for increasing no of seconds in %pylab mode
119 119
120 120 Issues closed in 2.2.0
121 121 ----------------------
122 122
123 123 GitHub stats for 2014/05/21 - 2014/08/06 (tag: rel-2.1.0)
124 124
125 125 These lists are automatically generated, and may be incomplete or contain duplicates.
126 126
127 127 The following 13 authors contributed 36 commits.
128 128
129 129 * Adam Hodgen
130 130 * Benjamin Ragan-Kelley
131 131 * Björn Grüning
132 132 * Dara Adib
133 133 * Eric Galloway
134 134 * Jonathan Frederic
135 135 * Kyle Kelley
136 136 * Matthias Bussonnier
137 137 * Paul Ivanov
138 138 * Shayne Hodge
139 139 * Steven Anton
140 140 * Thomas Kluyver
141 141 * Zahari
142 142
143 143 We closed 23 issues and merged 11 pull requests;
144 144 this is the full list (generated with the script
145 145 :file:`tools/github_stats.py`):
146 146
147 147 Pull Requests (23):
148 148
149 149 * :ghpull:`6279`: minor updates to release scripts
150 150 * :ghpull:`6273`: Upgrade default mathjax version.
151 151 * :ghpull:`6249`: always use HTTPS getting mathjax from CDN
152 152 * :ghpull:`6114`: update hmac signature comparison
153 153 * :ghpull:`6195`: Close handle on new temporary files before returning filename
154 154 * :ghpull:`6143`: pin tornado to < 4 on travis js tests
155 155 * :ghpull:`6134`: remove rackcdn https workaround for mathjax cdn
156 156 * :ghpull:`6120`: Only allow iframe embedding on same origin.
157 157 * :ghpull:`6117`: Remove / from route of TreeRedirectHandler.
158 158 * :ghpull:`6105`: only set allow_origin_pat if defined
159 159 * :ghpull:`6102`: Add newline if missing to end of script magic cell
160 160 * :ghpull:`6077`: allow unicode keys in dicts in json_clean
161 161 * :ghpull:`6061`: make CORS configurable
162 162 * :ghpull:`6081`: don’t modify dict keys while iterating through them
163 163 * :ghpull:`5803`: unify visual line handling
164 164 * :ghpull:`6005`: Changed right arrow key movement function to mirror left arrow key
165 165 * :ghpull:`6029`: add pickleutil.PICKLE_PROTOCOL
166 166 * :ghpull:`6003`: Set kernel_id before checking websocket
167 167 * :ghpull:`5994`: Fix ssh tunnel for Python3
168 168 * :ghpull:`5973`: Do not create checkpoint_dir relative to current dir
169 169 * :ghpull:`5933`: fix qt_loader import hook signature
170 170 * :ghpull:`5944`: Markdown rendering bug fix.
171 171 * :ghpull:`5917`: use shutil.move instead of os.rename
172 172
173 173 Issues (11):
174 174
175 175 * :ghissue:`6246`: Include MathJax by default or access the CDN over a secure connection
176 176 * :ghissue:`5525`: Websocket origin check fails when used with Apache WS proxy
177 177 * :ghissue:`5901`: 2 test failures in Python 3.4 in parallel group
178 178 * :ghissue:`5926`: QT console: text selection cannot be made from left to right with keyboard
179 179 * :ghissue:`5998`: use_dill does not work in Python 3.4
180 180 * :ghissue:`5964`: Traceback on Qt console exit
181 181 * :ghissue:`5787`: Error in Notebook-Generated latex (nbconvert)
182 182 * :ghissue:`5950`: qtconsole truncates help
183 183 * :ghissue:`5943`: 2.x: notebook fails to load when using HTML comments
184 184 * :ghissue:`5932`: Qt ImportDenier Does Not Adhere to PEP302
185 185 * :ghissue:`5898`: OSError when moving configuration file
186 186
187 187 Issues closed in 2.1.0
188 188 ----------------------
189 189
190 190 GitHub stats for 2014/04/02 - 2014/05/21 (since 2.0.0)
191 191
192 192 These lists are automatically generated, and may be incomplete or contain duplicates.
193 193
194 194 The following 35 authors contributed 145 commits.
195 195
196 196 * Adrian Price-Whelan
197 197 * Aron Ahmadia
198 198 * Benjamin Ragan-Kelley
199 199 * Benjamin Schultz
200 200 * Björn Linse
201 201 * Blake Griffith
202 202 * chebee7i
203 203 * Damián Avila
204 204 * Dav Clark
205 205 * dexterdev
206 206 * Erik Tollerud
207 207 * Grzegorz Rożniecki
208 208 * Jakob Gager
209 209 * jdavidheiser
210 210 * Jessica B. Hamrick
211 211 * Jim Garrison
212 212 * Jonathan Frederic
213 213 * Matthias Bussonnier
214 214 * Maximilian Albert
215 215 * Mohan Raj Rajamanickam
216 216 * ncornette
217 217 * Nikolay Koldunov
218 218 * Nile Geisinger
219 219 * Pankaj Pandey
220 220 * Paul Ivanov
221 221 * Pierre Haessig
222 222 * Raffaele De Feo
223 223 * Renaud Richardet
224 224 * Spencer Nelson
225 225 * Steve Chan
226 226 * sunny
227 227 * Susan Tan
228 228 * Thomas Kluyver
229 229 * Yaroslav Halchenko
230 230 * zah
231 231
232 232 We closed a total of 129 issues, 92 pull requests and 37 regular issues;
233 233 this is the full list (generated with the script
234 234 :file:`tools/github_stats.py --milestone 2.1`):
235 235
236 236 Pull Requests (92):
237 237
238 238 * :ghpull:`5871`: specify encoding in msgpack.unpackb
239 239 * :ghpull:`5869`: Catch more errors from clipboard access on Windows
240 240 * :ghpull:`5866`: Make test robust against differences in line endings
241 241 * :ghpull:`5605`: Two cell toolbar fixes.
242 242 * :ghpull:`5843`: remove Firefox-specific CSS workaround
243 243 * :ghpull:`5845`: Pass Windows interrupt event to kernels as an environment variable
244 244 * :ghpull:`5835`: fix typo in v2 convert
245 245 * :ghpull:`5841`: Fix writing history with output to a file in Python 2
246 246 * :ghpull:`5842`: fix typo in nbconvert help
247 247 * :ghpull:`5846`: Fix typos in Cython example
248 248 * :ghpull:`5839`: Close graphics dev in finally clause
249 249 * :ghpull:`5837`: pass on install docs
250 250 * :ghpull:`5832`: Fixed example to work with python3
251 251 * :ghpull:`5826`: allow notebook tour instantiation to fail
252 252 * :ghpull:`5560`: Minor expansion of Cython example
253 253 * :ghpull:`5818`: interpret any exception in getcallargs as not callable
254 254 * :ghpull:`5816`: Add output to IPython directive when in verbatim mode.
255 255 * :ghpull:`5822`: Don't overwrite widget description in interact
256 256 * :ghpull:`5782`: Silence exception thrown by completer when dir() does not return a list
257 257 * :ghpull:`5807`: Drop log level to info for Qt console shutdown
258 258 * :ghpull:`5814`: Remove -i options from mv, rm and cp aliases
259 259 * :ghpull:`5812`: Fix application name when printing subcommand help.
260 260 * :ghpull:`5804`: remove an inappropriate ``!``
261 261 * :ghpull:`5805`: fix engine startup files
262 262 * :ghpull:`5806`: Don't auto-move .config/ipython if symbolic link
263 263 * :ghpull:`5716`: Add booktabs package to latex base.tplx
264 264 * :ghpull:`5669`: allows threadsafe sys.stdout.flush from background threads
265 265 * :ghpull:`5668`: allow async output on the most recent request
266 266 * :ghpull:`5768`: fix cursor keys in long lines wrapped in markdown
267 267 * :ghpull:`5788`: run cells with ``silent=True`` in ``%run nb.ipynb``
268 268 * :ghpull:`5715`: log all failed ajax API requests
269 269 * :ghpull:`5769`: Don't urlescape the text that goes into a title tag
270 270 * :ghpull:`5762`: Fix check for pickling closures
271 271 * :ghpull:`5766`: View.map with empty sequence should return empty list
272 272 * :ghpull:`5758`: Applied bug fix: using fc and ec did not properly set the figure canvas ...
273 273 * :ghpull:`5754`: Format command name into subcommand_description at run time, not import
274 274 * :ghpull:`5744`: Describe using PyPI/pip to distribute & install extensions
275 275 * :ghpull:`5712`: monkeypatch inspect.findsource only when we use it
276 276 * :ghpull:`5708`: create checkpoints dir in notebook subdirectories
277 277 * :ghpull:`5714`: log error message when API requests fail
278 278 * :ghpull:`5732`: Quick typo fix in nbformat/convert.py
279 279 * :ghpull:`5713`: Fix a NameError in IPython.parallel
280 280 * :ghpull:`5704`: Update nbconvertapp.py
281 281 * :ghpull:`5534`: cleanup some ``pre`` css inheritance
282 282 * :ghpull:`5699`: don't use common names in require decorators
283 283 * :ghpull:`5692`: Update notebook.rst fixing broken reference to notebook examples readme
284 284 * :ghpull:`5693`: Update parallel_intro.rst to fix a broken link to examples
285 285 * :ghpull:`5486`: disambiguate to location when no IPs can be determined
286 286 * :ghpull:`5574`: Remove the outdated keyboard shortcuts from notebook docs
287 287 * :ghpull:`5568`: Use ``__qualname__`` in pretty reprs for Python 3
288 288 * :ghpull:`5678`: Fix copy & paste error in docstring of ImageWidget class
289 289 * :ghpull:`5677`: Fix %bookmark -l for Python 3
290 290 * :ghpull:`5670`: nbconvert: Fix CWD imports
291 291 * :ghpull:`5647`: Mention git hooks in install documentation
292 292 * :ghpull:`5671`: Fix blank slides issue in Reveal slideshow pdf export
293 293 * :ghpull:`5657`: use 'localhost' as default for the notebook server
294 294 * :ghpull:`5584`: more semantic icons
295 295 * :ghpull:`5594`: update components with marked-0.3.2
296 296 * :ghpull:`5500`: check for Python 3.2
297 297 * :ghpull:`5582`: reset readline after running PYTHONSTARTUP
298 298 * :ghpull:`5630`: Fixed Issue :ghissue:`4012` Added Help menubar link to Github markdown doc
299 299 * :ghpull:`5613`: Fixing bug :ghissue:`5607`
300 300 * :ghpull:`5633`: Provide more help if lessc is not found.
301 301 * :ghpull:`5620`: fixed a typo in IPython.core.formatters
302 302 * :ghpull:`5619`: Fix typo in storemagic module docstring
303 303 * :ghpull:`5592`: add missing ``browser`` to notebook_aliases list
304 304 * :ghpull:`5506`: Fix ipconfig regex pattern
305 305 * :ghpull:`5581`: Fix rmagic for cells ending in comment.
306 306 * :ghpull:`5576`: only process cr if it's found
307 307 * :ghpull:`5478`: Add git-hooks install script. Update README.md
308 308 * :ghpull:`5546`: do not shutdown notebook if 'n' is part of answer
309 309 * :ghpull:`5527`: Don't remove upload items from nav tree unless explicitly requested.
310 310 * :ghpull:`5501`: remove inappropriate wheel tag override
311 311 * :ghpull:`5548`: FileNotebookManager: Use shutil.move() instead of os.rename()
312 312 * :ghpull:`5524`: never use ``for (var i in array)``
313 313 * :ghpull:`5459`: Fix interact animation page jump FF
314 314 * :ghpull:`5559`: Minor typo fix in "Cython Magics.ipynb"
315 315 * :ghpull:`5507`: Fix typo in interactive widgets examples index notebook
316 316 * :ghpull:`5554`: Make HasTraits pickleable
317 317 * :ghpull:`5535`: fix n^2 performance issue in coalesce_streams preprocessor
318 318 * :ghpull:`5522`: fix iteration over Client
319 319 * :ghpull:`5488`: Added missing require and jquery from cdn.
320 320 * :ghpull:`5516`: ENH: list generated config files in generated, and rm them upon clean
321 321 * :ghpull:`5493`: made a minor fix to one of the widget examples
322 322 * :ghpull:`5512`: Update tooltips to refer to shift-tab
323 323 * :ghpull:`5505`: Make backport_pr work on Python 3
324 324 * :ghpull:`5503`: check explicitly for 'dev' before adding the note to docs
325 325 * :ghpull:`5498`: use milestones to indicate backport
326 326 * :ghpull:`5492`: Polish whatsnew docs
327 327 * :ghpull:`5495`: Fix various broken things in docs
328 328 * :ghpull:`5496`: Exclude whatsnew/pr directory from docs builds
329 329 * :ghpull:`5489`: Fix required Python versions
330 330
331 331 Issues (37):
332 332
333 333 * :ghissue:`5364`: Horizontal scrollbar hides cell's last line on Firefox
334 334 * :ghissue:`5192`: horisontal scrollbar overlaps output or touches next cell
335 335 * :ghissue:`5840`: Third-party Windows kernels don't get interrupt signal
336 336 * :ghissue:`2412`: print history to file using qtconsole and notebook
337 337 * :ghissue:`5703`: Notebook doesn't render with "ask me every time" cookie setting in Firefox
338 338 * :ghissue:`5817`: calling mock object in IPython 2.0.0 under Python 3.4.0 raises AttributeError
339 339 * :ghissue:`5499`: Error running widgets nbconvert example
340 340 * :ghissue:`5654`: Broken links from ipython documentation
341 341 * :ghissue:`5019`: print in QT event callback doesn't show up in ipython notebook.
342 342 * :ghissue:`5800`: Only last In prompt number set ?
343 343 * :ghissue:`5801`: startup_command specified in ipengine_config.py is not executed
344 344 * :ghissue:`5690`: ipython 2.0.0 and pandoc 1.12.2.1 problem
345 345 * :ghissue:`5408`: Add checking/flushing of background output from kernel in mainloop
346 346 * :ghissue:`5407`: clearing message handlers on status=idle loses async output
347 347 * :ghissue:`5467`: Incorrect behavior of up/down keyboard arrows in code cells on wrapped lines
348 348 * :ghissue:`3085`: nicer notebook error message when lacking permissions
349 349 * :ghissue:`5765`: map_sync over empty list raises IndexError
350 350 * :ghissue:`5553`: Notebook matplotlib inline backend: can't set figure facecolor
351 351 * :ghissue:`5710`: inspect.findsource monkeypatch raises wrong exception for C extensions
352 352 * :ghissue:`5706`: Multi-Directory notebooks overwrite each other's checkpoints
353 353 * :ghissue:`5698`: can't require a function named ``f``
354 354 * :ghissue:`5569`: Keyboard shortcuts in documentation are out of date
355 355 * :ghissue:`5566`: Function name printing should use ``__qualname__`` instead of ``__name__`` (Python 3)
356 356 * :ghissue:`5676`: "bookmark -l" not working in ipython 2.0
357 357 * :ghissue:`5555`: Differentiate more clearly between Notebooks and Folders in new UI
358 358 * :ghissue:`5590`: Marked double escape
359 359 * :ghissue:`5514`: import tab-complete fail with ipython 2.0 shell
360 360 * :ghissue:`4012`: Notebook: link to markdown formatting reference
361 361 * :ghissue:`5611`: Typo in 'storemagic' documentation
362 362 * :ghissue:`5589`: Kernel start fails when using --browser argument
363 363 * :ghissue:`5491`: Bug in Windows ipconfig ip address regular expression
364 364 * :ghissue:`5579`: rmagic extension throws 'Error while parsing the string.' when last line is comment
365 365 * :ghissue:`5518`: Ipython2 will not open ipynb in example directory
366 366 * :ghissue:`5561`: New widget documentation has missing notebook link
367 367 * :ghissue:`5128`: Page jumping when output from widget interaction replaced
368 368 * :ghissue:`5519`: IPython.parallel.Client behavior as iterator
369 369 * :ghissue:`5510`: Tab-completion for function argument list
370 370
371 371
372 372 Issues closed in 2.0.0
373 373 ----------------------
374 374
375 375
376 376 GitHub stats for 2013/08/09 - 2014/04/01 (since 1.0.0)
377 377
378 378 These lists are automatically generated, and may be incomplete or contain duplicates.
379 379
380 380 The following 94 authors contributed 3949 commits.
381 381
382 382 * Aaron Meurer
383 383 * Abhinav Upadhyay
384 384 * Adam Riggall
385 385 * Alex Rudy
386 386 * Andrew Mark
387 387 * Angus Griffith
388 388 * Antony Lee
389 389 * Aron Ahmadia
390 390 * Arun Persaud
391 391 * Benjamin Ragan-Kelley
392 392 * Bing Xia
393 393 * Blake Griffith
394 394 * Bouke van der Bijl
395 395 * Bradley M. Froehle
396 396 * Brian E. Granger
397 397 * Carlos Cordoba
398 398 * chapmanb
399 399 * chebee7i
400 400 * Christoph Gohlke
401 401 * Christophe Pradal
402 402 * Cyrille Rossant
403 403 * Damián Avila
404 404 * Daniel B. Vasquez
405 405 * Dav Clark
406 406 * David Hirschfeld
407 407 * David P. Sanders
408 408 * David Wyde
409 409 * David Österberg
410 410 * Doug Blank
411 411 * Dražen Lučanin
412 412 * epifanio
413 413 * Fernando Perez
414 414 * Gabriel Becker
415 415 * Geert Barentsen
416 416 * Hans Meine
417 417 * Ingolf Becker
418 418 * Jake Vanderplas
419 419 * Jakob Gager
420 420 * James Porter
421 421 * Jason Grout
422 422 * Jeffrey Tratner
423 423 * Jonah Graham
424 424 * Jonathan Frederic
425 425 * Joris Van den Bossche
426 426 * Juergen Hasch
427 427 * Julian Taylor
428 428 * Katie Silverio
429 429 * Kevin Burke
430 430 * Kieran O'Mahony
431 431 * Konrad Hinsen
432 432 * Kyle Kelley
433 433 * Lawrence Fu
434 434 * Marc Molla
435 435 * Martín Gaitán
436 436 * Matt Henderson
437 437 * Matthew Brett
438 438 * Matthias Bussonnier
439 439 * Michael Droettboom
440 440 * Mike McKerns
441 441 * Nathan Goldbaum
442 442 * Pablo de Oliveira
443 443 * Pankaj Pandey
444 444 * Pascal Schetelat
445 445 * Paul Ivanov
446 446 * Paul Moore
447 447 * Pere Vilas
448 448 * Peter Davis
449 449 * Philippe Mallet-Ladeira
450 450 * Preston Holmes
451 451 * Puneeth Chaganti
452 452 * Richard Everson
453 453 * Roberto Bonvallet
454 454 * Samuel Ainsworth
455 455 * Sean Vig
456 456 * Shashi Gowda
457 457 * Skipper Seabold
458 458 * Stephan Rave
459 459 * Steve Fox
460 460 * Steven Silvester
461 461 * stonebig
462 462 * Susan Tan
463 463 * Sylvain Corlay
464 464 * Takeshi Kanmae
465 465 * Ted Drain
466 466 * Thomas A Caswell
467 467 * Thomas Kluyver
468 468 * Théophile Studer
469 469 * Volker Braun
470 470 * Wieland Hoffmann
471 471 * Yaroslav Halchenko
472 472 * Yoval P.
473 473 * Yung Siang Liau
474 474 * Zachary Sailer
475 475 * zah
476 476
477 477
478 478 We closed a total of 1121 issues, 687 pull requests and 434 regular issues;
479 479 this is the full list (generated with the script
480 480 :file:`tools/github_stats.py`):
481 481
482 482 Pull Requests (687):
483 483
484 484 * :ghpull:`5487`: remove weird unicode space in the new copyright header
485 485 * :ghpull:`5476`: For 2.0: Fix links in Notebook Help Menu
486 486 * :ghpull:`5337`: Examples reorganization
487 487 * :ghpull:`5436`: CodeMirror shortcuts in QuickHelp
488 488 * :ghpull:`5444`: Fix numeric verification for Int and Float text widgets.
489 489 * :ghpull:`5449`: Stretch keyboard shortcut dialog
490 490 * :ghpull:`5473`: Minor corrections of git-hooks setup instructions
491 491 * :ghpull:`5471`: Add coding magic comment to nbconvert Python template
492 492 * :ghpull:`5452`: print_figure returns unicode for svg
493 493 * :ghpull:`5450`: proposal: remove codename
494 494 * :ghpull:`5462`: DOC : fixed minor error in using topological sort
495 495 * :ghpull:`5463`: make spin_thread tests more forgiving of slow VMs
496 496 * :ghpull:`5464`: Fix starting notebook server with file/directory at command line.
497 497 * :ghpull:`5453`: remove gitwash
498 498 * :ghpull:`5454`: Improve history API docs
499 499 * :ghpull:`5431`: update github_stats and gh_api for 2.0
500 500 * :ghpull:`5290`: Add dual mode JS tests
501 501 * :ghpull:`5451`: check that a handler is actually registered in ShortcutManager.handles
502 502 * :ghpull:`5447`: Add %%python2 cell magic
503 503 * :ghpull:`5439`: Point to the stable SymPy docs, not the dev docs
504 504 * :ghpull:`5437`: Install jquery-ui images
505 505 * :ghpull:`5434`: fix check for empty cells in rst template
506 506 * :ghpull:`5432`: update links in notebook help menu
507 507 * :ghpull:`5435`: Update whatsnew (notebook tour)
508 508 * :ghpull:`5433`: Document extraction of octave and R magics
509 509 * :ghpull:`5428`: Update COPYING.txt
510 510 * :ghpull:`5426`: Separate get_session_info between HistoryAccessor and HistoryManager
511 511 * :ghpull:`5419`: move prompts from margin to main column on small screens
512 512 * :ghpull:`5430`: Make sure `element` is correct in the context of displayed JS
513 513 * :ghpull:`5396`: prevent saving of partially loaded notebooks
514 514 * :ghpull:`5429`: Fix tooltip pager feature
515 515 * :ghpull:`5330`: Updates to shell reference doc
516 516 * :ghpull:`5404`: Fix broken accordion widget
517 517 * :ghpull:`5339`: Don't use fork to start the notebook in js tests
518 518 * :ghpull:`5320`: Fix for Tooltip & completer click focus bug.
519 519 * :ghpull:`5421`: Move configuration of Python test controllers into setup()
520 520 * :ghpull:`5418`: fix typo in ssh launcher send_file
521 521 * :ghpull:`5403`: remove alt-- shortcut
522 522 * :ghpull:`5389`: better log message in deprecated files/ redirect
523 523 * :ghpull:`5333`: Fix filenbmanager.list_dirs fails for Windows user profile directory
524 524 * :ghpull:`5390`: finish PR #5333
525 525 * :ghpull:`5326`: Some gardening on iptest result reporting
526 526 * :ghpull:`5375`: remove unnecessary onload hack from mathjax macro
527 527 * :ghpull:`5368`: Flexbox classes specificity fixes
528 528 * :ghpull:`5331`: fix raw_input CSS
529 529 * :ghpull:`5395`: urlencode images for rst files
530 530 * :ghpull:`5049`: update quickhelp on adding and removing shortcuts
531 531 * :ghpull:`5391`: Fix Gecko (Netscape) keyboard handling
532 532 * :ghpull:`5387`: Respect '\r' characters in nbconvert.
533 533 * :ghpull:`5399`: Revert PR #5388
534 534 * :ghpull:`5388`: Suppress output even when a comment follows ;. Fixes #4525.
535 535 * :ghpull:`5394`: nbconvert doc update
536 536 * :ghpull:`5359`: do not install less sources
537 537 * :ghpull:`5346`: give hint on where to find custom.js
538 538 * :ghpull:`5357`: catch exception in copystat
539 539 * :ghpull:`5380`: Remove DefineShortVerb... line from latex base template
540 540 * :ghpull:`5376`: elide long containers in pretty
541 541 * :ghpull:`5310`: remove raw cell placeholder on focus, closes #5238
542 542 * :ghpull:`5332`: semantic names for indicator icons
543 543 * :ghpull:`5386`: Fix import of socketserver on Python 3
544 544 * :ghpull:`5360`: remove some redundant font-family: monospace
545 545 * :ghpull:`5379`: don't instantiate Application just for default logger
546 546 * :ghpull:`5372`: Don't autoclose strings
547 547 * :ghpull:`5296`: unify keyboard shortcut and codemirror interaction
548 548 * :ghpull:`5349`: Make Hub.registration_timeout configurable
549 549 * :ghpull:`5340`: install bootstrap-tour css
550 550 * :ghpull:`5335`: Update docstring for deepreload module
551 551 * :ghpull:`5321`: Improve assignment regex to match more tuple unpacking syntax
552 552 * :ghpull:`5325`: add NotebookNotary to NotebookApp's class list
553 553 * :ghpull:`5313`: avoid loading preprocessors twice
554 554 * :ghpull:`5308`: fix HTML capitalization in Highlight2HTML
555 555 * :ghpull:`5295`: OutputArea.append_type functions are not prototype methods
556 556 * :ghpull:`5318`: Fix local import of select_figure_formats
557 557 * :ghpull:`5300`: Fix NameError: name '_rl' is not defined
558 558 * :ghpull:`5292`: focus next cell on shift+enter
559 559 * :ghpull:`5291`: debug occasional error in test_queue_status
560 560 * :ghpull:`5289`: Finishing up #5274 (widget paths fixes)
561 561 * :ghpull:`5232`: Make nbconvert html full output like notebook's html.
562 562 * :ghpull:`5288`: Correct initial state of kernel status indicator
563 563 * :ghpull:`5253`: display any output from this session in terminal console
564 564 * :ghpull:`4802`: Tour of the notebook UI (was UI elements inline with highlighting)
565 565 * :ghpull:`5285`: Update signature presentation in pinfo classes
566 566 * :ghpull:`5268`: Refactoring Notebook.command_mode
567 567 * :ghpull:`5226`: Don't run PYTHONSTARTUP file if a file or code is passed
568 568 * :ghpull:`5283`: Remove Widget.closed attribute
569 569 * :ghpull:`5279`: nbconvert: Make sure node is atleast version 0.9.12
570 570 * :ghpull:`5281`: fix a typo introduced by a rebased PR
571 571 * :ghpull:`5280`: append Firefox overflow-x fix
572 572 * :ghpull:`5277`: check that PIL can save JPEG to BytesIO
573 573 * :ghpull:`5044`: Store timestamps for modules to autoreload
574 574 * :ghpull:`5278`: Update whatsnew doc from pr files
575 575 * :ghpull:`5276`: Fix kernel restart in case connection file is deleted.
576 576 * :ghpull:`5272`: allow highlighting language to be set from notebook metadata
577 577 * :ghpull:`5158`: log refusal to serve hidden directories
578 578 * :ghpull:`5188`: New events system
579 579 * :ghpull:`5265`: Missing class def for TimeoutError
580 580 * :ghpull:`5267`: normalize unicode in notebook API tests
581 581 * :ghpull:`5076`: Refactor keyboard handling
582 582 * :ghpull:`5241`: Add some tests for utils
583 583 * :ghpull:`5261`: Don't allow edit mode up arrow to continue past index == 0
584 584 * :ghpull:`5223`: use on-load event to trigger resizable images
585 585 * :ghpull:`5252`: make one strptime call at import of jsonutil
586 586 * :ghpull:`5153`: Dashboard sorting
587 587 * :ghpull:`5169`: Allow custom header
588 588 * :ghpull:`5242`: clear _reply_content cache before using it
589 589 * :ghpull:`5194`: require latex titles to be ascii
590 590 * :ghpull:`5244`: try to avoid EADDRINUSE errors on travis
591 591 * :ghpull:`5245`: support extracted output in HTML template
592 592 * :ghpull:`5209`: make input_area css generic to cells
593 593 * :ghpull:`5246`: less %pylab, more cowbell!
594 594 * :ghpull:`4895`: Improvements to %run completions
595 595 * :ghpull:`5243`: Add Javscript to base display priority list.
596 596 * :ghpull:`5175`: Audit .html() calls take #2
597 597 * :ghpull:`5146`: Dual mode bug fixes.
598 598 * :ghpull:`5207`: Children fire event
599 599 * :ghpull:`5215`: Dashboard "Running" Tab
600 600 * :ghpull:`5240`: Remove unused IPython.nbconvert.utils.console module
601 601 * :ghpull:`5239`: Fix exclusion of tests directories from coverage reports
602 602 * :ghpull:`5203`: capture some logging/warning output in some tests
603 603 * :ghpull:`5216`: fixup positional arg handling in notebook app
604 604 * :ghpull:`5229`: get _ipython_display_ method safely
605 605 * :ghpull:`5234`: DOC : modified docs is HasTraits.traits and HasTraits.class_traits
606 606 * :ghpull:`5221`: Change widget children List to Tuple.
607 607 * :ghpull:`5231`: don't forget base_url when updating address bar in rename
608 608 * :ghpull:`5173`: Moved widget files into static/widgets/*
609 609 * :ghpull:`5222`: Unset PYTHONWARNINGS envvar before running subprocess tests.
610 610 * :ghpull:`5172`: Prevent page breaks when printing notebooks via print-view.
611 611 * :ghpull:`4985`: Add automatic Closebrackets function to Codemirror.
612 612 * :ghpull:`5220`: Make traitlets notify check more robust against classes redefining equality and bool
613 613 * :ghpull:`5197`: If there is an error comparing traitlet values when setting a trait, default to go ahead and notify of the new value.
614 614 * :ghpull:`5210`: fix pyreadline import in rlineimpl
615 615 * :ghpull:`5212`: Wrap nbconvert Markdown/Heading cells in live divs
616 616 * :ghpull:`5200`: Allow to pass option to jinja env
617 617 * :ghpull:`5202`: handle nodejs executable on debian
618 618 * :ghpull:`5112`: band-aid for completion
619 619 * :ghpull:`5187`: handle missing output metadata in nbconvert
620 620 * :ghpull:`5181`: use gnureadline on OS X
621 621 * :ghpull:`5136`: set default value from signature defaults in interact
622 622 * :ghpull:`5132`: remove application/pdf->pdf transform in javascript
623 623 * :ghpull:`5116`: reorganize who knows what about paths
624 624 * :ghpull:`5165`: Don't introspect __call__ for simple callables
625 625 * :ghpull:`5170`: Added msg_throttle sync=True widget traitlet
626 626 * :ghpull:`5191`: Translate markdown link to rst
627 627 * :ghpull:`5037`: FF Fix: alignment and scale of text widget
628 628 * :ghpull:`5179`: remove websocket url
629 629 * :ghpull:`5110`: add InlineBackend.print_figure_kwargs
630 630 * :ghpull:`5147`: Some template URL changes
631 631 * :ghpull:`5100`: remove base_kernel_url
632 632 * :ghpull:`5163`: Simplify implementation of TemporaryWorkingDirectory.
633 633 * :ghpull:`5166`: remove mktemp usage
634 634 * :ghpull:`5133`: don't use combine option on ucs package
635 635 * :ghpull:`5089`: Remove legacy azure nbmanager
636 636 * :ghpull:`5159`: remove append_json reference
637 637 * :ghpull:`5095`: handle image size metadata in nbconvert html
638 638 * :ghpull:`5156`: fix IPython typo, closes #5155
639 639 * :ghpull:`5150`: fix a link that was broken
640 640 * :ghpull:`5114`: use non-breaking space for button with no description
641 641 * :ghpull:`4778`: add APIs for installing notebook extensions
642 642 * :ghpull:`5125`: Fix the display of functions with keyword-only arguments on Python 3.
643 643 * :ghpull:`5097`: minor notebook logging changes
644 644 * :ghpull:`5047`: only validate package_data when it might be used
645 645 * :ghpull:`5121`: fix remove event in KeyboardManager.register_events
646 646 * :ghpull:`5119`: Removed 'list' view from Variable Inspector example
647 647 * :ghpull:`4925`: Notebook manager api fixes
648 648 * :ghpull:`4996`: require print_method to be a bound method
649 649 * :ghpull:`5108`: require specifying the version for gh-pages
650 650 * :ghpull:`5111`: Minor typo in docstring of IPython.parallel DirectView
651 651 * :ghpull:`5098`: mostly debugging changes for IPython.parallel
652 652 * :ghpull:`5087`: trust cells with no output
653 653 * :ghpull:`5059`: Fix incorrect `Patch` logic in widget code
654 654 * :ghpull:`5075`: More flexible box model fixes
655 655 * :ghpull:`5091`: Provide logging messages in ipcluster log when engine or controllers fail to start
656 656 * :ghpull:`5090`: Print a warning when iptest is run from the IPython source directory
657 657 * :ghpull:`5077`: flush replies when entering an eventloop
658 658 * :ghpull:`5055`: Minimal changes to import IPython from IronPython
659 659 * :ghpull:`5078`: Updating JS tests README.md
660 660 * :ghpull:`5083`: don't create js test directories unless they are being used
661 661 * :ghpull:`5062`: adjust some events in nb_roundtrip
662 662 * :ghpull:`5043`: various unicode / url fixes
663 663 * :ghpull:`5066`: remove (almost) all mentions of pylab from our examples
664 664 * :ghpull:`4977`: ensure scp destination directories exist (with mkdir -p)
665 665 * :ghpull:`5053`: Move&rename JS tests
666 666 * :ghpull:`5067`: show traceback in widget handlers
667 667 * :ghpull:`4920`: Adding PDFFormatter and kernel side handling of PDF display data
668 668 * :ghpull:`5048`: Add edit/command mode indicator
669 669 * :ghpull:`5061`: make execute button in menu bar match shift-enter
670 670 * :ghpull:`5052`: Add q to toggle the pager.
671 671 * :ghpull:`5070`: fix flex: auto
672 672 * :ghpull:`5065`: Add example of using annotations in interact
673 673 * :ghpull:`5063`: another pass on Interact example notebooks
674 674 * :ghpull:`5051`: FF Fix: code cell missing hscroll (2)
675 675 * :ghpull:`4960`: Interact/Interactive for widget
676 676 * :ghpull:`5045`: Clear timeout in multi-press keyboard shortcuts.
677 677 * :ghpull:`5060`: Change 'bind' to 'link'
678 678 * :ghpull:`5039`: Expose kernel_info method on inprocess kernel client
679 679 * :ghpull:`5058`: Fix iopubwatcher.py example script.
680 680 * :ghpull:`5035`: FF Fix: code cell missing hscroll
681 681 * :ghpull:`5040`: Polishing some docs
682 682 * :ghpull:`5001`: Add directory navigation to dashboard
683 683 * :ghpull:`5042`: Remove duplicated Channel ABC classes.
684 684 * :ghpull:`5036`: FF Fix: ext link icon same line as link text in help menu
685 685 * :ghpull:`4975`: setup.py changes for 2.0
686 686 * :ghpull:`4774`: emit event on appended element on dom
687 687 * :ghpull:`5023`: Widgets- add ability to pack and unpack arrays on JS side.
688 688 * :ghpull:`5003`: Fix pretty reprs of super() objects
689 689 * :ghpull:`4974`: make paste focus the pasted cell
690 690 * :ghpull:`5012`: Make `SelectionWidget.values` a dict
691 691 * :ghpull:`5018`: Prevent 'iptest IPython' from trying to run.
692 692 * :ghpull:`5025`: citation2latex filter (using HTMLParser)
693 693 * :ghpull:`5027`: pin lessc to 1.4
694 694 * :ghpull:`4952`: Widget test inconsistencies
695 695 * :ghpull:`5014`: Fix command mode & popup view bug
696 696 * :ghpull:`4842`: more subtle kernel indicator
697 697 * :ghpull:`5017`: Add notebook examples link to help menu.
698 698 * :ghpull:`5015`: don't write cell.trusted to disk
699 699 * :ghpull:`5007`: Update whatsnew doc from PR files
700 700 * :ghpull:`5010`: Fixes for widget alignment in FF
701 701 * :ghpull:`4901`: Add a convenience class to sync traitlet attributes
702 702 * :ghpull:`5008`: updated explanation of 'pyin' messages
703 703 * :ghpull:`5004`: Fix widget vslider spacing
704 704 * :ghpull:`4933`: Small Widget inconsistency fixes
705 705 * :ghpull:`4979`: add versioning notes to small message spec changes
706 706 * :ghpull:`4893`: add font-awesome 3.2.1
707 707 * :ghpull:`4982`: Live readout for slider widgets
708 708 * :ghpull:`4813`: make help menu a template
709 709 * :ghpull:`4939`: Embed qtconsole docs (continued)
710 710 * :ghpull:`4964`: remove shift-= merge keyboard shortcut
711 711 * :ghpull:`4504`: Allow input transformers to raise SyntaxError
712 712 * :ghpull:`4929`: Fixing various modal/focus related bugs
713 713 * :ghpull:`4971`: Fixing issues with js tests
714 714 * :ghpull:`4972`: Work around problem in doctest discovery in Python 3.4 with PyQt
715 715 * :ghpull:`4937`: pickle arrays with dtype=object
716 716 * :ghpull:`4934`: `ipython profile create` respects `--ipython-dir`
717 717 * :ghpull:`4954`: generate unicode filename
718 718 * :ghpull:`4845`: Add Origin Checking.
719 719 * :ghpull:`4916`: Fine tuning the behavior of the modal UI
720 720 * :ghpull:`4966`: Ignore sys.argv for NotebookNotary in tests
721 721 * :ghpull:`4967`: Fix typo in warning about web socket being closed
722 722 * :ghpull:`4965`: Remove mention of iplogger from setup.py
723 723 * :ghpull:`4962`: Fixed typos in quick-help text
724 724 * :ghpull:`4953`: add utils.wait_for_idle in js tests
725 725 * :ghpull:`4870`: ipython_directive, report except/warn in block and add :okexcept: :okwarning: options to suppress
726 726 * :ghpull:`4662`: Menu cleanup
727 727 * :ghpull:`4824`: sign notebooks
728 728 * :ghpull:`4943`: Docs shotgun 4
729 729 * :ghpull:`4848`: avoid import of nearby temporary with %edit
730 730 * :ghpull:`4950`: Two fixes for file upload related bugs
731 731 * :ghpull:`4927`: there shouldn't be a 'files/' prefix in FileLink[s]
732 732 * :ghpull:`4928`: use importlib.machinery when available
733 733 * :ghpull:`4949`: Remove the docscrape modules, which are part of numpydoc
734 734 * :ghpull:`4849`: Various unicode fixes (mostly on Windows)
735 735 * :ghpull:`4932`: always point py3compat.input to builtin_mod.input
736 736 * :ghpull:`4807`: Correct handling of ansi colour codes when nbconverting to latex
737 737 * :ghpull:`4922`: Python nbconvert output shouldn't have output
738 738 * :ghpull:`4912`: Skip some Windows io failures
739 739 * :ghpull:`4919`: flush output before showing tracebacks
740 740 * :ghpull:`4915`: ZMQCompleter inherits from IPCompleter
741 741 * :ghpull:`4890`: better cleanup channel FDs
742 742 * :ghpull:`4880`: set profile name from profile_dir
743 743 * :ghpull:`4853`: fix setting image height/width from metadata
744 744 * :ghpull:`4786`: Reduce spacing of heading cells
745 745 * :ghpull:`4680`: Minimal pandoc version warning
746 746 * :ghpull:`4908`: detect builtin docstrings in oinspect
747 747 * :ghpull:`4911`: Don't use `python -m package` on Windows Python 2
748 748 * :ghpull:`4909`: sort dictionary keys before comparison, ordering is not guaranteed
749 749 * :ghpull:`4374`: IPEP 23: Backbone.js Widgets
750 750 * :ghpull:`4903`: use https for all embeds
751 751 * :ghpull:`4894`: Shortcut changes
752 752 * :ghpull:`4897`: More detailed documentation about kernel_cmd
753 753 * :ghpull:`4891`: Squash a few Sphinx warnings from nbconvert.utils.lexers docstrings
754 754 * :ghpull:`4679`: JPG compression for inline pylab
755 755 * :ghpull:`4708`: Fix indent and center
756 756 * :ghpull:`4789`: fix IPython.embed
757 757 * :ghpull:`4655`: prefer marked to pandoc for markdown2html
758 758 * :ghpull:`4876`: don't show tooltip if object is not found
759 759 * :ghpull:`4873`: use 'combine' option to ucs package
760 760 * :ghpull:`4732`: Accents in notebook names and in command-line (nbconvert)
761 761 * :ghpull:`4867`: Update URL for Lawrence Hall of Science webcam image
762 762 * :ghpull:`4868`: Static path fixes
763 763 * :ghpull:`4858`: fix tb_offset when running a file
764 764 * :ghpull:`4826`: some $.html( -> $.text(
765 765 * :ghpull:`4847`: add js kernel_info request
766 766 * :ghpull:`4832`: allow NotImplementedError in formatters
767 767 * :ghpull:`4803`: BUG: fix cython magic support in ipython_directive
768 768 * :ghpull:`4865`: `build` listed twice in .gitignore. Removing one.
769 769 * :ghpull:`4851`: fix tooltip token regex for single-character names
770 770 * :ghpull:`4846`: Remove some leftover traces of irunner
771 771 * :ghpull:`4820`: fix regex for cleaning old logs with ipcluster
772 772 * :ghpull:`4844`: adjustments to notebook app logging
773 773 * :ghpull:`4840`: Error in Session.send_raw()
774 774 * :ghpull:`4819`: update CodeMirror to 3.21
775 775 * :ghpull:`4823`: Minor fixes for typos/inconsistencies in parallel docs
776 776 * :ghpull:`4811`: document code mirror tab and shift-tab
777 777 * :ghpull:`4795`: merge reveal templates
778 778 * :ghpull:`4796`: update components
779 779 * :ghpull:`4806`: Correct order of packages for unicode in nbconvert to LaTeX
780 780 * :ghpull:`4800`: Qt frontend: Handle 'aborted' prompt replies.
781 781 * :ghpull:`4794`: Compatibility fix for Python3 (Issue #4783 )
782 782 * :ghpull:`4799`: minor js test fix
783 783 * :ghpull:`4788`: warn when notebook is started in pylab mode
784 784 * :ghpull:`4772`: Notebook server info files
785 785 * :ghpull:`4797`: be conservative about kernel_info implementation
786 786 * :ghpull:`4787`: non-python kernels run python code with qtconsole
787 787 * :ghpull:`4565`: various display type validations
788 788 * :ghpull:`4703`: Math macro in jinja templates.
789 789 * :ghpull:`4781`: Fix "Source" text for the "Other Syntax" section of the "Typesetting Math" notebook
790 790 * :ghpull:`4776`: Manually document py3compat module.
791 791 * :ghpull:`4533`: propagate display metadata to all mimetypes
792 792 * :ghpull:`4785`: Replacing a for-in loop by an index loop on an array
793 793 * :ghpull:`4780`: Updating CSS for UI example.
794 794 * :ghpull:`3605`: Modal UI
795 795 * :ghpull:`4758`: Python 3.4 fixes
796 796 * :ghpull:`4735`: add some HTML error pages
797 797 * :ghpull:`4775`: Update whatsnew doc from PR files
798 798 * :ghpull:`4760`: Make examples and docs more Python 3 aware
799 799 * :ghpull:`4773`: Don't wait forever for notebook server to launch/die for tests
800 800 * :ghpull:`4768`: Qt console: Fix _prompt_pos accounting on timer flush output.
801 801 * :ghpull:`4727`: Remove Nbconvert template loading magic
802 802 * :ghpull:`4763`: Set numpydoc options to produce fewer Sphinx warnings.
803 803 * :ghpull:`4770`: alway define aliases, even if empty
804 804 * :ghpull:`4766`: add `python -m` entry points for everything
805 805 * :ghpull:`4767`: remove manpages for irunner, iplogger
806 806 * :ghpull:`4751`: Added --post-serve explanation into the nbconvert docs.
807 807 * :ghpull:`4762`: whitelist alphanumeric characters for cookie_name
808 808 * :ghpull:`4625`: Deprecate %profile magic
809 809 * :ghpull:`4745`: warn on failed formatter calls
810 810 * :ghpull:`4746`: remove redundant cls alias on Windows
811 811 * :ghpull:`4749`: Fix bug in determination of public ips.
812 812 * :ghpull:`4715`: restore use of tornado static_url in templates
813 813 * :ghpull:`4748`: fix race condition in profiledir creation.
814 814 * :ghpull:`4720`: never use ssh multiplexer in tunnels
815 815 * :ghpull:`4658`: Bug fix for #4643: Regex object needs to be reset between calls in toolt...
816 816 * :ghpull:`4561`: Add Formatter.pop(type)
817 817 * :ghpull:`4712`: Docs shotgun 3
818 818 * :ghpull:`4713`: Fix saving kernel history in Python 2
819 819 * :ghpull:`4744`: don't use lazily-evaluated rc.ids in wait_for_idle
820 820 * :ghpull:`4740`: %env can't set variables
821 821 * :ghpull:`4737`: check every link when detecting virutalenv
822 822 * :ghpull:`4738`: don't inject help into user_ns
823 823 * :ghpull:`4739`: skip html nbconvert tests when their dependencies are missing
824 824 * :ghpull:`4730`: Fix stripping continuation prompts when copying from Qt console
825 825 * :ghpull:`4725`: Doc fixes
826 826 * :ghpull:`4656`: Nbconvert HTTP service
827 827 * :ghpull:`4710`: make @interactive decorator friendlier with dill
828 828 * :ghpull:`4722`: allow purging local results as long as they are not outstanding
829 829 * :ghpull:`4549`: Updated IPython console lexers.
830 830 * :ghpull:`4570`: Update IPython directive
831 831 * :ghpull:`4719`: Fix comment typo in prefilter.py
832 832 * :ghpull:`4575`: make sure to encode URL components for API requests
833 833 * :ghpull:`4718`: Fixed typo in displaypub
834 834 * :ghpull:`4716`: Remove input_prefilter hook
835 835 * :ghpull:`4691`: survive failure to bind to localhost in zmq.iostream
836 836 * :ghpull:`4696`: don't do anything if add_anchor fails
837 837 * :ghpull:`4711`: some typos in the docs
838 838 * :ghpull:`4700`: use if main block in entry points
839 839 * :ghpull:`4692`: setup.py symlink improvements
840 840 * :ghpull:`4265`: JSON configuration file
841 841 * :ghpull:`4505`: Nbconvert latex markdown images2
842 842 * :ghpull:`4608`: transparent background match ... all colors
843 843 * :ghpull:`4678`: allow ipython console to handle text/plain display
844 844 * :ghpull:`4706`: remove irunner, iplogger
845 845 * :ghpull:`4701`: Delete an old dictionary available for selecting the aligment of text.
846 846 * :ghpull:`4702`: Making reveal font-size a relative unit.
847 847 * :ghpull:`4649`: added a quiet option to %cpaste to suppress output
848 848 * :ghpull:`4690`: Option to spew subprocess streams during tests
849 849 * :ghpull:`4688`: Fixed various typos in docstrings.
850 850 * :ghpull:`4645`: CasperJs utility functions.
851 851 * :ghpull:`4670`: Stop bundling the numpydoc Sphinx extension
852 852 * :ghpull:`4675`: common IPython prefix for ModIndex
853 853 * :ghpull:`4672`: Remove unused 'attic' module
854 854 * :ghpull:`4671`: Fix docstrings in utils.text
855 855 * :ghpull:`4669`: add missing help strings to HistoryManager configurables
856 856 * :ghpull:`4668`: Make non-ASCII docstring unicode
857 857 * :ghpull:`4650`: added a note about sharing of nbconvert tempates
858 858 * :ghpull:`4646`: Fixing various output related things:
859 859 * :ghpull:`4665`: check for libedit in readline on OS X
860 860 * :ghpull:`4606`: Make running PYTHONSTARTUP optional
861 861 * :ghpull:`4654`: Fixing left padding of text cells to match that of code cells.
862 862 * :ghpull:`4306`: add raw_mimetype metadata to raw cells
863 863 * :ghpull:`4576`: Tighten up the vertical spacing on cells and make the padding of cells more consistent
864 864 * :ghpull:`4353`: Don't reset the readline completer after each prompt
865 865 * :ghpull:`4567`: Adding prompt area to non-CodeCells to indent content.
866 866 * :ghpull:`4446`: Use SVG plots in OctaveMagic by default due to lack of Ghostscript on Windows Octave
867 867 * :ghpull:`4613`: remove configurable.created
868 868 * :ghpull:`4631`: Use argument lists for command help tests
869 869 * :ghpull:`4633`: Modifies test_get_long_path_name_winr32() to allow for long path names in temp dir
870 870 * :ghpull:`4642`: Allow docs to build without PyQt installed.
871 871 * :ghpull:`4641`: Don't check for wx in the test suite.
872 872 * :ghpull:`4622`: make QtConsole Lexer configurable
873 873 * :ghpull:`4594`: Fixed #2923 Move Save Away from Cut in toolbar
874 874 * :ghpull:`4593`: don't interfere with set_next_input contents in qtconsole
875 875 * :ghpull:`4640`: Support matplotlib's Gtk3 backend in --pylab mode
876 876 * :ghpull:`4639`: Minor import fix to get qtconsole with --pylab=qt working
877 877 * :ghpull:`4637`: Fixed typo in links.txt.
878 878 * :ghpull:`4634`: Fix nbrun in notebooks with non-code cells.
879 879 * :ghpull:`4632`: Restore the ability to run tests from a function.
880 880 * :ghpull:`4624`: Fix crash when $EDITOR is non-ASCII
881 881 * :ghpull:`4453`: Play nice with App Nap
882 882 * :ghpull:`4541`: relax ipconfig matching on Windows
883 883 * :ghpull:`4552`: add pickleutil.use_dill
884 884 * :ghpull:`4590`: Font awesome for IPython slides
885 885 * :ghpull:`4589`: Inherit the width of pre code inside the input code cells.
886 886 * :ghpull:`4588`: Update reveal.js CDN to 2.5.0.
887 887 * :ghpull:`4569`: store cell toolbar preset in notebook metadata
888 888 * :ghpull:`4609`: Fix bytes regex for Python 3.
889 889 * :ghpull:`4581`: Writing unicode to stdout
890 890 * :ghpull:`4591`: Documenting codemirror shorcuts.
891 891 * :ghpull:`4607`: Tutorial doc should link to user config intro
892 892 * :ghpull:`4601`: test that rename fails with 409 if it would clobber
893 893 * :ghpull:`4599`: re-cast int/float subclasses to int/float in json_clean
894 894 * :ghpull:`4542`: new `ipython history clear` subcommand
895 895 * :ghpull:`4568`: don't use lazily-evaluated rc.ids in wait_for_idle
896 896 * :ghpull:`4572`: DOC: %profile docstring should reference %prun
897 897 * :ghpull:`4571`: no longer need 3 suffix on travis, tox
898 898 * :ghpull:`4566`: Fixing cell_type in CodeCell constructor.
899 899 * :ghpull:`4563`: Specify encoding for reading notebook file.
900 900 * :ghpull:`4452`: support notebooks in %run
901 901 * :ghpull:`4546`: fix warning condition on notebook startup
902 902 * :ghpull:`4540`: Apidocs3
903 903 * :ghpull:`4553`: Fix Python 3 handling of urllib
904 904 * :ghpull:`4543`: make hiding of initial namespace optional
905 905 * :ghpull:`4517`: send shutdown_request on exit of `ipython console`
906 906 * :ghpull:`4528`: improvements to bash completion
907 907 * :ghpull:`4532`: Hide dynamically defined metaclass base from Sphinx.
908 908 * :ghpull:`4515`: Spring Cleaning, and Load speedup
909 909 * :ghpull:`4529`: note routing identities needed for input requests
910 910 * :ghpull:`4514`: allow restart in `%run -d`
911 911 * :ghpull:`4527`: add redirect for 1.0-style 'files/' prefix links
912 912 * :ghpull:`4526`: Allow unicode arguments to passwd_check on Python 2
913 913 * :ghpull:`4403`: Global highlight language selection.
914 914 * :ghpull:`4250`: outputarea.js: Wrap inline SVGs inside an iframe
915 915 * :ghpull:`4521`: Read wav files in binary mode
916 916 * :ghpull:`4444`: Css cleaning
917 917 * :ghpull:`4523`: Use username and password for MongoDB on ShiningPanda
918 918 * :ghpull:`4510`: Update whatsnew from PR files
919 919 * :ghpull:`4441`: add `setup.py jsversion`
920 920 * :ghpull:`4518`: Fix for race condition in url file decoding.
921 921 * :ghpull:`4497`: don't automatically unpack datetime objects in the message spec
922 922 * :ghpull:`4506`: wait for empty queues as well as load-balanced tasks
923 923 * :ghpull:`4492`: Configuration docs refresh
924 924 * :ghpull:`4508`: Fix some uses of map() in Qt console completion code.
925 925 * :ghpull:`4498`: Daemon StreamCapturer
926 926 * :ghpull:`4499`: Skip clipboard test on unix systems if headless.
927 927 * :ghpull:`4460`: Better clipboard handling, esp. with pywin32
928 928 * :ghpull:`4496`: Pass nbformat object to write call to save .py script
929 929 * :ghpull:`4466`: various pandoc latex fixes
930 930 * :ghpull:`4473`: Setup for Python 2/3
931 931 * :ghpull:`4459`: protect against broken repr in lib.pretty
932 932 * :ghpull:`4457`: Use ~/.ipython as default config directory
933 933 * :ghpull:`4489`: check realpath of env in init_virtualenv
934 934 * :ghpull:`4490`: fix possible race condition in test_await_data
935 935 * :ghpull:`4476`: Fix: Remove space added by display(JavaScript) on page reload
936 936 * :ghpull:`4398`: [Notebook] Deactivate tooltip on tab by default.
937 937 * :ghpull:`4480`: Docs shotgun 2
938 938 * :ghpull:`4488`: fix typo in message spec doc
939 939 * :ghpull:`4479`: yet another JS race condition fix
940 940 * :ghpull:`4477`: Allow incremental builds of the html_noapi docs target
941 941 * :ghpull:`4470`: Various Config object cleanups
942 942 * :ghpull:`4410`: make close-and-halt work on new tabs in Chrome
943 943 * :ghpull:`4469`: Python 3 & getcwdu
944 944 * :ghpull:`4451`: fix: allow JS test to run after shutdown test
945 945 * :ghpull:`4456`: Simplify StreamCapturer for subprocess testing
946 946 * :ghpull:`4464`: Correct description for Bytes traitlet type
947 947 * :ghpull:`4465`: Clean up MANIFEST.in
948 948 * :ghpull:`4461`: Correct TypeError message in svg2pdf
949 949 * :ghpull:`4458`: use signalstatus if exit status is undefined
950 950 * :ghpull:`4438`: Single codebase Python 3 support (again)
951 951 * :ghpull:`4198`: Version conversion, support for X to Y even if Y < X (nbformat)
952 952 * :ghpull:`4415`: More tooltips in the Notebook menu
953 953 * :ghpull:`4450`: remove monkey patch for older versions of tornado
954 954 * :ghpull:`4423`: Fix progress bar and scrolling bug.
955 955 * :ghpull:`4435`: raise 404 on not found static file
956 956 * :ghpull:`4442`: fix and add shim for change introduce by #4195
957 957 * :ghpull:`4436`: allow `require("nbextensions/extname")` to load from IPYTHONDIR/nbextensions
958 958 * :ghpull:`4437`: don't compute etags in static file handlers
959 959 * :ghpull:`4427`: notebooks should always have one checkpoint
960 960 * :ghpull:`4425`: fix js pythonisme
961 961 * :ghpull:`4195`: IPEP 21: widget messages
962 962 * :ghpull:`4434`: Fix broken link for Dive Into Python.
963 963 * :ghpull:`4428`: bump minimum tornado version to 3.1.0
964 964 * :ghpull:`4302`: Add an Audio display class
965 965 * :ghpull:`4285`: Notebook javascript test suite using CasperJS
966 966 * :ghpull:`4420`: Allow checking for backports via milestone
967 967 * :ghpull:`4426`: set kernel cwd to notebook's directory
968 968 * :ghpull:`4389`: By default, Magics inherit from Configurable
969 969 * :ghpull:`4393`: Capture output from subprocs during test, and display on failure
970 970 * :ghpull:`4419`: define InlineBackend configurable in its own file
971 971 * :ghpull:`4303`: Multidirectory support for the Notebook
972 972 * :ghpull:`4371`: Restored ipython profile locate dir and fixed typo. (Fixes #3708).
973 973 * :ghpull:`4414`: Specify unicode type properly in rmagic
974 974 * :ghpull:`4413`: don't instantiate IPython shell as class attr
975 975 * :ghpull:`4400`: Remove 5s wait on inactivity on GUI inputhook loops
976 976 * :ghpull:`4412`: Fix traitlet _notify_trait by-ref issue
977 977 * :ghpull:`4378`: split adds new cell above, rather than below
978 978 * :ghpull:`4405`: Bring display of builtin types and functions in line with Py 2
979 979 * :ghpull:`4367`: clean up of documentation files
980 980 * :ghpull:`4401`: Provide a name of the HistorySavingThread
981 981 * :ghpull:`4384`: fix menubar height measurement
982 982 * :ghpull:`4377`: fix tooltip cancel
983 983 * :ghpull:`4293`: Factorise code in tooltip for julia monkeypatching
984 984 * :ghpull:`4292`: improve js-completer logic.
985 985 * :ghpull:`4363`: set_next_input: keep only last input when repeatedly called in a single cell
986 986 * :ghpull:`4382`: Use safe_hasattr in dir2
987 987 * :ghpull:`4379`: fix (CTRL-M -) shortcut for splitting cell in FF
988 988 * :ghpull:`4380`: Test and fixes for localinterfaces
989 989 * :ghpull:`4372`: Don't assume that SyntaxTB is always called with a SyntaxError
990 990 * :ghpull:`4342`: Return value directly from the try block and avoid a variable
991 991 * :ghpull:`4154`: Center LaTeX and figures in markdown
992 992 * :ghpull:`4311`: %load -s to load specific functions or classes
993 993 * :ghpull:`4350`: WinHPC launcher fixes
994 994 * :ghpull:`4345`: Make irunner compatible with upcoming pexpect 3.0 interface
995 995 * :ghpull:`4276`: Support container methods in config
996 996 * :ghpull:`4359`: test_pylabtools also needs to modify matplotlib.rcParamsOrig
997 997 * :ghpull:`4355`: remove hardcoded box-orient
998 998 * :ghpull:`4333`: Add Edit Notebook Metadata to Edit menu
999 999 * :ghpull:`4349`: Script to update What's New file
1000 1000 * :ghpull:`4348`: Call PDF viewer after latex compiling (nbconvert)
1001 1001 * :ghpull:`4346`: getpass() on Windows & Python 2 needs bytes prompt
1002 1002 * :ghpull:`4304`: use netifaces for faster IPython.utils.localinterfaces
1003 1003 * :ghpull:`4305`: Add even more ways to populate localinterfaces
1004 1004 * :ghpull:`4313`: remove strip_math_space
1005 1005 * :ghpull:`4325`: Some changes to improve readability.
1006 1006 * :ghpull:`4281`: Adjust tab completion widget if too close to bottom of page.
1007 1007 * :ghpull:`4347`: Remove pycolor script
1008 1008 * :ghpull:`4322`: Scroll to the top after change of slides in the IPython slides
1009 1009 * :ghpull:`4289`: Fix scrolling output (not working post clear_output changes)
1010 1010 * :ghpull:`4343`: Make parameters for kernel start method more general
1011 1011 * :ghpull:`4237`: Keywords should shadow magic functions
1012 1012 * :ghpull:`4338`: adjust default value of level in sync_imports
1013 1013 * :ghpull:`4328`: Remove unused loop variable.
1014 1014 * :ghpull:`4340`: fix mathjax download url to new GitHub format
1015 1015 * :ghpull:`4336`: use simple replacement rather than string formatting in format_kernel_cmd
1016 1016 * :ghpull:`4264`: catch unicode error listing profiles
1017 1017 * :ghpull:`4314`: catch EACCES when binding notebook app
1018 1018 * :ghpull:`4324`: Remove commented addthis toolbar
1019 1019 * :ghpull:`4327`: Use the with statement to open a file.
1020 1020 * :ghpull:`4318`: fix initial sys.path
1021 1021 * :ghpull:`4315`: Explicitly state what version of Pandoc is supported in docs/install
1022 1022 * :ghpull:`4316`: underscore missing on notebook_p4
1023 1023 * :ghpull:`4295`: Implement boundary option for load magic (#1093)
1024 1024 * :ghpull:`4300`: traits defauts are strings not object
1025 1025 * :ghpull:`4297`: Remove an unreachable return statement.
1026 1026 * :ghpull:`4260`: Use subprocess for system_raw
1027 1027 * :ghpull:`4277`: add nbextensions
1028 1028 * :ghpull:`4294`: don't require tornado 3 in `--post serve`
1029 1029 * :ghpull:`4270`: adjust Scheduler timeout logic
1030 1030 * :ghpull:`4278`: add `-a` to easy_install command in libedit warning
1031 1031 * :ghpull:`4282`: Enable automatic line breaks in MathJax.
1032 1032 * :ghpull:`4279`: Fixing line-height of list items in tree view.
1033 1033 * :ghpull:`4253`: fixes #4039.
1034 1034 * :ghpull:`4131`: Add module's name argument in %%cython magic
1035 1035 * :ghpull:`4269`: Add mathletters option and longtable package to latex_base.tplx
1036 1036 * :ghpull:`4230`: Switch correctly to the user's default matplotlib backend after inline.
1037 1037 * :ghpull:`4271`: Hopefully fix ordering of output on ShiningPanda
1038 1038 * :ghpull:`4239`: more informative error message for bad serialization
1039 1039 * :ghpull:`4263`: Fix excludes for IPython.testing
1040 1040 * :ghpull:`4112`: nbconvert: Latex template refactor
1041 1041 * :ghpull:`4261`: Fixing a formatting error in the custom display example notebook.
1042 1042 * :ghpull:`4259`: Fix Windows test exclusions
1043 1043 * :ghpull:`4229`: Clear_output: Animation & widget related changes.
1044 1044 * :ghpull:`4151`: Refactor alias machinery
1045 1045 * :ghpull:`4153`: make timeit return an object that contains values
1046 1046 * :ghpull:`4258`: to-backport label is now 1.2
1047 1047 * :ghpull:`4242`: Allow passing extra arguments to iptest through for nose
1048 1048 * :ghpull:`4257`: fix unicode argv parsing
1049 1049 * :ghpull:`4166`: avoid executing code in utils.localinterfaces at import time
1050 1050 * :ghpull:`4214`: engine ID metadata should be unicode, not bytes
1051 1051 * :ghpull:`4232`: no highlight if no language specified
1052 1052 * :ghpull:`4218`: Fix display of SyntaxError when .py file is modified
1053 1053 * :ghpull:`4207`: add `setup.py css` command
1054 1054 * :ghpull:`4224`: clear previous callbacks on execute
1055 1055 * :ghpull:`4180`: Iptest refactoring
1056 1056 * :ghpull:`4105`: JS output area misaligned
1057 1057 * :ghpull:`4220`: Various improvements to docs formatting
1058 1058 * :ghpull:`4187`: Select adequate highlighter for cell magic languages
1059 1059 * :ghpull:`4228`: update -dev docs to reflect latest stable version
1060 1060 * :ghpull:`4219`: Drop bundled argparse
1061 1061 * :ghpull:`3851`: Adds an explicit newline for pretty-printing.
1062 1062 * :ghpull:`3622`: Drop fakemodule
1063 1063 * :ghpull:`4080`: change default behavior of database task storage
1064 1064 * :ghpull:`4197`: enable cython highlight in notebook
1065 1065 * :ghpull:`4225`: Updated docstring for core.display.Image
1066 1066 * :ghpull:`4175`: nbconvert: Jinjaless exporter base
1067 1067 * :ghpull:`4208`: Added a lightweight "htmlcore" Makefile entry
1068 1068 * :ghpull:`4209`: Magic doc fixes
1069 1069 * :ghpull:`4217`: avoid importing numpy at the module level
1070 1070 * :ghpull:`4213`: fixed dead link in examples/notebooks readme to Part 3
1071 1071 * :ghpull:`4183`: ESC should be handled by CM if tooltip is not on
1072 1072 * :ghpull:`4193`: Update for #3549: Append Firefox overflow-x fix
1073 1073 * :ghpull:`4205`: use TextIOWrapper when communicating with pandoc subprocess
1074 1074 * :ghpull:`4204`: remove some extraneous print statements from IPython.parallel
1075 1075 * :ghpull:`4201`: HeadingCells cannot be split or merged
1076 1076 * :ghpull:`4048`: finish up speaker-notes PR
1077 1077 * :ghpull:`4079`: trigger `Kernel.status_started` after websockets open
1078 1078 * :ghpull:`4186`: moved DummyMod to proper namespace to enable dill pickling
1079 1079 * :ghpull:`4190`: update version-check message in setup.py and IPython.__init__
1080 1080 * :ghpull:`4188`: Allow user_ns trait to be None
1081 1081 * :ghpull:`4189`: always fire LOCAL_IPS.extend(PUBLIC_IPS)
1082 1082 * :ghpull:`4174`: various issues in markdown and rst templates
1083 1083 * :ghpull:`4178`: add missing data_javascript
1084 1084 * :ghpull:`4168`: Py3 failing tests
1085 1085 * :ghpull:`4181`: nbconvert: Fix, sphinx template not removing new lines from headers
1086 1086 * :ghpull:`4043`: don't 'restore_bytes' in from_JSON
1087 1087 * :ghpull:`4149`: reuse more kernels in kernel tests
1088 1088 * :ghpull:`4163`: Fix for incorrect default encoding on Windows.
1089 1089 * :ghpull:`4136`: catch javascript errors in any output
1090 1090 * :ghpull:`4171`: add nbconvert config file when creating profiles
1091 1091 * :ghpull:`4172`: add ability to check what PRs should be backported in backport_pr
1092 1092 * :ghpull:`4167`: --fast flag for test suite!
1093 1093 * :ghpull:`4125`: Basic exercise of `ipython [subcommand] -h` and help-all
1094 1094 * :ghpull:`4085`: nbconvert: Fix sphinx preprocessor date format string for Windows
1095 1095 * :ghpull:`4159`: don't split `.cell` and `div.cell` CSS
1096 1096 * :ghpull:`4165`: Remove use of parametric tests
1097 1097 * :ghpull:`4158`: generate choices for `--gui` configurable from real mapping
1098 1098 * :ghpull:`4083`: Implement a better check for hidden values for %who etc.
1099 1099 * :ghpull:`4147`: Reference notebook examples, fixes #4146.
1100 1100 * :ghpull:`4065`: do not include specific css in embedable one
1101 1101 * :ghpull:`4092`: nbconvert: Fix for unicode html headers, Windows + Python 2.x
1102 1102 * :ghpull:`4074`: close Client sockets if connection fails
1103 1103 * :ghpull:`4064`: Store default codemirror mode in only 1 place
1104 1104 * :ghpull:`4104`: Add way to install MathJax to a particular profile
1105 1105 * :ghpull:`4161`: Select name when renaming a notebook
1106 1106 * :ghpull:`4160`: Add quotes around ".[notebook]" in readme
1107 1107 * :ghpull:`4144`: help_end transformer shouldn't pick up ? in multiline string
1108 1108 * :ghpull:`4090`: Add LaTeX citation handling to nbconvert
1109 1109 * :ghpull:`4143`: update example custom.js
1110 1110 * :ghpull:`4142`: DOC: unwrap openssl line in public_server doc
1111 1111 * :ghpull:`4126`: update tox.ini
1112 1112 * :ghpull:`4141`: add files with a separate `add` call in backport_pr
1113 1113 * :ghpull:`4137`: Restore autorestore option for storemagic
1114 1114 * :ghpull:`4098`: pass profile-dir instead of profile name to Kernel
1115 1115 * :ghpull:`4120`: support `input` in Python 2 kernels
1116 1116 * :ghpull:`4088`: nbconvert: Fix coalescestreams line with incorrect nesting causing strange behavior
1117 1117 * :ghpull:`4060`: only strip continuation prompts if regular prompts seen first
1118 1118 * :ghpull:`4132`: Fixed name error bug in function safe_unicode in module py3compat.
1119 1119 * :ghpull:`4121`: move test_kernel from IPython.zmq to IPython.kernel
1120 1120 * :ghpull:`4118`: ZMQ heartbeat channel: catch EINTR exceptions and continue.
1121 1121 * :ghpull:`4070`: New changes should go into pr/ folder
1122 1122 * :ghpull:`4054`: use unicode for HTML export
1123 1123 * :ghpull:`4106`: fix a couple of default block values
1124 1124 * :ghpull:`4107`: update parallel magic tests with capture_output API
1125 1125 * :ghpull:`4102`: Fix clashes between debugger tests and coverage.py
1126 1126 * :ghpull:`4115`: Update docs on declaring a magic function
1127 1127 * :ghpull:`4101`: restore accidentally removed EngineError
1128 1128 * :ghpull:`4096`: minor docs changes
1129 1129 * :ghpull:`4094`: Update target branch before backporting PR
1130 1130 * :ghpull:`4069`: Drop monkeypatch for pre-1.0 nose
1131 1131 * :ghpull:`4056`: respect `pylab_import_all` when `--pylab` specified at the command-line
1132 1132 * :ghpull:`4091`: Make Qt console banner configurable
1133 1133 * :ghpull:`4086`: fix missing errno import
1134 1134 * :ghpull:`4084`: Use msvcrt.getwch() for Windows pager.
1135 1135 * :ghpull:`4073`: rename ``post_processors`` submodule to ``postprocessors``
1136 1136 * :ghpull:`4075`: Update supported Python versions in tools/test_pr
1137 1137 * :ghpull:`4068`: minor bug fix, define 'cell' in dialog.js.
1138 1138 * :ghpull:`4044`: rename call methods to transform and postprocess
1139 1139 * :ghpull:`3744`: capture rich output as well as stdout/err in capture_output
1140 1140 * :ghpull:`3969`: "use strict" in most (if not all) our javascript
1141 1141 * :ghpull:`4030`: exclude `.git` in MANIFEST.in
1142 1142 * :ghpull:`4047`: Use istype() when checking if canned object is a dict
1143 1143 * :ghpull:`4031`: don't close_fds on Windows
1144 1144 * :ghpull:`4029`: bson.Binary moved
1145 1145 * :ghpull:`3883`: skip test on unix when x11 not available
1146 1146 * :ghpull:`3863`: Added working speaker notes for slides.
1147 1147 * :ghpull:`4035`: Fixed custom jinja2 templates being ignored when setting template_path
1148 1148 * :ghpull:`4002`: Drop Python 2.6 and 3.2
1149 1149 * :ghpull:`4026`: small doc fix in nbconvert
1150 1150 * :ghpull:`4016`: Fix IPython.start_* functions
1151 1151 * :ghpull:`4021`: Fix parallel.client.View map() on numpy arrays
1152 1152 * :ghpull:`4022`: DOC: fix links to matplotlib, notebook docs
1153 1153 * :ghpull:`4018`: Fix warning when running IPython.kernel tests
1154 1154 * :ghpull:`4017`: Add REPL-like printing of final/return value to %%R cell magic
1155 1155 * :ghpull:`4019`: Test skipping without unicode paths
1156 1156 * :ghpull:`4008`: Transform code before %prun/%%prun runs
1157 1157 * :ghpull:`4014`: Fix typo in ipapp
1158 1158 * :ghpull:`3997`: DOC: typos + rewording in examples/notebooks/Cell Magics.ipynb
1159 1159 * :ghpull:`3914`: nbconvert: Transformer tests
1160 1160 * :ghpull:`3987`: get files list in backport_pr
1161 1161 * :ghpull:`3923`: nbconvert: Writer tests
1162 1162 * :ghpull:`3974`: nbconvert: Fix app tests on Window7 w/ Python 3.3
1163 1163 * :ghpull:`3937`: make tab visible in codemirror and light red background
1164 1164 * :ghpull:`3933`: nbconvert: Post-processor tests
1165 1165 * :ghpull:`3978`: fix `--existing` with non-localhost IP
1166 1166 * :ghpull:`3939`: minor checkpoint cleanup
1167 1167 * :ghpull:`3955`: complete on % for magic in notebook
1168 1168 * :ghpull:`3981`: BF: fix nbconert rst input prompt spacing
1169 1169 * :ghpull:`3960`: Don't make sphinx a dependency for importing nbconvert
1170 1170 * :ghpull:`3973`: logging.Formatter is not new-style in 2.6
1171 1171
1172 1172 Issues (434):
1173 1173
1174 1174 * :ghissue:`5476`: For 2.0: Fix links in Notebook Help Menu
1175 1175 * :ghissue:`5337`: Examples reorganization
1176 1176 * :ghissue:`5436`: CodeMirror shortcuts in QuickHelp
1177 1177 * :ghissue:`5444`: Fix numeric verification for Int and Float text widgets.
1178 1178 * :ghissue:`5443`: Int and Float Widgets don't allow negative signs
1179 1179 * :ghissue:`5449`: Stretch keyboard shortcut dialog
1180 1180 * :ghissue:`5471`: Add coding magic comment to nbconvert Python template
1181 1181 * :ghissue:`5470`: UTF-8 Issue When Converting Notebook to a Script.
1182 1182 * :ghissue:`5369`: FormatterWarning for SVG matplotlib output in notebook
1183 1183 * :ghissue:`5460`: Can't start the notebook server specifying a notebook
1184 1184 * :ghissue:`2918`: CodeMirror related issues.
1185 1185 * :ghissue:`5431`: update github_stats and gh_api for 2.0
1186 1186 * :ghissue:`4887`: Add tests for modal UI
1187 1187 * :ghissue:`5290`: Add dual mode JS tests
1188 1188 * :ghissue:`5448`: Cmd+/ shortcut doesn't work in IPython master
1189 1189 * :ghissue:`5447`: Add %%python2 cell magic
1190 1190 * :ghissue:`5442`: Make a "python2" alias or rename the "python"cell magic.
1191 1191 * :ghissue:`2495`: non-ascii characters in the path
1192 1192 * :ghissue:`4554`: dictDB: Exception due to str to datetime comparission
1193 1193 * :ghissue:`5006`: Comm code is not run in the same context as notebook code
1194 1194 * :ghissue:`5118`: Weird interact behavior
1195 1195 * :ghissue:`5401`: Empty code cells in nbconvert rst output cause problems
1196 1196 * :ghissue:`5434`: fix check for empty cells in rst template
1197 1197 * :ghissue:`4944`: Trouble finding ipynb path in Windows 8
1198 1198 * :ghissue:`4605`: Change the url of Editor Shorcuts in the notebook menu.
1199 1199 * :ghissue:`5425`: Update COPYING.txt
1200 1200 * :ghissue:`5348`: BUG: HistoryAccessor.get_session_info(0) - exception
1201 1201 * :ghissue:`5293`: Javascript("element.append()") looks broken.
1202 1202 * :ghissue:`5363`: Disable saving if notebook has stopped loading
1203 1203 * :ghissue:`5189`: Tooltip pager mode is broken
1204 1204 * :ghissue:`5330`: Updates to shell reference doc
1205 1205 * :ghissue:`5397`: Accordion widget broken
1206 1206 * :ghissue:`5106`: Flexbox CSS specificity bugs
1207 1207 * :ghissue:`5297`: tooltip triggers focus bug
1208 1208 * :ghissue:`5417`: scp checking for existence of directories: directory names are incorrect
1209 1209 * :ghissue:`5302`: Parallel engine registration fails for slow engines
1210 1210 * :ghissue:`5334`: notebook's split-cell shortcut dangerous / incompatible with Neo layout (for instance)
1211 1211 * :ghissue:`5324`: Style of `raw_input` UI is off in notebook
1212 1212 * :ghissue:`5350`: Converting notebooks with spaces in their names to RST gives broken images
1213 1213 * :ghissue:`5049`: update quickhelp on adding and removing shortcuts
1214 1214 * :ghissue:`4941`: Eliminating display of intermediate stages in progress bars
1215 1215 * :ghissue:`5345`: nbconvert to markdown does not use backticks
1216 1216 * :ghissue:`5357`: catch exception in copystat
1217 1217 * :ghissue:`5351`: Notebook saving fails on smb share
1218 1218 * :ghissue:`4946`: TeX produced cannot be converted to PDF
1219 1219 * :ghissue:`5347`: pretty print list too slow
1220 1220 * :ghissue:`5238`: Raw cell placeholder is not removed when you edit the cell
1221 1221 * :ghissue:`5382`: Qtconsole doesn't run in Python 3
1222 1222 * :ghissue:`5378`: Unexpected and new conflict between PyFileConfigLoader and IPythonQtConsoleApp
1223 1223 * :ghissue:`4945`: Heading/cells positioning problem and cell output wrapping
1224 1224 * :ghissue:`5084`: Consistent approach for HTML/JS output on nbviewer
1225 1225 * :ghissue:`4902`: print preview does not work, custom.css not found
1226 1226 * :ghissue:`5336`: TypeError in bootstrap-tour.min.js
1227 1227 * :ghissue:`5303`: Changed Hub.registration_timeout to be a config input.
1228 1228 * :ghissue:`995`: Paste-able mode in terminal
1229 1229 * :ghissue:`5305`: Tuple unpacking for shell escape
1230 1230 * :ghissue:`5232`: Make nbconvert html full output like notebook's html.
1231 1231 * :ghissue:`5224`: Audit nbconvert HTML output
1232 1232 * :ghissue:`5253`: display any output from this session in terminal console
1233 1233 * :ghissue:`5251`: ipython console ignoring some stream messages?
1234 1234 * :ghissue:`4802`: Tour of the notebook UI (was UI elements inline with highlighting)
1235 1235 * :ghissue:`5103`: Moving Constructor definition to the top like a Function definition
1236 1236 * :ghissue:`5264`: Test failures on master with Anaconda
1237 1237 * :ghissue:`4833`: Serve /usr/share/javascript at /_sysassets/javascript/ in notebook
1238 1238 * :ghissue:`5071`: Prevent %pylab from clobbering interactive
1239 1239 * :ghissue:`5282`: Exception in widget __del__ methods in Python 3.4.
1240 1240 * :ghissue:`5280`: append Firefox overflow-x fix
1241 1241 * :ghissue:`5120`: append Firefox overflow-x fix, again
1242 1242 * :ghissue:`4127`: autoreload shouldn't rely on .pyc modification times
1243 1243 * :ghissue:`5272`: allow highlighting language to be set from notebook metadata
1244 1244 * :ghissue:`5050`: Notebook cells truncated with Firefox
1245 1245 * :ghissue:`4839`: Error in Session.send_raw()
1246 1246 * :ghissue:`5188`: New events system
1247 1247 * :ghissue:`5076`: Refactor keyboard handling
1248 1248 * :ghissue:`4886`: Refactor and consolidate different keyboard logic in JavaScript code
1249 1249 * :ghissue:`5002`: the green cell border moving forever in Chrome, when there are many code cells.
1250 1250 * :ghissue:`5259`: Codemirror still active in command mode
1251 1251 * :ghissue:`5219`: Output images appear as small thumbnails (Notebook)
1252 1252 * :ghissue:`4829`: Not able to connect qtconsole in Windows 8
1253 1253 * :ghissue:`5152`: Hide __pycache__ in dashboard directory list
1254 1254 * :ghissue:`5151`: Case-insesitive sort for dashboard list
1255 1255 * :ghissue:`4603`: Warn when overwriting a notebook with upload
1256 1256 * :ghissue:`4895`: Improvements to %run completions
1257 1257 * :ghissue:`3459`: Filename completion when run script with %run
1258 1258 * :ghissue:`5225`: Add JavaScript to nbconvert HTML display priority
1259 1259 * :ghissue:`5034`: Audit the places where we call `.html(something)`
1260 1260 * :ghissue:`5094`: Dancing cells in notebook
1261 1261 * :ghissue:`4999`: Notebook focus effects
1262 1262 * :ghissue:`5149`: Clicking on a TextBoxWidget in FF completely breaks dual mode.
1263 1263 * :ghissue:`5207`: Children fire event
1264 1264 * :ghissue:`5227`: display_method of objects with custom __getattr__
1265 1265 * :ghissue:`5236`: Cursor keys do not work to leave Markdown cell while it's being edited
1266 1266 * :ghissue:`5205`: Use CTuple traitlet for Widget children
1267 1267 * :ghissue:`5230`: notebook rename does not respect url prefix
1268 1268 * :ghissue:`5218`: Test failures with Python 3 and enabled warnings
1269 1269 * :ghissue:`5115`: Page Breaks for Print Preview Broken by display: flex - Simple CSS Fix
1270 1270 * :ghissue:`5024`: Make nbconvert HTML output smart about page breaking
1271 1271 * :ghissue:`4985`: Add automatic Closebrackets function to Codemirror.
1272 1272 * :ghissue:`5184`: print '\xa' crashes the interactive shell
1273 1273 * :ghissue:`5214`: Downloading notebook as Python (.py) fails
1274 1274 * :ghissue:`5211`: AttributeError: 'module' object has no attribute '_outputfile'
1275 1275 * :ghissue:`5206`: [CSS?] Inconsistencies in nbconvert divs and IPython Notebook divs?
1276 1276 * :ghissue:`5201`: node != nodejs within Debian packages
1277 1277 * :ghissue:`5112`: band-aid for completion
1278 1278 * :ghissue:`4860`: Completer As-You-Type Broken
1279 1279 * :ghissue:`5116`: reorganize who knows what about paths
1280 1280 * :ghissue:`4973`: Adding security.js with 1st attempt at is_safe
1281 1281 * :ghissue:`5164`: test_oinspect.test_calltip_builtin failure with python3.4
1282 1282 * :ghissue:`5127`: Widgets: skip intermediate callbacks during throttling
1283 1283 * :ghissue:`5013`: Widget alignment differs between FF and Chrome
1284 1284 * :ghissue:`5141`: tornado error static file
1285 1285 * :ghissue:`5160`: TemporaryWorkingDirectory incompatible with python3.4
1286 1286 * :ghissue:`5140`: WIP: %kernels magic
1287 1287 * :ghissue:`4987`: Widget lifecycle problems
1288 1288 * :ghissue:`5129`: UCS package break latex export on non-ascii
1289 1289 * :ghissue:`4986`: Cell horizontal scrollbar is missing in FF but not in Chrome
1290 1290 * :ghissue:`4685`: nbconvert ignores image size metadata
1291 1291 * :ghissue:`5155`: Notebook logout button does not work (source typo)
1292 1292 * :ghissue:`2678`: Ctrl-m keyboard shortcut clash on Chrome OS
1293 1293 * :ghissue:`5113`: ButtonWidget without caption wrong height.
1294 1294 * :ghissue:`4778`: add APIs for installing notebook extensions
1295 1295 * :ghissue:`5046`: python setup.py failed vs git submodule update worked
1296 1296 * :ghissue:`4925`: Notebook manager api fixes
1297 1297 * :ghissue:`5073`: Cannot align widgets horizontally in the notebook
1298 1298 * :ghissue:`4996`: require print_method to be a bound method
1299 1299 * :ghissue:`4990`: _repr_html_ exception reporting corner case when using type(foo)
1300 1300 * :ghissue:`5099`: Notebook: Changing base_project_url results in failed WebSockets call
1301 1301 * :ghissue:`5096`: Client.map is not fault tolerant
1302 1302 * :ghissue:`4997`: Inconsistent %matplotlib qt behavior
1303 1303 * :ghissue:`5041`: Remove more .html(...) calls.
1304 1304 * :ghissue:`5078`: Updating JS tests README.md
1305 1305 * :ghissue:`4977`: ensure scp destination directories exist (with mkdir -p)
1306 1306 * :ghissue:`3411`: ipython parallel: scp failure.
1307 1307 * :ghissue:`5064`: Errors during interact display at the terminal, not anywhere in the notebook
1308 1308 * :ghissue:`4921`: Add PDF formatter and handling
1309 1309 * :ghissue:`4920`: Adding PDFFormatter and kernel side handling of PDF display data
1310 1310 * :ghissue:`5048`: Add edit/command mode indicator
1311 1311 * :ghissue:`4889`: Add UI element for indicating command/edit modes
1312 1312 * :ghissue:`5052`: Add q to toggle the pager.
1313 1313 * :ghissue:`5000`: Closing pager with keyboard in modal UI
1314 1314 * :ghissue:`5069`: Box model changes broke the Keyboard Shortcuts help modal
1315 1315 * :ghissue:`4960`: Interact/Interactive for widget
1316 1316 * :ghissue:`4883`: Implement interact/interactive for widgets
1317 1317 * :ghissue:`5038`: Fix multiple press keyboard events
1318 1318 * :ghissue:`5054`: UnicodeDecodeError: 'ascii' codec can't decode byte 0xc6 in position 1: ordinal not in range(128)
1319 1319 * :ghissue:`5031`: Bug during integration of IPython console in Qt application
1320 1320 * :ghissue:`5057`: iopubwatcher.py example is broken.
1321 1321 * :ghissue:`4747`: Add event for output_area adding an output
1322 1322 * :ghissue:`5001`: Add directory navigation to dashboard
1323 1323 * :ghissue:`5016`: Help menu external-link icons break layout in FF
1324 1324 * :ghissue:`4885`: Modal UI behavior changes
1325 1325 * :ghissue:`5009`: notebook signatures don't work
1326 1326 * :ghissue:`4975`: setup.py changes for 2.0
1327 1327 * :ghissue:`4774`: emit event on appended element on dom
1328 1328 * :ghissue:`5020`: Python Lists translated to javascript objects in widgets
1329 1329 * :ghissue:`5003`: Fix pretty reprs of super() objects
1330 1330 * :ghissue:`5012`: Make `SelectionWidget.values` a dict
1331 1331 * :ghissue:`4961`: Bug when constructing a selection widget with both values and labels
1332 1332 * :ghissue:`4283`: A `<` in a markdown cell strips cell content when converting to latex
1333 1333 * :ghissue:`4006`: iptest IPython broken
1334 1334 * :ghissue:`4251`: & escaped to &amp; in tex ?
1335 1335 * :ghissue:`5027`: pin lessc to 1.4
1336 1336 * :ghissue:`4323`: Take 2: citation2latex filter (using HTMLParser)
1337 1337 * :ghissue:`4196`: Printing notebook from browser gives 1-page truncated output
1338 1338 * :ghissue:`4842`: more subtle kernel indicator
1339 1339 * :ghissue:`4057`: No path to notebook examples from Help menu
1340 1340 * :ghissue:`5015`: don't write cell.trusted to disk
1341 1341 * :ghissue:`4617`: Changed url link in Help dropdown menu.
1342 1342 * :ghissue:`4976`: Container widget layout broken on Firefox
1343 1343 * :ghissue:`4981`: Vertical slider layout broken
1344 1344 * :ghissue:`4793`: Message spec changes related to `clear_output`
1345 1345 * :ghissue:`4982`: Live readout for slider widgets
1346 1346 * :ghissue:`4813`: make help menu a template
1347 1347 * :ghissue:`4989`: Filename tab completion completely broken
1348 1348 * :ghissue:`1380`: Tab should insert 4 spaces in # comment lines
1349 1349 * :ghissue:`2888`: spaces vs tabs
1350 1350 * :ghissue:`1193`: Allow resizing figures in notebook
1351 1351 * :ghissue:`4504`: Allow input transformers to raise SyntaxError
1352 1352 * :ghissue:`4697`: Problems with height after toggling header and toolbar...
1353 1353 * :ghissue:`4951`: TextWidget to code cell command mode bug.
1354 1354 * :ghissue:`4809`: Arbitrary scrolling (jumping) in clicks in modal UI for notebook
1355 1355 * :ghissue:`4971`: Fixing issues with js tests
1356 1356 * :ghissue:`4972`: Work around problem in doctest discovery in Python 3.4 with PyQt
1357 1357 * :ghissue:`4892`: IPython.qt test failure with python3.4
1358 1358 * :ghissue:`4863`: BUG: cannot create an OBJECT array from memory buffer
1359 1359 * :ghissue:`4704`: Subcommand `profile` ignores --ipython-dir
1360 1360 * :ghissue:`4845`: Add Origin Checking.
1361 1361 * :ghissue:`4870`: ipython_directive, report except/warn in block and add :okexcept: :okwarning: options to suppress
1362 1362 * :ghissue:`4956`: Shift-Enter does not move to next cell
1363 1363 * :ghissue:`4662`: Menu cleanup
1364 1364 * :ghissue:`4824`: sign notebooks
1365 1365 * :ghissue:`4848`: avoid import of nearby temporary with %edit
1366 1366 * :ghissue:`4731`: %edit files mistakenly import modules in /tmp
1367 1367 * :ghissue:`4950`: Two fixes for file upload related bugs
1368 1368 * :ghissue:`4871`: Notebook upload fails after Delete
1369 1369 * :ghissue:`4825`: File Upload URL set incorrectly
1370 1370 * :ghissue:`3867`: display.FileLinks should work in the exported html verion of a notebook
1371 1371 * :ghissue:`4948`: reveal: ipython css overrides reveal themes
1372 1372 * :ghissue:`4947`: reveal: slides that are too big?
1373 1373 * :ghissue:`4051`: Test failures with Python 3 and enabled warnings
1374 1374 * :ghissue:`3633`: outstanding issues over in ipython/nbconvert repo
1375 1375 * :ghissue:`4087`: Sympy printing in the example notebook
1376 1376 * :ghissue:`4627`: Document various QtConsole embedding approaches.
1377 1377 * :ghissue:`4849`: Various unicode fixes (mostly on Windows)
1378 1378 * :ghissue:`3653`: autocompletion in "from package import <tab>"
1379 1379 * :ghissue:`4583`: overwrite? prompt gets EOFError in 2 process
1380 1380 * :ghissue:`4807`: Correct handling of ansi colour codes when nbconverting to latex
1381 1381 * :ghissue:`4611`: Document how to compile .less files in dev docs.
1382 1382 * :ghissue:`4618`: "Editor Shortcuts" link is broken in help menu dropdown notebook
1383 1383 * :ghissue:`4522`: DeprecationWarning: the sets module is deprecated
1384 1384 * :ghissue:`4368`: No symlink from ipython to ipython3 when inside a python3 virtualenv
1385 1385 * :ghissue:`4234`: Math without $$ doesn't show up when converted to slides
1386 1386 * :ghissue:`4194`: config.TerminalIPythonApp.nosep does not work
1387 1387 * :ghissue:`1491`: prefilter not called for multi-line notebook cells
1388 1388 * :ghissue:`4001`: Windows IPython executable /scripts/ipython not working
1389 1389 * :ghissue:`3959`: think more carefully about text wrapping in nbconvert
1390 1390 * :ghissue:`4907`: Test for traceback depth fails on Windows
1391 1391 * :ghissue:`4906`: Test for IPython.embed() fails on Windows
1392 1392 * :ghissue:`4912`: Skip some Windows io failures
1393 1393 * :ghissue:`3700`: stdout/stderr should be flushed printing exception output...
1394 1394 * :ghissue:`1181`: greedy completer bug in terminal console
1395 1395 * :ghissue:`2032`: check for a few places we should be using DEFAULT_ENCODING
1396 1396 * :ghissue:`4882`: Too many files open when starting and stopping kernel repeatedly
1397 1397 * :ghissue:`4880`: set profile name from profile_dir
1398 1398 * :ghissue:`4238`: parallel.Client() not using profile that notebook was run with?
1399 1399 * :ghissue:`4853`: fix setting image height/width from metadata
1400 1400 * :ghissue:`4786`: Reduce spacing of heading cells
1401 1401 * :ghissue:`4680`: Minimal pandoc version warning
1402 1402 * :ghissue:`3707`: nbconvert: Remove IPython magic commands from --format="python" output
1403 1403 * :ghissue:`4130`: PDF figures as links from png or svg figures
1404 1404 * :ghissue:`3919`: Allow --profile to be passed a dir.
1405 1405 * :ghissue:`2136`: Handle hard newlines in pretty printer
1406 1406 * :ghissue:`4790`: Notebook modal UI: "merge cell below" key binding, `shift+=`, does not work with some keyboard layouts
1407 1407 * :ghissue:`4884`: Keyboard shortcut changes
1408 1408 * :ghissue:`1184`: slow handling of keyboard input
1409 1409 * :ghissue:`4913`: Mathjax, Markdown, tex, env* and italic
1410 1410 * :ghissue:`3972`: nbconvert: Template output testing
1411 1411 * :ghissue:`4903`: use https for all embeds
1412 1412 * :ghissue:`4874`: --debug does not work if you set .kernel_cmd
1413 1413 * :ghissue:`4679`: JPG compression for inline pylab
1414 1414 * :ghissue:`4708`: Fix indent and center
1415 1415 * :ghissue:`4789`: fix IPython.embed
1416 1416 * :ghissue:`4759`: Application._load_config_files log parameter default fails
1417 1417 * :ghissue:`3153`: docs / file menu: explain how to exit the notebook
1418 1418 * :ghissue:`4791`: Did updates to ipython_directive bork support for cython magic snippets?
1419 1419 * :ghissue:`4385`: "Part 4 - Markdown Cells.ipynb" nbviewer example seems not well referenced in current online documentation page http://ipython.org/ipython-doc/stable/interactive/notebook.htm
1420 1420 * :ghissue:`4655`: prefer marked to pandoc for markdown2html
1421 1421 * :ghissue:`3441`: Fix focus related problems in the notebook
1422 1422 * :ghissue:`3402`: Feature Request: Save As (latex, html,..etc) as a menu option in Notebook rather than explicit need to invoke nbconvert
1423 1423 * :ghissue:`3224`: Revisit layout of notebook area
1424 1424 * :ghissue:`2746`: rerunning a cell with long output (exception) scrolls to much (html notebook)
1425 * :ghissue:`2667`: can't save opened notebook if accidently delete the notebook in the dashboard
1425 * :ghissue:`2667`: can't save opened notebook if accidentally delete the notebook in the dashboard
1426 1426 * :ghissue:`3026`: Reporting errors from _repr_<type>_ methods
1427 1427 * :ghissue:`1844`: Notebook does not exist and permalinks
1428 1428 * :ghissue:`2450`: [closed PR] Prevent jumping of window to input when output is clicked.
1429 1429 * :ghissue:`3166`: IPEP 16: Notebook multi directory dashboard and URL mapping
1430 1430 * :ghissue:`3691`: Slight misalignment of Notebook menu bar with focus box
1431 1431 * :ghissue:`4875`: Empty tooltip with `object_found = false` still being shown
1432 1432 * :ghissue:`4432`: The SSL cert for the MathJax CDN is invalid and URL is not protocol agnostic
1433 1433 * :ghissue:`2633`: Help text should leave current cell active
1434 1434 * :ghissue:`3976`: DOC: Pandas link on the notebook help menu?
1435 1435 * :ghissue:`4082`: /new handler redirect cached by browser
1436 1436 * :ghissue:`4298`: Slow ipython --pylab and ipython notebook startup
1437 1437 * :ghissue:`4545`: %store magic not working
1438 1438 * :ghissue:`4610`: toolbar UI enhancements
1439 1439 * :ghissue:`4782`: New modal UI
1440 1440 * :ghissue:`4732`: Accents in notebook names and in command-line (nbconvert)
1441 1441 * :ghissue:`4752`: link broken in docs/examples
1442 1442 * :ghissue:`4835`: running ipython on python files adds an extra traceback frame
1443 1443 * :ghissue:`4792`: repr_html exception warning on qtconsole with pandas #4745
1444 1444 * :ghissue:`4834`: function tooltip issues
1445 1445 * :ghissue:`4808`: Docstrings in Notebook not displayed properly and introspection
1446 1446 * :ghissue:`4846`: Remove some leftover traces of irunner
1447 1447 * :ghissue:`4810`: ipcluster bug in clean_logs flag
1448 1448 * :ghissue:`4812`: update CodeMirror for the notebook
1449 1449 * :ghissue:`671`: add migration guide for old IPython config
1450 1450 * :ghissue:`4783`: ipython 2dev under windows / (win)python 3.3 experiment
1451 1451 * :ghissue:`4772`: Notebook server info files
1452 1452 * :ghissue:`4765`: missing build script for highlight.js
1453 1453 * :ghissue:`4787`: non-python kernels run python code with qtconsole
1454 1454 * :ghissue:`4703`: Math macro in jinja templates.
1455 1455 * :ghissue:`4595`: ipython notebook XSS vulnerable
1456 1456 * :ghissue:`4776`: Manually document py3compat module.
1457 1457 * :ghissue:`4686`: For-in loop on an array in cell.js
1458 1458 * :ghissue:`3605`: Modal UI
1459 1459 * :ghissue:`4769`: Ipython 2.0 will not startup on py27 on windows
1460 1460 * :ghissue:`4482`: reveal.js converter not including CDN by default?
1461 1461 * :ghissue:`4761`: ipv6 address triggers cookie exception
1462 1462 * :ghissue:`4580`: rename or remove %profile magic
1463 1463 * :ghissue:`4643`: Docstring does not open properly
1464 1464 * :ghissue:`4714`: Static URLs are not auto-versioned
1465 1465 * :ghissue:`2573`: document code mirror keyboard shortcuts
1466 1466 * :ghissue:`4717`: hang in parallel.Client when using SSHAgent
1467 1467 * :ghissue:`4544`: Clarify the requirement for pyreadline on Windows
1468 1468 * :ghissue:`3451`: revisit REST /new handler to avoid systematic crawling.
1469 1469 * :ghissue:`2922`: File => Save as '.py' saves magic as code
1470 1470 * :ghissue:`4728`: Copy/Paste stripping broken in version > 0.13.x in QTConsole
1471 1471 * :ghissue:`4539`: Nbconvert: Latex to PDF conversion fails on notebooks with accented letters
1472 1472 * :ghissue:`4721`: purge_results with jobid crashing - looking for insight
1473 1473 * :ghissue:`4620`: Notebook with ? in title defies autosave, renaming and deletion.
1474 1474 * :ghissue:`4574`: Hash character in notebook name breaks a lot of things
1475 1475 * :ghissue:`4709`: input_prefilter hook not called
1476 1476 * :ghissue:`1680`: qtconsole should support --no-banner and custom banner
1477 1477 * :ghissue:`4689`: IOStream IP address configurable
1478 1478 * :ghissue:`4698`: Missing "if __name__ == '__main__':" check in /usr/bin/ipython
1479 1479 * :ghissue:`4191`: NBConvert: markdown inline and locally referenced files have incorrect file location for latex
1480 1480 * :ghissue:`2865`: %%!? does not display the shell execute docstring
1481 1481 * :ghissue:`1551`: Notebook should be saved before printing
1482 1482 * :ghissue:`4612`: remove `Configurable.created` ?
1483 1483 * :ghissue:`4629`: Lots of tests fail due to space in sys.executable
1484 1484 * :ghissue:`4644`: Fixed URLs for notebooks
1485 1485 * :ghissue:`4621`: IPython 1.1.0 Qtconsole syntax highlighting highlights python 2 only built-ins when using python 3
1486 1486 * :ghissue:`2923`: Move Delete Button Away from Save Button in the HTML notebook toolbar
1487 1487 * :ghissue:`4615`: UnicodeDecodeError
1488 1488 * :ghissue:`4431`: ipython slow in os x mavericks?
1489 1489 * :ghissue:`4538`: DOC: document how to change ipcontroller-engine.json in case controller was started with --ip="*"
1490 1490 * :ghissue:`4551`: Serialize methods and closures
1491 1491 * :ghissue:`4081`: [Nbconvert][reveal] link to font awesome ?
1492 1492 * :ghissue:`4602`: "ipcluster stop" fails after "ipcluster start --daemonize" using python3.3
1493 1493 * :ghissue:`4578`: NBconvert fails with unicode errors when `--stdout` and file redirection is specified and HTML entities are present
1494 1494 * :ghissue:`4600`: Renaming new notebook to an exist name silently deletes the old one
1495 1495 * :ghissue:`4598`: Qtconsole docstring pop-up fails on method containing defaulted enum argument
1496 1496 * :ghissue:`951`: Remove Tornado monkeypatch
1497 1497 * :ghissue:`4564`: Notebook save failure
1498 1498 * :ghissue:`4562`: nbconvert: Default encoding problem on OS X
1499 1499 * :ghissue:`1675`: add file_to_run=file.ipynb capability to the notebook
1500 1500 * :ghissue:`4516`: `ipython console` doesn't send a `shutdown_request`
1501 1501 * :ghissue:`3043`: can't restart pdb session in ipython
1502 1502 * :ghissue:`4524`: Fix bug with non ascii passwords in notebook login
1503 1503 * :ghissue:`1866`: problems rendering an SVG?
1504 1504 * :ghissue:`4520`: unicode error when trying Audio('data/Bach Cello Suite #3.wav')
1505 1505 * :ghissue:`4493`: Qtconsole cannot print an ISO8601 date at nanosecond precision
1506 1506 * :ghissue:`4502`: intermittent parallel test failure test_purge_everything
1507 1507 * :ghissue:`4495`: firefox 25.0: notebooks report "Notebook save failed", .py script save fails, but .ipynb save succeeds
1508 1508 * :ghissue:`4245`: nbconvert latex: code highlighting causes error
1509 1509 * :ghissue:`4486`: Test for whether inside virtualenv does not work if directory is symlinked
1510 1510 * :ghissue:`4485`: Incorrect info in "Messaging in IPython" documentation.
1511 1511 * :ghissue:`4447`: Ipcontroller broken in current HEAD on windows
1512 1512 * :ghissue:`4241`: Audio display object
1513 1513 * :ghissue:`4463`: Error on empty c.Session.key
1514 1514 * :ghissue:`4454`: UnicodeDecodeError when starting Ipython notebook on a directory containing a file with a non-ascii character
1515 1515 * :ghissue:`3801`: Autocompletion: Fix issue #3723 -- ordering of completions for magic commands and variables with same name
1516 1516 * :ghissue:`3723`: Code completion: 'matplotlib' and '%matplotlib'
1517 1517 * :ghissue:`4396`: Always checkpoint al least once ?
1518 1518 * :ghissue:`2524`: [Notebook] Clear kernel queue
1519 1519 * :ghissue:`2292`: Client side tests for the notebook
1520 1520 * :ghissue:`4424`: Dealing with images in multidirectory environment
1521 1521 * :ghissue:`4388`: Make writing configurable magics easier
1522 1522 * :ghissue:`852`: Notebook should be saved before downloading
1523 1523 * :ghissue:`3708`: ipython profile locate should also work
1524 1524 * :ghissue:`1349`: `?` may generate hundreds of cell
1525 1525 * :ghissue:`4381`: Using hasattr for trait_names instead of just looking for it directly/using __dir__?
1526 1526 * :ghissue:`4361`: Crash Ultratraceback/ session history
1527 1527 * :ghissue:`3044`: IPython notebook autocomplete for filename string converts multiple spaces to a single space
1528 1528 * :ghissue:`3346`: Up arrow history search shows duplicates in Qtconsole
1529 1529 * :ghissue:`3496`: Fix import errors when running tests from the source directory
1530 1530 * :ghissue:`4114`: If default profile doesn't exist, can't install mathjax to any location
1531 1531 * :ghissue:`4335`: TestPylabSwitch.test_qt fails
1532 1532 * :ghissue:`4291`: serve like option for nbconvert --to latex
1533 1533 * :ghissue:`1824`: Exception before prompting for password during ssh connection
1534 1534 * :ghissue:`4309`: Error in nbconvert - closing </code> tag is not inserted in HTML under some circumstances
1535 1535 * :ghissue:`4351`: /parallel/apps/launcher.py error
1536 1536 * :ghissue:`3603`: Upcoming issues with nbconvert
1537 1537 * :ghissue:`4296`: sync_imports() fails in python 3.3
1538 1538 * :ghissue:`4339`: local mathjax install doesn't work
1539 1539 * :ghissue:`4334`: NotebookApp.webapp_settings static_url_prefix causes crash
1540 1540 * :ghissue:`4308`: Error when use "ipython notebook" in win7 64 with python2.7.3 64.
1541 1541 * :ghissue:`4317`: Relative imports broken in the notebook (Windows)
1542 1542 * :ghissue:`3658`: Saving Notebook clears "Kernel Busy" status from the page and titlebar
1543 1543 * :ghissue:`4312`: Link broken on ipython-doc stable
1544 1544 * :ghissue:`1093`: Add boundary options to %load
1545 1545 * :ghissue:`3619`: Multi-dir webservice design
1546 1546 * :ghissue:`4299`: Nbconvert, default_preprocessors to list of dotted name not list of obj
1547 1547 * :ghissue:`3210`: IPython.parallel tests seem to hang on ShiningPanda
1548 1548 * :ghissue:`4280`: MathJax Automatic Line Breaking
1549 1549 * :ghissue:`4039`: Celltoolbar example issue
1550 1550 * :ghissue:`4247`: nbconvert --to latex: error when converting greek letter
1551 1551 * :ghissue:`4273`: %%capture not capturing rich objects like plots (IPython 1.1.0)
1552 1552 * :ghissue:`3866`: Vertical offsets in LaTeX output for nbconvert
1553 1553 * :ghissue:`3631`: xkcd mode for the IPython notebook
1554 1554 * :ghissue:`4243`: Test exclusions not working on Windows
1555 1555 * :ghissue:`4256`: IPython no longer handles unicode file names
1556 1556 * :ghissue:`3656`: Audio displayobject
1557 1557 * :ghissue:`4223`: Double output on Ctrl-enter-enter
1558 1558 * :ghissue:`4184`: nbconvert: use r pygmentize backend when highlighting "%%R" cells
1559 1559 * :ghissue:`3851`: Adds an explicit newline for pretty-printing.
1560 1560 * :ghissue:`3622`: Drop fakemodule
1561 1561 * :ghissue:`4122`: Nbconvert [windows]: Inconsistent line endings in markdown cells exported to latex
1562 1562 * :ghissue:`3819`: nbconvert add extra blank line to code block on Windows.
1563 1563 * :ghissue:`4203`: remove spurious print statement from parallel annoted functions
1564 1564 * :ghissue:`4200`: Notebook: merging a heading cell and markdown cell cannot be undone
1565 1565 * :ghissue:`3747`: ipynb -> ipynb transformer
1566 1566 * :ghissue:`4024`: nbconvert markdown issues
1567 1567 * :ghissue:`3903`: on Windows, 'ipython3 nbconvert "C:/blabla/first_try.ipynb" --to slides' gives an unexpected result, and '--post serve' fails
1568 1568 * :ghissue:`4095`: Catch js error in append html in stream/pyerr
1569 1569 * :ghissue:`1880`: Add parallelism to test_pr
1570 1570 * :ghissue:`4085`: nbconvert: Fix sphinx preprocessor date format string for Windows
1571 1571 * :ghissue:`4156`: Specifying --gui=tk at the command line
1572 1572 * :ghissue:`4146`: Having to prepend 'files/' to markdown image paths is confusing
1573 1573 * :ghissue:`3818`: nbconvert can't handle Heading with Chinese characters on Japanese Windows OS.
1574 1574 * :ghissue:`4134`: multi-line parser fails on ''' in comment, qtconsole and notebook.
1575 1575 * :ghissue:`3998`: sample custom.js needs to be updated
1576 1576 * :ghissue:`4078`: StoreMagic.autorestore not working in 1.0.0
1577 1577 * :ghissue:`3990`: Buitlin `input` doesn't work over zmq
1578 1578 * :ghissue:`4015`: nbconvert fails to convert all the content of a notebook
1579 1579 * :ghissue:`4059`: Issues with Ellipsis literal in Python 3
1580 1580 * :ghissue:`2310`: "ZMQError: Interrupted system call" from RichIPythonWidget
1581 1581 * :ghissue:`3807`: qtconsole ipython 0.13.2 - html/xhtml export fails
1582 1582 * :ghissue:`4103`: Wrong default argument of DirectView.clear
1583 1583 * :ghissue:`4100`: parallel.client.client references undefined error.EngineError
1584 1584 * :ghissue:`484`: Drop nosepatch
1585 1585 * :ghissue:`3350`: Added longlist support in ipdb.
1586 1586 * :ghissue:`1591`: Keying 'q' doesn't quit the interactive help in Wins7
1587 1587 * :ghissue:`40`: The tests in test_process fail under Windows
1588 1588 * :ghissue:`3744`: capture rich output as well as stdout/err in capture_output
1589 1589 * :ghissue:`3742`: %%capture to grab rich display outputs
1590 1590 * :ghissue:`3863`: Added working speaker notes for slides.
1591 1591 * :ghissue:`4013`: Iptest fails in dual python installation
1592 1592 * :ghissue:`4005`: IPython.start_kernel doesn't work.
1593 1593 * :ghissue:`4020`: IPython parallel map fails on numpy arrays
1594 1594 * :ghissue:`3914`: nbconvert: Transformer tests
1595 1595 * :ghissue:`3923`: nbconvert: Writer tests
1596 1596 * :ghissue:`3945`: nbconvert: commandline tests fail Win7x64 Py3.3
1597 1597 * :ghissue:`3937`: make tab visible in codemirror and light red background
1598 1598 * :ghissue:`3935`: No feedback for mixed tabs and spaces
1599 1599 * :ghissue:`3933`: nbconvert: Post-processor tests
1600 1600 * :ghissue:`3977`: unable to complete remote connections for two-process
1601 1601 * :ghissue:`3939`: minor checkpoint cleanup
1602 1602 * :ghissue:`3955`: complete on % for magic in notebook
1603 1603 * :ghissue:`3954`: all magics should be listed when completing on %
1604 1604 * :ghissue:`3980`: nbconvert rst output lacks needed blank lines
1605 1605 * :ghissue:`3968`: TypeError: super() argument 1 must be type, not classobj (Python 2.6.6)
1606 1606 * :ghissue:`3880`: nbconvert: R&D remaining tests
1607 1607 * :ghissue:`2440`: IPEP 4: Python 3 Compatibility
@@ -1,360 +1,360 b''
1 1 =============
2 2 0.10 series
3 3 =============
4 4
5 5 Release 0.10.2
6 6 ==============
7 7
8 8 IPython 0.10.2 was released April 9, 2011. This is a minor bugfix release that
9 9 preserves backward compatibility. At this point, all IPython development
10 10 resources are focused on the 0.11 series that includes a complete architectural
11 11 restructuring of the project as well as many new capabilities, so this is
12 12 likely to be the last release of the 0.10.x series. We have tried to fix all
13 13 major bugs in this series so that it remains a viable platform for those not
14 14 ready yet to transition to the 0.11 and newer codebase (since that will require
15 15 some porting effort, as a number of APIs have changed).
16 16
17 17 Thus, we are not opening a 0.10.3 active development branch yet, but if the
18 18 user community requires new patches and is willing to maintain/release such a
19 19 branch, we'll be happy to host it on the IPython github repositories.
20 20
21 21 Highlights of this release:
22 22
23 23 - The main one is the closing of github ticket #185, a major regression we had
24 24 in 0.10.1 where pylab mode with GTK (or gthread) was not working correctly,
25 25 hence plots were blocking with GTK. Since this is the default matplotlib
26 26 backend on Unix systems, this was a major annoyance for many users. Many
27 27 thanks to Paul Ivanov for helping resolve this issue.
28 28
29 29 - Fix IOError bug on Windows when used with -gthread.
30 30 - Work robustly if $HOME is missing from environment.
31 31 - Better POSIX support in ssh scripts (remove bash-specific idioms).
32 32 - Improved support for non-ascii characters in log files.
33 33 - Work correctly in environments where GTK can be imported but not started
34 34 (such as a linux text console without X11).
35 35
36 36 For this release we merged 24 commits, contributed by the following people
37 (please let us know if we ommitted your name and we'll gladly fix this in the
37 (please let us know if we omitted your name and we'll gladly fix this in the
38 38 notes for the future):
39 39
40 40 * Fernando Perez
41 41 * MinRK
42 42 * Paul Ivanov
43 43 * Pieter Cristiaan de Groot
44 44 * TvrtkoM
45 45
46 46 Release 0.10.1
47 47 ==============
48 48
49 49 IPython 0.10.1 was released October 11, 2010, over a year after version 0.10.
50 50 This is mostly a bugfix release, since after version 0.10 was released, the
51 51 development team's energy has been focused on the 0.11 series. We have
52 52 nonetheless tried to backport what fixes we could into 0.10.1, as it remains
53 53 the stable series that many users have in production systems they rely on.
54 54
55 55 Since the 0.11 series changes many APIs in backwards-incompatible ways, we are
56 56 willing to continue maintaining the 0.10.x series. We don't really have time
57 57 to actively write new code for 0.10.x, but we are happy to accept patches and
58 58 pull requests on the IPython `github site`_. If sufficient contributions are
59 59 made that improve 0.10.1, we will roll them into future releases. For this
60 60 purpose, we will have a branch called 0.10.2 on github, on which you can base
61 61 your contributions.
62 62
63 63 .. _github site: http://github.com/ipython
64 64
65 65 For this release, we applied approximately 60 commits totaling a diff of over
66 66 7000 lines::
67 67
68 68 (0.10.1)amirbar[dist]> git diff --oneline rel-0.10.. | wc -l
69 69 7296
70 70
71 71 Highlights of this release:
72 72
73 73 - The only significant new feature is that IPython's parallel computing
74 74 machinery now supports natively the Sun Grid Engine and LSF schedulers. This
75 75 work was a joint contribution from Justin Riley, Satra Ghosh and Matthieu
76 76 Brucher, who put a lot of work into it. We also improved traceback handling
77 77 in remote tasks, as well as providing better control for remote task IDs.
78 78
79 79 - New IPython Sphinx directive contributed by John Hunter. You can use this
80 80 directive to mark blocks in reSructuredText documents as containing IPython
81 81 syntax (including figures) and the will be executed during the build:
82 82
83 83 .. sourcecode:: ipython
84 84
85 85 In [2]: plt.figure() # ensure a fresh figure
86 86
87 87 @savefig psimple.png width=4in
88 88 In [3]: plt.plot([1,2,3])
89 89 Out[3]: [<matplotlib.lines.Line2D object at 0x9b74d8c>]
90 90
91 91 - Various fixes to the standalone ipython-wx application.
92 92
93 93 - We now ship internally the excellent argparse library, graciously licensed
94 94 under BSD terms by Steven Bethard. Now (2010) that argparse has become part
95 95 of Python 2.7 this will be less of an issue, but Steven's relicensing allowed
96 96 us to start updating IPython to using argparse well before Python 2.7. Many
97 97 thanks!
98 98
99 99 - Robustness improvements so that IPython doesn't crash if the readline library
100 100 is absent (though obviously a lot of functionality that requires readline
101 101 will not be available).
102 102
103 103 - Improvements to tab completion in Emacs with Python 2.6.
104 104
105 105 - Logging now supports timestamps (see ``%logstart?`` for full details).
106 106
107 107 - A long-standing and quite annoying bug where parentheses would be added to
108 108 ``print`` statements, under Python 2.5 and 2.6, was finally fixed.
109 109
110 110 - Improved handling of libreadline on Apple OSX.
111 111
112 112 - Fix ``reload`` method of IPython demos, which was broken.
113 113
114 114 - Fixes for the ipipe/ibrowse system on OSX.
115 115
116 116 - Fixes for Zope profile.
117 117
118 118 - Fix %timeit reporting when the time is longer than 1000s.
119 119
120 120 - Avoid lockups with ? or ?? in SunOS, due to a bug in termios.
121 121
122 122 - The usual assortment of miscellaneous bug fixes and small improvements.
123 123
124 124 The following people contributed to this release (please let us know if we
125 125 omitted your name and we'll gladly fix this in the notes for the future):
126 126
127 127 * Beni Cherniavsky
128 128 * Boyd Waters.
129 129 * David Warde-Farley
130 130 * Fernando Perez
131 131 * Gökhan Sever
132 132 * John Hunter
133 133 * Justin Riley
134 134 * Kiorky
135 135 * Laurent Dufrechou
136 136 * Mark E. Smith
137 137 * Matthieu Brucher
138 138 * Satrajit Ghosh
139 139 * Sebastian Busch
140 140 * Václav Šmilauer
141 141
142 142 Release 0.10
143 143 ============
144 144
145 145 This release brings months of slow but steady development, and will be the last
146 146 before a major restructuring and cleanup of IPython's internals that is already
147 147 under way. For this reason, we hope that 0.10 will be a stable and robust
148 148 release so that while users adapt to some of the API changes that will come
149 149 with the refactoring that will become IPython 0.11, they can safely use 0.10 in
150 150 all existing projects with minimal changes (if any).
151 151
152 152 IPython 0.10 is now a medium-sized project, with roughly (as reported by David
153 153 Wheeler's :command:`sloccount` utility) 40750 lines of Python code, and a diff
154 154 between 0.9.1 and this release that contains almost 28000 lines of code and
155 155 documentation. Our documentation, in PDF format, is a 495-page long PDF
156 156 document (also available in HTML format, both generated from the same sources).
157 157
158 158 Many users and developers contributed code, features, bug reports and ideas to
159 159 this release. Please do not hesitate in contacting us if we've failed to
160 160 acknowledge your contribution here. In particular, for this release we have
161 161 contribution from the following people, a mix of new and regular names (in
162 162 alphabetical order by first name):
163 163
164 164 * Alexander Clausen: fix #341726.
165 165 * Brian Granger: lots of work everywhere (features, bug fixes, etc).
166 166 * Daniel Ashbrook: bug report on MemoryError during compilation, now fixed.
167 167 * Darren Dale: improvements to documentation build system, feedback, design
168 168 ideas.
169 169 * Fernando Perez: various places.
170 170 * Gaël Varoquaux: core code, ipythonx GUI, design discussions, etc. Lots...
171 171 * John Hunter: suggestions, bug fixes, feedback.
172 172 * Jorgen Stenarson: work on many fronts, tests, fixes, win32 support, etc.
173 173 * Laurent Dufréchou: many improvements to ipython-wx standalone app.
174 174 * Lukasz Pankowski: prefilter, `%edit`, demo improvements.
175 175 * Matt Foster: TextMate support in `%edit`.
176 176 * Nathaniel Smith: fix #237073.
177 177 * Pauli Virtanen: fixes and improvements to extensions, documentation.
178 178 * Prabhu Ramachandran: improvements to `%timeit`.
179 179 * Robert Kern: several extensions.
180 180 * Sameer D'Costa: help on critical bug #269966.
181 181 * Stephan Peijnik: feedback on Debian compliance and many man pages.
182 182 * Steven Bethard: we are now shipping his :mod:`argparse` module.
183 183 * Tom Fetherston: many improvements to :mod:`IPython.demo` module.
184 184 * Ville Vainio: lots of work everywhere (features, bug fixes, etc).
185 185 * Vishal Vasta: ssh support in ipcluster.
186 186 * Walter Doerwald: work on the :mod:`IPython.ipipe` system.
187 187
188 188 Below we give an overview of new features, bug fixes and backwards-incompatible
189 189 changes. For a detailed account of every change made, feel free to view the
190 190 project log with :command:`bzr log`.
191 191
192 192 New features
193 193 ------------
194 194
195 195 * New `%paste` magic automatically extracts current contents of clipboard and
196 196 pastes it directly, while correctly handling code that is indented or
197 197 prepended with `>>>` or `...` python prompt markers. A very useful new
198 198 feature contributed by Robert Kern.
199 199
200 200 * IPython 'demos', created with the :mod:`IPython.demo` module, can now be
201 201 created from files on disk or strings in memory. Other fixes and
202 202 improvements to the demo system, by Tom Fetherston.
203 203
204 204 * Added :func:`find_cmd` function to :mod:`IPython.platutils` module, to find
205 205 commands in a cross-platform manner.
206 206
207 207 * Many improvements and fixes to Gaël Varoquaux's :command:`ipythonx`, a
208 208 WX-based lightweight IPython instance that can be easily embedded in other WX
209 209 applications. These improvements have made it possible to now have an
210 210 embedded IPython in Mayavi and other tools.
211 211
212 212 * :class:`MultiengineClient` objects now have a :meth:`benchmark` method.
213 213
214 214 * The manual now includes a full set of auto-generated API documents from the
215 215 code sources, using Sphinx and some of our own support code. We are now
216 216 using the `Numpy Documentation Standard`_ for all docstrings, and we have
217 217 tried to update as many existing ones as possible to this format.
218 218
219 219 * The new :mod:`IPython.Extensions.ipy_pretty` extension by Robert Kern
220 220 provides configurable pretty-printing.
221 221
222 222 * Many improvements to the :command:`ipython-wx` standalone WX-based IPython
223 223 application by Laurent Dufréchou. It can optionally run in a thread, and
224 224 this can be toggled at runtime (allowing the loading of Matplotlib in a
225 225 running session without ill effects).
226 226
227 227 * IPython includes a copy of Steven Bethard's argparse_ in the
228 228 :mod:`IPython.external` package, so we can use it internally and it is also
229 229 available to any IPython user. By installing it in this manner, we ensure
230 230 zero conflicts with any system-wide installation you may already have while
231 231 minimizing external dependencies for new users. In IPython 0.10, We ship
232 232 argparse version 1.0.
233 233
234 234 * An improved and much more robust test suite, that runs groups of tests in
235 235 separate subprocesses using either Nose or Twisted's :command:`trial` runner
236 236 to ensure proper management of Twisted-using code. The test suite degrades
237 237 gracefully if optional dependencies are not available, so that the
238 238 :command:`iptest` command can be run with only Nose installed and nothing
239 239 else. We also have more and cleaner test decorators to better select tests
240 240 depending on runtime conditions, do setup/teardown, etc.
241 241
242 242 * The new ipcluster now has a fully working ssh mode that should work on
243 243 Linux, Unix and OS X. Thanks to Vishal Vatsa for implementing this!
244 244
245 245 * The wonderful TextMate editor can now be used with %edit on OS X. Thanks
246 246 to Matt Foster for this patch.
247 247
248 248 * The documentation regarding parallel uses of IPython, including MPI and PBS,
249 249 has been significantly updated and improved.
250 250
251 251 * The developer guidelines in the documentation have been updated to explain
252 252 our workflow using :command:`bzr` and Launchpad.
253 253
254 254 * Fully refactored :command:`ipcluster` command line program for starting
255 255 IPython clusters. This new version is a complete rewrite and 1) is fully
256 256 cross platform (we now use Twisted's process management), 2) has much
257 257 improved performance, 3) uses subcommands for different types of clusters, 4)
258 258 uses argparse for parsing command line options, 5) has better support for
259 259 starting clusters using :command:`mpirun`, 6) has experimental support for
260 260 starting engines using PBS. It can also reuse FURL files, by appropriately
261 261 passing options to its subcommands. However, this new version of ipcluster
262 262 should be considered a technology preview. We plan on changing the API in
263 263 significant ways before it is final.
264 264
265 265 * Full description of the security model added to the docs.
266 266
267 267 * cd completer: show bookmarks if no other completions are available.
268 268
269 269 * sh profile: easy way to give 'title' to prompt: assign to variable
270 270 '_prompt_title'. It looks like this::
271 271
272 272 [~]|1> _prompt_title = 'sudo!'
273 273 sudo![~]|2>
274 274
275 275 * %edit: If you do '%edit pasted_block', pasted_block variable gets updated
276 276 with new data (so repeated editing makes sense)
277 277
278 278 .. _Numpy Documentation Standard: https://github.com/numpy/numpy/blob/master/doc/HOWTO_DOCUMENT.rst.txt#docstring-standard
279 279
280 280 .. _argparse: http://code.google.com/p/argparse/
281 281
282 282 Bug fixes
283 283 ---------
284 284
285 285 * Fix #368719, removed top-level debian/ directory to make the job of Debian
286 286 packagers easier.
287 287
288 288 * Fix #291143 by including man pages contributed by Stephan Peijnik from the
289 289 Debian project.
290 290
291 291 * Fix #358202, effectively a race condition, by properly synchronizing file
292 292 creation at cluster startup time.
293 293
294 294 * `%timeit` now handles correctly functions that take a long time to execute
295 295 even the first time, by not repeating them.
296 296
297 297 * Fix #239054, releasing of references after exiting.
298 298
299 299 * Fix #341726, thanks to Alexander Clausen.
300 300
301 301 * Fix #269966. This long-standing and very difficult bug (which is actually a
302 302 problem in Python itself) meant long-running sessions would inevitably grow
303 303 in memory size, often with catastrophic consequences if users had large
304 304 objects in their scripts. Now, using `%run` repeatedly should not cause any
305 305 memory leaks. Special thanks to John Hunter and Sameer D'Costa for their
306 306 help with this bug.
307 307
308 308 * Fix #295371, bug in `%history`.
309 309
310 310 * Improved support for py2exe.
311 311
312 312 * Fix #270856: IPython hangs with PyGTK
313 313
314 314 * Fix #270998: A magic with no docstring breaks the '%magic magic'
315 315
316 316 * fix #271684: -c startup commands screw up raw vs. native history
317 317
318 318 * Numerous bugs on Windows with the new ipcluster have been fixed.
319 319
320 320 * The ipengine and ipcontroller scripts now handle missing furl files
321 321 more gracefully by giving better error messages.
322 322
323 323 * %rehashx: Aliases no longer contain dots. python3.0 binary
324 324 will create alias python30. Fixes:
325 325 #259716 "commands with dots in them don't work"
326 326
327 327 * %cpaste: %cpaste -r repeats the last pasted block.
328 328 The block is assigned to pasted_block even if code
329 329 raises exception.
330 330
331 331 * Bug #274067 'The code in get_home_dir is broken for py2exe' was
332 332 fixed.
333 333
334 334 * Many other small bug fixes not listed here by number (see the bzr log for
335 335 more info).
336 336
337 337 Backwards incompatible changes
338 338 ------------------------------
339 339
340 340 * `ipykit` and related files were unmaintained and have been removed.
341 341
342 342 * The :func:`IPython.genutils.doctest_reload` does not actually call
343 343 `reload(doctest)` anymore, as this was causing many problems with the test
344 344 suite. It still resets `doctest.master` to None.
345 345
346 346 * While we have not deliberately broken Python 2.4 compatibility, only minor
347 347 testing was done with Python 2.4, while 2.5 and 2.6 were fully tested. But
348 348 if you encounter problems with 2.4, please do report them as bugs.
349 349
350 350 * The :command:`ipcluster` now requires a mode argument; for example to start a
351 351 cluster on the local machine with 4 engines, you must now type::
352 352
353 353 $ ipcluster local -n 4
354 354
355 355 * The controller now has a ``-r`` flag that needs to be used if you want to
356 356 reuse existing furl files. Otherwise they are deleted (the default).
357 357
358 358 * Remove ipy_leo.py. You can use :command:`easy_install ipython-extension` to
359 359 get it. (done to decouple it from ipython release cycle)
360 360
@@ -1,322 +1,322 b''
1 1 Migrating Widgets to IPython 3
2 2 ==============================
3 3
4 4 Upgrading Notebooks
5 5 -------------------
6 6
7 7 1. The first thing you'll notice when upgrading an IPython 2.0 widget
8 8 notebook to IPython 3.0 is the "Notebook converted" dialog. Click
9 9 "ok".
10 10 2. All of the widgets distributed with IPython have been renamed. The
11 11 "Widget" suffix was removed from the end of the class name. i.e.
12 12 ``ButtonWidget`` is now ``Button``.
13 13 3. ``ContainerWidget`` was renamed to ``Box``.
14 14 4. ``PopupWidget`` was removed from IPython, because bootstrapjs was
15 15 problematic (creates global variables, etc.). If you use the
16 16 ``PopupWidget``, try using a ``Box`` widget instead. If your notebook
17 17 can't live without the popup functionality, subclass the ``Box``
18 18 widget (both in Python and JS) and use JQuery UI's ``draggable()``
19 19 and ``resizable()`` methods to mimic the behavior.
20 20 5. ``add_class`` and ``remove_class`` were removed. More often than not
21 21 a new attribute exists on the widget that allows you to achieve the
22 22 same explicitly. i.e. the ``Button`` widget now has a
23 23 ``button_style`` attribute which you can set to 'primary', 'success',
24 24 'info', 'warning', 'danger', or '' instead of using ``add_class`` to
25 25 add the bootstrap class. ``VBox`` and ``HBox`` classes (flexible
26 26 ``Box`` subclasses) were added that allow you to avoid using
27 27 ``add_class`` and ``remove_class`` to make flexible box model
28 28 layouts. As a last resort, if you can't find a built in attribute for
29 29 the class you want to use, a new ``_dom_classes`` list trait was
30 30 added, which combines ``add_class`` and ``remove_class`` into one
31 31 stateful list.
32 32 6. ``set_css`` and ``get_css`` were removed in favor of explicit style
33 33 attributes - ``visible``, ``width``, ``height``, ``padding``,
34 34 ``margin``, ``color``, ``background_color``, ``border_color``,
35 35 ``border_width``, ``border_radius``, ``border_style``,
36 36 ``font_style``, ``font_weight``, ``font_size``, and ``font_family``
37 37 are a few. If you can't find a trait to see the css attribute you
38 38 need, you can, in order of preference, (A) subclass to create your
39 39 own custom widget, (B) use CSS and the ``_dom_classes`` trait to set
40 40 ``_dom_classes``, or (C) use the ``_css`` dictionary to set CSS
41 41 styling like ``set_css`` and ``get_css``.
42 42 7. For selection widgets, such as ``Dropdown``, the ``values`` argument
43 43 has been renamed to ``options``.
44 44
45 45 Upgrading Custom Widgets
46 46 ------------------------
47 47
48 48 Javascript
49 49 ~~~~~~~~~~
50 50
51 51 1. If you are distributing your widget and decide to use the deferred
52 52 loading technique (preferred), you can remove all references to the
53 53 WidgetManager and the register model/view calls (see the Python
54 54 section below for more information).
55 55 2. In 2.0 require.js was used incorrectly, that has been fixed and now
56 56 loading works more like Python's import. Requiring
57 57 ``widgets/js/widget`` doesn't import the ``WidgetManager`` class,
58 58 instead it imports a dictionary that exposes the classes within that
59 59 module:
60 60
61 61 .. code:: javascript
62 62
63 63 {
64 64 'WidgetModel': WidgetModel,
65 65 'WidgetView': WidgetView,
66 66 'DOMWidgetView': DOMWidgetView,
67 67 'ViewList': ViewList,
68 68 }
69 69
70 70 If you decide to continue to use the widget registry (by registering
71 71 your widgets with the manager), you can import a dictionary with a
72 72 handle to the WidgetManager class by requiring
73 73 ``widgets/js/manager``. Doing so will import:
74 74
75 75 .. code:: javascript
76 76
77 77 {'WidgetManager': WidgetManager}
78 78
79 79 3. Don't rely on the ``IPython`` namespace for anything. To inherit from
80 80 the DOMWidgetView, WidgetView, or WidgetModel, require
81 81 ``widgets/js/widget`` as ``widget``. If you were inheriting from
82 82 DOMWidgetView, and the code looked like this:
83 83
84 84 .. code:: javascript
85 85
86 86 IPython.DOMWidgetView.extend({...})
87 87
88 88 It would become this:
89 89
90 90 .. code:: javascript
91 91
92 92 widget.DOMWidgetView.extend({...})
93 93
94 94 4. Custom models are encouraged. When possible, it's recommended to move
95 95 your code into a custom model, so actions are performed 1 time,
96 96 instead of N times where N is the number of displayed views.
97 97
98 98 Python
99 99 ~~~~~~
100 100
101 101 Generally, custom widget Python code can remain unchanged. If you
102 102 distribute your custom widget, you may be using ``display`` and
103 103 ``Javascript`` to publish the widget's Javascript to the front-end. That
104 104 is no longer the recommended way of distributing widget Javascript.
105 105 Instead have the user install the Javascript to his/her nbextension
106 106 directory or their profile's static directory. Then use the new
107 107 ``_view_module`` and ``_model_module`` traitlets in combination with
108 108 ``_view_name`` and ``_model_name`` to instruct require.js on how to load
109 109 the widget's Javascript. The Javascript is then loaded when the widget
110 110 is used for the first time.
111 111
112 112 Details
113 113 -------
114 114
115 115 Asynchronous
116 116 ~~~~~~~~~~~~
117 117
118 118 In the IPython 2.x series the only way to register custom widget views
119 119 and models was to use the registry in the widget manager. Unfortunately,
120 120 using this method made distributing and running custom widgets difficult. The widget
121 121 maintainer had to either use the rich display framework to push the
122 122 widget's Javascript to the notebook or instruct the users to install the
123 123 Javascript by hand in a custom profile. With the first method, the
124 124 maintainer would have to be careful about when the Javascript was pushed
125 125 to the front-end. If the Javascript was pushed on Python widget
126 126 ``import``, the widgets wouldn't work after page refresh. This is
127 127 because refreshing the page does not restart the kernel, and the Python
128 128 ``import`` statement only runs once in a given kernel instance (unless
129 129 you reload the Python modules, which isn't straight forward). This meant
130 130 the maintainer would have to have a separate ``push_js()`` method that
131 131 the user would have to call after importing the widget's Python code.
132 132
133 133 Our solution was to add support for loading widget views and models
134 134 using require.js paths. Thus the comm and widget frameworks now support
135 135 lazy loading. To do so, everything had to be converted to asynchronous
136 136 code. HTML5 promises are used to accomplish that
137 137 (`#6818 <https://github.com/ipython/ipython/pull/6818>`__,
138 138 `#6914 <https://github.com/ipython/ipython/pull/6914>`__).
139 139
140 140 Symmetry
141 141 ~~~~~~~~
142 142
143 143 In IPython 3.0, widgets can be instantiated from the front-end
144 144 (`#6664 <https://github.com/ipython/ipython/pull/6664>`__). On top of
145 145 this, a widget persistence API was added
146 146 (`#7163 <https://github.com/ipython/ipython/pull/7163>`__,
147 147 `#7227 <https://github.com/ipython/ipython/pull/7227>`__). With the
148 148 widget persistence API, you can persist your widget instances using
149 149 Javascript. This makes it easy to persist your widgets to your notebook
150 150 document (with a small amount of custom JS). By default, the widgets are
151 151 persisted to your web browsers local storage which makes them reappear
152 152 when your refresh the page.
153 153
154 154 Smaller Changes
155 155 ~~~~~~~~~~~~~~~
156 156
157 157 - Latex math is supported in widget ``description``\ s
158 158 (`#5937 <https://github.com/ipython/ipython/pull/5937>`__).
159 159 - Widgets can be display more than once within a single container
160 160 widget (`#5963 <https://github.com/ipython/ipython/pull/5963>`__,
161 161 `#6990 <https://github.com/ipython/ipython/pull/6990>`__).
162 162 - ``FloatRangeSlider`` and ``IntRangeSlider`` were added
163 163 (`#6050 <https://github.com/ipython/ipython/pull/6050>`__).
164 164 - "Widget" was removed from the ends of all of the widget class names
165 165 (`#6125 <https://github.com/ipython/ipython/pull/6125>`__).
166 166 - ``ContainerWidget`` was renamed to ``Box``
167 167 (`#6125 <https://github.com/ipython/ipython/pull/6125>`__).
168 168 - ``HBox`` and ``VBox`` widgets were added
169 169 (`#6125 <https://github.com/ipython/ipython/pull/6125>`__).
170 170 - ``add\_class`` and ``remove\_class`` were removed in favor of a
171 171 ``_dom_classes`` list
172 172 (`#6235 <https://github.com/ipython/ipython/pull/6235>`__).
173 173 - ``get\_css`` and ``set\_css`` were removed in favor of explicit
174 174 traits for widget styling
175 175 (`#6235 <https://github.com/ipython/ipython/pull/6235>`__).
176 176 - ``jslink`` and ``jsdlink`` were added
177 177 (`#6454 <https://github.com/ipython/ipython/pull/6454>`__,
178 178 `#7468 <https://github.com/ipython/ipython/pull/7468>`__).
179 179 - An ``Output`` widget was added, which allows you to ``print`` and
180 180 ``display`` within widgets
181 181 (`#6670 <https://github.com/ipython/ipython/pull/6670>`__).
182 182 - ``PopupWidget`` was removed
183 183 (`#7341 <https://github.com/ipython/ipython/pull/7341>`__).
184 184 - A visual cue was added for widgets with 'dead' comms
185 185 (`#7227 <https://github.com/ipython/ipython/pull/7227>`__).
186 186 - A ``SelectMultiple`` widget was added (a ``Select`` widget that
187 187 allows multiple things to be selected at once)
188 188 (`#6890 <https://github.com/ipython/ipython/pull/6890>`__).
189 189 - A class was added to help manage children views
190 190 (`#6990 <https://github.com/ipython/ipython/pull/6990>`__).
191 191 - A warning was added that shows on widget import because it's expected
192 192 that the API will change again by IPython 4.0. This warning can be
193 supressed (`#7107 <https://github.com/ipython/ipython/pull/7107>`__,
193 suppressed (`#7107 <https://github.com/ipython/ipython/pull/7107>`__,
194 194 `#7200 <https://github.com/ipython/ipython/pull/7200>`__,
195 195 `#7201 <https://github.com/ipython/ipython/pull/7201>`__,
196 196 `#7204 <https://github.com/ipython/ipython/pull/7204>`__).
197 197
198 198 Comm and Widget PR Index
199 199 ------------------------
200 200
201 201 Here is a chronological list of PRs affecting the widget and comm frameworks for IPython 3.0. Note that later PRs may revert changes
202 202 made in earlier PRs:
203 203
204 204 - Add placeholder attribute to text widgets
205 205 `#5652 <https://github.com/ipython/ipython/pull/5652>`__
206 206 - Add latex support in widget labels,
207 207 `#5937 <https://github.com/ipython/ipython/pull/5937>`__
208 208 - Allow widgets to display more than once within container widgets.
209 209 `#5963 <https://github.com/ipython/ipython/pull/5963>`__
210 210 - use require.js,
211 211 `#5980 <https://github.com/ipython/ipython/pull/5980>`__
212 212 - Range widgets
213 213 `#6050 <https://github.com/ipython/ipython/pull/6050>`__
214 214 - Interact on\_demand option
215 215 `#6051 <https://github.com/ipython/ipython/pull/6051>`__
216 216 - Allow text input on slider widgets
217 217 `#6106 <https://github.com/ipython/ipython/pull/6106>`__
218 218 - support binary buffers in comm messages
219 219 `#6110 <https://github.com/ipython/ipython/pull/6110>`__
220 220 - Embrace the flexible box model in the widgets
221 221 `#6125 <https://github.com/ipython/ipython/pull/6125>`__
222 222 - Widget trait serialization
223 223 `#6128 <https://github.com/ipython/ipython/pull/6128>`__
224 224 - Make Container widgets take children as the first positional
225 225 argument `#6153 <https://github.com/ipython/ipython/pull/6153>`__
226 226 - once-displayed
227 227 `#6168 <https://github.com/ipython/ipython/pull/6168>`__
228 228 - Validate slider value, when limits change
229 229 `#6171 <https://github.com/ipython/ipython/pull/6171>`__
230 230 - Unregistering comms in Comm Manager
231 231 `#6216 <https://github.com/ipython/ipython/pull/6216>`__
232 232 - Add EventfulList and EventfulDict trait types.
233 233 `#6228 <https://github.com/ipython/ipython/pull/6228>`__
234 234 - Remove add/remove\_class and set/get\_css.
235 235 `#6235 <https://github.com/ipython/ipython/pull/6235>`__
236 236 - avoid unregistering widget model twice
237 237 `#6250 <https://github.com/ipython/ipython/pull/6250>`__
238 238 - Widget property lock should compare json states, not python states
239 239 `#6332 <https://github.com/ipython/ipython/pull/6332>`__
240 240 - Strip the IPY\_MODEL\_ prefix from widget IDs before referencing
241 241 them. `#6377 <https://github.com/ipython/ipython/pull/6377>`__
242 242 - "event" is not defined error in Firefox
243 243 `#6437 <https://github.com/ipython/ipython/pull/6437>`__
244 244 - Javascript link
245 245 `#6454 <https://github.com/ipython/ipython/pull/6454>`__
246 246 - Bulk update of widget attributes
247 247 `#6463 <https://github.com/ipython/ipython/pull/6463>`__
248 248 - Creating a widget registry on the Python side.
249 249 `#6493 <https://github.com/ipython/ipython/pull/6493>`__
250 250 - Allow widget views to be loaded from require modules
251 251 `#6494 <https://github.com/ipython/ipython/pull/6494>`__
252 252 - Fix Issue #6530
253 253 `#6532 <https://github.com/ipython/ipython/pull/6532>`__
254 254 - Make comm manager (mostly) independent of InteractiveShell
255 255 `#6540 <https://github.com/ipython/ipython/pull/6540>`__
256 256 - Add semantic classes to top-level containers for single widgets
257 257 `#6609 <https://github.com/ipython/ipython/pull/6609>`__
258 258 - Selection Widgets: forcing 'value' to be in 'values'
259 259 `#6617 <https://github.com/ipython/ipython/pull/6617>`__
260 260 - Allow widgets to be constructed from Javascript
261 261 `#6664 <https://github.com/ipython/ipython/pull/6664>`__
262 262 - Output widget
263 263 `#6670 <https://github.com/ipython/ipython/pull/6670>`__
264 264 - Minor change in widgets.less to fix alignment issue
265 265 `#6681 <https://github.com/ipython/ipython/pull/6681>`__
266 266 - Make Selection widgets respect values order.
267 267 `#6747 <https://github.com/ipython/ipython/pull/6747>`__
268 268 - Widget persistence API
269 269 `#6789 <https://github.com/ipython/ipython/pull/6789>`__
270 270 - Add promises to the widget framework.
271 271 `#6818 <https://github.com/ipython/ipython/pull/6818>`__
272 272 - SelectMultiple widget
273 273 `#6890 <https://github.com/ipython/ipython/pull/6890>`__
274 274 - Tooltip on toggle button
275 275 `#6923 <https://github.com/ipython/ipython/pull/6923>`__
276 276 - Allow empty text box \*while typing\* for numeric widgets
277 277 `#6943 <https://github.com/ipython/ipython/pull/6943>`__
278 278 - Ignore failure of widget MathJax typesetting
279 279 `#6948 <https://github.com/ipython/ipython/pull/6948>`__
280 280 - Refactor the do\_diff and manual child view lists into a separate
281 281 ViewList object
282 282 `#6990 <https://github.com/ipython/ipython/pull/6990>`__
283 283 - Add warning to widget namespace import.
284 284 `#7107 <https://github.com/ipython/ipython/pull/7107>`__
285 285 - lazy load widgets
286 286 `#7120 <https://github.com/ipython/ipython/pull/7120>`__
287 287 - Fix padding of widgets.
288 288 `#7139 <https://github.com/ipython/ipython/pull/7139>`__
289 289 - Persist widgets across page refresh
290 290 `#7163 <https://github.com/ipython/ipython/pull/7163>`__
291 291 - Make the widget experimental error a real python warning
292 292 `#7200 <https://github.com/ipython/ipython/pull/7200>`__
293 293 - Make the widget error message shorter and more understandable.
294 294 `#7201 <https://github.com/ipython/ipython/pull/7201>`__
295 295 - Make the widget warning brief and easy to filter
296 296 `#7204 <https://github.com/ipython/ipython/pull/7204>`__
297 297 - Add visual cue for widgets with dead comms
298 298 `#7227 <https://github.com/ipython/ipython/pull/7227>`__
299 299 - Widget values as positional arguments
300 300 `#7260 <https://github.com/ipython/ipython/pull/7260>`__
301 301 - Remove the popup widget
302 302 `#7341 <https://github.com/ipython/ipython/pull/7341>`__
303 303 - document and validate link, dlink
304 304 `#7468 <https://github.com/ipython/ipython/pull/7468>`__
305 305 - Document interact 5637
306 306 `#7525 <https://github.com/ipython/ipython/pull/7525>`__
307 307 - Update some broken examples of using widgets
308 308 `#7547 <https://github.com/ipython/ipython/pull/7547>`__
309 309 - Use Output widget with Interact
310 310 `#7554 <https://github.com/ipython/ipython/pull/7554>`__
311 311 - don't send empty execute\_result messages
312 312 `#7560 <https://github.com/ipython/ipython/pull/7560>`__
313 313 - Validation on the python side
314 314 `#7602 <https://github.com/ipython/ipython/pull/7602>`__
315 315 - only show prompt overlay if there's a prompt
316 316 `#7661 <https://github.com/ipython/ipython/pull/7661>`__
317 317 - Allow predictate to be used for comparison in selection widgets
318 318 `#7674 <https://github.com/ipython/ipython/pull/7674>`__
319 319 - Fix widget view persistence.
320 320 `#7680 <https://github.com/ipython/ipython/pull/7680>`__
321 321 - Revert "Use Output widget with Interact"
322 322 `#7703 <https://github.com/ipython/ipython/pull/7703>`__
@@ -1,413 +1,413 b''
1 1 ============
2 2 5.x Series
3 3 ============
4 4
5 5
6 6 .. _whatsnew550:
7 7
8 8 IPython 5.5
9 9 ===========
10 10
11 11 System Wide config
12 12 ------------------
13 13
14 14 - IPython now looks for config files in ``{sys.prefix}/etc/ipython``
15 15 for environment-specific configuration.
16 16 - Startup files can be found in ``/etc/ipython/startup`` or ``{sys.prefix}/etc/ipython/startup``
17 17 in addition to the profile directory, for system-wide or env-specific startup files.
18 18
19 19 See :ghpull:`10644`
20 20
21 21 ProgressBar
22 22 -----------
23 23
24 24
25 25 IPython now has built-in support for progressbars::
26 26
27 27 In[1]: from IPython.display import ProgressBar
28 28 ... : pb = ProgressBar(100)
29 29 ... : pb
30 30
31 31 In[2]: pb.progress = 50
32 32
33 33 # progress bar in cell 1 updates.
34 34
35 35 See :ghpull:`10755`
36 36
37 37
38 38 Misc
39 39 ----
40 40
41 41 - Fix ``IPython.core.display:Pretty._repr_pretty_`` had the wrong signature.
42 42 (:ghpull:`10625`)
43 43 - :magic:`timeit` now give a correct ``SyntaxError`` if naked ``return`` used.
44 44 (:ghpull:`10637`)
45 45 - Prepare the ``:ipython:`` directive to be compatible with Sphinx 1.7.
46 46 (:ghpull:`10668`)
47 47 - Make IPython work with OpenSSL in FIPS mode; change hash algorithm of input
48 48 from md5 to sha1. (:ghpull:`10696`)
49 49 - Clear breakpoints before running any script with debugger. (:ghpull:`10699`)
50 50 - Document that :magic:`profile` is deprecated, not to be confused with :magic:`prun`. (:ghpull:`10707`)
51 51 - Limit default number of returned completions to 500. (:ghpull:`10743`)
52 52
53 53 You can see all the PR marked for the `5.5. milestone <https://github.com/ipython/ipython/pulls?q=is%3Apr%20milestone%3A5.5%20is%3Aclosed%20NOT%20%22Backport%20PR%22>`_,
54 54 and all the `backport versions <https://github.com/ipython/ipython/pulls?utf8=%E2%9C%93&q=is%3Apr%20milestone%3A5.5%20is%3Aclosed%20%22Backport%20PR%22%20>`_.
55 55
56 56
57 57
58 58
59 59 .. _whatsnew540:
60 60
61 61 IPython 5.4
62 62 ===========
63 63
64 64 IPython 5.4-LTS is the first release of IPython after the release of the 6.x
65 65 series which is Python 3 only. It backports most of the new exposed API
66 66 additions made in IPython 6.0 and 6.1 and avoid having to write conditional
67 67 logics depending of the version of IPython.
68 68
69 69 Please upgrade to pip 9 or greater before upgrading IPython.
70 70 Failing to do so on Python 2 may lead to a broken IPython install.
71 71
72 72 Configurable TerminalInteractiveShell
73 73 -------------------------------------
74 74
75 75 Backported from the 6.x branch as an exceptional new feature. See
76 76 :ghpull:`10373` and :ghissue:`10364`
77 77
78 78 IPython gained a new ``c.TerminalIPythonApp.interactive_shell_class`` option
79 79 that allow to customize the class used to start the terminal frontend. This
80 80 should allow user to use custom interfaces, like reviving the former readline
81 81 interface which is now a separate package not maintained by the core team.
82 82
83 83
84 84 Define ``_repr_mimebundle_``
85 85 ----------------------------
86 86
87 87 Object can now define `_repr_mimebundle_` in place of multiple `_repr_*_`
88 88 methods and return a full mimebundle. This greatly simplify many implementation
89 89 and allow to publish custom mimetypes (like geojson, plotly, dataframes....).
90 See the ``Cutom Display Logic`` example notebook for more informations.
90 See the ``Custom Display Logic`` example notebook for more information.
91 91
92 92 Execution Heuristics
93 93 --------------------
94 94
95 95 The heuristic for execution in the command line interface is now more biased
96 96 toward executing for single statement. While in IPython 4.x and before a single
97 97 line would be executed when enter is pressed, IPython 5.x would insert a new
98 98 line. For single line statement this is not true anymore and if a single line is
99 99 valid Python, IPython will execute it regardless of the cursor position. Use
100 100 :kbd:`Ctrl-O` to insert a new line. :ghpull:`10489`
101 101
102 102
103 103 Implement Display IDs
104 104 ---------------------
105 105
106 106 Implement display id and ability to update a given display. This should greatly
107 107 simplify a lot of code by removing the need for widgets and allow other frontend
108 108 to implement things like progress-bars. See :ghpull:`10048`
109 109
110 110 Display function
111 111 ----------------
112 112
113 113 The :func:`display() <IPython.display.display>` function is now available by
114 114 default in an IPython session, meaning users can call it on any object to see
115 115 their rich representation. This should allow for better interactivity both at
116 116 the REPL and in notebook environment.
117 117
118 118 Scripts and library that rely on display and may be run outside of IPython still
119 119 need to import the display function using ``from IPython.display import
120 120 display``. See :ghpull:`10596`
121 121
122 122
123 123 Miscs
124 124 -----
125 125
126 126 * ``_mp_main_`` is not reloaded which fixes issues with multiprocessing.
127 127 :ghpull:`10523`
128 128 * Use user colorscheme in Pdb as well :ghpull:`10479`
129 129 * Faster shutdown. :ghpull:`10408`
130 130 * Fix a crash in reverse search. :ghpull:`10371`
131 131 * added ``Completer.backslash_combining_completions`` boolean option to
132 132 deactivate backslash-tab completion that may conflict with windows path.
133 133
134 134 IPython 5.3
135 135 ===========
136 136
137 137 Released on February 24th, 2017. Remarkable changes and fixes:
138 138
139 139 * Fix a bug in ``set_next_input`` leading to a crash of terminal IPython.
140 140 :ghpull:`10231`, :ghissue:`10296`, :ghissue:`10229`
141 141 * Always wait for editor inputhook for terminal IPython :ghpull:`10239`,
142 142 :ghpull:`10240`
143 143 * Disable ``_ipython_display_`` in terminal :ghpull:`10249`, :ghpull:`10274`
144 144 * Update terminal colors to be more visible by default on windows
145 145 :ghpull:`10260`, :ghpull:`10238`, :ghissue:`10281`
146 146 * Add Ctrl-Z shortcut (suspend) in terminal debugger :ghpull:`10254`,
147 147 :ghissue:`10273`
148 148 * Indent on new line by looking at the text before the cursor :ghpull:`10264`,
149 149 :ghpull:`10275`, :ghissue:`9283`
150 150 * Update QtEventloop integration to fix some matplotlib integration issues
151 151 :ghpull:`10201`, :ghpull:`10311`, :ghissue:`10201`
152 152 * Respect completions display style in terminal debugger :ghpull:`10305`,
153 153 :ghpull:`10313`
154 154 * Add a config option ``TerminalInteractiveShell.extra_open_editor_shortcuts``
155 155 to enable extra shortcuts to open the input in an editor. These are :kbd:`v`
156 156 in vi mode, and :kbd:`C-X C-E` in emacs mode (:ghpull:`10330`).
157 157 The :kbd:`F2` shortcut is always enabled.
158 158
159 159 IPython 5.2.2
160 160 =============
161 161
162 162 * Fix error when starting with ``IPCompleter.limit_to__all__`` configured.
163 163
164 164 IPython 5.2.1
165 165 =============
166 166
167 167 * Fix tab completion in the debugger. :ghpull:`10223`
168 168
169 169 IPython 5.2
170 170 ===========
171 171
172 172 Released on January 29th, 2017. Remarkable changes and fixes:
173 173
174 174 * restore IPython's debugger to raise on quit. :ghpull:`10009`
175 175 * The configuration value ``c.TerminalInteractiveShell.highlighting_style`` can
176 176 now directly take a class argument for custom color style. :ghpull:`9848`
177 177 * Correctly handle matplotlib figures dpi :ghpull:`9868`
178 178 * Deprecate ``-e`` flag for the ``%notebook`` magic that had no effects.
179 179 :ghpull:`9872`
180 180 * You can now press F2 while typing at a terminal prompt to edit the contents
181 181 in your favourite terminal editor. Set the :envvar:`EDITOR` environment
182 182 variable to pick which editor is used. :ghpull:`9929`
183 183 * sdists will now only be ``.tar.gz`` as per upstream PyPI requirements.
184 184 :ghpull:`9925`
185 185 * :any:`IPython.core.debugger` have gained a ``set_trace()`` method for
186 186 convenience. :ghpull:`9947`
187 187 * The 'smart command mode' added to the debugger in 5.0 was removed, as more
188 188 people preferred the previous behaviour. Therefore, debugger commands such as
189 189 ``c`` will act as debugger commands even when ``c`` is defined as a variable.
190 190 :ghpull:`10050`
191 191 * Fixes OS X event loop issues at startup, :ghpull:`10150`
192 192 * Deprecate the ``%autoindent`` magic. :ghpull:`10176`
193 193 * Emit a :any:`DeprecationWarning` when setting the deprecated
194 194 ``limit_to_all`` option of the completer. :ghpull:`10198`
195 195 * The :cellmagic:`capture` magic can now capture the result of a cell (from an
196 196 expression on the last line), as well as printed and displayed output.
197 197 :ghpull:`9851`.
198 198
199 199
200 200 Changes of behavior to :any:`InteractiveShellEmbed`.
201 201
202 202 :any:`InteractiveShellEmbed` interactive behavior have changed a bit in between
203 203 5.1 and 5.2. By default ``%kill_embedded`` magic will prevent further invocation
204 204 of the current ``call location`` instead of preventing further invocation of
205 205 the current instance creation location. For most use case this will not change
206 206 much for you, though previous behavior was confusing and less consistent with
207 207 previous IPython versions.
208 208
209 209 You can now deactivate instances by using ``%kill_embedded --instance`` flag,
210 210 (or ``-i`` in short). The ``%kill_embedded`` magic also gained a
211 211 ``--yes``/``-y`` option which skip confirmation step, and ``-x``/``--exit``
212 212 which also exit the current embedded call without asking for confirmation.
213 213
214 214 See :ghpull:`10207`.
215 215
216 216
217 217
218 218 IPython 5.1
219 219 ===========
220 220
221 221 * Broken ``%timeit`` on Python2 due to the use of ``__qualname__``. :ghpull:`9804`
222 222 * Restore ``%gui qt`` to create and return a ``QApplication`` if necessary. :ghpull:`9789`
223 223 * Don't set terminal title by default. :ghpull:`9801`
224 224 * Preserve indentation when inserting newlines with ``Ctrl-O``. :ghpull:`9770`
225 225 * Restore completion in debugger. :ghpull:`9785`
226 226 * Deprecate ``IPython.core.debugger.Tracer()`` in favor of simpler, newer, APIs. :ghpull:`9731`
227 227 * Restore ``NoOpContext`` context manager removed by mistake, and add `DeprecationWarning`. :ghpull:`9765`
228 228 * Add option allowing ``Prompt_toolkit`` to use 24bits colors. :ghpull:`9736`
229 229 * Fix for closing interactive matplotlib windows on OS X. :ghpull:`9854`
230 230 * An embedded interactive shell instance can be used more than once. :ghpull:`9843`
231 231 * More robust check for whether IPython is in a terminal. :ghpull:`9833`
232 232 * Better pretty-printing of dicts on PyPy. :ghpull:`9827`
233 233 * Some coloured output now looks better on dark background command prompts in Windows.
234 234 :ghpull:`9838`
235 235 * Improved tab completion of paths on Windows . :ghpull:`9826`
236 236 * Fix tkinter event loop integration on Python 2 with ``future`` installed. :ghpull:`9824`
237 237 * Restore ``Ctrl-\`` as a shortcut to quit IPython.
238 238 * Make ``get_ipython()`` accessible when modules are imported by startup files. :ghpull:`9818`
239 239 * Add support for running directories containing a ``__main__.py`` file with the
240 240 ``ipython`` command. :ghpull:`9813`
241 241
242 242
243 243 True Color feature
244 244 ------------------
245 245
246 246 ``prompt_toolkit`` uses pygments styles for syntax highlighting. By default, the
247 247 colors specified in the style are approximated using a standard 256-color
248 248 palette. ``prompt_toolkit`` also supports 24bit, a.k.a. "true", a.k.a. 16-million
249 249 color escape sequences which enable compatible terminals to display the exact
250 250 colors specified instead of an approximation. This true_color option exposes
251 251 that capability in prompt_toolkit to the IPython shell.
252 252
253 253 Here is a good source for the current state of true color support in various
254 254 terminal emulators and software projects: https://gist.github.com/XVilka/8346728
255 255
256 256
257 257
258 258 IPython 5.0
259 259 ===========
260 260
261 261 Released July 7, 2016
262 262
263 263 New terminal interface
264 264 ----------------------
265 265
266 266 IPython 5 features a major upgrade to the terminal interface, bringing live
267 267 syntax highlighting as you type, proper multiline editing and multiline paste,
268 268 and tab completions that don't clutter up your history.
269 269
270 270 .. image:: ../_images/ptshell_features.png
271 271 :alt: New terminal interface features
272 272 :align: center
273 273 :target: ../_images/ptshell_features.png
274 274
275 275 These features are provided by the Python library `prompt_toolkit
276 276 <http://python-prompt-toolkit.readthedocs.io/en/stable/>`__, which replaces
277 277 ``readline`` throughout our terminal interface.
278 278
279 279 Relying on this pure-Python, cross platform module also makes it simpler to
280 280 install IPython. We have removed dependencies on ``pyreadline`` for Windows and
281 281 ``gnureadline`` for Mac.
282 282
283 283 Backwards incompatible changes
284 284 ------------------------------
285 285
286 286 - The ``%install_ext`` magic function, deprecated since 4.0, has now been deleted.
287 287 You can distribute and install extensions as packages on PyPI.
288 288 - Callbacks registered while an event is being handled will now only be called
289 289 for subsequent events; previously they could be called for the current event.
290 290 Similarly, callbacks removed while handling an event *will* always get that
291 291 event. See :ghissue:`9447` and :ghpull:`9453`.
292 292 - Integration with pydb has been removed since pydb development has been stopped
293 293 since 2012, and pydb is not installable from PyPI.
294 294 - The ``autoedit_syntax`` option has apparently been broken for many years.
295 295 It has been removed.
296 296
297 297 New terminal interface
298 298 ~~~~~~~~~~~~~~~~~~~~~~
299 299
300 300 The overhaul of the terminal interface will probably cause a range of minor
301 301 issues for existing users.
302 302 This is inevitable for such a significant change, and we've done our best to
303 303 minimise these issues.
304 304 Some changes that we're aware of, with suggestions on how to handle them:
305 305
306 306 IPython no longer uses readline configuration (``~/.inputrc``). We hope that
307 307 the functionality you want (e.g. vi input mode) will be available by configuring
308 308 IPython directly (see :doc:`/config/options/terminal`).
309 309 If something's missing, please file an issue.
310 310
311 311 The ``PromptManager`` class has been removed, and the prompt machinery simplified.
312 312 See :ref:`custom_prompts` to customise prompts with the new machinery.
313 313
314 314 :mod:`IPython.core.debugger` now provides a plainer interface.
315 315 :mod:`IPython.terminal.debugger` contains the terminal debugger using
316 316 prompt_toolkit.
317 317
318 318 There are new options to configure the colours used in syntax highlighting.
319 319 We have tried to integrate them with our classic ``--colors`` option and
320 320 ``%colors`` magic, but there's a mismatch in possibilities, so some configurations
321 321 may produce unexpected results. See :ref:`termcolour` for more information.
322 322
323 323 The new interface is not compatible with Emacs 'inferior-shell' feature. To
324 324 continue using this, add the ``--simple-prompt`` flag to the command Emacs
325 325 runs. This flag disables most IPython features, relying on Emacs to provide
326 326 things like tab completion.
327 327
328 328 Provisional Changes
329 329 -------------------
330 330
331 331 Provisional changes are experimental functionality that may, or may not, make
332 332 it into a future version of IPython, and which API may change without warnings.
333 333 Activating these features and using these API are at your own risk, and may have
334 334 security implication for your system, especially if used with the Jupyter notebook,
335 335
336 336 When running via the Jupyter notebook interfaces, or other compatible client,
337 337 you can enable rich documentation experimental functionality:
338 338
339 339 When the ``docrepr`` package is installed setting the boolean flag
340 340 ``InteractiveShell.sphinxify_docstring`` to ``True``, will process the various
341 341 object through sphinx before displaying them (see the ``docrepr`` package
342 342 documentation for more information.
343 343
344 344 You need to also enable the IPython pager display rich HTML representation
345 345 using the ``InteractiveShell.enable_html_pager`` boolean configuration option.
346 346 As usual you can set these configuration options globally in your configuration
347 347 files, alternatively you can turn them on dynamically using the following
348 348 snippet:
349 349
350 350 .. code-block:: python
351 351
352 352 ip = get_ipython()
353 353 ip.sphinxify_docstring = True
354 354 ip.enable_html_pager = True
355 355
356 356
357 357 You can test the effect of various combinations of the above configuration in
358 358 the Jupyter notebook, with things example like :
359 359
360 360 .. code-block:: ipython
361 361
362 362 import numpy as np
363 363 np.histogram?
364 364
365 365
366 366 This is part of an effort to make Documentation in Python richer and provide in
367 367 the long term if possible dynamic examples that can contain math, images,
368 368 widgets... As stated above this is nightly experimental feature with a lot of
369 369 (fun) problem to solve. We would be happy to get your feedback and expertise on
370 370 it.
371 371
372 372
373 373
374 374 Deprecated Features
375 375 -------------------
376 376
377 377 Some deprecated features are listed in this section. Don't forget to enable
378 378 ``DeprecationWarning`` as an error if you are using IPython in a Continuous
379 379 Integration setup or in your testing in general:
380 380
381 381 .. code-block:: python
382 382
383 383 import warnings
384 384 warnings.filterwarnings('error', '.*', DeprecationWarning, module='yourmodule.*')
385 385
386 386
387 387 - ``hooks.fix_error_editor`` seems unused and is pending deprecation.
388 388 - `IPython/core/excolors.py:ExceptionColors` is deprecated.
389 389 - `IPython.core.InteractiveShell:write()` is deprecated; use `sys.stdout` instead.
390 390 - `IPython.core.InteractiveShell:write_err()` is deprecated; use `sys.stderr` instead.
391 391 - The `formatter` keyword argument to `Inspector.info` in `IPython.core.oinspec` has no effect.
392 392 - The `global_ns` keyword argument of IPython Embed was deprecated, and has no effect. Use `module` keyword argument instead.
393 393
394 394
395 395 Known Issues:
396 396 -------------
397 397
398 398 - ``<Esc>`` Key does not dismiss the completer and does not clear the current
399 399 buffer. This is an on purpose modification due to current technical
400 400 limitation. Cf :ghpull:`9572`. Escape the control character which is used
401 401 for other shortcut, and there is no practical way to distinguish. Use Ctr-G
402 402 or Ctrl-C as an alternative.
403 403
404 404 - Cannot use ``Shift-Enter`` and ``Ctrl-Enter`` to submit code in terminal. cf
405 405 :ghissue:`9587` and :ghissue:`9401`. In terminal there is no practical way to
406 406 distinguish these key sequences from a normal new line return.
407 407
408 408 - ``PageUp`` and ``pageDown`` do not move through completion menu.
409 409
410 410 - Color styles might not adapt to terminal emulator themes. This will need new
411 411 version of Pygments to be released, and can be mitigated with custom themes.
412 412
413 413
@@ -1,976 +1,976 b''
1 1 {
2 2 "cells": [
3 3 {
4 4 "cell_type": "markdown",
5 5 "metadata": {},
6 6 "source": [
7 7 "# Custom Display Logic"
8 8 ]
9 9 },
10 10 {
11 11 "cell_type": "markdown",
12 12 "metadata": {},
13 13 "source": [
14 14 "## Overview"
15 15 ]
16 16 },
17 17 {
18 18 "cell_type": "markdown",
19 19 "metadata": {},
20 20 "source": [
21 21 "As described in the [Rich Output](Rich Output.ipynb) tutorial, the IPython display system can display rich representations of objects in the following formats:\n",
22 22 "\n",
23 23 "* JavaScript\n",
24 24 "* HTML\n",
25 25 "* PNG\n",
26 26 "* JPEG\n",
27 27 "* SVG\n",
28 28 "* LaTeX\n",
29 29 "* PDF\n",
30 30 "\n",
31 31 "This Notebook shows how you can add custom display logic to your own classes, so that they can be displayed using these rich representations. There are two ways of accomplishing this:\n",
32 32 "\n",
33 33 "1. Implementing special display methods such as `_repr_html_` when you define your class.\n",
34 34 "2. Registering a display function for a particular existing class.\n",
35 35 "\n",
36 36 "This Notebook describes and illustrates both approaches."
37 37 ]
38 38 },
39 39 {
40 40 "cell_type": "markdown",
41 41 "metadata": {},
42 42 "source": [
43 43 "Import the IPython display functions."
44 44 ]
45 45 },
46 46 {
47 47 "cell_type": "code",
48 48 "execution_count": 1,
49 49 "metadata": {
50 50 "collapsed": true
51 51 },
52 52 "outputs": [],
53 53 "source": [
54 54 "from IPython.display import (\n",
55 55 " display, display_html, display_png, display_svg\n",
56 56 ")"
57 57 ]
58 58 },
59 59 {
60 60 "cell_type": "markdown",
61 61 "metadata": {},
62 62 "source": [
63 63 "Parts of this notebook need the matplotlib inline backend:"
64 64 ]
65 65 },
66 66 {
67 67 "cell_type": "code",
68 68 "execution_count": 2,
69 69 "metadata": {
70 70 "collapsed": true
71 71 },
72 72 "outputs": [],
73 73 "source": [
74 74 "import numpy as np\n",
75 75 "import matplotlib.pyplot as plt\n",
76 76 "plt.ion()"
77 77 ]
78 78 },
79 79 {
80 80 "cell_type": "markdown",
81 81 "metadata": {},
82 82 "source": [
83 83 "## Special display methods"
84 84 ]
85 85 },
86 86 {
87 87 "cell_type": "markdown",
88 88 "metadata": {},
89 89 "source": [
90 90 "The main idea of the first approach is that you have to implement special display methods when you define your class, one for each representation you want to use. Here is a list of the names of the special methods and the values they must return:\n",
91 91 "\n",
92 92 "* `_repr_html_`: return raw HTML as a string\n",
93 93 "* `_repr_json_`: return a JSONable dict\n",
94 94 "* `_repr_jpeg_`: return raw JPEG data\n",
95 95 "* `_repr_png_`: return raw PNG data\n",
96 96 "* `_repr_svg_`: return raw SVG data as a string\n",
97 97 "* `_repr_latex_`: return LaTeX commands in a string surrounded by \"$\".\n",
98 98 "* `_repr_mimebundle_`: return a full mimebundle containing the mapping from all mimetypes to data "
99 99 ]
100 100 },
101 101 {
102 102 "cell_type": "markdown",
103 103 "metadata": {},
104 104 "source": [
105 105 "As an illustration, we build a class that holds data generated by sampling a Gaussian distribution with given mean and standard deviation. Here is the definition of the `Gaussian` class, which has a custom PNG and LaTeX representation."
106 106 ]
107 107 },
108 108 {
109 109 "cell_type": "code",
110 110 "execution_count": 3,
111 111 "metadata": {
112 112 "collapsed": true
113 113 },
114 114 "outputs": [],
115 115 "source": [
116 116 "from IPython.core.pylabtools import print_figure\n",
117 117 "from IPython.display import Image, SVG, Math\n",
118 118 "\n",
119 119 "class Gaussian(object):\n",
120 120 " \"\"\"A simple object holding data sampled from a Gaussian distribution.\n",
121 121 " \"\"\"\n",
122 122 " def __init__(self, mean=0.0, std=1, size=1000):\n",
123 123 " self.data = np.random.normal(mean, std, size)\n",
124 124 " self.mean = mean\n",
125 125 " self.std = std\n",
126 126 " self.size = size\n",
127 127 " # For caching plots that may be expensive to compute\n",
128 128 " self._png_data = None\n",
129 129 " \n",
130 130 " def _figure_data(self, format):\n",
131 131 " fig, ax = plt.subplots()\n",
132 132 " ax.hist(self.data, bins=50)\n",
133 133 " ax.set_title(self._repr_latex_())\n",
134 134 " ax.set_xlim(-10.0,10.0)\n",
135 135 " data = print_figure(fig, format)\n",
136 136 " # We MUST close the figure, otherwise IPython's display machinery\n",
137 137 " # will pick it up and send it as output, resulting in a double display\n",
138 138 " plt.close(fig)\n",
139 139 " return data\n",
140 140 " \n",
141 141 " def _repr_png_(self):\n",
142 142 " if self._png_data is None:\n",
143 143 " self._png_data = self._figure_data('png')\n",
144 144 " return self._png_data\n",
145 145 " \n",
146 146 " def _repr_latex_(self):\n",
147 147 " return r'$\\mathcal{N}(\\mu=%.2g, \\sigma=%.2g),\\ N=%d$' % (self.mean,\n",
148 148 " self.std, self.size)"
149 149 ]
150 150 },
151 151 {
152 152 "cell_type": "markdown",
153 153 "metadata": {},
154 154 "source": [
155 155 "Create an instance of the Gaussian distribution and return it to display the default representation:"
156 156 ]
157 157 },
158 158 {
159 159 "cell_type": "code",
160 160 "execution_count": 4,
161 161 "metadata": {},
162 162 "outputs": [
163 163 {
164 164 "data": {
165 165 "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXsAAAEKCAYAAADzQPVvAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAFOZJREFUeJzt3X+0ZWV93/H3xxnAVIlAGJCIOpiFFgxhMLMIDUlKxBB+\nuAQbtRiXmRaSadrQ6lrtSsayklJjW0ybaNommolQJ1k0QBWEBRidotaVtRLMID+EAPIjoyKEGRUQ\niDEi3/6x99Xj5dx7z73nnPtjnvdrrbPu2fvZe5/vPGfP5+zz7H33TVUhSdq3PWelC5AkTZ9hL0kN\nMOwlqQGGvSQ1wLCXpAYY9pLUAMNekhpg2EtSAwx7keTMJI8kuTjJf0ny9pWuabVJ8pkkr1zpOqSl\nMuwbkuTHkuw3a95zgFOAXwK+CvwC8AdTruOAJJck+UKSJ5LckuSMab7mCDVdkGRXkm8m+eCQRf4b\n8M4lbvvgJJXkz2fN/4Mk71nKNge2MW/dSQ5JcnWSp/r+/vlR2kZp19pi2LflPODsWfNOBq6qqmv7\n6Ruq6htTrmM98CXgHwMvAH4duDLJxim/7nweAt4FXDpH+7XATyc5Ygnb3gT8DXDsrPU3AbcuYXuD\nFqr794C/Bw4H3gK8b+Abynxto7RrDTHs23ICsHXWvJOAm/rnZwD/b7AxyYVJ3jcwfXCSbyV57lKL\nqKqnquqiqtpdVc9U1XXAXwM/utC6SfZL8p+S7O7rqP5x21Lr6Wu6qqo+QvftZlj73wE3A6ctYfOb\ngF3ATuB1AEnWAccBtyyp4O/WNWfdSZ4H/Bzw61X1ZFX9Gd2H1lvna1to3XHq1cox7BuRZD2wFzg1\nycsHmtbXd++Gdxxwz6xVj+N7jz43Aff04Te4/euSPDbH47oFajsceDlw5wj/lHcBpwI/CRwE3Ahc\nDbx+UvXM4y7g+CWsdwJdH34EOKef9w+Bdf02p1X3y4FvV9XnB+bdBrxygbaF1tUatH6lC9Cy2QT8\nL2B/4G3AryQ5lu8Nm4OAJ2atdxwwOK68ie4//feoqtcupaj+HMJlwI6qunuBZQ8E/g3wI1X1pX7e\nh4F/WlUPTKKeBTwBLHUY5xrgE8D7+3/HJuCOqvrW4IITrvv5wOOz5j0OHLhA20Lrag3yyL4dp9Ad\nBf82cF6Sl9ANSewcWOZRBv4zJ9kf+CHgcwPLHM/448wz238O8Md048IXjLDKTwEPVNW9A/MOphsP\nXw4HAo8tZoUkBwDHALdW1aPAZ+iGy2aO9qfpSeD7Z837froPrfnaFlpXa5Bh347DqurRqvpTujH6\n3wWeX1VPDSxzO93X9xnHAl+uqr8FSBK6D41nHdkn+WiSJ+d4fHTI8gEuoTv593Ozj3DnsIHuA2lw\nG68HnjW8sdh6RnQMQ/7tC/hh4BvAzDePmaGcExgyXj/huj8PrE9y9MC84+mGy+ZrW2hdrUEO4+zD\nkvwE3TDM14FPDzT9C7rQ+visVW6gu0Lmsn76OOCwJD9Ed9XHhcBLgd2zX6uqFnvp5PvowvM1w67+\nmbmMsKr+2cDsO4BXJdlEd27hPwAFXDFuPf05jfV04+jr+hPQT1fV0337AXQnkLfMU98wJwC3DZwX\nuYbuEs5n+vqnVndVPZXkKuCdSX6RbujobODH52vr65i3XWtQVfnYRx90V1N8A3jvkLZfBV48a96h\nwIPA9/XTvwV8iO4o78vAvwbupxtfH6eul9KF9N/RDRfMPN4ysMyNwC8NWfdCug+eh4EPAodOqK8u\n6msafFw00P5GuktU561vyHb/J/A/Zs27lS7sD1yGug+h+zbxFPBF4OdHaRul3cfaeqR/U7WPSpJa\nxJuc5D8De6rqvf2wwQeq6sPTq3BoDfvTffP4kRpteGfqktwEnF9Vd6zG+qSFGPaaU5IHgdOq6q9W\nuhZJ4zHsNVSSg4FHgOd59CqtfYa9JDXASy8lqQHLeunloYceWhs3blzOl5SkNe/mm2/+SlVtGGcb\nyxr2GzduZNeuXcv5kpK05iX5wrjbcBhHkhpg2EtSAwx7SWqAYS9JDTDsJakBhr0kNcCwl6QGGPaS\n1ADDXpIaYNhLy2TjtuvZuO36sZeRlsKwl6QGGPaS1ADDXpIaYNhLUgMMe0lqgGEvSQ0w7CWpASP9\npaoku4EngG8DT1fV5iSHAFcAG4HdwJuq6tHplClJGsdijux/uqo2VdXmfnobcGNVHQ3c2E9Lklah\ncYZxzgZ29M93AOeMX44kaRpGDfsCPp7k5iRb+3mHV9XDAP3Pw4atmGRrkl1Jdu3du3f8iiVJizbS\nmD1wclU9lOQwYGeSu0d9garaDmwH2Lx5cy2hRknSmEY6sq+qh/qfe4CrgROBR5IcAdD/3DOtIiVJ\n41kw7JM8L8mBM8+B04A7gGuBLf1iW4BrplWkJGk8owzjHA5cnWRm+f9dVX+a5C+BK5OcD3wReOP0\nypT2HYO3MN598VkrWIlasmDYV9UDwPFD5n8VOHUaRUmSJsvfoJWkBhj2ktQAw15aQZP4M4T+KUON\nwrCXpAYY9pLUAMNekhpg2EtSAwx7SWqAYS9JDTDsJakBo97iWNISeQ28VgOP7CWpAYa9JDXAsJek\nBhj2ktQAw16SGmDYS1IDDHtJaoBhL0kNMOwlqQGGvSQ1wLCXpAYY9pLUAMNekhpg2EtSAwx7SWqA\n97OXVqGZe+Dvvvis75kenCcthkf2ktQAw16SGmDYS1IDRg77JOuS3JLkun76qCQ3Jbk3yRVJ9p9e\nmZKkcSzmyP5twF0D0+8G3lNVRwOPAudPsjBJ0uSMFPZJjgTOAj7QTwd4NfChfpEdwDnTKFCSNL5R\nj+zfC/wq8Ew//QPAY1X1dD/9IPCiCdcmSZqQBa+zT/JaYE9V3ZzklJnZQxatOdbfCmwFeMlLXrLE\nMqW1Y/Y18otZZ1rbl0Y5sj8ZeF2S3cDldMM37wUOSjLzYXEk8NCwlatqe1VtrqrNGzZsmEDJkqTF\nWjDsq+odVXVkVW0EzgU+UVVvAT4JvKFfbAtwzdSqlCSNZZzbJfwacHmSdwG3AJdMpiRJMxYzvCPN\nZ1FhX1WfAj7VP38AOHHyJUmSJs3foJWkBhj2ktQAb3EsTYnj7VpNPLKXpAYY9pLUAMNekhrgmL20\nRnlOQIvhkb0kNcCwl6QGGPaS1ADDXpIaYNhLUgMMe0lqgGEvSQ0w7KV9xMZt13vtveZk2EtSAwx7\nSWqAYS9JDTDspSVwfFxrjWEvSQ0w7CWpAYa9JDXAsJekBhj2ktQAw16SGmDYS1IDDHtJaoBhL0kN\nMOwlqQGGvSQ1YMGwT/LcJJ9JcluSO5P8x37+UUluSnJvkiuS7D/9ciVJSzHKkf03gVdX1fHAJuD0\nJCcB7wbeU1VHA48C50+vTEnSOBYM++o82U/u1z8KeDXwoX7+DuCcqVQoSRrbSGP2SdYluRXYA+wE\n7gceq6qn+0UeBF40nRIlSeMaKeyr6ttVtQk4EjgROGbYYsPWTbI1ya4ku/bu3bv0SiVJS7aoq3Gq\n6jHgU8BJwEFJ1vdNRwIPzbHO9qraXFWbN2zYME6tkqQlGuVqnA1JDuqffx/wGuAu4JPAG/rFtgDX\nTKtISdJ41i+8CEcAO5Kso/twuLKqrkvyV8DlSd4F3AJcMsU6pVXPP1Oo1WzBsK+q24EThsx/gG78\nXpK0yvkbtJLUAMNekhpg2EtSAwx7SWqAYS9JDTDsJakBhr0kNcCwl6QGGPaS1ADDXpIaYNhLUgMM\ne0lqgGEvSQ0w7CWpAYa9NIKN265fM/erX0u1avkY9pLUAMNekhpg2EtSA0b5G7SSeo6Fa63yyF6S\nGmDYS1IDDHtJaoBhLzXEa/DbZdhLUgMMe0lqgGEvSQ0w7CWpAYa9JDXAsJekBhj2ktSABe+Nk+TF\nwB8BLwSeAbZX1e8mOQS4AtgI7AbeVFWPTq9UafVZK9esr5U6NT2jHNk/DfzbqjoGOAn4lSTHAtuA\nG6vqaODGflqStAotGPZV9XBVfbZ//gRwF/Ai4GxgR7/YDuCcaRUpSRrPosbsk2wETgBuAg6vqoeh\n+0AADpt0cZKkyRg57JM8H/gw8Paq+voi1tuaZFeSXXv37l1KjZKkMY0U9kn2owv6y6rqqn72I0mO\n6NuPAPYMW7eqtlfV5qravGHDhknULElapAXDPkmAS4C7qup3BpquBbb0z7cA10y+PEnSJIzyZwlP\nBt4KfC7Jrf28fw9cDFyZ5Hzgi8Abp1OiJGlcC4Z9Vf0ZkDmaT51sOZKWw8x197svPmuFK9Fy8Tdo\nJakBhr0kNcCwl6QGGPaS1ADDXpIaYNhLUgMMe0lqgGEvSQ0w7CWpAYa9JDXAsJekBhj2ktQAw16S\nGmDYS1IDRrmfvaQ1aOY2xhJ4ZC9JTTDsJakBhr0kNcCwl6QGGPaS1ADDXpIaYNhLUgMMe0lqgGEv\nSQ0w7CWpAYa9JDXAe+NIvcF7yey++KxnzZPWMo/sJakBhr0kNcCwl6QGGPaS1IAFwz7JpUn2JLlj\nYN4hSXYmubf/efB0y5QkjWOUI/sPAqfPmrcNuLGqjgZu7KclSavUgmFfVZ8GvjZr9tnAjv75DuCc\nCdclSZqgpY7ZH15VDwP0Pw+ba8EkW5PsSrJr7969S3w5SdOwcdv1c/4uwXxtWnumfoK2qrZX1eaq\n2rxhw4Zpv5wkaYilhv0jSY4A6H/umVxJkqRJW2rYXwts6Z9vAa6ZTDmSpGkY5dLLPwH+HHhFkgeT\nnA9cDPxMknuBn+mnJUmr1II3QquqN8/RdOqEa5EkTYm/QStJDTDsJakB3s9eGqK168tn/r0z9/HX\nvscje0lqgGEvSQ0w7CXNy9sm7BsMe0lqgGEvSQ0w7CWpAV56qWZ5ueGzLWZs3v5bWzyyl6QGGPaS\n1ADDXpIa4Ji99kmDY88zY8peK66WeWQvSQ0w7CWpAYa9JDXAsJekBhj2ktQAw16SGmDYS1IDvM5e\nzfP6e7XAI3tJaoBhL0kNMOwlqQGO2Wuf55j8ZM3Xn97jfvXyyF6SGmDYS1IDDHtJaoBj9lqTZo8N\nOy4/fUvpY8fwV4+xjuyTnJ7kniT3Jdk2qaIkSZO15LBPsg74PeAM4FjgzUmOnVRhkqTJGefI/kTg\nvqp6oKr+HrgcOHsyZUmSJilVtbQVkzcAp1fVL/bTbwV+rKoumLXcVmBrP/nDwB1LL3fZHAp8ZaWL\nGMFaqHMt1AjWOWnWOVmvqKoDx9nAOCdoM2Tesz45qmo7sB0gya6q2jzGay4L65yctVAjWOekWedk\nJdk17jbGGcZ5EHjxwPSRwEPjlSNJmoZxwv4vgaOTHJVkf+Bc4NrJlCVJmqQlD+NU1dNJLgA+BqwD\nLq2qOxdYbftSX2+ZWefkrIUawTonzTona+w6l3yCVpK0dni7BElqgGEvSQ2YeNgneWOSO5M8k2Tz\nrLZ39LdWuCfJz86x/lFJbkpyb5Ir+pO/U9W/zq39Y3eSW+dYbneSz/XLjX0p1BLqvCjJlwdqPXOO\n5VbsNhZJ/muSu5PcnuTqJAfNsdyK9OVCfZPkgH5/uK/fDzcuV20DNbw4ySeT3NX/X3rbkGVOSfL4\nwL7wG8tdZ1/HvO9jOv+978/bk7xqBWp8xUA/3Zrk60nePmuZFenPJJcm2ZPkjoF5hyTZ2WfgziQH\nz7Huln6Ze5NsWfDFqmqiD+AY4BXAp4DNA/OPBW4DDgCOAu4H1g1Z/0rg3P75+4F/OekaF6j/t4Hf\nmKNtN3DoctYz6/UvAv7dAsus6/v2ZcD+fZ8fu4w1ngas75+/G3j3aunLUfoG+FfA+/vn5wJXrMD7\nfATwqv75gcDnh9R5CnDdcte22PcROBP4KN3v5ZwE3LTC9a4D/gZ46WroT+CngFcBdwzM+y1gW/98\n27D/Q8AhwAP9z4P75wfP91oTP7Kvqruq6p4hTWcDl1fVN6vqr4H76G658B1JArwa+FA/awdwzqRr\nnEv/+m8C/mS5XnMKVvQ2FlX18ap6up/8C7rfv1gtRumbs+n2O+j2w1P7/WLZVNXDVfXZ/vkTwF3A\ni5azhgk6G/ij6vwFcFCSI1awnlOB+6vqCytYw3dU1aeBr82aPbgPzpWBPwvsrKqvVdWjwE7g9Ple\naznH7F8EfGlg+kGevQP/APDYQFgMW2aafhJ4pKrunaO9gI8nubm/DcRKuKD/OnzpHF/vRunn5XIe\n3VHdMCvRl6P0zXeW6ffDx+n2yxXRDyOdANw0pPkfJbktyUeTvHJZC/uuhd7H1bQ/Qvdtba6DudXQ\nnwCHV9XD0H3wA4cNWWbR/bqk6+yT/F/ghUOaLqyqa+Zabci82dd9jnQLhqUYseY3M/9R/clV9VCS\nw4CdSe7uP5knZr46gfcBv0nXJ79JN+R03uxNDFl3otfXjtKXSS4EngYum2MzU+/LIVZ0H1ysJM8H\nPgy8vaq+Pqv5s3RDEU/2524+Ahy93DWy8Pu4mvpzf+B1wDuGNK+W/hzVovt1SWFfVa9Zwmqj3F7h\nK3Rf89b3R1UTuwXDQjUnWQ/8E+BH59nGQ/3PPUmuphsWmGhAjdq3Sf4QuG5I09RvYzFCX24BXguc\nWv0A45BtTL0vhxilb2aWebDfJ17As79mT12S/eiC/rKqump2+2D4V9UNSX4/yaFVtaw39RrhfVxN\nt1U5A/hsVT0yu2G19GfvkSRHVNXD/ZDXniHLPEh3nmHGkXTnSee0nMM41wLn9lc7HEX3qfmZwQX6\nYPgk8IZ+1hZgrm8Kk/Ya4O6qenBYY5LnJTlw5jndichlvYPnrLHO18/x+it6G4skpwO/Bryuqv52\njmVWqi9H6Ztr6fY76PbDT8z1gTUt/TmCS4C7qup35ljmhTPnEpKcSPd/+avLV+XI7+O1wC/0V+Wc\nBDw+M0SxAub85r4a+nPA4D44VwZ+DDgtycH9cO5p/by5TeHs8uvpPnW+CTwCfGyg7UK6qyHuAc4Y\nmH8D8IP985fRfQjcB/wf4IBJ1zhH3R8EfnnWvB8Ebhio67b+cSfdkMVyn7n/Y+BzwO39DnHE7Dr7\n6TPpruC4f7nr7N+3LwG39o/3z65xJftyWN8A76T7cAJ4br/f3dfvhy9bgff5J+i+kt8+0I9nAr88\ns48CF/R9dxvdifAfX4E6h76Ps+oM3R85ur/fdzcvd519Hf+ALrxfMDBvxfuT7sPnYeBbfW6eT3eO\n6Ebg3v7nIf2ym4EPDKx7Xr+f3gf884Vey9slSFID/A1aSWqAYS9JDTDsJakBhr0kNcCwl6QGGPaS\n1ADDXpIa8P8BEb7Ae9JKdQAAAAAASUVORK5CYII=\n",
166 166 "text/latex": [
167 167 "$\\mathcal{N}(\\mu=2, \\sigma=1),\\ N=1000$"
168 168 ],
169 169 "text/plain": [
170 170 "<__main__.Gaussian at 0x116fe76d8>"
171 171 ]
172 172 },
173 173 "execution_count": 4,
174 174 "metadata": {},
175 175 "output_type": "execute_result"
176 176 }
177 177 ],
178 178 "source": [
179 179 "x = Gaussian(2.0, 1.0)\n",
180 180 "x"
181 181 ]
182 182 },
183 183 {
184 184 "cell_type": "markdown",
185 185 "metadata": {},
186 186 "source": [
187 187 "You can also pass the object to the `display` function to display the default representation:"
188 188 ]
189 189 },
190 190 {
191 191 "cell_type": "code",
192 192 "execution_count": 5,
193 193 "metadata": {},
194 194 "outputs": [
195 195 {
196 196 "data": {
197 197 "image/png": "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\n1ADDXpIa8P8BEb7Ae9JKdQAAAAAASUVORK5CYII=\n",
198 198 "text/latex": [
199 199 "$\\mathcal{N}(\\mu=2, \\sigma=1),\\ N=1000$"
200 200 ],
201 201 "text/plain": [
202 202 "<__main__.Gaussian at 0x116fe76d8>"
203 203 ]
204 204 },
205 205 "metadata": {},
206 206 "output_type": "display_data"
207 207 }
208 208 ],
209 209 "source": [
210 210 "display(x)"
211 211 ]
212 212 },
213 213 {
214 214 "cell_type": "markdown",
215 215 "metadata": {},
216 216 "source": [
217 217 "Use `display_png` to view the PNG representation:"
218 218 ]
219 219 },
220 220 {
221 221 "cell_type": "code",
222 222 "execution_count": 6,
223 223 "metadata": {},
224 224 "outputs": [
225 225 {
226 226 "data": {
227 227 "image/png": "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\n1ADDXpIa8P8BEb7Ae9JKdQAAAAAASUVORK5CYII=\n"
228 228 },
229 229 "metadata": {},
230 230 "output_type": "display_data"
231 231 }
232 232 ],
233 233 "source": [
234 234 "display_png(x)"
235 235 ]
236 236 },
237 237 {
238 238 "cell_type": "markdown",
239 239 "metadata": {},
240 240 "source": [
241 241 "<div class=\"alert alert-success\">\n",
242 242 "It is important to note a subtle different between <code>display</code> and <code>display_png</code>. The former computes <em>all</em> representations of the object, and lets the notebook UI decide which to display. The later only computes the PNG representation.\n",
243 243 "</div>"
244 244 ]
245 245 },
246 246 {
247 247 "cell_type": "markdown",
248 248 "metadata": {},
249 249 "source": [
250 250 "Create a new Gaussian with different parameters:"
251 251 ]
252 252 },
253 253 {
254 254 "cell_type": "code",
255 255 "execution_count": 7,
256 256 "metadata": {},
257 257 "outputs": [
258 258 {
259 259 "data": {
260 260 "image/png": "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\nLnYAAAAASUVORK5CYII=\n",
261 261 "text/latex": [
262 262 "$\\mathcal{N}(\\mu=0, \\sigma=2),\\ N=2000$"
263 263 ],
264 264 "text/plain": [
265 265 "<__main__.Gaussian at 0x116fe7668>"
266 266 ]
267 267 },
268 268 "execution_count": 7,
269 269 "metadata": {},
270 270 "output_type": "execute_result"
271 271 }
272 272 ],
273 273 "source": [
274 274 "x2 = Gaussian(0, 2, 2000)\n",
275 275 "x2"
276 276 ]
277 277 },
278 278 {
279 279 "cell_type": "markdown",
280 280 "metadata": {},
281 281 "source": [
282 282 "You can then compare the two Gaussians by displaying their histograms:"
283 283 ]
284 284 },
285 285 {
286 286 "cell_type": "code",
287 287 "execution_count": 8,
288 288 "metadata": {},
289 289 "outputs": [
290 290 {
291 291 "data": {
292 292 "image/png": "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\n1ADDXpIa8P8BEb7Ae9JKdQAAAAAASUVORK5CYII=\n"
293 293 },
294 294 "metadata": {},
295 295 "output_type": "display_data"
296 296 },
297 297 {
298 298 "data": {
299 299 "image/png": "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\nLnYAAAAASUVORK5CYII=\n"
300 300 },
301 301 "metadata": {},
302 302 "output_type": "display_data"
303 303 }
304 304 ],
305 305 "source": [
306 306 "display_png(x)\n",
307 307 "display_png(x2)"
308 308 ]
309 309 },
310 310 {
311 311 "cell_type": "markdown",
312 312 "metadata": {},
313 313 "source": [
314 314 "Note that like `print`, you can call any of the `display` functions multiple times in a cell."
315 315 ]
316 316 },
317 317 {
318 318 "cell_type": "markdown",
319 319 "metadata": {},
320 320 "source": [
321 321 "## Adding IPython display support to existing objects"
322 322 ]
323 323 },
324 324 {
325 325 "cell_type": "markdown",
326 326 "metadata": {},
327 327 "source": [
328 328 "When you are directly writing your own classes, you can adapt them for display in IPython by following the above approach. But in practice, you often need to work with existing classes that you can't easily modify. We now illustrate how to add rich output capabilities to existing objects. We will use the NumPy polynomials and change their default representation to be a formatted LaTeX expression."
329 329 ]
330 330 },
331 331 {
332 332 "cell_type": "markdown",
333 333 "metadata": {},
334 334 "source": [
335 335 "First, consider how a NumPy polynomial object renders by default:"
336 336 ]
337 337 },
338 338 {
339 339 "cell_type": "code",
340 340 "execution_count": 9,
341 341 "metadata": {},
342 342 "outputs": [
343 343 {
344 344 "data": {
345 345 "text/plain": [
346 346 "Polynomial([ 1., 2., 3.], [-10., 10.], [-1, 1])"
347 347 ]
348 348 },
349 349 "execution_count": 9,
350 350 "metadata": {},
351 351 "output_type": "execute_result"
352 352 }
353 353 ],
354 354 "source": [
355 355 "p = np.polynomial.Polynomial([1,2,3], [-10, 10])\n",
356 356 "p"
357 357 ]
358 358 },
359 359 {
360 360 "cell_type": "markdown",
361 361 "metadata": {},
362 362 "source": [
363 363 "Next, define a function that pretty-prints a polynomial as a LaTeX string:"
364 364 ]
365 365 },
366 366 {
367 367 "cell_type": "code",
368 368 "execution_count": 10,
369 369 "metadata": {
370 370 "collapsed": true
371 371 },
372 372 "outputs": [],
373 373 "source": [
374 374 "def poly_to_latex(p):\n",
375 375 " terms = ['%.2g' % p.coef[0]]\n",
376 376 " if len(p) > 1:\n",
377 377 " term = 'x'\n",
378 378 " c = p.coef[1]\n",
379 379 " if c!=1:\n",
380 380 " term = ('%.2g ' % c) + term\n",
381 381 " terms.append(term)\n",
382 382 " if len(p) > 2:\n",
383 383 " for i in range(2, len(p)):\n",
384 384 " term = 'x^%d' % i\n",
385 385 " c = p.coef[i]\n",
386 386 " if c!=1:\n",
387 387 " term = ('%.2g ' % c) + term\n",
388 388 " terms.append(term)\n",
389 389 " px = '$P(x)=%s$' % '+'.join(terms)\n",
390 390 " dom = r', $x \\in [%.2g,\\ %.2g]$' % tuple(p.domain)\n",
391 391 " return px+dom"
392 392 ]
393 393 },
394 394 {
395 395 "cell_type": "markdown",
396 396 "metadata": {},
397 397 "source": [
398 398 "This produces, on our polynomial ``p``, the following:"
399 399 ]
400 400 },
401 401 {
402 402 "cell_type": "code",
403 403 "execution_count": 11,
404 404 "metadata": {},
405 405 "outputs": [
406 406 {
407 407 "data": {
408 408 "text/plain": [
409 409 "'$P(x)=1+2 x+3 x^2$, $x \\\\in [-10,\\\\ 10]$'"
410 410 ]
411 411 },
412 412 "execution_count": 11,
413 413 "metadata": {},
414 414 "output_type": "execute_result"
415 415 }
416 416 ],
417 417 "source": [
418 418 "poly_to_latex(p)"
419 419 ]
420 420 },
421 421 {
422 422 "cell_type": "markdown",
423 423 "metadata": {},
424 424 "source": [
425 425 "You can render this string using the `Latex` class:"
426 426 ]
427 427 },
428 428 {
429 429 "cell_type": "code",
430 430 "execution_count": 12,
431 431 "metadata": {},
432 432 "outputs": [
433 433 {
434 434 "data": {
435 435 "text/latex": [
436 436 "$P(x)=1+2 x+3 x^2$, $x \\in [-10,\\ 10]$"
437 437 ],
438 438 "text/plain": [
439 439 "<IPython.core.display.Latex object>"
440 440 ]
441 441 },
442 442 "execution_count": 12,
443 443 "metadata": {},
444 444 "output_type": "execute_result"
445 445 }
446 446 ],
447 447 "source": [
448 448 "from IPython.display import Latex\n",
449 449 "Latex(poly_to_latex(p))"
450 450 ]
451 451 },
452 452 {
453 453 "cell_type": "markdown",
454 454 "metadata": {},
455 455 "source": [
456 456 "However, you can configure IPython to do this automatically by registering the `Polynomial` class and the `poly_to_latex` function with an IPython display formatter. Let's look at the default formatters provided by IPython:"
457 457 ]
458 458 },
459 459 {
460 460 "cell_type": "code",
461 461 "execution_count": 13,
462 462 "metadata": {},
463 463 "outputs": [
464 464 {
465 465 "name": "stdout",
466 466 "output_type": "stream",
467 467 "text": [
468 468 " text/plain : PlainTextFormatter\n",
469 469 " text/html : HTMLFormatter\n",
470 470 " text/markdown : MarkdownFormatter\n",
471 471 " image/svg+xml : SVGFormatter\n",
472 472 " image/png : PNGFormatter\n",
473 473 " application/pdf : PDFFormatter\n",
474 474 " image/jpeg : JPEGFormatter\n",
475 475 " text/latex : LatexFormatter\n",
476 476 " application/json : JSONFormatter\n",
477 477 " application/javascript : JavascriptFormatter\n"
478 478 ]
479 479 }
480 480 ],
481 481 "source": [
482 482 "ip = get_ipython()\n",
483 483 "for mime, formatter in ip.display_formatter.formatters.items():\n",
484 484 " print('%24s : %s' % (mime, formatter.__class__.__name__))"
485 485 ]
486 486 },
487 487 {
488 488 "cell_type": "markdown",
489 489 "metadata": {},
490 490 "source": [
491 491 "The `formatters` attribute is a dictionary keyed by MIME types. To define a custom LaTeX display function, you want a handle on the `text/latex` formatter:"
492 492 ]
493 493 },
494 494 {
495 495 "cell_type": "code",
496 496 "execution_count": 14,
497 497 "metadata": {
498 498 "collapsed": true
499 499 },
500 500 "outputs": [],
501 501 "source": [
502 502 "ip = get_ipython()\n",
503 503 "latex_f = ip.display_formatter.formatters['text/latex']"
504 504 ]
505 505 },
506 506 {
507 507 "cell_type": "markdown",
508 508 "metadata": {},
509 509 "source": [
510 510 "The formatter object has a couple of methods for registering custom display functions for existing types."
511 511 ]
512 512 },
513 513 {
514 514 "cell_type": "code",
515 515 "execution_count": 15,
516 516 "metadata": {},
517 517 "outputs": [
518 518 {
519 519 "name": "stdout",
520 520 "output_type": "stream",
521 521 "text": [
522 522 "Help on method for_type in module IPython.core.formatters:\n",
523 523 "\n",
524 524 "for_type(typ, func=None) method of IPython.core.formatters.LatexFormatter instance\n",
525 525 " Add a format function for a given type.\n",
526 526 " \n",
527 527 " Parameters\n",
528 528 " -----------\n",
529 529 " typ : type or '__module__.__name__' string for a type\n",
530 530 " The class of the object that will be formatted using `func`.\n",
531 531 " func : callable\n",
532 532 " A callable for computing the format data.\n",
533 533 " `func` will be called with the object to be formatted,\n",
534 534 " and will return the raw data in this formatter's format.\n",
535 535 " Subclasses may use a different call signature for the\n",
536 536 " `func` argument.\n",
537 537 " \n",
538 538 " If `func` is None or not specified, there will be no change,\n",
539 539 " only returning the current value.\n",
540 540 " \n",
541 541 " Returns\n",
542 542 " -------\n",
543 543 " oldfunc : callable\n",
544 544 " The currently registered callable.\n",
545 545 " If you are registering a new formatter,\n",
546 546 " this will be the previous value (to enable restoring later).\n",
547 547 "\n"
548 548 ]
549 549 }
550 550 ],
551 551 "source": [
552 552 "help(latex_f.for_type)"
553 553 ]
554 554 },
555 555 {
556 556 "cell_type": "code",
557 557 "execution_count": 16,
558 558 "metadata": {},
559 559 "outputs": [
560 560 {
561 561 "name": "stdout",
562 562 "output_type": "stream",
563 563 "text": [
564 564 "Help on method for_type_by_name in module IPython.core.formatters:\n",
565 565 "\n",
566 566 "for_type_by_name(type_module, type_name, func=None) method of IPython.core.formatters.LatexFormatter instance\n",
567 567 " Add a format function for a type specified by the full dotted\n",
568 568 " module and name of the type, rather than the type of the object.\n",
569 569 " \n",
570 570 " Parameters\n",
571 571 " ----------\n",
572 572 " type_module : str\n",
573 573 " The full dotted name of the module the type is defined in, like\n",
574 574 " ``numpy``.\n",
575 575 " type_name : str\n",
576 576 " The name of the type (the class name), like ``dtype``\n",
577 577 " func : callable\n",
578 578 " A callable for computing the format data.\n",
579 579 " `func` will be called with the object to be formatted,\n",
580 580 " and will return the raw data in this formatter's format.\n",
581 581 " Subclasses may use a different call signature for the\n",
582 582 " `func` argument.\n",
583 583 " \n",
584 584 " If `func` is None or unspecified, there will be no change,\n",
585 585 " only returning the current value.\n",
586 586 " \n",
587 587 " Returns\n",
588 588 " -------\n",
589 589 " oldfunc : callable\n",
590 590 " The currently registered callable.\n",
591 591 " If you are registering a new formatter,\n",
592 592 " this will be the previous value (to enable restoring later).\n",
593 593 "\n"
594 594 ]
595 595 }
596 596 ],
597 597 "source": [
598 598 "help(latex_f.for_type_by_name)"
599 599 ]
600 600 },
601 601 {
602 602 "cell_type": "markdown",
603 603 "metadata": {},
604 604 "source": [
605 605 "In this case, we will use `for_type_by_name` to register `poly_to_latex` as the display function for the `Polynomial` type:"
606 606 ]
607 607 },
608 608 {
609 609 "cell_type": "code",
610 610 "execution_count": 17,
611 611 "metadata": {
612 612 "collapsed": true
613 613 },
614 614 "outputs": [],
615 615 "source": [
616 616 "latex_f.for_type_by_name('numpy.polynomial.polynomial',\n",
617 617 " 'Polynomial', poly_to_latex)"
618 618 ]
619 619 },
620 620 {
621 621 "cell_type": "markdown",
622 622 "metadata": {},
623 623 "source": [
624 624 "Once the custom display function has been registered, all NumPy `Polynomial` instances will be represented by their LaTeX form instead:"
625 625 ]
626 626 },
627 627 {
628 628 "cell_type": "code",
629 629 "execution_count": 18,
630 630 "metadata": {},
631 631 "outputs": [
632 632 {
633 633 "data": {
634 634 "text/latex": [
635 635 "$P(x)=1+2 x+3 x^2$, $x \\in [-10,\\ 10]$"
636 636 ],
637 637 "text/plain": [
638 638 "Polynomial([ 1., 2., 3.], [-10., 10.], [-1, 1])"
639 639 ]
640 640 },
641 641 "execution_count": 18,
642 642 "metadata": {},
643 643 "output_type": "execute_result"
644 644 }
645 645 ],
646 646 "source": [
647 647 "p"
648 648 ]
649 649 },
650 650 {
651 651 "cell_type": "code",
652 652 "execution_count": 19,
653 653 "metadata": {},
654 654 "outputs": [
655 655 {
656 656 "data": {
657 657 "text/latex": [
658 658 "$P(x)=-20+71 x+-15 x^2+x^3$, $x \\in [-1,\\ 1]$"
659 659 ],
660 660 "text/plain": [
661 661 "Polynomial([-20., 71., -15., 1.], [-1, 1], [-1, 1])"
662 662 ]
663 663 },
664 664 "execution_count": 19,
665 665 "metadata": {},
666 666 "output_type": "execute_result"
667 667 }
668 668 ],
669 669 "source": [
670 670 "p2 = np.polynomial.Polynomial([-20, 71, -15, 1])\n",
671 671 "p2"
672 672 ]
673 673 },
674 674 {
675 675 "cell_type": "markdown",
676 676 "metadata": {},
677 677 "source": [
678 678 "## Custom Mimetypes with `_repr_mimebundle_`\n",
679 679 "\n",
680 680 "Available on IPython 5.4+ and 6.1+.\n",
681 681 "\n",
682 682 "For objects needing full control over the `repr` protocol may decide to implement the `_repr_mimebundle_(include, exclude)` method.\n",
683 683 "Unlike the other `_repr_*_` methods must return many representation of the object in a mapping object which keys are _mimetypes_ and value are associated data. The `_repr_mimebundle_()` method, may also return a second mapping from _mimetypes_ to metadata. \n",
684 684 "\n",
685 685 "Example:"
686 686 ]
687 687 },
688 688 {
689 689 "cell_type": "code",
690 690 "execution_count": 20,
691 691 "metadata": {
692 692 "collapsed": true
693 693 },
694 694 "outputs": [],
695 695 "source": [
696 696 "class Gaussian(object):\n",
697 697 " \"\"\"A simple object holding data sampled from a Gaussian distribution.\n",
698 698 " \"\"\"\n",
699 699 " def __init__(self, mean=0.0, std=1, size=1000):\n",
700 700 " self.data = np.random.normal(mean, std, size)\n",
701 701 " self.mean = mean\n",
702 702 " self.std = std\n",
703 703 " self.size = size\n",
704 704 " # For caching plots that may be expensive to compute\n",
705 705 " self._png_data = None\n",
706 706 " \n",
707 707 " def _figure_data(self, format):\n",
708 708 " fig, ax = plt.subplots()\n",
709 709 " ax.hist(self.data, bins=50)\n",
710 710 " ax.set_xlim(-10.0,10.0)\n",
711 711 " data = print_figure(fig, format)\n",
712 712 " # We MUST close the figure, otherwise IPython's display machinery\n",
713 713 " # will pick it up and send it as output, resulting in a double display\n",
714 714 " plt.close(fig)\n",
715 715 " return data\n",
716 716 " \n",
717 717 " def _compute_mathml(self):\n",
718 718 " return \"\"\"\n",
719 719 " <math xmlns=\"http://www.w3.org/1998/Math/MathML\">\n",
720 720 " <mrow class=\"MJX-TeXAtom-ORD\">\n",
721 721 " <mi class=\"MJX-tex-caligraphic\" mathvariant=\"script\">N</mi>\n",
722 722 " </mrow>\n",
723 723 " <mo stretchy=\"false\">(</mo>\n",
724 724 " <mi>&#x03BC;<!-- μ --></mi>\n",
725 725 " <mo>=</mo>\n",
726 726 " <mn>{mu}</mn>\n",
727 727 " <mo>,</mo>\n",
728 728 " <mi>&#x03C3;<!-- σ --></mi>\n",
729 729 " <mo>=</mo>\n",
730 730 " <mn>{sigma}</mn>\n",
731 731 " <mo stretchy=\"false\">)</mo>\n",
732 732 " <mo>,</mo>\n",
733 733 " <mtext>&#xA0;</mtext>\n",
734 734 " <mi>N</mi>\n",
735 735 " <mo>=</mo>\n",
736 736 " <mn>{N}</mn>\n",
737 737 " </math>\n",
738 738 " \"\"\".format(N=self.size, mu=self.mean, sigma=self.std)\n",
739 739 " \n",
740 740 " def _repr_mimebundle_(self, include, exclude, **kwargs):\n",
741 741 " \"\"\"\n",
742 " repr_mimebundle shoudl accept include, exclude and **kwargs\n",
742 " repr_mimebundle should accept include, exclude and **kwargs\n",
743 743 " \"\"\"\n",
744 744 " if self._png_data is None:\n",
745 745 " self._png_data = self._figure_data('png')\n",
746 746 " math = r'$\\mathcal{N}(\\mu=%.2g, \\sigma=%.2g),\\ N=%d$' % (self.mean,\n",
747 747 " self.std, self.size)\n",
748 748 " data = {'image/png':self._png_data,\n",
749 749 " 'text/latex':math,\n",
750 750 " 'application/mathml+xml': self._compute_mathml()\n",
751 751 " }\n",
752 752 " if include:\n",
753 753 " data = {k:v for (k,v) in data.items() if k in include}\n",
754 754 " if exclude:\n",
755 755 " data = {k:v for (k,v) in data.items() if k not in exclude}\n",
756 756 " return data"
757 757 ]
758 758 },
759 759 {
760 760 "cell_type": "code",
761 761 "execution_count": 21,
762 762 "metadata": {},
763 763 "outputs": [
764 764 {
765 765 "data": {
766 766 "application/mathml+xml": "\n <math xmlns=\"http://www.w3.org/1998/Math/MathML\">\n <mrow class=\"MJX-TeXAtom-ORD\">\n <mi class=\"MJX-tex-caligraphic\" mathvariant=\"script\">N</mi>\n </mrow>\n <mo stretchy=\"false\">(</mo>\n <mi>&#x03BC;<!-- μ --></mi>\n <mo>=</mo>\n <mn>0.0</mn>\n <mo>,</mo>\n <mi>&#x03C3;<!-- σ --></mi>\n <mo>=</mo>\n <mn>1</mn>\n <mo stretchy=\"false\">)</mo>\n <mo>,</mo>\n <mtext>&#xA0;</mtext>\n <mi>N</mi>\n <mo>=</mo>\n <mn>1000</mn>\n </math>\n ",
767 767 "image/png": "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\nDfgfS9fLKUqMYTsAAAAASUVORK5CYII=\n",
768 768 "text/latex": [
769 769 "$\\mathcal{N}(\\mu=0, \\sigma=1),\\ N=1000$"
770 770 ],
771 771 "text/plain": [
772 772 "<__main__.Gaussian at 0x11a614e80>"
773 773 ]
774 774 },
775 775 "metadata": {},
776 776 "output_type": "display_data"
777 777 }
778 778 ],
779 779 "source": [
780 "# that is deffinitively wrong as it shoudl show the PNG. \n",
780 "# that is deffinitively wrong as it should show the PNG. \n",
781 781 "display(Gaussian())"
782 782 ]
783 783 },
784 784 {
785 785 "cell_type": "markdown",
786 786 "metadata": {},
787 787 "source": [
788 788 "In the above example, the 3 mimetypes are embedded in the notebook document this allowing custom extensions and converters to display the representation(s) of their choice.\n",
789 789 "\n",
790 790 "For example, converting this noetebook to _epub_ may decide to use the MathML representation as most ebook reader cannot run mathjax (unlike browsers). \n",
791 791 "\n",
792 792 "\n",
793 793 "### Implementation guidelines\n",
794 794 "\n",
795 795 "The `_repr_mimebundle_` methods is also given two keywords parameters : `include` and `exclude`. Each can be a containers (e.g.:`list`, `set` ...) of mimetypes to return or `None`, This allows implementation to avoid computing potentially unnecessary and expensive mimetypes representations. \n",
796 796 "\n",
797 797 "When `include` is non-empty (empty `list` or None), `_repr_mimebundle_` may decide to returns only the mimetypes in include.\n",
798 798 "When `exclude` is non-empty, `_repr_mimebundle_` may decide to not return any mimetype in exclude. \n",
799 799 "If both `include` and `exclude` and overlap, mimetypes present in exclude may not be returned. \n",
800 800 "\n",
801 801 "If implementations decide to ignore the `include` and `exclude` logic and always returns a full mimebundles, the IPython kernel will take care of removing non-desired representations.\n",
802 802 "\n",
803 803 "The `_repr_mimebundle_` method should accept arbitrary keyword arguments for future compatiility.\n"
804 804 ]
805 805 },
806 806 {
807 807 "cell_type": "code",
808 808 "execution_count": 22,
809 809 "metadata": {},
810 810 "outputs": [
811 811 {
812 812 "data": {
813 813 "text/latex": [
814 814 "$\\mathcal{N}(\\mu=0, \\sigma=1),\\ N=1000$"
815 815 ]
816 816 },
817 817 "metadata": {},
818 818 "output_type": "display_data"
819 819 }
820 820 ],
821 821 "source": [
822 822 "display(Gaussian(), include={'text/latex'}) # only show latex"
823 823 ]
824 824 },
825 825 {
826 826 "cell_type": "code",
827 827 "execution_count": 23,
828 828 "metadata": {},
829 829 "outputs": [
830 830 {
831 831 "data": {
832 832 "application/mathml+xml": "\n <math xmlns=\"http://www.w3.org/1998/Math/MathML\">\n <mrow class=\"MJX-TeXAtom-ORD\">\n <mi class=\"MJX-tex-caligraphic\" mathvariant=\"script\">N</mi>\n </mrow>\n <mo stretchy=\"false\">(</mo>\n <mi>&#x03BC;<!-- μ --></mi>\n <mo>=</mo>\n <mn>0.0</mn>\n <mo>,</mo>\n <mi>&#x03C3;<!-- σ --></mi>\n <mo>=</mo>\n <mn>1</mn>\n <mo stretchy=\"false\">)</mo>\n <mo>,</mo>\n <mtext>&#xA0;</mtext>\n <mi>N</mi>\n <mo>=</mo>\n <mn>1000</mn>\n </math>\n ",
833 833 "text/latex": [
834 834 "$\\mathcal{N}(\\mu=0, \\sigma=1),\\ N=1000$"
835 835 ],
836 836 "text/plain": [
837 837 "<__main__.Gaussian at 0x116fe7550>"
838 838 ]
839 839 },
840 840 "metadata": {},
841 841 "output_type": "display_data"
842 842 }
843 843 ],
844 844 "source": [
845 845 "display(Gaussian(), exclude={'image/png'}) # exclude png"
846 846 ]
847 847 },
848 848 {
849 849 "cell_type": "code",
850 850 "execution_count": 24,
851 851 "metadata": {},
852 852 "outputs": [
853 853 {
854 854 "data": {
855 855 "text/plain": [
856 856 "<__main__.Gaussian at 0x11a8a0b38>"
857 857 ]
858 858 },
859 859 "metadata": {},
860 860 "output_type": "display_data"
861 861 }
862 862 ],
863 863 "source": [
864 864 "display(Gaussian(), include={'text/plain', 'image/png'}, exclude={'image/png'}) # keep only plain/text"
865 865 ]
866 866 },
867 867 {
868 868 "cell_type": "markdown",
869 869 "metadata": {},
870 870 "source": [
871 871 "## More complex display with `_ipython_display_`"
872 872 ]
873 873 },
874 874 {
875 875 "cell_type": "markdown",
876 876 "metadata": {},
877 877 "source": [
878 878 "Rich output special methods and functions can only display one object or MIME type at a time. Sometimes this is not enough if you want to display multiple objects or MIME types at once. An example of this would be to use an HTML representation to put some HTML elements in the DOM and then use a JavaScript representation to add events to those elements.\n",
879 879 "\n",
880 880 "**IPython 2.0** recognizes another display method, `_ipython_display_`, which allows your objects to take complete control of displaying themselves. If this method is defined, IPython will call it, and make no effort to display the object using the above described `_repr_*_` methods for custom display functions. It's a way for you to say \"Back off, IPython, I can display this myself.\" Most importantly, your `_ipython_display_` method can make multiple calls to the top-level `display` functions to accomplish its goals.\n",
881 881 "\n",
882 882 "Here is an object that uses `display_html` and `display_javascript` to make a plot using the [Flot](http://www.flotcharts.org/) JavaScript plotting library:"
883 883 ]
884 884 },
885 885 {
886 886 "cell_type": "code",
887 887 "execution_count": 25,
888 888 "metadata": {
889 889 "collapsed": true
890 890 },
891 891 "outputs": [],
892 892 "source": [
893 893 "import json\n",
894 894 "import uuid\n",
895 895 "from IPython.display import display_javascript, display_html, display\n",
896 896 "\n",
897 897 "class FlotPlot(object):\n",
898 898 " def __init__(self, x, y):\n",
899 899 " self.x = x\n",
900 900 " self.y = y\n",
901 901 " self.uuid = str(uuid.uuid4())\n",
902 902 " \n",
903 903 " def _ipython_display_(self):\n",
904 904 " json_data = json.dumps(list(zip(self.x, self.y)))\n",
905 905 " display_html('<div id=\"{}\" style=\"height: 300px; width:80%;\"></div>'.format(self.uuid),\n",
906 906 " raw=True\n",
907 907 " )\n",
908 908 " display_javascript(\"\"\"\n",
909 909 " require([\"//cdnjs.cloudflare.com/ajax/libs/flot/0.8.2/jquery.flot.min.js\"], function() {\n",
910 910 " var line = JSON.parse(\"%s\");\n",
911 911 " console.log(line);\n",
912 912 " $.plot(\"#%s\", [line]);\n",
913 913 " });\n",
914 914 " \"\"\" % (json_data, self.uuid), raw=True)\n"
915 915 ]
916 916 },
917 917 {
918 918 "cell_type": "code",
919 919 "execution_count": 26,
920 920 "metadata": {},
921 921 "outputs": [
922 922 {
923 923 "data": {
924 924 "text/html": [
925 925 "<div id=\"c6929609-3cb6-4443-9574-d9f71791a987\" style=\"height: 300px; width:80%;\"></div>"
926 926 ]
927 927 },
928 928 "metadata": {},
929 929 "output_type": "display_data"
930 930 },
931 931 {
932 932 "data": {
933 933 "application/javascript": [
934 934 "\n",
935 935 " require([\"//cdnjs.cloudflare.com/ajax/libs/flot/0.8.2/jquery.flot.min.js\"], function() {\n",
936 936 " var line = JSON.parse(\"[[0.0, 0.0], [0.20408163265306123, 0.20266793654820095], [0.40816326530612246, 0.39692414892492234], [0.6122448979591837, 0.5747060412161791], [0.8163265306122449, 0.7286347834693503], [1.0204081632653061, 0.8523215697196184], [1.2244897959183674, 0.9406327851124867], [1.4285714285714286, 0.9899030763721239], [1.6326530612244898, 0.9980874821347183], [1.836734693877551, 0.9648463089837632], [2.0408163265306123, 0.8915592304110037], [2.2448979591836737, 0.7812680235262639], [2.4489795918367347, 0.6385503202266021], [2.6530612244897958, 0.469329612777201], [2.857142857142857, 0.28062939951435684], [3.0612244897959187, 0.0802816748428135], [3.2653061224489797, -0.12339813736217871], [3.4693877551020407, -0.3219563150726187], [3.673469387755102, -0.5071517094845144], [3.8775510204081636, -0.6712977935519321], [4.081632653061225, -0.8075816909683364], [4.285714285714286, -0.9103469443107828], [4.4897959183673475, -0.9753282860670456], [4.6938775510204085, -0.9998286683840896], [4.8979591836734695, -0.9828312039256306], [5.1020408163265305, -0.9250413717382029], [5.3061224489795915, -0.8288577363730427], [5.510204081632653, -0.6982723955653996], [5.714285714285714, -0.5387052883861563], [5.918367346938775, -0.35677924089893803], [6.122448979591837, -0.16004508604325057], [6.326530612244898, 0.04333173336868346], [6.530612244897959, 0.2449100710119793], [6.73469387755102, 0.4363234264718193], [6.938775510204081, 0.6096271964908323], [7.142857142857143, 0.7576284153927202], [7.346938775510204, 0.8741842988197335], [7.551020408163265, 0.9544571997387519], [7.755102040816327, 0.9951153947776636], [7.959183673469388, 0.9944713672636168], [8.16326530612245, 0.9525518475314604], [8.36734693877551, 0.8710967034823207], [8.571428571428571, 0.7534867274396376], [8.775510204081632, 0.6046033165061543], [8.979591836734695, 0.43062587038273736], [9.183673469387756, 0.23877531564403087], [9.387755102040817, 0.03701440148506237], [9.591836734693878, -0.1662827938487564], [9.795918367346939, -0.3626784288265488], [10.0, -0.5440211108893699]]\");\n",
937 937 " console.log(line);\n",
938 938 " $.plot(\"#c6929609-3cb6-4443-9574-d9f71791a987\", [line]);\n",
939 939 " });\n",
940 940 " "
941 941 ]
942 942 },
943 943 "metadata": {},
944 944 "output_type": "display_data"
945 945 }
946 946 ],
947 947 "source": [
948 948 "import numpy as np\n",
949 949 "x = np.linspace(0,10)\n",
950 950 "y = np.sin(x)\n",
951 951 "FlotPlot(x, np.sin(x))"
952 952 ]
953 953 }
954 954 ],
955 955 "metadata": {
956 956 "kernelspec": {
957 957 "display_name": "Python 3",
958 958 "language": "python",
959 959 "name": "python3"
960 960 },
961 961 "language_info": {
962 962 "codemirror_mode": {
963 963 "name": "ipython",
964 964 "version": 3
965 965 },
966 966 "file_extension": ".py",
967 967 "mimetype": "text/x-python",
968 968 "name": "python",
969 969 "nbconvert_exporter": "python",
970 970 "pygments_lexer": "ipython3",
971 971 "version": "3.6.0"
972 972 }
973 973 },
974 974 "nbformat": 4,
975 975 "nbformat_minor": 1
976 976 }
@@ -1,2837 +1,2837 b''
1 1 {
2 2 "cells": [
3 3 {
4 4 "cell_type": "markdown",
5 5 "metadata": {},
6 6 "source": [
7 7 "# Plotting with Matplotlib"
8 8 ]
9 9 },
10 10 {
11 11 "cell_type": "markdown",
12 12 "metadata": {},
13 13 "source": [
14 14 "IPython works with the [Matplotlib](http://matplotlib.org/) plotting library, which integrates Matplotlib with IPython's display system and event loop handling."
15 15 ]
16 16 },
17 17 {
18 18 "cell_type": "markdown",
19 19 "metadata": {},
20 20 "source": [
21 21 "## matplotlib mode"
22 22 ]
23 23 },
24 24 {
25 25 "cell_type": "markdown",
26 26 "metadata": {},
27 27 "source": [
28 28 "To make plots using Matplotlib, you must first enable IPython's matplotlib mode.\n",
29 29 "\n",
30 30 "To do this, run the `%matplotlib` magic command to enable plotting in the current Notebook.\n",
31 31 "\n",
32 32 "This magic takes an optional argument that specifies which Matplotlib backend should be used. Most of the time, in the Notebook, you will want to use the `inline` backend, which will embed plots inside the Notebook:"
33 33 ]
34 34 },
35 35 {
36 36 "cell_type": "code",
37 37 "execution_count": 1,
38 38 "metadata": {
39 39 "collapsed": false
40 40 },
41 41 "outputs": [],
42 42 "source": [
43 43 "%matplotlib inline"
44 44 ]
45 45 },
46 46 {
47 47 "cell_type": "markdown",
48 48 "metadata": {},
49 49 "source": [
50 50 "You can also use Matplotlib GUI backends in the Notebook, such as the Qt backend (`%matplotlib qt`). This will use Matplotlib's interactive Qt UI in a floating window to the side of your browser. Of course, this only works if your browser is running on the same system as the Notebook Server. You can always call the `display` function to paste figures into the Notebook document."
51 51 ]
52 52 },
53 53 {
54 54 "cell_type": "markdown",
55 55 "metadata": {},
56 56 "source": [
57 57 "## Making a simple plot"
58 58 ]
59 59 },
60 60 {
61 61 "cell_type": "markdown",
62 62 "metadata": {},
63 63 "source": [
64 64 "With matplotlib enabled, plotting should just work."
65 65 ]
66 66 },
67 67 {
68 68 "cell_type": "code",
69 69 "execution_count": 2,
70 70 "metadata": {
71 71 "collapsed": false
72 72 },
73 73 "outputs": [],
74 74 "source": [
75 75 "import matplotlib.pyplot as plt\n",
76 76 "import numpy as np"
77 77 ]
78 78 },
79 79 {
80 80 "cell_type": "code",
81 81 "execution_count": 3,
82 82 "metadata": {
83 83 "collapsed": false
84 84 },
85 85 "outputs": [
86 86 {
87 87 "data": {
88 88 "image/png": [
89 89 "iVBORw0KGgoAAAANSUhEUgAABLUAAAMQCAYAAADRs1frAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\n",
90 90 "AAAWJQAAFiUBSVIk8AAAIABJREFUeJzsvXn8LFdd5v+c3C03e24WsnOTsEokECw2WUKFVRSXF7bi\n",
91 91 "RlQQdMB12tFRAWFc5tcyiqMI47gh42gjOioKSlJhCSA0EQgBQgjJJQnhQpJ7s9/ctX5/nHP6W9/+\n",
92 92 "dtdedT7n1PN+ve6rbndXV5/q5dtVTz/Pc1SapiCEEEIIIYQQQgghxCeOcj0AQgghhBBCCCGEEEKq\n",
93 93 "QlGLEEIIIYQQQgghhHgHRS1CCCGEEEIIIYQQ4h0UtQghhBBCCCGEEEKId1DUIoQQQgghhBBCCCHe\n",
94 94 "QVGLEEIIIYQQQgghhHgHRS1CCCGEEEIIIYQQ4h0UtQghhBBCCCGEEEKId1DUIoQQQgghhBBCCCHe\n",
95 95 "QVGLEEIIIYQQQgghhHgHRS1CCCGEEEIIIYQQ4h0UtQghhBBCCCGEEEKId1DUIoQQQgghhBBCCCHe\n",
96 96 "QVGLEEIIIcQjlFKXK6WOKKVe73osZTHjvdn1OAghhBASFhS1CCGEENI5SqkfMMLGAaXUmQ7H8Z+V\n",
97 97 "UvcqpX7O1RhaJHU9gIrUHq9S6i1Kqb1KqVGbAyKEEEKI31DUIoQQQkgfvMYsNwN4lcNxvBzAcQAu\n",
98 98 "dzgGUp0fA3AigB90PRBCCCGEyIGiFiGEEEI6RSn1RABPBbDXXPUTSqnNjobzJgAzAG909PikHr8K\n",
99 99 "4OMAfsf1QAghhBAiB4pahBBCCOma15rlWwB8AsAZAF7qYiBpmk7TNH1KmqbvdvH4pB5pmr4lTdOn\n",
100 100 "pWn6YddjIYQQQogcKGoRQgghpDOUUjsAfD+AwwD+DMCfmJtes/JOhBBCCCGElICiFiGEEEK65BUA\n",
101 101 "jgZwRZqmtwL4awD7ADxdKXWx05ERQgghhBCvoahFCCGEkE5QSh0F4CfNxT8BgDRN7wPwLnMd3VqE\n",
102 102 "EEIIIaQ2FLUIIYQQ0hXfDuDhAO4E8P8y19sI4g8opU5q8gBKqWOUUr+olPqEUup+pdQDSqnrlFJv\n",
103 103 "Ukodt2T9y5VSR5RSr1+4/gRz/RFz+eFKqT9SSt2ilHpIKXW9UuoNSqljMvd5llLqn5RSdyilHjTr\n",
104 104 "/Hel1MkrxrrusZVSFyqlflcp9Xlz/71KqU+axzmthefl55VSHzXbfVApdYNS6veUUg9vsm2z/e1K\n",
105 105 "qdcqpRKl1DeUUvuVUrcqpd6hlHpywX3PNvv9ZXO/3Uqpv1NKPTXnPm8wz93Ll9y2Syl10Pz/QqXU\n",
106 106 "nyulblZKHVZK/Y25vrfnnhBCCCH9QVGLEEIIIV1hnVjvTNP0kL3SlH1/CcB2AD9ed+NGEPs4gN8G\n",
107 107 "8HgANwD4IoBHA/gVAJ/KEc3Shcv32+uVUs8AcC2AywF8DcD1AC4E8DoAVyiltiilfhbABwA8E8CN\n",
108 108 "AL4A4HwAYwAfKxLrlFI/AeA6AD8D4CQAnwZwM4BvNo9zk1LqBwqfhOXbvsSM+XcARABuAfApAMcD\n",
109 109 "+GkAX1BK/WCdbZvtPxX6uX4LgGcD2APgk+bmH4Le/99acd9nQz+3rwVwL/R+HwvguwB8SCn13QUP\n",
110 110 "v/i6za9XSj3JjONHADwE4KMArloyhs6ee0IIIYT0C0UtQgghhLSOUurRAJ4LLUL8yZJV/swsf1Ip\n",
111 111 "pWo+zK8BeByADwI4L03TS9I0vQTAYwF8HsA50KJLIWmaHrFDBzAFcDWAc8xMiU8A8AhoweypZn8m\n",
112 112 "AN4O4EwzK9+TAJwH4N8BPArA67GalwD4IwCfBfDMNE3PStP06WbspwF4I3QP2TuVUt9f7qkwg1fq\n",
113 113 "UQAS6H3/GwDnpml6cZqm35qm6ZnQ7rl7ALxDKfXcKts2278IwBUAzoaOkV6QpuljzPbPBfCdAL4B\n",
114 114 "4MeVUo9YuPtJ5j6fMvd7YpqmTwFwOvRzuhnA25RSW6uOC/qY9k+gBbyL0zR9bJqmz0zT9G0L63X2\n",
115 115 "3BNCCCGkfyhqEUIIIaQL/pNZztI0/dyS2/8CwBEAFwB4Uc3HsKLMb6Zp+g17ZZqmN0KLF09K0/Qf\n",
116 116 "amz3PgDfnabpXZltfgVrQtUPAfhImqY/mabpvsw6Xwfw8+biKGf7TwRwJYBnpGn6kewNaZrem6bp\n",
117 117 "GwD8qLnq7UqpUyuM/e0ATgDwS2mavixN090L2/8XAC+Efu7/sIag+McAjgHwp2mafp95XrLb/ycA\n",
118 118 "MYAnmNchy0kAbgfwojRNb8ncZx9099ot0MLScyqOCdDHtKcDiNM0/WzOel0+94QQQgjpGYpahBBC\n",
119 119 "CGkV02Vlu4+WubSQpunXAPyLuVi3MN5G0R69ZPs3pWn6+Zrb/Z00TQ8suf4fM4/7lqUDStN/B3AH\n",
120 120 "gDOUUieu2P79AH5oxWPY7bwTwHugI4OvLjNopdQToJ1pn07T9P/L2fZnoPflkSjpZDPbfzKApwC4\n",
121 121 "G8DP5mz/C2ma3r7sJgCvS9P04JL7HMLa8/uYsmNa4M1ZIXIFnTz3hBBCCHEDRS1CCCGEtM2PQAsC\n",
122 122 "DwD4vznrWcHrBUqpC2s8jt32m5VSb1dKPadmdC1LCuD9S29I04egBR1AR+hW8VWzPH7F7f+QdZbl\n",
123 123 "8A6zLOtke75ZvqfEuteY5TNKbhvQDiwA+Oc0Te/PXXM5RwC8N+f2L5nlquetiI+WWKer554QQggh\n",
124 124 "DqCoRQghhJC2sdHDvy0QP/4Zun9JZe5ThQmA3zf3fyV0rOxepdSHlFI/p5Q6ocY2AWB3zm33muVX\n",
125 125 "C9ZRWH2cdW3JcXzBLHeWXN/OavirdibHVf8A/Dez7lkltw0A55rlFyvcJ8ueZS6tDPa9Uuf4NEX+\n",
126 126 "a2Lp6rknhBBCiAM2ux4AIYQQQsJBKRVDF7UDwMuVUi/PWz/D5UqpX03T9MGyj2XK3X9WKfUWAC+F\n",
127 127 "jtI9Ddp99AwAr1FKPS9N05vK78HckVW0Tp444wobx7wBuruqDLu6GcpSHii4fdXMhoQQQgghS6Go\n",
128 128 "RQghhJA2sf1Y+6EL18twCnSJ+A9CF5FXIk3Tm6FdWxOl1FHQBfITAN8M4G1Yi+VJ4fEl17Pi4K6S\n",
129 129 "69v1/i5N0/9aZUAlseXuGzrMPKKr554QQgghDmD8kBBCCCGtoJQ6F3rWQQB4bZqmp5f5B8DOUFgn\n",
130 130 "griONE2PpGn6bwC+y1z1LKXUpqbbbZnvVEqdXmK9HzbLf8lda433meX3KaW6+OHyKrP8NjMZgI90\n",
131 131 "9dwTQgghxAEUtQghhBDSFj8JfWxxJ4C/rHC//2GWj1dKPbPsnZRST1ZK/eiKm22MUZqgBQDHAXhH\n",
132 132 "Xqm9UuplAL4Dup/rbWU2mqbpdQD+DcD5AN6Us+1NSqk/U0pVKkFP0/QTAD4O4GQAb87Z/uOVUjur\n",
133 133 "bLtHOnnuCSGEEOIGilqEEEIIaYxSahuAV5iLb0/TdH/Z+6ZpejXWZuN7Td66mcc7D8CHAPyxUuqX\n",
134 134 "zePb2x6GtdnrrkzT9HDZsbRIXj/UpwE8D8DVSqlvzd6glDpRKfUGaFEwBfCqNE3vqvC4rwawB8B/\n",
135 135 "McLVOQvbjwB8AMDLoQvlq4p+r4TuxnqlUuqvs+KV0rwEwBUA/kMp9ciK2+6DLp97QgghhPQMRS1C\n",
136 136 "CCGEtMH3ATgVwAEAf1jj/tat9d1KqTOLVk7T9BYArwJwEMBvAPiGUuoTSqlrAdwGLVx8FcBP1RhL\n",
137 137 "G6ic2/4fdNTymwF8WCm1Wyn1MaXUpwHcAeB1APYB+OE0Tf+myoOmaboLwHMA3AwtXH1FKfV5s/1b\n",
138 138 "oZ1W3wodq3thVcHPuMGeC/3cjgDcpJS6QSn1UQC3mn07GcAfpGn6pSrbbkje852ls+eeEEIIIf1D\n",
139 139 "UYsQQgghbfCfoN0t0zRNd9e4/7ughZJN0GJVIWma/gWAJ0BHxHYDeByAM6DdOL8J4OIlMx+maDbL\n",
140 140 "Xpn7Fj5GmqZvgxZW/hDA3dAF5g8HcC20SHdhmqZ/VWf7aZp+FsA3AfhpAB8GcBr083QY+nl+SZqm\n",
141 141 "356madki/8XtfxzAowD8PLTr60QAlwA4AuCdAJ6Wpunr6mwaq/er7m0bV2723BNCCCFEECpN3cye\n",
142 142 "PBqNzgLwzwB2TqfTkyvc72HQPREvArADwE0A/mA6nb69k4ESQgghhLSAUupyAH8K4A1pmr7R8XAG\n",
143 143 "BZ97QgghJEycOLVGo9FFAP4d+pex0qraaDQ6Cbo/4zkA3gDgpQDeA+Ato9Hot9ofKSGEEEIIIYQQ\n",
144 144 "QgiRSBfTPecyGo0uA/BuANdD9xr8cP491vFGACcBuHg6ndpow3tHo9GXAPyv0Wj019Pp9DOtDpgQ\n",
145 145 "QgghhBBCCCGEiMOFU+tHoGc4ugx6dp5SjEajbdCFp3+QEbQsfwZgF4CfaGmMhBBCCCGEEEIIIUQw\n",
146 146 "LkStVwN40XQ6faDi/S4BcDx0D9c6ptNpCuC9AC5tPDpCCCGEEEIIIYQQIp7e44fT6XRfzbs+wiyv\n",
147 147 "X3H7DQBeWXPbhBBCCCGEEEIIIcQjnBTF12QHgEPT6fTBFbffDWDraDQ6pscxEUIIIYQQQgghhBAH\n",
148 148 "+CRqHQ/goZzbrdh1Yg9jIYQQQgipSooKsz6TVuFzTwghhARI7/HDBtwH4Oic261D654exkIIIYQQ\n",
149 149 "Uok0Tf8CwF+4HscQ4XNPCCGEhIlPotYeAJtHo9ExKyKIJwI4kBNPXMqVV17JX+0IIYQQQgghhBBC\n",
150 150 "OuCyyy5TXW3bp/jhl83y0Stuf0xmHUIIIYQQQgghhBASMD45tf4DOoL47QA+lb1hNBopAC8E8K91\n",
151 151 "N96lckj8I5ok2wBMAbzEXPX3AN4K4EMADgI4B8CrAbwGwAkArgXwktk4/kr/o/Wb0WiUTqdTfv5a\n",
152 152 "JJokCsB7AbwAwD8C+AyAXwNwJ4Cds3H8gMPhkQWiSfJE6O+4Q9DfywcBPHU2jv+jy8cN+bMXTZIX\n",
153 153 "Qn8GLG+ejeP/7Go80ogmyRYA7wMQm6sOAzhuNo7zukuDIpokzwbwAXPx3bNx/NK+Hrvvz140SS4H\n",
154 154 "8Gfm4stm4/iv+3rsrogmySUAroHuSXvKbBzPHA+pNtEkeS/0ecy/z8bx01yPpyrRJDkP+jj4i7Nx\n",
155 155 "/BTX48ljNBqlN0evfhiAr5urRH8eoknySQBPAvD7s3H8M67H4xvRJHkPgBcD+IvZOL7c8XAGSx/J\n",
156 156 "OLFOrdFodOJoNNpuL0+n04eguxBeOxqNHraw+uUAzgfwx/2NkIRKNEm2A/gHaEFrD4CXzsbx98zG\n",
157 157 "8RWzcXxgNo7T2Ti+dTaOfwXAkwF8CcDjAVwVTZJT3I2ckDnfDy1o3Q3gJwC8HsAMwKkAXulwXGQ5\n",
158 158 "v2mWvw/gDwBsAb/PmvJCs3w/tEj4C9EkudjheKTxbGhBaw+02L0JwGOdjqh/suLBi8x3f6j8WOb/\n",
159 159 "j3E2inY51ywVgLdGk2STy8E05OFm+eRokpzsdCT1eCN0Dcwl5kc16Twu8/9znI2iHGea5eNy1yKr\n",
160 160 "sJrBTpeDIN0jUtQajUbHArgJC44sAK+DPkn78Gg0+vHRaPRto9HoN6AdNL8znU4/3fNQSWCYg6J3\n",
161 161 "QwsCdwB4zmwcv3vV+rNx/EUAT4F2WZwP4G+iSeKTA5KEya+Z5S/OxvHXZ+M4BfDfzHVj40QkAogm\n",
162 162 "ybdACzD3AfgtAL8IYB/0yQFF8vpYUetNAP7W/P9bHI1FIo8yy78HcJX5/+MdjcUVVtQ6Aj3Z0PMc\n",
163 163 "jqUzoknyKADPzFy1qsbDN87N/P9boH/A8Q4jAllR6ygAz3E4nMqYHwt+xFzcDOAkh8Mpy0WZ/5+7\n",
164 164 "ci3HRJPkKKyJMiJFrWiSnBBNkh+MJsmro0lyeTRJjnU9pgVON8vznY6CdI5rUWvV9MoHAXwNwC3Z\n",
165 165 "K6fT6d0AngUdAXsjgHdBu2l+YTqd/pduh0oGwusBvAj6l+tLZ+P42qI7zMbxXgDfBeAbAC4D8N87\n",
166 166 "HSEhOUST5BHQjou7Afx55qb3APgsgLMA/FD/IyMreLZZ/vVsHN85G8f7oCM1ABA5GpPXRJNkJ/SJ\n",
167 167 "+70A/h3AdeYmkScFjrCi1g3QfxcA4JsdjaV3jJBgRS07I+J3OxpO11xulp8zy9BErU+Y5etcDaQh\n",
168 168 "O7A2gzvgn7j629BuOcvpq1YUhC9OrVOhXbQAcIbQH7peB+CdAP4IOuIsJg1g/s5bUfAcE7sngeJU\n",
169 169 "1JpOp78+nU53LLn+wHQ6vWg6nT5/yW27p9PpK6bT6dnT6fTY6XT6zdPp9K39jJiETDRJXgztcDkC\n",
170 170 "4Ptn4/jzZe87G8e3Avge6E6cn4smiehOARI0LzbL983G8UF75WwcH4GOtwHAd/Q+KrKKS8wy2wdj\n",
171 171 "T9Ke3PNYQuEFZnmF+QzYk3mKWmtkRS37482QnFoXADgN+gesN5vrviNQp/UPmuV/NctHGweI71hR\n",
172 172 "663Qx15neOpCti4t22e34dxHKsYFaJ3G15urfRC1sk4tyaLWGQuXJX6H2fev7SiT9HyeAMD+TTgK\n",
173 173 "ssZGWiaELzVCGhNNktMBvMNc/NXZOL6y6jZm4/gj0AfHIfQ7EH+xgtV7ltx2hVk+m+9PMVhRK1sK\n",
174 174 "T1GrGTZ6+D6ztKLWRUvWHSrLRK3BOLWw5tL6GIDPA7gRwClY+zwGQTRJtgI4D3oigPdA1yocA+Bs\n",
175 175 "l+NqCStq3QItTgJaqPQNKwpcBWAvgAuiSXKhw/FUwYoE/wFPRC0TD8qKQ2Ljh1jr07JIFLVONMuP\n",
176 176 "LlyWwOJ7caeLQZB+oKhFiOb3oC3g70ez+OCbANwKfWD8qhbGRUhpoklyAnSc7QjWz/wGAJiN410A\n",
177 177 "dkF3XrA02zHRJDkeOgp0EGsROWBN1HqKJ6W7YjDPl53Rz86IfDN0T9lZ0STxoe+lU4zQcT70+d2X\n",
178 178 "AXwFwP3QThcfRYE6zEUt0zlohU/JJ7h1sCd13zBu3S+ayyFEEO1rdSu0WAf4LWrdDCAx//clgmhL\n",
179 179 "7fdCV3AAwkWtw1uOBfQx0N3Qx0pnCI6l+eDUsiLWrWZ5gquBLGFxYjn2agUMRS0yeKJJ8iIAL4M+\n",
180 180 "6Xm1OfCrxWwcPwDgZ83F34gmiaRfLEj4PB+6qPUjs3G8Z8U6thTaqzLaQLkY2tl53Wwc789cvwva\n",
181 181 "eXAq+MtiVU6HPqjeMxvHtwDAbBwfBvAFc7vEk4K+uQD6+G/XbBzvN995Q+vVyjq1AGC3WS6eBPnO\n",
182 182 "XNQyS+um8VrUMk5j6za7DWGIWl/B2vvRl5lIvRO1DmyfTy55LfTnXmGjI0oKdlySeyGtiGVFLUnn\n",
183 183 "PYt/z3e6GATpB4paZNCYKbz/yFx8/Wwc39TCZv8ewAehfwn6qRa2R0hZ8qKHFopacniSWV6TvdI4\n",
184 184 "Rz5uLjKCWI2dZvmVhevZq7VGNnposaJW8L1apk/KinefNEsrai06I3xnUdSyTq3HOBhLm5wO/QPO\n",
185 185 "nbNx/BDWRC3RgsoKzjPLrwC4y/zfF0epd6LWwe3zKufPQQuigFyHphW1bHWExO8vK2LZyd0kObXs\n",
186 186 "e9H21e10NA7SAxS1yNB5LfSvZNcC+N02NmhOSH/DXPy5aJIck7c+IW1gYle2IPufc1a1otazAi1F\n",
187 187 "9ollfVoW9mrVw7oedi1cT1FrjUeaZVbUGlJZ/MnQgsjds3F8v7luaKKW104trI8eAuE4tfaa/5+8\n",
188 188 "Yl1peCdqZZxa12FN1JJaIG7/Hs2gy/hPMx3AkvDBqWV/ONzpaBykByhqkcESTZIdAH7ZXPzF2Tg+\n",
189 189 "1OLmr4D+EjoNwCta3C4hqzgb+gt8L3Tx8VJm4/g26FLk4xFYKbKHWKcWRa322GmWdGqtZplTa0hl\n",
190 190 "8fak8I7MdaGKWvakLqj4ITaKWnb/fBe17jb/p1OrIxacWvb9I1XUsk6tr0Hgd5j5YfRY6H7G283V\n",
191 191 "kpxa9u+fPZ5ip1bAUNQiQ+aXoA8crgTwb21u2Li1ftNcHJtiXrKcX3c9gECYCyTm/ZcHI4iOMQ7O\n",
192 192 "x0LPSnbtklVmZvmkDmeqDPGzR6dWMXnxw4tMPC9krPDxjcx1fYtafX32rMDwdbO8GXpiivM8d5EH\n",
193 193 "4dSKJsmx0N2JB6BfIzq1OubA9h37zH+vh/z4of17lBW1JPWtWQHrXqwJspKcWva9+EnoSQHO5vlY\n",
194 194 "uIR+4ELIUqJJcjaAnzYXf6mECFCHf4QuJz4Ha11HZIHpdPoG12MIBOu6uiZ3Lc0HzfJpuWuRLrkY\n",
195 195 "+jv487NxvG/xxtk4vgv6RHs7gLO6GECgn72s6yHLVwA8CD3T1Sn9DkkcG0St2Ti+G8A9AI6GPy6R\n",
196 196 "uixG8oA10aeXovgeP3vr9tU40m801z1q6T38IAhRC2t9WreaCRvo1OqQaJKodNMWK2rsgfz4oXVq\n",
197 197 "7cba8yvpvWFFrXugZ9AFgOMF/TBi/57fBuCr0JMCSBUwSUOkvOkI6ZtfALANwN/OxvEni1augzlA\n",
198 198 "ebu5+MouHoOQDHlRtkU+Y5Z0rbjjYrPMe712meXOTkcSFjvNclf2SvP3ePBurWiSHActku7HmiBg\n",
199 199 "8TnCVYVl8UMrap1h+glDYZmAZwXfTsTynghN1LKvic9Orbug3TA7okmyxd2QctkGYBOA/bNxfBCC\n",
200 200 "44fmb/Vx0CXnWdHoOGeD2oh1Zd1rZhm+z1w+3tF4FsnGr282/9/pZiikayhqkcERTZJTAbzKXPzN\n",
201 201 "vHVb4C+hTx6eH02SnR0/Fhk2S2fSW8ENAA4BuNDzCIrP2G6HG3PW2WWWOzsdSSAYMWKVUwtYcyZd\n",
202 202 "2M+IRGJL4m80JyFZxDstWmJD/HA2jh+EjtBshSwnRFOWiVq+CSfLCEXUWvx7dT90JP1YwcJQlrmo\n",
203 203 "ZX44sK/DqY7GU4QVW6xAJDl+OI8emjSJRFEr69QC9N/Q7PWuycavd5n/s1crUChqkSHyWgDHAHjv\n",
204 204 "bBx/qssHmo3jPQDeDW15/bEuH4sMl2iSnAl9AHQPgC8XrT8bxwegZ8FSAL6p29GRFazqfspib9vZ\n",
205 205 "5UACYgf0Af99WIvxZPmaWfYSMRPKBWa57O/EUEStZU4tIMyy+MWieGDts+GzqGWdNUGJWka88CmC\n",
206 206 "mHVqAWvvM6l/Y62oZR1Ft0OXnJ8pUETMRg8BmaLW3KlllvcsXO+MaJIcDS2uHYT+TO0yN+10NCTS\n",
207 207 "MRS1yKCIJsnxWOvS6tqlZfljs/wxM1MIIW1TpSTecp1ZXtTBeEgxO81ymaPIsmthXZLPXChc8Tmw\n",
208 208 "olZIokVVrKCze8ltdyysEyrLiuKBtedE6gl5JYxzMc+p5YNosgFzHHUW1s+4tgc6+naSZ0XQNn54\n",
209 209 "S+Y6L0Qt8/6yY1wUtaT+DVknapkI4m7oH/ikfS9kS+IB4AGzPNbBWFZhxSuJTq25oG+OB/aYyxLG\n",
210 210 "RjqAohYZGj8K/SV89WwcX93TY34QwJcAnA3gsp4ekwyLKn1aFopabqFTq312muUqoTBEJ05VbCzo\n",
211 211 "ziW3ST8hbYtVTq15r1aPY+mSEwFsAXDfwmQUvscPz4Q+f/m6cR3bzjz7npYafVuGnbQi+1705fU5\n",
212 212 "Hrqf6gEjDgHy/4ZYl9N9meukRhB9cGotxg/FOLWwceZX+zdwu4OxkB6gqEUGg5mN4zXm4u/29bjm\n",
213 213 "F4K/Mhe/t6/HJYOiysyHls+aJUWtnjG2+DOge81uz1l1l1nu7HhIoVAkFNqTgzNX3D4E7An/oqAD\n",
214 214 "yD8hbYsip1YootYylxbgf/xwMXpo8TGCuBiHAzxxamFj9BCQ/zdksVMLWBM9pImh9nvKOrUkilqL\n",
215 215 "8cN7F653iXVq2df3QbNkj2ygUNQiQ+IF0CW5twD4x54f+11m+d0Cc/vEf6qUxFvo1HJHdhr3xbLu\n",
216 216 "LNZxdF40STZ1PKYQyCuJB8ITLepgT/jp1Apf1FrWpwV4Hj/EcndT9rKPota9met8cWr5LGplRUSJ\n",
217 217 "sT5g7e+QZKfWYvzQLiVE/Bb//lHUChyKWmRIvNYs3zobx4f6fODZOP4cgM9DFxnHfT42CZtokpwM\n",
218 218 "HW19EPkz6S1yM7Qd+2yzDdIfReILAGA2jh+C/pXWdsiQfHaa5a4Vt4cmWtRh0PFDIw5bUeSuhZtD\n",
219 219 "e38sxm8svju17AnzvQvX+yxq0anVD8vih1JFrUWnlh2nJFFr8bMoOX5oRS3GDwOFohYZBNEkeRSA\n",
220 220 "FwF4CMD/djSMqVmOHD0+CZNHm+UXTa9IKcy6nzMX6dbql51mmStqGXYt3Iespkgs3AvgAIATokky\n",
221 221 "1F9r7Qn/UOOHp0CXQt+15MetoIrisdqR5osTaBXL3E1AOKKWL6+Pj6LWsvihVFFrh1la8d2OWdI4\n",
222 222 "fSiKX+zUGup3f/BQ1CJD4SfM8q9m43jx19m+YASRdMGjzPKGGvdlBNENZUriLXadnV0MJDB2muWu\n",
223 223 "ZTeafsPQhIuqDNqphdUl8UB4RfFFopZ0J9AqhuLUki5qWdHFR1HLB6eWFV/s+CTGD30oimf8cCBQ\n",
224 224 "1CLBY6Z3frm5+HZX45iN489DO2NOBiOIpD3mTq0a96Wo5YadZkmnVktEk+QE6JP0fVgu2FgGWxYf\n",
225 225 "TRKF/KL4PQCOANgR8A8vq0rigXDjh6EVxdsT6fsWrvdK1IomyWYAR0N/5pbNTilddPTRqeVT/NCK\n",
226 226 "L1aMmccPzd9yCawqipfg1Fp0dFLUChyKWmQIvAT6QP6zAGaOx/L3Zvlip6MgIdGGU+ubWhoLKUcd\n",
227 227 "p9b5nYwkHKwQcbtxZK0iNOGiCsdCn0Tvm43jBxdvNJMWWEHwlMXbAyHPqTU/IQ9kYoZVRfH3AEih\n",
228 228 "Y7g+7ueq+KHdTy9ELWRcQwt/s3wRHXNFLUHCSxaf4ofrRK3ZOD4IHZ/fBGCbq0EtsKooXoJTy3Zn\n",
229 229 "7VtYslMrUChqkSHwCrP83wUnO33wL2b5YqFf+MQ/mji1bLH8BS2NhZRjp1nSqdUeeQ6kLEMWtfKi\n",
230 230 "hxbpToumrHRqmZPGO6GPjU9dvN1DlhbFmz5FSSefVQklfrgsCgf47dR6AFp42Q4toEvDx/hh9gcI\n",
231 231 "ab1ai59FSU6tRVGLTq3AoahFgiaaJA8H8HwA+wG80/FwAOAT0BGPCwA80vFYiOdEk+QorL2P6ji1\n",
232 232 "boGOPpxrYrqkY8zzfBb0835bibvsMsudHQ0pFOyJbJ5gA1DUAvKFv9BFrVWRPEtInWt5++qLG2gZ\n",
233 233 "QcQPsVrU8uW12SBqmR+OrUgkUTzwQtQyP3rniVpSerV8cmpR1AocilokdF4OPdPR383G8R7XgzHx\n",
234 234 "jveZi9+wC74uAAAgAElEQVTmciwkCM6F/jV092wcL/5qXYhxJtwK/Rl5eMHqpB3Ogf7uvX02jg+U\n",
235 235 "WP8WszzXdLCQ5eTN6pfFTo8+uE4tlBP+hiJqrXqfhFQWnydq+TLD3jKKnFq+vHdDdGoBAkWiDL50\n",
236 236 "am2BjhkeMsdplnmvVv9DWo8R3nxyas1nP2RSJkwoapFgMX+0fsRc/HOHQ1nERhApapGmNOnTstxk\n",
237 237 "luxs6ocqfVqYjeOHoIWYzdAOL7KcMtE6gE4tYNhOrbyi+Oz1Xu+/cYSeDOAwtDt8EV+Ek2Ws6tS6\n",
238 238 "C7orbIcnPwCscpx569QySHbE+NKptcylBchyam2HPi7ZPxvH+811kpxaNv76EDD/EfcQtPYR6kQo\n",
239 239 "g4aiFgmZpwK4EPqE8ErHY8nyr9AHXs+OJomELybiL036tCw3myV7tfrBilpl+rQs1l00RCGmLGWd\n",
240 240 "WkMWtejUKnZq2ZMyCU6DJswFB9OhtYgvwskylopBxglv98sHsa4ofniScEeJj04tL+KHKBa1JIx1\n",
241 241 "MXoIyHZqAbIFV9IQilokZH7ILP/KHOyIYDaO7wTwcQBbAcSOh0P8hk4t/6gjatlIVAg9P11BUasY\n",
242 242 "FsUXO7VCEbVWCSaWEOOHgKyT/iKWvkYmlv4gdPxM8g+fRaKWROHAl/ihD06tZZ/DfdBuqKMF9LRS\n",
243 243 "1BoYFLVIkJg/pt9vLv6ly7GswPZqPdfpKIjvtOHUsqIWnVr9YLucbq9wH4paxVSNHz7MTLQwJMrE\n",
244 244 "D33rJapKkVNLktOgCWVFLR8cTYusih8Csk76i8h7jUS/PsZBZse2Kn4oSSSy+B4/FNOphSVOLTNR\n",
245 245 "gJQfBvJEre0gwTG0AzoyHF4EYAeA6wBc63gsy7jKLJ/jdBTEd9pwajF+2C9WmNqdu9Z6KGoVU8qp\n",
246 246 "ZTrK7obu1NjR9aCEMej4YTRJtkC7S45gec8UsCaUSOiEaUKRqOVl/HChnPr+Jat479QySH99jod2\n",
247 247 "kj24ZMITiSKRJZT4oQRRy34O71m43vnf0GiSbIL+jk8BZN+f87L43gdFOoeiFgmVHzDLd5pfDqTx\n",
248 248 "cejywouiSeLL9NNEENEk2Q4dZTuMNbdVHRg/7Bcbe/t67lrroahVTFmnFjDcCOLQi+KtiLknp5Jg\n",
249 249 "aE4tqaLJKo6Fnq33wdk4PrTkdklOliK8dWphdfQQEBrxMgmOLQAOZorNAT9FLQljtaLVomNSQln8\n",
250 250 "vCR+4RxQ5HuTtANFLRIc0SQ5BsCLzcW/cTmWVZgv1I+Yi5c6HArxl53QB/e7FqZ8rsod0Ad1J0eT\n",
251 251 "xLcTHB+xwhRFrXYp26kFUNQapFMLq50FWaREZ5oSpFML+dFDQJaTpYi8fZH++uSJWhJFImB59BDI\n",
252 252 "jFdQMb8PTq1lRfGAjB8GlkUPAYpaQUNRi4TIC6G/TGezcbzL8VjyYASRNGGnWd6ct1IR5lcsuw26\n",
253 253 "tTrEHDAzftgyxrV4LHTMYNVJfJahilpl4of3AdgPfYIX2oF/XsE4Fm4LXdSS7gRaxdKZDzNIcrIU\n",
254 254 "EapTS2pR/Kpi/sPQf/MU1hw+rvGhU2vV31MJTq1Vota+hdtJQFDUIiHyUrP8W6ejKMaKWpwBkdSh\n",
255 255 "zix6q2AEsR+Ogz5Y3YflfTCroKiVz9yBVDJubp/PwYhapmNkB3THyKo+KStyW7fbqavW85Qqolbo\n",
256 256 "nVq+xg+LXkNJJ/1F+NypZT8fdy+5TWpRfN7zLc1dRqdWM+jUGiAUtUhQmF/sv8NcfJfLsZRgBv1F\n",
257 257 "+uhokpzlejDEO3aa5a4WtsUZEPthHj2s2PVHUSufKtFDYE3UkXrC2AU7oJ0Ie1d0EWWR8Et7F5QR\n",
258 258 "tRg/lE2I8UMfnVqrRBdAnkBkse+JZT8oSRNDfejUWhXnlvD9QVFrgFDUIqHxfOgvpWtm47hRLKtr\n",
259 259 "TA/S1ebipQ6HQvykTacWZ0Dshzp9WgBwF/SEACebsluynjKxuiy+ulSaUKYk3iLhpKQLioQeQIbL\n",
260 260 "oA0YP5RPGVFL6t8oKxosE7WkCgd0arXLqqJ4CX9D50XxC9fb55PxwwChqEVC43vNUnr00GIjiM92\n",
261 261 "OgriIzvNclcL22L8sB/q9GlhNo6PYE2MCLHAuylVBBtgmE6tKrNDhipqMX64xtypJagcuwyMH8rA\n",
262 262 "ii6LThhAnkBkCUHUkvT+XhU/lPD9UdSpJU1wJS1AUYsEQzRJtgF4ibnoi6hlnVpPczoK4iNdOLUo\n",
263 263 "anWL7XCq6tTK3ocRxI1UjR9Kd0F0QRU3WygRvEXKiFr7ARwEsNUcU/hKrqhlZmDeB2ATZJwglyWk\n",
264 264 "+GGe60y64yzPqSW1KN6+J3wWtSS9v1e9fyU4tRg/HCAUtUhIPB/6gOfTs3F8o+vBlOQa6APoi6JJ\n",
265 265 "4vsvw6QnoklyNIAzoSNpt7ewyVvN8hzPfrX3jbrxw+x9KGpthPHDYqo4tUJxKy1SFF2zRfkhiHpl\n",
266 266 "opY+RhCHEj+UHpPKc2pJL4rP69SSMmYfRC0b8Vsco4T3LkWtAUJRi4SEnfVQekH8nNk4fgha2FIA\n",
267 267 "nuJ4OMQfzjXLW0uUPhcyG8f3Qh8sHYPwTmQlUSt+aKCotZqq8UN7Mr+jg7FIxQoXK2c+zCAhPtIF\n",
268 268 "RS4fLNzu8/5XEbV8EneDiB+aH4/KiFpST77LOLWkCESWEOKHkkTbVb1V+83SpdO1KH4oVSwmDaCo\n",
269 269 "RYLAxAS+01z0JXpo+ahZPt3pKIhP7DTLNqKHlq+a5dktbpOsh/HDbqBTq5hVpb7LCFXUKhM/zN4e\n",
270 270 "ulNLem/TMkKJH26HPgfbbyYNWkS6qFXGqSVt7CHEDyWJtqtErYcWbndBUVG8tPcmaQGKWiQULoM+\n",
271 271 "AL92No5vcD2YilDUIlWxfVq7WtzmbWZ5TovbJOth/LAb6jq1ThpQ3HbV9OvLCEHUWUZZUYvxQ7mE\n",
272 272 "Ej8sen2kF1r77NRi/LAdrBNr/8L1EkQtxg8HCEUtEgq+zXqY5WNm+dRokmxyOhLiCzvNkk4tv2D8\n",
273 273 "sBsqFcXPxvEB6IPbTVg70QmdsoIOEL5TK0/oAcIQ9ao4tXwUtbyOH6L49ZHQS5RHmdkPpQkHIcQP\n",
274 274 "5+MU8IOMj/FD6Z8r0gCKWsR7okmyGf7NejhnNo5vh3bcHA/gcW5HQzyhC6cWRa0OMQegdGp1Q9X4\n",
275 275 "ITC8CCLjh+zUWkTaiXwZQokflhW1pAlDljynlvSieG9Frdk4PgwtIim4F2Ykxw+LOrWkfq5IAyhq\n",
276 276 "kRB4KnTh740Arnc8lrowgkiqsNMsu3BqMX7YDcdBH0jtw/L4QxEUtZZg3K228P2uCncdmqhVJX4Y\n",
277 277 "qqg1iE6taJIchbWT87y/NdJO5MswlPihdFGrjFNL2mtghU6f44eAHOG2yKklUdSS/rkiDaCoRULg\n",
278 278 "O8zyn8x03D5CUYtUwTq12hS1bKcWnVrdMHdp1fw7RVFrOTugf7XeW3Em0KGKWmWcWl6LOjkMpVPL\n",
279 279 "nuw+MBvHR3LWk3YiX4ahxA+lO0rKOLWOERCRy+K9U8sgRdQq6tRyGT9kUfwAoahFQmAuajkdRTM+\n",
280 280 "bpbf4nQURDzRJNkCLTylAG5tcdOMH3ZLkz4tQEfrUgCnmMg10VTq08qwxyyHImoxfli9U8vX/S8T\n",
281 281 "PQTknciXoSh+OBe1hAkqixS9RgcBHAaw2XznS2OlU8vM5ngQurNwa5+DKoCiVkuYz5YVjnwqit+3\n",
282 282 "cDsJCIpaxGuiSXIhgMdCH4Rf7Xg4Tfgs9EHAY6JJMpTiYlKPc6D/dt9uCq/bgqJWt5xhlnX6tGBc\n",
283 283 "SHdCu5JOLVh9SNjo4Z7ctTYyVKfWIOOHJqZaJpIH+O9UC1nUyhUmjaCyH/o70qVTpIhccc64eSWX\n",
284 284 "Wuc5tQCZZfFWBPJd1JIwVitWHjQ9X1kYPyROoKhFfMe6tN5rDma8ZDaO9wO4FvqE9RLHwyGyOc8s\n",
285 285 "24weAsA3ABwCcFo0SSSfDPhKk5J4CyOIG7HCy97ctTZi19+Ru1Y4VHFqzZ1Kwt0uVZif0BZE8gD/\n",
286 286 "44dBiloZYTLF2tiX4dzJUoIyrkHJJ+B5okv2eknvLfu5YKdWc1bF+7LXSZ79UOJnijSEohbxnRCi\n",
287 287 "h5aZWTKCSPKwTqrbcteqiPm17Wvm4lltbpsAaB4/BLTwCACnNxxLSJxklmUcSFkG49QyIvU2aNF6\n",
288 288 "2UnIOowD9CHo+JBEl0gdhtQpFqSohfLCpA+9WmVeI8m9WqtEA4tEp5YX8UMz0UPe8ytB1LKCVZ6o\n",
289 289 "JdmpFcr3GslAUYt4SzRJTgTwLOjegfc5Hk4bfNIsI6ejINKxotbtHWybEcTuaMOpNbQeqDJYUevu\n",
290 290 "ivcbjKiFtZO5eypMUhBaBLFsnxbATi2plBUmfZgBscxrJNlV4pVTy/SSbYM+X1gmxEj6LMxdUCvE\n",
291 291 "Wwmi1qo+rex1LkWtVU4yyUIxaQhFLeIzLwSwGcBHZuO4ap+KRKyoRacWycMKTl/NXaseFLW6o26h\n",
292 292 "eRb7d24okbkyWOGBotZqqkQPLaGJWkUF41no1JJJWWFSwkl/EVVELYmukrJOLSnvrfl4Vwj7ksZb\n",
293 293 "JBhKGGte/PAQgCMANjmc1GbV+3M/dHx5KyfcCQ+KWsRnQooeAsDnob8gLowmyRBOtEg9uhS1bKTx\n",
294 294 "nA62PXSsEHVXg21YUeuUhmMJCcYPi6lSEm/xXdhZpEr8kJ1aMikrTIYSPxTp1DKup83QrqdVXbbS\n",
295 295 "4odWhPFBhCsStSSItitFLSMauu7VWipqeTABA2kARS3iJUZh/zZzMQhRyxTdf8pcpFuLrIJOLT+x\n",
296 296 "QlQTV6kVxOjUWoPxw2KqCDqW0JxajB9uRJrwUMTQ4odSo1JFridAWPwQ+c4igKJWVfI6tQD3EcQ8\n",
297 297 "J+G+hXVIIFDUIr7yNOiTkS/NxvEXXQ+mRRhBJEVQ1PITK2q14dSiqLUG44fFMH5Ysyje09kfQ3Vq\n",
298 298 "DTV+KE3UKhJdAHmCaWlRS8Bnvmz8UIJTa1mnFiDUqWWQ+rkiDaGoRXwltOihhWXxZCVmVhw7M2GX\n",
299 299 "RfGMH7aIOUimqNUNdGoVUyd+GJqoVbpTazaO90OfrNlyad8IVdSyJ/H3564l46S/CPuc5+2L1JhU\n",
300 300 "UZ8WIO+9lStqmRlfD0HP+Lq1r0GtoEjUkjC7YJFI6HqMeeOjqBUoFLWIr1hR6z1OR9E+15jlE5yO\n",
301 301 "gkjlNOguiz2zcZx3QFkX26lFp1a7HAN9cvzQbBzn/bpdBEWtjTTu1DJiccjUiR8OuVMru56Pol5Z\n",
302 302 "UUtaRKwIexL6QO5afsQPywhDUk++yzi1pL23iuJygBwhruj5te4ol4J7kaglOX4oVSwmDQn9QI4E\n",
303 303 "SDRJLgDwGOiTmKsdD6dtvgj9ZXB+NElOKlqZDA4rNnXh0spu9ywBFvyQaMOlBVDUWkat+KH5Zf4B\n",
304 304 "6OOg4wtW9x3GD6t1agF+i3plRa190DOBbYsmyaZuh9QK9mS/6AcdH+KH9oQ6T2QR36mVs47U+OGq\n",
305 305 "uBzgj6jlOtqXfewip5bE+KHUzxVpCEUt4iMvMMv3m3L1YJiN40MArjMXH+9yLEQkNnrYRZ8WjPvr\n",
306 306 "XujYDUXV9mhb1OLsh2vUjR8Cw4kgMn5Y36kVrKi1MBOY6xP5MpQRUwA/4odFs/EBdGq1SZGzCPBH\n",
307 307 "1JLk1Crq1OrdqWUE+q3Qgv2y8Un9XJGGUNQiPvJCs3yf01F0x6fN8mKnoyAS6bIk3vJ1s3xYh48x\n",
308 308 "NKyzqsnMh9n776CTbk7d+CEwPFGrTvwwFFGrdKeWwb6fghW1DFJO5MtgRa2iCHdo8UNpMSmfnVoU\n",
309 309 "tdpBcvxwPrYVs3NS1AoUilrEK6JJshVAbC7+q8uxdMhnzJK9WmQRilp+0opTazaOH4I+INsC9wfe\n",
310 310 "zokmydHQB/YHUezeWMZQRK0m8UMfRZ1lsFNrOVJO5MswtPih1JPvKrMfSnlfhShq+VAU70J4K/ps\n",
311 311 "7VtYjwQCRS3iG0+HPlD53Gwc31a0sqfQqUVW0aeodUaHjzE02oofAuzVyjLv01rxi2wRQxG1GD9k\n",
312 312 "p9YqpJzIlyGI+KGZmKJMcbnU7p8qLjMp76sQRS0fOrVcOrVWvT+lisWkIRS1iG+EHj0EgGvN8qJo\n",
313 313 "kmx2OhIiDTq1/ISiVjc0iR4CwxG1WBRf3anls1MtdFHL9/ihFQT2z8bxkZz1pJ58V3FqSRl7SKKW\n",
314 314 "6xJ2oLhTy6WbrEh0lfq5Ig2hqEV8I3hRazaO7wFwM/QX1qMdD4fIgqKWn1DU6oZaMx9mGIqoxU6t\n",
315 315 "6p1aVhjxcWZMO+b7c9fSSDmRL0Mo8cOyjjOfO7Xo1KqPD04tH+KHFLUGBkUt4g3RJDkTOpL3IICr\n",
316 316 "HQ+na2wEkb1aJAtFLT/pQtTiDIjNZj4Ehidq1Ykf+uhUWkZVYU+a06QU0STZAn0ieQTFjiZAzol8\n",
317 317 "Gco6tUTHD1GuTwuQGz/00ak1d8flrCNFRAxJ1JLo1GKnVqBQ1CI+8XyzvMoUJoeMLYtnrxYBAEST\n",
318 318 "ZDv0yfdBAHd2+FC7zZKiVntYAarp7IfZbdCp1Tx+aMWwUNxIq2D8sHqnljSnSVnmLq2SPXPSxIc8\n",
319 319 "qjq1pL52RZ0/FqmOkjLiojSxtIxTS4JYBPhRFF/UqSUhfrhqbFI/V6QhFLWITwQfPcxApxZZ5Cyz\n",
320 320 "/FpBD0dT6NRqHytAMX7YLk3jhz6XgZcimiQK9eKHDwI4DGC7cf94SzRJtgHYCuAQit0xFmkn5WWp\n",
321 321 "0qcF+LWfZWN7ocUPpZ18lxEXpYnCVUQtl2IREEanlssxsih+oFDUIl4QTZJNWHNqDUHUolOLLNJH\n",
322 322 "9BCgqNUFbcYP7TYoajWPH9oTfx97k8qyDcAW6FLqvOjNOozLJxTRb96nVWGWTF9PfKyQE7KoFUr8\n",
323 323 "0PdOLZ/ih2VELQliEcD4YVPKdmpJ+1yRhlDUIr7wLdAncTfNxvGNrgfTA1+B/rXx9GiSnOZ6MEQE\n",
324 324 "1ql1e8ePMxe1jMuDNIdF8d3QVNQKRbTJo0700BJKBLGOU80nsSeLPSF+IHetNXzaz7Lxw/k+Cf0O\n",
325 325 "KyOwAPI7tUJ1alHUKqbo+ZQQP1z1/rRjlva5Ig2hqEV8YUjRQ/sr+efMxce5HAsRwxlm+bUuH2Q2\n",
326 326 "jh+EFlS3wf+TWecYl6ktIt+bt25JKGqtYd+fdTu1huDUqiPoWEITtcq6lwB5TpOylCnxzuKTqFXK\n",
327 327 "4TQbxzZmehTcR8mW4Xv8MFSnlgSxCPBD1Crq1JI8+6F9/ryO1ZONUNQivvACsxyEqGW4ziwpahFg\n",
328 328 "TdTanbtWOzCC2B4nAVAA7jYnW03h7Idr0KlVTJ2ZDy2hiH5WsCnrXgLkOU3KUlYwsfgkalUR7CRH\n",
329 329 "EH0XtQqdWrNxfAC6w26LkE6+kDq15qKWQydi2U4tiUXxB8xyaw9jIT1CUYuIJ5okOwA8BXrWt6sc\n",
330 330 "D6dPrFPrIqejIFKgqOUnbc58mN0OnVrs1CpDk/ihT4JHHlUjedl1pQkKRQzeqWWQPANi0Um3RWr3\n",
331 331 "T9luM0nCsHUM5fUKetGpZSYKOmguuhJmJMcPi4rirajl+nUmLUNRi/hADP1evXo2ju8vWjkgrFOL\n",
332 332 "ohYBKGr5Spt9WgBFrSxN44dDcmrVEbWkzyJXFntSXVboya4r4YS8CmV7pyxeiFrRJMlGCcvMYCnZ\n",
333 333 "qVV00m3ZDyCFduRs6nZIlajabSZBGPYpflhG9HQ91rJF8RLjh3RqBQpFLeIDzzPL9zsdRf/M44dC\n",
334 334 "y05Jv1iB6eu5a7UDRa32sOJTW6LWfPZD/l1o7NSauzmEnTS2SRPhzwvBowRDcmqVddFYfHmN5yfR\n",
335 335 "xqlShD2hdR0lW0bZbrA0s44kt1bZ95ikonufRK0yrjLXYy3bqSWxKJ6iVqBQ1CI+8FyzHJqotRu6\n",
336 336 "WPpkAGc6HgtxT59OLfsYFLWa06pTazaO90EfMG6DrBMdFzQStczJcShupFXQqUWnVh6+7GfVrjB7\n",
337 337 "Ui3xb2SVfZHYq1X2PSYlzgf41allxZYyoparsRZ1akme/ZCiVqBQ1CKiiSbJBQAugBZ3PuV4OL1i\n",
338 338 "fqVjBJHYGfRONxe/0cND0qnVHm3HDwFGEC1N44dA+L1aTUQtX1w8RdCptRpfXuOq+yXZqVUlRimx\n",
339 339 "V6vsa+HaTZSlzHMuRYTzwanlQ/ywqO+LolZgUNQi0rEurWQ2jg87HYkbOAMiAYBTof9e32VmFeoa\n",
340 340 "ilrt0aWoNdgZEKNJshlaiEqxJkzVIfReLYpa1cvTAX1ClAI42rNoaqhF8VUdaC7jT0VUcWpJivBZ\n",
341 341 "yr4Wrt1EWbyIH5pKASu25B3ruRbgyopakoviKWoFBkUtIp2hRg8tnAGRAGviUh/RQ2BN1Dojdy1S\n",
342 342 "hrZnP8xua8hOLSvW3FOyY2cVoTu1bHSwziQrocUPSzu1jFNaYvSriKoxPV8caVX3S2IXlcX3+GFZ\n",
343 343 "p5Zr4SWLF6IWgC1meajge831WCXPfigyfhhNkmOiSbKVXajdQVGLiMX8OnqZuXiFy7E4hE4tAqyJ\n",
344 344 "S32UxGcfh06t5tCp1Q1tRA+B8J1aVtCpI2r54uIpoo5TK7u+JEGhiNCdWmX3S7JTq078UNJ7sKpT\n",
345 345 "i6JWecpED7O3uy6KXzVOCfHDIlGr77F9Evr5+qaeH3cwUNQiknkCtBNhF4Cb3A7FGdapxRkQh02f\n",
346 346 "JfFARtTi+64xbc9+COiOQWBN2BkiTWc+tAzFqVWlT8oyWKfWwvrSBZ8sVWN6vuzj0J1aIvYjmiRb\n",
347 347 "AGyCdhIdLFhdUvywSk+Vy/FWFbV6H6s5JiwqiufshxuxLrw+KkQGCUUtIpl59NBEAQbHbBzfCeAO\n",
348 348 "6JOKcxwPh7ijV1FrNo7vhz6YPhrhnuz3hRVf9uauVQ3rTjopd62waUvUGopTq46o5YvgUcSQnFq1\n",
349 349 "i+KF/4BRdb8kO7V87tSq8lnyLX4oYbz2sYuED5djtWLQwZyuYwnxw1WvtStRq0xXGmkARS0imeeZ\n",
350 350 "5VCjh5YvmOVjnI6CuKTvTi1Ai6mALqkn9WlLfMliRa0hO7Xaih8Oxak15PjhEJ1apcQfc1K6H0DW\n",
351 351 "fSGRukXxIhxOC/jcqVVl7K4jcll8iR9a4UNy/FC6QGgfU6qoVeRwJDWhqEVEEk2S7QCeAT37UOJ4\n",
352 352 "OK653iwpag2Xvju1AIpabUFRqxuss6rJzIcAnVp5hBI/HKJTq6z4A/gh3tWNH0oU6nzu1KryWZIQ\n",
353 353 "57P9vFugzyfyBAUJopYPnVpFolH2NhevfZEjav/Cen1Bp1bHUNQiUnkG9B/OT5kI3pCxotZjnY6C\n",
354 354 "uKTvTi0AsJ+703p8zKAwcR4rajV1FGWxAtmQRS3rrGoqatGptRofxI4y0KmVjw/7WbcoPhSnlpT9\n",
355 355 "qDJ2CXG+7OM/VFBlIkGE80HUKurTyt4mTtQy7tQjAI4ygmdfsFOrYyhqEanYPq2hRw8Bxg+JW1GL\n",
356 356 "Tq36HAddqvvgbBy3eSDDTq32RC3r1ApV1KJTq75Tyz5nUlwyZaBTa/16Ep1aQ+nUkuB8Aso74ySI\n",
357 357 "cGXdPC5FoypRzq0OuvrKPIcuIoiMH3YMRS0ilXlJvNNRyIDxQ+KiU4uiVnO6iB4CjB8C7YtaoccP\n",
358 358 "6dSqHz/0af9DdWpVFbUkF8XbMYXeqSXlNSgras2FDoeTJpR1arkU4AqfT+OIcyVqShe16NTqCIpa\n",
359 359 "RBzRJDkVwBOh/yB+xPFwJHAL9AHEmdEkGfJJ7CCJJslWAKcAOAzgrh4fmp1azeli5kOAohbA+GEh\n",
360 360 "5sTMuqw4++Gw4oehObWqinV2/6XE9rIUzc6WRZqo5bNTK1como3jI1hz0fTdt2TxIX5YplMLcOcm\n",
361 361 "KxPzs7f18vyZmKMCcCRnxkjSEIpaRCIx9If/6tk4rnJgFiTmi/aL5iLdWsPjdLO8o+cvQ3ZqNacr\n",
362 362 "pxY7tejUKsNW6Pjrwdk4rhN5mDuVokni8/HiEIvi6dTSuHYJLWMonVoSOqqA8iIM4H7Mdqxl44dS\n",
363 363 "O7UAd24yiU4turR6wOeDFBIul5nllU5HIQuWxQ8XF31aAOOHbdB1/JCdWnRq5dGkJN4W6kp2vJSF\n",
364 364 "RfH5+LCfVcU6yUXxVeKHPndqSeioAqrNNul6zFb8kOzUqtpR1rdAKFnUYp9Wh1DUIhJ5jlkmTkch\n",
365 365 "C/ZqDRcXfVoARa026LxTy2H3h2vo1CqmSUm8xeuyeOMwq3JSm8Urp5b5W9CkKF7yflaNVfpQFO9j\n",
366 366 "/LCOU8snUcv1mKvGD6UWxQPuxlhG1JoX2Xc8FgudWj1AUYuIIpokZwN4JPSJyjWOhyMJzoA4XOjU\n",
367 367 "8pdORC0zk+JD0NEyKSc7fUOnVjGNnFoGH1w8ecydJSbKXwXf9n0bdHXDgYpRdR/2s278UJRTq4bw\n",
368 368 "KFXU8iHKZwlR1HLpKCsb5+x9jObzZTu18lxRfTu1yvR8kYZQ1CLSsC6tD8/G8SGnI5EF44fDxTq1\n",
369 369 "vtHz47Iovjknm2XbTq3sNofaq0WnVjFtOLXsfb10aqF+n1b2PlIEhSLquLQAP0StukXxrgWVRbZA\n",
370 370 "n3sdKnmMK61Tq6zoAriP8lnqiFqu3jdlHT0S4ocS3WRzQcvMwLgKxg8DhKIWkYYVta5yOgp53AAg\n",
371 371 "BXChmQ2PDAdbFN+3qLUX+j23w8zcQqrTVfwQ4AyIbYla8xP6AN/nbcYPJQseeTR5DnwQe7LUFfB8\n",
372 372 "6E0LwqmFan1awNp+SBFWq4harl1PFp86tXyY/VByp1ZZ8YhF8QFCUYtIg31aS5iN44cA7IKOG13g\n",
373 373 "djSkZ+zsg72KWuZX5L3QcZYdfT52QFhRa28H2x56WXwropaJpNlt+OpGWgXjh8NyalXtnbJIFYCy\n",
374 374 "VBW1pDq1qsT3suu5FoYsdUQt169BWWdRdh1fRC3JnVou3rtlxSN7e19jY/ywByhqETFEk2QngPOh\n",
375 375 "XQ2fcTsakdxglo90OgrSN9apdUfuWt3AXq1m0KnVHW05tbLbCK1Xa/BF8RiWU6vqDIEWqQJQlqri\n",
376 376 "pKuZ14qoKs65FlkWGUr80LWoJTl+WLZTy4XwVlXUolMrIChqEUlYl9YHK5acDoUvmeWjnI6C9I0T\n",
377 377 "p5aBolYzuhS1BtupFU2SbdC/fB5CuZOrIkLt1aJTqx2nli/7XndfQ3ZqSdunqvFD1yLLIj7GD8uK\n",
378 378 "MMATeUgAACAASURBVIB7d5kVPyQXxZd1vrmMH0oVtdip1SEUtYgk2KeVj3VqUdQaFi6dWvYxT8td\n",
379 379 "i6yCTq1umLu0Cspgy0Kn1mpCKYpv4tTyJX5YtyjeJ6dW1S4qaftUNX7oWmRZxOf4ITu12iGE+KF9\n",
380 380 "/jj7YUBQ1CIiMNOwUtTKxzq1GD8cCOZzYQUlxg/9ow9Ra4idWm1GDwE6tfIIpSi+jlPLN5faEJxa\n",
381 381 "VeOH2833qBTqFt67djtZGD/slpBELZezH0p1alHU6hCKWkQKFwI4B8BdAK5zPBap0Kk1PE4CsBna\n",
382 382 "kVL2l902oajVDDq1uqFtUYtOrdX4Juws0sSpNZSieB+cWpXEIDMBRN8nrmUYUqeWlLH7JGpVdRq5\n",
383 383 "+MyWjXMyfrgG44c9QFGLSMG6tD5gDkbIRm6B/oN4djRJfD3BINVw2acFUNSqTTRJjsKaqHVP3ro1\n",
384 384 "GWynFujUKguL4ofl1KpbFC/aqWWcVnUEO4n7VbdTS4rgGHr80LWoVfb59alTS2L8kE6tAKGoRaTA\n",
385 385 "6GEBs3F8CMCXzcVHuBwL6Q2XfVrZx2WnVnWOB6CgXXaHOtg+nVp0ahXBovhmTi0rPBwjLMK2irrx\n",
386 386 "Q+lOra3Qf0sPVvxbKnG/6nZqbRPyHvQ5flhlzK7eM4wfNqOqqNXX88dOrR6gqEWcs9Cnlbgciwew\n",
387 387 "V2tY0KnlL11GDwF2agF0ahXBovgGTi0zC7NEt88q6hbFuz6RL6Lpfkl67arGKA9Dz/IKrJ0Yu4RO\n",
388 388 "rW4JSdRi/HANxg97gKIWkcBjAJwBYDeA6x2PRTrs1RoWrp1aFLXq05eoNWSn1r25a5WHTq3V+F4U\n",
389 389 "38SpBfjVq9XUqSVJ/MkSkgOtavwQcC+0ZGGnVrdU7dRyMc6qnVqMHzJ+2AsUtYgEsn1abUzPHjIU\n",
390 390 "tYYFnVr+0rWoxU4tOrWKYFF8s04twK/9p1NrPRL3q86+SNqPOqLWVsfRybIiDOBe1Krq1HLxnigb\n",
391 391 "53QZPyxyRM3fmx2OJQvjhz1AUYtIgH1a5WH8cFhIcWqxU6s6dGp1R1edWqGJWtapNeSi+LouHwud\n",
392 392 "Wu6pO6uj5PhhldmMXQstWUqLWuZH6r67i5ZRx6klvVNLQlE844floVOrByhqEaeYGcIuNRcpahVD\n",
393 393 "p9awcO3Uuhf6F69jo0ki6cTAB9ip1R1diVq+CjersO6iIRfFN3Wr+bT/TcUfCU6gZdSd1ZHxw/ap\n",
394 394 "4tTKrueLqOW63N6H+GFVUYvxQ3Zq9QJFLeKax0FHm74K4EbHY/GB26EP7E6NJsnJrgdDOseKWk6c\n",
395 395 "WuaXVuvWOsXFGDzGfj67ErXmkTnz48CQaFvU8km4qEIbTi3fi+Lbcmr58N5oKv5I/eFisEXxBtfu\n",
396 396 "oSxVRS3XIhHgV6dW2ef3EIAUwKZokmzqdkgbKBvn9GH2Q8YPA2JoB8JEHvPoIfu0ijHPESOIw8HG\n",
397 397 "D105tQD2atXFOqj2drFxM7X9/dBT3fsqONSlbVHL9zL0VbTh1PL9uWlaFG/vF3L8cH7y6bj7aBUh\n",
398 398 "FcXXiR9KEIYsVfqpABmCXNkOqOw6okUtcy7gaqz28YoEGhcO0LLiUd+xWMYPe4CiFnEN+7Sq82Wz\n",
399 399 "vNDpKEgfOHVqGfaY5Q6HY/CRruOHwHB7tbpyaoUmDrIovnlRvI9OrUqOptk4Pgwdi1Hoz7lQBTq1\n",
400 400 "NJJErVDjh65FuDpF/H2P1f6NKFsUz/gh44e9QFGLOMNYZp9tLiYux+IZFLUGgImUUdTylz5FraH1\n",
401 401 "ajF+WID5fj0aOqJSVQzIEkpRPJ1a+Uh0NVnqdoVJ3KehdWpJcJmF2KkFuBtrWYHG3r4ld612kS5q\n",
402 402 "0anVIRS1iEsuhu6d2TUbx7scj8UnKGoNg5MAbAJwz2wcu/wipKhVDzq1uqOr+KGvws0y5i6tJtF+\n",
403 403 "87fnEIDN0SSR6OIpoqlTyyfBs66jCZDparLU7QqTuE91XiNJRf51nVoS4ochdWpl13ElakkTjrKP\n",
404 404 "JW1s7NTqAYpaxCWMHtbDFupT1AobCX1aAHCXWVLUqkYfopbdNkWtZvgkXJSljZJ4i8/xzKZOLSuk\n",
405 405 "0KnljqbxQ0n7VKdTy7XQAgAwfWtVHScSxl6lB8z1eH0Qtar2Vkl0atnnjvHDgKCoRVxCUasedGoN\n",
406 406 "AwnRQ2DNqcXZD6tBp1Z3tC1qzXuTAppJso2SeIvPZfFDcmrVjekBMl1NFsYPNa7jh3PBoIL703Wc\n",
407 407 "D/CrU6uKaOjaqVU2fkinFuOHvRDKwRvxjGiSbAbwLHORolY1boX+sjgrmiQ+/HpM6iHFqcX4YT2s\n",
408 408 "0HRP7lrNYKdWC5iibHuSKfGkvg6Dd2oZZ0kT91L2fj5819aN6QEyBSBLHSEIkCnUNSmKd/3aVI0e\n",
409 409 "Ztf1JX7oWoSr8hy7ciJKFY6yjyVtbIwf9gBFLeKKS6BPTG6cjePbXA/GJ8wJ2C5z8QKHQyHdIs2p\n",
410 410 "RVGrGn2KWoNxahmhwoorbbiQLD45csrQplPL1+dmK3Qv4cHZOK4b+/Bp9sMmAp5EAchSR0wBZAp1\n",
411 411 "deKHroUWS53XwenYzfeFff0lR/rsWEXHD80YrUAjuSi+aGxWXOrruaNTqwcoahFXMHrYDEYQw4dO\n",
412 412 "LU8xB34nmIttReSWca9ZHp+7VlgcA33ssm82jg+1uN3QyuLnRfEtbMvX+GHTPi1ApjCyiiZF8ZL3\n",
413 413 "s4rTJotEoc7n+KGPTq0tABSAQ+YH4SJcPtdW/Dk0G8dHSqzvYqybzfJwiTHSqbUGO7V6gKIWcYUV\n",
414 414 "tRKno/AXlsWHj3Vq3el0FBS16rAd2iHyUMczV1rBbEiiVtt9WhZf3UirGHz8EM2jh4AnsVTTBVdX\n",
415 415 "/MneR+J+hujUGpqo5WrsVT8TLkU4H0r4q4xRclE8O7UChKIW6R0zLfgzzcUPOByKz9CpFT6nmiXj\n",
416 416 "h/7RR/QQoKjVJqE6tYYcP2zDrSZZ7MkyP3kv6fJYRKIAZAnRqVUnfuj6tfEufojqz7fL8VZ9fl0I\n",
417 417 "cFW6oVgUvwY7tXqAohZxQQT9C+oXZuN4t+vBeApFrfCxsw26dmrdZZYUtcpjo4f35q7VHLv9E3LX\n",
418 418 "Cgs6tcrRplPLOp0kiQNlaNOp5VpQKKLpvkoUgCx1nVpSxKAsPrqdLD7GD+2Yqzq1fBC1XAhwdZxa\n",
419 419 "fYpaZcUj+xwzfhgQFLWIC9in1Rwraj3C6ShIl1inlmtRax/0AcDRnG2zNH2JWnRqtYevvVGraNOp\n",
420 420 "5dMMgFnacGp5ET9Ec1FLsnhX16kl8bUbqqjl2qlV1f3kYrw+xQ/LiDOMH67B+GEPUNQiLqCo1Zyb\n",
421 421 "zfLh0STZnLsm8RURotZsHKdgBLEqjB92R9dOrVDih206taw44Juo1YZTS7KDKUuTknhA9n4O3akl\n",
422 422 "ZT98jB9aMaGyqGUmfOmTuvFDqU4txg/XYPywByhqkV6JJsk2AE83Fz/gcCheMxvH+wDcBj0TyXmO\n",
423 423 "h0O6QYSoZaCoVQ3GD7uD8cNydOHUkih45MH4YXkk72dTp5aIfYomySboCURSAGVm4rO4djtZfI4f\n",
424 424 "lhITzIy6h6HPj/v+wdgHUatOp9bmHgVCqaIW44c9QFGL9M1Tob/cPjsbxxJO1n2GvVqBYmJ+26EP\n",
425 425 "4puckLUFRa1qMH7YHSyKL0cb0TuLr/HDpu6l7H2lC3p0am1E2j7N98M4oMsSgqjl2qlVxSHjasw+\n",
426 426 "FMWXFmfMe/yQudhXBLGqqNXXa8z4YQ9Q1CJ9w+hhe9xkluc7HQXpgrlLq+LBb1dQ1KoG44fdYUWn\n",
427 427 "NhxIWUJzanURP5QiDpSlDVFLmjCyiraK4kW4mhYIwqmF+uKca7eTpWo/FSAnfuiDqFV1rNKL4rPr\n",
428 428 "SeuuYvwwQChqkb6xolbidBRhYHu1LnA6CtIFVtS6K3et/uAMiNXo3anloP/DFW3G6rKE5tSyIged\n",
429 429 "WtXFkCzShJFV1BV+LJL3s+oMdhZpgmRTx5nPTi1X76uqnVrZdX1xakmNH2bXk+rU2trTsROdWj1A\n",
430 430 "UYv0holUPQ26T+BDjocTAlbUolMrPCT1aQF0alWlF1HL9H/sg/4u901wqEubDqQsoTm12uiTsvha\n",
431 431 "FD+k+KEVDUKMH9ZxCAHy3GdNnVo+i1o+ObVcvW98ELWqdkP1XRZfanyzcXwEa9HIPrrT2KnVAxS1\n",
432 432 "SJ88HVqt/9RsHO91PZgAoKgVLlJFrVOcjsIf+oofAsOLILbZFZUlNFGrDUHH4mtRfFOhB5At9mSh\n",
433 433 "U2sj0gTJIYparl1mIccPpc9+mF1PWvwwu04fY6NTqwcoapE+YZ9Wu1DUChepohadWuXoK36YfYyh\n",
434 434 "zIDYVadWqPHDNpxavscPm4haB6Dd5ZujSdL3bGhVaCpqSRbvQnFq1YnCAXL2w+f4oQ+ilg9F8VXj\n",
435 435 "h9aZJC1+mF2nD1GLnVo9QFGL9AlFrXbZDf2ldmo0SUI5ESMailp+06eoRadWO4Tm1OoifihR8Mij\n",
436 436 "caeWmahDsovJQqfWArNxfBDAYQCboknS10l1HkN0arkee8iiFoviNyJV1GL8sAcoapFeMKJLBH2A\n",
437 437 "8WHHwwkCkwnfZS7SrRUWNuZHUctPGD/sDhbFl4NOrfYimJJdTBY6tZYjxeUEDFPUcv38NxG12Km1\n",
438 438 "kariTN9F8VUcUXadPp4/xg97gKIW6YtnQJfxXTMbx324F4YCI4hhIs2pxdkPq8H4YXewKL4cLIpv\n",
439 439 "T9SS7GKyNBF+AKH7aGYmqysGAbL2q6mo5XoffHRq2cetUxQvvVOrb8EIqD5GV0XxYpxa5m+YfY3o\n",
440 440 "1OoQilqkLxg97IabzJKiVlhYUeuu3LX6g06tajB+2B1dxw/p1NrIkIvis/eXvP+hOrXmzhDjTq+K\n",
441 441 "pP2qK2q5Llu3+ChqhRw/7FswAqp3QzF+CGwCoAAcno3jwx0/1qChqEX6IjbLxOkowoNOrTCR5tTi\n",
442 442 "7IfVYPywO7ouig/FqdXF7IdDdWpJEkZWEWqnVt2ZDy2u429ZGD/sn5BFrb4Fo+xjSY0fVnm97fPc\n",
443 443 "9fPHPq2eoKhFOieaJCcCuAT6A/0Rx8MJDStqXeB0FKRtpIlaD0B/frdHk0TyiZ1zjNXcOrXuy1u3\n",
444 444 "JYYWP2RRfAGmFHszdIdlGwfSPjiVltG4KN4gVfDJEqpTq61YpYT9GqKo5XrsdWacdBX3rBvtY/wQ\n",
445 445 "82OvKgJSX6IgZz7sCYpapA+eBf1e+8RsHLd9IjJ06NQKDPPFLCp+aGYAs26tk12OxQOOhbaaPzAb\n",
446 446 "x4d6eLyhObW6ErVCKoqfRw/NZ7cpQ3dqSRJGVkGn1nJcO4Wy1Ol3AuTsg8+ilg+dWj44terGD/sQ\n",
447 447 "3qrG/Pp6/lgS3xMUtUgfsE+rO+ailhFDiP8cB/0l+OBsHLfRh9MW7NUqh40e9jUhxtBErU7ih7Nx\n",
448 448 "fADAIQCbo0nS50lCF7TZpwXok6wUwNZokmxqaZt9wPhheaTuI51aGWHI8XEe44fdUlfUcuHUKusA\n",
449 449 "7rP3q240kvHDQKCoRfqAolZHzMbxXujenmOx5u4hfiMtemjhDIjl6LMkPvs4wccPjdi0GcAhI0K1\n",
450 450 "TShl8a2KWsbtJUkcKEvbRfGunTJ5tCVqSdvHEJ1alUQt4zo5DO1C2dz2oCowFKeWL6KWi6L4ujM0\n",
451 451 "9ilqVR1b168znVo9QVGLdEo0SXYAuBj6w/wxx8MJFUYQw0KqqLXXLClq5WPFpT5K4oFhObW6Kom3\n",
452 452 "hFIW32ZJvMXHCGLbnVqSBb224ofbhbm+mzq1XIsqWeo6tbL3cSnODU3Ukt6pxfjheqQ+f+zU6gmK\n",
453 453 "WqRrng3969LHZuO4zQNssgZFrbCQLmqd5HQU8mH8sDu66tOy0Km1Gh+EnUWGFD9s5Ggy/X+Hoc8L\n",
454 454 "XLqBFmnq1HItqmRpImq56nnKUmf8c1EjmiQuzjlD7tRiUfx6pIpajB/2BEUt0jWxWTJ62B1W1Nrp\n",
455 455 "chCkNUSVxGe42yxZFJ8P44fd0bWoFYpTqwtRy2enFuOH5ZAoXNKptf4+XolaJrrscux1RC0XXVWA\n",
456 456 "H0XxUnurso9R9rW2zzOL4gOBohbpGtunlTgdRdjcYpbnOR0FaYtTzFKqU4uiVj6MH3ZH1/FDK5ZR\n",
457 457 "1NqIRMGjCM5+WA1J/VMWOrXW38crUWthfRdjrzPjpAuxKPt4EqN9FsljrBuNZPwwEChqkc6IJsnp\n",
458 458 "AB4HfUD4CcfDCZmvmOXDnY6CtIXU+KF1ajF+mA/jh93B+GE5Bu/UMr1QbQg92fuHLmpJFO9CcmrZ\n",
459 459 "k+cm8UPfOrUAt2Ov45JxUcAO+FEUX1WgYfyQTq3eoKhFuuRSs/zIbBzXPSAhxdCpFRZSRS06tcrB\n",
460 460 "+GF3sCi+HIMXtZBxaMzG8ZGG2xpK/FCCcLIInVrr70OnVjXqCImunFp144cunFpV44dDLopnp1ZP\n",
461 461 "UNQiXWKjh+zT6hY6tcJCeqcWnVr5OIsfCpu1rAvo1CpHF7MfSnTx5NHmc+DDvtOptRx74kpRqzlD\n",
462 462 "cWr5Imq5cGqFWBTf9WeK8cOeoKhFuoSiVj/sgf4V/YRoklBw8B/bqSVN1KJTqxy9xg9n4/gA9MHS\n",
463 463 "Zsg4cesSFsWXg06tdkUtn+KHTVzxdGp1SxuzH/oYP5Tg1PKhKF6q0yiL1N6q7GNIGxvjhz1BUYt0\n",
464 464 "QjRJzgLwaOiTj086Hk7QmNllrFuLEUT/kS5qUTjNp+/4YfaxQo8g9lUU77tTi0Xxayf/bTq1JIk9\n",
465 465 "i9CptZxQRC0J+zE0UUu6U+swgBTAUdEk2dTNkDbA+GF1GD/sCYpapCsuNcsPz8YxP8jdwwhiOOww\n",
466 466 "S2milo0f0qmVT9/xQ2A4ZfF9xQ/p1NqIr06tpiXxgEyxZxF2ai1HghhkqTMTn0XCfjQVtXyJH3pR\n",
467 467 "FG9+0LZj7ctV5kP8sOw5p32e6dQKBIpapCtis2T0sB9YFh8O0p1aFLXy6Xv2Q2A4opZ1UDF+mA9F\n",
468 468 "rQHFD6NJshk6fpw9ya2DRPGuqVgnQQyytOHU8jl+2HecD/DLqeVDVLJu/HDITi12avUERS3SFbZP\n",
469 469 "K3E6iuFAp1YARJPkGOiD1gNo94S0DR6AtrtvjyaJhBMEqTB+2B1WbGL8MB8WxXdTFC/JwZRl7mYy\n",
470 470 "7o26SHZqDT1+aF8bJ/thhNOjAByZjeNDFe/uSiTKPqZkochS5/3Rt6vMB6eWNFGL8cOeoKhFWiea\n",
471 471 "JOcBuAA6fvMpx8MZCnRqhcE8etjw5KR1zHjYq1WMdWoxftg+LIovB51aw5r9sI3oISBTvKNTa/19\n",
472 472 "XO1Hk7G7FLXqRD596dQC+h9r3U4tilp0anUORS3SBdal9aHZOD7sdCTDgU6tMJAaPbRQ1CrGuqXu\n",
473 473 "y12rXYYiarEovhwsiu+mKF7qvrclakmMWdKptf4+FLWqYR9TsvvJ0sSpxfih3JkZGT/sCYpapAus\n",
474 474 "qMU+rf6wTi2KWn5jRa09TkexGpbF5xBNEoU1QaRPUWto8UM6tfKhU6vdoniJsbwsTcvULRL3k04t\n",
475 475 "jevXxndRywenlg9jDTF+2PXfBjq1eoKiFmkVc1JHUat/vgrgCIAz2XfkNb44tShqLedYAArAgz27\n",
476 476 "VIfm1Op69kM6tTbiq6hFp1Z5JO5nW04tF4LKInRq9Y+PnVqSx8r4YXXYqdUTFLVI25wP3eu0B8C1\n",
477 477 "jscyGExx51fNxXNcjoU0Yt6p5XQUq7FOLcYPl+Mieph9vNBFra6L4q1wI+mkvg6MH1LUqoNrN9Ay\n",
478 478 "6NRafx+KWtXwwf2EaJJsgv5BLK1YxC+9KJ6zH9Kp1RsUtUjbxGb5wdk4PuJ0JMPD9mqxLN5fpMcP\n",
479 479 "6dTKx4pKfc58CKyJWowfNsM3N9Iqupj90Lfnps3nQKLYkyVkp5bdN3ZqaRg/rEYdQcFFp5YVfaq6\n",
480 480 "efp+bqv2Q0mOH/bl4mSnVk9Q1CJtY0WtK52OYpiwV8t/fIkf0qm1HCtquXJq+R6bK6LronjfhJtV\n",
481 481 "0KnVntADyN/3IRTFD92pZfefTq2SRJPkKACbzcUq7icX463r5um7KL5u/JBOLcYPO4eiFmkN06dl\n",
482 482 "Ra3E5VgGCp1a/uNL/JBOreW4ErWsyBO6qEWnVjnYqdWNU2u7Oc6RRluiliQByBKSU6vOTHwW1/vh\n",
483 483 "naiFjENmNo7TCvdz0anli1MrpKL4vsbG+GFPUNQibfJYAA8DsBvA9Y7HMkSsqEWnlr/QqeU3FLW6\n",
484 484 "pa+ieM5+uJHBilpm0gd7AiRBHFmkqfBjce0GWgadWuvvQ1GrPHXFBBfjbSpq9SXAVY3SuSiKL/sc\n",
485 485 "9uVyY/ywJyhqkTaZu7Qq/ipC2sHGD+nU8hfpnVp0auXjuig+WFHLREmsUNGmWJPlIIDDADZHk6Tv\n",
486 486 "ma/ahPHD9nvF7HYk9mrRqbUaEftkisA3AUih/8ZUxXWvG0Wtbqkrarkqig8hftiXqEWnVk9sLl6l\n",
487 487 "G0aj0WYAvwjgRwGcDeDrAN4F4Nen02nur7Cj0ehS5MfbTppOp30X9RJGD11Dp5b/SI8fsig+Hzq1\n",
488 488 "umMu1HQ1CclsHKfRJHkQ+nU8BsA9XTxOlxgxbjOAI2i3w2OwTq3Mdk4w2727YN2+CVnUCsWpNReF\n",
489 489 "av7o63o/fBS16o7Zx6L4zkUjE72uOk4f4od9iVrs1OoYl06t/wPglwD8KYDvAfA/APwwgPeORqNN\n",
490 490 "JbfxCgCXLvnXVTSBrMD8CnWpuUhRyw1zp5ZxNRD/YPzQb1zNfjgEUavr6KHFN/FmkbmbrWXHtG9O\n",
491 491 "rTaL4rPbkbj/bYtaktxoQTi10EwUyt6PolZ5mpavb+2xQ6/xWFscyyrmpfsVfliiU4vxw95w4tQa\n",
492 492 "jUbfA+B7ATx/Op1eYa5+32g0ugLAfwD4KQD/s8SmPjmdTq/taJikGhdDuzd2zcbxza4HM0Rm4/j+\n",
493 493 "aJLsgXb7nAbtfiSeYA6erFOL8UM/oVOrO2zPVVczH1p8F7W6iB5mt3dMNEmUBxUDjB9Wh51a3dFU\n",
494 494 "1GL8sDq1hKLZOD4cTZLD0HHRTag2c2JdfCiKr/N89im6VRWPGD8MDFdujlcBuCojaAEAptPpFwD8\n",
495 495 "XwCvdjIq0gRGD2Vg3VqMIPrHidAHUPfPxrHULz86tfKhqNUddGqVoxNRazaOD0Kf3G1Cv7OC1aUr\n",
496 496 "UWsITi3XAlAWOrXW349OrfI0ERP6HrP4+CHqxegki26MHwZG76KW6dL6VgD/vGKVfwHw2NFodGqJ\n",
497 497 "zUmcWnmoUNSSge3VYlm8f0jv0wLWOoZOYsR1KRS1uoNOrXJ05dQCZAs7i7Qtag0pfuhaAMrSyKk1\n",
498 498 "G8eHoPvljoomibMeYVDUAvwStfru1fKhKL7O88n4IZ1aveHipORM6IOu61fc/kWzvLDEtt4xGo3u\n",
499 499 "HY1G949Gow+MRqPntjJCUglTTPssc/Eql2MhdGp5jPQ+LXuCcB/0DwonFKw+RJzMfmicfQcBbIkm\n",
500 500 "Sd8nDn1hRa2unVp2+8fmriWXLmeI9EnwY/ywOqI6tUwkv6lTK3tfl2IdRS2/RC06tTZSpxtKsuhm\n",
501 501 "Y6Xs1AoEF6KWdSOsmj3GXn/KitsBPSXuNQDeBl0y/1PQb+Z/HY1GP9DGIEklIugTgOtn4/h214MZ\n",
502 502 "OHRq+Yv9mye1T8vCCOJqXBXFA2sOpuNz1/IXxg/LYcfdlpiTxSenVttF8ZL3vWnvlEVap9b8RL/h\n",
503 503 "jKeuBaHsYw+5U6vv578NUauvqLUPRfGhxg+7dnAyftgTLqy49oB71QGXPaA8MWcbH5lOp1H2itFo\n",
504 504 "9H8AXAngraPR6D3T6dTFScVQYfRQDlbUolPLP3yIHwL6h4fzYCaGcDsUcbiKHwJa1DoZWvyR/h6q\n",
505 505 "A+OH5egyfujTc8P4YXUkiD9Z2nBpZe/vs6jleh/o1OqWUIviGT9k/LA3XDi17MH+qgMDe7B0z4rb\n",
506 506 "MZ1ON8xEMZ1ODwP4Bej4x3c2GSCpDEUtOdj4IZ1a/iE+fmigU2s1rkUtINxeLTq1ykFRS8P4YXVc\n",
507 507 "CyeLtOVAc+UUytJU1HIlDFns4w5F1PKtU0tk/HA2jg9Dp6uOiibJpk5GtYZUUYvxw55wIWrZaM2q\n",
508 508 "EyLr0Kp8YjedTq+BdhE8usa4SA2iSbIdwNOh/2h9wO1oCOjU8hlf4oc2In6y01HIxKWoZR8zVFGL\n",
509 509 "Tq1ysChew9kPqyOqUwt0amWRImrViVC5FrV8EOJ8cmpJ7f2qOj46tQLDhaj1NeiDg8esuN1ef1PN\n",
510 510 "7R8AcLjmfUl1ngb9Zf3p2TiW7jAZAndAf4HviCZJqCe3oeKbU4ui1kacFMUbQndq9VUUT1FrNT49\n",
511 511 "N1Z8aqtTawjxQ2mdWm05tShqNcenKJ/FPuc+dGr5UBQvvfer0vgyLjLVsYuMnVo90buoZaKDVwN4\n",
512 512 "8YpVvg3AF6bT6R2rtjEajU4ZjUYbTqhGo9EjAZwO4Lo2xkpKweihIEyZKiOIfuJTpxaQ33s4VCQU\n",
513 513 "xYcqavUVP+Tsh6uR7FaaszBrHuOH5ZkXJ0eTxMWP3ouE5NRq4hrK3s+VqNUkQuXaqeXDmKULRkD9\n",
514 514 "90Bfz2Wd57APtxbjhz3h6kvr7QCeMxqNLsteORqNHgvgZeZ2e92Jo9Foe+byaQC+DOAtC/fdDOD3\n",
515 515 "AOwG8E/dDZ0sQFFLHlbUYgTRL3xxatm+Q4paGaJJsg364OXgbBw3PQmrQ+iilnUH0amVT5ezH/ry\n",
516 516 "3GwFoKA/i2059yULeq2IP7NxnEKGAGQJ0alV98R2Ll4Y0bZvfI4fhtyp5YNTq+/4oTRRi/HDnnAx\n",
517 517 "+yGm0+nfjUajdwN492g0+m0AnwHwCAC/DOAaAH8IAKPR6FjoGOIdMLHE6XR6x2g0+kMAvzwajY4H\n",
518 518 "8A7o/fgZAE8E8J3T6bQtuznJIZokxwN4MnTc88OOh0PWsL1adGr5hXVq+dKpxaL49bjs0wKGI2p1\n",
519 519 "4UDK4otwswrGD9vv0wKGET8EtAC0zWyzC2G0CiEV4DeKH87G8eFokhwGsMn82zBhVsf45Hqy+DTm\n",
520 520 "pkXxkju1+hpjneewT1GL8cOOcWkvfhmANwP4cQDvBvDzAP4KwAvMTIaAfgN8DWvOEwDAdDr9FQAv\n",
521 521 "B3A2gL8E8DYAXwfwtOl0ekUvoycA8EzoL9dPzMaxqxM5shE6tfzERqr35q7lHjq1lkNRq1tsaKLz\n",
522 522 "VAAAIABJREFUHJCiVj59FMVLf266ELWGED/MbkOSUyuE+GEb++JyFkfGD7vFp6L4kJxaVhymqBUA\n",
523 523 "TpxawLxb603m36p1DgC4aMVtfwktaBF3MHooEzq1/MQ3UYtOrfVQ1OoWxg/L0YeoJVHYydJ2STzg\n",
524 524 "R/ywLacWIEPUolNrPQeg339b0f3fwUV8EogsbYyZRfFr1BU2fXBqdamH2G0zftgxEoogib/YTjSK\n",
525 525 "WrK4zSzPcToKUhrTkWFForvz1hUAi+KX43LmQ2A4ohadWvl0WRRvxQXpolbbJfHAsOKHgAxRq22n\n",
526 526 "lquSdaBdp5aL/RhapxaL4jdS9z3Q13NpxaMq0dw+i+L7jgwPDopapBbRJDkFwBOgv6A/5ng4ZD1W\n",
527 527 "1Drb6ShIFY6HjvI+OBvH0n/NoVNrOS5nPgTWRK3jc9fyFxs/pFMrny6L4iW7lbJ0GT+UuO9diFoS\n",
528 528 "hEs6tdbjUpzzSSCyNJlxkkXxG5EePxTXqWVmkbVaS1uTlpAVUNQidbnULD86G8euy0TJer5qluc4\n",
529 529 "miWHVMcKRNKjhwCdWqtg/LBb+nJqWdHs2Ny15NLl8yTZrZSly6J4CQ6mRdiplU8oopZLpxY7tbrF\n",
530 530 "h6L4kOOHXQluc/eYmV2WdAhFLVIX9mkJxZT23wN9oLujYHUiA1/6tAA6tVbhWtSyjxuqqEWnVjn6\n",
531 531 "cGpJcPHk0UWnliSxZxE7ptDih3RqrcdlUbyP8UP7PA2hU2vQ8cMGjqiuRa26ryupAUUtUpfnmiVF\n",
532 532 "LZmwV8svfBS1TqQTcB2uRS06tdrBd1Gry04tyRG8LF10akmK5c0xf4PbcjRltyFB1KJTaz0SOrXq\n",
533 533 "CESHAaQAjoomyab2hlTIEJxajB+u3/bBio6o3pxaHW2fZKCoRSoTTZLzADwKujvmE46HQ5ZDUcsv\n",
534 534 "vBG1ZuP4IPQJ81EIV0CpA4viu4WiVjnajKIt4ktRfJfxQ2n7PhdLWoq3SBLv6NRaj5fxQ/O+dDH2\n",
535 535 "JqJW351aPhTFS44fNo1v0qkVABS1SB2sS+uq2Tim+iwTilp+4Y2oZWCv1kakFMUHJ2oZNwrjh+Xo\n",
536 536 "QtCx+OLUGlKnVtsipqT9pFNrPb4WxWfv54uoRafWRrxwalW8H51aAUFRi9TheWZ5hdNRkDzmZfFO\n",
537 537 "R0HK4puoxV6tjTB+2B1boGcHPWScgl3iu6hFp1Y3nVqSHExZ2n69JQhAFjq11iMhflj376+vopb0\n",
538 538 "Tq0+nVp13wN0atGp1QsUtUglTBmfdWq93+VYSC50avmFFbXuzl1LDnRqbYSiVnf05dIC9Al0CmBb\n",
539 539 "z/0vbUGnVjedWlIFvZBFrRCdWnWdTtn70qlVjiE5tfoUteo6tbocY11HlF2/a6cWRa0eoKhFqvJ4\n",
540 540 "AKcCuBXADY7HQlZjRa2znY6ClIVOLf+hqNUdffVp2f4Xn91adGq1OxugRVIsL4t9Ldooic9uR8Jr\n",
541 541 "3Na+SRK1fJ39sHan1sL9fBG1+u7Ukuo0ylL3PeBD/HBz7lr1seNi/LAHKGqRqsyjhy2VkpJuoFPL\n",
542 542 "L6w45IuoRafWRlwXxe+HnmVqWzRJ+opM9EVvotbC4/goatGp1Y2wJ0nsyRJyp5YVFEIQtdrYFwlO\n",
543 543 "LR/jh3We877HK9kFZWH8sDp0avUIRS1SFStqMXooG4pafkGnlv84LYo3PzJYt9axeet6SJ/xQ8BT\n",
544 544 "Uev/Z+/Ng2TL8vq+b716r3u6p3v6MWsPBBI2OBhCBmxQysKAGF1kEIsAE5AGyzAQEMLGxkFIpC1Z\n",
545 545 "GDBgCSuBCBkJCWFpsBaWhGEzqwRpxCLbJGhAwgIMjEdjwUDP0Lye7p7p5VWV/7jnZN6syuXmvef8\n",
546 546 "lnO+n4iJiuqpyjyZb8v81Pf7vZP58jbaF9FXyPMiOkota2LnOjmkltWUGuuHx7HwmErZ1KolqeVl\n",
547 547 "U4tD8du3bU1qMaklCKUW6c1kvnwJgI8On/6k5lnIUe6hfWP26GS+fNmxLybqeJNaTGrdRLt+CGyk\n",
548 548 "1qMHv8ofTGr1Y70llSlJHcVJzUmtB8LVOK1QstQaK1IiFh6T96sf1lY/9LKpJVmTHPp7oOakFofi\n",
549 549 "BaHUIqfwkWhfQP3yatY8oX0Ysp/whoZpLT94k1pMat3EktQqbVeLSa1+5NzTAvzVD1PtTMV/UzU3\n",
550 550 "jfaRS2pZSKSVVD90m9QKEnfsm3ONs48Z5/eyqaWR1LI4Zm9Vag0dsCcDoNQip8CrHvqCUssP3qQW\n",
551 551 "k1o3sSC14n2XJrWY1OpHzj0twG4F7zq55J7Fx1/yplaKKwYClFpjWVeoRiRAmdQ6jIekFuuHp8Ok\n",
552 552 "liCUWuQU1iPxqqcgfaHUckD4Kag3qcWkVofJfHkO+TTRLkpNakW5JPXcxvvxJrVyJ7XWwmMyX1p+\n",
553 553 "/ZhbalkQPpEa6odMarVoJQXHVg+730uptRsPQ/GW64dDB9mZ1CoIyy9KiCEm8+UrAHwY2r/Mfkb5\n",
554 554 "OKQfvx0+UmrZ5mG0/6A+v5o1ud6MpoZJrW2i0HpmNWsuFc9RqtSKz690Usvb4H7WpFZIaVgQBMfI\n",
555 555 "JbUsVfMiJUutVEktC7VRz0mtFNtmXqWW6aH41ay5AHAJ4Cz8cC0nlsXb0EF2JrUKglKL9KUBcAbg\n",
556 556 "Z1ezRuqNBRkHk1o+8JbSApjUuo6F6iFQrtRi/bAfuZNagI9drZrqh6muEBixJO44FL+NttQa88bc\n",
557 557 "q9SyXj/sfk/us47d1LJYP4wSLHdSi1JLAEot0hdWD/0Rpdb7qJ6CHCOKIU9Si0mtbaJEotTKA4fi\n",
558 558 "+5F7UwuwKXauU1P9MLXUsvQYUz22UqSW1tUPvSe1hjznXobiAblUmeX64dhNrdsHv2o4QxNkZACU\n",
559 559 "WuQoYfMnSi2OxPuBSS0fMKnln5jUeubgV+WnVKnFpFY/mNRqiQKhhvphrqSWBanFpNY22kPxXqUW\n",
560 560 "k1pp4FD86TCpJQilFunDvw3g/dC+6X6z7lHICVBq+cCj1GJSa5sokSi18iA9FO9VakkkteJtWxI7\n",
561 561 "12H9cDgWBFCkiKH4sHV0C8AVgIsRN+W5fqiRMvO0qeVBwA39feAhqZV7U4tJLQEotUgfYkrrJ8Mo\n",
562 562 "IfHBO9H+Y/fyyXzp7c1ZTXiUWs+ifXH+8GS+lHrRZxnWD/OiNRTv7e9NiaRWvG3LSS3WD4djKY2W\n",
563 563 "aiheW9SthUW42MJQtAbvvdcPLYuiiIf6oYeheKtSi0ktASi1SB9YPXRIuApbvAIid7Xs4k5qhRfm\n",
564 564 "sYLItJa9+uGjB7/KH9L1w5gI49UPb1JzUsuS8ImUvKlVSv0w1eNg/bAnk/nyFtrq19B0nKdNLamz\n",
565 565 "Dv19wPohk1oiUGqRg4TYdBM+5Ui8P1hBtI87qRWg1NrA+mFeOBTfDya1WuLzkEr0RCzXD8cKk4i2\n",
566 566 "AOqSeiheWgZFvEstj1c/HJuOY1LrJpbrh0O3q5jUKghKLXKMD0c7Bv2W1ax5i/ZhyMlQatknSq17\n",
567 567 "B7/KHvG8HIvfJKNYP8wDh+L7IZnU8iC1WD88HUtSK3lSK1z4SJrUj4NXPzzO2DNLb2p5SGp5GIo/\n",
568 568 "NRHFpFZBUGqRY/yp8JEpLZ9QatmHSS3/WElqea3NHYND8f2QTGpZSitdh/XD4Vh6jEmG4sMW7AWA\n",
569 569 "M2zeZEqSavCe9cP+pJJaHs4rddahvw84FM+klgiUWuQY3NPyDTe17BOTTt6kFpNaG6wktUqVWhyK\n",
570 570 "70f1Sa2QxKmxfljUplaCTaTraCbQSqkf1iS1PG5qWa0f1jwUP7QWSQZAqUX2MpkvHwHwH6J9UbFU\n",
571 571 "Pg4ZBpNa9mFSyz9MauWFSa1+SCS1rA/F30GbyLm/mjWpKx8mhM81UqWAIlbqh6muGBgpSWppXf3Q\n",
572 572 "46bW0D8XYucNAje+Hx8icKWTWkOllsWh+PhvRO6kFuuHAlBqkUO8Hu1fkj+/mjVPKp+FDINSyz5e\n",
573 573 "pRaTWhsotfLCpFY/JJJa1ofic4o9S9W8SKmbWiU9Lia1/CW1JDe11kJm5Kh97rOOTUNZTmrlqiUz\n",
574 574 "qSUIpRY5xJ8OH39M9RRkDJRa9vEqtWJSi1KL9cPcSA/Fe30emdTaSIscz4HFpFapm1qpRFCEUms4\n",
575 575 "3NTKy9jdJamqZMlSi0mtAqDUIoeIUuvHVU9BxvC7aOPMr5nMl1qXsyaH8Sq13hU+Pnrwq+qASa28\n",
576 576 "SNcPo7hhUusmNSe1atjUWl9hT+lKgREmtW6iffVDj/XDoc/5BdrplfPJfHme5kh7Gfv8Zk9qhefg\n",
577 577 "DMBVuPDCKeROQ3Vv26rUYlJLAEotspPJfPkBAN4f7RvtlfJxyEDCPz5vD5++t+ZZyE0m8+VL0L5B\n",
578 578 "ehFyKZRUcFNrA5NamQh7I1Eu5ZQ1XeKfRaviZh9MarF+OIrVrLmE/Ej2LpjUugnrh/0ZdeZQA5Qa\n",
579 579 "YB+bhLOchOp+j8VNLamheCa1BKDUIvv4+PDxn2QYWyWysIJol5jSupdoDFeSmNR6meopbGAiqbWa\n",
580 580 "NS+gffF0u6BkZhQI7wlvuCUwfYW/AzCpJZPUKrl+2L0tzcdZ0gC+d6nlsX4Yf509pMvGpnksX12w\n",
581 581 "+z0SUuvU96tMahUEpRbZB/e0yoFSyy5eq4cApVYXE1IrUFpaS3okHuhILeUK1qkwqbU5V0rJE6mh\n",
582 582 "fgjYeJzxcTGptUH76oeepFZKEWd1gD1i+eqC3e+xeD6ppBallgCUWuQGk/nyQQBN+JR7Wv6h1LJL\n",
583 583 "HFn3KLVYP9xgpX4IlCe1pEfiEdLJ99G+RvKUeGNSi/XDFFhKalFqbdCuH3pIPUU8iTgPQ/GUWsPg\n",
584 584 "ULwglFpkFx+F9o3Ev1jNmt/RPgwZzW+Hj++jegqyCya1yoBJrXxIj8RHPFYQJZNaVp+XWuuHqeQP\n",
585 585 "YENqcSj+JtpSy4MgiqSofUlty5kfise4baiapRaTWoJQapFdxD0tprTKgEktu3iWWkxqYZ1svQPg\n",
586 586 "xdWsyVF5OpXSpJZG/RCwL292IZHU8lI/5NUPh2NBajGpdROtqx963NRKIbWkk1ocih/O0PNFScek\n",
587 587 "VgFQapFdcE+rLCi17OJZajGp1WIppQWUJ7W0kloer4AokdRi/bB8qWVB3nEo/ibaSS0PgiiSMl3m\n",
588 588 "ZVOLUmt4Uuv2wa8aDpNaglBqkS0m8+X7APhgtG8gfk75OCQNsX5IqWUPz1LrGQBXAB6ZzJfn2odR\n",
589 589 "hFIrL0xq9YdJrfrqh6nlT/e2LNQPmdTaENMetyfzpeT7t1rrh942tSxKo+733Ml44ZWh8oibWgVB\n",
590 590 "qUWuE6uHSyNVGjKeuIv2uPALIXIct1JrNWsusRlGf/TQ1xaOpZF4oDypxU2t/jCptZEWxdcPwxtE\n",
591 591 "1g/7oVXd697nqMeymjVX0Elr1Vo/lNrUKjqpFV4rXoVPc/0A1OqmVorfh6QnfINLrsPqYWEEOfn7\n",
592 592 "aH+S8Url45BtotS6p3qK4bCCyKRWbsSvfhiIUuvhg19lCya16qofrlMA4Y1jKixIrdSyTqu6173P\n",
593 593 "FIJO43HUXj/kUHy6NFmumt/QRJTUUDyTWgJQapE1k/nyNoA/FT6l1CqLt4eP7616CnKdu+Gju6RW\n",
594 594 "gFJrk9Si1MoD64c9CBXgO2h/Ip7ySnjXsZ7Uqql+mCOlBdhIpKVOapUitTQSZ54EUSRl/VBqU6vU\n",
595 595 "ofju91lLRFk9FxkApRbp8sfQJkd+czVr3qJ9GJKUWEGk1LKF2/phgFdA3CS1WD/MA+uH/VjLnFBT\n",
596 596 "ykXNSS0LsqdLLqlVclLL86ZW9zZYPzxMTZtanpJa1uSRVFKLUksASi3S5ZPCxx9RPQXJAaWWTbxL\n",
597 597 "LSa1WD/MDZNa/ZDY0wLsPy/xecixCWqtfliy1GJSazea9UNPUivFmb1sakmcc2yNrlapxaF4QSi1\n",
598 598 "SJdPDh9/WPUUJAeUWjah1PIPh+LzopXUihLNqry5jsSeFmAvrXQd1g/HY0lqcVNrG43EmcdNrRqT\n",
599 599 "Wqwf2pNaTGoJQqlFAACT+fJ9AXwI2jcO/1T5OCQ9lFo28S61WD9kUis32kPxXqSWVFJrLTyMXk1X\n",
600 600 "ZCg+46XpT6HkTa342Hj1w22Y1OqHp02tmobirckjJrUKwuILEqLDJ4aP/yRcLY+UBaWWMSbz5R20\n",
601 601 "4uESdlI+p8KkFofic8P6YT9Eklphr8uC9NhHNqm1mjX3AVygfe2c6ypep5Ba/EQsJbVYP9zG66bW\n",
602 602 "uiInJIQ9iTgOxY9n6PkuwsdbmX5Iw6F4QSi1SCTuabF6WCZRar1W9RSkS0xp3cs87JwTSi0OxedG\n",
603 603 "O6n18MGvsoNUUguwPRaf+3mwVEEsuX7IofjdaF79cPAb89WsucQmrSIhhGusH9ac1Bp0vvDaO+fv\n",
604 604 "y7FbZOQEKLUIJvPlQwA+NnzKkfgyYVLLHt6rhwDrhwCTWrmJCSQmtQ4jtakFbMSOxedGSmpZEHol\n",
605 605 "Sy0mtXbjtX7Y/X6Js6eQWhyK3+BFag2RRznPxqSWIJRaBABej/an0W9ezZrfOfK1xCe/Gz4+Ppkv\n",
606 606 "z1VPQiJ3w0fPUotJLSa1cqOd1LIobnbBpFZLFDG5ngdLV0BMPaYesSDuciW1KLVOJ0X9sPv9Emf3\n",
607 607 "WD8seSg+yiZTSa1r35PjbExqCUKpRQBWD4tnNWteBPAE2j/zr1Y+DmkpIalFqcWh+NxoSS1e/XA/\n",
608 608 "TGqxfpib1Emt0obiNa5+6ElqeRqKr0Fqxe/LVT21KrWY1BKEUqtywmAjpVYdsIJoixKkFuuHrB/m\n",
609 609 "hkmtfjCp1cL64XhKlFpMag1n9KZWwKvUyn3esb8/clf7gPGJI5ObWte+J2dSi1JLAEot8kEA3g/A\n",
610 610 "OwGsdI9CMkOpZYsSpBaTWqwf5kYygdTFm9SSfJ4sPze5pZal+mHJUov1w92wftiPFM+5t00tDsXb\n",
611 611 "k1pjtr7IiVBqkZjS+tHVrLk4+JXEO5RatqDUKgMmtfKindTi1Q9vYimtdJ14ptSiJ1JD/dDCr2+u\n",
612 612 "pBavfng6tdcPrUut3HtV3du2KrXGJKKY1CoESi0SpdYPqZ6CSECpZYsSpBbrh0xq5UZballMI+0i\n",
613 613 "nlOyfmjxuWH9cDxMaqXFe1Kr9vqh9U0tJrWY1CKg1KqayXz5XgA+CsAFgH+sfBySH0otW0SpdU/1\n",
614 614 "FONgUsveUPxzAK4APFjIlU5ZP+xHlCySQ/EWxM51WD8cjwWpxaH43WhKLU9JrZqufli11Arb0GPk\n",
615 615 "Uc6kG4fiBaHUqpuPA3AO4GdXs8bzG2vSD0otW5SQ1HoWwCWAhyfzZa6r2pglvJiKUuvZQ18rxWrW\n",
616 616 "XKGQtFZ4fmNSS1pqeb36IZNaLbz64XA0U00RDsXvRqNG6XFTK4VMkNrU8jAUb1ZqoX0fCwCXq1lz\n",
617 617 "OeD7c16ZcezAPjkBSq26+dTwkdXDOnh7+EipZYO74aNbqRUESs1prYcBnAF4z2rWWHrRUoTUQvti\n",
618 618 "/xaAFxSeX8viZhcaSS2Lz02N9cNU4idiIanF+uFuWD/sR02bWjmlTMSy1DJ5tvBDuSjcLL0+LBZK\n",
619 619 "rUqZzJd3AHxi+PQHNM9CxGBSyxYlJLWAuqWWtZH4SClSSyul1b1Pi+JmFxpJLQti5zpMao3HgtTi\n",
620 620 "UPxuRKVWeGOeauzaW/1QIgHVvX1TUuYalsfsrT5/8c/NRfgBMMkMpVa9fAzaced/tZo1v6F9GCLC\n",
621 621 "E2irYq8OUpPoQqnlH2sj8ZFSpFYUNdIj8YDfqx9KCECTwi9syN1GuymXa8Okhk0tC/VDJrV2I70N\n",
622 622 "thYGCd6Ye0tqUWptGFujy5kms/r8cU9LGEqteonVQ6a0KiHUd34vfPq45lkIgHKkVs1XQDS1p9Wh\n",
623 623 "FKmldeVDwKi4OYBkUstSBa9LFCHPZfzJuKXHHuUAk1rHKUVqST8Or2en1EqL5TOOTRLmTmpRaglB\n",
624 624 "qVUhIU5MqVUnsYL4WtVTVE5IFLwMbaLgqSNfbh0mtZjUyoUJqRX+zbRO9Ukt5K8edm+7hvphSUkt\n",
625 625 "Xv1wGKn2tADZCqin+iGH4sdh9WxjrshIBkCpVSf/HoD3RTscvlI+C5GFu1o2iCPxTw28WoslKLWY\n",
626 626 "1MpFlCbim1oh2Xof7YUANN/c94VJLRmpVVP9kEmtkQQh7lUMAWl/HaQkUfc+ahqKp9QaBpNahUCp\n",
627 627 "VSefFj7+bwW8oSanQallg1g9vKd6ijTUXD+M0ohD8XnQTGp179daImkXGlc/tCB2usTzpJY8XSw9\n",
628 628 "dg7F90dL1K23iBK93paWc/GNfsqUmRep5aV+eBE+3prMl7ne11sVR93btHY2JrWEodSqk1g9/H7V\n",
629 629 "UxANKLVsUMqeFsCkFkCplQttqWW1ZrcLJrVYP0xFiUPx66HqjG/8d+E9cZYyZRZvg1c/3GaUlAn7\n",
630 630 "gbnPalUcdW9z7Ig9h+KdQ6lVGZP58v0AfCjaN2FL3dMQBSi1bBDrh5RavqHUykuUWuL1w2v360Fq\n",
631 631 "ManF+mEqiktqCb3x30VqqSW9DVZz/dCF1Lr2vTVLraFnizIsV/2QSS0hKLXq41PCxx9bzZqcEX1i\n",
632 632 "E0otG5SU1Kq5fshNrbxEmaSd1Hr44FfZgEkt2aSWhceeXWppXCQhXEjlHMBl2LZLhcZYvPekVo76\n",
633 633 "Ia9+uI2HVFnJUmud4kxwli5MaglDqVUfvOph3VBq2aAkqcWkFpNauWD9sD9MarF+mITVrLkAcIn2\n",
634 634 "IgnnKW+7J6lFUESjVuldauWoH0oktVKc28tQfPd7c0staxW/7m1aE25MaglDqVURk/ny5QA+Bu2o\n",
635 635 "4I8oH4foQKllA0qtMuBQfF5YP+wPk1r11g9Tyx9At4JIqbUfz1c/FBmKD+lCD6Io4uGsY6/kl6vi\n",
636 636 "B4w/Gze1CoFSqy4+Ee1P3f7patY8qX0YosI70f7j8orJfGnhJ821UpLUYv2QUisX2vVDXv1wN1al\n",
637 637 "Vvw3jfXD8WhU9SK5B/AlX/t4T2qlrB9KDcXHdOHFyCtOUmptsFrxA+wntSi1hKDUqotPCx9ZPayU\n",
638 638 "8A/828Onr9U8S+WUJLVqTmpRauWF9cP+MKnF+mFKNARQhEmt/WjVD90ktZCuMkmptcGqOOreprWz\n",
639 639 "ja1skhOh1KqEyXz5UrRJLQD4Ps2zEHVYQdQnSq17qqdIA6UWh+JzQanVg8l8eQubN3KUWjL1Qwu/\n",
640 640 "J+Kvec6klobUyj2A71lqaV39MOWmltRG1djnnEPxG6yKo+5tWjsbk1rCUGrVwyegfRH2f65mzf+n\n",
641 641 "fRiiCqWWPnfDxxKSWjXXD61vanm4at8hrGxqWX8eo8x5fjVrrgTuj1KrnqSWRv2QSa39eE5qeUo+\n",
642 642 "db/fw3kpteyN2DOpJQylVj18Rvj4PaqnIBaI9UNKLT1YPywD1g/zor2p5SKpBdk9LcC+1MoheSK1\n",
643 643 "1A9LTGpRap1Oyk0tqbOnSpfx6ocbPEgta2fjULwwlFoVMJkvHwLwyeHTN2mehZiASS19SpJa70H7\n",
644 644 "k6iXTOZLjZ/qa0KplRfWD/shkVDqYl1qMak1npKvfljCULz01Q9T1g+lkk9e6oeUWuMYe7ZcV2aM\n",
645 645 "9UMmtYSg1KqDj0f75uYXVrPmrcpnIfpEqcWheD2KkVqh7lRrWotSKy/a9UMvVz+M52NSq4VSazys\n",
646 646 "H6bBe1Irx1C8h+RT9/sptexW/IDx21W5rszIpJYwlFp1wOoh6cKkliJh1DluapUwFA9QanEoPg+s\n",
647 647 "H/ZDOqn1IoArAHcm8+W50H32QaJ+aEJqTebLM5Sb1OJQ/H6kH0PK+qH08HoqqXU7/HlLTrjdFIPi\n",
648 648 "uZ/bVOLIYlKLQ/GFQKlVOJP58kEAnxI+ZfWQAJRa2rwMwBmAp1ezppRYcq1j8daH4r1LLdYP+yGa\n",
649 649 "1ArpTEvbUpF4FomklnZKbZ2cWM2aywy3ryGAIkxq7aeEpJaL+mH4e+4ifJo6xRPp/jkec5EP1g/t\n",
650 650 "nY1D8cJQapXPfwTgUQC/tJo1v6l9GGICSi1diqkedqguqTWZL++gfRN9CbmETF+iBHo410+YhbAi\n",
651 651 "tbxc/VDy96HFCmJN9cOcKS1AZ38qwqH4/ZSwqeWlfgjk/z3jpSppdbeqe5vWpBaTWsJQapUPq4fk\n",
652 652 "Ok+i/Yf67mS+tP5mrUSi1CqleghUKLXQSWmN/AlrckJy4zm0iUDrKaNDaG9qMam1H4tSK7fo6d72\n",
653 653 "g8rCOD7W1GmmCIfi05D6sazfgAv9/vOY1PI0bp9KauWURt3btbZbBdiVWkxqCUOpVTDhSmSfGj6l\n",
654 654 "1CIA1pHqt4dPH9c8S6XEPa2Sklo11g+t7mlFSqggclOrHxpJrfjcWJJa2Z+H1ay5QPsmpbuFo4FU\n",
655 655 "Uov1w3EkfSzh998l2t9/Ent2OTa1pJJaHnbAaklqSdQPrY3YM6klDKVW2TRo30D/y9Ws+XXtwxBT\n",
656 656 "/G74yCsgysP6YRlY3dOKlCC1rNQPrUstJrVaJJJa3dvXrCDmfqwlDsW7l1rXbkvicXhKPUVS1g9z\n",
657 657 "nznV7w9KLXtnY1JLGEqtsmH1kOyDSS09KLXKICa1KLXyoV0/jDLNutTiplaL1PNgQWrFN8MlSq1c\n",
658 658 "Sa0Srn7Yva3ccgjIUz/M/fx7EnHmk1qh5hpTgdbSUN3btCq1mNQSglKrUEL18NPDp7zqIbkOk1p6\n",
659 659 "lCi1aq4fUmplYDJf3kb7ovAS+XaDjsGk1n4sSi3ppJbmYy+5fsik1mEkH4enKl8k5ZlzC0TzUqtz\n",
660 660 "mxcj9kNznm9szS93/ZBJLSEotcrl49G+ef4Xq1nzf2sfhpiDSS09SpRaTGrZw7XUQmdPS3GI34vU\n",
661 661 "YlKrRUpqxcfO+mEeOBR/GKltqu59eLiSYCRH/dDL1Q9z7Pyl2IaynNTKNbLPpJYwlFrl8p+Gj9+h\n",
662 662 "egpilSi1mNSSh1KrDDgUnxft6mH3vq1fJZZJrZaa6odSUkszqcWh+N1obGp5TGqxfpiGFGe0fL5c\n",
663 663 "QpBD8cJQahXIZL58BJurHn6n5lmIWVg/1CNKrXuqp0hLjfVDDsXnRXskHmBS6xAWpRaH4tOhkWqK\n",
664 664 "5NoLK01qSWxqearyRTyJOA9D8bVILQ7FO4dSq0w+Fe2L8J9bzZq3Kp+F2IT1Qz2Y1CoD1g/zsq4f\n",
665 665 "Kp7Bi9RiUquFSa10lFg/LG0o3mtSy2P9kEmtcWfMVfHr3qY1qcWkljCUWmUSq4ffrnr2nX/vAAAg\n",
666 666 "AElEQVQKYhkmtfS4Gz5SavmGUisvFpJavPrhfixKLQ7Fp4ND8WngptYG1g9vUovUyrn5NTYRxaRW\n",
667 667 "IVBqFcZkvnwV2pH4CwDfrXwcYpffCx9fPZkvzw9+JUlNiUmtGuuHlFp5sbSp9VC4rLlVmNRqYVIr\n",
668 668 "HSUmtUqRWl6TWlLn9nTm2qSWxfMxqVUIlFrl8RkAzgH849WseYf2YYhNVrPmRQDvRPt3wKuUj1Mb\n",
669 669 "JUqtGpNaURZxKD4P6vXD1ay5QPuC9Aw6iZW+MKnVUuPVD1OLn4im1Mqd1PJ+9UOvm1pMat2EUms8\n",
670 670 "Y+URk1qFQKlVHqwekr5wV0uYkPag1CoDJrXyYqF+CPi4AiKTWi1MaqVDs37IpNZhNJJaKQSR1Lk9\n",
671 671 "SS1PQ/Fj5MxF+HhrMl+mdg9Wk1opfx+SHlBqFcRkvvzDAD4K7QvbH1A+DrEPd7XkeQRtkvLdq1mT\n",
672 672 "6yfs4qxmzXNoX5Q9MJkvLb3JzQmlVl4s1A+79295V6v6pFb4gUEuGXKdGqRWifXDUobiNTa1Upw/\n",
673 673 "p9jo4unqhx6SWqNrdKtZcwW78ijKutR7X/H2mNQSglKrLD4rfPzB1ax5WvUkxANMaslTYkorUlta\n",
674 674 "i1IrL9aSWpallmZSy8rzsq7jrWbNZeb7siC14hv33FKLQ/HjYP0wEMSGxNk9JbU8SC3rZ2RSiwCg\n",
675 675 "1CoNVg/JKTCpJU+UWvdUT5GHWqUWN7XyoL6pde3+rcibXVSf1ILcnlb3Pmq4+mFJSa3SpJa3+mH3\n",
676 676 "dnKePaVMyC3hrAuj7m1aPWMqqZUrqUWpJQSlViFM5ssPAfAhaBMgP658HOKDmNSi1JKj5KRWbVdA\n",
677 677 "jLKISa08sH7YH25qyYo9S0PxJdYPORR/GK9XP+zeTs6kVo76Ia9+aPeMqeqHHIp3DqVWOXx++Pgd\n",
678 678 "q1kj8ZNK4h/WD+W5Gz6WKLVqTWpRauWB9cP+MKmlk9QqWWpxKD4N3je1Ul79EPCX1OJQvB+pNVQe\n",
679 679 "5ToXk1rCUGoVwGS+fADAfxY+faPmWYgrWD+Up+SkFqWWLbxLLSv1Q179cDfWpJak2KtBallIalFq\n",
680 680 "7UZyUyv1+XNLou5te5Ba1oVR9zbHnjF3Ispa/ZBJLWEotcrgkwG8EsCvAPhF5bMQPzCpJU/JUqu2\n",
681 681 "+iGlVl6Y1OoPk1pMaqXGwtUPUz+2Uq5+6HlTS+LsvPphWlKf0dp2lVXZRk6EUqsMYvXwjeHqIoT0\n",
682 682 "YZ3UCpdDJ/kpWWpVk9QKf16iLOJQfB64qdUfJrV0klo1DMWzfjiOUqQWk1p58CS1xiaOTG5qrWbN\n",
683 683 "BYArAGeT+fI82ak2so1JLSEotZwzmS8fB/AJaP/Q/EPl4xBfPI02BfEwNqkTkhdKrTJ4AO0LlhdX\n",
684 684 "syb1G69UlCK1tJNavPrhbqxJLSa10mKhfsih+N143tSSEHI5rn5Y81B8qm0ok1IrEMVTyhQZk1rC\n",
685 685 "UGr553MAnAP44dWseUL7MMQPIdXHXS1ZSpZaNdUPrVcPgY7UcprEtLapZVJqhV9bSi1ZqWXp6oe5\n",
686 686 "pLpGVS/CpNZhNDa1Ur0xl0hqeaofcih+PCnOl+NsTGoJQ6nlmPBidl091DwLcUvc1aLUkiFKrXuq\n",
687 687 "p8hDTUkt81JrNWteRPtC7Rw6b0zHwvphP9ZyYzVrLgXv15rU4lB8WjRSTZHcSa1SpJbH+qGEkGP9\n",
688 688 "MC3Wz5hSajGp5RhKLd/8MQAfBOAJAD+ifBbik5jU4li8DCUntSi17OG5gmilfmhdamnsaQH2pBbr\n",
689 689 "h2mxMBSfOqlVylC8SP1wMl/eQvtDESBd2kTi7JRaabF+xpT1wxxJLUotISi1fBNTWv8w/FSekFNh\n",
690 690 "UkuWu+FjiVKrpvqh9ZH4iGepZa1++PDBr9JDo3rYvT8rUqu2ofhcVwiMsH6YBs9JrfWeVsKLUEnW\n",
691 691 "Dym10mD9jFbrh6kG9klPKLWcMpkvHwLwWeFTVg/JUJjUkqWGpNajqqeQgUmt/DCp1Q8mtVqY1ErL\n",
692 692 "OlGjsMmX67HFx/SgxGMKSaccuzpSm1qp97QA2aH4FCIx93NtXRh1b9PqGVP8GctRP2RSSxhKLb98\n",
693 693 "BtpExC+sZs2vaB+GuIVJLSHCi+iSpdbT4SPrh3YoQWpxU+swTGq1SD4Plobis0itsM8meZU9AMBk\n",
694 694 "vjxH+97kcjVrLlLedri9eJsp37zuI0fSCZBLauWsTnrb1Mr1XKd6jnPU5yLWpZbV+iGTWsJQavnl\n",
695 695 "vwgf/7bqKYh3otRiUis/D6F9AfP8atZov1HPATe17OFZalmpH8b7tyq1mNRqYVIrPRp1PakBfI8j\n",
696 696 "6xEp2Zgy8RSReP5ZP0xLKjmTS7xZrx8yqSUEpZZDJvPlvw/gI9Bu2Hyn8nGIb2L9kEmt/JSc0gLq\n",
697 697 "klrc1MoP64f90Epq3QdwCeD2ZL6USL0cg1c/TI/G48wlgiKSW2Het8Fy1A8lk1opnndKrXQ1uuQV\n",
698 698 "v9CAiBczGJPsjMItR/2QSS0hKLV8ElNa37aaNdbfVBHbsH4oR+lSK9YPuallB5dSK2zRRIkkLWuu\n",
699 699 "Y11qqSS1Qp3KQg0vwqRWejTG4uPjyiW1SkhqSW9q5Uhqeasf1iy1LJ9xLdxGVnyZ1CoASi1nTObL\n",
700 700 "xwD82fDp39I8CymCd6D9afsrJ/Nl7hdItROl1j3VU+TjObQ/kXpwMl9aeJObE0qtvKxTN2HbRxNe\n",
701 701 "/XA/liqItV39ULJ+qJHUYv1wP+JXP0x4mxLVyZQJM29D8TlSs5alVqpqZM6heCa1hKDU8sfnon1x\n",
702 702 "/ZOrWfPr2ochvgnDqU+ET1+jeZYKuBs+FpnUCj8lq+UKiJRaebGypwUwqXUIS1KLSa30lFg/lBR1\n",
703 703 "3je1cl790Fv90PpQfK1JrVRnyzkUz6SWEJRajgjd4S8OnzKlRVIRd7U4Fp+X0uuHAKWWNbxKLStX\n",
704 704 "PgTsSy0mtVpqvfphLvkD6NYPmdTaTwlXP8x5dtYP02L5jKnSUFmrkQlvkxyAUssXrwfwOgC/A+AH\n",
705 705 "dY9CCoK7WjLUILXirlbpY/Ecis+LlZF4gFc/PIQlqVVNUiv8gLP0+iGH4vcjtamVs36Y8+y8+mFa\n",
706 706 "LJ/RZH0z/B3N+qEwlFq+iCmtv7OaNTS/JBVMaslQg9Sq5QqITGrlhfXD/jCp1VLT1Q/jG7mLMCGQ\n",
707 707 "C43HyaH443hOakmcveqrHwahkpIapFbq+uH6iowjB+zJCVBqOWEyX743gE9De8nSb1U+DikLJrVk\n",
708 708 "qElqsX5oA69Sy1JSy7rUYlKrRTKptX5jHq7UKU3uMfWIpACKcCj+OJ43tSSSWtXVD8MFVeJFVc4P\n",
709 709 "fe0AUo+x11A/TPWckROg1PLDF6H9w/t9q1nzO9qHIUXBpJYMNUitWuqHlFp5sbipxasf3sSi1Mr+\n",
710 710 "PISfvGsIn4iUwONQ/Di81w/dJbVCSsnT1Q9TPse5BFyqbSjLY+ypr37IkXgFKLUcMJkvHwbwX4ZP\n",
711 711 "v0nzLKRImNSSoQapVUv9MEoiSq08mExqZah1pIBJrZZ4BomkVvd+NCqI0lKLQ/HD8F4/9Lip1a19\n",
712 712 "XR78yn7kTsV5SJVZFUfd27Im3LinpQCllg/eAOAVAH4ewM8on4WUB6WWDFFq3VM9RV5qqx9yKD4P\n",
713 713 "Zja1wmZRfMGsebW7fTCp1SJZPwR0r4Ao9VhLHIqn1OpPjvph7uRT6oSMi/rhtduwLrVyJLVS1Q+Z\n",
714 714 "1HIMpZZxJvPlOYC/ED79eg7OkQywfijD3fCx5KQW64e28Cq1LNUPAdtXQNRMasX7tCC1pOVeTUkt\n",
715 715 "jaH4XI+thKsfSm9q5Uhq5Tp7ahFHqeVDajGpRSi1HPBpAN4fwP8L4HuVz0LKJEqt1xqt15QC64fl\n",
716 716 "QKmVF0v1Q8D2WDyTWi3SSa2apJbGUDyTWvuR2tTyWD9MfWZKLdtSy/pQPJNaglBqGSYIhln49Bsz\n",
717 717 "X7qZVMpq1jyLNmHzADZpIpIeSq0CCH8vR0nE+mEezNQPA5alFje1WrSSWhqPveT6YbwvDsXvp4T6\n",
718 718 "oYeNKkBuKJ5SaxhW975SbX2RE6DUss1HAvgPADwJ4I3KZyFlw12tjEzmywfRvvm8D/siZAyxfljy\n",
719 719 "ptZDAM4APOfgBw1epZa1+qFlqcWkVguTWunRvPohh+L3Iy21PCW1vNYPLV/90LLUsjoUn2rri5wA\n",
720 720 "pZZtvix8/OaQpiEkF+sKouopymWd0ip8F6/4pBb8VA+BjdR6+OBX2cNq/dDi88ikVou03LMwFJ8r\n",
721 721 "zRSRFEAR1g+PI7WplaN+KJXUSl0/9JAsyy21rFX8urdl7WxMailAqWWUyXz5gQA+Be1Pq/6G8nFI\n",
722 722 "+USp9RrVU5RLDdVDgFLLGlEKeU1qWZNaTGptY0lqMamVHg7FjyO31LqdeQfVY1KLVz9Mf9ZUgqam\n",
723 723 "+iGTWgpQatnly9BWXP7+atb8nvZhSPFQauWlNqlVcv3Qk9R6DsAVgAfDlXS9wE2t/jCp1cKrH6aH\n",
724 724 "Q/HjyPJYQto7t2wB8m5qVV8/DELSg9TyUD8cK49y1Q+Z1BKEUssgk/ny/QB8HoBLAN+gehhSC1Gc\n",
725 725 "Pq56inKJUuue6inyEze1Sk5qxdSTeakV3vx4rCBa29SKcs2i1LKQ1FJ9XsKbQ62klobQy707FSl5\n",
726 726 "KN6t1Lp2mzkfR86klov6YdjNvARwluEHQ1HIXK5mzWWC27MutVKLo+5tWUtqpZJt5AQotWzy5Wj/\n",
727 727 "QHz7atb8uvZhSBUwqZWXeFXJWpJaJUutmNTysnPosYLI+mF/mNRq39icAbgvePGGmpJaJQ7Fe776\n",
728 728 "ISCzq5VzU8tDnS+SWxal3v+yKrVSi6PubVkTbkxqKUCpZYzJfPn+aFNaFwC+Wvc0pCKY1MpLLfXD\n",
729 729 "9dUPM299aOKpfgj4TGqxftgfC0ktbaklndLq3lcNUov1w2FIJLW81Q9zyzhPZ/ay/2W5fsiheLKG\n",
730 730 "UsseXw7gHMA/WM2a39A+DKkGJrXyUoXUWs2aF9G+0T2HTQGQAm9Sy3NSy0r9kFc/3I0VqaUh9ixc\n",
731 731 "/bDk+iGH4g/jvX6YO6nl4cyUWuOxmiLjULwClFqGmMyX/w6Az0Wb0vpa5eOQumBSKy9VSK1A6RVE\n",
732 732 "b1LLY1KL9cP+MKnFpFYumNQah3eplbN+mHtTy1P9kFJrOFaH4pnUUoBSyxb/Pdpfk29bzZrf0j4M\n",
733 733 "qYonwsdXObtKmhcotcrBzVB8wHNSi1LrAKHiG89Us9TSEHuaQ/FMag2nFKklsanlMamVs36Y+sxe\n",
734 734 "rtRoteLXvS1rwo1JLQUotYwwmS9fB+DPov0DwJQWEWU1a14A8CTa2tgrlI9TIjVJrfWuluop8uFt\n",
735 735 "KN5jUsvappbVqx+u3xQJDqR3sSK1mNTKg+ZQfO6klveheK+bWlJJLQ/j9l6G4lOljnImtazVD5nU\n",
736 736 "UoBSyw5fgfbX4++uZs1blc9C6oS7WvmIUuue6ilkKD2p5bV+6DGpZW1Ty5rU0tzTAii1uvctScn1\n",
737 737 "w/jYWD88DDe1dlNz/TB1hS5iNQ3VvS1r9UMmtRSg1DLAZL78MACfjfYfjr+ifBxSL9zVykdNSS1K\n",
738 738 "LVuwfjgeq1JLc0+re7/aUqvWofhc4ieiUT+MIoX1w8N439TyWD/k1Q/H4aF+mHoonkktQSi1lAmb\n",
739 739 "GN8QPv2m1ax5m+Z5SNUwqZWPu+FjDVKr9Pqht00tV/XDaztR1pJa1p5D7efJitRiUisPJdYPS7n6\n",
740 740 "oeSmlgdBFOHVDxOeM2zsngG4SlBxr3EonkktQSi19PkkAK9H+2b3f9Q9CqkcJrXywaRWOXjb1PKW\n",
741 741 "1LqDdtvv/mrWWPkpJ5Nau7EitTSH4muQWhr1Qya1DiO5qeUpqVVz/dByEgrIU4+0miJjUksBSi1F\n",
742 742 "JvPlHQDz8OnXrGZNDW94iV2Y1MpA+HP+CIBLbFJMJVOL1GJSKw/WqoeAXanFpFaLZlJL47HnruhF\n",
743 743 "NOuHHIo/jNf6Ye6kVs5x+1xXP0w9FJ+qQgeklTOWz8eh+AKg1NLlvwLwOgC/BeCblc9CCJNaeYjV\n",
744 744 "w3urWXOpehIZotQqtX7oTWp5S2pZlFpWr37IpNb2/TOplRYOxY/Du9TKWT9kUqu+pFZN9UMOxStA\n",
745 745 "qaXEZL58HMBXhU+/dDVrJH/CSMgumNTKQ03VQ2CTRmNSywbeklra6aNdMKm1GytSi5taeeBQ/DhK\n",
746 746 "2dRKef74Jv98Ml/meA/qKV3mSWqlkDOWpVvqszGppQCllh5fh/ZN3w+vZs0PaR+GEDCplYvapFbp\n",
747 747 "9UNvQ/FMao3HqtRSTWqtZs19ABdo36CmrJScSq1XPyxxKD53UquUoXiJTa3kgmg1a66QN63lKV3m\n",
748 748 "QWqllDOWk1q5rn7IpJYglFoKTObLjwbwBrT/UHyp8nEIiTCplYcote6pnkKOWuqHXobivSW1KLX6\n",
749 749 "o53UAmyktZjUyoNG/ZBJrX5I1g9Tnz/n2Vk/tJmE6t6GxfPluvohk1qCUGoJM5kvHwTwreHTr1vN\n",
750 750 "mt/UPA8hHd4B4ArAq5R/6l4acVOrlqQW64e2iFLLS1IrihqLUsuaGNTe1Oret6bU0tzU0njcNdQP\n",
751 751 "ORR/GK+bWt3by5HUylk/9DIUb1EadW/D4vmY1CoASi15/jsAHwjg1wD8FeWzELImVEneCeAMwKuU\n",
752 752 "j1MSrB8WwmS+PEcrXa5ga/PpEF7rh5aeXya19mNBajGplYcS64elJLVyD64D+ZNaXuqHuc5bW1Kr\n",
753 753 "u6d2luD2APtD8UxqCUKpJchkvvxgAH8pfPrnOA5PDBJ3tVhBTAelVjlE4fKsoytZsn44HqtSi0mt\n",
754 754 "7fvm1Q/Tch+twD8PQl8C1g/7IfE4cqSegLwj96wfGpVaYU/NqjzKNRTPpJYglFpCTObLBwD8A7R/\n",
755 755 "YL5lNWt+RvlIhOwi7mpxLD4dtUmtWD8scVPLW/UQ8JvUMim1Ev6EOQVMarVoJLUsDMXnSjMBWL8J\n",
756 756 "FZNA4c8Wh+L7wfrhbnj1Q6NSK5Bru8rqUDyTWoJQasnxlQA+FMBbAHyZ8lkI2QeTWumpTWqVnNTy\n",
757 757 "NhIP+EtqWRA1W6xmzQV09oWOwaTW9n0zqZUeSQl0jnb+4CL8mcsBk1r98TgUz6sf2pZaVuURh+IL\n",
758 758 "gFJLgMl8+ZEA/iLaGPcbVrPG00/5SV0wqZWe2qRW/Pvtkcl8Wdq/MUxq5cdiUguwWUG0IAAtSC1u\n",
759 759 "auWjlGH1yAXkKpXeN7Vy1w9zJrU8SK3ahuK7t1N6/ZBD8QqU9obDHJP58hUAvgPtcz1fzZqfVT4S\n",
760 760 "IYdgUis9VUmtsDW1FluaZ8mAR6nlLallXWpZeh6Z1Nq+bw2ppfG4c+9OdZGUd9llnVSlMgizWwAu\n",
761 761 "M6XOsj6GcP5ztAIw9flznj2HiKt5KD71NpTV7arUCTImtRSg1MpI2Ad4I4D3BfB/Afhy3RMRchQm\n",
762 762 "tdITpdY91VPIUmoFMaadPEmttYxxkpyzkD7aBZNau7EgtaIMYf0wPaVsUHXxXN2L5H4Ma+ESRGBK\n",
763 763 "cia1WD9kUmsIuQbsmdQSxMMLXM/8NwD+DNo3s5+1mjU0tsQ6TGql5274WEVSK1Cq1HK3qRWSc1F6\n",
764 764 "aIqHvlhPall6DpnU2r7v4qXWtTH10uqHIgP4kBF1uaVWzisIAvmqh93b9FY/5FD8eGpJanEoXgFK\n",
765 765 "rUxM5stPAvBXw6dvWM2atyoeh5C+MKmVnqrqh4EotUq7AqLH+iGwkXAedrWsSy0mtbaxILU0NrXu\n",
766 766 "A7iEzDZTl9vIP6beRVLeSdUqS0pq5drUktgD81I/ZFLL7hmtbmqlrm2SHlBqZWAyX34QgG9H+8Lj\n",
767 767 "K1az5geVj0RIX5jUSkh4s/NY+PQpzbMI83T4WGpSy5vU8jQWT6nVHya1tu9b7HkIlSyNtJa0wJOs\n",
768 768 "H0oltUqSWrkeQ44aXySnkPNUP+RQ/His1w+Z1BKEUisxk/nyvQH8KNo3c98D4Gt1T0TISbwT7U+f\n",
769 769 "XzGZL3NeVacW1kJL6KfqVii1fuhxUwvwNRZvIX20C4tSy8JzZUFqaSS1uvcn+dilH6vG1Q+lklo5\n",
770 770 "H1MpUstrUiulTKh5KN76Ga3WD5nUUoBSKyGT+fIugB8D8IfRDsN/XoaBRUKyEcTLO8Knr9Y8SyHU\n",
771 771 "WD0EWD+0BpNa47EotZjU2r5v6eeBSa20cCi+P543tXIOxbN+WJfUSnW++EPn87BbOBYmtRSg1ErE\n",
772 772 "ZL58GYAfBvDBAH4dwCevZo2bMWFCOnBXKx21Sq3S64fe/m73lNSyKrWiMLEktZjUatG4+iFQl9Qq\n",
773 773 "aSi+BKkltamVs36Y4/n3VD+0Loy6t5XqjKlrfkkSUSGAkvJs8VyUWoKkitmdxHQ6vY32yoCfD+B9\n",
774 774 "0O74fDeA/2GxWBx9szCdTl8D4GsAfAKAlwN4C4C/sVgsviXboQ8wmS8fQ5vQ+uMA3gbg41ez5p0a\n",
775 775 "ZyEkAdzVSketUqvU+iGTWvmxIGp2waTWbixIrXjf0vXD+Ng1pFZu8RMpsX5YwtUPS6gf8uqH27c/\n",
776 776 "lhzPa+oaneWrDL6I9ly3Mf73fTwX64eCaCW1/hGAvwjg7wH4dADfCOBzAPzodDo9eBWZ6XR6F8BP\n",
777 777 "A/iTAL4KwGcA+CEAf306nf7VA9+ahcl8+TiAn0QrtP41gNevZs2/lj4HIQlhUisdUWrdUz2FPJRa\n",
778 778 "tmBSazwWpZYFARjv24LUYlIrPRyKH4Z3qZWzfpjz7J7qhxyKH0/K8zGp5RzxpNZ0Ov10AJ8J4OMW\n",
779 779 "i8VPhP/8Y9Pp9CcA/HMAXwzgmw7cxFcDuAvgQxeLRXzz/aPT6fQ3APyd6XT6nYvF4pczHX+LcJXD\n",
780 780 "H0W7ofUWAB+7mjVvlbhvQjLCpFY67oaPtSW1Yv2wtE0t70PxHpJaUWoxqXUcJrVaOBSfjxKTWiUM\n",
781 781 "xefe1PKa1GL9sC6plTJJljJFxqSWAhpJrS8C8L93hBYAYLFY/CqA7wDwn+/7xul0+iCAN6CtGv7u\n",
782 782 "tf/7jQDeCuDPJT3tHibz5WeiHYOPo/AfQaFFCoFJrXSwflgWXpNanuqHUWpZ2y2zKLUsJLUsbI3V\n",
783 783 "lNSSEj8RycfIofj+lLCp5aV+yKsf2j1j6vph9zbHwKF4BUSlVtjS+ki0g+q7+BEAHzSdTl+55///\n",
784 784 "MLQ/+b/x/YvF4gptaur140+6n8l8+chkvvybABbhLAsAzWrWPJHzfgkRhEmtdFBqlQWH4vNjQdTs\n",
785 785 "wqLUqj6pFa5UpZ3UYv0wDVKPrSSp5TmpVXv90PoIe/e2rEutFImoHPVDJrUEkU5qvRbti+pf2/P/\n",
786 786 "/3r4+P57/v8PCB/3ff//c+B7RzOZLz8BwK+grUi+COBLAHzWatZY2/4gZAxMaqWjdqlVWv2QSa38\n",
787 787 "cFOrB0HmxLNUK7XQvnm4BeBiNWuk30DUILU06oe5k1ocij9Ozk0tDsW3WBdG3duyesaU21U56odM\n",
788 788 "agkivan18vBx32hy/O+vOPD99xeLxb4Xu/cAPDCdTh8+8DUnM5kvPwLA1wJown96M4AvWM2aN6e6\n",
789 789 "D0IMwaRWOmqVWnFTq9Skljep5SKpNZkvz9G+cbiCfOrmGKakFtoXzWcA7ivInC7aUivKFg2xp3n1\n",
790 790 "w5KTWqwfHkdqUytn/TDH2T1tanEofjzWh+KZ1BJEWmrFn9rvqxVEEfXYge8/9MKl+/2jpNZkvnwV\n",
791 791 "gE9FuwH2R8N/vodWbv115ReRhOSESa101Cq1Sq0feh2K95LUWlcPV7PmSvUkN7Fwlb8uFlJa3fvX\n",
792 792 "el7i/WpI0BqSWhqbWqwfHkdqU8trUqvG+mGNUivHUDw3tZwiLbXiT+/3/aQz/hT5qQPff+iF07Hv\n",
793 793 "38tkvpwCeBWAPwLgwwFM0P4UFGhl1jcD+PrVrKntzSmpjycBXAC4O5kvH1zNGmuJCU/ULrVYP7SB\n",
794 794 "i6QW7FYPAXtJrfhaSHt7TFtqaSa1ePXDtEgntTxf/dBz/TDL2UMlm0Pxad/bp04cJUtDhWT3GYDL\n",
795 795 "1ay5HHt7SPv8paxFkp5IS60nw8e7e/7/mND6/QPff/tAvfAxAC8MrB5+17XPXwDwU2ivyPhdq1mj\n",
796 796 "/cKREBFWs+ZyMl/+HoD3RltBfJvykTwTpda+ynWpFFc/nMyXD6B9EX6B/G+6UuMlqUWp1R8mtbbv\n",
797 797 "l0mtPEjWD5nU6o/UUHyON+W5kk+pJUeESS2bZ0w5Et+9HYtnIz2QllpvR/vC8HVor3R4ndeFj2/Z\n",
798 798 "8/2/FT5+INpdq13f/1s7/nsf3oQ2TfGrAP4lgH+2mjXernBFSCootdIQBX5tSa33oJU/L5nMl3dW\n",
799 799 "s6aEn1atq4cGq3HHYFJrPNakFpNa2/ermdQqWWpxKH4YuVNnOSt8QN5fi9zJp9Rn9iK1okA5n8yX\n",
800 800 "Z4lep1hOk6VOQ1k+G+mBqNRaLBb3p9PpzwL4JADfuONLPhHAry4Wi3fsuYl/jjYB8Mm4JrWm0+kZ\n",
801 801 "gD8N4MeHnG01az5jyPcRUijc1RrJZL68hY3UqiqptZo1V5P58l1ok2qPYpPS9YzXPS1gI7WsJ7XW\n",
802 802 "m1qqp9iNNanFpFaLtOTpojkUL5UWlRR3HIrvj+f6oZerCUZynTfp75Hwuus+2vf2dxLdroekluWz\n",
803 803 "MaklyC2F+/wWAH9yOp1+bPc/TqfTDwLw2eH/j//tsel0un4BuVgsngPwvwL4kul0ev3KbJ8H4N8C\n",
804 804 "8K2Zzk1ITfAKiON5FO3fsc8UklQ6ldIqiF73tADWD1NgTWoxqbV9v0xq5YH1w2F4l1oek1q5KpNe\n",
805 805 "klrd27J4dcHu7Vi8wmCO+mGNr/3VkK4fYrFYfO90On0TgDdNp9OvA/DLAD4AwF8C8IsA/iYATKfT\n",
806 806 "l6KtIb4Dm1oiAHwF2kTWz0yn0/8JbaXxIwH8eQBfv1gsfknqsRBSMExqjafWkfhIaVdAjFLLYy2d\n",
807 807 "9cPxRGliRWoxqdXCofi8cCh+GFml1mrWXEzmy0sAtybz5flq1lwkvguJTa1cSa1a64fxth5CHVLL\n",
808 808 "ZDUyXLAgtXAjPdBIagFtIusbAHwB2i2rPw/g2wF8/GKxiH8xv4hWWG3t+SwWi3sA/gSAnwbw1QC+\n",
809 809 "G8CnAPgLi8XivxU5PSHlw6TWeCi1WkqTWkxq5YP1w/4wqbV9v7UMxUulmSJMah9Iy/YAACAASURB\n",
810 810 "VA1DYh8s565WzvN7kkSAn6sfdm+rJqllLal1Hj6mvmABOYJ4Ugtot7UAfE34376veQHAv7vn//td\n",
811 811 "AF+Y53SEEDCplYLapVasHz6qeop0eJZaTGqNx5rUspLUWqeVEo4Tn4KFpFYN9cOShuJLkVovoP11\n",
812 812 "eQDpf//n3NTK9fyzfliX1Mo1FD/2bByJV0IrqUUIsQ2TWuOJUquqkfgOpSW1PA/Fe0lqUWr1x0RS\n",
813 813 "azVr7qP9Cfct6PygtLakFuuH45FIn0lJre59pUSifujt6oemh+IDqZ/b1DW64uuH4Ei8GpRahJBd\n",
814 814 "MKk1nnjlw1qTWqVJrSKSWmHvwSqUWv2xktQCdCuImkktzasfsn44nJKSWt37SonEULy3qx8yqTWe\n",
815 815 "GobimdRSglKLELILJrXGU3v9MEqt0uqH7obiw4jw82j/zZd8A34qlje1ngdwBeDOZL48P/bFAphI\n",
816 816 "agU0pRaTWnkpManlfig+kHNTK2f9MNe5WT+0L7UsX2GQSS3nUGoRQnbxB2j/gn/ZZL60kkzwRu1S\n",
817 817 "K25qMallAw8VRLNJrbAVZekKiExqbd8nr36YB41NLSa1+uE9qeVBEgEbOXGeKukcfjByBuAq8ZUr\n",
818 818 "rUutVOIISC+PuKnlHEotQsgNwhs4prXGUbvUKq1+6HlTC/AxFm9WagViKkrrSn9dmNRqkZY8XWpI\n",
819 819 "aknWD6WTWpRa+5HY1MpVP0z6nIfXw9ZlUcT6OS0PxadKkTGppQSlFiFkH9zVGgelVktp9UOvUstD\n",
820 820 "Usty/RCwtavFpNb2ffLqh3mQrB9KJbU4FH8c1g+3SX3mXL8/apJaVlNkuYQlOQKlFiFkH0xqjaN2\n",
821 821 "qcX6oS2Y1BqPJanFpFZLrUPxudNMEY2heCa1+pFzU4tD8dukTpcxqTUe6/VDJrWEodQihOyDSa1x\n",
822 822 "1C61Sqsfuh2KD3hIalFq9YdJre37ZP0wD5KPkUPxp+G9fphrU8tDuoxSazzW64dMaglDqUUI2QeT\n",
823 823 "WuOIUuue6in0KFVqMamVD0qt/jCp1aKZ1KphKL7E+mEpSS3vQ/Gpz51TxKUet/citVKnjjwktcbW\n",
824 824 "DzkUrwSlFiFkH0xqjeNu+FhrUivWD0vZ1PI+FO8hqcVNrf4wqbV9n7UktaTET4RD8cPwLrU8pZ4i\n",
825 825 "EvXD2qQWk1qnw6F4JSi1CCH7YFJrIOGyz6wftjCpZQMmtcYT5Y0FqcWk1vZ9cig+D+ukVvh3LScc\n",
826 826 "ij8NiU0tD6mniCcRx6H48VgdimdSSwlKLULIPpjUGs5L0f7D9p7VrNFIEFigVKnldVMrnttyUsu6\n",
827 827 "1LKU1NKUOdexUD+sJakl+nhXs+YCwAWAM4x/s3cMDsWfhtf6YerR9YjEDhiH4sfhoX7IpJZTKLUI\n",
828 828 "IftgUms4tae0gE79UOAn/BJ4T2qxfjgeS1LL0nNVa1JL8+qHkhJPqoLI+uFpeK0f5k5qsX5o95yp\n",
829 829 "Kn6A3fohk1pKUGoRQvbBpNZwqpdaq1nzAto3Q7eh82Y3Nd43tVg/HI8lqcWkVguH4vOTfSw+/OBD\n",
830 830 "OqnFqx/ux2NSy1P9sFaplariB9gdimdSSwlKLULIPt6F9oXzSyfz5SPHvphsUb3UChRRQQxvuLzX\n",
831 831 "Dz0ktSi1+sOk1vZ9qtYPBdOopSa1bqOtOF6EymNOSklqed3Uim/2zyfzZcr3oZ52wGqXWhaTWqnr\n",
832 832 "h0xqCUOpRQjZyWrWXGGT1mIF8TQotVqi1PJ+BcQHAZwDeH41a7y+UGFSazyWpBaTWi1qSa3VrLlE\n",
833 833 "2jrNQYI405RaEskmicdVylC8y6RWeG2ZQ8h5qh/men6T/X0U/r45v3a7Y7E8FJ+6fsikljCUWoSQ\n",
834 834 "Q3BXaxhRat1TPYU+cVfLdVIL/lNagPGkVngBbSl9tAtLUsvSc1VrUqt7vxK7WpJppi4SdT2pPS2g\n",
835 835 "88Y6Y8LOu9TKWeUD8kot1g/TSqOLICJT4GEoPlX90OsPQN1CqUUIOQR3tYZxN3xkUqulFKnldU8L\n",
836 836 "sJ/UWsuJkICxSBRIFjbimNRq0dzU6t6vhNSSFD9dJJNN2eVkxqRQF0mp5a1+COQRcrz6oe16X/e2\n",
837 837 "LJ6PQ/HOodQihByCSa1hsH7YUkr90PtIPGA8qQX71UOASa19MKklK7WkH2spw+pdsj2mkP6SSGvk\n",
838 838 "Glzv3qbHpJaH+qEHqZXjjDUltVg/FIZSixByCCa1hkGp1VJa/dCz1LKe1LIkafZhSWoxqbV9n1rP\n",
839 839 "g+QVELWkloS4k06hSVT37mdOnXquH+ZImeU8s7eh+JRXF7QqtawOxTOppQSlFiHkEDGpRal1GpRa\n",
840 840 "Lawf2iFKLSa1hmNCak3myztoB3wvjFy4oOb6oWRSS3JMvUtR9cOAy5H1a0g8hlx/v+RImUnUD60P\n",
841 841 "xdeY1LJWP2RSSwlKLULIIXj1w2FQarWUJrU4FJ8PSq3+aKeTrhPPofG8sH6Yn9KG4oG8ok5aaiXd\n",
842 842 "1JrMl+do3x9eAch1QYKcSS0PUqvW+mHKq8Varx9a+IFTVVBqEUIOwU2tYVBqtcT6ITe19LFeP6TU\n",
843 843 "6o+1qqZKUitsF2mJnkgNUotJrdOQklq5NrXWNb6EV727To6z8+qH9qVWTfVDJrWEodQihByCUmsY\n",
844 844 "lFotpSW1PEst60kta6JmF5qJpC7WklpaV4W8A+AM7XZRrkTJMTSufljiplYxQ/HwXz+UOH+OoXhe\n",
845 845 "/dCP1LodfigxhtRJrdT1Qya1hKHUIoQcYj0Un+AfoJqIUuue6in0odSyA5Na42FSazdam1rae1pA\n",
846 846 "HUPxJdYPS0hq5ZZaOd+U5zg764e2ry6IcOGEePGE85E3lyupNbZ+yKSWEpRahJBDPIP2jdND2Lyx\n",
847 847 "J8e5Gz7WntQqpX7ITa38UGr1x1pSS0tqae9pde+7hqQW64f9cL2pBb9JLU9XP/QwFJ/rKn6pzmh9\n",
848 848 "KJ5JLWEotQghewl7CqwgnsBkvnwI7ZuPF2AnSaFFaUmtpw9+lWFWs+YFtC/aboer51nDWvpoF1ak\n",
849 849 "lrXnikmtOqRWSUmtEobis29qJb7dLjmEnKerH3pKalk9o9Wh+FwykByBUosQcox1BVH1FH5Y72ll\n",
850 850 "HFn1QmlSy3P9ENgkzSymtZjU6g+TWtv3R6mVF4n6IZNap+O5fphzKJ5Sqw6pZXUoPnltk/SDUosQ\n",
851 851 "cgwmtU6DI/EbotQqpX7oXWpZriBSavWHSa3t+9OsH2oMxUulmSIS9UNuap2O56H4HEktiasfcih+\n",
852 852 "PFblUar6IZNaSlBqEUKOQal1GpRaG2Jdj0ktG1gei6fU6o+FhFIX1g85FD8WXv3wdHLsUnVvT2JT\n",
853 853 "K6WQY/2wTqllbSieSS0lKLUIIcdg/fA0KLU2sH5oC8tJLWvpo13Es0nLm+tYe65qTmrVUD/kUPxp\n",
854 854 "MKl1nJxD8TmkVo1D8dallvX6IZNawlBqEUKOwaTWaVBqbYgS6JHJfOn535tYn/QutZjUGsFq1rwI\n",
855 855 "4ALAufLYvrWk1jqtNJkvzwTv11JSS0JqSYufCIfiT6MUqZXzTXmOs0vUD5nUGk/qqwxarR8yqSWM\n",
856 856 "5zcZhBAZKLVOI0qte6qnMMBq1lygFSlnsJkO6guTWvkxL7UCFiqIppJa4c/5i2j/nEvKPia1ZOBQ\n",
857 857 "/GmUIrW8JbVYP8wjtVLLGatXGUxdP2RSSxhKLULIMVg/PI274SOTWi0lVBCj1Hr64FfZx3JSy5So\n",
858 858 "OYAFqWUtqQXoVBBrS2qVXD/kUPzpeN7UypnUotRKc85cg+e1DMUzqSUMpRYh5BhMap0G64fblCS1\n",
859 859 "mNTKB5Na/bEoADWkloWklsbVD0usH2oltTwPxXuuH+bc1OLVD23XD61uVzGp5RxKLULIMdZSS3gv\n",
860 860 "xSuUWtvEdNOjB7/KNqVILctJLUqt/jCptX1fFpJavPrhOLSufug5qeW5fph6eB3IK+M4FJ+O0ofi\n",
861 861 "cyXcyBEotQghx3gG7RvNh+BbTEhBqbWN66TWZL68jfYN6yVsSYQhRKnFpNZw4u8BJrW2Yf0wP9pJ\n",
862 862 "rZLqhxyK349E/TB18glg/bB7ezVILav1w1xbZOQIlFqEkIOsZs0VWEE8BUqtbVxLLWwE0DPhz4Jn\n",
863 863 "LNcPLYqaXTCptZta64c1SC0OxZ+G900tyasfeqsfUmqNx2oial0/HNlKYVJLCUotQkgfKLX6Q6m1\n",
864 864 "jff6YTy39+ohwPphCixILYsCkEmt/DCplY4SpJbn+mGOpBavfliX1EqaiAo/tLwIn56PuCkmtZSg\n",
865 865 "1CKE9IFXQOxPlFr3VE9hB+9JrVL2tADbSS1Krf4wqbV9X7UltaTET4RD8afhXWpJ1g9zJLVySi0O\n",
866 866 "xY/H6lA8kKaCyKF4JSi1CCF9YFKrP3fDRya1Wii17GA5qWUxfbQLC1LL4nNVa1JL8nGXXD9kUut0\n",
867 867 "PCe1kp491MU8bWrlSpXlkFqpE0dW64fd2xpzBcT4vUxqCUOpRQjpA6VWDybz5QNohcEFypAgKYhS\n",
868 868 "y2v9MEqtpw9+lQ+Y1BqPBanFpNb2fdWW1CqxfsirH57OWg4kvjK1xKZWakl0DuAMwOVq1lwc++IB\n",
869 869 "pN4Ay5WGS/m85tqGsjzInuL5Y1JLCUotQkgfWD/sx3pPq4BR8VREGcSklj4mk1rhDRmlVn+Y1Gqx\n",
870 870 "kNSSlFrSFb1IifVD91c/DK8x4hv6McmS67hLaiG/SPCyqZVKGHVvI1eabOzv2RzSLcWfJw7FK0Gp\n",
871 871 "RQjpA5Na/eBI/E1YP7SD1aTWHbQ/ab+/mjXWXwhakFpMam3fVy1SS7t+yKH4fkimznI8Do+bWpRa\n",
872 872 "27fnQWqVntRi/VAYSi1CSB8otfpBqXWTUuqHJUitmNSyJrUsJo/2Ec8oKW+uY/H5Yv0wP9r1w5KS\n",
873 873 "WiUMxXfvI+XgukT9MPW5cz/nlFrpKH0onkktJSi1CCF9YP2wH5RaN/FeP4wyriSpZap+CD/VQ4BJ\n",
874 874 "rX3UWj+M912y1OJQ/GlISq3UV+Xr3pZEUstb/TDVebMPxSfYWbMutawOxTOppQSlFiGkD+ukVuJB\n",
875 875 "0tKg1LoJ64d2sFo/pNQ6DSa1tu/LQlKr5Ksfcij+NFg/PI6X5FPExVB8GMmPe65j3+Nbl1pW64dM\n",
876 876 "ailBqUUIOcpq1jyDNuXxEvitkUkQpdY91VPYglLLDlaTWhYlzT4sSC0mtVosJLVYP0wDh+KHkUNq\n",
877 877 "SdYPUyefaq8fdm/TYr2ve3uDzxd+uH4ePk0ptVLUD5nUUoJSixDSl5jWYgVxP3fDRya1NsT6oVcZ\n",
878 878 "WpLUYlJrPBaklkUJWHtSq2SpxfrhaZSyqcWk1gZP57WchALSpqEuEl9pPGX9kEktYSi1CCF94Vj8\n",
879 879 "cVg/vEkpSa2nD36VD6wmtTxJrShvmNTahkmt/GhLrRQ7PfvQGor3LrVybGpJ1A9TP/+UWhssb1Z1\n",
880 880 "by9FGsri2eLzxqSWMJRahJC+xLF4Sq39vDx8fFL1FLZ4N4BLAA9N5ssxP/3SoqSk1vNo9zYenMyX\n",
881 881 "58e+WBBPUks1qRX+DN1G+2fK0k+CNZNamlKrK3xyv6aWTjMBAEISIqcEAvSSWqVc/dDrULy3qx96\n",
882 882 "kHDW64eWrzAYz8aklkMotQghfWH98DhMal0jvCGKaS2PFcRipFb4tbCY1rJYp9uHdv1wLXIS1y7G\n",
883 883 "opnUUqsfhl8DqbSW5uPNLbWY1BqG900tD8mn7u16kHDWpVbKpJblaiSlljCUWoSQvrB+eBwmtXYT\n",
884 884 "q3seK4hRxLmXWoEotSztajGp1R+rArDWpBYgILVC7U9TauV+jNJJrdKG4r1uanlIPnVvd3QFNyQ6\n",
885 885 "4/vvi1Gn2o0XqWUxDcWheMdQahFC+hLrh0xq7YdJrd143tUqJqkVsDgWT6nVHysi5zq1DsV37z9n\n",
886 886 "UuscwBmAy9Ws0XizlK2uFySBpAjq3o93qeV9U8tD8gmrWXOJjYAaW91fC5lMaVsvUsviblUK4cak\n",
887 887 "lhKUWoSQvjCpdRwmtXbD+qEdWD8ch7bUsvpcaQzoWxiKB2SklnbVMmeyaf0GNcgDCSSklsSvldf6\n",
888 888 "obekVve2rcqiiPVzFjsUH7ZKzwBcCf5dRgKUWoSQvlBqHYdJrd14rh+WJrWY1BqHttRiUmtDTUkt\n",
889 889 "K1Irx2PUGMDnUPx+PA7FU2ptsH5Oy1JrbP2QKS1FKLUIIX1h/fAAk/nyJWjf6L6ITRqGtLB+aAeL\n",
890 890 "SS1Krf5YT2qJSC0DG1NdJB679mOVkECSj62U+mGOTS3J+mGq59/TDpjUlRpTSS2LY+xW9764p6UI\n",
891 891 "pRYhpC/rpNbYocxCWae0jF2VzAIupVaIkj8E4Ao+hEsfmNQaR5RJkomkLkxqtazfGBqoedSU1Moh\n",
892 892 "gTSTWg9keD3jfVOLSa3dpBKIXpJauVJHHqTW0LNJ/D4ke6DUIoT0YjVrnkWb8ngQzuSEEFFqcU/r\n",
893 893 "JrF+6G1TK4qfZwoSlRaTWlbTR7tgUms30lJLW/J0qUlqea/rAQBWs+YC7fD3GcYPf1+nlPqhhCDi\n",
894 894 "plZ6rJ/TstSKCauhSa1cA/akB5RahJBTYAVxP3EknntaN3GZ1MJGwpVSPQSY1BrLWmopJVaZ1Nq+\n",
895 895 "HwvPQw1SK2ddT+ux5XpMpUgtT0ktT2em1Nq+/SFYPRuTWopQahFCToFj8fvhSPx+vEqt0va0AJtJ\n",
896 896 "LTdSK1Tdcu4LHYNJre37YVJLhqKSWtfuL/Vj4qbWcVKfm0mtDdbPOXaMvfu91s7GoXhFKLUIIadA\n",
897 897 "qbWfmNRi/fAmXuuHJUstS0ktq6JmH5oVREsJpS5a9UMLz4Ok1JIWP5HShuKBDCmnsMN4jnaH8SLV\n",
898 898 "7R4g56ZWzjfm65pXosSrpNSqbSje2hg7kH/EnkPxDqHUIoScAuuH+2FSaz9MatmB9cPxRJGiIbWs\n",
899 899 "CkDpAX1LSa0arn5Y2lB89/5SPqZ1ykloh9Fl/TA8NykSOxGJdFxtQ/FWK36A3RF7JrUUodQihJwC\n",
900 900 "k1r7YVJrP5RadmD9cDxMat0kSo+XCG2N1ZrU0pZaJSW1cog66SplVjGX8DZ3kfLsrB9usH5Oy5ta\n",
901 901 "Y0Urk1qKUGoRQk6BUms/TGrtJ0ot1g/1YVJrPJpSy2RS69rWWI40z3UsJbVqkFo564clJbW0pFbK\n",
902 902 "TS2J+mH39lOcXULEWZdFkdTnzFXxsyi1UtUPmdRSgFKLEHIKrB/uh0mt/cRNLa9JracPfpUvLCa1\n",
903 903 "TIqaAzCptRvJXa3aklpaaaZIzvqh9lC8Z6mVc1PLU1JLQsTVJrWsVvy632vtbJRailBqEUJOgUmt\n",
904 904 "/TCptR+v9cOYLGNSKy9MavXHsgCUlFqW5F4NSa0S64c50meu64dh6P4MwOVq1uQeuq81qcWh+O3b\n",
905 905 "H0Lu+uHQpBY3tRSh1CKEnAKl1n6Y1NoP64d2sJjUotTqjyWZcx2NpJaF+mENQ/E5q6WsHw4ndf1Q\n",
906 906 "8vwpzy6Z1Br7+8VLUqtGqZUqqcVNLQUotQghpxCl1uNCY8CeYFJrP+v6obPfNyVLLUtJLcvpo10w\n",
907 907 "qbUbJrXyoS21SkxqcSj+JlJ7Wt37SFk/5NUPE1xVspPYu8qQ2KtBajGppQClFiGkN6tZ8yzaN/gP\n",
908 908 "AHhM+TjWiFKLSa1rrGbN82hfEN5B3jd+qSlRapmqH4YXz5b2kfrApNZuNKSWhaRWDVKLQ/H98L6p\n",
909 909 "5TWp5al+6CGplfOMls83tn5IqaUIpRYh5FRYQbxGSB/F+iGTWrvxuKtVotSyVj+MYujdq1lzpXqS\n",
910 910 "/kSpJSFvrsOkVoslEVqD1OJQfD+8J7Uk5FAkR1KLQ/G2pRGQIEkGJrXIDii1CCGnwisg3uQRAOdo\n",
911 911 "35hLvzD3QqwgetrVKlFqmUpqwd+eFsCk1j6Y1MqHFamVM6nFofjTybWpJVk/rC2p5WEoXiKpNTQN\n",
912 912 "BeRPag197jgUrwilFiHkVJjUuglH4o/jOan19MGv8oXVpJbF5NE+uKm1Gya18qFV0YvkrB8yqTWc\n",
913 913 "XJtakvVDb0mtGobicw6eWz7fWOHGoXhFKLUIIadCqXUTjsQfx7PUYlIrH0xqnQaTWtv3YeF5qOHq\n",
914 914 "hxL1Qw7Fn07qTS2N+mHKqx9yKD5NEipn4ijFr3uu87F+6BhKLULIqbB+eBMmtY7jsX4Yz1qS1FoL\n",
915 915 "mcl8aeE1AKXWaTCp1aItebqwfjgODsUPh0mtFk/1Q09JLatSi0Px5AYWXtASQnzBpNZNmNQ6DpNa\n",
916 916 "BljNmkvoSpnrWJY0+4jyhkmtbWpNatUgtXIIoAjrh8PhplYLh+I3WJZG3du0eD4mtRxDqUUIORVK\n",
917 917 "rZswqXUcSi07WNrVYlLrNCxLQCa18qFV0YtwKL4f3pNakvXDlELOU1Kr6qH41ay5AHAF4GwyX54P\n",
918 918 "vBmrUismvLippQClFiHkVFg/vAmTWseJUstT/bB0qWVhV4tS6zQsJZSuw6RWPrQlXs7HyKTWcFJv\n",
919 919 "akmeP+XZmdTaYFpqXbtda4ko1g8dQ6lFCDkVJrVuwqTWceKmloukVvgJokfh0gdLY/Een2MmtXaj\n",
920 920 "IbUsJLVqGIqXqB9qJbU8S61cm1oSb8pTJrUknvearn5oPU1mNalFqaUIpRYh5FTWUmsyX56pnsQO\n",
921 921 "TGodx1v9MMqWZ8MOVUlYqh9aljT7YFJrNxr1QwvPA5Na49Aaii/h6oe5NrW8JbUk6ofern5oOakV\n",
922 922 "E1HW5JHVc5EeUGoRQk5iNWvejTZ18wCAu8rHsQKl1nG81Q9j9fDpg1/lEya1xqEitUJ68A7aPRJp\n",
923 923 "AdAH1g/zoS21cuxPRZjUGk7q+qHkphaH4vPgQWrF27VW87N6LtIDSi1CyBBYQdyG9cPjuKofYiPf\n",
924 924 "StvTAmwltSi1+rMWOatZcyV8333gUHw+tCVejlRTRCupxaH4m2jUD70ktTgUnw6rNT8OxTuGUosQ\n",
925 925 "MgRKrW2Y1DqOt/phqSPxgM2kFuuHx7Fe1WRSKx/aEo9D8f0oRWoxqXUTJrXSkUpqpZZHHIp3DKUW\n",
926 926 "IWQIvALiNkxqHYdSyw6WklpR1HhMaknImy6WRM4uak9qcSh+GFqPrSSplWpTS7J+yKH4PNQwFB+l\n",
927 927 "k7WkFqWWIpRahJAhMKm1DZNax4n1Q2+bWiVKLYtJLY9Si0mtbWpNasUzSNQPmdRKRwlD8ak3tTgU\n",
928 928 "vx8OxafDqjyyei7SA0otQsgQmNQKhPHmx9CONz+lfBzLMKllh5jUotQahvqmlvD99kVDallKaknU\n",
929 929 "D7U3tTgUf5hS6oeSm1qsH6aFUms4rB86hlKLEDIEJrU2xCtAPrWaNReqJ7ENpZYdLNYPraaPdsGk\n",
930 930 "1m406ofqgm81a+4DuARwazJfDn0zdIwa6ofc1DqdC7Q/UDufzJcp3tMxqbUfDsWnw6rU4lC8Yyi1\n",
931 931 "CCFDoNTawD2tfkQ59OhkvjxTPUk/SpZarB+Og1JrN7XWD4H8aS1tqVVi/dD91Q/DVVBTJp40NrVG\n",
932 932 "Sa3weoJJrQ01bGrlTmpZOxfpAaUWIWQIrB9u4J5WD0Ka4d0AzmBDphwjbn89ffCrfGIpqeVRaq23\n",
933 933 "eEL9WAovUktC9mlLnuvkllraEq+bCEr9e55D8eNImXiSrB+mkkQxHXOxmjWXI2/rEDVJLetnzJ3U\n",
934 934 "Yv3QIZRahJAhMKm1gUmt/niqIDKpJUOUWlZFzQ1COkIylRSJsshKOuk6NSe1sj32UCuTTNDcIPye\n",
935 935 "zzGs3r09DsUPI6Wckzx/qnNL/dlIfV6rwqj7vbnOaDURZVW2kR5QahFChrCWWk6qZDlhUqs/UWp5\n",
936 936 "uAJiyVLLUlIrihpPSS1Ap4LoJamVVWpdqxupSJ4diNTzglzSItdjZFJrHFXXDyGXLmNSKx1WE1Ec\n",
937 937 "incMpRYh5GRWs+Y9aAXFHWykTq1QavUnVvmY1NLFYlKLUus4lFotawmiLHm65JRaVq70mGssnlJr\n",
938 938 "HDmSWp6ufigl4jgUnw6riSgOxTuGUosQMhRWEFtYP+wP64c2sJTUotTqD6VWi7U9LSCv1LJypcfc\n",
939 939 "SS0OxQ8jx6YWk1o3qSmpZV28WZVaTGopQqlFCBkKpVYLk1r9Yf3QBlFqWUhqWRc1+6DUuomU1LK2\n",
940 940 "pwXISC1tiZf8MYa9sJhu0JJaTGpt8Fw/5KbW9u3WkNRKmogKFxq4AnAW/m46FUotRSi1CCFD4RUQ\n",
941 941 "W5jU6g/rhzZg/XA8lFo3kZZa2pKnSzxLjsduRWpllUAKVVJKrZt4TGp5qx9aF0bd77V6xijCc5xv\n",
942 942 "zNkotRSh1CKEDIVJrRYmtfrjqX4Y02QlSi0T9cMw+O3u6ocBSq2brJM8mS8gYqWO1yWeJeemlvbj\n",
943 943 "zZFG0xR2vPrhTTQ2tbzUD1NvgFm9smD3e61KrZznG/P8UWopQqlFCBkKpVYLk1r98SS1YlLr6YNf\n",
944 944 "5RMrSa34Zv2F1ay5UD3J6USxlDuV1CXel0mpFaobOXaKrmNF8nSpoX6Y49dW87ExqXUTyfOn2gKT\n",
945 945 "TmpZr0umkG+1bmp1b3PIFRA5FK8IpRYhZCisH7YwqdWfKIi4qaWLiaQWNskjb9VDYCOWJJ9D60kt\n",
946 946 "QKaCaEXydKlBauVINlmQWt6H4lP+unje1JJKalnf1IpC5XxEYrbmpBbrh06h1CKEDIVJrRYmtfrj\n",
947 947 "MalVotRaJ7Uy18SOEZNizx78KpvE55D1w20kpBaTWjqUVj9kUusmnuuHUkPxpuuHYZvOsjTq3q7F\n",
948 948 "80UpOCSpRamlCKUWIWQolFotTGr1x4XUCle9icLFY4roIKHq9zyAM+StiR3D60g8wE2tfTCplR4r\n",
949 949 "Ei+HBIrPl/SVD4HtRMt5otvUlFopfu9pDMWnkkRe6ocS4mPsWa3vfjGpRW5AqUUIGUr19cPJfPkS\n",
950 950 "tG8078Nn2kQaL/XDtWxxuPXUFwu7Wp7FYTwz64fbSGyNWZE8XXLKPCsSL4e4i2+6xR9bSLTE+x0r\n",
951 951 "ViLek1qsH+7HS/2we9sWpVH3dk9OQwUBfQbgKtPrszHPXc6rMpIjUGoRQoYSk1qvVq4waRJTWk8q\n",
952 952 "XI7cIy6SWii7ehixsKsV79ujEGZSazdMaqXHyuMtrX4IpE+fed/U0khqeRmKX9fShr7mDd8nIT7G\n",
953 953 "PreWh+KlUmRj6occileAUosQMojVrHkOraS4g43cqQ1WD0/Di9SKSbIafiAAkQAAIABJREFUpJZm\n",
954 954 "Ustz/VAzqWUpoXQdbmqlJz5ebamVs36oLbVS/bp5T2p53tTKeubEW1X3M/8g1EtSy6LUsnw2cgBK\n",
955 955 "LULIGGqvIHIk/jSi1LJeP6whqWWpfsikVj+Y1Nq+7VqkVrxN7cfLpNYBQgpHUgpFUoo5yTfl3obi\n",
956 956 "u/dhdasqYv2clsWR5bORA1BqEULGUPtYPJNapxE3tawntaLUevrgV/mGSa1xcFNrN6wfpsfK402d\n",
957 957 "aurelnupBSBu/VwIbzGmfAySvx7e6ofd+7CagIrUkNTKVfHj1Q+dQqlFCBlD7VKLSa3T8FI/rCGp\n",
958 958 "ZUFqMal1GpRa27etnVzqEiVADUPxJdUPve5RdfH6GFJdTVAyHWf9qoKRsfLN8qZW7k2yFGfjppYC\n",
959 959 "lFqEkDHUXj9kUus0ngVwBeDhyXw55KdgUlBqycCk1mlQarVoi5BdxMedc1NLW+LlrB9Ki6BIjj0q\n",
960 960 "6cfi9TGMFS8RT1dslHp+rcs3yxU/JrWcQqlFCBkDk1otTGr1IAyjxkrfI4e+VpkapFZ8bJRaw2BS\n",
961 961 "aze1J7VqqB+mTGrF2yqhfqgttVL83hP79QgVzUsAtybz5fmIm9IYt7da64tYP6dlqTXobGFTj1JL\n",
962 962 "EUotQsgYapdaTGqdjocKYg1SKya1NOWi5/ohk1q7qTWpVYPUKnkoPqUQYlKrPynO7qkyKb2pZfWc\n",
963 963 "MQ1VjNRCu6kHAJerWXOZ8DykJ5RahJAx1F4/ZFLrdCi1bMD64ThEk1qhrnsbbX1Xq6rVBya10hMf\n",
964 964 "L6VWejwLoUiOoXhPUstT/ZBD8du3a7HiN7R+yJSWMpRahJAxMKnVwqRWf2L98FHVUxwmno1SKy9M\n",
965 965 "avUnio33hBqvVWqXWjmH4rUfb476obbU8jqy3iXJYwgVwJg2kRq6TpnUYv1wg/Xtr+Lqh+BIvDqU\n",
966 966 "WoSQMdQutV4RPjKp1R8mtWxgQWoxqdUfD9VDoN76Yc6heCuPl0mtw2gntcb+usQ38c8LinNvSa2x\n",
967 967 "tT7poXir8q1EqcWkljKUWoSQMayl1mS+rPHvkyi1fl/1FL7wJLWePvhVvonCjptaw5BOalFqbbCc\n",
968 968 "1CpZaqXcn4poP7aSpNbYx6Bxfq9JLev1Q+vntCy1WD90So1vQgkhiVjNmucAPIX2L//3OvLlJRI3\n",
969 969 "tSi1+hOlluX6IZNaMjCp1R9KrQ3aImQXEpta2hIvZVUvIr3hdB0OxW/Q+LUYm3zqfq/kppbVBFSE\n",
970 970 "Sa3hMKnlFEotQshYqqwghv2Ju2iHm7mp1Z+YfrKc1OKmlgyepRaTWrthUis9ViRejscYhQSTWsNJ\n",
971 971 "JRs1k1pD5Uv3ez3UD6WTWkOfVw+bWrm2q5jUcgqlFiFkLLVeAfG9AJwBuLeaNRfah3GEh/phlFol\n",
972 972 "1w8tSC3P9cN1UmsyX54J3B+l1gYrkqdLDVKrxKH4EqRWqrQZ64fHsV7ri1iXbyUmtTgUrwylFiFk\n",
973 973 "LFUmtcA9raF4qB9SasngNqm1mjX30b74vYW0b/L3EaWWpXTSLmpPauV43PE2taVWiUPxJVz9MPWm\n",
974 974 "luSvhbeh+FQJKOtJLaviCNjII2tnY1JLGUotQshYotSqLalFqTUMT/XDkqUWh+LHI7mrxaTWhihC\n",
975 975 "LEktiasfaj/eEqVWjqSW9JtaDsW3SDzvqRJQUlc/PPmcIXlsVRx1v4dD8WQLSi1CyFhi/ZBJLdIH\n",
976 976 "1g9twKTWeCR3tSi1NlhJLnVh/XAY2o8t5VC81mNJlTbTGIpPKbUkk1pDzyt11hRJqIvVrLlKdJ7r\n",
977 977 "RHFkUWoxqeUUSi1CyFhYPySnQKllA0tSi0mt41BqbbBcPyxZajGpdRitx1L7ppbGUPzYWl/us455\n",
978 978 "XiV+H8Tn8dQ0FECpRfZAqUUIGUutQ/GUWsOIosjkptZkvryD9s3BJewLhDGoSq1w9VCLcuIUmNS6\n",
979 979 "iaTUsvRc5JRaVv6c5JRa0jtUkZKkVq2bWp6G4j0ktSTkjOXzDa0fciheGUotQshYak9qPal6Cn9Y\n",
980 980 "T2qtU1oZo/cWiFLrEaGr910nSpp3O36emdS6SRQvOZ8Ti6P5a+GT4c+TdpopUmL9kEPxG5jUOk4q\n",
981 981 "qSU1FD/knLVLLSa1nEKpRQgZS+1Si0mt03AjtVRPkZnVrHkR7QvfW8iTLjmG95F4gEmtXVRZP1zN\n",
982 982 "mkuMH5Heh7b4ieRIammkg7qUkNRKJeY0pNbYOh+gMxQ/9uqHTGpt39cpWE1qUWopQ6lFCBnLWmpN\n",
983 983 "5sua/k6h1BqG6fohKpFaAc0KoveReEA2qWWxcreLrFIrpKAsJrWAfBVEK8P4JSa1SpBaqTa1OBR/\n",
984 984 "nLHnld7UGiKNJDe1LEotJrWcUtMbUEJIBlaz5nkA9wCcA3i58nEkodQaBpNadrAgtZjU6geTWi13\n",
985 985 "AJwBeHE1ay4y3cdQkkutIPG000yRkofiUzwm1g9Pp9b6oVRSi/XD06HUcgqlFiEkBTVWECm1hvE8\n",
986 986 "2n/0H5jMlxq1t2PUKLUeUbjvKNKY1OoHpdb27VpLaQF5Hvu6WhUqjpqULLVKSGpxKD4/XuqHY5Ja\n",
987 987 "XqRWrkF2DsU7hVKLEJKCGq+ASKk1gDAKHtNaFiuINUmtZ8JHJrWGwaTWTXJLLcvPQ3zsJUmfLmsB\n",
988 988 "kXAMX/vxpRyK56bW6dSa1Mot4EpOakV5xKQW2YJSixCSgqqSWuEFPaXWcKIwslhBrElqadYPmdQ6\n",
989 989 "Dcsyp8v6DXamjcXaklpmHm9Iit1HW/8cM+zdRWPHqUvKpJZWTTS+iR575U3vm1oSMsFL/bCGpBal\n",
990 990 "FtmCUosQkoKqpBbaZMaDaF+8en5TroXlXS1KLRlKGIpnUusaIYmZazAdsP085JBa2kmm66ROo2k/\n",
991 991 "vpSbWiqCLmzLXaCVjecjbsprUkvy3GPrh1KpsjFJLYnnM+4h3hrwww9e/ZDshFKLEJKC2uqH65RW\n",
992 992 "eBNHToNSywYWpJbn+qFGUks9sdODnBVEM8mlHdQgtVILS+0R/BxSS+OxeJNDkVrrh1JSy2ISKv7w\n",
993 993 "w6o8YlLLKZRahJAU1JbUYvVwHJRaNuBQ/DiY1NpNTqllWe7lrB8WJ7VCVU5b2qWUdKVILY2h+DF1\n",
994 994 "VtYPbzLmnFJyxqo8irfLoXhnUGoRQlJQm9R6efhIqTWMp8LHx1RPsZuapBaH4sfBTa3dSCS1LD4P\n",
995 995 "OZNaViReyse4voqZ4pUdU0otjaRTJMXj0Dj/mJpcRDKplerqh1aFUfd7rJ5Rqn5o7VzkCJRahJAU\n",
996 996 "VFs/VD2FX2JSy7LUetfBryoDDsWPg0mt3bB+mA7tJNN1Skk2RUp5PCmSWhyKP04NSS3rFUnWD8lO\n",
997 997 "KLUIISmoLalFqTUOJrVsYGFTy7PUYlJrNxL1Q4vPQw1SK+VjtPDYKLU2uNvUChXWWPvyILWkh+KZ\n",
998 998 "1Dodq1tf5AiUWoSQFDwRPr4602XcrUGpNY4otbippYvmplYJ9UMmtXbDpFY6rD3eHBJIo64XyVE/\n",
999 999 "9C61NDa1xkqiF4Uu2pOqfiiV1KLUOh2r5yJHqOHNJyEkM6tZ8zyAP0B7OelXHPnyEqDUGgeTWjZg\n",
1000 1000 "/XAcTGrthkPx6bCQZurCpNZ+NCWd102tVHU+KZHg5bxjtsootbbvpy8cileGUosQkoqadrUotcbh\n",
1001 1001 "YVOrBqnFofhxMKm1Gw7Fp8OC+OlSSrIpwvrhBo+bWpIj8d378bKpVXJSK5c8Yv3QKZRahJBUUGqR\n",
1002 1002 "vlhOasVKZA1Si0mtcYgktcJujGWZcx3WD9MRb8ua1GJS6ybepRaTWsfxUj8ck9SSOuPQqwzm3lCz\n",
1003 1003 "miAjR6DUIoSk4u3h42tVTyEDpdY4uKllAwtD8UxqHecO2tdr91ezxkO1gfXDdERRYuXxxnN4l0CR\n",
1004 1004 "HMkzjfqhd6llXRJFvCTLPA3FW0tEWT0XOQKlFiEkFTGpRalFjmEyqRUSMTVKLY2heCa1+uOpeghs\n",
1005 1005 "zsn64XgsiJ8upSSbIvEN6PlkvjwfeVuajyflppbk+cckigDWD/cx5pxe6oe5r37ITS1nUGoRQlLB\n",
1006 1006 "pBbpi9VNrYfQ/rv4/GrW1PDTNgtJLc9SSyqp5U1qMamVDgvip0tRQ/Hhinnx/seknADWD4dQa/3Q\n",
1007 1007 "qjDqfo/VM1odimdSSxlKLUJIKqLUKnpTK/w09y6AK7RXfCSnYzKphbpSWgCH4sfCpNZuOBSfDqub\n",
1008 1008 "Wt6vFtgl1WPSHL7nULwMNSS1pHe/rMkjDsU7hVKLEJKKWpJa7wXgDMC91ay50D6MU2JS62Wh8meF\n",
1009 1009 "2qQWh+LHEcXKw5l/H1NqbahtKN7qplYRSa1r9z9WamlKOia1ZPBSl2RSazhWz0WOQKlFCElFLZta\n",
1010 1010 "rB6OJFT73o323yANobKPWqWWxqaW+6RWGG1/Ea3kHltdOoTlyt0uWD9MhxXxE8kxrK792EY/psl8\n",
1011 1011 "eQvyqaEuKTe1PEot6aSW9WH7Meek1Nq+n75QailDqUUISUUtSS1KrTRY3NWqVWrlThptEe6rhKQW\n",
1012 1012 "ILOrxaTWhtrqh1alFpNa26yFVtjpkiZlUkvy14P1wzysK3QD/m2vXWoNrR9yKF4ZSi1CSCruoX0x\n",
1013 1013 "9MhkvtRIfkhBqZUGi7taVUmtUJ99Hm3SKPcuVJc7AM4BvFjAIL/Erhal1obaklrW6pbxHKVc/bB7\n",
1014 1014 "/2Mek/Y+GOuHMoytH4qcN4hVq9IoYvV8Vs9FjkCpRQhJQvhHtIax+Ci1nlQ9hX+i1HqZ6im2qUpq\n",
1015 1015 "BTTG4ku48mGESa2bMKmVDiviJ5JjKF77saWUWlqPxftQ/NA6n3RSay08BqabJcXhUAFX+1B8vF0O\n",
1016 1016 "xTuDUosQkpIadrWY1EoDk1o20NjVKqV6CMgktbztj3EoPh3asuQ6HIrfjfZjqX1TS0QkrGbNJQbW\n",
1017 1017 "08Lu2nn4VKKiZlUaReJzMPR8uZ7Dseei1FKCUosQkpKaklqUWuPgppYNNK6A6E3SHIJJrZuwfpiO\n",
1018 1018 "eFva4ieSI6mlVdmLpBRCnpNaGo8hVZ1P8vfQ0DNL764N/T0hXT8cul2V63zxqubnJ6bxKLWUodQi\n",
1019 1019 "hKSkhrF4Sq00MKllAw2pxaTWaXira7J+mI4oWqxIPCa1dqMt6Grd1NK44uTQyqTW/pfVxJHJ8wXh\n",
1020 1020 "OCSNx6F4ZSi1CCEpqaF++PLwkVJrHNzUsoGm1Hrm4Ff5QCKpRam1obaklhXxE0mZ1NJON0VKqB96\n",
1021 1021 "3dRKtVElmY4Z+lxLS0Pr5zQpta7d9ilnY1JLGUotQkhKmNQifbGc1HrXwa8qiyiWJDe14n2VUD9k\n",
1022 1022 "Uusm3NRKh7YsuU48B5Na22gLuiggBj2GsPeUu9Z1g5FX6et+j4f6obTUsiyNurdv8XyUWg6h1CKE\n",
1023 1023 "pISbWqQv3NSygcbVD+N9lSC1mNS6CeuH6bAm8eI5ePXDbbTrh/ExjK3xvSi099RlTMpMM6k1VMZY\n",
1024 1024 "T2qZlVpBvkZ3cXHoa0cyZCyeUksZSi1CSEqY1CJ9sZzUqlFqaSS1SqgfRrkiMRRPqcX6oTZMau1G\n",
1025 1025 "+7GkuoqgxvlTSC0PO2BMam0zKg2VWb4OEZeUWspQahFCUlLDphalVhq4qWUDDalVYlJLon5oMZ20\n",
1026 1026 "iyxSazJfnqN943AF/Svm3WA1a+6jTQ+cT+bLU6/otQ8mtfJDqaUjhyJDk0/d7/FUP5SSHmMTZaal\n",
1027 1027 "VuKzXGfIc8eheGUotQghKXkC7RuOV03myyEvUEwzmS8fRvsm43n4SU1YhUktG2hKrRKSWhJD+17r\n",
1028 1028 "h6lF31rwKFSk+pJa6FmrW6Yciteu7EWq39SC7q9FLfVDraSW1USZZak15LljUksZSi1CSDLCT6qf\n",
1029 1029 "CJ++WvMsmVintAy/qfKCxU2tmBrjUHxeShqK56bWTXLVD62llnaR+rFbq1uyfrgbbUE3dlNLM6k1\n",
1030 1030 "VL4AOkmtsVtV0ptaTGqdzpBfY0otZVLFo09iOp02AL4SwIegjen9PIC/vFgsfqnn978VwB/a839/\n",
1031 1031 "6WKx+J9TnJMQMoi3A3gN2gribyufJTWsHqbDYlKLUkuGEuuHTGptyC21rKSWdpErqWVFaqWsH2qn\n",
1032 1032 "myKsH/rf1JIUCdYTUJGh55SSM2PG2HNX/Lip5RDxpNZ0Ov0zAH4c7fbO5wP4YrR/4H56Op1+eM+b\n",
1033 1033 "uQLwPQBev+N/b0p4XELI6ZS8q0WplQ6Lm1qUWjKUWD/kUPyGXPVDa6mlXZQutZjU2o22oCthU8vb\n",
1034 1034 "ULyX+qH1pNYpAZv4tawfkhuIJrWm0+lDAL4VwHcuFovP6fz3NwH4CQDfAuCP9ry5f7NYLH46/SkJ\n",
1035 1035 "ISMp+QqIlFrpMJXUmsyXD6B9o3YB20mQ1LB+OA7WD2/yAtofPt6ezJe3Qy09BVUltcLY/DmAS9gZ\n",
1036 1036 "H+ZQ/G60H8vYTS2vUktDJIy9+qH0ULzVRFlp9UMOxSsjndT6NLQ7O3+5+x8Xi8UlgK8C8GHT6XQi\n",
1037 1037 "fCZCSFqi1Hpc9RR5oNRKx3No//F/cDJfpniDNJY4Ev+uyvbSWD8ch+RQvGWZsyb8+YlnTZnWqi2p\n",
1038 1038 "tZZ4hv5OYlJrN943tbwOxWv8HvJWP7Se1LIstSyejexBWmq9HsCvLBaLt+34/34ObeXjY3re1lmq\n",
1039 1039 "QxFCksL6ITlKeJNmKa1VY/UQYP1wLExq7SaeNaXUslbF20VKqWVR4r2ITQrvfORtlSS1WD8cztA6\n",
1040 1040 "H+Crfqg1FG91U8uy1DpJXE7my1vYOJWLLCciR5Eeiv8AAL+26/9YLBYX0+n0NwG8f4/bOQPwH0+n\n",
1041 1041 "088E8EoAbwPw9wH8tcVioX1pYEJqh/VD0pen0D6nL8Pmqpla1Cq1ng4fHz34VWlh/fA0PEqtHEmt\n",
1042 1042 "quqHMCjxVrPmajJfPo/2bA9i3O9J7XRTpKT6YW1D8RrPu/VaX4RJreGc+mu8PpehVG11SCe1Xg7g\n",
1043 1043 "3oH//x5aSXWMdwL4TgBfBODT0e5xfSWA759Op0xwEaIL64ekLxaTWk8d/KryYP1wHJL1Q49SK6Xs\n",
1044 1044 "s5hcuk7RUiuQQgJ1v7+EpJa2oKt1U8tj/VB6U4tS63ROfe5YPTSAdFLrERz+Cdt70O9KWH98sVh0\n",
1045 1045 "h9h+ZDqdvhnt0PwbAHzb4BMSQsbCpBbpS0xFWZJatSW1NIfiWT88wmS+PMNG5lhOKF0nZ/3Q8vOQ\n",
1046 1046 "ZVMrwW2l5Dm0f2ePlVralb1ICUmtWje1PNUPtZJaVhNlQ6SW9Nn6PncciTfAKKk1nU6/DMBf6/Gl\n",
1047 1047 "P7VYLBq0NYdDL3AeRo83i9eEVvxv3zqdTr8EwOeAUosQTeKm1uOT+fKssCgupVZaLCa1KLXyw6RW\n",
1048 1048 "fx5EO7nw/GrWeNrq4FD8eKw+3lRj8doiKMJNLd2k1lD5ArB+eIgSk1pSz+Hg+mGGs5CejK0f/l0A\n",
1049 1049 "r+vxv88NX/8kgPc6cHuPYdybxZ8M90cIUWI1a96NVgw8gLZyXBKUWmmh1NLnPWiHnx9KMPzcl5Kk\n",
1050 1050 "Vu5NLVdXPuyQ43mxWsfrUkP9MJ6nlPrh2Ope93sptU6nlvqh9FD8yecMyeAYeMktaGJAxbLUYv3Q\n",
1051 1051 "EaOSWovF4g8A/MEJ3/JbAD5i1/8xnU5voR2S/64RR3oBjP4RYoG3o5UEj6MsAUSplZa4sUippcRq\n",
1052 1052 "1lxO5stn0Sa1XorMjz+8aOZQfH887mkBHIovWWoxqXWTUja1vA3Fs364nyFJqOgFLgRaFvF8p7gI\n",
1053 1053 "KTF4qhCk1DKA9FD8TwH4I9Pp9A/t+P8+Cu2bip86dAPT6fRsOp3uu0LiRwH4lTEHJIQkobhdrcl8\n",
1054 1054 "eRvAXbSpllNkPtlPlFp3VU/REsVaVVIrIFlBfBDta48XVrOmhBeAUbC8JFPSjVJrg9U6XpdaNrWA\n",
1055 1055 "ERIo/Ht6C8DVatZo/zC6qPph+MHBqTCp1R9vQ/GnnFPy9wHrhyQp0lLr+wG8A8DXdv9jSGl9FYA3\n",
1056 1056 "LxaLVfe/T6fT11y7jX8E4J9Np9OtK6tNp9PPRpsC+18ynJsQchpxV6sYqYW2SnkG4Eln2zaWifVD\n",
1057 1057 "C1KryqRWQFJqlVQ9RPhpdo5R9Ei8TW9Si/XD8ViVeCmSWlFGWBB27ofiw2uSC7SvUYbIdQtD8acm\n",
1058 1058 "nwDdpJb1TS3LVxfs3odlqdX3bByKN4Do1Q8Xi8V7ptPpFwH4nul0egfAIpzhCwFMAPzJa9/ytwB8\n",
1059 1059 "wXQ6/ejFYvF/hP/2DQA+Ca3Y+joAbwPwcQD+awB/b7FYfJ/AQyGEHKa4pBaAV4WP71A9RVmwfmgD\n",
1060 1060 "SalV0pUPI8+ilTcPI/3jYlJrg4erQNZUPxwjgSw9thLqh/G+H0L7xv/UN9dMavVn7AC79FD8Kc8r\n",
1061 1061 "pVYL64cOkU5qYbFY/ACATwDwPgDeCOBvo/3pwscsFotfuPbl/wZtzeepzvf/ItpE1grA1wD4XgB/\n",
1062 1062 "AsAXLRaLL8z+AAghfYhS6/GDX+WLKLXeqXqKsrBUP6TUYlJrKFE45bgCIqXWBksiZB/xbCket9XH\n",
1063 1063 "m0LcWXps7pNagTG7Wl43tTzWD5nU2r4Pi1KL9UOHiCa1IovF4icA/ESPr/satOLq+n//VwD+kwxH\n",
1064 1064 "I4SkocT64SvDRya10sH6oQ00klolSq0cY/G8+uEGqxtTXZjU6oelx1bCphbgb3A94u3cXuqHTGoN\n",
1065 1065 "h1c/dIh4UosQUgWsH5I+sH5og6fDR8mkVmn1Q4BJrS4cih+PVYk3eige5UktC0mteN9jEk8aUmto\n",
1066 1066 "8gnwVT+UHoq3LI0A2+c79fckN7UMQKlFCMkB64ekD6wf2oD1w3HkTGp5HYqvvX7IofjDWPq1LGlT\n",
1067 1067 "C/CTeIqwfpiHIfKNSa3t22f90BGUWoSQHJSY1GL9MD2sH9qA9cNxxMeSs37oTWrlEH0cirdByqSW\n",
1068 1068 "ZrIpspZak/nybOBtWKofjtnU8ia1PNUPpYfih8g3Sq3t22f90BGUWoSQHPwB2n8UXjaZL3O80dOA\n",
1069 1069 "9cP0RKn12Ig3E6mIUuupg19VJhpJrZLqhxyKvwmTWuOx+niLSmqtZs19AJcAzjB8a9hC/TCFHHIz\n",
1070 1070 "FD+ZL88BnAO4gmzta2z9kEPxLfHXzKLUGnr1Q82kZvVQahFCkrOaNVcobyye9cPErGbNC2jfrJ8j\n",
1071 1071 "jxDoRXhx/FK0L45LShD1JQqmRwXui/XD06DU2mB1Y6pLDZtapQ3FA+Mfk4X64ZhNLQtJrVMl0f/f\n",
1072 1072 "3r1Hy3Ke9Z3/HZ1zdD/SkWzL8l22ZLADNhfTjh0mCWkDBnKZQEjNsJIANhMw10wGN5e1AhjICmZ6\n",
1073 1073 "uCXGkwyGsIAQKGIu42AIthubECZxG2wMlgy2ZfluXay7ZOlcdOaP93171+7dXV1VXVXv81Z9P2tp\n",
1074 1074 "lc7evXu/fdl7d/36eZ53FST615x92bf9sK9qniZhYYyZWnWCZKvthzF/fuARagHoytDmatF+2A0L\n",
1075 1075 "LYghzLm/5xfHVtB+uJ8+BsVbCzZ26bL90EoQsskYZmq1cRuHFmpZaj9MbVB8KrsJBqms13ql1pDa\n",
1076 1076 "Dwm1DCDUAtCVUKn15KiraA/th92wsAPimOdpSbQf7otKraNoP9yf1dtLpdZRltoPU52pVXfdse7z\n",
1077 1077 "VNoPm4RvhFpO3Wo8Qi0DCLUAdOXj/ph8+6Gf90T7YTcs7IBIqOWw+2EzXQ6KT3X3QwbF789a8BO0\n",
1078 1078 "OSjeym0j1Dp8HX1quu5Ya27afhhrUHyT0KiP5/Gq/bDGTFXaD7EVoRaArnzMH58SdRXtOCX3wuCh\n",
1079 1079 "5Wxq+YQqRRbaD0OVGKFW94bYfsig+KOo1Nqf9ZlaQ2w/rN2650/I+56XtEkbM7VihHJNA0Uqtco1\n",
1080 1080 "qdTqrQ3Vj3o47/9Zda4W7YfYilALQFeGFGpRpdUd2g/jo/1wP7QfHkWotT/rM7Wo1HJWLVvL2fSx\n",
1081 1081 "ltbTxD7PvZgn5amGWtYHxVuv1JLqr5H2Q2xFqAWgK6H9cAgztZin1R3aD+OjUms/XbYfphpq0X64\n",
1082 1082 "P2vBTzDkSq0moZaF1sPi99/nNsQ4KW8akqbWfhirUqtOqNX388BqqEX7YYIItQB0ZUiVWux82B1C\n",
1083 1083 "rfge8EcqtZrpo/3QcpCzSauVWpP54iIRalnBoPjDYgZCRftU0FGpVV3T9sNYM7XqhG/Wd2gk1MJW\n",
1084 1084 "hFoAurIKtWoMgbSK9sPuhJlatB/Gw6D4/TAo/qi22w9XIUjkFq9dVqFWC3/3rAU/QRvBXQgkrNy2\n",
1085 1085 "fUKtmPOoivapoGOmVnX7th+mUKnV1316zh+thVpWwzaUINQC0JX75E5srpAbtJ4y2g+7Q6VWfLQf\n",
1086 1086 "7odB8UetQq2W3tRIoUpLy9n0nNzw44tUffjxNtYHxVOpdfhrrIRaY6nUov2w3JArtbqeS0alVoII\n",
1087 1087 "tQB0wu9sMpQWRNoPu0OoFd8qlPFtXl0acvshM7U8X03VxuylIKX7oa0WROuD4pmpdfhrYoda+zwu\n",
1088 1088 "MVsoU63Uarr7oeVB8X3fp1Yrogi1EkSoBaBLIdRKfVg87YfdCe2HhFqRLGfT83JhwTG1u1vdJrQf\n",
1089 1089 "1pNSmLOuzRbElO6HtkIta8FPQKXWYVZmao2tUit2qGW9sqxJm6T1FknaD7EVoRaALoUdEFOv1KL9\n",
1090 1090 "sDuhUouZWnH11YJI+2E9KYU569qsYEui/dAbeqi1z0DywNptG8JMrX2edymGWrHW3HSmVqxB8ZYr\n",
1091 1091 "teo+9lRqYStCLQBdGlr7IZVa7bPUfnhf6aWGrfNQazJfHJc74bqgNMKJqjqp1PKzqFLd/VCiUqtx\n",
1092 1092 "qDWZL07IzeR6TP21K1XVRlvpkEItK+2HqVabNX0+xbrfUwnhUqrUshYeWV0XShBqAejS0NoPqdRq\n",
1093 1093 "H+2HNoRQq8tNHUIl08PGd7Crq6uZWhfLtYSe8S2iqQn3C6FWfcXdHi/suZ620X54mJX2wzZmasV4\n",
1094 1094 "PFYBQs1NJWIPij9RdQalv12hYqqvkDrsLHi8xv1KpZZD+2GCCLUAdIn2Q+xC+6ENfbQfDnGeltRd\n",
1095 1095 "+2FKQc4moVJrrO2H+4R51kKfIgbFH2al/bDRbfAVtCfkKmh7rwr0b3A02akvSqWWD5nr3tchHDnX\n",
1096 1096 "V0jtv4/1cMZqRZTVdaEEoRaALiXffjiZLy6Rq145r3G3p3Xl03IvvC6dzBdt7JLWBKFWv6HWkHY+\n",
1097 1097 "1HI2PSP3rviJyXxRd0esMkMJtcZWqRVu95BCnyIqtQ6z0n7YNGybwyPTAAAgAElEQVRcrT9iVWCT\n",
1098 1098 "+z/m/W61wmhd3bCQSq3D10+olRBCLQBdGkL74Wrnw4G1TJngX0SHsDBWtVb4voRa3YZaQxwSH3RR\n",
1099 1099 "rZVSkLPJWNsP26hQsxb6FFGpdZiVUKvpbbDwWDRZe0rD7fseEh9Y3V0wsBoehXb/4xVbTAm1DCDU\n",
1100 1100 "AtClT/jjk3yJe4qu88fbo65i2KK1IPqBzKfkWi8e6Pv7G0L74X66GBafUpCzyVjbD9sI8yzf3tUJ\n",
1101 1101 "fc0ZSEUWgpSiNtoPY5/Q7l2p1eJa6mqyoyaVWruFSq2q67ReqdVLOOjfbK0TCFr5HTBqhFoAOrOc\n",
1102 1102 "TR+V2zHwuA7CodSEdd8RdRXDFnMHxFXr4cgr8UKg18eg+CGGWl0Mi7ccbFQx9vbDQc7U2mMGUpG1\n",
1103 1103 "20elVnqVWimGWn3PLAvrtFYJFVit1Cp+jyprI9QygFALQNfCsPhUWxAJtboXcwfEUB12b+mlhi+E\n",
1104 1104 "Wl1WaoXAbIgVcbQfHkX7YXMWgoYy+87Vsnb7hhBqpVypNfT2w1hrbbrOviu1dgZHvtvjuFxVfR+7\n",
1105 1105 "AdcZsk+oZQChFoCupT4snvbD7sXcATEEaWPfBCAETVeVXmo/Qw61aD88qs32w3AdKVSttRHmWQt9\n",
1106 1106 "1hFqHbAQChW/P5Va3TPZNrdB+H512w/7rtSqsr7VfdjThgZUaiWGUAtA11IfFv9Ef6RSqzsx2w+p\n",
1107 1107 "1HL6aD8ccqhFpdZRbbYfhutI4b5os/3Qaoi377B4C0FK0T6hlpXHquljYuGx2KdSK4VQi0qtzeq0\n",
1108 1108 "R1pujSTUMoBQC0DXQvth6pVahFrdCYHSNRG+N5VaTtj5kUqtZqjUOor2w+bCfWYl9FkX1lX7sfVt\n",
1109 1109 "RCfl2oj6njG0zT6hlpXHqultsFBpFr53nUCu76qioqGGWpYrtfq+D2k/TAyhFoCuDaX9kFCrO1Rq\n",
1110 1110 "xddHpVaY1/Vg6aXS1MWg+JRa7jbpov0whVBrDO2H4bFtUqkVTmAf6amNqIo2KrViP1Zjq9RKqf0w\n",
1111 1111 "tUHxVGpRqZUcQi0AXUu9/ZCZWt27xx+p1IqHSq39dNF+mHoI2EX7YQoB36B3P/T2uY0Wb9sQQq0h\n",
1112 1112 "VGoxKL5dVGo1R6iVGEItAF2j/RC7xAy1qNRymKm1ny7aD0NA9lDppewaa/thG1V7VuY0bUOodcDK\n",
1113 1113 "7WFQfH9SGRTPTK3maD9MDKEWgK4l2344mS+O6SDUujPmWgaOSq34qNTaTxfthyHUSr1Sa2zth21U\n",
1114 1114 "almZ07QNodYBKwFk0/bDVTtoi2upa+ihFpVam1GphdYQagHo2l1y73hcM5kv2njHvk9Xy/2xenA5\n",
1115 1115 "m6ZwMpUqKrXio1JrP6Gaqov2Qyq1aD+0hlDrgJUA8pzc8P3jk/niRI2vC48H7YfVpTZTi0qt+gi1\n",
1116 1116 "EkOoBaBTy9n0MUmf8P9Mba4WrYf9oFIrvj4qtUJIQ6hVTerth23O1EqpUqvN9sPYQck2Qwu1mlY5\n",
1117 1117 "Fb8m6u3xQ/fDGuqEQxbWT6VWN6jUaq5S+6Hv6IgVWqKAUAtAH1JtQWRIfD9CqHVthO9NpZYTWtyu\n",
1118 1118 "nMwXXb02CJVaqbbTlVndfy1e51AGxdN+WJ+FoKFMWBehlq3bk1o4FDQJ4wi1drO+TsvVUFXXdlzS\n",
1119 1119 "MUnnl7Pp+W6XhDKEWgD6kOoOiFRq9SOEWqc7DFS2oVJLq4rKEJ60WW1UNOT2wy5CrdQrtWg/bM76\n",
1120 1120 "7d3nNloIUdYNpfKsSThnYf1Dbz+MNSi+ciXUWsVRX+uscz9aDbVoPTSCUAtAH1LdAfGJ/kio1aHl\n",
1121 1121 "bHpWLhS4SN3OdNqESq0DIWzqqgWRUKue1EMt2g+bsxA0lBlKCBS0UallIYDcp1IrtVCLSq3d6qwz\n",
1122 1122 "BG/n/JtcfbBcqVV190NCLSMItQD0gUot7BJrrhaVWge6HhY/5FArBE+0Hx6g/bA5i8FP0dBCrX1u\n",
1123 1123 "j5VB8dJ+lVoMiq+u6ayqWIPiq4RGMUJCKrXQGkItAH1gphZ26T3U8uX2oVKLUKvDYfGT+eISuXc8\n",
1124 1124 "z8lW21FbqNQ6qpX2w8l8cVJubsl5X9VpHaFWOYu3bXXyP5kvjtf8Wku3p0k4ZGH9Yd11wriUKrVi\n",
1125 1125 "VcNZDo2K38tipRahVmIItQD0IdX2Qyq1+hOjUusyuaDl0eVsauGEJLYuK7VWOx/6XbqGhlDrqLYq\n",
1126 1126 "tVKq0pLabT+00NK2SVhX6oPVJe21c6Bk6/Y0qdSyMONs6O2HsZ4jddZJpdZhtB8mhlALQB9oP8Qu\n",
1127 1127 "MUIt5mkd1lmllobdeih1M2R/KO2H+87USi3UanNQvIWgZJOhVWpJzW+TpduTeqXW0NsP+w7gLIdG\n",
1128 1128 "xe9Vp1Krr2pdKrUSQ6gFoA+rSi3f8pUKQq3+xAi1mKd1WJeVWuE6Uw1odmm1Usv/nky6Usu3Cp6T\n",
1129 1129 "dNy3EDZlfSfAdY9KuqBmrWyBhaChzBBDrabD4i3dnlFUavnfj1Rq7UalVnOEWokh1ALQueVs+qBc\n",
1130 1130 "Fcglkq6NvJw62P2wP1RqxUelVnNttx9eKumYpEeWs+n5lq4zhjZaEJOq1PKtbPtWa1kKSjYZYqhV\n",
1131 1131 "+zb5cMVSVd1YKrVi7NRXRKVWOyzP1KL9MDGEWgD6klQL4mS+uFguYHlM0qciL2cMqNSKr49KraGG\n",
1132 1132 "Wo9KOi/pkj2rkoIQjiVZpVXQxnyppEItr61Qy2p12hBDrSZVTiflwuezRsLnfSq1Ugq1YgcJVGq1\n",
1133 1133 "w3LoRqVWYgi1APQltR0QH++Pd0Z6J3BsQqjVZyUflVqHUanVkK/OaXOuVtKthwVh/fvcJyHUshrw\n",
1134 1134 "bLLvzo+Wqn82CesaUqjVJKizdlv2qdRKpv1Q8VsmU1lvCFoshkbF72WxUotQKzGEWgD6ktoOiLQe\n",
1135 1135 "9otKrfh62f2wg+u2os0WxNSHxAdthFohZEixUqtphZq1sGQdlVqHL2vltqR6G1IJiQIqtdphuVIr\n",
1136 1136 "tB8SaiWCUAtAX5JqP5R0vT9+MuoqxuNuf2SmVjy0H+6nzVCLSq0DY2w/tF6pNcRQa6yVWrEDouL3\n",
1137 1137 "Hmr7ITO1NkuhUouZWokg1ALQlxBqPTXqKqoLodYnoq5iPKjUiq+P9sPUK4/KEGodRfthTX74uPUg\n",
1138 1138 "b4ihVpOWSms7c6Y6KD58b+shUZBapVaV0ChmpZblUItKrUQQagHoy0f9MbVQi0qtfrD7YXxUau0n\n",
1139 1139 "BDi0Hx6g/bC+i+Ven59dzqZnd104kiGGWuE2pda6V5T6oPiq644dJFCp1Y7VzC8f5peh/RClCLUA\n",
1140 1140 "9OUj/vi0qKuo7kn+SKjVDyq14mNQ/H6o1DqK9sP6Uri9Qw61xtZ+yKD4+lKr1KoTavV2n/odQ8/L\n",
1141 1141 "7SB6fMfFaT9EKUItAH1JLdSiUqtfoVrq9GS+6OtvE5VahzEofj+EWkeNNdTaZ/fDcHstP/ZNqpoC\n",
1142 1142 "a0FQkOqQ9aJUb8PQQ60UKrXCZfoOZ6ru0BjCJdoPsRGhFoC+3CX3B/b0ZL5o46Sva4RaPfJtNg/K\n",
1143 1143 "/V3qIlTZhEqtw6jU2g+7Hx7VZvuhlblFVezTfphCiEel1uHLWrktDIrvB5Va7ak6V4v2Q5Qi1ALQ\n",
1144 1144 "i+VsekFpzdUi1Opf3y2IVGodxkyt/VCpddRYK7X2CX3CfWX59p6V9JikE5P54kTNr7Uaau1T5WQl\n",
1145 1145 "cKVSqx+prHdIlVq0H6IUoRaAPqXUgsjuh/3rO9SiUuuwEMqc6qAFlN0P6wnXQaiVZqjVRvuh2dvr\n",
1146 1146 "36RqGtxZCFE2Gd1MLR9IXiTpseVseq6zVe2WSkgUUKnVHquVWrQfJoZQC0Cfkgi1JvPFFXIn4Y+K\n",
1147 1147 "wKNPIdS6tqfvR6VWgR/a2kYIscmYKrXauO/CdaQeArYR9NF+aNPQQq2wnpRDrbqVWlbWvwpfKuyC\n",
1148 1148 "J8UPEuquN1YIV7UKqngZKrUc2g8TQ6gFoE9JhFoqtB76d6TRj94qtSbzxXG5oOWChh201NXVXK0x\n",
1149 1149 "hVq0Hx4Ya6XW0Hc/lJqFQJKdIGVdk+H31m5LKhVEhyxn08ckhUqxXe1eUuRKrbVd+6q031KptZ3V\n",
1150 1150 "iijaDxNDqAWgT2GmVjKhVtRVjE+f7Yer1kP/ghpOV3O12P2wHtoPD6QS8hSFtVKpdZSJIGWDIQyK\n",
1151 1151 "r1upFbuNr6jJ/Cfzw+19JVfsSq0TFUYKxKrUqvq4036IUoRaAPoUKrWsD4on1Irjbn/sI9QKLY53\n",
1152 1152 "l15qfLoKtajUqmco7Ydj3/1wyJVaTW9jOHm1EgQFqQ5ZL0qyUstrUlUUM0iout4wt+x833PLfKeB\n",
1153 1153 "9XDG6vpoP0wMoRaAPiXXfhh1FePTZ6VW+B6EWoe13n44mS8ukSvhP7ucTS1UBHQlBDi0Hx4Ye6UW\n",
1154 1154 "odZRloKUon0GxVsJXKnU6k/V9cZeq/V1Wq/Uov0wEYRaAPqUWqjFzof96nNQfPge95Reany6qNQa\n",
1155 1155 "Q5WWRPvhJmMNtRgUv8FaK5a1k0AqteKqc/9bCBKq3tex72OroVFgtVLL6rqwBaEWgD7dI/dC+NRk\n",
1156 1156 "vrh614UjepI/UqnVr0/54+N6+F60H27WxaD4EGql3kq3C+2HR9F+WN9gQy0VWg8NbsKyT6WWhVBI\n",
1157 1157 "al6pZWH9VGp1w/o6rYZutB8mhlALQG/8i9gU5mrRfhhHn6FWaD+kUuswKrWaY/fDo8ZaqdVG+6H1\n",
1158 1158 "x34IuwUWNanUsjYovmmlFu2H9VGp1Q6rFVG0HyaGUAtA31JoQSTUioNKrfi6qNQaw86HEu2Hm4w1\n",
1159 1159 "1Nqn/TDcV9Zv7xAqm4qGcHvqBnOW1j/UQfGxAzjr67QaulkN27AFoRaAvhFqYZsYlVqEWoeF4KmL\n",
1160 1160 "9kNCrepoPzwQgiHaD21pchvDZS1UBq0LwU7Kg+LrVmrFDlyKqNTqRghbrIVGgdXwiPbDxBBqAejb\n",
1161 1161 "R/3RZKg1mS8ukvRE/8/bY65lhFahlh8o3CUGxW92nz8SatW3CnD875FGJvPFCbkTkAuyUUGxj1Xw\n",
1162 1162 "MZkvjtf9Yn8/Wpr7UxW7H25mubVyCO2UY6nUSinUir1W6+u0XqlF+2EiCLUA9M16pdbjJJ2QdM9y\n",
1163 1163 "NrXwQm9MHpZ7gXOJmrXt1EH74Wb3+uPpFq9zFIPil7PpebkT42NqFmYEq3laBodp17KcTR/TQTjT\n",
1164 1164 "5Gd6NbPIX1cq2P1wM8u3bQjth2Op1LIQJKRSqWU1NAqsVmpZXRe2INQC0LcP+6PVUIvWw0j8Cfxd\n",
1165 1165 "/p9dtyDSfrhZqNRqc3fScF33lV5qGNpoQRxK62GwTwtiqvfFGNoPm7TrWb5tQxgUv6ouqVgtGjtw\n",
1166 1166 "KaJSqxvh++4KZ6jUOuycP57Y0TlAqGUEoRaAvoVQ6xlRV7FdCLVoPYyjr7latB9u1kWlFqFWPUMZ\n",
1167 1167 "Eh/sE2qF+yK1UIv2w80s7+qZfKWWf2OoTjhkaf1NQi0qtXazGhoFOyuifOv6RZIu+IrozvmfpTBX\n",
1168 1168 "q6wFkVDLCEItAH37kD8+fZ+5Mx16ij9+LOoqxqvvUItKrcNC8ESo1Uwbg9Etn/g3McZQa9V+2GA+\n",
1169 1169 "4JBDLcu37YzcHLuTNea/WRsUL6VX8RQ0WXfMMC61Si2r66yyPrOBmwi1zLB4QglgwJaz6UNywcXF\n",
1170 1170 "OhjIbsmT/fHjUVcxXp2HWv4kk/bDzUKlVhfth/eWXmoYaD88anShlp//VXXXsXWWg5+iQYVavjIj\n",
1171 1171 "5UHrQZ3bYGn9Idyosu7wnIsZJlKp1Q7LwVGVHRAJtYwg1AIQw6paK+oqNqNSK64+KrUuk3uB9+hy\n",
1172 1172 "NrX0DrsFtB/uh/bDo8J9MppQy2vagmg2+FkzqFDLqzsnLHZgsckYKrVSCrVi38fW11ll5lfswI32\n",
1173 1173 "wwQQagGIwfJcLUKtuPoItWg93O5BuRacKyfzxYmWrjMEZIRa1dB+eCDlUKvpDojh8tYf/31malkN\n",
1174 1174 "tcJtqlqpZW1QvJR+pdbQQq3Y93EqlVq0H2IvhFoAYgiVWhZDLdoP4+oj1AqthwyJX+PbpkL4dFVL\n",
1175 1175 "V0ulVj0pBzmbjDXUalqpZT34CeoGQJL9wG6slVoW1h/WMLRQK5VKrRDOUKl1gPbDhBBqAYjBcqhF\n",
1176 1176 "pVZcVGrF1/aweEKteqjUOpByqFW7kmkyX5yUa3UpzuSyaojth3WDOouD4ptUatF+WF8qlVpVZ/vF\n",
1177 1177 "2lEyhUot2g8TQKgFIAaTM7V8u9X1/p+fiLmWESPUiq/tYfGEWvUwKP7AEEKtOu2H4WT9YT+43LIh\n",
1178 1178 "h1o7b5N/vXBc0vnlbHqu01XVUyccih24FNVZd3gepRBqUalVznKlluXADWsItQDEYLVS6zq534t3\n",
1179 1179 "LGdT/kDFQfthfF1VarH7YTVDGxQ/1lCrSfuh9dCnaIgztVKdR1VU5zbEDlyKqNTqxs51TuaL43IB\n",
1180 1180 "7QVJ5/tYVIHl4KjKY0yoZQShFoAYrA6KD62HzNOKh0qt+Fqr1JrMF5fKvSA8K3snf11oI9Q65Y/3\n",
1181 1181 "77kWK0Ko1eQ+STnUGmIlU1Hd+VOS/ZladR4zi0PipXFUaqUUasUODutUQj0aoULU8jD20oB4Ml8c\n",
1182 1182 "00Fr4tlNl0F/CLUAxHCX3IuRqyfzRVstTm1gnlZ8hFrxhVCrjUqtVethAu1UbWgj1AoD+ocWao21\n",
1183 1183 "UqvO7U4p1BpiaEelVjyVQiI/d+643Ny5mEHCYCq1FG+elmS7GmrXjL1VoDWS1zemEWoB6J3/5W+x\n",
1184 1184 "BTHsfEioFc+9ciXwp/3Mki7QflgutB+2ETiPaZ6WdBC+nCq9VDlCrQMph1phzYRaB6zfvjq3KXZY\n",
1185 1185 "sc3QK7VWVVqRg4TUKrUshkbF71lWqRXCo1iVWtt+H9B6aAihFoBYLA6Lp/0wsuVsel4HYdO1ZZfd\n",
1186 1186 "A5Va5Tqp1GrhulIQgqirSi9VjlDrwBBCrTpVe9ZDn6Ihz9SqE2pZ2vlQSrfarG6oFfs5NMRKrRjB\n",
1187 1187 "m+XQbdfPEqGWIYRaAGKxWKlF+6ENd/ljVy2IoVKLUGuzNgfFj2lIvNROlRuh1gFCLbtWoZafLVNF\n",
1188 1188 "KjO1UguEiuoEc7GriIrCGnbd9xbmaUlUarWlSqVWWHvf7aa7gntCLUMItQDEYnFYPO2HNnQ9VytU\n",
1189 1189 "atF+uFlrg+I1vkotQq2jCLWqsx76rCxn03OSzkk6pvIT0iLroV2dQMjqoPg6u25aCuZqtx92uJYq\n",
1190 1190 "qNRqR5X1xboPqdRKCKEWgFgsV2rRfhhXX6EWlVqbtVmpFa5jLKEW7YdHEWpVZ709b13dFkTrodYQ\n",
1191 1191 "KrXCfXt56aWc2FVEReF+HFqoFfs+HkKlVqzHnFArIYRaAGKxHGpRqRVX16EWg+LLUanVHJVaRxFq\n",
1192 1192 "VWc99FlXJwSS7Id2QxgUX+fnzdJtqHrfpxZqxb6PQ+CScqVWrMec9sOEEGoBiOWD/vjMqKvwJvPF\n",
1193 1193 "FXInomd0EKogjs5Crcl8cVwH1UNjmfNUF4Pim3vAH6+qMWdoxX9NCLUeKLtsQgi1qks11KpbqWW1\n",
1194 1194 "vbLJkPXY4cq6OpVasQOXoqrrTi3UolKrHJVaaAWhFoBYPi73h+A6HyjFFuZpfTzyNtHotlJrFWj5\n",
1195 1195 "nRZxVBeD4kcRai1n07NyJ2fHVC/MCK7wX/uwn1k0BCHcIdTabbChln9D4RJJF2Sj3W2TOiGd9Zla\n",
1196 1196 "qbUfDjXUih0cDmmmVqxKLUKtBBBqAYhiOZs+poMWRAvVWrQe2tFlqMWQ+N26aD8cU1XcPnO1htZ6\n",
1197 1197 "KDWs1JrMFxdLOik3jDzFkwZCrcPCZR42/MZRk0ota6FWpZ83XxUabgOhVn2pVWqVVUJRqbXZro0j\n",
1198 1198 "CLUMIdQCENOt/mgh1GLnQzu6DLWe4I93dnDdQ7Gq1GrSQrdmVJVa3j5ztYYYaq1OVifzRZ3Xnasq\n",
1199 1199 "LcMhSJkxhVpVqoKsz9OShjFTq2o4dNIfzxmpWh5qqBX7eTKESq3YoRaVWgkg1AIQk6W5Wk/zR0Kt\n",
1200 1200 "+O7wxyeUXqqZx/sjodYWy9n0jNyLx+OqdrJaZmy7H0oHt5VKLa2qcuuEH0HKrYfSOEKtOq2l1udp\n",
1201 1201 "SbsrM4pihxXbVA2HLFVpSYUAYUf4nVqoZaVSy+pMrbP+eKLkcY89KJ5QKwGEWgBiCqHWs6Kuwnm6\n",
1202 1202 "P36o9FLoQwi1ruvgukNQdlcH1z0kbc3VGmOlVgikqNQ60KQFkVDLvjq3MYXbVmc3x9QHxYefRRMh\n",
1203 1203 "41r4XRYqphZqxQ4/61Rq9R7O+CrcXS2IsSu1aD9MAKEWgJgstR+GUOvDUVcBqZ9Qi0qtcm3N1Rpj\n",
1204 1204 "qEWl1lGEWtWkEPwUDS3UqlOpFS5jpdIpqPqzZrFyrkogFz6XSqiVQqVW7IDWeqhFpVYCCLUAxGSp\n",
1205 1205 "/ZBQy4575YZDn/bDottEqFVNCLWo1KqPSq2jxhhqhdt8ZY3ZdCkEP0V1Qq2UZmpVqdSyGApJiVZq\n",
1206 1206 "eVXWbqVSKwQZJ7e1zU3mixNybfyPyb2miaFKqBX7986uNcbaaXTX74Mwl45QywBCLQAxrdoPWxhI\n",
1207 1207 "vS9CLSN8G0IIndqeq8VMrWr2bj/0P9NjDLUYFH/UA/54qsbXJB1q+dl0ZySdUPnOXkUWg4YyTSq1\n",
1208 1208 "LN+2OoPirT4/64ZalkLGZEKtim1zqyqtiJtdhDVaDrWsV2pt+30Q7tOzWz6PHhFqAYjpHrkTwCt0\n",
1209 1209 "EDb0bjJfXCV38v6ImLVkRVctiMzUqqaN9sPL5N7JfHQ5m1obptylEEjRfnigyX1iNTSoo24LYuyT\n",
1210 1210 "y7qG2n5YpVLLagAZ1jP0Si0Lz6NdIWjseVpShYoyxf/ZDJVaVkOtbb8PYrdtooBQC0A0/p0rC8Pi\n",
1211 1211 "w86HH0506/gh6jrUolKrXBuD4sdYpSVRqbVJkzljhFr2DS3UGlKl1q5WX4uhVpVAzkSllrcrhIs9\n",
1212 1212 "TytUvodKom2hUeyfzV3VZFZ3P4x9v6GAUAtAbBbmatF6aE9XoRbth9W0Uak11lCLSq2jmswZsxoa\n",
1213 1213 "1EGodcBiu9u6OoPiw222FApJLsA4L+nEZL44WXI5i6FWMu2H3q5ZgRYqtaTqlVBUah226/eBpefi\n",
1214 1214 "6BFqAYjNwg6IhFr20H4YF5VazVGpdRTth9UMOdRKYaZW1dY96SDIMPX89NXmdXYRtPR4pBZqma/U\n",
1215 1215 "Wvv+2yqhYu8oSaUW9kaoBSA2U+2HEdeAw1oPtSbzxWVyJyJnNbzQoG1UajXXpNUuGGqoRfthNamd\n",
1216 1216 "JA2t/XDVulcyfyiwWqklVdttlEqt/aVWqbUr1IrdfkilFhoj1AIQG+2H2KSLSq3VPC1mp+0UQq1r\n",
1217 1217 "9riOEGrdW3qp4WnSahcMNdSi/XAHH6KkdpI0qFBrOZueV/3dAy0+P6vcBkKt/Q2tUivWz+auWXax\n",
1218 1218 "Qy0qtRJAqAUgttB+GLNSi1DLni5CLeZpVfcpf3zcHtcRWhep1Kpu6KEWlVrbhRO3R/xw5xQMbaaW\n",
1219 1219 "VP02Wa7UqhNqWXo8Ug21qNTaz67HPdYug6tQazJfHNvw+dhtmygg1AIQ222SLkh6xmS+2FZ63DVC\n",
1220 1220 "LXu6rNRintZubYRaY20/pFLrKNoPdzvljyk99kObqSVJD/jjqdJL2a7UqjIbjEqt/e26n6nUqmbr\n",
1221 1221 "4z6ZL47LtSVeUM/3o6/cPCvpmDa3RsYesI8CQi0AUS1n00fkwqSLJN3Q9/f3fzCf6v/50b6/P7bq\n",
1222 1222 "tP2wxescqjYrtcbWfkil1lG0H+6W4mM/qPZDb+dt8m/AnZTbZfDMtstFtKuCqPg5Qq3mUqnUCvfV\n",
1223 1223 "tvs1djhTNptsdR9GGhtR1oKYyu+0USDUAmDB+/3x2RG+9xPlXpzesZxNLbxIghOCp+u2lH03Qfth\n",
1224 1224 "dSHUenzppcqFQOxTpZcanockPSbp8sl8cbLqF/nneYrBRhVUau2W4mM/ylBLhSoto/MZ2f2wH6lU\n",
1225 1225 "au0aaB+7ja7scY/9eJftgBh7bSgg1AJgwfv8MUaoReuhQcvZ9CG5F2KXqvrOYbtQqVXdA5LOyQUz\n",
1226 1226 "24ak7jLKUMuf5DaZIXWJXMB+Zjmbxj4JahuVWrulGGqFk+UrK7z5YHGG0yZVHjPrz00GxfcjlUqt\n",
1227 1227 "qqGWufZDFWYN9rSWdWU7IMa+31BAqAXAghBq3RThe4dQ6yMRvjfKtd2CyEytinwwE+6npi2Iowy1\n",
1228 1228 "vCahVoqhRlUMit8tucd/OZuekWu/O67t83oCi5VBm9Sp1LJ6W3aFGMXPWboNqYVaQ6vUsth+GPvx\n",
1229 1229 "Lms/jL02FBBqAbAgZvshlVp2dRVqUalVzb5ztcYcaoV2uzqVScmFGjXQfrhbqo9/1dsY+8S5qrFV\n",
1230 1230 "all6PErXHXNo+BZVd+2zUqm1bZ2xfzZTbT+Mfb+hgFALgAUx2w+f6Y+3RfjeKNd2qMVMrXoItZpr\n",
1231 1231 "EuKkGmpU8ZDciegVk/niRMWvsR4cVEGodSCVE8AhVGoNtf1wFXAYmWW2qwLKfKWW/318Um4OZKxN\n",
1232 1232 "DyyHWlXaD6nUMoBQC4AFt8r9QX2G31WoTzf64wd6/r7YjfbDuPYNtUKIOMZQq8kMqVRDjZ2Ws+lj\n",
1233 1233 "cnPaJOnUrsv7iozL5IIw6yFIGUKtAxYrgzYZQqXWrsocKfFQq4e1VJFapVZZe9/DEYNCy+2HVQbF\n",
1234 1234 "W/+dNgqEWgCi80ORPyz3O+mZOy7etmf54609f1/sRvthXI1Drcl8cbnci8AzsnXS1BcqtY6qc59Y\n",
1235 1235 "312uqiah1gOll7KnbqWW9d8HVcJXi4FQ0a4B5pLNxyO1UCv5Si3ZqDZKoVKrrP3QyvNx1Ai1AFjR\n",
1236 1236 "+1wtXw1wg//nB/v6vqistVDLl9hfI1f5McbKoSbC/fT40ktttmo9TDyUaIpKraPq3CfWK2GqolLr\n",
1237 1237 "wJDaD60/PwffftjDWqrYtV4roUdZyGnh5zKFUOtQ++FkvrhIB6Fl7Eo8iFALgB0x5mo9VW6WwCeW\n",
1238 1238 "s6n1F9pj1Gal1rWSjkm6ezmbnm/h+sZgn/bDMc/TkqjU2qTODoghNLB0wt1ECD12tlwq3cd/Zwjk\n",
1239 1239 "30C6RHYGfJepE2pZfX7uGrh+TIRabdhVqRWeJ7GrL6tUasV8DZxi+6GFtk0UEGoBsCKEWjf1+D1p\n",
1240 1240 "PbStzVCLeVr1hfuKUKs+KrWOqhP0nV77mlRRqeWsTpwTOAGsMyjeaqXWrplaF0s6LunccjY928+S\n",
1241 1241 "KtnVNhk74Fi3K4SzUtFnPdRKoVJrW6hl5bk4eoRaAKzovZU+YpcAACAASURBVP1QhFrW3e6PT2rh\n",
1242 1242 "ukIwxjyt6tqo1BpriEil1lF1gr4Qat3T0Vr6UifUCtVcqT3+dUItS1VB2wypUmtbOGSxSksabqUW\n",
1243 1243 "oVa5FEKt9d0PLdxvKCDUAmBFjPbDsPMhoZZNH/fHJ7dwXSEY+3jppVBE+2FzVGodVaf98Bp/vLej\n",
1244 1244 "tfTlEbmdfS+ZzBcnd1w21ce/VqVWx2tpwxAqtXaFQ+ZDLd8iuS52wLFuCJVaFnbwK1tfqJCy1n5o\n",
1245 1245 "ZV4aPEItAFbcKvfi/+mT+WLTLiNdCJVaH+jp+6Geu+Xmr1w9mS/KdnGqIoRan9jzesaEUKu5UKlV\n",
1246 1246 "J9QaSsvdNnWq10KolXSllm+1Cye0u36HEWrZMIRB8bvaD01WzvlWyHNyrZGbQmBrodauSq1QfclM\n",
1247 1247 "rXIpVmpZCANRQKgFwITlbHpGLti6SP1Va9F+aJg/IWyrWit8PZVa1bWy+2FLa0lNqDA6XXqpw4Z+\n",
1248 1248 "n9WpXhtEqOVVbUEk1LIhBBBlw/2tVjoFqbYfSrYDjnVDqNSyUHFk+THfNlPLwv2GAkItAJbc4o/P\n",
1249 1249 "7en70X5o38f88Sl7Xg+VWvWFQOG0372sjqEHNLs0qXIb+n1Wp/1wKDO1JEIt6SAgin1yX8UQKrVS\n",
1250 1250 "bT+UbAcc61aBx5a/kVaeJ2WVexYC51UIu6HtNDzmjyiOnbsf9rgWlCDUAmDJzf74V7r+RpP54rSk\n",
1251 1251 "a+X+YH2y6++HxkKoRaVWz5az6Tm5UOGYDipnqhp6QLNLGJBfp8pt6PdZk/bD1GdqSRVCksl8cbHc\n",
1252 1252 "SdN52Tlhr6pKCBRCyhQezzoztSyGQtLu9kPL608m1FrOpo/pYL3r7WmSvVDLZPuhf61xRu61xiVr\n",
1253 1253 "n479mDMoPhGEWgAs6bNS65n+eGsCW4yPWQihqNSKo+lcraEHNLvc7Y/XTuaLqq+1hn6f0X643Wrn\n",
1254 1254 "wwT/HlW5feExT2Fe3CoAKPnZtRJWbFO1UsviCXkyoZa3sdXTVxwxU6u6bUFs7Md8W/th7HVhDaEW\n",
1255 1255 "AEv6DLVoPUwDlVpxEWo14GcE3i838HhniON3xrtabrOMFKpZmqhTqTW29sNUWw+lgVVqLWfTUC13\n",
1256 1256 "TJurbyTblU5SeTuXZHv9qYVa28KYiyWdkHTW/z2IqWxXSSttdNvmwMV+zHftfhj7foNHqAXAkhBq\n",
1257 1257 "fUaDGT51sfNhGvau1JrMF6fkTrgeURqVApYQajVX57671h/v8S0tQ1RnptbYKrXCfRK7oqOJoVVq\n",
1258 1258 "Sbtvk+lKrQq7CJrc/dCrEmpZChK2rdfMc8QHtY9oc1BrJZzZdj/GDrV2tR9aClhHjVALgBnL2fQB\n",
1259 1259 "SR+V66l/5o6L74tKrTS0UakVWg8/nmBrT2y1Q63JfHFCLpS4oGGEEk3Vmas1hhCwSfuh+cqeCqjU\n",
1260 1260 "SqhSy9t1myxXOgVlc7Usr78s1LIYJGxr7TMTannb1mnlPrXafsig+EQQagGwpq8WxOf44190/H2w\n",
1261 1261 "nzZmatF62FwIWeoMPF8FEv4d4rEi1DqsyaD4IYSiofqq7HYTatmSdKWWt62dq/ix1EKt2AHHJtvW\n",
1262 1262 "a2WeVrDt+WCtUsta++G2mVpWwkB4hFoArAmhVtc7IIZQ670dfx/sJwRRT94yG6QKhsQ316T9cAwB\n",
1263 1263 "TRV17rsx3GeV2g/9cO5QzZVKCFImbBpQtoPoalB8x2vpwhDbD0MQcWr9E74S9RK5StRH1j9vSFk4\n",
1264 1264 "RKjVnqFUalkJtaxVam1rP6RSyxhCLQDW3OyPnVVqTeaLayVdJ/fH6KNdfR/sbzmbPix3Ynux6s91\n",
1265 1265 "CqjUai5UGxFq1Uel1mEPSzov6TI/GH+bU3KvTx/0W72nLoRaZT9DVGrZUnabQijwoPF29irthxZP\n",
1266 1266 "yMvWHTvg2MT8TC3PeqiVWvshlVrGEGoBsKaP9sNVldaAhzIPyb5ztcLXUalV3z6VWneVXmr4qNQq\n",
1267 1267 "8AFAlWqtIbUeSgeh1rUll0k51HpEbtfOS0rCyhBqpVKpVRZqhY9ZrHIqolKrH6lXalmpOEqt/dDK\n",
1268 1268 "/QaPUAuANatQa492s11oPUzLvnO1VoPiW1jL2NSpNgoGH9BURKXWUYRamyUbavmwMpy4b5rfJKXX\n",
1269 1269 "TlqpUquntTRVNlMr9d0PLYVauyq1rMzUsl6plVr7oZX7DR6hFgBTlrPpnXIng6ckPbWjbxOqwG4p\n",
1270 1270 "vRSsoFIrnk/645NKL3XYWAKaXeoM2R/LfVZlB8RQ1TOUUCs8poMMtbxdLYhDaj+0VoGzDZVa/dgW\n",
1271 1271 "FoV5bFaeJ6nufhgqpGg/RClCLQAW/Zk/Pr+j66dSKy1UasWzGtRf42vGEtDsUmce2Vjusyo7IK52\n",
1272 1272 "z+x4LX0ZdKWWtzUE8hXXIcRM5fZVqdSyGAgVVZmpZfE2lIVaFjccSG2m1vo6rVQc7Wo/jLUpA+2H\n",
1273 1273 "iSDUAmDRu/zxczu6/hBqUamVhlCp1TTUolKrufvlXrRdMZkvjuwEtkWoTBp6QLML7YdHhZPR0yWX\n",
1274 1274 "of0wPbsqmy6S9NByNj3b35L2QqVWPGXrtvi7IfWZWtZCrdXj7mf0HZeb2Rfrd8eu9kMqtYwg1AJg\n",
1275 1275 "UQi1PqftK57MF5dKepbcH8n3t3396ESTaiFJkg9irpR7YTKUyo/e+Hk5IQysev+Hyrixh4gMij8q\n",
1276 1276 "BH1PKLmMxRPXfdwn6YKkqyfzxYktlxlyqJXakHjpYA5SypVaZTO1LN+GjaGWr/izWMXJTK12bKok\n",
1277 1277 "W7WbRtxp9FF/vHgyXxRzEyq1jCHUAmDRn/pjF5VaN8n97rt1OZs+uuvCMGGfSq1V66Hx7dctqxsq\n",
1278 1278 "hsfpY6WXGr5VqFVh04uxhFp3+GNZqDWomVp+h91wW7ZVqA051EptSLx0cHs2Vadaq8DZpkr7ocUT\n",
1279 1279 "8m0h0eWSTsgFHJZeu6U+U8tKOLMphI0+Q82/btzUgkilljGEWgAsukWu1PimyXyxbfBsU7QepieE\n",
1280 1280 "I002DqD1cH91Q61wuVHPMPMnXg/KnYhtnSHlA6+xhVrXlVzGYjXGvna1IIbnh5WqjrrCujc9z1Mb\n",
1281 1281 "Ei8NY6ZWCAk23YYUdz+0WsGZ2kytVWjkK0cvlutcOBNjUQWb7sfoodba9y+GWlbCQHiEWgDMWc6m\n",
1282 1282 "ZyTdLOmYpOe1fPVh50OGxKfjk3Il4E+oMdcpINTaX+VQazJfXCwXWDwm6fYuF5WIKnO1TskFXw8v\n",
1283 1283 "Z9NYw3D7UifUsnbyuo+qoVaqlVplmyKk2H44hJlaIUS8ZsPnLAdz20Iiq+FoyjO1LLT3BaXthz2v\n",
1284 1284 "ZV1ZpRahlhGEWgCs6mpYPJVaifHtOx/0/3xmzS8Pl/9g6aVQJgSCTyq9lHO9P35yOZue72g9KQmV\n",
1285 1285 "V2WhVggC7iq5zFDc6Y+EWoeFsD71UGtTW2nK7YcpV2qF3z2HnnN+LpDlE/KhVWpZqb7c1N5n6Xlg\n",
1286 1286 "sv3Q2zQsnvZDYwi1AFgV5mq1PSw+XN97Wr5edOsD/visml8XLn9ri2sZmzrth8zTOqysgkVrnxt6\n",
1287 1287 "66E0wpla3tZQy4cMIdSycgJcV1lFIpVacWzbqKJYnfNYj+upaleoZS0cTbb9UDZDLYuVWrQfJoBQ\n",
1288 1288 "C4BVrVdqTeaLy+Qqtc5L+rO2rhe9CKHUjTW/jlBrf3VCLeZpHVal/XCModZYZ2ptCjevkGu1fyjh\n",
1289 1289 "6sZQgUellh3bQi3r6w/rWr/vrYbdKQ+KtxRqJdN+6GeRnZQbs3A21qJwGKEWAKtCpdbzJ/PF8Zau\n",
1290 1290 "83mSjkt673I2jf1HEvWEUIpKrf5RqdXcthPLojGFWqv2w5IdIa22Ge2jrP0w9XlaUrVKrZRCrVAx\n",
1291 1291 "tynUshZWbLMr1LIQZGyyCoDXfkdYDbtTrtSyVG2UUvvh6n4zMIsMHqEWAJOWs+ndkj4i98fj2S1d\n",
1292 1292 "7ef745+0dH3oT+1Qyw8tf5rcu2kf7mJRI7GaqVUSRARUah1GpVaBH4T/gNxg/NPrn/fPL6sVGfso\n",
1293 1293 "C7XCx6ydrNcxpvbDUI1254bPWbIt1LIWthyynE0fkgsxLtXhoMjq74Vdg+KttBRbr9RKqf2QeVoG\n",
1294 1294 "EWoBsOyP/fGFLV3f5/njO1u6PvSnyUytZ8i19XzE76iJZh6Qe0F8uQ6qSrahUuuwOoPiBx9qeWVz\n",
1295 1295 "tS6T22L+0YHtBFkWaq02V+hpLV0YWvvhqgVuQ5AfWmfvkG33yY1aOOXf4AnCY2R5/Zs2HrBawXkk\n",
1296 1296 "jPHPmRBqWWnzLAu1LIQzltsPw2McHlNLFW7wCLUAWPb/+eOLW7o+Qq10rXY/rNGOSuthC3x5fdUW\n",
1297 1297 "RCq1DmNQ/FFlc7Wsnrjua+NOdN4QQq1VeLshBEquUms5m56TO5G+SEertZIItfzv7U1hali/5Uqz\n",
1298 1298 "TZV/1tsPryg89y+Rq0Y9Y+gNtU2hkcVKLYvth+vPR0thIDxCLQCW/Xd/3DvUmswXJyU93//zXWWX\n",
1299 1299 "hT3L2fRhuZO+kzqoBtqFUKs9VUMtKrUOo1LrqDGGWmWVWk/yx09s+FwSlrPpo3IVncd1UJkVpFip\n",
1300 1300 "JUm3++MTwwf8TpWptB9Km1sQUwjlNoVaJtsPl7PpWblh4RfJVZlKNls8rbcfhoDoMv9zJtmZ/7Ze\n",
1301 1301 "iWrpfoNHqAXAsndIOifpeZP54tSuC+/wHLl3z25dzqapvbiGU3euFqFWe1ZztXZcjkqtw6rM1Aov\n",
1302 1302 "lMcSapW1qpk8cW3B0NsPpe2Pa4qD4qWDx+OJhY9dIxfc3WuoAqdMqqFWeC6lUKklHQ2MrM3TkoyH\n",
1303 1303 "WsvZ9DEdnV1l5bm63g5L+6FBhFoAzPLVOX8q97tqsufV0XqYvjBX68aKlyfUas/OSi0fPJ+Se2Fq\n",
1304 1304 "8cQjhlCx9tSSyzzDH8eymUFZpVYIEO7a8LmUjSHU2hbgJtd+6IXH4/rCx6ycZFeVaqi1aaaW5cB7\n",
1305 1305 "fa6WxUqtM3Iz1k76zgXJXjiz3oJo5bm6HrLSfmgQoRYA69qaqxVCLXY+TBeVWvFUaT9cVWmxzfXK\n",
1306 1306 "p+TeIb96Ml9s2u3vIklP9//8UJ8Li6gs1Ar3xdACvhDyXlNorQmGHmql2n5IqBVP2Uwti6FWCK/C\n",
1307 1307 "Riqn1j4enf+bvF6tFY5Wwpn1cDC8yXH7hsv2ab0K1VoYCBFqAbAvhFov2vN6Pt8fqdRKV+VQyw9s\n",
1308 1308 "JdRqT51Qi3lanj+RCGHVDRsucp1cW/Tdy9nUzAlQx8pCraf540d6Wksv/ODx++R2Y12fOZX8TC3v\n",
1309 1309 "SPvhZL64VK6VKAxeT0k4kR5aqJXCTLCymVoWw9H1ANRipZZ0NNQKoZGV5/P6MHsrP2/bZmql9jtt\n",
1310 1310 "0Ai1AFi3CrU27KpUyWS+uETSC/0/39HKqhBDCKeqtB9eI/eu6QMaz6yiLlWZqRWGxDNP67Db/PEZ\n",
1311 1311 "Gz4XPjaWKi2pfKbWUCu1pO0tiEOu1FpVaSVYvbmpUis8Z2OfZFeVaqXWoXYv3y53paTHZGtOVbD+\n",
1312 1312 "po/FmVrS0VDL2gzM9fZDKrVQGaEWAOtuk/uD9nhJNzW8joncu8XvWc6mlt+dRLkwU6tK++GqSivB\n",
1313 1313 "kymLQvXV00suQ6XWZrf54w0bPveMtcuMwegqtbwjoZavZDotV8l096YvSsimsDLV1kNp86D48JxN\n",
1314 1314 "5XVEqqHWekC6qtIy+vd8W6hlrVJrPTSyGmpd7t/EtvJcXZ/xRqWWQYRaAEzzL2D+yP/zbza8mvB1\n",
1315 1315 "b9t/RYjok3IvEh83mS82nRAX0XrYrtvkTryfNpkvLt9yGSq1NrvNH2/Y8LkxVmqNcaaWdBBaFQOG\n",
1316 1316 "VZWW3/0rZWUtY6kNiZcGOFPLh6hXyf0utxw0rocIlofESwd/80Ils9VQy3qlVnF9V0u6WNKDftOo\n",
1317 1317 "mB6U9Kiky/zrHzO7RuIAoRaAFLzJH1/a8OtDqPXW/ZeCWHzA+S7/z88ru6ykz/RHQq0WLGfTs5Le\n",
1318 1318 "JzcT6DO3XCyEWlRqHVY2U+uGtcuMwSr8mMwXx8MHfZv49XItRqnPl9pkU/vhUFoPpR3thz2vpQ2D\n",
1319 1319 "C7VUaJ80WvEUrD+XwpB4q8+j9Uotc4PivVVo5Cuhwnqt/L4tDooPP2uxWw/Da89iJWr4HZ5iWD9Y\n",
1320 1320 "hFoAUvBf/PGLJ/PFiTpf6GcxfKH/5x+0uirEEAb9f37ppdgYoAu3+ONzt3z+M/zxgz2sJSW3+SMz\n",
1321 1321 "tbQamn63XEBaDHhWoai/zNAMPdTa1H6Y8snfalB8YZ5n6qFWKu2Tq3X73UKtV2qFUMj6TK1w/z1O\n",
1322 1322 "7mfzYkn3LWfTh7Z/Sa9CaPl42RtiX/z99kz//7zWMYRQC4B5y9n0Vkl/KffC5oU7Lr7uC+Te9Xnv\n",
1323 1323 "cjaN/o4P9vYn/rgr1PoCf/zjDtcyNltDLR8eP0fSBUnv6XNRCbjNH2/Y8LkxztSSNrcgDnmellTe\n",
1324 1324 "fmilUmIfmyq1wslfcqHtcjb9tKT7JZ3UQaVQ6qFWEoPufWXwvXLnqad1cP9bDbVSmakVQpgbddAq\n",
1325 1325 "aaX1UDq8GZCZSi2vGGqF8RaEWoYQagFIxe/645fV/DrmaQ1LCLW2th/6eVtPlXtB+Zd9LGokyiq1\n",
1326 1326 "PlPu5O9WQ+/6WnGn3EDZaybzxVXhg776Y3SVWt4YQ61w8vi0wsfCieUQKrU2hVrP9sf39byWtqwP\n",
1327 1327 "i0811LrW2ODtKopztay3H64qtfz9bDXUer8/3ih787Skw+uzVqlVfD4ys9UgQi0AqQgtiE1Drbe2\n",
1328 1328 "txREdIvcwM4bJ/PF6S2XeYE/vnMAw5ctKQu1nuePf9bTWpLh53GE0KrYgnhabvbKg7JbgdCVTaHW\n",
1329 1329 "kIfESwc/P3+l8LEhtR/eK+m8pKsn88XF/mOhJTn1UOt6f5uukZv5lsROlcvZ9Izc75cTcgPiUwy1\n",
1330 1330 "Hi/j7YfL2fQBuVbDsJtpCIw+tfWL4gg7SN8k26HWTbJbqXWT3O+Bh5XGz9FoEGoBiCrLsldVvOjb\n",
1331 1331 "5MKML5jMF0/YdWFJmswXV0j6G/6fzNMaAN+WEIKTz91ysRBq0XpYosbPXvAX/vjsDbPtPtsf/3yv\n",
1332 1332 "RQ3Xbf54Q+Fj4f8/ZHxocxfCiVQx5Bt6pdYqFP6HBz97gwm1/BsI6+1uQ6nUul4HFWh3JvZmSfEx\n",
1333 1333 "STXUaq1Sq8HfvaqKLYjhTR5rrfgh1LJaqVUM3cLvRmuhVhiB8sER/t02jVALQGw/UOVCvqXpD+SG\n",
1334 1334 "C1et1vo7cvO0/sdyNrX0hxv72dWCGEKtd/SwlpRV+tkL/M/gh+TaDG9c+zSVWuVu88cbCh8b6zwt\n",
1335 1335 "SXq3PxZ/hodeqXW7XKXJ6fMnLw8/e6H9cAgztaTDO1teJddC9KjSDSqLoVZKgVDRplDL+qB46WCN\n",
1336 1336 "bVdq1fq7V0N4jflcud9lj+qg8siKj0o6I/d8DlWUZl4bL2fTe+SqIC+X9Hz/YSs/b+uhFq2HxtTa\n",
1337 1337 "RawtWZYdk/RqSTNJX5nn+W/V/PpXSPo2uQGUd0t6o6Tvy/PcyhMfQDd+S9KXSPpaSb9Y4fL/qz/+\n",
1338 1338 "x85WhBh2DYtnSHx3bpELY56rg8otiVBrl9v88YbCx8Y6T0va/DM86Eqt5Wx6YTJf3CzpC89euuqc\n",
1339 1339 "HkylllccpnzS///7E6tsKlrtgKhhhVop3IZNM7VMth96IRz6En+82doursvZ9Pxkvvig3AzM/8l/\n",
1340 1340 "2Eyo5b1fLjgKb05aq9QKz0WGxBvTe6VWlmWXSPplSa+U2yWpVulelmU/KumnJL1B0ldLepWkqaS3\n",
1341 1341 "ZVl2VcmXAkjfL8u9+/XFk/nihrIL+nlLXyH3O+bXul8aerQ11GJIfOeOzNWazBen5MKaM0q3zahr\n",
1342 1342 "m2ZqjTnUeo+ks5I+wz9/pOFXakn+5+fsZdeEjQKGFmoVW8ZSbz2UDg+KTykQKiqGWknsfuh10n7Y\n",
1343 1343 "oRAOvdQfrbbiF4exS/aqRMP6wlw+K8/Vu9b+TaWWMb2GWlmWXSPpTXItQd8s10ZU5+tfIBeGfUue\n",
1344 1344 "59+b5/nv5Hn+s3Jp87XqrqQUgAG+NPn1/p8v23Hxvy/3R/GttB4Ozp/JDSR+zmS+uHLtcwyJ79am\n",
1345 1345 "YfGfFT5n7Z1pQ27zxxsKHxttqOUHWIeqvs/xrWpXS3pE9oYrt+lmSTpz6TWSe916UtJ9y9n00zEX\n",
1346 1346 "1aJw4ldsbxpCqEWlVv+SGRTvrc8JtFq1/IG1f1t7fbzesmmtUisg1DKm70qtF8jt+vJSSb/X4Ou/\n",
1347 1347 "UdKtPshayfP8dkk/LellWZZFaakE0JvX+ePLJ/PF8ZLLhdbDX+l4PejZcjZ9RNJS7m/Y31379MQf\n",
1348 1348 "aT3sxqZQi9bD3W7zxxsLv7dCJcvoQi2vWHEZWg8/PPDhu6tKLQ2vSkuS/tQfv0QHz++UK2YJteIp\n",
1349 1349 "ztS61v9/CpVagdW/h+uhlrVKreL6zsrOY74eatF+aEyvoVae52+WdFOe53/U8Cq+SNLvbPncG+WS\n",
1350 1350 "/G27YQEYhrfJ/dF7qqQv3XSByXzxXElfLOmcDiq7MCy/5I9fFz4wmS8ukvSP/T9/v/cVjUMItT6r\n",
1351 1351 "UCVHqLXb7XLv7J6W9Lcm88VnyN1vD+pgaPrYbAq1BjlPq+BmaRVq/VX/sSHd5t+Q9Jjcm9dhtiGV\n",
1352 1352 "WnGFUOuzJV0q6dN+0w/rQqXWF0l6lqSHJX0s2mp2Ww+1rLcfStLd/k1CS4rru8PQmxz3yHUIBIRa\n",
1353 1353 "xvQ+UyvP80aJqx8u/yxJ791ykTCwdn1HJgAD4lvKQrXWj0zmi5MbLvZjko5L+tnlbDrkVpYx+xW5\n",
1354 1354 "d/G+ZDJfhK2pXyJXHfBRuTc60DL/8/SHki6T27BBOmj5JNTawr8wD5tb/BP/nyT9p+Vs+nCcVUX3\n",
1355 1355 "Tn/8fB1UXK5XEQzNRyQ9dP7k5ZL0L/zHfmn7xdOynE0/KffG00kdVHOmHGqF6ozrJL3I/39qoVao\n",
1356 1356 "Wv4qf0xl/SHUusIfX2k8jCtWPN0ruwFc8XestdZDaS3UiraKNf7cI5xP3GH8uThKvYdae7hK7iR1\n",
1357 1357 "YyiW5/kDcgnq4/pcFIAo/o3cuySfI+m7ip+YzBdfLunLJd0v6fv6Xxr64MOVN8j9HftH/sPf7I//\n",
1358 1358 "jtlOnfrX/vjtk/nipZL+mqSHJL093pKSEMKLf6CDCsMqu7gO1bvlqno+S9I3+f9/TdQVdcyHm6Ha\n",
1359 1359 "8ZlyJ5VD2503L/z/Q7LX3lTZcjY9KxeuHJML6R6V2+QgGcvZ9L9J+tbCh8wEBTsUB3O/QdK/jbWQ\n",
1360 1360 "iorP8z83VGG07jYdbNJmMdS6U9ID/v+tzNMKwnOSeVoGpRRqhd1xyoZpflpu0CiAAfPvkPxT/8/v\n",
1361 1361 "n8wXnytJk/niqZJ+wn/8h5az6XoPPIblF/zx6yfzxWdL+p/lqrdet/1L0ILflKuGe44OZtb9MFWR\n",
1362 1362 "5Zaz6fsl/ZFc5cHT5O7Dt8ZcU0y+Qu0WudeixyW9bjmbjqHa75bC//+UH5o/JL8uF1BK0vsMn9xX\n",
1363 1363 "9etyQdCPSXrucjZNrppwOZu+VtLL5UYyLCMvp6r75Kr8PiTpG6w/j/zvs1B4Yfb32HI2fVQHO8ya\n",
1364 1364 "C7X84xx+xqyFWuGcglDLoMZD1bMse6Wk/7PCRd+a5/m06fcpCKntZSWXuUzulyCAgVvOpm+ZzBc/\n",
1365 1365 "J/dC7R2T+eI/y7WfXSk3mHbQ7/hDkpuxeJfcBiThRWTuW2DQkeVsenYyX7xW0r+SmxH1l5J+Mu6q\n",
1366 1366 "kvGLcpVtkvRL7NCpP5Gr1HpA0vdHXktfbvbHByX9PzEX0oXlbHrHZL74fbm/xym3HkqSlrPpN8lV\n",
1367 1367 "EiZtOZv++8l88ZtK5DxpOZs+Npkvni/peEKtXh+X+5toNtTyPiC3S6O5UMt7v9yMbGtVhSHUYp6W\n",
1368 1368 "QccuXGgWfGdZdo2kJ1S46MN5nn90w9ffIJd0/v08z//fCt/vmKQzkv5Znuev3fD5K+Xajb4mz/Nf\n",
1369 1369 "rbAuSdJb3vIW08k/AAAAAABAql7ykpcc6+q6G1dq5Xl+j9xOAL3I8/xClmW3yrU7bBI+TkkgAAAA\n",
1370 1370 "AADAwDUOtSJ5q9wA6E2+Qq6X+V11rrDLxBAAAAAAAADdMDsoPsuyi7Ise+Lah39G0rOyLHv52mWf\n",
1371 1371 "KLezx8/neX62rzUCAAAAAAAgDrOhlqT/W9LHsix7cfhAnufvkNvZ7LVZlv2rLMv+dpZl3yDpv8pV\n",
1372 1372 "ab0qykoBAAAAAADQq9ihVtmQ9o/Kzew6tEtHnuevlPSdkv6epFzSD0l6m6S/nuf5/R2tEwAAAAAA\n",
1373 1373 "AIY03v0QAAAAAAAAiCV2pRYAAAAAAABQG6EWAAAAAAAAkkOoBQAAAAAAgOQQagEAAAAAACA5hFoA\n",
1374 1374 "AAAAAABIDqEWAAAAAAAAkkOoBQAAAAAAgOSciL2AmLIsOyHpuyS9TNJTJN0u6dck/WCe5w/FXBsw\n",
1375 1375 "VFmWXSLpOyR9naRnSbpX0u9JelWe57dFXBowKlmWHZf0x5KeL+kr8zz/rchLAgYvy7KXSHqTpO/I\n",
1376 1376 "8/w1sdcDDF2WZSclfYukb5P0dEl3SPpFST+S5/kDMdcGDEmWZU+W9NuSbsjz/Jotl3mF3M/iMyXd\n",
1377 1377 "LemNkr4vz/M79vneY6/U+g+SvkfSz0n6Kkk/LumfSPod/2IfQIuyLLtIUi7ph+V+6X21pB+U9GJJ\n",
1378 1378 "b8+y7IZ4qwNG51skXS/pgv8PQIf8m6n/WtI7Jf105OUAY/Ezkl4t6VclfaWkn5T0TyX9rv+ZBLCn\n",
1379 1379 "LMs+W9J/l3ujdONryizLflTST0l6g9w54KskTSW9Lcuyq/b5/qP9Qc6y7Ksk/UNJX5rn+Zv9h383\n",
1380 1380 "y7I3S/oTuRf7/ybW+oCB+rv+v6/L8/wXwwezLHu9pPdI+n5JL4+0NmA0siy7Ti5Q/k5JPxt5OcBY\n",
1381 1381 "fLuk50h6cZ7nBMlAx7Ise4Gkr5X0jXmev85/+I1Zlv1XuRPwfyzp5yMtDxgEX4H8eknvlfSbckVC\n",
1382 1382 "65d5gaRXyv0s/mzh4/9Z0rsl/YDca9JGxlyp9U2Sfr8QaEmS8jy/RdJ/lPSKKKsChu0hSXNJv1T8\n",
1383 1383 "YJ7nd8m1IP7VGIsCRuhHJb1F0iL2QoAx8EHyD0h6XZ7nb4+9HmAknu2Pv1P8oP8ZvLvweQDNfa3c\n",
1384 1384 "OIuXyP1cbfKNkm4tBlqSlOf57XKVyy/bp3JylKGWv8O+UK79aZM3SnpulmWP729VwPDlef7mPM+/\n",
1385 1385 "e8s71JdKOtP3moCxybLsxZIyuXfMjkVeDjAWr5b7e/eJCwAABZtJREFUG/c9sRcCjMjN/vi84gez\n",
1386 1386 "LHuKpGsk3dL7ioDheYWkL98xk/yLtBYuF7xR0mlJn9t0AaMMtSQ9SdLlciVym/yFP97Yz3KAccuy\n",
1387 1387 "7AmSvlzSH8ReCzBkfq7dT0v6v/I8/1Ds9QBjkGXZC+U2R/leSWezLLs08pKAUcjz/N1yM5T/bZZl\n",
1388 1388 "X5Zl2bVZlr1I0m/IjZv5lagLBAYgz/NP53m+tTAhy7JjcpuDdZa9jDXUutYf793y+fDxx/WwFmDU\n",
1389 1389 "/C+6n5Gb8ffjkZcDDN0r5P62/UjshQAj8pOSzkv655Lul/RQlmW/72eMAOjWy+QCrDdKukvSH0k6\n",
1390 1390 "KemleZ6fi7kwYCSuknRcW7IXvwvpee2RvYw11Drlj5/e8vmH/fHqHtYCjN2PS/p7kl5J5QjQHd9S\n",
1391 1391 "/8OSvivP80dirwcYgyzLvlTSi+RmSv6a3I5PM7ntzP8gy7JJxOUBg+ark/+DpL8l6X+X9Dckfb1c\n",
1392 1392 "q9Ob9t1xDUAlu7KX8LnG2ctYdz98wB8v2/L5y/3xvh7WAoxWlmX/QtI/k/SaPM9fE3s9wMD9iKQ/\n",
1393 1393 "z/P8V2MvBBiRb5d7sf6iPM9Di4WyLHud3I5PPyXpr0VaGzB0XyvpH0j6gjzP3+U/9odZlv22XCvU\n",
1394 1394 "D8pVUALozq7sJXyucfYy1kqtMJX/9JbPh5TwUz2sBRilLMteIemHJP1CnuffEXs9wJBlWfYcuRaM\n",
1395 1395 "V2dZdn34T9IT/EWu8R9j1g/QrhdL+tVioCVJeZ7fL9eW+KIsyxh3AXTjayS9pRBoSZLyPP+UpJ/3\n",
1396 1396 "nwfQrfvl2gs3Zi9Zll0p157YOHsZa6j1Cbl3zZ6z5fPh47f2sxxgXLIs+18kvUZSLneiDaBb18v9\n",
1397 1397 "zf9tSR8v/Pc//Of/vf93FmV1wHCdkvS+LZ8LH3/Cls8D2M/TJX1wy+duk3RdlmUn+1sOMD5+1/tb\n",
1398 1398 "1WH2MspQyw8F/ENJf3vLRb5C0i15nt/Z36qAcciy7KWSfkHu5Pof+V90ALr1p3I7jH7Z2n9f7z//\n",
1399 1399 "g/7fb46xOGDAPibppi2fu0nSY3JvtgJo393a/vN3o6QH8jw/2+N6gLF6q9zr0E2+Qm6I/Lu2fH6n\n",
1400 1400 "sc7UkqR/J+k/ZVn2kjzP3xI+mGXZc+VKUb872sqAgfLbKL9e7hfbV+d5fj7uioBxyPP8Hkn/Zf3j\n",
1401 1401 "WZbd4P/3nXme/16viwLG4dckfWuWZf8yz/NVxUiWZVdI+g5Jb87znBmuQDd+RdJPZFn2wjzP3x4+\n",
1402 1402 "mGXZE+Xe1Hl9rIUBI/Mzkv63LMtenuf5z4UP+p/Fb5X08/sEzKMNtfI8//Usy14v6fVZlr1a7l3s\n",
1403 1403 "myR9r6Q/lvTTMdcHDNQb5YYA/qSkL8yyo51OeZ6/tec1AQDQlX8pVwX59izLflTSzXItUf9c0pWS\n",
1404 1404 "vi3i2oChe43cDttv8j9/75Z0g6Tvkns9+r3xlgaMR57n78iy7CckvTbLspsk/Te50RjfLVel9ap9\n",
1405 1405 "rn+U7YcFXyPpxyR9g1xS/39I+mVJL6WCBOjEablfYL8tabHhv7ds/1IAHaEFGOhInucPSPpCSa+T\n",
1406 1406 "9M2SfkPS90t6m6TPy/P8/RGXBwyaH3HxdyT9hNwM19dL+h5Jb5A0yfP89ojLA4bogra8rszz/JWS\n",
1407 1407 "vlMuaM7lNgx7m6S/7jdPaezYhQu8lgUAAAAAAEBaxl6pBQAAAAAAgAQRagEAAAAAACA5hFoAAAAA\n",
1408 1408 "AABIDqEWAAAAAAAAkkOoBQAAAAAAgOQQagEAAAAAACA5hFoAAAAAAABIDqEWAAAAAAAAkkOoBQAA\n",
1409 1409 "AAAAgOQQagEAAAAAACA5hFoAAAAAAABIDqEWAAAAAAAAkkOoBQAAAAAAgOQQagEAAAAAACA5hFoA\n",
1410 1410 "AAAAAABIDqEWAAAAAAAAkkOoBQAAAAAAgOQQagEAAAAAACA5hFoAAAAAAABIzv8PtKN7Annmb8kA\n",
1411 1411 "AAAASUVORK5CYII=\n"
1412 1412 ],
1413 1413 "text/plain": [
1414 1414 "<matplotlib.figure.Figure at 0x106622080>"
1415 1415 ]
1416 1416 },
1417 1417 "metadata": {
1418 1418 "image/png": {
1419 1419 "height": 392,
1420 1420 "width": 602
1421 1421 }
1422 1422 },
1423 1423 "output_type": "display_data"
1424 1424 }
1425 1425 ],
1426 1426 "source": [
1427 1427 "x = np.linspace(0, 3*np.pi, 500)\n",
1428 1428 "plt.plot(x, np.sin(x**2))\n",
1429 1429 "plt.title('A simple chirp');"
1430 1430 ]
1431 1431 },
1432 1432 {
1433 1433 "cell_type": "markdown",
1434 1434 "metadata": {},
1435 1435 "source": [
1436 1436 "These images can be resized by dragging the handle in the lower right corner. Double clicking will return them to their original size."
1437 1437 ]
1438 1438 },
1439 1439 {
1440 1440 "cell_type": "markdown",
1441 1441 "metadata": {},
1442 1442 "source": [
1443 1443 "One thing to be aware of is that by default, the `Figure` object is cleared at the end of each cell, so you will need to issue all plotting commands for a single figure in a single cell."
1444 1444 ]
1445 1445 },
1446 1446 {
1447 1447 "cell_type": "markdown",
1448 1448 "metadata": {},
1449 1449 "source": [
1450 1450 "## Loading Matplotlib demos with %load"
1451 1451 ]
1452 1452 },
1453 1453 {
1454 1454 "cell_type": "markdown",
1455 1455 "metadata": {},
1456 1456 "source": [
1457 1457 "IPython's `%load` magic can be used to load any Matplotlib demo by its URL:"
1458 1458 ]
1459 1459 },
1460 1460 {
1461 1461 "cell_type": "code",
1462 1462 "execution_count": 4,
1463 1463 "metadata": {
1464 1464 "collapsed": false
1465 1465 },
1466 1466 "outputs": [
1467 1467 {
1468 1468 "data": {
1469 1469 "image/png": [
1470 1470 "iVBORw0KGgoAAAANSUhEUgAABKkAAAMnCAYAAAD1XgGYAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\n",
1471 1471 "AAAWJQAAFiUBSVIk8AAAIABJREFUeJzs3Xm0pWV9J/rvc05VUQU1MhdTMY8lgwioQMRGcUIhRBHF\n",
1472 1472 "GTCKUcAERVTiCChEMQYHxClIHGNak2jS3VlJJ52k+2a+t3t1eqVv3xhAQKAKqqj5nPPeP3aVtWtz\n",
1473 1473 "ihrOOfvZw+ez1rv2fn/vPmd/F4tVp863nvfZpWmaAAAAAEBNI7UDAAAAAICSCgAAAIDqlFQAAAAA\n",
1474 1474 "VKekAgAAAKA6JRUAAAAA1SmpAAAAAKhOSQUAAABAdUoqAAAAAKpTUgEAAABQnZIKAAAAgOqUVAAA\n",
1475 1475 "AABUp6QCAAAAoDolFQAAAADVKakAAAAAqE5JBQAAAEB1SioAAAAAqlNSAQAAAFCdkgoAAACA6pRU\n",
1476 1476 "AAAAAFSnpAIAAACguimXVKWUw0spv1lK+YNSyms6rr2jlPIfp/oeAAAAAAy26VhJdX2Sdyf5j0lu\n",
1477 1477 "6Lj2hiSPTMN7AAAAADDAplRSlVLOTvIXTdOMJXlxkv/Vdm2vJKcl+c9TSggAAADAwJs1xa//30n+\n",
1478 1478 "ppRycJIXJvmltmvP3fz9/3yK7wEAAADAgJtSSdU0zcNJUkq5NMnqJD9qu3xukkeapvmfU3kPAAAA\n",
1479 1479 "AAbfdH2634uS/GnTNJvaZr+Q5C+m6fsDAAAAMMCmq6Q6LNvuR7VHkjPjVj8AAAAAdsJ0lVQ/SbJP\n",
1480 1480 "2/mtSebGpukAAAAA7ITSNM3Uv0kpxyW5O8k/Jlmb1qbpJzVNs/eUv/lO+JM/+ZMmSc4///zSjfcD\n",
1481 1481 "AAAAYHpN9dP9kiRN0/yvtDZKTymlJHkwyQ+n43sDAAAAMPimfLtfKeWbpZR/ahtdnGRJklum+r0B\n",
1482 1482 "AAAAGA7TsSfV+Un+LElKKQcluT3JmzavrgIAAACAHZqO2/3eluSMUsptSQ5MclnTNH8zDd8XAAAA\n",
1483 1483 "gCEx5ZKqaZrvJ/n+NGQBAAAAYEhNx+1+AAAAADAlSioAAAAAqlNSAQAAAFCdkgoAAACA6pRUAAAA\n",
1484 1484 "AFSnpAIAAACgOiUVAAAAANUpqQAAAACoTkkFAAAAQHVKKgAAAACqU1IBAAAAUJ2SCgAAAIDqlFQA\n",
1485 1485 "AAAAVKekAgAAAKA6JRUAAAAA1SmpAAAAAKhOSQUAAABAdUoqAAAAAKpTUgEAAABQnZIKAAAAgOqU\n",
1486 1486 "VAAAAABUp6QCAAAAoDolFQAAAADVKakAAAAAqE5JBQAAAEB1SioAAAAAqlNSAQAAAPBUpZRuvp2S\n",
1487 1487 "CgAAAIBttQqqv+jmWyqpAAAAAOj0kiRnd/MNlVQAAAAAbNVaRfX+br+tkgoAAACAducmeW6331RJ\n",
1488 1488 "BQAAAEC7G2u8qZIKAAAAgJZSnpnkRTXeWkkFAAAAwBbvq/XGSioAAAAAklKOT/JLtd5eSQUAAABA\n",
1489 1489 "krw3SWk7/8duvrmSCgAAAGDYlbIsyes6prd0M4KSCgAAAIBfSzKr7fxfkvxuNwMoqQAAAACGWSn7\n",
1490 1490 "J7myY3prmma8mzGUVAAAAADD7dokc9vO70/yjW6HUFIBAAAADKtSFid5R8f0tjTNxm5HUVIBAAAA\n",
1491 1491 "DK+rkyxsO380yd01giipAAAAAIZRKXsmua5j+uk0zdoacZRUAAAAAMPpyiT7tp2vTvK5SlmUVAAA\n",
1492 1492 "AABDp5Q5Sa7vmN6Zpnm8RpxESQUAAAAwjC5Pckjb+fokd1TKkkRJBQAAADBcShlNckPH9O40zcM1\n",
1493 1493 "4myhpAIAAAAYLpckObbtfCzJ7ZWy/JySCgAAAGBYlFKS3Ngx/Uaa5ic14rRTUgEAAAAMjxcnObXt\n",
1494 1494 "vEnyiUpZtqGkAgAAABgenauovp+m+ecqSTooqQAAAACGQSnnJjmnY3pLjSiTUVIBAAAADIf3dZz/\n",
1495 1495 "cZrm76okmYSSCgAAAGDQlXJakpd0TG+uEWV7lFQAAAAAg69zFdVfJvmLGkG2R0kFAAAAMMhKOS7J\n",
1496 1496 "KzumN6dpmhpxtkdJBQAAADDY3puktJ3/U5IfV8qyXUoqAAAAgEFVymFJXt8xvaXXVlElSioAAACA\n",
1497 1497 "QfarSWa1nf/vJN+rlOVpKakAAAAABlEp+ye5qmN6a5pmvEacHVFSAQAAAAyma5LMazu/P8k9lbLs\n",
1498 1498 "kJIKAAAAYNCUsijJr3RMb0/TbKwRZ2coqQAAAAAGz9VJFradP5rk7kpZdoqSCgAAAGCQlLJnkus6\n",
1499 1499 "pnekadbUiLOzlFQAAAAAg+UtSfZrO1+d5M5KWXaakgoAAABgUJQyJ8l7OqafS9M8XiPOrlBSAQAA\n",
1500 1500 "AAyO1yY5tO18fZJPV8qyS5RUAAAAAIOglNEkN3RMv5ymebhGnF2lpAIAAAAYDL+Y5Li287Ekt1XK\n",
1501 1501 "ssuUVAAAAAD9rpSS5MaO6b1pmp/UiLM7lFQAAAAA/e+CJKe1nTdJPlEpy25RUgEAAAD0v85VVL+X\n",
1502 1502 "pvmfVZLsJiUVAAAAQD8r5Zwkv9AxvaVGlKlQUgEAAAD0t/d1nP+HNM3fVkkyBUoqAAAAgH5VyqlJ\n",
1503 1503 "XtoxvblGlKlSUgEAAAD0r85VVH+V5M9rBJkqJRUAAABAPyrluCSv6pjenKZpasSZKiUVAAAAQH/6\n",
1504 1504 "UJLSdv5/J/lRnShTp6QCAAAA6DelnJLkso7px/t1FVWipAIAAADoRx/tOP+nJN+rEWS6KKkAAAAA\n",
1505 1505 "+kkpz07y8o7p+9M0EzXiTBclFQAAAEB/+XjH+V+nj/ei2kJJBQAAANAvSjk/yb/rmN7Yz3tRbaGk\n",
1506 1506 "AgAAAOgHpZQ8dRXVf0rT/FmFNNNOSQUAAADQHy5MclbH7P01gswEJRUAAABArytlJMnHOqY/SNP8\n",
1507 1507 "XzXizAQlFQAAAEDvuzTJyW3nTZIPVsoyI5RUAAAAAL2slFlJPtIx/Vaa5v+pEWemKKkAAAAAetsb\n",
1508 1508 "kxzTdj6e5NcrZZkxSioAAACAXlXKHklu6ph+NU3zLzXizCQlFQAAAEDvemuSw9rON+apt/4NBCUV\n",
1509 1509 "AAAAQC8qZa8kH+iYfj5Nc1+NODNNSQUAAADQm96ZZP+287VJbqmUZcYpqQAAAAB6TSmLk7y3Y3pH\n",
1510 1510 "mubhGnG6QUkFAAAA0Ht+NcnitvMnktxeKUtXKKkAAAAAekkp+ye5rmN6W5pmZY043aKkAgAAAOgt\n",
1511 1511 "NyTZq+38kSSfqZSla5RUAAAAAL2ilEOSXN0xvTlN82SNON2kpAIAAADoHR9Mskfb+f1JvlApS1cp\n",
1512 1512 "qQAAAAB6QSlHJXlLx/QjaZr1NeJ0m5IKAAAAoDd8KMmstvP/N8nXqiSpQEkFAAAAUFspy5Nc3jG9\n",
1513 1513 "KU2zqUacGpRUAAAAAPV9JElpO//vSb5VKUsVSioAAACAmko5I8kvdkw/mKaZqBGnFiUVAAAAQF0f\n",
1514 1514 "6zj/myQ/qBGkJiUVAAAAQC2lPC/JBR3T96dpmhpxalJSAQAAANRQSkny8Y7pnyX5T90PU5+SCgAA\n",
1515 1515 "AKCOFyc5u2M2lKuoEiUVAAAAQPeVMpKnrqL6UZrmr2rE6QVKKgAAAIDuuyTJaR2zD9QI0iuUVAAA\n",
1516 1516 "AADdVMpoko92TL+bpvmHGnF6hZIKAAAAoLtel+T4tvOJJDdVytIzlFQAAAAA3VLKnCQf6pj+dprm\n",
1517 1517 "nyuk6SlKKgAAAIDuuTLJ4W3nm5J8uE6U3qKkAgAAAOiGUvbMUzdHvytN868V0vQcJRUAAABAd1yd\n",
1518 1518 "ZGnb+bokH6+UpecoqQAAAABmWikLk7yvY/pbaZoHa8TpRUoqAAAAgJl3XZK9285XJ/lEpSw9SUkF\n",
1519 1519 "AAAAMJNK2SfJr3ZMfyNN81iNOL1KSQUAAAAws96bZEHb+WNJPl0pS89SUgEAAADMlFIOTfLOjumt\n",
1520 1520 "aZpVNeL0MiUVAAAAwMz5RJK5becPJrmzUpaepqQCAAAAmAmlPDfJazqmv56mWVcjTq9TUgEAAABM\n",
1521 1521 "t1JGktzRMf2nJF+pkKYvKKkAAAAApt/rkpzRMbsmTTNeI0w/UFIBAAAATKdS5ie5tWP6u2ma/1wj\n",
1522 1522 "Tr9QUgEAAABMr/cmWdp2vjHJeypl6RtKKgAAAIDpUsqyJL/WMf1Umub/1IjTT5RUAAAAANPnk0nm\n",
1523 1523 "tp0/nOTmSln6ipIKAAAAYDqUck6SSzumN6ZpVteI02+UVAAAAABTVcpIkjs6pn+f5GvdD9OflFQA\n",
1524 1524 "AAAAU/fGJKd3zK5N00zUCNOPlFQAAAAAU1HKgjx136nvpmn+okacfqWkAgAAAJia9yU5sO18Q5L3\n",
1525 1525 "VMrSt5RUAAAAALurlCOSvLtjenua5l8rpOlrSioAAACA3ffJJHu0nT+Y5NZKWfqakgoAAABgd5Ty\n",
1526 1526 "vCSv7Ji+L03zZI04/U5JBQAAALCrShlNckfH9G+T3FMhzUBQUgEAAADsujclObVjdm2aZqJCloGg\n",
1527 1527 "pAIAAADYFaUsTHJzx/RbaZq/rBFnUCipAAAAAHbN+5Ps33a+Lsl7K2UZGEoqAAAAgJ1VylFJru2Y\n",
1528 1528 "3pam+bcacQaJkgoAAABg592WZE7b+QNJPlkpy0BRUgEAAADsjFKen+QXO6Y3pGnW1IgzaJRUAAAA\n",
1529 1529 "ADtSymiSOzqm/y3J71RIM5CUVAAAAAA7dkWSkztm16ZpJmqEGURKKgAAAICnU8qiJB/rmN6bpvmv\n",
1530 1530 "NeIMKiUVAAAAwNP7QJL92s7XJbmhUpaBpaQCAAAA2J5SjklyTcf0E2ma+2vEGWRKKgAAAIDtuz3J\n",
1531 1531 "7Lbz+5LcVinLQFNSAQAAAEymlBckeUXH9L1pmrU14gw6JRUAAABAp1JmJfl0x/Svk3yrQpqhoKQC\n",
1532 1532 "AAAAeKqrkizvmF2TpmlqhBkGSioAAACAdqUsTvLRjulvp2n+pkacYaGkAgAAANjWTUn2aTtfm+TG\n",
1533 1533 "SlmGhpIKAAAAYItSjkvyzo7pLWmaB2rEGSZKKgAAAICtfiPJrLbzf9s8Y4YpqQAAAACSpJQXJXlZ\n",
1534 1534 "x/Q9aZp1NeIMGyUVAAAAQCmzknyqY/pfknynQpqhpKQCAAAASN6W5MS28ybJtWmaplKeoaOkAgAA\n",
1535 1535 "AIZbKUuTfKxj+vU0zd/ViDOslFQAAADAsLsjyaK28zVJbqyUZWgpqQAAAIDhVcqFSS7tmH4wTfNg\n",
1536 1536 "jTjDTEkFAAAADKdSFiT5XMf0b5P8ZoU0Q09JBQAAAAyrjyY5tO18PMlb0zTjlfIMNSUVAAAAMHxK\n",
1537 1537 "OTPJuzqmn0rT/EONOCipAAAAgGFTyuwkdyUpbdP/L8mH6wQiUVIBAAAAw+e6JKd0zN6epllTIwwt\n",
1538 1538 "SioAAABgeJRyVJIPdUzvTdP8cYU0tFFSAQAAAMOhlJLk80nmtU1XJHl3nUC0U1IBAAAAw+LyJC/s\n",
1539 1539 "mP1qmuZnNcKwLSUVAAAAMPhK2TfJpzumf5rk6xXSMAklFQAAADAMbk+yb9v5hiS/nKZpKuWhg5IK\n",
1540 1540 "AAAAGGylnJ/kjR3Tj6Rp/qVGHCanpAIAAAAGVynzknyxY/rf01pZRQ9RUgEAAACD7KYkR7WdN0mu\n",
1541 1541 "StNsrJSH7VBSAQAAAIOplJOTXN8xvTNN819rxOHpKakAAACAwVPKaJIvJRltmz6Q5P11ArEjSioA\n",
1542 1542 "AABgEF2d5MyO2TvSNKtqhGHHlFQAAADAYCnl0CQ3d0y/n6b5QY047BwlFQAAADA4SilJ7kwyv226\n",
1543 1543 "Ksm76gRiZympAAAAgEFySZKXd8xuSNM8UCMMO09JBQAAAAyGUhYn+WzH9K+SfLFCGnaRkgoAAAAY\n",
1544 1544 "FLckWdp2vinJW9M0E5XysAuUVAAAAED/K+WcJG/rmH4iTfM/asRh1ympAAAAgP5Wyh5J7uqY/kuS\n",
1545 1545 "j1dIw25SUgEAAAD97r1JTuiYvTVNs75GGHaPkgoAAADoX6Ucn+T9HdOvpGn+rEIapkBJBQAAAPSn\n",
1546 1546 "UkbSus1vTtv0Z0murxOIqVBSAQAAAP3qLUnO7Zhdk6ZZUSMMU6OkAgAAAPpPKQcmua1j+uMk366Q\n",
1547 1547 "hmmgpAIAAAD60R1JFredr01ydZqmqZSHKVJSAQAAAP2llJcleXXH9INpmn+tkIZpoqQCAAAA+kcp\n",
1548 1548 "85N8rmP690l+s0IappGSCgAAAOgnH0lyWNv5RJKr0jRjlfIwTZRUAAAAQH8o5VlJrumYfjpN8/c1\n",
1549 1549 "4jC9lFQAAABA7ytlzyT3ZNsu4ydJfr1OIKabkgoAAADoB59IcnzH7O1pmjU1wjD9lFQAAABAbyvl\n",
1550 1550 "JUl+pWP61TTNj2vEYWYoqQAAAIDeVcp+Sb7aMf0/eereVPQ5JRUAAADQm0opSb6U5IC26USS16Vp\n",
1551 1551 "VtcJxUxRUgEAAAC96ookF3XMPpam+esaYZhZSioAAACg95RyTJLPdEz/W5KPVUhDFyipAAAAgN5S\n",
1552 1552 "yuwk30iyZ9t0TZLXp2k21QnFTFNSAQAAAL3m/UnO7Jhdm6b5lxph6A4lFQAAANA7SnlOkg90TH+Q\n",
1553 1553 "5MsV0tBFSioAAACgN5SyIMk9SUbbpg8nuSpN09QJRbcoqQAAAIBecUeSozpmb07TPFIjDN2lpAIA\n",
1554 1554 "AADqK+WSJG/pmN6ZpvlxjTh0n5IKAAAAqKuUg5J8qWP6z0neUyENlSipAAAAgHpKGUny1SR7t003\n",
1555 1555 "Jbk8TbO2TihqUFIBAAAANb0jyQUdsw+maf6+RhjqUVIBAAAAdZRyUpJPdkz/PMntFdJQmZIKAAAA\n",
1556 1556 "6L5S9kjyjSRz26arkrwhTTNeJxQ1KakAAACAGj6S5NSO2dVpmp/UCEN9SioAAACgu0o5L8n1HdNv\n",
1557 1557 "Jfmd7oehVyipAAAAgO4pZUmS305S2qb3pbWKqqkTil6gpAIAAAC66c4kh7adN0nemKZZWSkPPUJJ\n",
1558 1558 "BQAAAHRHKa9N8pqO6e1pmj+tEYfeoqQCAAAAZl4py5J8rmP6T0k+WCENPUhJBQAAAMysUkaTfD3J\n",
1559 1559 "orbphiSXp2k21AlFr1FSAQAAADPtV5M8r2P2njTN/6gRht6kpAIAAABmTimnJflYx/Q/JPmtCmno\n",
1560 1560 "YUoqAAAAYGaUMi/JvUlmt01XJHlzmmaiTih6lZIKAAAAmCmfSHJCx+yqNM1Pa4ShtympAAAAgOlX\n",
1561 1561 "youTvLNj+pU0zfdrxKH3KakAAACA6VXKfkm+2jH9P0murZCGPqGkAgAAAKZPKSXJXUkO3DJqkokk\n",
1562 1562 "r0vTrK6Wi56npAIAAACm0zuSXNw+uO/QQ7+TpvnrSnnoE0oqAAAAYHqUck6ST7ePHlm2bPx3Lr/8\n",
1563 1563 "25US0Udm1Q4AAAAADIBSlib5btq6hon58/OnV1yxdsPExHi9YPQLK6kAAACAqSllTloF1YHt48c/\n",
1564 1564 "85k8ceCBE3VC0W+UVAAAAMBU3Z7k7PbBk+96Vza85CWV4tCPlFQAAADA7ivldUne2T7a8LznZfX1\n",
1565 1565 "11cKRL9SUgEAAAC7p5RTk9zVPho75JCsvPPOZHS0Uij6lZIKAAAA2HWl7J3k+0nmbRk1c+dm5d13\n",
1566 1566 "p9l773q56FtKKgAAAGDXlDKa5N4kR7SPn7j11oydfHKdTPQ9JRUAAACwq349yYvbB2ve+Masu/TS\n",
1567 1567 "SnEYBEoqAAAAYOeV8vIkH2wfbTz99Kz68IcrBWJQKKkAAACAnVPKMUm+0T4a33ffrLzrrmTOnEqh\n",
1568 1568 "GBRKKgAAAGDHSpmf1kbpC7eMmtHRPH7XXZlYurReLgaGkgoAAAB4eqWUJHcnWd4+XnXTTdn47GfX\n",
1569 1569 "ycTAUVIBAAAAO3Jtkle3D9ZdfHHWXnllpTgMIiUVAAAAsH2lnJfktvbRphNOyBO3356UUicTA0lJ\n",
1570 1570 "BQAAAEyulEOSfDvJ6JbRxMKFWXn33Wn23LNeLgaSkgoAAAB4qlL2SPK9JPu3jx//7GczfsQRdTIx\n",
1571 1571 "0JRUAAAAwGTuSHJW+2D1u9+dDS98YaU4DDolFQAAALCtUt6c5G3to/Xnn58n3/3uSoEYBkoqAAAA\n",
1572 1572 "YKtSTk/y+fbR2LJlefyzn01G1AjMHP93AQAAAC2l7Jvk+0n22DJq5s7Nyi9/Oc3ixfVyMRSUVAAA\n",
1573 1573 "AEBSymiSbyY5rH38+O23Z+zEE+tkYqgoqQAAAIAk+ViSF7QP1lxxRdZfckmlOAwbJRUAAAAMu1Iu\n",
1574 1574 "SXJD+2jDWWdl1U03VQrEMFJSAQAAwDAr5fgkX28fjR9wQB7/4heT2bMrhWIYKakAAABgWJWyIMnv\n",
1575 1575 "JZm/ZdTMnp2Vd92Vif33r5eLoaSkAgAAgGFUSknytSTHt49XfehD2XTGGVUiMdyUVAAAADCc3pNk\n",
1576 1576 "m13R177qVVn7pjfVScPQU1IBAADAsGltlH5L+2jTSSfliVtvTUqpFIphp6QCAACAYVLK2UnuTfLz\n",
1577 1577 "Nmpi8eKs/PKXk3nz6uVi6CmpAAAAYFi0Psnv95PM3TJqRkez8nOfy/hhh9XLBVFSAQAAwHAoZWmS\n",
1578 1578 "P0qypH38xG23ZeN551WJBO2UVAAAADDoSlmQ5A+TLGsfr/61X8u6yy6rkwk6KKkAAABgkJUyO8n3\n",
1579 1579 "kpzWPl772tfmyeuuq5MJJqGkAgAAgEFVSklyd5IL2sfrzz/fJ/nRc5RUAAAAMLg+muQN7YONp5yS\n",
1580 1580 "x7/whWTWrEqRYHJKKgAAABhEpfxykve3j8aWLcvKe+5Js9delULB9impAAAAYNCU8ookn2sfje+9\n",
1581 1581 "d1bce28m9t23Uih4ekoqAAAAGCSlPDvJt9L2O38zd25W/vZvZ/zII+vlgh1QUgEAAMCgKOWYJL+f\n",
1582 1582 "ZN6WUTMykpVf+EI2PfOZ9XLBTlBSAQAAwCAo5YAkf5Rkm/v5Vt1ySzZccMHkXwM9REkFAAAA/a6U\n",
1583 1583 "+Un+IMk29/OtvuaarH396+tkgl2kpAIAAIB+VsqsJN9O8qz28dpLL82T73lPnUywG5RUAAAA0K9K\n",
1584 1584 "KUm+kOSl7eMNz3tenrjttqSUOrlgNyipAAAAoH/dlOSK9sGm5cuz8ktfSmbPrhQJdo+SCgAAAPpR\n",
1585 1585 "KVck+VD7aOyQQ7LinnvSzJ9fJxNMgZIKAAAA+k0pL03yxfbRxJIlWXHvvZk44IBKoWBqlFQAAADQ\n",
1586 1586 "T0p5VpLvJhndMmrmzs2Kr34148ccUy8XTJGSCgAAAPpFKUcm+cMke24ZNaVk5Z13ZtOZZ9bLBdNA\n",
1587 1587 "SQUAAAD9oJT9kvxRkv3bx6s++tFseMlL6mSCaaSkAgAAgF5Xyp5Jfj/JNvfzPXn11Vn7lrfUyQTT\n",
1588 1588 "TEkFAAAAvayUWUm+meSs9vG6Sy7J6htvrJMJZoCSCgAAAHpVKSXJZ5O8on284Zxz8vinPpWM+LWe\n",
1589 1589 "weH/ZgAAAOhdH0zytvbBphNPzMq7707mzKkUCWaGkgoAAAB6USkfSPLh9tH4QQdlxT33pFm4sFIo\n",
1590 1590 "mDlKKgAAAOg1pdyU5KPto4lFi7Li3nszsXRppVAws5RUAAAA0EtK+VA6VlBN7LVXVnztaxk77rg6\n",
1591 1591 "maALZtUOAAAAAGTLJukfSnJT+3hir72y4t57s+nMM6vEgm5RUgEAAEBtrYLqI0k+0D6emD+/VVCd\n",
1592 1592 "cUadXNBFSioAAACoqVVQfSzJje3jiQULsuJ3fiebTj+9Ti7oMiUVAAAA1NIqqG5OckP7eGLBgqz4\n",
1593 1593 "5jez6ZnPrJMLKlBSAQAAQA2tgurWJO9pH08sXNgqqE47rU4uqERJBQAAAN3WKqg+meTX2scTixZl\n",
1594 1594 "xbe+lU2nnFInF1SkpAIAAIBuahVUtyd5d/t4YtGiPPbtb2fs5JPr5ILKRmoHAAAAgKHRKqg+lc6C\n",
1595 1595 "avFiBRVDz0oqAAAA6IZWQfXpJNe0jyeWLMlj3/pWxp7xjDq5oEcoqQAAAGCmtQqqzyR5Z/t4YsmS\n",
1596 1596 "1gqq5cvr5IIeoqQCAACAmdQqqD6b5B3t44klS/LYd76TsZNOqpMLeoySCgAAAGZKKSNJfivJ29vH\n",
1597 1597 "43vvnRXf+U7GTjyxTi7oQUoqAAAAmAmtgurOJG9rH4/vs09WfPe7GTv++Dq5oEcpqQAAAGC6tQqq\n",
1598 1598 "zyd5a/t4fN99WwXVccfVyQU9TEkFAAAA06lVUH0xyZXt4/H99msVVMceWycX9DglFQAAAEyXVkH1\n",
1599 1599 "pSRvaR+P77dfVnzvexk75pg6uaAPjNQOAAAAAAOhlNEkX05nQbX//nlMQQU7ZCUVAAAATNXWguqN\n",
1600 1600 "7ePxAw7IY9/9bsaPPrpOLugjSioAAACYilZB9dUkr28fjx94YKugOuqoOrmgzyipAAAAYHeVsmeS\n",
1601 1601 "byT5xfbx+NKlrYLqyCPr5II+pKQCAACA3VHKAUl+mOTM9vH40qV57Hvfy/gRR9TJBX1KSQUAAAC7\n",
1602 1602 "qpQTkvwoyeHt4/GDDmoVVIcfPtlXAU/Dp/sBAADArijl+Un+Kh0F1aYTTsijP/iBggp2k5IKAAAA\n",
1603 1603 "dlYpb0jyx0kWt4/Xn3deHvv3/z4TBx9cJxcMACUVAAAA7EgpJaV8KMnXk8xuv7T28suz8utfT7Ng\n",
1604 1604 "QZVoMCjsSQUAAABPp5Q5Se5O8vrOS6tuvDFr3vGOpJTu54IBo6QCAACA7SllSZLvJzmvfdzssUce\n",
1605 1605 "v+OOrL/ooiqxYBApqQAAAGAypRyR1if4Hd8+nliyJCu++tVsOvPMOrlgQCmpAAAAoFMpZyb5/ST7\n",
1606 1606 "t4/HjjgiK+65J+NHHlknFwwwG6cDAABAu1J+McmfpaOg2njGGXn0hz9UUMEMUVIBAABAsuUT/K5L\n",
1607 1607 "8rtJ5rVfWnfRRXns299Os88+dbLBEFBSAQAAQCmzknw2yaeSbPNRfU++8515/M47k7lzq0SDYWFP\n",
1608 1608 "KgAAAIZbKfOTfDPJhe3jZnQ0T9x6a9ZdfnmdXDBklFQAAAAMr1IOSvIHSU5rH0/Mn5+Vd92Vjeed\n",
1609 1609 "VyUWDCMlFQAAAMOplGck+cMkh7aPx5cuzYp77snYiSfWyQVDyp5UAAAADJ9SXpjkL9NRUG1avjyP\n",
1610 1610 "/uEfKqigAiUVAAAAw6WUK5L8KMmC9vH6F7wgj/3e72XiwAPr5IIhp6QCAABgOJQyklI+nuTudGx/\n",
1611 1611 "s+aNb8zKr3wlzV571ckG2JMKAACAIVDKnkm+nOSy9nFTSlbfdFPWvPWtSSl1sgFJlFQAAAAMulJO\n",
1612 1612 "SvKdJNtsNNXMnZvHf+u3sv6lL62TC9iGkgoAAIDBVEpJ8qYkdyaZ135pfJ99svJrX8um00+vkQyY\n",
1613 1613 "hJIKAACAwVPK/CSfS/L6zktjRx+dFffck/Fly7qfC9guG6cDAAAwWEo5OcnfZJKCau0rX5lHf/xj\n",
1614 1614 "BRX0ICupAAAAGAyt2/uuSvKZJHPbLzVz5+aJm2/Oule/2gbp0KOUVAAAAPS/UhYm+WI6Pr0vSTYd\n",
1615 1615 "e2wev+vpHga3AAAgAElEQVSujB17bPdzATvN7X4AAAD0t1JOS/J3maSgWnvZZXn0Rz9SUEEfsJIK\n",
1616 1616 "AACA/tS6ve/tST6dZE77pYk998yqW2/Nule+sko0YNcpqQAAAOg/pSxKcneSp7RQm044ISu/8IWM\n",
1617 1617 "H3NM93MBu83tfgAAAPSXUp6V5B8ySUG15vWvz6N/8AcKKuhDVlIBAADQH1q3970ryW1JZrdfmpg/\n",
1618 1618 "P0988pNZf/HFVaIBU6ekAgAAoPeVsiTJV5I8pYXatHx56/a+I4/sfi5g2rjdDwAAgN5Wyllp3d73\n",
1619 1619 "lIJqzZvelEd/+EMFFQwAK6kAAADoTaWMJLkuya3p+P11YsGCPPEbv5H1F15YJRow/ZRUAAAA9J5S\n",
1620 1620 "9kny9SQv67y08ZRT8vgXvpDxZcu6nwuYMW73AwAAoLeUcnaSf8wkBdWTV12Vx37wAwUVDCArqQAA\n",
1621 1621 "AOgNpcxO8p4kH04y2n5pYtGiPP7pT2fDi19cJRow85RUAAAA1NfaHP1LSZ7ReWnj6afn8c9/PuOH\n",
1622 1622 "HNL9XEDXuN0PAACAekpZkFJ+M8lfZ5KC6sm3vS2Pff/7CioYAlZSAQAAUEcpL0/yuSRPaaAmlizJ\n",
1623 1623 "45/5TDa84AXdzwVUYSUVAAAA3VXK0pTy3SQ/zCQF1dpXvjKP/PmfK6hgyFhJBQAAQHeUMpLkqiSf\n",
1624 1624 "SLKo8/LYsmV54tZbs/F5z+t6NKA+JRUAAAAzr5QTk9yV5OzOS83oaNa87W1Zfd11yZ57dj8b0BOU\n",
1625 1625 "VAAAAMycUvZIcmOS9yWZ3Xl54ymn5InbbsvY8uVdjwb0FiUVAAAAM6OUX0hr9dRxnZcm9twzq2+4\n",
1626 1626 "IWvf/OZkdLT72YCeo6QCAABgepWyJK19p66a7PL6F7wgT9x8cyYOecqe6cAQU1IBAAAwPUopSV6V\n",
1627 1627 "5DeTHNB5eXy//bLqox/N+pe/PCml6/GA3qakAgAAYOpKOSzJ55K8bLLLay+/PKve//40ixd3NxfQ\n",
1628 1628 "N5RUAAAA7L5SRpP8SpKPJ9mr8/LYUUflidtuy8ZnP7vr0YD+oqQCAABg95RyapIvJXlW56Vm9uw8\n",
1629 1629 "+Su/kiff+c5k7tzuZwP6jpIKAACAXVPKXkluSvKrSZ7y0XwbzzgjT9x2W8aOPbbr0YD+paQCAABg\n",
1630 1630 "55QyJ8mVST6Y5MDOyxMLFmT1Bz6QtZdfnoyMdD0e0N+UVAAAADy9UkaSXJbko0mOnOwl6y68MKs+\n",
1631 1631 "8pFMHPiU7gpgpyipAAAAmFwpJclLk9yc5OTJXjK+dGmeuPnmbHjRi7oaDRg8SioAAACeqpRzk9yS\n",
1632 1632 "5OzJLjdz52bNW96SJ6+5Js2CBd3NBgwkJRUAAABblXJKWiunXjrZ5WbWrKx97Wvz5LXXurUPmFZK\n",
1633 1633 "KgAAAJJSjk7ykSSv2d5L1l18cVZff33Gjziie7mAoaGkAgAAGGalHJTWp/Vdme38jrj+/POz+r3v\n",
1634 1634 "zdjy5V2NBgwXJRUAAMAwKmVJkvcmeVeSeZO9ZOMZZ2TVjTdm01lndTUaMJyUVAAAAMOklL3SKqbe\n",
1635 1635 "k2TxZC/ZdOKJWX3DDdlw/vlJKV2NBwwvJRUAAMAwKGVOWrf0fTDJpDuejy1bltXXX5/1F1+cjIx0\n",
1636 1636 "NR6AkgoAAGCQlTKS1mboH0ly5GQvGd9//zx53XVZ+5rXJHPmdDUewBZKKgAAgEFUSklyYZKPJ3nG\n",
1637 1637 "ZC+ZWLQoT159ddZecUWaPffsajyATkoqAACAQdLac+r1ae07dcJkL2nmzs2aK6/Mk1dfnWbxpNtS\n",
1638 1638 "AXSdkgoAAGAQlLIsyTuSXJXtbIjezJqVtZdfnievvTYTBxzQ1XgAO6KkAgAA6FetW/rOTXJNkouT\n",
1639 1639 "TLrbeVNK1l98cVZff33GDz+8iwEBdp6SCgAAoN+UMjfJZWmVU6du72XN6GjWv/SlefJd78rYSSd1\n",
1640 1640 "LR7A7lBSAQAA9ItSDkry9iS/nGS/7b1sYsmSrH3d67LmDW/IxMEHdy0ewFQoqQAAAHpdKWeltWrq\n",
1641 1641 "VXma3+M2HX981lxxRdZdckkyb17X4gFMByUVAABALypldpJXplVOnbW9lzWlZMMFF2TNFVdk49ln\n",
1642 1642 "J6V0LSLAdFJSAQAA9JJS9kvrdr63Jzloey+bWLAga1/zmqx985szvmxZ1+IBzBQlFQAAQC8o5ZS0\n",
1643 1643 "Vk29Nske23vZ2JFHtm7pu/TSNHvt1bV4ADNNSQUAAFBLKfOSXJjkHUme93QvXX/eeVl75ZXZcN55\n",
1644 1644 "ychIN9IBdJWSCgAAoJtKmZPkhUkuS3Jxkvnbe+nEvHlZd+mlWfOWt2T8mGO6lRCgCiUVACRbNqdd\n",
1645 1645 "kmTx5sfOY0FaPze3HLM7zqdyJMnGJBs6jslmuzpfk+TxtmNVmmZiWv6bAbDzShlNcl5axdQvpfWz\n",
1646 1646 "ZbvGDj00a9/85qx9zWvSLFrUhYAA9SmpABgcpeyRZO9sv2jackx2fXg29ShlVbaWVk9k2xKr87xz\n",
1647 1647 "9kSaZlOF1AD9p5SRJM9Jq5h6VZIDdvQlG5773Ky54opsuOCCZHR0phMC9BQlFQD9o5T5SZYlOXzz\n",
1648 1648 "0fl8/zrB+s7Czcdhu/XVpaxNq7B6NMnDm4+fbef5I2majVOPDNAnSilJnplWMfXqJIfu6EvGDzgg\n",
1649 1649 "61/+8qx99aszdtJJM50QoGcpqQDoHaUsytbiabIyap86weiw5+Zjux+Lvo1SVmb7Jda2z5vmyRnI\n",
1650 1650 "CzDzSjkprWLqsiRH7+jlE0uWZN2FF2b9RRdl41lnWTUFECUVAN3U2ij2+CRHZvLVUIvrBEuakZE0\n",
1651 1651 "ixZlYvPRLFyYicWLW88XLcrEwoXJ7NlpZs1q/SIxa1aaLY9TmGXWrKRpko0bUzYf2bCh9XzTpq3P\n",
1652 1652 "n26+cWPKhg2t+ZbnW+Zr1mRk1aqMPPFEyqpVGXmySge05ZbK43b4ytYqrYeTPLD5uH/z8UDb44Nu\n",
1653 1653 "OQR6QilHpbVa6rIkz9jRyyfmz8/6l7wk6y++OBvOOSeZPXvGIwL0EyUVADOjtSrqlCSnJTl18+OJ\n",
1654 1654 "aW04PiOakZFMLF6cZnO59POCafHibQuo9udbiqj584fj47zHx1NWr87IqlUpTzyRkdWrW4+rVrVK\n",
1655 1655 "rC2Pk802P5aJGd13fc8kR2w+tqdJKQ9l+yVW67Fp1s5kUGBIlXJIkkvTKqbO2NHLm7lzs/6FL8y6\n",
1656 1656 "iy/Ohuc/P5k7d8YjAvQrJRUAU9Pae+OgbC2itpRSR073WzWzZmX84IMzfuihWx8PPTTjhxzSejzw\n",
1657 1657 "wNbKJLZvdDTN4sUZX7ybi9aaJmXNmpTHH8/oY49l5NFHM/LII63jsccy2vZ85JFHMrJixUyUWiXJ\n",
1658 1658 "0s3Hs7b/qrIyTy2x7k/yb0l+kuS+NM266Q4HDJjW5uenJDk/ySuSnLujL2lmz86G5z8/6y66KBsu\n",
1659 1659 "uCDNXsPz2RwAU+Fv8gDsvNbHZx+TbVdHnZpkv+n49s2cOa3yaUvptPlxbPPjxAEH2LOjtlLSzJ+f\n",
1660 1660 "Zv78TBxyyI5fPz6ekZUrtxZZjz6a0S3F1qOP/rzkGt38vGyc1j3Wt9xmuP1bcEr5WbaWVpM9Ppam\n",
1661 1661 "aaYzFNDjWv/4clRapdT5Sf5ddmJPxGZ0NBvPOSfrLroo61/84jS7+48BAENMSQXA5EqZl9Yv9+1l\n",
1662 1662 "1Mlp3Y6128aXLs3YscdmrH0V1JYSav/9h+OWu2EyOpqJfffNxL77Jiec8PSvbZrWrYgPP5zRhx7K\n",
1663 1663 "6EMPZeTBBzPadow89FBGH3lkOhPuv/nY3oqstSllS2k1WZH1QJpmbDoDARWUckC2llLnp7Vf4k7Z\n",
1664 1664 "8OxnZ/1FF2X9y17W+rMOgN2mpAKgpZSFSX4hyQuSPD/JSUl2e9lSMzKSsaOPztjy5dl00kk/P5p9\n",
1665 1665 "fEAf21FKmoULM75wYcaPOWb7r9u4MaMPP7xNgTXy0ENbnz/4YEYffjhlbFq6oz3T2uz/+O1cn0gp\n",
1666 1666 "D2RrafWvHY//5pZC6EGtn3nPy9ZSavmufPnG007L+osuyroLL8zEQTv3QacA7JiSCmBYlbJHkmen\n",
1667 1667 "VUqdn+TM7GYp1cydu7WIWr48YyedlE3HH5/MmzeNgWGzOXN+vh/Zdj/ib2KidWvhltJqy/HTn2bk\n",
1668 1668 "gQcyev/9GX3ooZTx8ammGUly6Obj7Elf0drkfbICq/XYNGumGgLYgSn+zJtYuDAbn/OcbDjnnGw4\n",
1669 1669 "//yMH374zOQEGHJKKoBh0dpP6tRs/Vfjc5Pscos0vvferdVRW1ZILV+e8SOPtFcUvWVkJBP779+6\n",
1670 1670 "hfSUUyZ/zdhYawXWAw+0jvvv3/q4+RhZNy2LoA7cfJw16dVSHs3kBVbredOsmo4QMFRam51v+Zn3\n",
1671 1671 "guziz7xmjz2y8YwzsuGcc7LxnHOy6eSTfTAHQBf4kxZgULU2fj06W//V+PlJ9t6VbzG2bNnWlVGb\n",
1672 1672 "S6mJAw9MSpmBwNBls2Zl4pBDMnHIIZOvyGqalJUrty2wOsusRx+djiT7bj4m3xer9SmFk+2HteX5\n",
1673 1673 "z9I00/4RitBXWntKbdlD8VnZxZ95TSnZdMop2XjOOa1i6owzrAYGqEBJBTBISlmabTd+PXRXvnzs\n",
1674 1674 "6KOz4dxzW39Bf85zfDIRw62UNHvvnbG9987YM7bzAYHr1mX0pz/duvrqgQcyet99mXXffa2VWA89\n",
1675 1675 "lDIx5f5oy6cUnrqd6xtSyn2ZvMD6SZL70zQbphoCekJrhdSReeqnzC7d1W81dvTRrdv3zj3XzzyA\n",
1676 1676 "HqGkAuhnpSxKcl62llIn7sqXjy9d2vrL+TnnZMPZZ2di6S7/HR+G27x5GT/qqIwfddTk1zdtau2F\n",
1677 1677 "tbm0+vnjluc//el07Iu1R1qrJo/ezvWmbV+sztVY/5bkviQr0zTNVIPAtGrtI3VSti2jTkmyYHe+\n",
1678 1678 "3fiBB279mXfOOX7mAfQgJRVAvynlwCSvTPLqJM9Na+PmnTKxaFE2Pve5P18tNX7UUW7dg5k0e3bG\n",
1679 1679 "Dzss44cdNvn1tn2xZt1337Zl1uZbCsum7W4Pv7NKWqtMlqa1cfRk1m3+lML7k2x5bH/+QJKH0zRT\n",
1680 1680 "btRgUqUsTquAal8hdWKm8PvKz3/mbS6lxo8+2s88gB6npALoB6XsneSSJJeltc/GThVTzdy5rY1f\n",
1681 1681 "zz03G889N5uWL7fBOfSS9n2xzppkX/WJiYw8/PC2+2G174/1wAMZWTUt+6rPy9OvxkqS8ZTy02y/\n",
1682 1682 "xLo/yU/dWsjTapVRhyc5IsnybC2ljpjKt23mzMmm44/fuofiaadl0zOe4WceQJ9RUgH0qlIWJLko\n",
1683 1683 "rWLqRdmJP7ObkZFsOvXU1q0M556bjaefnsydO9NJgZkyMpKJpUszsXRpNj1rO/uqr1r11A3d2x5H\n",
1684 1684 "Hn44ZXru5BtNa5+7p9/rrpRH0r76qnX8bJLnK2z4PmBaH9ixd1ol1LLNj53PF071bSYWLfr5h3mM\n",
1685 1685 "bXk8+uhk9uypfmsAKlNSAfSSUuYleVlaxdTLkuywYdp07LFbS6nnPCfNwin//R/oI83ChRlbuDBj\n",
1686 1686 "J5ww+Qs2bmzti7WdImvkoYcysnbtdEbab/Nx2g5eN7650Hq6ImvL85+laaZ83yNT1Cqh9s3Wwunw\n",
1687 1687 "PLWMmj+dbzl28MHbfMLs2DOekfGDD3bbHsCAUlIB1FbKnCQXpFVMXZSd+Av+ppNOyrqLLsr6V7xi\n",
1688 1688 "+3vdACTJnDkZX7Ys48uWTX69aVqrsR56KCMPPtgqtDYfIw89tPX5ypXTnWw0yYGbjx0rZUW2lleP\n",
1689 1689 "JHl88/FE2/PJzp+0KfzTaP3jyJZPkFzc9nzLcWC2LaLmzUSMZnQ0Y0cfnU3Ll28tpU48Mc3ee8/E\n",
1690 1690 "2wHQo5RUADWUMprWp/JdluSX0vpF4GmNHXVU1l18cda94hUZP+aYGQ4IDI1S0ixalLFFi5Ljjtv+\n",
1691 1691 "69aty+hDD20ts37609Z5W5k18rOfpUzM2B18e28+jt/Fr5tIKTsqstrP1yTZmGTDJMfGbZ7Xvl2x\n",
1692 1692 "tbJpVlqf8DhZwdR+bO/6Ht2M3OyxR8YPPjjjhx6ascMP33rL3nHHJfNmpP8CoI8oqQC6pZSRJM9J\n",
1693 1693 "q5h6VZIDdvQlY4cemvUXXZR1F12UsRNPdHsDUM+8eRk/4oiMH/E0+1uPjWXkZz9rrb56+OGMPPJI\n",
1694 1694 "Rh59tHU88kj+f/buPM7Ksv7/+OuaYZMdFFyA3JDFBUVNXEhQUFxS02JcyhA1zUwzKNwycUkzRcOS\n",
1695 1695 "zARcMnX0p5lb7ruJ4hpopn1RLMUF2ZcBZq7fH8cZZu4ZYAZmzn3Omdfz8eDBuT/XWd5HeQi+ue/r\n",
1696 1696 "Lq72uGjRomwlL2J1IdO4QlhJ7fJqzaVW5k6LLRrxR73v7potsU0bVvXqRXmvXpT37Jn5Ufm4Vy8q\n",
1697 1697 "NtkEinIutiQpR1hSSVJTyvwt965kiqmjWdeGw0D5ppuy7PDDWX744azcdVeLKUn5o0ULKrbYgoot\n",
1698 1698 "tmCdG0gtX07RF19QPHduprSqVmgVJ8qtoi+/bKzN3xtby69+NBsV7dqtsYAq79WLiq5d/X1LkrTe\n",
1699 1699 "LKkkqSmE0BY4HjgD2GFdT6/o0oVl3/wmy484ghWDBnnLbEmFr00bKnr2pKJnz3U/t7ycoi+/XF1m\n",
1700 1700 "zZ9P0cKFhAULKFq0iLBwIUULFmR+Xrhw9c8LFlC0bFnTf5c8Flu2pKJTJ2LHjlR07px53KkTFZ06\n",
1701 1701 "UdG5M7FLF8p79mTVV6VU7NLFEkqS1GQsqSSpMYXwNeB04Aes49KSig4dWH7wwSw/4gjKBg/21tmS\n",
1702 1702 "tCbFxVR060ZFt24Nf+3KlVWlVY1ia8GCmoVWZdG1bBlhxYrM68rKMo9XrKjxc+WPXBBbtMicwdap\n",
1703 1703 "ExUdO2YKprrKpsr1r9YqOnUidu5M3GgjSydJUs6wpJKkDZW5pG8w8BPgSNayR0hs04blBx7IsiOO\n",
1704 1704 "oGy//aBNm2yllKTmqWVL4sYbU77xxpQ35vvGuObyqrLcqlZ0hRUriEVF0KJFplgqLs48rvy5jlmN\n",
1705 1705 "9TpmFBVZMEmSCoollSStrxBak9lr6ifAwDU9LRYXUzZsGMu+9S3KDjiA2K5d1iJKkppICNC6NbF1\n",
1706 1706 "5uZ4ObljliRJecaSSpIaKoTNgdOAU4Hua3paRZcuLP3ud1kyahQVPXpkLZ4kSZIk5SNLKkmqrxC+\n",
1707 1707 "TuasqRLWcjenlX37suTkk1l25JHQtm3W4kmSJElSPrOkkqS1CaEl8G3gTGCvNT0thkDZAQew5OST\n",
1708 1708 "WbHPPu4RIkmSJEkNZEklSXUJYRPgFOBHwBqv1avo0IGlxxzD0tGjKd9qq2ylkyRJkqSCY0klSdWF\n",
1709 1709 "MIDMJX3fBVqv6WmrttmGJSeeyLKSEmL79lmLJ0mSJEmFypJKkkIoBg4jU04NXdtTy4YMYcnJJ1O2\n",
1710 1710 "336ZW39LkiRJkhqFJZWk5iuEABwJXAr0X9PTKjbaiGUlJSw98URWbbdd1uJJkiRJUnNiSSWpeQph\n",
1711 1711 "f+ByYI81PWVVz54sHT2apcceS+zcOXvZJEmSJKkZsqSS1LyE8HXgMmD4mp5SttdeLD3pJJYfeCC0\n",
1712 1712 "8D+TkiRJkpQN/t+XpOYhhH5kLuv7dl3LsaiIZUcdxZJTTmHVjjtmN5skSZIkyZJKUoEL4WvAhcAJ\n",
1713 1713 "QJ07nS8/+GAWnX02q/r0yWYySZIkSVI1llSSClMI3YDzgB8Brep6Stk++7Do3HNZueuuWY0mSZIk\n",
1714 1714 "SarNkkpSYQmhAzAG+BnQvq6nrBgwgEXnnsuKffeFELIaT5IkSZJUN0sqSYUhhDbAD4HzgU3qesqq\n",
1715 1715 "bbdl0dlns/zQQy2nJEmSJCnHWFJJym8htAC+D4wHetX1lPLNN2fR2LEsKynxbn2SJEmSlKP8vzVJ\n",
1716 1716 "+SmEABxF5o59/ep6SkWXLiw+80yWjBoFbdpkNZ4kSZIkqWEsqSTlnxCGA5cBX69ruaJdO5aceipL\n",
1717 1717 "Tj2V2KFDdrNJkiRJktaLJZWk/BHC14HLgWF1LcdWrVj6/e+z+Mwzqdikzm2pJEmSJEk5ypJKUu4L\n",
1718 1718 "oRswATi+ruVYVMSykSNZPHYs5T17ZjebJEmSJKlRWFJJyl2ZfaeOB64GNq7rKcsOOYTF48axqk+f\n",
1719 1719 "rEaTJEmSJDUuSypJuSmEbYHrgeF1LZcNHsyic89l5cCB2c0lSZIkSWoSllSScksILYExwHig1i35\n",
1720 1720 "Vvbrx8Lx41mx777ZTiZJkiRJakKWVJJyRwh7AH8CBiSXYuvWLBozhiU//CG0bJn9bJIkSZKkJmVJ\n",
1721 1721 "JSl9IXQALgHOBEJyuWzwYBb8+teUb7NN1qNJkiRJkrLDkkpSukL4JjAJ6JVcqujShYUXXsiykSMh\n",
1722 1722 "1OquJEmSJEkFxJJKUjpC2ByYCIysa3nZUUexcPx4KjbZJLu5JEmSJEmpsKSSlF0hFAEnAVcCnZLL\n",
1723 1723 "q3r1YsEVV7Bi6NBsJ5MkSZIkpciSSlL2hNAPuAH4RnIpFhez5JRTWDx2LLFt2+xnkyRJkiSlypJK\n",
1724 1724 "UtMLoTVwDnAe0Cq5vGLAABZceSWrdtop69EkSZIkSbnBkkpS0wrhG2TOnuqXXKpo25ZFZ5/N0tGj\n",
1725 1725 "oYX/OZIkSZKk5sz/K5TUNELoDFwBnFLX8vL992fhr39Nec+e2c0lSZIkScpJllSSGlcIAfg28Dtg\n",
1726 1726 "s+Ry+SabsPCSS1h++OEQQtbjSZIkSZJykyWVpMYTwmZkLu07rK7lpccdx8Lzzyd26ZLdXJIkSZKk\n",
1727 1727 "nGdJJalxhDAcuA3onlxatc02LLjySlbstVf2c0mSJEmS8oIllaQNE0ILYDyZO/fVuH4vtmzJ4tNP\n",
1728 1728 "Z/GZZ0KbNmmkkyRJkiTlCUsqSesvhB7AX4B9k0srdtuNBVddxaq+fbOfS5IkSZKUdyypJK2fEA4C\n",
1729 1729 "bgU2qT6OIbB4zBgWn3UWFBenk02SJEmSlHcsqSQ1TAgtgUuAs5NL5d27M/+661ixzz7ZzyVJkiRJ\n",
1730 1730 "ymuWVJLqL4RewB3A3smlsn33Zf7vfkdFt27ZzyVJkiRJyntFaQeQlCdCOAx4g0RBVRECc8eM4cu/\n",
1731 1731 "/MWCSpIkSZK03iypJK1dCK0IYQLwN6BrYvXjv4wevXjeaadBkf85kSRJkiStP/+vUtKahbAV8Bww\n",
1732 1732 "po7Vh4FdPtxmm/JsRpIkSZIkFSZLKkl1C+FI4HVgj8RKOZlN079JjJ9nPZckSZIkqSC5cbqkmkJo\n",
1733 1733 "DVwJnFHH6kfAMcT4YnZDSZIkSZIKnSWVpNVC2Ba4E9itjtX7gdHEODe7oSRJkiRJzYGX+0nKCGEk\n",
1734 1734 "8Bq1C6pVZPakOsKCSpIkSZLUVDyTSmruQmgDXA2cVsfqB8DRxPhyVjNJkiRJkpodSyqpOQuhD1AK\n",
1735 1735 "7FzH6r3AicQ4P7uhJEmSJEnNkZf7Sc1VCMcBr1K7oFoBnAl824JKkiRJkpQtnkklNTeZu/f9DvhB\n",
1736 1736 "Hav/B5QQ46vZDSVJkiRJau4sqaTmJISNyVzG9406VkuBU4hxQXZDSZIkSZLk5X5S8xHCtsCL1C6o\n",
1737 1737 "yshsmn6MBZUkSZIkKS2eSSU1ByHsBfwN2CSx8j4wkhjfyH4oSZIkSZJW80wqqdCFMBJ4itoF1XPA\n",
1738 1738 "IAsqSZIkSVIusKSSClUIgRDGkdlrqnVi9S/AAcT4ZfaDSZIkSZJUmyWVVIhCaAH8AbiijtVLgO8R\n",
1739 1739 "Y1l2Q0mSJEmStGbuSSUVmhA6kDl76qDEyioyd++bmv1QkiRJkiStnSWVVEhC6Ak8AOycWFkIHEWM\n",
1740 1740 "T2Q/lCRJkiRJ62ZJJRWKEHYBHgS2SKzMBg4hxpnZDyVJkiRJUv24J5VUCEI4mMzd+pIF1XQyd/Cz\n",
1741 1741 "oJIkSZIk5TRLKinfhXAqcD/QPrHyN2AoMc7JfihJkiRJkhrGkkrKVyEUEcIVwPVAcWL1WjJ7UC3J\n",
1742 1742 "fjBJkiRJkhrOPamkfBTCRsDNwMjESgR+SowTsx9KkiRJkqT1Z0kl5ZsQugH3AXslVpYBxxLjfdkP\n",
1743 1743 "JUmSJEnShrGkkvJJCH2Bh4BtEiufAocR4yvZDyVJkiRJ0oZzTyopX4SwL/APahdUbwN7WlBJkiRJ\n",
1744 1744 "kvKZJZWUD0I4DngM6JJYeRLYhxg/yHomSZIkSZIakSWVlMtCCITwC+A2oFVi9SbgYGKcn/VckiRJ\n",
1745 1745 "kiQ1MvekknJVCC2B64ET61j9JXApMcbshpIkSZIkqWlYUkm5KIR2wL3AAYmVlcCJxPjn7IeSJEmS\n",
1746 1746 "JKnpWFJJuSZTUD0IDEmszAOOJMZnsh9KkiRJkqSmZUkl5ZIQ2pMpqPZNrMwCDiHGf2U/lCRJkiRJ\n",
1747 1747 "Tc+SSsoVIXQAHgIGJ1beAEYQ42fZDyVJkiRJUnZYUkm5IFNQPQzsk1h5DTiAGL/MfihJkiRJkrKn\n",
1748 1748 "KO0AUrMXQkfg79QuqF4FhltQSZIkSZKaA0sqKU0hdAIeAfZOrLxCpqCal/1QkiRJkiRlnyWVlJbV\n",
1749 1749 "BdWeiZWXgQOJcX72Q0mSJEmSlA5LKikNIXQGHgUGJVamYUElSZIkSWqGLKmkbAuhC/AYsEdi5SUy\n",
1750 1750 "d/FbkP1QkiRJkiSly7v7Sdm0uqDaLbHyD+AgYlyY/VCSJEmSJKXPM6mkbAmhK/A4tQuqF8icQWVB\n",
1751 1751 "JUmSJElqtiyppGxYXVDtmlh5HjiYGBdlP5QkSZIkSbnDkkpqaiFsDDwBDEysPIcFlSRJkiRJgCWV\n",
1752 1752 "1LRC2IRMQbVLYuUZ4BBiXJz9UJIkSZIk5R43TpeaSgjdyBRUOyVWnga+SYxLsp5JkiRJkqQc5ZlU\n",
1753 1753 "UlMIoTvwJLULqieBQy2oJEmSJEmqyZJKamyrC6odEytPAIcR49Lsh5IkSZIkKbdZUkmNKYRNgaeA\n",
1754 1754 "HRIrj2FBJUmSJEnSGllSSY0lhM3IFFTbJ1YeBY4gxmXZDyVJkiRJUn6wpJIaQwibkymo+idW/o4F\n",
1755 1755 "lSRJkiRJ62RJJW2o1QVVv8TKw8CRxLg8+6EkSZIkScovllTShghhC+BpoG9i5UEsqCRJkiRJqjdL\n",
1756 1756 "Kml9hbAxmbv49UmsPAB8mxjLsh9KkiRJkqT8ZEklrY8QNgLup/YZVH8DvmNBJUmSJElSw1hSSQ0V\n",
1757 1757 "QjHwF2CvxMp9wEgLKkmSJEmSGs6SSmqIEAIwEfhWYuVp4GhiXJH1TJIkSZIkFQBLKqlhxgGnJ2Yz\n",
1758 1758 "yGyS7hlUkiRJkiStJ0sqqb5C+C7w68T0f8AhxDg/hUSSJEmSJBUMSyqpPkIYBkxNTBcCBxPjRykk\n",
1759 1759 "kqhB0Q8AACAASURBVCRJkiSpoFhSSesSwgDgHqBltekK4FvE+M90QkmSJEmSVFgsqaS1CeFrwMNA\n",
1760 1760 "x8TKKGJ8KoVEkiRJkiQVJEsqaU1C6EKmoNoisfJzYrwjhUSSJEmSJBUsSyqpLiG0Af4KbJ9YuRaY\n",
1761 1761 "kP1AkiRJkiQVNksqKSmEIuBmYN/Eyv8DxhBjzH4oSZIkSZIKmyWVVNtVQEli9jzwPWIsTyGPJEmS\n",
1762 1762 "JEkFz5JKqi6EnwI/TUzfAY4gxuUpJJIkSZIkqVmwpJIqhVACXJ2YfgIcTIxfppBIkiRJkqRmw5JK\n",
1763 1763 "AghhCHBrYroIOIQYP0whkSRJkiRJzYollRTCDmTu5Neq2nQV8G1ifCOdUJKk5uqqq65i6NCh9OjR\n",
1764 1764 "gx49ejBmzJi0I0mSJGWFJZWatxB6AH8HOidWTiTGx1JIJElq5n72s5/x9NNPs+eeewJU/SxJklTo\n",
1765 1765 "LKnUfIXQCXgY6JlYOY8Yk5f+SZKUVe+++y4hBEsqSZLUbFhSqXkKoRVwD7BTYuUPwK+zH0iSpNXe\n",
1766 1766 "e+895s2bx2abbcbXvva1tONIkiRlhSWVmp8QioCpwP6JlfuAM4gxZj+UJEmrvfzyywAMGjQo5SSS\n",
1767 1767 "JEnZY0ml5uhy4LjE7CXgOGIsTyGPJEk1VJZUXuonSZKaE0sqNS8h/BgYl5i+BxxGjEtTSCRJUi0v\n",
1768 1768 "v/yy+1FJkqRmp0XaAaSsCeEo4NrE9DPgIGL8IoVEkiTV8umnnzJ79mw23nhjiouLOfXUU/n4449Z\n",
1769 1769 "sGAB+++/P+eccw5t2rRJO6YkSVKjs6RS8xDCPsBtQKg2XQIcQoz/l04oSZJqmzZtGgCtW7fm7LPP\n",
1770 1770 "5oorrmCbbbbh888/Z7/99mP27NlMmTIl5ZSSJEmNz8v9VPhC6Af8Daj+187lwEhifDWdUJKk5ujO\n",
1771 1771 "O+9k8ODBbLvttgwfPpypU6fWul9H5X5UnTp1YurUqWyzzTYAdOvWjYMOOohHHnmEV1/1ty9JklR4\n",
1772 1772 "LKlU2ELoDNwPdE2s/IAYH04hkSSpmfrd737HmDFjGDBgAG+88QaXXnoppaWljB49moqKiqrnVZZU\n",
1773 1773 "V155Je3bt6/xHl27Zn47e+qpp7IXXJIkKUssqVS4QigCbgF6J1YuJMapKSSSJDVTr776KldccQVt\n",
1774 1774 "27blV7/6FR06dODFF19k1qxZPPbYY9x5550ALF68mHfeeYdOnToxcODAWu8zd+5cAL74wq0UJUlS\n",
1775 1775 "4bGkUiE7HzgsMZsKXJJCFklSM7Vy5UrGjh1LjJEjjzySLl26MGvWLCZMmMCiRYuA1WdGTZ8+nYqK\n",
1776 1776 "Cnbfffc63+tf//oXAB07dsxOeEmSpCyypFJhCuFg4KLE9BXgR7U2/5AkqQndc889vPfee4QQ+M53\n",
1777 1777 "vgNAeXl5jee0aJG5l83rr78OwKBBg2q9z/Lly3n77bcB2H777ZsysiRJUiosqVR4QtgG+As17+T3\n",
1778 1778 "BfBtYlyeTihJUnMUY2TSpEkA9OjRgz322AOA3r1785Of/IQOHTrQv39/xowZA8CsWbMA2HXXXWu9\n",
1779 1779 "10svvcSKFSto3bo1Q4YMydI3kCRJyp4WaQeQGlUIbYF7gM7VphXA0cT4UTqhJEnN1TPPPMP7778P\n",
1780 1780 "wLBhw2qsjRs3jnHjxtWYVe411adPn1rv9fDDmft9HHbYYXTp0qUp4kqSJKXKM6lUOEIIwB+BnRMr\n",
1781 1781 "5xDjkykkkiQ1c3fccUfV42RJVZfNN98cgE6dOtWYL1y4kL/+9a+0a9eOn//8540bUpIkKUdYUqmQ\n",
1782 1782 "nA58LzG7G7gqhSySpGZu0aJFPProowC0atWKvffee52v2WeffQCYPXt2jfnFF1/M4sWLueyyy+jZ\n",
1783 1783 "s2fjh5UkScoBllQqDCEMBq5JTN8BTnSjdElSGh5//HHKysoAGDBgABtttNE6X3PEEUew7bbb8qc/\n",
1784 1784 "/QmAiooKrrzySu666y4uu+yyqo3XJUmSCpF7Uin/hbA5cBc1fz0vAo4kxkXphJIkNXeVZ1EB9TqL\n",
1785 1785 "CqC4uJi//OUvnHvuuQwbNoyioiK23XZbHnroIXbYYYemiipJkpQTLKmU30JoRaag2iyx8n1ifDeF\n",
1786 1786 "RJIkEWPk2WefrTquvKtfffTs2ZNbb721KWJJkiTlNC/3U767CtgnMbuMGP+aRhhJkgBmzJjB/Pnz\n",
1787 1787 "ASgqKmK33XZLOZEkSVLus6RS/grhe8AZiemjwC9TSCNJUpXnnnuu6vHWW29Nx44dU0wjSZKUHyyp\n",
1788 1788 "lJ9C2AW4ITH9EDiOGMtTSCRJUpXnn3++6vHOO++cYhJJkqT8YUml/BNCV+AeoPptkpYDRxHj3HRC\n",
1789 1789 "SZKUsWLFCqZNm1Z1PGDAgBTTSJIk5Q9LKuWXEIqB24CtEys/JMbXUkgkSVINr732GsuXL686tqSS\n",
1790 1790 "JEmqH0sq5ZsLgYMSsz8Q481phJEkKemFF16oelxUVMSOO+6YYhpJkqT8YUml/BHCYcAFielLwFkp\n",
1791 1791 "pJEkqU7/+Mc/qh5vueWWtGvXLsU0kiRJ+cOSSvkhhO2APyemnwHfIcYVKSSSJKmWFStW8Nprq68+\n",
1792 1792 "32mnnVJMI0mSlF8sqZT7QmhPZqP06vfvLgdGEuP/0gklSVJtr7/+OmVlZVXHllSSJEn1Z0ml3BZC\n",
1793 1793 "AG4Ekht6/IwYn00hkSRJa1T9rn5gSSVJktQQllTKdWcBRydmtwMTU8giSdJavfTSS1WPQwjssMMO\n",
1794 1794 "KaaRJEnKL5ZUyl0hDAWuTEz/CfyAGGP2A0mStGbl5eVMnz696njTTTela9euKSaSJEnKL5ZUyk0h\n",
1795 1795 "9ATuBIqrTRcARxHjknRCSZK0ZjNmzGDJktW/RW2//fYpppEkSco/llTKPSG0Bu4GuidWvkeM76eQ\n",
1796 1796 "SJKkdXrllVdqHPfr1y+lJJIkSfnJkkq56LfAoMTsImJ8II0wkiTVx8svv1zjuH///iklkSRJyk+W\n",
1797 1797 "VMotIYwGfpiYPgRcnEIaSZLq7dVXX61x7JlUkiRJDWNJpdwRwm7AHxLT/yNzmV9FCokkSaqX//73\n",
1798 1798 "v8yZM6fquEWLFvTu3TvFRLnj3XffZc899+T997N3xf5ZZ53FRRddlLXPkyRJjcOSSrkhhE2Ae4DW\n",
1799 1799 "1abLgCOJcV46oSRJqp/kpX5bbbUVrVq1SilN7nj55Zc56qijOP3007Na2l188cU8++yzjBs3rslv\n",
1800 1800 "CFxRUcG8efOYNWsWr7/+Ok899RTLli1r0s+UJKlQtUg7gEQIAZgCfC2x8gNifCuFRJIkNUihX+pX\n",
1801 1801 "VlbG5MmTufPOO/noo4/o1q0bhx56KGPHjqVdu3Z1vubf//43xx9/PCeddBLHH398VvN27NiR2267\n",
1802 1802 "jREjRlBWVsbEiROb5HMOOeQQ/vnPf1JRUfOE72nTptGzZ88m+UxJkgqZZ1IpF/wAOCwxm0iMt6UR\n",
1803 1803 "RpKkhkre2a+QNk1ftGgRJSUl/OpXv2LkyJG88sornHHGGdx0001rLJ++/PJLTjjhBPr168fPf/7z\n",
1804 1804 "LCfO2Gyzzbj66qu5++67ufXWW5vkM7797W9z8skn1yglM3/3JkmS1odnUildIfQBrklMXwLS+ROt\n",
1805 1805 "JEkNtHTpUt55550as0I6k+rss89m+vTp7Lfffvz4xz/mwQcf5JxzziHGyLRp05g/fz6dO3eu8Zpx\n",
1806 1806 "48bx2Wefcccdd6Ra2gwbNoxjjz2W8ePHs+eee7Lddts16vufdNJJQObXwG677cbChQsb9f0lSWpu\n",
1807 1807 "PJNK6QmhJfBnoG216WIyG6WvTCeUJEkN89prr9W43CuEUDBnUs2YMYP77rsPgP333x+A0tLSqn2e\n",
1808 1808 "evbsWaugeuSRR3j44Yc58cQT+drXklfyZ9+4ceMIIXD66afXuiyvsbRt29aN8iVJagSWVErTL4Gv\n",
1809 1809 "J2ZnEuN/0ggjSdL6SO5H1bZtW7bccsuU0jSuP//5z0CmeNt9990BOPbYY9lqq63YY489mDx5co3n\n",
1810 1810 "r1ixgvPPP5+OHTvyox/9KOt569K9e3dOOukkZs6cye23395kn+NG+ZIkbThLKqUjhH2A8xLTe4Cb\n",
1811 1811 "sh9GkqT1lyyp+vbtm1KSxvf4448D0Lp1a3bYYQcADjroIF544QXuvfdedtxxxxrPv+uuu/jkk08Y\n",
1812 1812 "OXJkrTOs0jRq1CiKi4u5+uqrWbVqVdpxJEnSGlhSKftC6AjcSs1ff58Apzb5faIlSWpkr7/+eo3j\n",
1813 1813 "7bffPqUkjWv27Nl88sknAOy0004UFxev9fkVFRVMmjSJEALHHHNMNiLW2xZbbMGwYcOYM2cO9957\n",
1814 1814 "b9pxJEnSGlhSKQ0Tga0Ts9HE+EUaYSRJWl+zZ8/myy+/rDErlJLqtddeq3o8cODAdT7/ueee44MP\n",
1815 1815 "PqBfv345+c/gsMMyNxKuvIRRkiTlHksqZVcI3wFOSEyvJcZHUkgjSdIGeeONN2rNKi+Ly3dvvvlm\n",
1816 1816 "1eP6lFSVG6zvu+++TZZpQwwdOpQQAq+++iqzZ89OO44kSaqDJZWyJ4QewB8T05nAOSmkkSRpgyUv\n",
1817 1817 "9SsqKsrJs4jWxz//+U8gs2n6LrvsstbnlpeX8/e//x3I3ZKqa9euDBgwgBgjjz76aNpxJElSHSyp\n",
1818 1818 "lB0hFAFTga7VpiuA7xLjsnRCSZK0YZJnUm299da0bds2pTQb5sADD6RHjx5VP/7xj38AEGNkr732\n",
1819 1819 "qrH2pz/9qcZrZ86cyYIFCwgh1Ousq7qUl5dz9913c/jhh9O/f38GDBjAiSeeWOOMrpUrV3Ldddcx\n",
1820 1820 "ePBgttlmG4YMGcJVV11FWVlZvT5jp512AuDZZ59tULZ3332X8ePHM3z4cPr06cO2227LvvvuyyWX\n",
1821 1821 "XMKcOXMa9F6VsvF9JUnKNy3SDqBm40zggMTsfGJ8s64nS5KU68rLy6vONqpUWYLkowcffJCVK1cC\n",
1822 1822 "8K9//atqD6cRI0bw+9//vsZzk0Xcyy+/DMBmm21Gp06dGvzZ8+fP54c//CELFy7krLPOYpddduF/\n",
1823 1823 "//sfZ5xxBt/61reYNGkSw4cP56STTqKiooIbb7yRbt268eCDD/LLX/6St956i1tuuWWdn1P572fm\n",
1824 1824 "zJn1yrVy5UrGjx/PzTffzGabbcaPf/xjvvGNb9ClSxc+/vhj7r//fkaMGMGFF16Yk99XkqR8Y0ml\n",
1825 1825 "phfCTsCvE9OngKtTSCNJUqN49913Wbas5snAAwYMSCnNhmvZsiUtW7YEYNasWVXznXbaaZ1nh1Ve\n",
1826 1826 "9ti3b98Gf+7KlSsZPXo0vXr14rbbbqu6i2D37t256KKL+P73v8+4ceP41re+xdy5c/nb3/5GcXEx\n",
1827 1827 "L7zwAuPHj2flypU88cQTLFy4kI4dO671s7bbbjsAPv30U+bOncvGG2+8xufOnz+fUaNGMX36dLbe\n",
1828 1828 "emvuv/9+unTpUrXetWtXdtxxR4488khGjhxZVfDl0veVJCnfeLmfmlYIbYDbgNbVpguAUcRYkU4o\n",
1829 1829 "SZI2XF2bpudzSVXd22+/XfW4PntsffDBB0DmTKqGmjhxIuXl5VxzzTVVhU3ys7/88kumTJnCFVdc\n",
1830 1830 "UfWcyZMnV1321q5dO9q3b7/Oz9p0002rHlf/jnU566yzmD59Oi1atGDKlCk1Cqrq+vXrxzXXXMPi\n",
1831 1831 "xYvX+fmQ3e8rSVK+saRSU7sUSF778ENi/CiNMJIkNZa33nqrxnFRURE77rhjSmka1zvvvANkNk2v\n",
1832 1832 "z90KP/zwQyBzNlBDfP755/zxj3/k8ssvr1XYAMydO7fq8W677Vbjn2///v0BaNGiBRdddBFFRev+\n",
1833 1833 "Y+3mm28OZPbZqizW6nLzzTfz2GOPAZnLHfv06bPW9x0+fDhbbLHFOj8/299XkqR84+V+ajohDAPG\n",
1834 1834 "Jqa3EeMdacSRJKkxJUuqrbbaig4dOqSUpnFVllQdOnSgZ8+ea33uqlWrmDdvHsAazzZak3vuuYfd\n",
1835 1835 "dtttjUVY9bOdDjig5taWP//5zzn00EPp1q0b3bp1q9fntW7dmtatW1NWVsaCBQvqfM6qVav47W9/\n",
1836 1836 "W3V85JFH1uu96yPb31eSpHxjSaWmEUIX4ObEdDbw4xTSSJLUqFauXFlV5FTaeeedU0rTuObOnctn\n",
1837 1837 "n30GrD57Z22WLl1a9bh169ZreWZtW221FWPHJv8+a7Xp06dXPd5rr71qrdfnUsSkjTbaiLKyMhYt\n",
1838 1838 "WlTn+gsvvFD1/UMIjfrvNY3vK0lSPrGkUuMLIQDXAz2qTSNwPDHOTyeUJEmN59///jcrVqyoMdtl\n",
1839 1839 "l11SStO4Grof1YaUVCNGjFjr+vPPPw9k7iY4cODABr33mrRp0waAhQsX1rn+6quvVj1u1apVvS7j\n",
1840 1840 "q680vq8kSfnEi9nVFL4LlCRmVxDjs2mEkSSpsf3zn/+sNSuUkqr6GWINPXMnxthoOf773/9W7XW1\n",
1841 1841 "++6717mH0/qozFhRUff9Wz799NOqx506dWqUz6yPpvq+kiTlE0sqNa4QtgKuS0xfBy7MehZJkprI\n",
1842 1842 "zJkzaxy3bNmSnXZK3ickP1U/k6o+m6a3bdu26nHl3ecaQ+VZRQB77713o73v8uXLgZq516Rly5aN\n",
1843 1843 "9rnr0lTfV5KkfGJJpcYTQjFwK9Cx2nQ58F1iXFH3iyRJyj/Jkqpv374NvtQtV1WWVMXFxfTt23ed\n",
1844 1844 "z69e9lQWQI3hhRdeqHpc1/5M66sy40YbbVTneuUdAKs/Nxua6vtKkpRPLKnUmMYBgxOznxHjO3U9\n",
1845 1845 "WZKkfJXcNH3XXXdNKUnjWrVqFe+99x4AW2+9ddX+TWvTokULunbtCrDGO+atj8rSZm37M82fP5+J\n",
1846 1846 "EyfW+z2XL19edbZX9TKquuqfNX/+/DVeFtjYmuL7SpKUbyyp1DhC2A24ODH9OzAphTSSJDWZ//3v\n",
1847 1847 "f7U23S6UTa7fe++9qg3hG7If1ZZbbgnAJ5980qDPW7p0Ka+//jpLliyplaNyb6iBAweucX+mBx98\n",
1848 1848 "kEcffbTen1eZL4RAr1696nzO3nvvzSabbAJk9q1KFpIbItvfV5KkfGNJpQ0XQlvgNmreLfILYHSj\n",
1849 1849 "7qAqSVIOePfdd2schxAKpqSaMWNG1eOGlFRbb701AB9//HG9X/Pf//6XoUOH8s1vfpMDDjiAVatW\n",
1850 1850 "Va09/vjjVY933HHHOl9fXl7O5MmTOeaYY+r9mdVLtMrMSS1btuS0004DMpusP/zww+t835UrV9a4\n",
1851 1851 "y2Fd0vi+kiTlG0sqNYYrgeSmFScT45w0wkiS1JT+9a9/1Tju0KED2223XUppGlf1kqo+m6ZXqryz\n",
1852 1852 "4X/+8596v+baa6/lf//7HwCzZ8+u2v9p1apV3H777VXP69KlS52vv/766ykvL29QafP+++8D0Llz\n",
1853 1853 "56qzv+pyyimnsPvuuwNw00038cUXX6z1fa+//nrmzZtXdbx48eJaz0nj+0qSlG8sqbRhQjgE+FFi\n",
1854 1854 "+idivC+NOJIkNbVkSVVZ0BSCypIqhNCgkmqPPfYA4NNPP11noVPps88+q3p8/PHH0759ewAmTZpE\n",
1855 1855 "RUUFRx11VI1M1T300ENcd911TJo0qUF34HvrrbcAqgqoNSkqKmLSpElst912zJs3j1NOOYVFixbV\n",
1856 1856 "+dzbbruNyZMn06FDByBz9tWdd95Z62TyNL6vJEn5xpJK6y+E7sDUxPR9YEwKaSRJyopkSVUom6bD\n",
1857 1857 "6rsW9ujRg0033bTer9thhx3o3LkzMUbefPPNer2mspQ54IADOP300/n000+ZOHEiU6ZM4cYbb2T8\n",
1858 1858 "+PH07t2bhx56iJtvvpnPP/+cmTNncv7553P22WczderUBhVpsLqk2meffdb53B49enD//fczbNgw\n",
1859 1859 "pk2bxkEHHcQdd9zBrFmzmD17No8++ijHHnssU6ZM4e6776Zjx9U3N77hhhvo378/gwcPrtprKo3v\n",
1860 1860 "K0lSvmmx7qdIdQghADcC3atNy4HvEWPtc9wlSSoA5eXlVZeMVVrXWTn54oMPPqg6W6jyzKj6Kioq\n",
1861 1861 "4uCDD+b222/n6aefZtiwYet8zeGHH07btm254YYb2H///WnZsiVDhw7lgQceoGfPngDcd999TJo0\n",
1862 1862 "iRtuuIGLLrqIbt26MWLECJ566qmqzc3r64svvmDmzJkUFRVx6KGH1us1HTp04JZbbuGZZ57hzjvv\n",
1863 1863 "ZMKECXz++ee0b9+eHXbYgSOPPJKSkhKKiopo3bo1m222GV26dKFr165VP1feITHb31eSpHxkSaX1\n",
1864 1864 "9QPgsMTsYmKclkYYSZKy4YMPPqCsrKzquKioqGBKquqXmQ0dOrTBrz/iiCO4/fbbeeKJJ7jkkkvq\n",
1865 1865 "9Zrhw4czfPjwNa537tyZ8847j/POO6/BeZKeeOIJIHP3vC222KJBrx0yZAhDhgxZ63Oee+65db5P\n",
1866 1866 "Nr+vJEn5yMv91HAh9AGuSUxfAi5LIY0kSVmTvLNf3759q/YiyneVl8K1aNGiXmdCJQ0ePJitt96a\n",
1867 1867 "Dz/8sOq9csmDDz4IZPaDkiRJucmSSg0TQkvgz0DbatPFZC7zW1X3iyRJKgzJkmrQoEEpJVl/Cxcu\n",
1868 1868 "ZNSoUfTt25ff/OY3VfM33ngDyOzX1Llz5wa/bwiB0047DYBbbrmlccI2ko8++ognn3ySLbbYompv\n",
1869 1869 "KEmSlHssqdRQFwBfT8zOJMb633NakqQ8VQgl1YQJE3j88cdZvHgxN954I5DZa6vy7KfRo0ev93uX\n",
1870 1870 "lJTQo0cP/vrXv/Lll182St7GMHXqVGKMnHbaaRQXF6cdR5IkrYElleovhEHA+YnpPcBN2Q8jSVL2\n",
1871 1871 "vfPOO1WPQwjsueeeKaZZP88//3zV4wEDBgDw4osvsmjRInr37s0BBxyw3u/dsmVLLr30UpYtW8Y1\n",
1872 1872 "1yR3BkjHxx9/zE033cQOO+zACSeckHYcSZK0FpZUqp/MZX43UvPXzCfAqcQY0wklSVL2lJWVMWvW\n",
1873 1873 "rKrjLbfcku7du6/lFbmpbdvMFfv9+/evutzvlltuoaioqMblf+vrwAMP5OCDD+bWW2/lP/9J/0Tr\n",
1874 1874 "K664glWrVnHllVdSVOQffSVJymX+Tq36+hmwY2I2mhi/SCOMJEnZ9t5771FeXl51vMcee6SYZv2N\n",
1875 1875 "Hj2aEALf/OY3adWqFZMnT+ahhx7i9NNPb7TLF6+66ip69OjBmWeeyapV6W1Z+eijj3L33Xdz7rnn\n",
1876 1876 "svPOO6eWQ5Ik1Y8lldYthO2ACxPTm4nxkTTiSJKUhhkzZtQ4zsdL/QCOOuooJk+ezGOPPcbQoUOZ\n",
1877 1877 "OnUql19+Oeecc06jfUbnzp256aabeP/99/n1r3/daO/bEJ988gljx47lO9/5TtWG7pIkKbe1SDuA\n",
1878 1878 "clwIAbgeaF1t+gWZM6skSWo2Zs6cWfU4X/ejqjRixAhGjBjRpJ+x3XbbcdtttzFq1Ch69OixQRuy\n",
1879 1879 "N9T8+fP57ne/y+DBg5kwYULWPleSJG0Yz6TSunwf2D8x+6mX+UmSmpu333676nH37t3ZcsstU0yT\n",
1880 1880 "H3bffXfuvfderr/+et5///2sfe4FF1zAPvvswx/+8AdatPDvZCVJyhf+rq01C6E7cHVi+hhwWwpp\n",
1881 1881 "JElKVfWSKl/3o0pDnz59mDZtWlY/83e/+11WP0+SJDUOz6TS2lwNdK12vAz4oXfzkyQ1Nx999BEL\n",
1882 1882 "Fy6sOm6sDcYlSZK0miWV6hbCCOC7iel4Yvy/NOJIkpSm6pumhxDYe++9U0wjSZJUmCypVFsI7chs\n",
1883 1883 "ll7dm8A1KaSRJCl1b731VtXjTTfdlL59+6aYRpIkqTBZUqkuFwJbVTuOwA+IcWU6cSRJStebb75Z\n",
1884 1884 "9fgb3/hGikkkSZIKlyWVagphIDAmMb2WGF9JI44kSbmg+plUllSSJElNw5JKq4VQDPwJKK42/Qi4\n",
1885 1885 "IJ1AkiSlb/bs2cybNw/I7Ec1ePDglBNJkiQVJksqVXcGsFtidjoxLkojjCRJuWD69OlVj3v37s2m\n",
1886 1886 "m26aYhpJkqTCZUmljBC2BC5NTO8ixvvTiCNJUq546aWXqh7vt99+KSaRJEkqbJZUyly7AJOAdtWm\n",
1887 1887 "C4Az0wkkSVLuePHFF6sejxgxIsUkkiRJhc2SSgAlwCGJ2c+JcU4aYSRJyhUffPABs2bNAqBz587s\n",
1888 1888 "scceKSeSJEkqXJZUzV0IXYBrE9PngMkppJEkKac88cQTVY8POuggior8o5MkSVJT8U9a+g3Qvdrx\n",
1889 1889 "CuBUYqxIKY8kSTnjkUceATJXxo8aNSrlNJIkSYXNkqo5C2EIcHJiehkxvpNGHEmScsnHH39ctR/V\n",
1890 1890 "wIEDGTBgQMqJJEmSCpslVXMVQhvgj4npv4Bfp5BGkqSsmzVrFiNGjKBPnz5cd911tdbvvfdeYoyE\n",
1891 1891 "EPjRj36UQkJJkqTmxZKq+ToX6JuYnUKMZWmEkSQp2yZMmMCMGTNYsmQJl112WdUG6QBlZWVMmTIF\n",
1892 1892 "gP3224+DDz44rZiSJEnNhiVVcxTC9mRKqupuIMbn0ogjSVIaFi9eXPU4hEBFxertGP/85z8zZ84c\n",
1893 1893 "2rZty+WXX55GPEmSpGbHkqq5CaEIuAFoWW06Bzg7nUCSJKVj2LBhALRv354zzzyTbbfdFoA5c+Zw\n",
1894 1894 "9dVXE0LgoosuomfPnmnGlCRJajYsqZqfHwD7JGZnEuP8NMJIkpSW4447jmHDhtG7d2+GDBnC4sWL\n",
1895 1895 "ee211zj66KNZvHgxv/jFLzjuuOM26DP+/ve/M3LkSA488EAOOOAAbrzxRioqKnjwwQeZO3duI30T\n",
1896 1896 "SZKkwtAi7QDKohC2AH6TmD4A3J1CGkmSUlVcXMxNN93ElClTOOecc/jggw/o3LkzgwYNYuLEieyy\n",
1897 1897 "yy7r/d4xRs4991xKS0u57rrrOPjggykvL+fUU0/lqaee4umnn+acc87hjDPOaMRvJEmSlN8sqZqX\n",
1898 1898 "a4GO1Y6XAKcTY0wpjyRJqSoqKuLkk0/m5JNPbtT3veCCC7j11luZMGFC1abrxcXFjB8/nkGDBhFC\n",
1899 1899 "YPvtt2/Uz5QkScp3Xu7XXIRwBPDtxPR8YpydRhxJkgrVk08+ydSpUxk4cCDHHHNMjbVNN92UVq1a\n",
1900 1900 "UVRUxB577JFSQkmSpNxkSdUchNARuC4xnQ78PoU0kiQVrPLycn7xi18AcPzxx9daf/PNN1mxYgX9\n",
1901 1901 "+/enQ4cO2Y4nSZKU0yypmodLgR7VjsuBHxBjeUp5JEkqSM899xwffvghxcXFHHjggbXWp02bBsBe\n",
1902 1902 "e+2V7WiSJEk5z5Kq0IUwCPhxYjqBGN9II44kSYXsgQceAGDAgAF06dKl1nplSTVo0KCs5pIkfeao\n",
1903 1903 "7gAADLpJREFUScoHllSFLISWwJ+AUG36f8BF6QSSJKmwvffeewDsuuuutdYqKip45ZVXKCoqYs89\n",
1904 1904 "98x2NEmSpJxnSVXYxgI7JWY/JMalaYSRJKnQzZ07F4D+/fvXWnv77bdZuHAh2223XdVZVpdffrk3\n",
1905 1905 "2ZUkSfqKJVWhCqE3cGFieisxPpZGHEmSmoNNNtmkxs/VPfPMM8DqS/3Kysp45ZVXCCHUeq4kSVJz\n",
1906 1906 "ZElViDJ/2r0eaFNtOpfMmVWSJKmJDBs2DIAvvviixnzGjBn89re/BaBfv34APPvsswwZMiS7ASVJ\n",
1907 1907 "knKYJVVh+j4wLDEbQ4yfpxFGkqTmYvTo0fTq1Ys777yT8vLMTXSffPJJzjvvPK666ioAli9fToyR\n",
1908 1908 "W2+9laOPPjrNuJIkSTmlRdoB1MhC2Bi4OjF9Arg1hTSSJDUr7du356677uKCCy5g6NChdO7cmV13\n",
1909 1909 "3ZXbb7+ddu3aMW/ePCZPnsx9993Hsccey2abbZZ2ZEmSpJxhSVV4xgNdqx0vJ7NZuruySpKUBb16\n",
1910 1910 "9eKmm26qc+2EE07ghBNOyGoeSZKkfOHlfoUkhB2A0xLTS4jx/TTiSJIkSZIk1ZclVaHIbJZ+NVBc\n",
1911 1911 "bTqL2pf+SZIkSZIk5RxLqsJxCHBgYvYzYlyeRhhJkiRJkqSGsKQqBCG0ovYZU88A96aQRpIkSZIk\n",
1912 1912 "qcEsqQrD6UCfascROMvN0iVJkiRJUr6wpMp3IWwCXJiY3kiMb6QRR5IkSZIkaX1YUuW/i4FO1Y4X\n",
1913 1913 "AReklEWSJEmSJGm9WFLlsxB2Ak5NTC8hxk/TiCNJkiRJkrS+LKnyVQgBuIaa/w7/A1ybTiBJkiRJ\n",
1914 1914 "kqT1Z0mVvw4DhiVmPyPGsjTCSJIkSZIkbQhLqnwUQmtgQmL6JHBfCmkkSZIkSZI2mCVVfvox0Lva\n",
1915 1915 "cQXwU2KMKeWRJEmSJEnaIJZU+SaE7sAvE9M/EeNbacSRJEmSJElqDJZU+ecSoGO14wXABSllkSRJ\n",
1916 1916 "kiRJahSWVPkkhJ2BkxPTi4nx8zTiSJIkSZIkNRZLqnwRQgCuoea/s/eA36cTSJIkSZIkqfFYUuWP\n",
1917 1917 "I4D9ErOxxLgijTCSJEmSJEmNyZIqH4TQGrgqMX0MeCCFNJIkSZIkSY3Okio//ATYttpxBTCGGGNK\n",
1918 1918 "eSRJkiRJkhqVJVWuC2FT4BeJ6fXEOCONOJIkSZIkSU3Bkir3XQp0qHY8H7gwpSySJEmSJElNwpIq\n",
1919 1919 "l4UwEDgpMb2IGL9II44kSZIkSVJTsaTKVSEE4BogVJu+C1yXTiBJkiRJkqSmY0mVu44ChiRmY4hx\n",
1920 1920 "ZRphJEmSJEmSmpIlVS4KoQ1wVWL6CPBwCmkkSZIkSZKanCVVbjoL2KracTmZs6hiOnEkSZIkSZKa\n",
1921 1921 "liVVrglhc+D8xHQSMb6dRhxJkiRJkqRssKTKPb8C2lc7ngdclFIWSZIkSZKkrLCkyiUh7AackJhe\n",
1922 1922 "SIxzU0gjSZIkSZKUNZZUuSKEAPwWCNWm7wDXpxNIkiRJkiQpeyypcsdIYHBi9lNiXJlGGEmSJEmS\n",
1923 1923 "pGyypMoFIWwE/CYxfYgYH0kjjiRJkiRJUrZZUuWGMcCW1Y5XfTWTJEmSJElqFiyp0hbCFsC5ienv\n",
1924 1924 "ifHdNOJIkiRJkiSlwZIqfZcB7aodzwUuTimLJEmSJElSKiyp0hTC14FRiekviXFeGnEkSZIkSZLS\n",
1925 1925 "YkmVlhAC8NvEdCZwQwppJEmSJEmSUmVJlZ6jgb0Ts58S46o0wkiSJEmSJKXJkioNIbQGrkhM7yfG\n",
1926 1926 "x9KII0mSJEmSlDZLqnScCnyt2vFKYGxKWSRJkiRJklJnSZVtIbQDzk9M/0CM76URR5IkSZIkKRdY\n",
1927 1927 "UmXfGUD3asdLgctSyiJJkiRJkpQTLKmyKYTOwNmJ6URi/DSNOJIkSZIkSbnCkiq7xgKdqx0vAK5M\n",
1928 1928 "KYskSZIkSVLOsKTKlhC6Az9NTK8kxnlpxJEkSZIkScolllTZcw7Qrtrx58DElLJIkiRJkiTlFEuq\n",
1929 1929 "bAihJ/CjxPQyYlycRhxJkiRJkqRcY0mVHRcArasd/xe4PqUskiRJkiRJOceSqqmF0Bs4MTG9mBiX\n",
1930 1930 "pxFHkiRJkiQpF1lSNb3xQItqx/8BbkoliSRJkiRJUo6ypGpKIewIHJeYXkiMK9OII0mSJElSGubM\n",
1931 1931 "mXNs2hmU+yypmtbFQKh2PAO4I6UskiRJkiSloqyszJJK62RJ1VRC+DpwZGJ6ATGWpxFHkiRJkiQp\n",
1932 1932 "l1lSNZ1LE8evAPelEUSSJEmSJCnXWVI1hRCGAAcmpucTY0wjjiRJkiRJUq6zpGpsIQTgV4npM8Dj\n",
1933 1933 "KaSRJEmSJEnKC5ZUje8gYJ/EzLOoJEmSJEmS1sKSqjGFUETts6geIsYX0ogjSZIkSZKULyypGtdR\n",
1934 1934 "wMDE7BdpBJEkSZIkSconllSNJYRi4JLE9C5ifD2NOJIkSZIkSfnEkqrxfA/oV+24AvhlSlkkSZIk\n",
1935 1935 "SZLySiiE/byfeOKJ/P8SkiRJkiRJOWjYsGEhG5/jmVSSJEmSJElKXUGcSSVJkiRJkqT85plUkiRJ\n",
1936 1936 "kiRJSp0llSRJkiRJklJnSSVJkiRJkqTUWVJJkiRJkiQpdZZUkiRJkiRJSp0llSRJkiRJklJnSSVJ\n",
1937 1937 "kiRJkqTUWVJJkiRJkiQpdZZUkiRJkiRJSp0llSRJkiRJklJnSSVJkiRJkqTUWVJJkiRJkiQpdS3S\n",
1938 1938 "DiBJkiRJkgpPSUnJvsAVwCDg1tLS0lEpR1KO80wqSZIkSZLU6EpLS58FhgHlwHMpx1EesKSSJEmS\n",
1939 1939 "JElNZW+gGEsq1YMllSRJkiRJairfAD4vLS19N+0gyn2WVJIkSZIkqansCzyfdgjlhxBjTDuDpDxV\n",
1940 1940 "UlKyP3AK8CHQDXgS+ElpaenXUw0mSZIkKXUlJSUtgfnAFKDsq/EA4KzS0tK3UwumnOWZVJLWS0lJ\n",
1941 1941 "yUnAX4AxpaWlZwMXATcCX6QaTJIkSVKu+DqwEfA14OzS0tKfAQ8Dd6eaSjnLkkpSg5WUlOwM/IHM\n",
1942 1942 "WVMfA5SWln4ILMINESVJkiRlfAP4Eji6tLS0/KvZh0C/kpKS/unFUq6ypJK0Pn4FLKTa34B89ZvM\n",
1943 1943 "xlhSSZIkScrYF3iutLR0ebVZr69+bpdCHuU4SypJDVJSUtIZOAh4rNrfhgAMBVYA09LIJUmSJCnn\n",
1944 1944 "DAKeTcz2BFYB72U/jnKdJZWkhupN5r8d/0jMhwIvl5aWrigpKdk666kkSZIk5YySkpJNgK7AK9Vm\n",
1945 1945 "xcBwMn/hvSCtbMpdllSSGmrhVz/PrhyUlJRsRKakevGr0U+ynEmSJElSblkKRGBOtdl3gC7Ahakk\n",
1946 1946 "Us6zpJLUIKWlpf8G3gK2hqrbyv4eaA18+NXfmHiHP0mSJKkZKy0tXQo8DmwPUFJS0gO4FhhbWlo6\n",
1947 1947 "Pc1syl0t0g4gKS+NBK4pKSnpBRQDl5G51vwEYBfg3PSiSZIkScoRJwNXlZSUDCWzbchJpaWlD6Qb\n",
1948 1948 "SbksxBjTziBJkiRJkqRm7v+3dwerOkVxGIffJROZKDMmJykTM3egTNyDpJSJGTKQThmSzEydW3AB\n",
1949 1949 "MlA6E8oNSDKUDE/CMjifOimfnH3qlZ5ntvZuf/89/rXX+mz3AwAAAKBOpAIAAACgTqQCAAAAoE6k\n",
1950 1950 "AgAAAKBOpAIAAACgTqQCAAAAoE6kAgAAAKBOpAIAAACgTqQCAAAAoE6kAgAAAKBOpAIAAACgTqQC\n",
1951 1951 "AAAAoE6kAgAAAKBOpAIAAACgTqQCAAAAoE6kAgAAAKBOpAIAAACgTqQCAAAAoE6kAgAAAKBOpAIA\n",
1952 1952 "AACgTqQCAAAAoE6kAgAAAKBOpAIAAACgTqQCAAAAoE6kAgAAAKBOpAIAAACgTqQCAAAAoE6kAgAA\n",
1953 1953 "AKBOpAIAAACg7nD7BQAAAAD4940xziW5lORbko0kV5NcS3Isyckkm3POt/v9fZEKAAAAgLXGGKeS\n",
1954 1954 "XJlzXl+tt5JsJ7mc3Z16L5K8TvJovzNs9wMAAADgT24kub1nfTTJpznndpL3SR4m2VoyYMw5lzwP\n",
1955 1955 "AAAAwH9ujLEx53y3Z/0hyZM5592DmuFLKgAAAADW+iVQnUlyIsnzg5whUgEAAADwN84n+ZLk5c8L\n",
1956 1956 "qzOrFhGpAAAAAPitMcaRMcb9McbZ1aULSd7MOXdW9w8lubV0jn/3AwAAAGCdi0luJnk1xvia5HSS\n",
1957 1957 "z3vu38nCQ9MTB6cDAAAAsMYY43iSB0k+Jvme5F6Sx0l2srvt7+mc89niOSIVAAAAAG3OpAIAAACg\n",
1958 1958 "TqQCAAAAoE6kAgAAAKBOpAIAAACgTqQCAAAAoE6kAgAAAKBOpAIAAACgTqQCAAAAoE6kAgAAAKBO\n",
1959 1959 "pAIAAACgTqQCAAAAoE6kAgAAAKBOpAIAAACgTqQCAAAAoE6kAgAAAKBOpAIAAACgTqQCAAAAoE6k\n",
1960 1960 "AgAAAKBOpAIAAACg7gefISOV+L+GHQAAAABJRU5ErkJggg==\n"
1961 1961 ],
1962 1962 "text/plain": [
1963 1963 "<matplotlib.figure.Figure at 0x106d1b198>"
1964 1964 ]
1965 1965 },
1966 1966 "metadata": {
1967 1967 "image/png": {
1968 1968 "height": 403,
1969 1969 "width": 596
1970 1970 }
1971 1971 },
1972 1972 "output_type": "display_data"
1973 1973 }
1974 1974 ],
1975 1975 "source": [
1976 1976 "# %load http://matplotlib.org/mpl_examples/showcase/integral_demo.py\n",
1977 1977 "\"\"\"\n",
1978 1978 "Plot demonstrating the integral as the area under a curve.\n",
1979 1979 "\n",
1980 1980 "Although this is a simple example, it demonstrates some important tweaks:\n",
1981 1981 "\n",
1982 1982 " * A simple line plot with custom color and line width.\n",
1983 1983 " * A shaded region created using a Polygon patch.\n",
1984 1984 " * A text label with mathtext rendering.\n",
1985 1985 " * figtext calls to label the x- and y-axes.\n",
1986 1986 " * Use of axis spines to hide the top and right spines.\n",
1987 1987 " * Custom tick placement and labels.\n",
1988 1988 "\"\"\"\n",
1989 1989 "import numpy as np\n",
1990 1990 "import matplotlib.pyplot as plt\n",
1991 1991 "from matplotlib.patches import Polygon\n",
1992 1992 "\n",
1993 1993 "\n",
1994 1994 "def func(x):\n",
1995 1995 " return (x - 3) * (x - 5) * (x - 7) + 85\n",
1996 1996 "\n",
1997 1997 "\n",
1998 1998 "a, b = 2, 9 # integral limits\n",
1999 1999 "x = np.linspace(0, 10)\n",
2000 2000 "y = func(x)\n",
2001 2001 "\n",
2002 2002 "fig, ax = plt.subplots()\n",
2003 2003 "plt.plot(x, y, 'r', linewidth=2)\n",
2004 2004 "plt.ylim(ymin=0)\n",
2005 2005 "\n",
2006 2006 "# Make the shaded region\n",
2007 2007 "ix = np.linspace(a, b)\n",
2008 2008 "iy = func(ix)\n",
2009 2009 "verts = [(a, 0)] + list(zip(ix, iy)) + [(b, 0)]\n",
2010 2010 "poly = Polygon(verts, facecolor='0.9', edgecolor='0.5')\n",
2011 2011 "ax.add_patch(poly)\n",
2012 2012 "\n",
2013 2013 "plt.text(0.5 * (a + b), 30, r\"$\\int_a^b f(x)\\mathrm{d}x$\",\n",
2014 2014 " horizontalalignment='center', fontsize=20)\n",
2015 2015 "\n",
2016 2016 "plt.figtext(0.9, 0.05, '$x$')\n",
2017 2017 "plt.figtext(0.1, 0.9, '$y$')\n",
2018 2018 "\n",
2019 2019 "ax.spines['right'].set_visible(False)\n",
2020 2020 "ax.spines['top'].set_visible(False)\n",
2021 2021 "ax.xaxis.set_ticks_position('bottom')\n",
2022 2022 "\n",
2023 2023 "ax.set_xticks((a, b))\n",
2024 2024 "ax.set_xticklabels(('$a$', '$b$'))\n",
2025 2025 "ax.set_yticks([])\n",
2026 2026 "\n",
2027 2027 "plt.show()\n"
2028 2028 ]
2029 2029 },
2030 2030 {
2031 2031 "cell_type": "markdown",
2032 2032 "metadata": {},
2033 2033 "source": [
2034 2034 "Matplotlib 1.4 introduces an interactive backend for use in the notebook,\n",
2035 2035 "called 'nbagg'. You can enable this with `%matplotlib notebook`.\n",
2036 2036 "\n",
2037 2037 "With this backend, you will get interactive panning and zooming of matplotlib figures in your browser."
2038 2038 ]
2039 2039 },
2040 2040 {
2041 2041 "cell_type": "code",
2042 2042 "execution_count": 5,
2043 2043 "metadata": {
2044 2044 "collapsed": true
2045 2045 },
2046 2046 "outputs": [],
2047 2047 "source": [
2048 2048 "%matplotlib notebook"
2049 2049 ]
2050 2050 },
2051 2051 {
2052 2052 "cell_type": "code",
2053 2053 "execution_count": 6,
2054 2054 "metadata": {
2055 2055 "collapsed": false
2056 2056 },
2057 2057 "outputs": [
2058 2058 {
2059 2059 "data": {
2060 2060 "application/javascript": [
2061 2061 "/* Put everything inside the global mpl namespace */\n",
2062 2062 "window.mpl = {};\n",
2063 2063 "\n",
2064 2064 "mpl.get_websocket_type = function() {\n",
2065 2065 " if (typeof(WebSocket) !== 'undefined') {\n",
2066 2066 " return WebSocket;\n",
2067 2067 " } else if (typeof(MozWebSocket) !== 'undefined') {\n",
2068 2068 " return MozWebSocket;\n",
2069 2069 " } else {\n",
2070 2070 " alert('Your browser does not have WebSocket support.' +\n",
2071 2071 " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n",
2072 2072 " 'Firefox 4 and 5 are also supported but you ' +\n",
2073 2073 " 'have to enable WebSockets in about:config.');\n",
2074 2074 " };\n",
2075 2075 "}\n",
2076 2076 "\n",
2077 2077 "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n",
2078 2078 " this.id = figure_id;\n",
2079 2079 "\n",
2080 2080 " this.ws = websocket;\n",
2081 2081 "\n",
2082 2082 " this.supports_binary = (this.ws.binaryType != undefined);\n",
2083 2083 "\n",
2084 2084 " if (!this.supports_binary) {\n",
2085 2085 " var warnings = document.getElementById(\"mpl-warnings\");\n",
2086 2086 " if (warnings) {\n",
2087 2087 " warnings.style.display = 'block';\n",
2088 2088 " warnings.textContent = (\n",
2089 2089 " \"This browser does not support binary websocket messages. \" +\n",
2090 2090 " \"Performance may be slow.\");\n",
2091 2091 " }\n",
2092 2092 " }\n",
2093 2093 "\n",
2094 2094 " this.imageObj = new Image();\n",
2095 2095 "\n",
2096 2096 " this.context = undefined;\n",
2097 2097 " this.message = undefined;\n",
2098 2098 " this.canvas = undefined;\n",
2099 2099 " this.rubberband_canvas = undefined;\n",
2100 2100 " this.rubberband_context = undefined;\n",
2101 2101 " this.format_dropdown = undefined;\n",
2102 2102 "\n",
2103 2103 " this.image_mode = 'full';\n",
2104 2104 "\n",
2105 2105 " this.root = $('<div/>');\n",
2106 2106 " this._root_extra_style(this.root)\n",
2107 2107 " this.root.attr('style', 'display: inline-block');\n",
2108 2108 "\n",
2109 2109 " $(parent_element).append(this.root);\n",
2110 2110 "\n",
2111 2111 " this._init_header(this);\n",
2112 2112 " this._init_canvas(this);\n",
2113 2113 " this._init_toolbar(this);\n",
2114 2114 "\n",
2115 2115 " var fig = this;\n",
2116 2116 "\n",
2117 2117 " this.waiting = false;\n",
2118 2118 "\n",
2119 2119 " this.ws.onopen = function () {\n",
2120 2120 " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n",
2121 2121 " fig.send_message(\"send_image_mode\", {});\n",
2122 2122 " fig.send_message(\"refresh\", {});\n",
2123 2123 " }\n",
2124 2124 "\n",
2125 2125 " this.imageObj.onload = function() {\n",
2126 2126 " if (fig.image_mode == 'full') {\n",
2127 2127 " // Full images could contain transparency (where diff images\n",
2128 2128 " // almost always do), so we need to clear the canvas so that\n",
2129 2129 " // there is no ghosting.\n",
2130 2130 " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n",
2131 2131 " }\n",
2132 2132 " fig.context.drawImage(fig.imageObj, 0, 0);\n",
2133 2133 " fig.waiting = false;\n",
2134 2134 " };\n",
2135 2135 "\n",
2136 2136 " this.imageObj.onunload = function() {\n",
2137 2137 " this.ws.close();\n",
2138 2138 " }\n",
2139 2139 "\n",
2140 2140 " this.ws.onmessage = this._make_on_message_function(this);\n",
2141 2141 "\n",
2142 2142 " this.ondownload = ondownload;\n",
2143 2143 "}\n",
2144 2144 "\n",
2145 2145 "mpl.figure.prototype._init_header = function() {\n",
2146 2146 " var titlebar = $(\n",
2147 2147 " '<div class=\"ui-dialog-titlebar ui-widget-header ui-corner-all ' +\n",
2148 2148 " 'ui-helper-clearfix\"/>');\n",
2149 2149 " var titletext = $(\n",
2150 2150 " '<div class=\"ui-dialog-title\" style=\"width: 100%; ' +\n",
2151 2151 " 'text-align: center; padding: 3px;\"/>');\n",
2152 2152 " titlebar.append(titletext)\n",
2153 2153 " this.root.append(titlebar);\n",
2154 2154 " this.header = titletext[0];\n",
2155 2155 "}\n",
2156 2156 "\n",
2157 2157 "\n",
2158 2158 "\n",
2159 2159 "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n",
2160 2160 "\n",
2161 2161 "}\n",
2162 2162 "\n",
2163 2163 "\n",
2164 2164 "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n",
2165 2165 "\n",
2166 2166 "}\n",
2167 2167 "\n",
2168 2168 "mpl.figure.prototype._init_canvas = function() {\n",
2169 2169 " var fig = this;\n",
2170 2170 "\n",
2171 2171 " var canvas_div = $('<div/>');\n",
2172 2172 "\n",
2173 2173 " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n",
2174 2174 "\n",
2175 2175 " function canvas_keyboard_event(event) {\n",
2176 2176 " return fig.key_event(event, event['data']);\n",
2177 2177 " }\n",
2178 2178 "\n",
2179 2179 " canvas_div.keydown('key_press', canvas_keyboard_event);\n",
2180 2180 " canvas_div.keyup('key_release', canvas_keyboard_event);\n",
2181 2181 " this.canvas_div = canvas_div\n",
2182 2182 " this._canvas_extra_style(canvas_div)\n",
2183 2183 " this.root.append(canvas_div);\n",
2184 2184 "\n",
2185 2185 " var canvas = $('<canvas/>');\n",
2186 2186 " canvas.addClass('mpl-canvas');\n",
2187 2187 " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n",
2188 2188 "\n",
2189 2189 " this.canvas = canvas[0];\n",
2190 2190 " this.context = canvas[0].getContext(\"2d\");\n",
2191 2191 "\n",
2192 2192 " var rubberband = $('<canvas/>');\n",
2193 2193 " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n",
2194 2194 "\n",
2195 2195 " var pass_mouse_events = true;\n",
2196 2196 "\n",
2197 2197 " canvas_div.resizable({\n",
2198 2198 " start: function(event, ui) {\n",
2199 2199 " pass_mouse_events = false;\n",
2200 2200 " },\n",
2201 2201 " resize: function(event, ui) {\n",
2202 2202 " fig.request_resize(ui.size.width, ui.size.height);\n",
2203 2203 " },\n",
2204 2204 " stop: function(event, ui) {\n",
2205 2205 " pass_mouse_events = true;\n",
2206 2206 " fig.request_resize(ui.size.width, ui.size.height);\n",
2207 2207 " },\n",
2208 2208 " });\n",
2209 2209 "\n",
2210 2210 " function mouse_event_fn(event) {\n",
2211 2211 " if (pass_mouse_events)\n",
2212 2212 " return fig.mouse_event(event, event['data']);\n",
2213 2213 " }\n",
2214 2214 "\n",
2215 2215 " rubberband.mousedown('button_press', mouse_event_fn);\n",
2216 2216 " rubberband.mouseup('button_release', mouse_event_fn);\n",
2217 2217 " // Throttle sequential mouse events to 1 every 20ms.\n",
2218 2218 " rubberband.mousemove('motion_notify', mouse_event_fn);\n",
2219 2219 "\n",
2220 2220 " rubberband.mouseenter('figure_enter', mouse_event_fn);\n",
2221 2221 " rubberband.mouseleave('figure_leave', mouse_event_fn);\n",
2222 2222 "\n",
2223 2223 " canvas_div.on(\"wheel\", function (event) {\n",
2224 2224 " event = event.originalEvent;\n",
2225 2225 " event['data'] = 'scroll'\n",
2226 2226 " if (event.deltaY < 0) {\n",
2227 2227 " event.step = 1;\n",
2228 2228 " } else {\n",
2229 2229 " event.step = -1;\n",
2230 2230 " }\n",
2231 2231 " mouse_event_fn(event);\n",
2232 2232 " });\n",
2233 2233 "\n",
2234 2234 " canvas_div.append(canvas);\n",
2235 2235 " canvas_div.append(rubberband);\n",
2236 2236 "\n",
2237 2237 " this.rubberband = rubberband;\n",
2238 2238 " this.rubberband_canvas = rubberband[0];\n",
2239 2239 " this.rubberband_context = rubberband[0].getContext(\"2d\");\n",
2240 2240 " this.rubberband_context.strokeStyle = \"#000000\";\n",
2241 2241 "\n",
2242 2242 " this._resize_canvas = function(width, height) {\n",
2243 2243 " // Keep the size of the canvas, canvas container, and rubber band\n",
2244 2244 " // canvas in synch.\n",
2245 2245 " canvas_div.css('width', width)\n",
2246 2246 " canvas_div.css('height', height)\n",
2247 2247 "\n",
2248 2248 " canvas.attr('width', width);\n",
2249 2249 " canvas.attr('height', height);\n",
2250 2250 "\n",
2251 2251 " rubberband.attr('width', width);\n",
2252 2252 " rubberband.attr('height', height);\n",
2253 2253 " }\n",
2254 2254 "\n",
2255 2255 " // Set the figure to an initial 600x600px, this will subsequently be updated\n",
2256 2256 " // upon first draw.\n",
2257 2257 " this._resize_canvas(600, 600);\n",
2258 2258 "\n",
2259 2259 " // Disable right mouse context menu.\n",
2260 2260 " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n",
2261 2261 " return false;\n",
2262 2262 " });\n",
2263 2263 "\n",
2264 2264 " function set_focus () {\n",
2265 2265 " canvas.focus();\n",
2266 2266 " canvas_div.focus();\n",
2267 2267 " }\n",
2268 2268 "\n",
2269 2269 " window.setTimeout(set_focus, 100);\n",
2270 2270 "}\n",
2271 2271 "\n",
2272 2272 "mpl.figure.prototype._init_toolbar = function() {\n",
2273 2273 " var fig = this;\n",
2274 2274 "\n",
2275 2275 " var nav_element = $('<div/>')\n",
2276 2276 " nav_element.attr('style', 'width: 100%');\n",
2277 2277 " this.root.append(nav_element);\n",
2278 2278 "\n",
2279 2279 " // Define a callback function for later on.\n",
2280 2280 " function toolbar_event(event) {\n",
2281 2281 " return fig.toolbar_button_onclick(event['data']);\n",
2282 2282 " }\n",
2283 2283 " function toolbar_mouse_event(event) {\n",
2284 2284 " return fig.toolbar_button_onmouseover(event['data']);\n",
2285 2285 " }\n",
2286 2286 "\n",
2287 2287 " for(var toolbar_ind in mpl.toolbar_items) {\n",
2288 2288 " var name = mpl.toolbar_items[toolbar_ind][0];\n",
2289 2289 " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
2290 2290 " var image = mpl.toolbar_items[toolbar_ind][2];\n",
2291 2291 " var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
2292 2292 "\n",
2293 2293 " if (!name) {\n",
2294 2294 " // put a spacer in here.\n",
2295 2295 " continue;\n",
2296 2296 " }\n",
2297 2297 " var button = $('<button/>');\n",
2298 2298 " button.addClass('ui-button ui-widget ui-state-default ui-corner-all ' +\n",
2299 2299 " 'ui-button-icon-only');\n",
2300 2300 " button.attr('role', 'button');\n",
2301 2301 " button.attr('aria-disabled', 'false');\n",
2302 2302 " button.click(method_name, toolbar_event);\n",
2303 2303 " button.mouseover(tooltip, toolbar_mouse_event);\n",
2304 2304 "\n",
2305 2305 " var icon_img = $('<span/>');\n",
2306 2306 " icon_img.addClass('ui-button-icon-primary ui-icon');\n",
2307 2307 " icon_img.addClass(image);\n",
2308 2308 " icon_img.addClass('ui-corner-all');\n",
2309 2309 "\n",
2310 2310 " var tooltip_span = $('<span/>');\n",
2311 2311 " tooltip_span.addClass('ui-button-text');\n",
2312 2312 " tooltip_span.html(tooltip);\n",
2313 2313 "\n",
2314 2314 " button.append(icon_img);\n",
2315 2315 " button.append(tooltip_span);\n",
2316 2316 "\n",
2317 2317 " nav_element.append(button);\n",
2318 2318 " }\n",
2319 2319 "\n",
2320 2320 " var fmt_picker_span = $('<span/>');\n",
2321 2321 "\n",
2322 2322 " var fmt_picker = $('<select/>');\n",
2323 2323 " fmt_picker.addClass('mpl-toolbar-option ui-widget ui-widget-content');\n",
2324 2324 " fmt_picker_span.append(fmt_picker);\n",
2325 2325 " nav_element.append(fmt_picker_span);\n",
2326 2326 " this.format_dropdown = fmt_picker[0];\n",
2327 2327 "\n",
2328 2328 " for (var ind in mpl.extensions) {\n",
2329 2329 " var fmt = mpl.extensions[ind];\n",
2330 2330 " var option = $(\n",
2331 2331 " '<option/>', {selected: fmt === mpl.default_extension}).html(fmt);\n",
2332 2332 " fmt_picker.append(option)\n",
2333 2333 " }\n",
2334 2334 "\n",
2335 2335 " // Add hover states to the ui-buttons\n",
2336 2336 " $( \".ui-button\" ).hover(\n",
2337 2337 " function() { $(this).addClass(\"ui-state-hover\");},\n",
2338 2338 " function() { $(this).removeClass(\"ui-state-hover\");}\n",
2339 2339 " );\n",
2340 2340 "\n",
2341 2341 " var status_bar = $('<span class=\"mpl-message\"/>');\n",
2342 2342 " nav_element.append(status_bar);\n",
2343 2343 " this.message = status_bar[0];\n",
2344 2344 "}\n",
2345 2345 "\n",
2346 2346 "mpl.figure.prototype.request_resize = function(x_pixels, y_pixels) {\n",
2347 2347 " // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n",
2348 2348 " // which will in turn request a refresh of the image.\n",
2349 2349 " this.send_message('resize', {'width': x_pixels, 'height': y_pixels});\n",
2350 2350 "}\n",
2351 2351 "\n",
2352 2352 "mpl.figure.prototype.send_message = function(type, properties) {\n",
2353 2353 " properties['type'] = type;\n",
2354 2354 " properties['figure_id'] = this.id;\n",
2355 2355 " this.ws.send(JSON.stringify(properties));\n",
2356 2356 "}\n",
2357 2357 "\n",
2358 2358 "mpl.figure.prototype.send_draw_message = function() {\n",
2359 2359 " if (!this.waiting) {\n",
2360 2360 " this.waiting = true;\n",
2361 2361 " this.ws.send(JSON.stringify({type: \"draw\", figure_id: this.id}));\n",
2362 2362 " }\n",
2363 2363 "}\n",
2364 2364 "\n",
2365 2365 "\n",
2366 2366 "mpl.figure.prototype.handle_save = function(fig, msg) {\n",
2367 2367 " var format_dropdown = fig.format_dropdown;\n",
2368 2368 " var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n",
2369 2369 " fig.ondownload(fig, format);\n",
2370 2370 "}\n",
2371 2371 "\n",
2372 2372 "\n",
2373 2373 "mpl.figure.prototype.handle_resize = function(fig, msg) {\n",
2374 2374 " var size = msg['size'];\n",
2375 2375 " if (size[0] != fig.canvas.width || size[1] != fig.canvas.height) {\n",
2376 2376 " fig._resize_canvas(size[0], size[1]);\n",
2377 2377 " fig.send_message(\"refresh\", {});\n",
2378 2378 " };\n",
2379 2379 "}\n",
2380 2380 "\n",
2381 2381 "mpl.figure.prototype.handle_rubberband = function(fig, msg) {\n",
2382 2382 " var x0 = msg['x0'];\n",
2383 2383 " var y0 = fig.canvas.height - msg['y0'];\n",
2384 2384 " var x1 = msg['x1'];\n",
2385 2385 " var y1 = fig.canvas.height - msg['y1'];\n",
2386 2386 " x0 = Math.floor(x0) + 0.5;\n",
2387 2387 " y0 = Math.floor(y0) + 0.5;\n",
2388 2388 " x1 = Math.floor(x1) + 0.5;\n",
2389 2389 " y1 = Math.floor(y1) + 0.5;\n",
2390 2390 " var min_x = Math.min(x0, x1);\n",
2391 2391 " var min_y = Math.min(y0, y1);\n",
2392 2392 " var width = Math.abs(x1 - x0);\n",
2393 2393 " var height = Math.abs(y1 - y0);\n",
2394 2394 "\n",
2395 2395 " fig.rubberband_context.clearRect(\n",
2396 2396 " 0, 0, fig.canvas.width, fig.canvas.height);\n",
2397 2397 "\n",
2398 2398 " fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n",
2399 2399 "}\n",
2400 2400 "\n",
2401 2401 "mpl.figure.prototype.handle_figure_label = function(fig, msg) {\n",
2402 2402 " // Updates the figure title.\n",
2403 2403 " fig.header.textContent = msg['label'];\n",
2404 2404 "}\n",
2405 2405 "\n",
2406 2406 "mpl.figure.prototype.handle_cursor = function(fig, msg) {\n",
2407 2407 " var cursor = msg['cursor'];\n",
2408 2408 " switch(cursor)\n",
2409 2409 " {\n",
2410 2410 " case 0:\n",
2411 2411 " cursor = 'pointer';\n",
2412 2412 " break;\n",
2413 2413 " case 1:\n",
2414 2414 " cursor = 'default';\n",
2415 2415 " break;\n",
2416 2416 " case 2:\n",
2417 2417 " cursor = 'crosshair';\n",
2418 2418 " break;\n",
2419 2419 " case 3:\n",
2420 2420 " cursor = 'move';\n",
2421 2421 " break;\n",
2422 2422 " }\n",
2423 2423 " fig.rubberband_canvas.style.cursor = cursor;\n",
2424 2424 "}\n",
2425 2425 "\n",
2426 2426 "mpl.figure.prototype.handle_message = function(fig, msg) {\n",
2427 2427 " fig.message.textContent = msg['message'];\n",
2428 2428 "}\n",
2429 2429 "\n",
2430 2430 "mpl.figure.prototype.handle_draw = function(fig, msg) {\n",
2431 2431 " // Request the server to send over a new figure.\n",
2432 2432 " fig.send_draw_message();\n",
2433 2433 "}\n",
2434 2434 "\n",
2435 2435 "mpl.figure.prototype.handle_image_mode = function(fig, msg) {\n",
2436 2436 " fig.image_mode = msg['mode'];\n",
2437 2437 "}\n",
2438 2438 "\n",
2439 2439 "mpl.figure.prototype.updated_canvas_event = function() {\n",
2440 2440 " // Called whenever the canvas gets updated.\n",
2441 2441 " this.send_message(\"ack\", {});\n",
2442 2442 "}\n",
2443 2443 "\n",
2444 2444 "// A function to construct a web socket function for onmessage handling.\n",
2445 2445 "// Called in the figure constructor.\n",
2446 2446 "mpl.figure.prototype._make_on_message_function = function(fig) {\n",
2447 2447 " return function socket_on_message(evt) {\n",
2448 2448 " if (evt.data instanceof Blob) {\n",
2449 2449 " /* FIXME: We get \"Resource interpreted as Image but\n",
2450 2450 " * transferred with MIME type text/plain:\" errors on\n",
2451 2451 " * Chrome. But how to set the MIME type? It doesn't seem\n",
2452 2452 " * to be part of the websocket stream */\n",
2453 2453 " evt.data.type = \"image/png\";\n",
2454 2454 "\n",
2455 2455 " /* Free the memory for the previous frames */\n",
2456 2456 " if (fig.imageObj.src) {\n",
2457 2457 " (window.URL || window.webkitURL).revokeObjectURL(\n",
2458 2458 " fig.imageObj.src);\n",
2459 2459 " }\n",
2460 2460 "\n",
2461 2461 " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
2462 2462 " evt.data);\n",
2463 2463 " fig.updated_canvas_event();\n",
2464 2464 " return;\n",
2465 2465 " }\n",
2466 2466 " else if (typeof evt.data === 'string' && evt.data.slice(0, 21) == \"data:image/png;base64\") {\n",
2467 2467 " fig.imageObj.src = evt.data;\n",
2468 2468 " fig.updated_canvas_event();\n",
2469 2469 " return;\n",
2470 2470 " }\n",
2471 2471 "\n",
2472 2472 " var msg = JSON.parse(evt.data);\n",
2473 2473 " var msg_type = msg['type'];\n",
2474 2474 "\n",
2475 2475 " // Call the \"handle_{type}\" callback, which takes\n",
2476 2476 " // the figure and JSON message as its only arguments.\n",
2477 2477 " try {\n",
2478 2478 " var callback = fig[\"handle_\" + msg_type];\n",
2479 2479 " } catch (e) {\n",
2480 2480 " console.log(\"No handler for the '\" + msg_type + \"' message type: \", msg);\n",
2481 2481 " return;\n",
2482 2482 " }\n",
2483 2483 "\n",
2484 2484 " if (callback) {\n",
2485 2485 " try {\n",
2486 2486 " // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n",
2487 2487 " callback(fig, msg);\n",
2488 2488 " } catch (e) {\n",
2489 2489 " console.log(\"Exception inside the 'handler_\" + msg_type + \"' callback:\", e, e.stack, msg);\n",
2490 2490 " }\n",
2491 2491 " }\n",
2492 2492 " };\n",
2493 2493 "}\n",
2494 2494 "\n",
2495 2495 "// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n",
2496 2496 "mpl.findpos = function(e) {\n",
2497 2497 " //this section is from http://www.quirksmode.org/js/events_properties.html\n",
2498 2498 " var targ;\n",
2499 2499 " if (!e)\n",
2500 2500 " e = window.event;\n",
2501 2501 " if (e.target)\n",
2502 2502 " targ = e.target;\n",
2503 2503 " else if (e.srcElement)\n",
2504 2504 " targ = e.srcElement;\n",
2505 2505 " if (targ.nodeType == 3) // defeat Safari bug\n",
2506 2506 " targ = targ.parentNode;\n",
2507 2507 "\n",
2508 2508 " // jQuery normalizes the pageX and pageY\n",
2509 2509 " // pageX,Y are the mouse positions relative to the document\n",
2510 2510 " // offset() returns the position of the element relative to the document\n",
2511 2511 " var x = e.pageX - $(targ).offset().left;\n",
2512 2512 " var y = e.pageY - $(targ).offset().top;\n",
2513 2513 "\n",
2514 2514 " return {\"x\": x, \"y\": y};\n",
2515 2515 "};\n",
2516 2516 "\n",
2517 2517 "mpl.figure.prototype.mouse_event = function(event, name) {\n",
2518 2518 " var canvas_pos = mpl.findpos(event)\n",
2519 2519 "\n",
2520 2520 " if (name === 'button_press')\n",
2521 2521 " {\n",
2522 2522 " this.canvas.focus();\n",
2523 2523 " this.canvas_div.focus();\n",
2524 2524 " }\n",
2525 2525 "\n",
2526 2526 " var x = canvas_pos.x;\n",
2527 2527 " var y = canvas_pos.y;\n",
2528 2528 "\n",
2529 2529 " this.send_message(name, {x: x, y: y, button: event.button,\n",
2530 2530 " step: event.step});\n",
2531 2531 "\n",
2532 2532 " /* This prevents the web browser from automatically changing to\n",
2533 2533 " * the text insertion cursor when the button is pressed. We want\n",
2534 2534 " * to control all of the cursor setting manually through the\n",
2535 2535 " * 'cursor' event from matplotlib */\n",
2536 2536 " event.preventDefault();\n",
2537 2537 " return false;\n",
2538 2538 "}\n",
2539 2539 "\n",
2540 2540 "mpl.figure.prototype._key_event_extra = function(event, name) {\n",
2541 2541 " // Handle any extra behaviour associated with a key event\n",
2542 2542 "}\n",
2543 2543 "\n",
2544 2544 "mpl.figure.prototype.key_event = function(event, name) {\n",
2545 2545 "\n",
2546 2546 " // Prevent repeat events\n",
2547 2547 " if (name == 'key_press')\n",
2548 2548 " {\n",
2549 2549 " if (event.which === this._key)\n",
2550 2550 " return;\n",
2551 2551 " else\n",
2552 2552 " this._key = event.which;\n",
2553 2553 " }\n",
2554 2554 " if (name == 'key_release')\n",
2555 2555 " this._key = null;\n",
2556 2556 "\n",
2557 2557 " var value = '';\n",
2558 2558 " if (event.ctrlKey && event.which != 17)\n",
2559 2559 " value += \"ctrl+\";\n",
2560 2560 " if (event.altKey && event.which != 18)\n",
2561 2561 " value += \"alt+\";\n",
2562 2562 " if (event.shiftKey && event.which != 16)\n",
2563 2563 " value += \"shift+\";\n",
2564 2564 "\n",
2565 2565 " value += 'k';\n",
2566 2566 " value += event.which.toString();\n",
2567 2567 "\n",
2568 2568 " this._key_event_extra(event, name);\n",
2569 2569 "\n",
2570 2570 " this.send_message(name, {key: value});\n",
2571 2571 " return false;\n",
2572 2572 "}\n",
2573 2573 "\n",
2574 2574 "mpl.figure.prototype.toolbar_button_onclick = function(name) {\n",
2575 2575 " if (name == 'download') {\n",
2576 2576 " this.handle_save(this, null);\n",
2577 2577 " } else {\n",
2578 2578 " this.send_message(\"toolbar_button\", {name: name});\n",
2579 2579 " }\n",
2580 2580 "};\n",
2581 2581 "\n",
2582 2582 "mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n",
2583 2583 " this.message.textContent = tooltip;\n",
2584 2584 "};\n",
2585 2585 "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n",
2586 2586 "\n",
2587 2587 "mpl.extensions = [\"eps\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\"];\n",
2588 2588 "\n",
2589 2589 "mpl.default_extension = \"png\";var comm_websocket_adapter = function(comm) {\n",
2590 2590 " // Create a \"websocket\"-like object which calls the given IPython comm\n",
2591 2591 " // object with the appropriate methods. Currently this is a non binary\n",
2592 2592 " // socket, so there is still some room for performance tuning.\n",
2593 2593 " var ws = {};\n",
2594 2594 "\n",
2595 2595 " ws.close = function() {\n",
2596 2596 " comm.close()\n",
2597 2597 " };\n",
2598 2598 " ws.send = function(m) {\n",
2599 2599 " //console.log('sending', m);\n",
2600 2600 " comm.send(m);\n",
2601 2601 " };\n",
2602 2602 " // Register the callback with on_msg.\n",
2603 2603 " comm.on_msg(function(msg) {\n",
2604 2604 " //console.log('receiving', msg['content']['data'], msg);\n",
2605 " // Pass the mpl event to the overriden (by mpl) onmessage function.\n",
2605 " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
2606 2606 " ws.onmessage(msg['content']['data'])\n",
2607 2607 " });\n",
2608 2608 " return ws;\n",
2609 2609 "}\n",
2610 2610 "\n",
2611 2611 "mpl.mpl_figure_comm = function(comm, msg) {\n",
2612 2612 " // This is the function which gets called when the mpl process\n",
2613 2613 " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
2614 2614 "\n",
2615 2615 " var id = msg.content.data.id;\n",
2616 2616 " // Get hold of the div created by the display call when the Comm\n",
2617 2617 " // socket was opened in Python.\n",
2618 2618 " var element = $(\"#\" + id);\n",
2619 2619 " var ws_proxy = comm_websocket_adapter(comm)\n",
2620 2620 "\n",
2621 2621 " function ondownload(figure, format) {\n",
2622 2622 " window.open(figure.imageObj.src);\n",
2623 2623 " }\n",
2624 2624 "\n",
2625 2625 " var fig = new mpl.figure(id, ws_proxy,\n",
2626 2626 " ondownload,\n",
2627 2627 " element.get(0));\n",
2628 2628 "\n",
2629 2629 " // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n",
2630 2630 " // web socket which is closed, not our websocket->open comm proxy.\n",
2631 2631 " ws_proxy.onopen();\n",
2632 2632 "\n",
2633 2633 " fig.parent_element = element.get(0);\n",
2634 2634 " fig.cell_info = mpl.find_output_cell(\"<div id='\" + id + \"'></div>\");\n",
2635 2635 " if (!fig.cell_info) {\n",
2636 2636 " console.error(\"Failed to find cell for figure\", id, fig);\n",
2637 2637 " return;\n",
2638 2638 " }\n",
2639 2639 "\n",
2640 2640 " var output_index = fig.cell_info[2]\n",
2641 2641 " var cell = fig.cell_info[0];\n",
2642 2642 "\n",
2643 2643 "};\n",
2644 2644 "\n",
2645 2645 "mpl.figure.prototype.handle_close = function(fig, msg) {\n",
2646 2646 " // Update the output cell to use the data from the current canvas.\n",
2647 2647 " fig.push_to_output();\n",
2648 2648 " var dataURL = fig.canvas.toDataURL();\n",
2649 2649 " // Re-enable the keyboard manager in IPython - without this line, in FF,\n",
2650 2650 " // the notebook keyboard shortcuts fail.\n",
2651 2651 " IPython.keyboard_manager.enable()\n",
2652 2652 " $(fig.parent_element).html('<img src=\"' + dataURL + '\">');\n",
2653 2653 " fig.send_message('closing', {});\n",
2654 2654 " fig.ws.close()\n",
2655 2655 "}\n",
2656 2656 "\n",
2657 2657 "mpl.figure.prototype.push_to_output = function(remove_interactive) {\n",
2658 2658 " // Turn the data on the canvas into data in the output cell.\n",
2659 2659 " var dataURL = this.canvas.toDataURL();\n",
2660 2660 " this.cell_info[1]['text/html'] = '<img src=\"' + dataURL + '\">';\n",
2661 2661 "}\n",
2662 2662 "\n",
2663 2663 "mpl.figure.prototype.updated_canvas_event = function() {\n",
2664 2664 " // Tell IPython that the notebook contents must change.\n",
2665 2665 " IPython.notebook.set_dirty(true);\n",
2666 2666 " this.send_message(\"ack\", {});\n",
2667 2667 " var fig = this;\n",
2668 2668 " // Wait a second, then push the new image to the DOM so\n",
2669 2669 " // that it is saved nicely (might be nice to debounce this).\n",
2670 2670 " setTimeout(function () { fig.push_to_output() }, 1000);\n",
2671 2671 "}\n",
2672 2672 "\n",
2673 2673 "mpl.figure.prototype._init_toolbar = function() {\n",
2674 2674 " var fig = this;\n",
2675 2675 "\n",
2676 2676 " var nav_element = $('<div/>')\n",
2677 2677 " nav_element.attr('style', 'width: 100%');\n",
2678 2678 " this.root.append(nav_element);\n",
2679 2679 "\n",
2680 2680 " // Define a callback function for later on.\n",
2681 2681 " function toolbar_event(event) {\n",
2682 2682 " return fig.toolbar_button_onclick(event['data']);\n",
2683 2683 " }\n",
2684 2684 " function toolbar_mouse_event(event) {\n",
2685 2685 " return fig.toolbar_button_onmouseover(event['data']);\n",
2686 2686 " }\n",
2687 2687 "\n",
2688 2688 " for(var toolbar_ind in mpl.toolbar_items){\n",
2689 2689 " var name = mpl.toolbar_items[toolbar_ind][0];\n",
2690 2690 " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
2691 2691 " var image = mpl.toolbar_items[toolbar_ind][2];\n",
2692 2692 " var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
2693 2693 "\n",
2694 2694 " if (!name) { continue; };\n",
2695 2695 "\n",
2696 2696 " var button = $('<button class=\"btn btn-default\" href=\"#\" title=\"' + name + '\"><i class=\"fa ' + image + ' fa-lg\"></i></button>');\n",
2697 2697 " button.click(method_name, toolbar_event);\n",
2698 2698 " button.mouseover(tooltip, toolbar_mouse_event);\n",
2699 2699 " nav_element.append(button);\n",
2700 2700 " }\n",
2701 2701 "\n",
2702 2702 " // Add the status bar.\n",
2703 2703 " var status_bar = $('<span class=\"mpl-message\" style=\"text-align:right; float: right;\"/>');\n",
2704 2704 " nav_element.append(status_bar);\n",
2705 2705 " this.message = status_bar[0];\n",
2706 2706 "\n",
2707 2707 " // Add the close button to the window.\n",
2708 2708 " var buttongrp = $('<div class=\"btn-group inline pull-right\"></div>');\n",
2709 2709 " var button = $('<button class=\"btn btn-mini btn-danger\" href=\"#\" title=\"Close figure\"><i class=\"fa fa-times icon-remove icon-large\"></i></button>');\n",
2710 2710 " button.click(function (evt) { fig.handle_close(fig, {}); } );\n",
2711 2711 " button.mouseover('Close figure', toolbar_mouse_event);\n",
2712 2712 " buttongrp.append(button);\n",
2713 2713 " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n",
2714 2714 " titlebar.prepend(buttongrp);\n",
2715 2715 "}\n",
2716 2716 "\n",
2717 2717 "\n",
2718 2718 "mpl.figure.prototype._canvas_extra_style = function(el){\n",
2719 2719 " // this is important to make the div 'focusable\n",
2720 2720 " el.attr('tabindex', 0)\n",
2721 2721 " // reach out to IPython and tell the keyboard manager to turn it's self\n",
2722 2722 " // off when our div gets focus\n",
2723 2723 "\n",
2724 2724 " // location in version 3\n",
2725 2725 " if (IPython.notebook.keyboard_manager) {\n",
2726 2726 " IPython.notebook.keyboard_manager.register_events(el);\n",
2727 2727 " }\n",
2728 2728 " else {\n",
2729 2729 " // location in version 2\n",
2730 2730 " IPython.keyboard_manager.register_events(el);\n",
2731 2731 " }\n",
2732 2732 "\n",
2733 2733 "}\n",
2734 2734 "\n",
2735 2735 "mpl.figure.prototype._key_event_extra = function(event, name) {\n",
2736 2736 " var manager = IPython.notebook.keyboard_manager;\n",
2737 2737 " if (!manager)\n",
2738 2738 " manager = IPython.keyboard_manager;\n",
2739 2739 "\n",
2740 2740 " // Check for shift+enter\n",
2741 2741 " if (event.shiftKey && event.which == 13) {\n",
2742 2742 " this.canvas_div.blur();\n",
2743 2743 " event.shiftKey = false;\n",
2744 2744 " // Send a \"J\" for go to next cell\n",
2745 2745 " event.which = 74;\n",
2746 2746 " event.keyCode = 74;\n",
2747 2747 " manager.command_mode();\n",
2748 2748 " manager.handle_keydown(event);\n",
2749 2749 " }\n",
2750 2750 "}\n",
2751 2751 "\n",
2752 2752 "mpl.figure.prototype.handle_save = function(fig, msg) {\n",
2753 2753 " fig.ondownload(fig, null);\n",
2754 2754 "}\n",
2755 2755 "\n",
2756 2756 "\n",
2757 2757 "mpl.find_output_cell = function(html_output) {\n",
2758 2758 " // Return the cell and output element which can be found *uniquely* in the notebook.\n",
2759 2759 " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n",
2760 2760 " // IPython event is triggered only after the cells have been serialised, which for\n",
2761 2761 " // our purposes (turning an active figure into a static one), is too late.\n",
2762 2762 " var cells = IPython.notebook.get_cells();\n",
2763 2763 " var ncells = cells.length;\n",
2764 2764 " for (var i=0; i<ncells; i++) {\n",
2765 2765 " var cell = cells[i];\n",
2766 2766 " if (cell.cell_type === 'code'){\n",
2767 2767 " for (var j=0; j<cell.output_area.outputs.length; j++) {\n",
2768 2768 " var data = cell.output_area.outputs[j];\n",
2769 2769 " if (data.data) {\n",
2770 2770 " // IPython >= 3 moved mimebundle to data attribute of output\n",
2771 2771 " data = data.data;\n",
2772 2772 " }\n",
2773 2773 " if (data['text/html'] == html_output) {\n",
2774 2774 " return [cell, data, j];\n",
2775 2775 " }\n",
2776 2776 " }\n",
2777 2777 " }\n",
2778 2778 " }\n",
2779 2779 "}\n",
2780 2780 "\n",
2781 2781 "// Register the function which deals with the matplotlib target/channel.\n",
2782 2782 "// The kernel may be null if the page has been refreshed.\n",
2783 2783 "if (IPython.notebook.kernel != null) {\n",
2784 2784 " IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n",
2785 2785 "}\n"
2786 2786 ],
2787 2787 "text/plain": [
2788 2788 "<IPython.core.display.Javascript object>"
2789 2789 ]
2790 2790 },
2791 2791 "metadata": {},
2792 2792 "output_type": "display_data"
2793 2793 },
2794 2794 {
2795 2795 "data": {
2796 2796 "text/html": [
2797 2797 "<img src=\"data:image/png;base64,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\">"
2798 2798 ],
2799 2799 "text/plain": [
2800 2800 "<IPython.core.display.HTML object>"
2801 2801 ]
2802 2802 },
2803 2803 "metadata": {},
2804 2804 "output_type": "display_data"
2805 2805 }
2806 2806 ],
2807 2807 "source": [
2808 2808 "plt.figure()\n",
2809 2809 "x = np.linspace(0, 5 * np.pi, 1000)\n",
2810 2810 "for n in range(1, 4):\n",
2811 2811 " plt.plot(np.sin(n * x))\n",
2812 2812 "plt.show()"
2813 2813 ]
2814 2814 }
2815 2815 ],
2816 2816 "metadata": {
2817 2817 "kernelspec": {
2818 2818 "display_name": "Python 3",
2819 2819 "language": "python",
2820 2820 "name": "python3"
2821 2821 },
2822 2822 "language_info": {
2823 2823 "codemirror_mode": {
2824 2824 "name": "ipython",
2825 2825 "version": 3
2826 2826 },
2827 2827 "file_extension": ".py",
2828 2828 "mimetype": "text/x-python",
2829 2829 "name": "python",
2830 2830 "nbconvert_exporter": "python",
2831 2831 "pygments_lexer": "ipython3",
2832 2832 "version": "3.4.2"
2833 2833 }
2834 2834 },
2835 2835 "nbformat": 4,
2836 2836 "nbformat_minor": 0
2837 2837 }
@@ -1,88 +1,88 b''
1 1 # coding: utf-8
2 2
3 3 # This script autogenerates `IPython.core.latex_symbols.py`, which contains a
4 4 # single dict , named `latex_symbols`. The keys in this dict are latex symbols,
5 5 # such as `\\alpha` and the values in the dict are the unicode equivalents for
6 # those. Most importantly, only unicode symbols that are valid identifers in
6 # those. Most importantly, only unicode symbols that are valid identifiers in
7 7 # Python 3 are included.
8 8
9 9 #
10 10 # The original mapping of latex symbols to unicode comes from the `latex_symbols.jl` files from Julia.
11 11
12 12 import os, sys
13 13
14 14 if not sys.version_info[0] == 3:
15 15 print("This script must be run with Python 3, exiting...")
16 16 sys.exit(1)
17 17
18 18 # Import the Julia LaTeX symbols
19 19 print('Importing latex_symbols.js from Julia...')
20 20 import requests
21 21 url = 'https://raw.githubusercontent.com/JuliaLang/julia/master/base/latex_symbols.jl'
22 22 r = requests.get(url)
23 23
24 24
25 25 # Build a list of key, value pairs
26 26 print('Building a list of (latex, unicode) key-value pairs...')
27 27 lines = r.text.splitlines()[60:]
28 28 lines = [line for line in lines if '=>' in line]
29 29 lines = [line.replace('=>',':') for line in lines]
30 30
31 31 def line_to_tuple(line):
32 32 """Convert a single line of the .jl file to a 2-tuple of strings like ("\\alpha", "α")"""
33 33 kv = line.split(',')[0].split(':')
34 34 # kv = tuple(line.strip(', ').split(':'))
35 35 k, v = kv[0].strip(' "'), kv[1].strip(' "')
36 36 # if not test_ident(v):
37 37 # print(line)
38 38 return k, v
39 39
40 40 assert line_to_tuple(' "\\sqrt" : "\u221A",') == ('\\sqrt', '\u221A')
41 41 lines = [line_to_tuple(line) for line in lines]
42 42
43 43
44 44 # Filter out non-valid identifiers
45 45 print('Filtering out characters that are not valid Python 3 identifiers')
46 46
47 47 def test_ident(i):
48 48 """Is the unicode string valid in a Python 3 identifer."""
49 49 # Some characters are not valid at the start of a name, but we still want to
50 50 # include them. So prefix with 'a', which is valid at the start.
51 51 return ('a' + i).isidentifier()
52 52
53 53 assert test_ident("α")
54 54 assert not test_ident('‴')
55 55
56 56 valid_idents = [line for line in lines if test_ident(line[1])]
57 57
58 58
59 59 # Write the `latex_symbols.py` module in the cwd
60 60
61 61 s = """# encoding: utf-8
62 62
63 63 # DO NOT EDIT THIS FILE BY HAND.
64 64
65 65 # To update this file, run the script /tools/gen_latex_symbols.py using Python 3
66 66
67 67 # This file is autogenerated from the file:
68 68 # https://raw.githubusercontent.com/JuliaLang/julia/master/base/latex_symbols.jl
69 69 # This original list is filtered to remove any unicode characters that are not valid
70 70 # Python identifiers.
71 71
72 72 latex_symbols = {\n
73 73 """
74 74 for line in valid_idents:
75 75 s += ' "%s" : "%s",\n' % (line[0], line[1])
76 76 s += "}\n"
77 77
78 78 s += """
79 79
80 80 reverse_latex_symbol = { v:k for k,v in latex_symbols.items()}
81 81 """
82 82
83 83 fn = os.path.join('..','IPython','core','latex_symbols.py')
84 84 print("Writing the file: %s" % fn)
85 85 with open(fn, 'w', encoding='utf-8') as f:
86 86 f.write(s)
87 87
88 88
@@ -1,127 +1,127 b''
1 1 #!/usr/bin/env python
2 2 # -*- coding: utf-8 -*-
3 3 """
4 4 Usage:
5 5 git-mpr [-h] [-l | -a] [pr-number [pr-number ...]]
6 6
7 7 Type `git mpr -h` for details.
8 8 """
9 9
10 10
11 11 import io, os
12 12 import argparse
13 13 from subprocess import check_call, CalledProcessError
14 14
15 15 import gh_api
16 16
17 17 ipy_repository = 'git://github.com/ipython/ipython.git'
18 18 gh_project = "ipython/ipython"
19 19 not_merged = {}
20 20
21 21 def merge_branch(repo, branch ):
22 22 """try to merge the givent branch into the current one
23 23
24 24 If something does not goes smoothly, merge is aborted
25 25
26 Returns True if merge sucessfull, False otherwise
26 Returns True if merge successful, False otherwise
27 27 """
28 28 # Delete the branch first
29 29 try :
30 30 check_call(['git', 'pull', repo, branch], stdin=io.open(os.devnull))
31 31 except CalledProcessError :
32 32 check_call(['git', 'merge', '--abort'])
33 33 return False
34 34 return True
35 35
36 36
37 37 def git_new_branch(name):
38 38 """Create a new branch with the given name and check it out.
39 39 """
40 40 check_call(['git', 'checkout', '-b', name])
41 41
42 42
43 43 def merge_pr(num):
44 44 """ try to merge the branch of PR `num` into current branch
45 45 """
46 46 # Get Github authorisation first, so that the user is prompted straight away
47 47 # if their login is needed.
48 48
49 49 pr = gh_api.get_pull_request(gh_project, num)
50 50 repo = pr['head']['repo']['clone_url']
51 51
52 52
53 53 branch = pr['head']['ref']
54 54 mergeable = merge_branch(repo=repo,
55 55 branch=branch,
56 56 )
57 57 if not mergeable :
58 58 cmd = "git pull "+repo+" "+branch
59 59 not_merged[str(num)] = cmd
60 60 print("==============================================================================")
61 61 print("Something went wrong merging this branch, you can try it manually by runngin :")
62 62 print(cmd)
63 63 print("==============================================================================")
64 64
65 65
66 66 def main(*args):
67 67 parser = argparse.ArgumentParser(
68 68 description="""
69 69 Merge one or more github pull requests by their number. If any
70 70 one pull request can't be merged as is, its merge is ignored
71 71 and the process continues with the next ones (if any).
72 72 """
73 73 )
74 74
75 75 grp = parser.add_mutually_exclusive_group()
76 76 grp.add_argument(
77 77 '-l',
78 78 '--list',
79 79 action='store_const',
80 80 const=True,
81 81 help='list PR, their number and their mergeability')
82 82 grp.add_argument('-a',
83 83 '--merge-all',
84 84 action='store_const',
85 85 const=True ,
86 86 help='try to merge as many PR as possible, one by one')
87 87 parser.add_argument('merge',
88 88 type=int,
89 89 help="The pull request numbers",
90 90 nargs='*',
91 91 metavar='pr-number')
92 92 args = parser.parse_args()
93 93
94 94 if(args.list):
95 95 pr_list = gh_api.get_pulls_list(gh_project)
96 96 for pr in pr_list :
97 97 mergeable = gh_api.get_pull_request(gh_project, pr['number'])['mergeable']
98 98
99 99 ismgb = u"√" if mergeable else " "
100 100 print(u"* #{number} [{ismgb}]: {title}".format(
101 101 number=pr['number'],
102 102 title=pr['title'],
103 103 ismgb=ismgb))
104 104
105 105 if(args.merge_all):
106 106 branch_name = 'merge-' + '-'.join(str(pr['number']) for pr in pr_list)
107 107 git_new_branch(branch_name)
108 108 pr_list = gh_api.get_pulls_list(gh_project)
109 109 for pr in pr_list :
110 110 merge_pr(pr['number'])
111 111
112 112
113 113 elif args.merge:
114 114 branch_name = 'merge-' + '-'.join(map(str, args.merge))
115 115 git_new_branch(branch_name)
116 116 for num in args.merge :
117 117 merge_pr(num)
118 118
119 119 if not_merged :
120 120 print('*************************************************************************************')
121 121 print('the following branch have not been merged automatically, considere doing it by hand :')
122 122 for num, cmd in not_merged.items() :
123 123 print( "PR {num}: {cmd}".format(num=num, cmd=cmd))
124 124 print('*************************************************************************************')
125 125
126 126 if __name__ == '__main__':
127 127 main()
General Comments 0
You need to be logged in to leave comments. Login now