##// END OF EJS Templates
Merge branch 'master' into jedi_completion
Kelly Liu -
r22293:eca61c4d merge
parent child Browse files
Show More
@@ -71,11 +71,10 b' from IPython.core.error import TryNext'
71 from IPython.core.inputsplitter import ESC_MAGIC
71 from IPython.core.inputsplitter import ESC_MAGIC
72 from IPython.core.latex_symbols import latex_symbols, reverse_latex_symbol
72 from IPython.core.latex_symbols import latex_symbols, reverse_latex_symbol
73 from IPython.utils import generics
73 from IPython.utils import generics
74 from IPython.utils import io
75 from IPython.utils.decorators import undoc
74 from IPython.utils.decorators import undoc
76 from IPython.utils.dir2 import dir2, get_real_method
75 from IPython.utils.dir2 import dir2, get_real_method
77 from IPython.utils.process import arg_split
76 from IPython.utils.process import arg_split
78 from IPython.utils.py3compat import builtin_mod, string_types, PY3
77 from IPython.utils.py3compat import builtin_mod, string_types, PY3, cast_unicode_py2
79 from traitlets import CBool, Enum
78 from traitlets import CBool, Enum
80
79
81 try:
80 try:
@@ -201,6 +200,9 b' def completions_sorting_key(word):'
201 elif word.startswith('_'):
200 elif word.startswith('_'):
202 prio1 = 1
201 prio1 = 1
203
202
203 if word.endswith('='):
204 prio1 = -1
205
204 if word.startswith('%%'):
206 if word.startswith('%%'):
205 # If there's another % in there, this is something else, so leave it alone
207 # If there's another % in there, this is something else, so leave it alone
206 if not "%" in word[2:]:
208 if not "%" in word[2:]:
@@ -358,7 +360,7 b' class Completer(Configurable):'
358 for word in lst:
360 for word in lst:
359 if word[:n] == text and word != "__builtins__":
361 if word[:n] == text and word != "__builtins__":
360 match_append(word)
362 match_append(word)
361 return matches
363 return [cast_unicode_py2(m) for m in matches]
362
364
363 def attr_matches(self, text):
365 def attr_matches(self, text):
364 """Compute matches when text contains a dot.
366 """Compute matches when text contains a dot.
@@ -410,8 +412,7 b' class Completer(Configurable):'
410 pass
412 pass
411 # Build match list to return
413 # Build match list to return
412 n = len(attr)
414 n = len(attr)
413 res = ["%s.%s" % (expr, w) for w in words if w[:n] == attr ]
415 return [u"%s.%s" % (expr, w) for w in words if w[:n] == attr ]
414 return res
415
416
416
417
417 def get__all__entries(obj):
418 def get__all__entries(obj):
@@ -421,7 +422,7 b' def get__all__entries(obj):'
421 except:
422 except:
422 return []
423 return []
423
424
424 return [w for w in words if isinstance(w, string_types)]
425 return [cast_unicode_py2(w) for w in words if isinstance(w, string_types)]
425
426
426
427
427 def match_dict_keys(keys, prefix, delims):
428 def match_dict_keys(keys, prefix, delims):
@@ -695,9 +696,9 b' class IPCompleter(Completer):'
695 # when escaped with backslash
696 # when escaped with backslash
696 if text.startswith('!'):
697 if text.startswith('!'):
697 text = text[1:]
698 text = text[1:]
698 text_prefix = '!'
699 text_prefix = u'!'
699 else:
700 else:
700 text_prefix = ''
701 text_prefix = u''
701
702
702 text_until_cursor = self.text_until_cursor
703 text_until_cursor = self.text_until_cursor
703 # track strings with open quotes
704 # track strings with open quotes
@@ -728,7 +729,7 b' class IPCompleter(Completer):'
728 text = os.path.expanduser(text)
729 text = os.path.expanduser(text)
729
730
730 if text == "":
731 if text == "":
731 return [text_prefix + protect_filename(f) for f in self.glob("*")]
732 return [text_prefix + cast_unicode_py2(protect_filename(f)) for f in self.glob("*")]
732
733
733 # Compute the matches from the filesystem
734 # Compute the matches from the filesystem
734 m0 = self.clean_glob(text.replace('\\',''))
735 m0 = self.clean_glob(text.replace('\\',''))
@@ -751,8 +752,7 b' class IPCompleter(Completer):'
751 protect_filename(f) for f in m0]
752 protect_filename(f) for f in m0]
752
753
753 # Mark directories in input list by appending '/' to their names.
754 # Mark directories in input list by appending '/' to their names.
754 matches = [x+'/' if os.path.isdir(x) else x for x in matches]
755 return [cast_unicode_py2(x+'/') if os.path.isdir(x) else x for x in matches]
755 return matches
756
756
757 def magic_matches(self, text):
757 def magic_matches(self, text):
758 """Match magics"""
758 """Match magics"""
@@ -773,7 +773,7 b' class IPCompleter(Completer):'
773 comp = [ pre2+m for m in cell_magics if m.startswith(bare_text)]
773 comp = [ pre2+m for m in cell_magics if m.startswith(bare_text)]
774 if not text.startswith(pre2):
774 if not text.startswith(pre2):
775 comp += [ pre+m for m in line_magics if m.startswith(bare_text)]
775 comp += [ pre+m for m in line_magics if m.startswith(bare_text)]
776 return comp
776 return [cast_unicode_py2(c) for c in comp]
777
777
778 def python_jedi_matches(self, text, line_buffer, cursor_pos):
778 def python_jedi_matches(self, text, line_buffer, cursor_pos):
779 """Match attributes or global Python names using Jedi."""
779 """Match attributes or global Python names using Jedi."""
@@ -849,7 +849,6 b' class IPCompleter(Completer):'
849 matches = []
849 matches = []
850 else:
850 else:
851 matches = self.global_matches(text)
851 matches = self.global_matches(text)
852
853 return matches
852 return matches
854
853
855 def _default_arguments_from_docstring(self, doc):
854 def _default_arguments_from_docstring(self, doc):
@@ -978,7 +977,7 b' class IPCompleter(Completer):'
978
977
979 for namedArg in namedArgs:
978 for namedArg in namedArgs:
980 if namedArg.startswith(text):
979 if namedArg.startswith(text):
981 argMatches.append("%s=" %namedArg)
980 argMatches.append(u"%s=" %namedArg)
982 return argMatches
981 return argMatches
983
982
984 def dict_key_matches(self, text):
983 def dict_key_matches(self, text):
@@ -1164,12 +1163,12 b' class IPCompleter(Completer):'
1164 res = c(event)
1163 res = c(event)
1165 if res:
1164 if res:
1166 # first, try case sensitive match
1165 # first, try case sensitive match
1167 withcase = [r for r in res if r.startswith(text)]
1166 withcase = [cast_unicode_py2(r) for r in res if r.startswith(text)]
1168 if withcase:
1167 if withcase:
1169 return withcase
1168 return withcase
1170 # if none, then case insensitive ones are ok too
1169 # if none, then case insensitive ones are ok too
1171 text_low = text.lower()
1170 text_low = text.lower()
1172 return [r for r in res if r.lower().startswith(text_low)]
1171 return [cast_unicode_py2(r) for r in res if r.lower().startswith(text_low)]
1173 except TryNext:
1172 except TryNext:
1174 pass
1173 pass
1175
1174
@@ -944,7 +944,7 b' def format_display_data(obj, include=None, exclude=None):'
944 """
944 """
945 from IPython.core.interactiveshell import InteractiveShell
945 from IPython.core.interactiveshell import InteractiveShell
946
946
947 InteractiveShell.instance().display_formatter.format(
947 return InteractiveShell.instance().display_formatter.format(
948 obj,
948 obj,
949 include,
949 include,
950 exclude
950 exclude
@@ -1,18 +1,10 b''
1 """ History related magics and functionality """
1 """ History related magics and functionality """
2 #-----------------------------------------------------------------------------
3 # Copyright (C) 2010-2011 The IPython Development Team.
4 #
5 # Distributed under the terms of the BSD License.
6 #
7 # The full license is in the file COPYING.txt, distributed with this software.
8 #-----------------------------------------------------------------------------
9
2
10 #-----------------------------------------------------------------------------
3 # Copyright (c) IPython Development Team.
11 # Imports
4 # Distributed under the terms of the Modified BSD License.
12 #-----------------------------------------------------------------------------
5
13 from __future__ import print_function
6 from __future__ import print_function
14
7
15 # Stdlib imports
16 import atexit
8 import atexit
17 import datetime
9 import datetime
18 import os
10 import os
@@ -26,7 +18,6 b' except ImportError:'
26 sqlite3 = None
18 sqlite3 = None
27 import threading
19 import threading
28
20
29 # Our own packages
30 from traitlets.config.configurable import LoggingConfigurable
21 from traitlets.config.configurable import LoggingConfigurable
31 from decorator import decorator
22 from decorator import decorator
32 from IPython.utils.decorators import undoc
23 from IPython.utils.decorators import undoc
@@ -80,27 +71,52 b' else:'
80 class OperationalError(Exception):
71 class OperationalError(Exception):
81 "Dummy exception when sqlite could not be imported. Should never occur."
72 "Dummy exception when sqlite could not be imported. Should never occur."
82
73
74 # use 16kB as threshold for whether a corrupt history db should be saved
75 # that should be at least 100 entries or so
76 _SAVE_DB_SIZE = 16384
77
83 @decorator
78 @decorator
84 def catch_corrupt_db(f, self, *a, **kw):
79 def catch_corrupt_db(f, self, *a, **kw):
85 """A decorator which wraps HistoryAccessor method calls to catch errors from
80 """A decorator which wraps HistoryAccessor method calls to catch errors from
86 a corrupt SQLite database, move the old database out of the way, and create
81 a corrupt SQLite database, move the old database out of the way, and create
87 a new one.
82 a new one.
83
84 We avoid clobbering larger databases because this may be triggered due to filesystem issues,
85 not just a corrupt file.
88 """
86 """
89 try:
87 try:
90 return f(self, *a, **kw)
88 return f(self, *a, **kw)
91 except (DatabaseError, OperationalError):
89 except (DatabaseError, OperationalError) as e:
92 if os.path.isfile(self.hist_file):
90 self._corrupt_db_counter += 1
93 # Try to move the file out of the way
91 self.log.error("Failed to open SQLite history %s (%s).", self.hist_file, e)
94 base,ext = os.path.splitext(self.hist_file)
92 if self.hist_file != ':memory:':
95 newpath = base + '-corrupt' + ext
93 if self._corrupt_db_counter > self._corrupt_db_limit:
96 os.rename(self.hist_file, newpath)
94 self.hist_file = ':memory:'
95 self.log.error("Failed to load history too many times, history will not be saved.")
96 elif os.path.isfile(self.hist_file):
97 # move the file out of the way
98 base, ext = os.path.splitext(self.hist_file)
99 size = os.stat(self.hist_file).st_size
100 if size >= _SAVE_DB_SIZE:
101 # if there's significant content, avoid clobbering
102 now = datetime.datetime.now().isoformat().replace(':', '.')
103 newpath = base + '-corrupt-' + now + ext
104 # don't clobber previous corrupt backups
105 for i in range(100):
106 if not os.path.isfile(newpath):
107 break
108 else:
109 newpath = base + '-corrupt-' + now + (u'-%i' % i) + ext
110 else:
111 # not much content, possibly empty; don't worry about clobbering
112 # maybe we should just delete it?
113 newpath = base + '-corrupt' + ext
114 os.rename(self.hist_file, newpath)
115 self.log.error("History file was moved to %s and a new file created.", newpath)
97 self.init_db()
116 self.init_db()
98 print("ERROR! History file wasn't a valid SQLite database.",
99 "It was moved to %s" % newpath, "and a new file created.")
100 return []
117 return []
101
102 else:
118 else:
103 # The hist_file is probably :memory: or something else.
119 # Failed with :memory:, something serious is wrong
104 raise
120 raise
105
121
106 class HistoryAccessorBase(LoggingConfigurable):
122 class HistoryAccessorBase(LoggingConfigurable):
@@ -126,6 +142,11 b' class HistoryAccessor(HistoryAccessorBase):'
126 This is intended for use by standalone history tools. IPython shells use
142 This is intended for use by standalone history tools. IPython shells use
127 HistoryManager, below, which is a subclass of this."""
143 HistoryManager, below, which is a subclass of this."""
128
144
145 # counter for init_db retries, so we don't keep trying over and over
146 _corrupt_db_counter = 0
147 # after two failures, fallback on :memory:
148 _corrupt_db_limit = 2
149
129 # String holding the path to the history file
150 # String holding the path to the history file
130 hist_file = Unicode(config=True,
151 hist_file = Unicode(config=True,
131 help="""Path to file to use for SQLite history database.
152 help="""Path to file to use for SQLite history database.
@@ -239,6 +260,8 b' class HistoryAccessor(HistoryAccessorBase):'
239 (session integer, line integer, output text,
260 (session integer, line integer, output text,
240 PRIMARY KEY (session, line))""")
261 PRIMARY KEY (session, line))""")
241 self.db.commit()
262 self.db.commit()
263 # success! reset corrupt db count
264 self._corrupt_db_counter = 0
242
265
243 def writeout_cache(self):
266 def writeout_cache(self):
244 """Overridden by HistoryManager to dump the cache before certain
267 """Overridden by HistoryManager to dump the cache before certain
@@ -57,7 +57,7 b' from IPython.core.prefilter import PrefilterManager'
57 from IPython.core.profiledir import ProfileDir
57 from IPython.core.profiledir import ProfileDir
58 from IPython.core.prompts import PromptManager
58 from IPython.core.prompts import PromptManager
59 from IPython.core.usage import default_banner
59 from IPython.core.usage import default_banner
60 from IPython.testing.skipdoctest import skip_doctest
60 from IPython.testing.skipdoctest import skip_doctest_py2, skip_doctest
61 from IPython.utils import PyColorize
61 from IPython.utils import PyColorize
62 from IPython.utils import io
62 from IPython.utils import io
63 from IPython.utils import py3compat
63 from IPython.utils import py3compat
@@ -1939,6 +1939,7 b' class InteractiveShell(SingletonConfigurable):'
1939 self.set_hook('complete_command', reset_completer, str_key = '%reset')
1939 self.set_hook('complete_command', reset_completer, str_key = '%reset')
1940
1940
1941
1941
1942 @skip_doctest_py2
1942 def complete(self, text, line=None, cursor_pos=None):
1943 def complete(self, text, line=None, cursor_pos=None):
1943 """Return the completed text and a list of completions.
1944 """Return the completed text and a list of completions.
1944
1945
@@ -61,12 +61,12 b' class TimeitResult(object):'
61 """
61 """
62 Object returned by the timeit magic with info about the run.
62 Object returned by the timeit magic with info about the run.
63
63
64 Contain the following attributes :
64 Contains the following attributes :
65
65
66 loops: (int) number of loop done per measurement
66 loops: (int) number of loops done per measurement
67 repeat: (int) number of time the mesurement has been repeated
67 repeat: (int) number of times the measurement has been repeated
68 best: (float) best execusion time / number
68 best: (float) best execution time / number
69 all_runs: (list of float) execusion time of each run (in s)
69 all_runs: (list of float) execution time of each run (in s)
70 compile_time: (float) time of statement compilation (s)
70 compile_time: (float) time of statement compilation (s)
71
71
72 """
72 """
@@ -298,7 +298,7 b' def get_pager_cmd(pager_cmd=None):'
298 Makes some attempts at finding an OS-correct one.
298 Makes some attempts at finding an OS-correct one.
299 """
299 """
300 if os.name == 'posix':
300 if os.name == 'posix':
301 default_pager_cmd = 'less -r' # -r for color control sequences
301 default_pager_cmd = 'less -R' # -R for color control sequences
302 elif os.name in ['nt','dos']:
302 elif os.name in ['nt','dos']:
303 default_pager_cmd = 'type'
303 default_pager_cmd = 'type'
304
304
@@ -308,8 +308,8 b' def get_pager_cmd(pager_cmd=None):'
308 except:
308 except:
309 pager_cmd = default_pager_cmd
309 pager_cmd = default_pager_cmd
310
310
311 if pager_cmd == 'less' and '-r' not in os.environ.get('LESS', ''):
311 if pager_cmd == 'less' and '-r' not in os.environ.get('LESS', '').lower():
312 pager_cmd += ' -r'
312 pager_cmd += ' -R'
313
313
314 return pager_cmd
314 return pager_cmd
315
315
@@ -790,6 +790,7 b' def test_nested_import_module_completer():'
790 _, matches = ip.complete(None, 'import IPython.co', 17)
790 _, matches = ip.complete(None, 'import IPython.co', 17)
791 nt.assert_in('IPython.core', matches)
791 nt.assert_in('IPython.core', matches)
792 nt.assert_not_in('import IPython.core', matches)
792 nt.assert_not_in('import IPython.core', matches)
793 nt.assert_not_in('IPython.display', matches)
793
794
794 def test_import_module_completer():
795 def test_import_module_completer():
795 ip = get_ipython()
796 ip = get_ipython()
@@ -99,6 +99,21 b' class NonAsciiTest(unittest.TestCase):'
99 with tt.AssertPrints("ZeroDivisionError"):
99 with tt.AssertPrints("ZeroDivisionError"):
100 with tt.AssertPrints(u'дбИЖ', suppress=False):
100 with tt.AssertPrints(u'дбИЖ', suppress=False):
101 ip.run_cell('fail()')
101 ip.run_cell('fail()')
102
103 def test_nonascii_msg(self):
104 cell = u"raise Exception('é')"
105 expected = u"Exception('é')"
106 ip.run_cell("%xmode plain")
107 with tt.AssertPrints(expected):
108 ip.run_cell(cell)
109
110 ip.run_cell("%xmode verbose")
111 with tt.AssertPrints(expected):
112 ip.run_cell(cell)
113
114 ip.run_cell("%xmode context")
115 with tt.AssertPrints(expected):
116 ip.run_cell(cell)
102
117
103
118
104 class NestedGenExprTestCase(unittest.TestCase):
119 class NestedGenExprTestCase(unittest.TestCase):
@@ -709,10 +709,10 b' class ListTB(TBTools):'
709 have_filedata = False
709 have_filedata = False
710 Colors = self.Colors
710 Colors = self.Colors
711 list = []
711 list = []
712 stype = Colors.excName + etype.__name__ + Colors.Normal
712 stype = py3compat.cast_unicode(Colors.excName + etype.__name__ + Colors.Normal)
713 if value is None:
713 if value is None:
714 # Not sure if this can still happen in Python 2.6 and above
714 # Not sure if this can still happen in Python 2.6 and above
715 list.append(py3compat.cast_unicode(stype) + '\n')
715 list.append(stype + '\n')
716 else:
716 else:
717 if issubclass(etype, SyntaxError):
717 if issubclass(etype, SyntaxError):
718 have_filedata = True
718 have_filedata = True
@@ -752,10 +752,10 b' class ListTB(TBTools):'
752 except Exception:
752 except Exception:
753 s = self._some_str(value)
753 s = self._some_str(value)
754 if s:
754 if s:
755 list.append('%s%s:%s %s\n' % (str(stype), Colors.excName,
755 list.append('%s%s:%s %s\n' % (stype, Colors.excName,
756 Colors.Normal, s))
756 Colors.Normal, s))
757 else:
757 else:
758 list.append('%s\n' % str(stype))
758 list.append('%s\n' % stype)
759
759
760 # sync with user hooks
760 # sync with user hooks
761 if have_filedata:
761 if have_filedata:
@@ -793,9 +793,9 b' class ListTB(TBTools):'
793 def _some_str(self, value):
793 def _some_str(self, value):
794 # Lifted from traceback.py
794 # Lifted from traceback.py
795 try:
795 try:
796 return str(value)
796 return py3compat.cast_unicode(str(value))
797 except:
797 except:
798 return '<unprintable %s object>' % type(value).__name__
798 return u'<unprintable %s object>' % type(value).__name__
799
799
800
800
801 #----------------------------------------------------------------------------
801 #----------------------------------------------------------------------------
@@ -1432,6 +1432,7 b' class SyntaxTB(ListTB):'
1432 newtext = ulinecache.getline(value.filename, value.lineno)
1432 newtext = ulinecache.getline(value.filename, value.lineno)
1433 if newtext:
1433 if newtext:
1434 value.text = newtext
1434 value.text = newtext
1435 self.last_syntax_error = value
1435 return super(SyntaxTB, self).structured_traceback(etype, value, elist,
1436 return super(SyntaxTB, self).structured_traceback(etype, value, elist,
1436 tb_offset=tb_offset, context=context)
1437 tb_offset=tb_offset, context=context)
1437
1438
@@ -41,7 +41,7 b' class Audio(DisplayObject):'
41 filename : unicode
41 filename : unicode
42 Path to a local file to load the data from.
42 Path to a local file to load the data from.
43 embed : boolean
43 embed : boolean
44 Should the image data be embedded using a data URI (True) or should
44 Should the audio data be embedded using a data URI (True) or should
45 the original source be referenced. Set this to True if you want the
45 the original source be referenced. Set this to True if you want the
46 audio to playable later with no internet connection in the notebook.
46 audio to playable later with no internet connection in the notebook.
47
47
@@ -15,7 +15,7 b' from IPython.core import ultratb, compilerop'
15 from IPython.core.magic import Magics, magics_class, line_magic
15 from IPython.core.magic import Magics, magics_class, line_magic
16 from IPython.core.interactiveshell import DummyMod
16 from IPython.core.interactiveshell import DummyMod
17 from IPython.core.interactiveshell import InteractiveShell
17 from IPython.core.interactiveshell import InteractiveShell
18 from IPython.terminal.interactiveshell import TerminalInteractiveShell
18 from IPython.terminal.ptshell import TerminalInteractiveShell
19 from IPython.terminal.ipapp import load_default_config
19 from IPython.terminal.ipapp import load_default_config
20
20
21 from traitlets import Bool, CBool, Unicode
21 from traitlets import Bool, CBool, Unicode
@@ -136,6 +136,9 b' class InteractiveShellEmbed(TerminalInteractiveShell):'
136 else:
136 else:
137 self.old_banner2 = ''
137 self.old_banner2 = ''
138
138
139 if self.display_banner:
140 self.show_banner()
141
139 # Call the embedding code with a stack depth of 1 so it can skip over
142 # Call the embedding code with a stack depth of 1 so it can skip over
140 # our call and get the original caller's namespaces.
143 # our call and get the original caller's namespaces.
141 self.mainloop(local_ns, module, stack_depth=stack_depth,
144 self.mainloop(local_ns, module, stack_depth=stack_depth,
@@ -182,6 +185,9 b' class InteractiveShellEmbed(TerminalInteractiveShell):'
182 module = DummyMod()
185 module = DummyMod()
183 module.__dict__ = global_ns
186 module.__dict__ = global_ns
184
187
188 if (display_banner is not None):
189 warnings.warn("The display_banner parameter is deprecated.", DeprecationWarning)
190
185 # Get locals and globals from caller
191 # Get locals and globals from caller
186 if ((local_ns is None or module is None or compile_flags is None)
192 if ((local_ns is None or module is None or compile_flags is None)
187 and self.default_user_namespaces):
193 and self.default_user_namespaces):
@@ -191,7 +197,14 b' class InteractiveShellEmbed(TerminalInteractiveShell):'
191 local_ns = call_frame.f_locals
197 local_ns = call_frame.f_locals
192 if module is None:
198 if module is None:
193 global_ns = call_frame.f_globals
199 global_ns = call_frame.f_globals
194 module = sys.modules[global_ns['__name__']]
200 try:
201 module = sys.modules[global_ns['__name__']]
202 except KeyError:
203 warnings.warn("Failed to get module %s" % \
204 global_ns.get('__name__', 'unknown module')
205 )
206 module = DummyMod()
207 module.__dict__ = global_ns
195 if compile_flags is None:
208 if compile_flags is None:
196 compile_flags = (call_frame.f_code.co_flags &
209 compile_flags = (call_frame.f_code.co_flags &
197 compilerop.PyCF_MASK)
210 compilerop.PyCF_MASK)
@@ -226,7 +239,7 b' class InteractiveShellEmbed(TerminalInteractiveShell):'
226 self.set_completer_frame()
239 self.set_completer_frame()
227
240
228 with self.builtin_trap, self.display_trap:
241 with self.builtin_trap, self.display_trap:
229 self.interact(display_banner=display_banner)
242 self.interact()
230
243
231 # now, purge out the local namespace of IPython's hidden variables.
244 # now, purge out the local namespace of IPython's hidden variables.
232 if local_ns is not None:
245 if local_ns is not None:
@@ -4,18 +4,22 b' from __future__ import print_function'
4 import os
4 import os
5 import sys
5 import sys
6 import signal
6 import signal
7 import unicodedata
8 from warnings import warn
9 from wcwidth import wcwidth
7
10
11 from IPython.core.error import TryNext
8 from IPython.core.interactiveshell import InteractiveShell
12 from IPython.core.interactiveshell import InteractiveShell
9 from IPython.utils.py3compat import PY3, cast_unicode_py2, input
13 from IPython.utils.py3compat import PY3, cast_unicode_py2, input
10 from IPython.utils.terminal import toggle_set_term_title, set_term_title
14 from IPython.utils.terminal import toggle_set_term_title, set_term_title
11 from IPython.utils.process import abbrev_cwd
15 from IPython.utils.process import abbrev_cwd
12 from traitlets import Bool, Unicode, Dict
16 from traitlets import Bool, CBool, Unicode, Dict, Integer
13
17
14 from prompt_toolkit.completion import Completer, Completion
18 from prompt_toolkit.completion import Completer, Completion
15 from prompt_toolkit.enums import DEFAULT_BUFFER
19 from prompt_toolkit.enums import DEFAULT_BUFFER, SEARCH_BUFFER
16 from prompt_toolkit.filters import HasFocus, HasSelection, Condition
20 from prompt_toolkit.filters import HasFocus, HasSelection, Condition
17 from prompt_toolkit.history import InMemoryHistory
21 from prompt_toolkit.history import InMemoryHistory
18 from prompt_toolkit.shortcuts import create_prompt_application, create_eventloop
22 from prompt_toolkit.shortcuts import create_prompt_application, create_eventloop, create_prompt_layout
19 from prompt_toolkit.interface import CommandLineInterface
23 from prompt_toolkit.interface import CommandLineInterface
20 from prompt_toolkit.key_binding.manager import KeyBindingManager
24 from prompt_toolkit.key_binding.manager import KeyBindingManager
21 from prompt_toolkit.key_binding.vi_state import InputMode
25 from prompt_toolkit.key_binding.vi_state import InputMode
@@ -23,9 +27,9 b' from prompt_toolkit.key_binding.bindings.vi import ViStateFilter'
23 from prompt_toolkit.keys import Keys
27 from prompt_toolkit.keys import Keys
24 from prompt_toolkit.layout.lexers import Lexer
28 from prompt_toolkit.layout.lexers import Lexer
25 from prompt_toolkit.layout.lexers import PygmentsLexer
29 from prompt_toolkit.layout.lexers import PygmentsLexer
26 from prompt_toolkit.styles import PygmentsStyle
30 from prompt_toolkit.styles import PygmentsStyle, DynamicStyle
27
31
28 from pygments.styles import get_style_by_name
32 from pygments.styles import get_style_by_name, get_all_styles
29 from pygments.lexers import Python3Lexer, BashLexer, PythonLexer
33 from pygments.lexers import Python3Lexer, BashLexer, PythonLexer
30 from pygments.token import Token
34 from pygments.token import Token
31
35
@@ -33,7 +37,6 b' from .pt_inputhooks import get_inputhook_func'
33 from .interactiveshell import get_default_editor, TerminalMagics
37 from .interactiveshell import get_default_editor, TerminalMagics
34
38
35
39
36
37 class IPythonPTCompleter(Completer):
40 class IPythonPTCompleter(Completer):
38 """Adaptor to provide IPython completions to prompt_toolkit"""
41 """Adaptor to provide IPython completions to prompt_toolkit"""
39 def __init__(self, ipy_completer):
42 def __init__(self, ipy_completer):
@@ -49,6 +52,22 b' class IPythonPTCompleter(Completer):'
49 )
52 )
50 start_pos = -len(used)
53 start_pos = -len(used)
51 for m in matches:
54 for m in matches:
55 m = unicodedata.normalize('NFC', m)
56
57 # When the first character of the completion has a zero length,
58 # then it's probably a decomposed unicode character. E.g. caused by
59 # the "\dot" completion. Try to compose again with the previous
60 # character.
61 if wcwidth(m[0]) == 0:
62 if document.cursor_position + start_pos > 0:
63 char_before = document.text[document.cursor_position + start_pos - 1]
64 m = unicodedata.normalize('NFC', char_before + m)
65
66 # Yield the modified completion instead, if this worked.
67 if wcwidth(m[0:1]) == 1:
68 yield Completion(m, start_position=start_pos - 1)
69 continue
70
52 # TODO: Use Jedi to determine meta_text
71 # TODO: Use Jedi to determine meta_text
53 # (Jedi currently has a bug that results in incorrect information.)
72 # (Jedi currently has a bug that results in incorrect information.)
54 # meta_text = ''
73 # meta_text = ''
@@ -74,8 +93,23 b' class IPythonPTLexer(Lexer):'
74 class TerminalInteractiveShell(InteractiveShell):
93 class TerminalInteractiveShell(InteractiveShell):
75 colors_force = True
94 colors_force = True
76
95
96 space_for_menu = Integer(6, config=True, help='Number of line at the bottom of the screen '
97 'to reserve for the completion menu')
98
99 def _space_for_menu_changed(self, old, new):
100 self._update_layout()
101
77 pt_cli = None
102 pt_cli = None
78
103
104 autoedit_syntax = CBool(False, config=True,
105 help="auto editing of files with syntax errors.")
106
107 confirm_exit = CBool(True, config=True,
108 help="""
109 Set to confirm when you try to exit IPython with an EOF (Control-D
110 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
111 you can force a direct exit without any confirmation.""",
112 )
79 vi_mode = Bool(False, config=True,
113 vi_mode = Bool(False, config=True,
80 help="Use vi style keybindings at the prompt",
114 help="Use vi style keybindings at the prompt",
81 )
115 )
@@ -84,10 +118,13 b' class TerminalInteractiveShell(InteractiveShell):'
84 help="Enable mouse support in the prompt"
118 help="Enable mouse support in the prompt"
85 )
119 )
86
120
87 highlighting_style = Unicode('', config=True,
121 highlighting_style = Unicode('default', config=True,
88 help="The name of a Pygments style to use for syntax highlighting"
122 help="The name of a Pygments style to use for syntax highlighting: \n %s" % ', '.join(get_all_styles())
89 )
123 )
90
124
125 def _highlighting_style_changed(self, old, new):
126 self._style = self._make_style_from_name(self.highlighting_style)
127
91 highlighting_style_overrides = Dict(config=True,
128 highlighting_style_overrides = Dict(config=True,
92 help="Override highlighting format for specific tokens"
129 help="Override highlighting format for specific tokens"
93 )
130 )
@@ -158,6 +195,13 b' class TerminalInteractiveShell(InteractiveShell):'
158 def _(event):
195 def _(event):
159 event.current_buffer.reset()
196 event.current_buffer.reset()
160
197
198 @kbmanager.registry.add_binding(Keys.ControlC, filter=HasFocus(SEARCH_BUFFER))
199 def _(event):
200 if event.current_buffer.document.text:
201 event.current_buffer.reset()
202 else:
203 event.cli.push_focus(DEFAULT_BUFFER)
204
161 supports_suspend = Condition(lambda cli: hasattr(signal, 'SIGTSTP'))
205 supports_suspend = Condition(lambda cli: hasattr(signal, 'SIGTSTP'))
162
206
163 @kbmanager.registry.add_binding(Keys.ControlZ, filter=supports_suspend)
207 @kbmanager.registry.add_binding(Keys.ControlZ, filter=supports_suspend)
@@ -189,13 +233,33 b' class TerminalInteractiveShell(InteractiveShell):'
189 if cell and (cell != last_cell):
233 if cell and (cell != last_cell):
190 history.append(cell)
234 history.append(cell)
191
235
236 self._style = self._make_style_from_name(self.highlighting_style)
237 style = DynamicStyle(lambda: self._style)
238
239 self._app = create_prompt_application(
240 key_bindings_registry=kbmanager.registry,
241 history=history,
242 completer=IPythonPTCompleter(self.Completer),
243 enable_history_search=True,
244 style=style,
245 mouse_support=self.mouse_support,
246 **self._layout_options()
247 )
248 self.pt_cli = CommandLineInterface(self._app,
249 eventloop=create_eventloop(self.inputhook))
250
251 def _make_style_from_name(self, name):
252 """
253 Small wrapper that make an IPython compatible style from a style name
254
255 We need that to add style for prompt ... etc.
256 """
257 style_cls = get_style_by_name(name)
192 style_overrides = {
258 style_overrides = {
193 Token.Prompt: '#009900',
259 Token.Prompt: '#009900',
194 Token.PromptNum: '#00ff00 bold',
260 Token.PromptNum: '#00ff00 bold',
195 }
261 }
196 if self.highlighting_style:
262 if name is 'default':
197 style_cls = get_style_by_name(self.highlighting_style)
198 else:
199 style_cls = get_style_by_name('default')
263 style_cls = get_style_by_name('default')
200 # The default theme needs to be visible on both a dark background
264 # The default theme needs to be visible on both a dark background
201 # and a light background, because we can't tell what the terminal
265 # and a light background, because we can't tell what the terminal
@@ -212,21 +276,27 b' class TerminalInteractiveShell(InteractiveShell):'
212 style = PygmentsStyle.from_defaults(pygments_style_cls=style_cls,
276 style = PygmentsStyle.from_defaults(pygments_style_cls=style_cls,
213 style_dict=style_overrides)
277 style_dict=style_overrides)
214
278
215 app = create_prompt_application(multiline=True,
279 return style
216 lexer=IPythonPTLexer(),
280
217 get_prompt_tokens=self.get_prompt_tokens,
281 def _layout_options(self):
218 get_continuation_tokens=self.get_continuation_tokens,
282 """
219 key_bindings_registry=kbmanager.registry,
283 Return the current layout option for the current Terminal InteractiveShell
220 history=history,
284 """
221 completer=IPythonPTCompleter(self.Completer),
285 return {
222 enable_history_search=True,
286 'lexer':IPythonPTLexer(),
223 style=style,
287 'reserve_space_for_menu':self.space_for_menu,
224 mouse_support=self.mouse_support,
288 'get_prompt_tokens':self.get_prompt_tokens,
225 reserve_space_for_menu=6,
289 'get_continuation_tokens':self.get_continuation_tokens,
226 )
290 'multiline':True,
291 }
227
292
228 self.pt_cli = CommandLineInterface(app,
293
229 eventloop=create_eventloop(self.inputhook))
294 def _update_layout(self):
295 """
296 Ask for a re computation of the application layout, if for example ,
297 some configuration options have changed.
298 """
299 self._app.layout = create_prompt_layout(**self._layout_options())
230
300
231 def prompt_for_code(self):
301 def prompt_for_code(self):
232 document = self.pt_cli.run(pre_run=self.pre_prompt)
302 document = self.pt_cli.run(pre_run=self.pre_prompt)
@@ -286,12 +356,15 b' class TerminalInteractiveShell(InteractiveShell):'
286 try:
356 try:
287 code = self.prompt_for_code()
357 code = self.prompt_for_code()
288 except EOFError:
358 except EOFError:
289 if self.ask_yes_no('Do you really want to exit ([y]/n)?','y','n'):
359 if (not self.confirm_exit) \
360 or self.ask_yes_no('Do you really want to exit ([y]/n)?','y','n'):
290 self.ask_exit()
361 self.ask_exit()
291
362
292 else:
363 else:
293 if code:
364 if code:
294 self.run_cell(code, store_history=True)
365 self.run_cell(code, store_history=True)
366 if self.autoedit_syntax and self.SyntaxTB.last_syntax_error:
367 self.edit_syntax_error()
295
368
296 def mainloop(self):
369 def mainloop(self):
297 # An extra layer of protection in case someone mashing Ctrl-C breaks
370 # An extra layer of protection in case someone mashing Ctrl-C breaks
@@ -314,5 +387,69 b' class TerminalInteractiveShell(InteractiveShell):'
314 else:
387 else:
315 self._inputhook = None
388 self._inputhook = None
316
389
390 # Methods to support auto-editing of SyntaxErrors:
391
392 def edit_syntax_error(self):
393 """The bottom half of the syntax error handler called in the main loop.
394
395 Loop until syntax error is fixed or user cancels.
396 """
397
398 while self.SyntaxTB.last_syntax_error:
399 # copy and clear last_syntax_error
400 err = self.SyntaxTB.clear_err_state()
401 if not self._should_recompile(err):
402 return
403 try:
404 # may set last_syntax_error again if a SyntaxError is raised
405 self.safe_execfile(err.filename, self.user_ns)
406 except:
407 self.showtraceback()
408 else:
409 try:
410 with open(err.filename) as f:
411 # This should be inside a display_trap block and I
412 # think it is.
413 sys.displayhook(f.read())
414 except:
415 self.showtraceback()
416
417 def _should_recompile(self, e):
418 """Utility routine for edit_syntax_error"""
419
420 if e.filename in ('<ipython console>', '<input>', '<string>',
421 '<console>', '<BackgroundJob compilation>',
422 None):
423 return False
424 try:
425 if (self.autoedit_syntax and
426 not self.ask_yes_no(
427 'Return to editor to correct syntax error? '
428 '[Y/n] ', 'y')):
429 return False
430 except EOFError:
431 return False
432
433 def int0(x):
434 try:
435 return int(x)
436 except TypeError:
437 return 0
438
439 # always pass integer line and offset values to editor hook
440 try:
441 self.hooks.fix_error_editor(e.filename,
442 int0(e.lineno), int0(e.offset),
443 e.msg)
444 except TryNext:
445 warn('Could not open editor')
446 return False
447 return True
448
449 # Run !system commands directly, not through pipes, so terminal programs
450 # work correctly.
451 system = InteractiveShell.system_raw
452
453
317 if __name__ == '__main__':
454 if __name__ == '__main__':
318 TerminalInteractiveShell.instance().interact()
455 TerminalInteractiveShell.instance().interact()
@@ -25,8 +25,6 b' import logging'
25 import os
25 import os
26 import re
26 import re
27 import sys
27 import sys
28 import traceback
29 import unittest
30
28
31 from testpath import modified_env
29 from testpath import modified_env
32
30
@@ -41,10 +39,9 b' from doctest import (REPORTING_FLAGS, REPORT_ONLY_FIRST_FAILURE,'
41 linecache)
39 linecache)
42
40
43 # Third-party modules
41 # Third-party modules
44 import nose.core
45
42
46 from nose.plugins import doctests, Plugin
43 from nose.plugins import doctests, Plugin
47 from nose.util import anyp, getpackage, test_address, resolve_name, tolist
44 from nose.util import anyp, tolist
48
45
49 # Our own imports
46 # Our own imports
50 from IPython.utils.py3compat import builtin_mod, PY3, getcwd
47 from IPython.utils.py3compat import builtin_mod, PY3, getcwd
@@ -143,7 +140,7 b' class DocTestFinder(doctest.DocTestFinder):'
143 # doctests in extension modules.
140 # doctests in extension modules.
144
141
145 # Local shorthands
142 # Local shorthands
146 from inspect import isroutine, isclass, ismodule
143 from inspect import isroutine, isclass
147
144
148 # Look for tests in a module's contained objects.
145 # Look for tests in a module's contained objects.
149 if inspect.ismodule(obj) and self._recurse:
146 if inspect.ismodule(obj) and self._recurse:
@@ -36,3 +36,8 b' def skip_doctest_py3(f):'
36 """Decorator - skip the doctest under Python 3."""
36 """Decorator - skip the doctest under Python 3."""
37 f.skip_doctest = (sys.version_info[0] >= 3)
37 f.skip_doctest = (sys.version_info[0] >= 3)
38 return f
38 return f
39
40 def skip_doctest_py2(f):
41 """Decorator - skip the doctest under Python 3."""
42 f.skip_doctest = (sys.version_info[0] < 3)
43 return f
@@ -9,22 +9,18 b' Authors:'
9 * Alexander Belchenko (e-mail: bialix AT ukr.net)
9 * Alexander Belchenko (e-mail: bialix AT ukr.net)
10 """
10 """
11
11
12 #-----------------------------------------------------------------------------
12 # Copyright (c) IPython Development Team.
13 # Copyright (C) 2008-2011 The IPython Development Team
13 # Distributed under the terms of the Modified BSD License.
14 #
15 # Distributed under the terms of the BSD License. The full license is in
16 # the file COPYING, distributed as part of this software.
17 #-----------------------------------------------------------------------------
18
19 #-----------------------------------------------------------------------------
20 # Imports
21 #-----------------------------------------------------------------------------
22
14
23 import os
15 import os
24 import struct
16 import struct
25 import sys
17 import sys
26 import warnings
18 import warnings
27 import backports.shutil_get_terminal_size
19 try:
20 from shutil import get_terminal_size as _get_terminal_size
21 except ImportError:
22 # use backport on Python 2
23 from backports.shutil_get_terminal_size import get_terminal_size as _get_terminal_size
28
24
29 from . import py3compat
25 from . import py3compat
30
26
@@ -122,4 +118,4 b' def freeze_term_title():'
122
118
123
119
124 def get_terminal_size(defaultx=80, defaulty=25):
120 def get_terminal_size(defaultx=80, defaulty=25):
125 return backports.shutil_get_terminal_size.get_terminal_size((defaultx, defaulty))
121 return _get_terminal_size((defaultx, defaulty))
@@ -19,7 +19,11 b' import random'
19 import sys
19 import sys
20
20
21 import nose.tools as nt
21 import nose.tools as nt
22 import path
22 try:
23 from pathlib import Path
24 except ImportError:
25 # Python 2 backport
26 from pathlib2 import Path
23
27
24 from IPython.utils import text
28 from IPython.utils import text
25
29
@@ -207,7 +211,7 b' def test_LSString():'
207 nt.assert_equal(lss.l, ['abc', 'def'])
211 nt.assert_equal(lss.l, ['abc', 'def'])
208 nt.assert_equal(lss.s, 'abc def')
212 nt.assert_equal(lss.s, 'abc def')
209 lss = text.LSString(os.getcwd())
213 lss = text.LSString(os.getcwd())
210 nt.assert_is_instance(lss.p[0], path.path)
214 nt.assert_is_instance(lss.p[0], Path)
211
215
212 def test_SList():
216 def test_SList():
213 sl = text.SList(['a 11', 'b 1', 'a 2'])
217 sl = text.SList(['a 11', 'b 1', 'a 2'])
@@ -14,6 +14,11 b' import re'
14 import sys
14 import sys
15 import textwrap
15 import textwrap
16 from string import Formatter
16 from string import Formatter
17 try:
18 from pathlib import Path
19 except ImportError:
20 # Python 2 backport
21 from pathlib2 import Path
17
22
18 from IPython.testing.skipdoctest import skip_doctest_py3, skip_doctest
23 from IPython.testing.skipdoctest import skip_doctest_py3, skip_doctest
19 from IPython.utils import py3compat
24 from IPython.utils import py3compat
@@ -64,11 +69,10 b' class LSString(str):'
64 n = nlstr = property(get_nlstr)
69 n = nlstr = property(get_nlstr)
65
70
66 def get_paths(self):
71 def get_paths(self):
67 from path import path
68 try:
72 try:
69 return self.__paths
73 return self.__paths
70 except AttributeError:
74 except AttributeError:
71 self.__paths = [path(p) for p in self.split('\n') if os.path.exists(p)]
75 self.__paths = [Path(p) for p in self.split('\n') if os.path.exists(p)]
72 return self.__paths
76 return self.__paths
73
77
74 p = paths = property(get_paths)
78 p = paths = property(get_paths)
@@ -123,11 +127,10 b' class SList(list):'
123 n = nlstr = property(get_nlstr)
127 n = nlstr = property(get_nlstr)
124
128
125 def get_paths(self):
129 def get_paths(self):
126 from path import path
127 try:
130 try:
128 return self.__paths
131 return self.__paths
129 except AttributeError:
132 except AttributeError:
130 self.__paths = [path(p) for p in self if os.path.exists(p)]
133 self.__paths = [Path(p) for p in self if os.path.exists(p)]
131 return self.__paths
134 return self.__paths
132
135
133 p = paths = property(get_paths)
136 p = paths = property(get_paths)
@@ -28,7 +28,7 b' these manuals. If you have Sphinx installed, you can build them by typing'
28 See the `install page <http://ipython.org/install.html>`__ to install IPython.
28 See the `install page <http://ipython.org/install.html>`__ to install IPython.
29
29
30 The Notebook, Qt console and a number of other pieces are now parts of *Jupyter*.
30 The Notebook, Qt console and a number of other pieces are now parts of *Jupyter*.
31 See the `Jupyter installation docs <http://jupyter.readthedocs.org/en/latest/install.html>`__
31 See the `Jupyter installation docs <http://jupyter.readthedocs.io/en/latest/install.html>`__
32 if you want to use these.
32 if you want to use these.
33
33
34 Officially, IPython requires Python version 2.7, or 3.3 and above.
34 Officially, IPython requires Python version 2.7, or 3.3 and above.
@@ -22,7 +22,7 b" ON_RTD = os.environ.get('READTHEDOCS', None) == 'True'"
22 if ON_RTD:
22 if ON_RTD:
23 # Mock the presence of matplotlib, which we don't have on RTD
23 # Mock the presence of matplotlib, which we don't have on RTD
24 # see
24 # see
25 # http://read-the-docs.readthedocs.org/en/latest/faq.html
25 # http://read-the-docs.readthedocs.io/en/latest/faq.html
26 tags.add('rtd')
26 tags.add('rtd')
27
27
28 # RTD doesn't use the Makefile, so re-run autogen_{things}.py here.
28 # RTD doesn't use the Makefile, so re-run autogen_{things}.py here.
@@ -201,12 +201,12 b' html_additional_pages = {'
201 # Output file base name for HTML help builder.
201 # Output file base name for HTML help builder.
202 htmlhelp_basename = 'ipythondoc'
202 htmlhelp_basename = 'ipythondoc'
203
203
204 intersphinx_mapping = {'python': ('http://docs.python.org/2/', None),
204 intersphinx_mapping = {'python': ('http://docs.python.org/3/', None),
205 'rpy2': ('http://rpy.sourceforge.net/rpy2/doc-2.4/html/', None),
205 'rpy2': ('http://rpy.sourceforge.net/rpy2/doc-2.4/html/', None),
206 'traitlets': ('http://traitlets.readthedocs.org/en/latest/', None),
206 'traitlets': ('http://traitlets.readthedocs.io/en/latest/', None),
207 'jupyterclient': ('http://jupyter-client.readthedocs.org/en/latest/', None),
207 'jupyterclient': ('http://jupyter-client.readthedocs.io/en/latest/', None),
208 'ipyparallel': ('http://ipyparallel.readthedocs.org/en/latest/', None),
208 'ipyparallel': ('http://ipyparallel.readthedocs.io/en/latest/', None),
209 'jupyter': ('http://jupyter.readthedocs.org/en/latest/', None),
209 'jupyter': ('http://jupyter.readthedocs.io/en/latest/', None),
210 }
210 }
211
211
212 # Options for LaTeX output
212 # Options for LaTeX output
@@ -19,4 +19,4 b" Developer's guide for third party tools and libraries"
19 lexer
19 lexer
20 pycompat
20 pycompat
21 config
21 config
22 inputhook_app No newline at end of file
22 inputhook_app
@@ -7,7 +7,7 b' You can now re-use the kernel machinery in IPython to easily make new kernels.'
7 This is useful for languages that have Python bindings, such as `Octave
7 This is useful for languages that have Python bindings, such as `Octave
8 <http://www.gnu.org/software/octave/>`_ (via
8 <http://www.gnu.org/software/octave/>`_ (via
9 `Oct2Py <http://blink1073.github.io/oct2py/docs/index.html>`_), or languages
9 `Oct2Py <http://blink1073.github.io/oct2py/docs/index.html>`_), or languages
10 where the REPL can be controlled in a tty using `pexpect <http://pexpect.readthedocs.org/en/latest/>`_,
10 where the REPL can be controlled in a tty using `pexpect <http://pexpect.readthedocs.io/en/latest/>`_,
11 such as bash.
11 such as bash.
12
12
13 .. seealso::
13 .. seealso::
@@ -27,10 +27,10 b' Contents'
27
27
28 .. seealso::
28 .. seealso::
29
29
30 `Jupyter documentation <http://jupyter.readthedocs.org/en/latest/>`__
30 `Jupyter documentation <http://jupyter.readthedocs.io/en/latest/>`__
31 The Notebook code and many other pieces formerly in IPython are now parts
31 The Notebook code and many other pieces formerly in IPython are now parts
32 of Project Jupyter.
32 of Project Jupyter.
33 `ipyparallel documentation <http://ipyparallel.readthedocs.org/en/latest/>`__
33 `ipyparallel documentation <http://ipyparallel.readthedocs.io/en/latest/>`__
34 Formerly ``IPython.parallel``.
34 Formerly ``IPython.parallel``.
35
35
36
36
@@ -2,7 +2,7 b' IPython requires Python 2.7 or \xe2\x89\xa5 3.3.'
2
2
3 .. seealso::
3 .. seealso::
4
4
5 `Installing Jupyter <http://jupyter.readthedocs.org/en/latest/install.html>`__
5 `Installing Jupyter <http://jupyter.readthedocs.io/en/latest/install.html>`__
6 The Notebook, nbconvert, and many other former pieces of IPython are now
6 The Notebook, nbconvert, and many other former pieces of IPython are now
7 part of Project Jupyter.
7 part of Project Jupyter.
8
8
@@ -15,4 +15,4 b' Using IPython for interactive work'
15 .. seealso::
15 .. seealso::
16
16
17 `A Qt Console for Jupyter <http://jupyter.org/qtconsole/>`__
17 `A Qt Console for Jupyter <http://jupyter.org/qtconsole/>`__
18 `The Jupyter Notebook <http://jupyter-notebook.readthedocs.org/en/latest/>`__
18 `The Jupyter Notebook <http://jupyter-notebook.readthedocs.io/en/latest/>`__
@@ -219,7 +219,7 b' different numbers which correspond to the Process ID of the kernel.'
219
219
220 You can read more about using `ipython qtconsole
220 You can read more about using `ipython qtconsole
221 <http://jupyter.org/qtconsole/>`_, and
221 <http://jupyter.org/qtconsole/>`_, and
222 `ipython notebook <http://jupyter-notebook.readthedocs.org/en/latest/>`_. There
222 `ipython notebook <http://jupyter-notebook.readthedocs.io/en/latest/>`_. There
223 is also a :ref:`message spec <messaging>` which documents the protocol for
223 is also a :ref:`message spec <messaging>` which documents the protocol for
224 communication between kernels
224 communication between kernels
225 and clients.
225 and clients.
@@ -1000,7 +1000,7 b' Pull Requests (793):'
1000 * :ghpull:`2274`: CLN: Use name to id mapping of notebooks instead of searching.
1000 * :ghpull:`2274`: CLN: Use name to id mapping of notebooks instead of searching.
1001 * :ghpull:`2270`: SSHLauncher tweaks
1001 * :ghpull:`2270`: SSHLauncher tweaks
1002 * :ghpull:`2269`: add missing location when disambiguating controller IP
1002 * :ghpull:`2269`: add missing location when disambiguating controller IP
1003 * :ghpull:`2263`: Allow docs to build on http://readthedocs.org/
1003 * :ghpull:`2263`: Allow docs to build on http://readthedocs.io/
1004 * :ghpull:`2256`: Adding data publication example notebook.
1004 * :ghpull:`2256`: Adding data publication example notebook.
1005 * :ghpull:`2255`: better flush iopub with AsyncResults
1005 * :ghpull:`2255`: better flush iopub with AsyncResults
1006 * :ghpull:`2261`: Fix: longest_substr([]) -> ''
1006 * :ghpull:`2261`: Fix: longest_substr([]) -> ''
@@ -3,9 +3,33 b''
3 Issues closed in the 4.x development cycle
3 Issues closed in the 4.x development cycle
4 ==========================================
4 ==========================================
5
5
6 Issues closed in 4.1
6
7 Issues closed in 4.2
7 --------------------
8 --------------------
8
9
10 GitHub stats for 2015/02/02 - 2016/04/20 (since 4.1)
11
12 These lists are automatically generated, and may be incomplete or contain duplicates.
13
14 We closed 10 issues and merged 22 pull requests.
15 The full list can be seen `on GitHub <https://github.com/ipython/ipython/issues?q=milestone%3A4.2+>`__
16
17 The following 10 authors contributed 27 commits.
18
19 * Benjamin Ragan-Kelley
20 * Carlos Cordoba
21 * Gökhan Karabulut
22 * Jonas Rauber
23 * Matthias Bussonnier
24 * Paul Ivanov
25 * Sebastian Bank
26 * Thomas A Caswell
27 * Thomas Kluyver
28 * Vincent Woo
29
30
31 Issues closed in 4.1
32 --------------------
9
33
10 GitHub stats for 2015/08/12 - 2016/02/02 (since 4.0.0)
34 GitHub stats for 2015/08/12 - 2016/02/02 (since 4.0.0)
11
35
@@ -2,6 +2,19 b''
2 4.x Series
2 4.x Series
3 ============
3 ============
4
4
5 IPython 4.2
6 ===========
7
8 IPython 4.2 (April, 2016) includes various bugfixes and improvements over 4.1.
9
10 - Fix ``ipython -i`` on errors, which was broken in 4.1.
11 - The delay meant to highlight deprecated commands that have moved to jupyter has been removed.
12 - Improve compatibility with future versions of traitlets and matplotlib.
13 - Use stdlib :func:`python:shutil.get_terminal_size` to measure terminal width when displaying tracebacks
14 (provided by ``backports.shutil_get_terminal_size`` on Python 2).
15
16 You can see the rest `on GitHub <https://github.com/ipython/ipython/issues?q=milestone%3A4.2>`__.
17
5
18
6 IPython 4.1
19 IPython 4.1
7 ===========
20 ===========
@@ -34,8 +47,8 b' Released August, 2015'
34
47
35 IPython 4.0 is the first major release after the Big Split.
48 IPython 4.0 is the first major release after the Big Split.
36 IPython no longer contains the notebook, qtconsole, etc. which have moved to
49 IPython no longer contains the notebook, qtconsole, etc. which have moved to
37 `jupyter <https://jupyter.readthedocs.org>`_.
50 `jupyter <https://jupyter.readthedocs.io>`_.
38 IPython subprojects, such as `IPython.parallel <https://ipyparallel.readthedocs.org>`_ and `widgets <https://ipywidgets.readthedocs.org>`_ have moved to their own repos as well.
51 IPython subprojects, such as `IPython.parallel <https://ipyparallel.readthedocs.io>`_ and `widgets <https://ipywidgets.readthedocs.io>`_ have moved to their own repos as well.
39
52
40 The following subpackages are deprecated:
53 The following subpackages are deprecated:
41
54
@@ -354,7 +354,7 b''
354 "cell_type": "markdown",
354 "cell_type": "markdown",
355 "metadata": {},
355 "metadata": {},
356 "source": [
356 "source": [
357 "[Vincent](https://vincent.readthedocs.org/en/latest/) is a visualization library that uses the [Vega](http://trifacta.github.io/vega/) visualization grammar to build [d3.js](http://d3js.org/) based visualizations in the Notebook and on http://nbviewer.ipython.org. `Visualization` objects in Vincetn have rich HTML and JavaSrcript representations."
357 "[Vincent](https://vincent.readthedocs.io/en/latest/) is a visualization library that uses the [Vega](http://trifacta.github.io/vega/) visualization grammar to build [d3.js](http://d3js.org/) based visualizations in the Notebook and on http://nbviewer.ipython.org. `Visualization` objects in Vincetn have rich HTML and JavaSrcript representations."
358 ]
358 ]
359 },
359 },
360 {
360 {
@@ -198,7 +198,6 b' install_requires = ['
198 'traitlets',
198 'traitlets',
199 'prompt_toolkit>=0.60',
199 'prompt_toolkit>=0.60',
200 'pygments',
200 'pygments',
201 'backports.shutil_get_terminal_size',
202 ]
201 ]
203
202
204 # Platform-specific dependencies:
203 # Platform-specific dependencies:
@@ -206,6 +205,8 b' install_requires = ['
206 # but requires pip >= 6. pip < 6 ignores these.
205 # but requires pip >= 6. pip < 6 ignores these.
207
206
208 extras_require.update({
207 extras_require.update({
208 ':python_version == "2.7"': ['backports.shutil_get_terminal_size'],
209 ':python_version == "2.7" or python_version == "3.3"': ['pathlib2'],
209 ':sys_platform != "win32"': ['pexpect'],
210 ':sys_platform != "win32"': ['pexpect'],
210 ':sys_platform == "darwin"': ['appnope'],
211 ':sys_platform == "darwin"': ['appnope'],
211 ':sys_platform == "win32"': ['colorama'],
212 ':sys_platform == "win32"': ['colorama'],
@@ -168,7 +168,7 b' if __name__ == "__main__":'
168 state='closed',
168 state='closed',
169 auth=True,
169 auth=True,
170 )
170 )
171 issues, pulls = split_pulls(issues_and_pulls)
171 issues, pulls = split_pulls(issues_and_pulls, project=project)
172 else:
172 else:
173 issues = issues_closed_since(since, project=project, pulls=False)
173 issues = issues_closed_since(since, project=project, pulls=False)
174 pulls = issues_closed_since(since, project=project, pulls=True)
174 pulls = issues_closed_since(since, project=project, pulls=True)
General Comments 0
You need to be logged in to leave comments. Login now