Show More
@@ -62,6 +62,7 b' from IPython.utils import PyColorize' | |||
|
62 | 62 | from IPython.utils import io |
|
63 | 63 | from IPython.utils import py3compat |
|
64 | 64 | from IPython.utils import openpy |
|
65 | from IPython.utils.contexts import NoOpContext | |
|
65 | 66 | from IPython.utils.decorators import undoc |
|
66 | 67 | from IPython.utils.io import ask_yes_no |
|
67 | 68 | from IPython.utils.ipstruct import Struct |
@@ -109,11 +110,6 b' def softspace(file, newvalue):' | |||
|
109 | 110 | @undoc |
|
110 | 111 | def no_op(*a, **kw): pass |
|
111 | 112 | |
|
112 | @undoc | |
|
113 | class NoOpContext(object): | |
|
114 | def __enter__(self): pass | |
|
115 | def __exit__(self, type, value, traceback): pass | |
|
116 | no_op_context = NoOpContext() | |
|
117 | 113 | |
|
118 | 114 | class SpaceInInput(Exception): pass |
|
119 | 115 | |
@@ -142,52 +138,6 b' class SeparateUnicode(Unicode):' | |||
|
142 | 138 | return super(SeparateUnicode, self).validate(obj, value) |
|
143 | 139 | |
|
144 | 140 | |
|
145 | class ReadlineNoRecord(object): | |
|
146 | """Context manager to execute some code, then reload readline history | |
|
147 | so that interactive input to the code doesn't appear when pressing up.""" | |
|
148 | def __init__(self, shell): | |
|
149 | self.shell = shell | |
|
150 | self._nested_level = 0 | |
|
151 | ||
|
152 | def __enter__(self): | |
|
153 | if self._nested_level == 0: | |
|
154 | try: | |
|
155 | self.orig_length = self.current_length() | |
|
156 | self.readline_tail = self.get_readline_tail() | |
|
157 | except (AttributeError, IndexError): # Can fail with pyreadline | |
|
158 | self.orig_length, self.readline_tail = 999999, [] | |
|
159 | self._nested_level += 1 | |
|
160 | ||
|
161 | def __exit__(self, type, value, traceback): | |
|
162 | self._nested_level -= 1 | |
|
163 | if self._nested_level == 0: | |
|
164 | # Try clipping the end if it's got longer | |
|
165 | try: | |
|
166 | e = self.current_length() - self.orig_length | |
|
167 | if e > 0: | |
|
168 | for _ in range(e): | |
|
169 | self.shell.readline.remove_history_item(self.orig_length) | |
|
170 | ||
|
171 | # If it still doesn't match, just reload readline history. | |
|
172 | if self.current_length() != self.orig_length \ | |
|
173 | or self.get_readline_tail() != self.readline_tail: | |
|
174 | self.shell.refill_readline_hist() | |
|
175 | except (AttributeError, IndexError): | |
|
176 | pass | |
|
177 | # Returning False will cause exceptions to propagate | |
|
178 | return False | |
|
179 | ||
|
180 | def current_length(self): | |
|
181 | return self.shell.readline.get_current_history_length() | |
|
182 | ||
|
183 | def get_readline_tail(self, n=10): | |
|
184 | """Get the last n items in readline history.""" | |
|
185 | end = self.shell.readline.get_current_history_length() + 1 | |
|
186 | start = max(end-n, 1) | |
|
187 | ghi = self.shell.readline.get_history_item | |
|
188 | return [ghi(x) for x in range(start, end)] | |
|
189 | ||
|
190 | ||
|
191 | 141 | @undoc |
|
192 | 142 | class DummyMod(object): |
|
193 | 143 | """A dummy module used for IPython's interactive module when |
@@ -1934,120 +1884,17 b' class InteractiveShell(SingletonConfigurable):' | |||
|
1934 | 1884 | #------------------------------------------------------------------------- |
|
1935 | 1885 | |
|
1936 | 1886 | def init_readline(self): |
|
1937 | """Command history completion/saving/reloading.""" | |
|
1938 | ||
|
1939 | if self.readline_use: | |
|
1940 | import IPython.utils.rlineimpl as readline | |
|
1941 | ||
|
1942 | self.rl_next_input = None | |
|
1943 | self.rl_do_indent = False | |
|
1944 | ||
|
1945 | if not self.readline_use or not readline.have_readline: | |
|
1946 | self.has_readline = False | |
|
1947 | self.readline = None | |
|
1948 | # Set a number of methods that depend on readline to be no-op | |
|
1949 | self.readline_no_record = no_op_context | |
|
1950 | self.set_readline_completer = no_op | |
|
1951 | self.set_custom_completer = no_op | |
|
1952 | if self.readline_use: | |
|
1953 | warn('Readline services not available or not loaded.') | |
|
1954 | else: | |
|
1955 | self.has_readline = True | |
|
1956 | self.readline = readline | |
|
1957 | sys.modules['readline'] = readline | |
|
1958 | ||
|
1959 | # Platform-specific configuration | |
|
1960 | if os.name == 'nt': | |
|
1961 | # FIXME - check with Frederick to see if we can harmonize | |
|
1962 | # naming conventions with pyreadline to avoid this | |
|
1963 | # platform-dependent check | |
|
1964 | self.readline_startup_hook = readline.set_pre_input_hook | |
|
1965 | else: | |
|
1966 | self.readline_startup_hook = readline.set_startup_hook | |
|
1967 | ||
|
1968 | # Readline config order: | |
|
1969 | # - IPython config (default value) | |
|
1970 | # - custom inputrc | |
|
1971 | # - IPython config (user customized) | |
|
1972 | ||
|
1973 | # load IPython config before inputrc if default | |
|
1974 | # skip if libedit because parse_and_bind syntax is different | |
|
1975 | if not self._custom_readline_config and not readline.uses_libedit: | |
|
1976 | for rlcommand in self.readline_parse_and_bind: | |
|
1977 | readline.parse_and_bind(rlcommand) | |
|
1978 | ||
|
1979 | # Load user's initrc file (readline config) | |
|
1980 | # Or if libedit is used, load editrc. | |
|
1981 | inputrc_name = os.environ.get('INPUTRC') | |
|
1982 | if inputrc_name is None: | |
|
1983 | inputrc_name = '.inputrc' | |
|
1984 | if readline.uses_libedit: | |
|
1985 | inputrc_name = '.editrc' | |
|
1986 | inputrc_name = os.path.join(self.home_dir, inputrc_name) | |
|
1987 | if os.path.isfile(inputrc_name): | |
|
1988 | try: | |
|
1989 | readline.read_init_file(inputrc_name) | |
|
1990 | except: | |
|
1991 | warn('Problems reading readline initialization file <%s>' | |
|
1992 | % inputrc_name) | |
|
1993 | ||
|
1994 | # load IPython config after inputrc if user has customized | |
|
1995 | if self._custom_readline_config: | |
|
1996 | for rlcommand in self.readline_parse_and_bind: | |
|
1997 | readline.parse_and_bind(rlcommand) | |
|
1998 | ||
|
1999 | # Remove some chars from the delimiters list. If we encounter | |
|
2000 | # unicode chars, discard them. | |
|
2001 | delims = readline.get_completer_delims() | |
|
2002 | if not py3compat.PY3: | |
|
2003 | delims = delims.encode("ascii", "ignore") | |
|
2004 | for d in self.readline_remove_delims: | |
|
2005 | delims = delims.replace(d, "") | |
|
2006 | delims = delims.replace(ESC_MAGIC, '') | |
|
2007 | readline.set_completer_delims(delims) | |
|
2008 | # Store these so we can restore them if something like rpy2 modifies | |
|
2009 | # them. | |
|
2010 | self.readline_delims = delims | |
|
2011 | # otherwise we end up with a monster history after a while: | |
|
2012 | readline.set_history_length(self.history_length) | |
|
2013 | ||
|
2014 | self.refill_readline_hist() | |
|
2015 | self.readline_no_record = ReadlineNoRecord(self) | |
|
2016 | ||
|
2017 | # Configure auto-indent for all platforms | |
|
2018 | self.set_autoindent(self.autoindent) | |
|
2019 | ||
|
2020 | def refill_readline_hist(self): | |
|
2021 | # Load the last 1000 lines from history | |
|
2022 | self.readline.clear_history() | |
|
2023 | stdin_encoding = sys.stdin.encoding or "utf-8" | |
|
2024 | last_cell = u"" | |
|
2025 | for _, _, cell in self.history_manager.get_tail(self.history_load_length, | |
|
2026 | include_latest=True): | |
|
2027 | # Ignore blank lines and consecutive duplicates | |
|
2028 | cell = cell.rstrip() | |
|
2029 | if cell and (cell != last_cell): | |
|
2030 | try: | |
|
2031 | if self.multiline_history: | |
|
2032 | self.readline.add_history(py3compat.unicode_to_str(cell, | |
|
2033 | stdin_encoding)) | |
|
2034 | else: | |
|
2035 | for line in cell.splitlines(): | |
|
2036 | self.readline.add_history(py3compat.unicode_to_str(line, | |
|
2037 | stdin_encoding)) | |
|
2038 | last_cell = cell | |
|
2039 | ||
|
2040 | except TypeError: | |
|
2041 | # The history DB can get corrupted so it returns strings | |
|
2042 | # containing null bytes, which readline objects to. | |
|
2043 | continue | |
|
1887 | """Moved to terminal subclass, here only to simplify the init logic.""" | |
|
1888 | self.readline = None | |
|
1889 | # Set a number of methods that depend on readline to be no-op | |
|
1890 | self.readline_no_record = NoOpContext() | |
|
1891 | self.set_readline_completer = no_op | |
|
1892 | self.set_custom_completer = no_op | |
|
2044 | 1893 | |
|
2045 | 1894 | @skip_doctest |
|
2046 | 1895 | def set_next_input(self, s, replace=False): |
|
2047 | 1896 | """ Sets the 'default' input string for the next command line. |
|
2048 | 1897 | |
|
2049 | Requires readline. | |
|
2050 | ||
|
2051 | 1898 | Example:: |
|
2052 | 1899 | |
|
2053 | 1900 | In [1]: _ip.set_next_input("Hello Word") |
@@ -2055,18 +1902,6 b' class InteractiveShell(SingletonConfigurable):' | |||
|
2055 | 1902 | """ |
|
2056 | 1903 | self.rl_next_input = py3compat.cast_bytes_py2(s) |
|
2057 | 1904 | |
|
2058 | # Maybe move this to the terminal subclass? | |
|
2059 | def pre_readline(self): | |
|
2060 | """readline hook to be used at the start of each line. | |
|
2061 | ||
|
2062 | Currently it handles auto-indent only.""" | |
|
2063 | ||
|
2064 | if self.rl_do_indent: | |
|
2065 | self.readline.insert_text(self._indent_current_str()) | |
|
2066 | if self.rl_next_input is not None: | |
|
2067 | self.readline.insert_text(self.rl_next_input) | |
|
2068 | self.rl_next_input = None | |
|
2069 | ||
|
2070 | 1905 | def _indent_current_str(self): |
|
2071 | 1906 | """return the current level of indentation as a string""" |
|
2072 | 1907 | return self.input_splitter.indent_spaces * ' ' |
@@ -2107,11 +1942,6 b' class InteractiveShell(SingletonConfigurable):' | |||
|
2107 | 1942 | self.set_hook('complete_command', cd_completer, str_key = '%cd') |
|
2108 | 1943 | self.set_hook('complete_command', reset_completer, str_key = '%reset') |
|
2109 | 1944 | |
|
2110 | # Only configure readline if we truly are using readline. IPython can | |
|
2111 | # do tab-completion over the network, in GUIs, etc, where readline | |
|
2112 | # itself may be absent | |
|
2113 | if self.has_readline: | |
|
2114 | self.set_readline_completer() | |
|
2115 | 1945 | |
|
2116 | 1946 | def complete(self, text, line=None, cursor_pos=None): |
|
2117 | 1947 | """Return the completed text and a list of completions. |
@@ -2167,10 +1997,6 b' class InteractiveShell(SingletonConfigurable):' | |||
|
2167 | 1997 | newcomp = types.MethodType(completer,self.Completer) |
|
2168 | 1998 | self.Completer.matchers.insert(pos,newcomp) |
|
2169 | 1999 | |
|
2170 | def set_readline_completer(self): | |
|
2171 | """Reset readline's completer to be our own.""" | |
|
2172 | self.readline.set_completer(self.Completer.rlcomplete) | |
|
2173 | ||
|
2174 | 2000 | def set_completer_frame(self, frame=None): |
|
2175 | 2001 | """Set the frame of the completer.""" |
|
2176 | 2002 | if frame: |
@@ -1,18 +1,9 b'' | |||
|
1 | 1 | # -*- coding: utf-8 -*- |
|
2 | 2 | """Subclass of InteractiveShell for terminal based frontends.""" |
|
3 | 3 | |
|
4 | #----------------------------------------------------------------------------- | |
|
5 | # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de> | |
|
6 | # Copyright (C) 2001-2007 Fernando Perez. <fperez@colorado.edu> | |
|
7 | # Copyright (C) 2008-2011 The IPython Development Team | |
|
8 | # | |
|
9 | # Distributed under the terms of the BSD License. The full license is in | |
|
10 | # the file COPYING, distributed as part of this software. | |
|
11 | #----------------------------------------------------------------------------- | |
|
12 | ||
|
13 | #----------------------------------------------------------------------------- | |
|
14 | # Imports | |
|
15 | #----------------------------------------------------------------------------- | |
|
4 | # Copyright (c) IPython Development Team. | |
|
5 | # Distributed under the terms of the Modified BSD License. | |
|
6 | ||
|
16 | 7 | from __future__ import print_function |
|
17 | 8 | |
|
18 | 9 | import bdb |
@@ -21,10 +12,12 b' import sys' | |||
|
21 | 12 | |
|
22 | 13 | from IPython.core.error import TryNext, UsageError |
|
23 | 14 | from IPython.core.usage import interactive_usage |
|
24 | from IPython.core.inputsplitter import IPythonInputSplitter | |
|
15 | from IPython.core.inputsplitter import IPythonInputSplitter, ESC_MAGIC | |
|
25 | 16 | from IPython.core.interactiveshell import InteractiveShell, InteractiveShellABC |
|
26 | 17 | from IPython.core.magic import Magics, magics_class, line_magic |
|
27 | 18 | from IPython.lib.clipboard import ClipboardEmpty |
|
19 | from IPython.utils.contexts import NoOpContext | |
|
20 | from IPython.utils.decorators import undoc | |
|
28 | 21 | from IPython.utils.encoding import get_stream_enc |
|
29 | 22 | from IPython.utils import py3compat |
|
30 | 23 | from IPython.utils.terminal import toggle_set_term_title, set_term_title |
@@ -33,9 +26,6 b' from IPython.utils.warn import warn, error' | |||
|
33 | 26 | from IPython.utils.text import num_ini_spaces, SList, strip_email_quotes |
|
34 | 27 | from traitlets import Integer, CBool, Unicode |
|
35 | 28 | |
|
36 | #----------------------------------------------------------------------------- | |
|
37 | # Utilities | |
|
38 | #----------------------------------------------------------------------------- | |
|
39 | 29 | |
|
40 | 30 | def get_default_editor(): |
|
41 | 31 | try: |
@@ -74,10 +64,55 b' def get_pasted_lines(sentinel, l_input=py3compat.input, quiet=False):' | |||
|
74 | 64 | print('<EOF>') |
|
75 | 65 | return |
|
76 | 66 | |
|
67 | @undoc | |
|
68 | def no_op(*a, **kw): pass | |
|
69 | ||
|
70 | ||
|
71 | class ReadlineNoRecord(object): | |
|
72 | """Context manager to execute some code, then reload readline history | |
|
73 | so that interactive input to the code doesn't appear when pressing up.""" | |
|
74 | def __init__(self, shell): | |
|
75 | self.shell = shell | |
|
76 | self._nested_level = 0 | |
|
77 | ||
|
78 | def __enter__(self): | |
|
79 | if self._nested_level == 0: | |
|
80 | try: | |
|
81 | self.orig_length = self.current_length() | |
|
82 | self.readline_tail = self.get_readline_tail() | |
|
83 | except (AttributeError, IndexError): # Can fail with pyreadline | |
|
84 | self.orig_length, self.readline_tail = 999999, [] | |
|
85 | self._nested_level += 1 | |
|
86 | ||
|
87 | def __exit__(self, type, value, traceback): | |
|
88 | self._nested_level -= 1 | |
|
89 | if self._nested_level == 0: | |
|
90 | # Try clipping the end if it's got longer | |
|
91 | try: | |
|
92 | e = self.current_length() - self.orig_length | |
|
93 | if e > 0: | |
|
94 | for _ in range(e): | |
|
95 | self.shell.readline.remove_history_item(self.orig_length) | |
|
96 | ||
|
97 | # If it still doesn't match, just reload readline history. | |
|
98 | if self.current_length() != self.orig_length \ | |
|
99 | or self.get_readline_tail() != self.readline_tail: | |
|
100 | self.shell.refill_readline_hist() | |
|
101 | except (AttributeError, IndexError): | |
|
102 | pass | |
|
103 | # Returning False will cause exceptions to propagate | |
|
104 | return False | |
|
105 | ||
|
106 | def current_length(self): | |
|
107 | return self.shell.readline.get_current_history_length() | |
|
108 | ||
|
109 | def get_readline_tail(self, n=10): | |
|
110 | """Get the last n items in readline history.""" | |
|
111 | end = self.shell.readline.get_current_history_length() + 1 | |
|
112 | start = max(end-n, 1) | |
|
113 | ghi = self.shell.readline.get_history_item | |
|
114 | return [ghi(x) for x in range(start, end)] | |
|
77 | 115 | |
|
78 | #------------------------------------------------------------------------ | |
|
79 | # Terminal-specific magics | |
|
80 | #------------------------------------------------------------------------ | |
|
81 | 116 | |
|
82 | 117 | @magics_class |
|
83 | 118 | class TerminalMagics(Magics): |
@@ -248,9 +283,6 b' class TerminalMagics(Magics):' | |||
|
248 | 283 | """ |
|
249 | 284 | os.system("cls") |
|
250 | 285 | |
|
251 | #----------------------------------------------------------------------------- | |
|
252 | # Main class | |
|
253 | #----------------------------------------------------------------------------- | |
|
254 | 286 | |
|
255 | 287 | class TerminalInteractiveShell(InteractiveShell): |
|
256 | 288 | |
@@ -320,6 +352,141 b' class TerminalInteractiveShell(InteractiveShell):' | |||
|
320 | 352 | self.display_formatter.active_types = ['text/plain'] |
|
321 | 353 | |
|
322 | 354 | #------------------------------------------------------------------------- |
|
355 | # Things related to readline | |
|
356 | #------------------------------------------------------------------------- | |
|
357 | ||
|
358 | def init_readline(self): | |
|
359 | """Command history completion/saving/reloading.""" | |
|
360 | ||
|
361 | if self.readline_use: | |
|
362 | import IPython.utils.rlineimpl as readline | |
|
363 | ||
|
364 | self.rl_next_input = None | |
|
365 | self.rl_do_indent = False | |
|
366 | ||
|
367 | if not self.readline_use or not readline.have_readline: | |
|
368 | self.readline = None | |
|
369 | # Set a number of methods that depend on readline to be no-op | |
|
370 | self.readline_no_record = NoOpContext() | |
|
371 | self.set_readline_completer = no_op | |
|
372 | self.set_custom_completer = no_op | |
|
373 | if self.readline_use: | |
|
374 | warn('Readline services not available or not loaded.') | |
|
375 | else: | |
|
376 | self.has_readline = True | |
|
377 | self.readline = readline | |
|
378 | sys.modules['readline'] = readline | |
|
379 | ||
|
380 | # Platform-specific configuration | |
|
381 | if os.name == 'nt': | |
|
382 | # FIXME - check with Frederick to see if we can harmonize | |
|
383 | # naming conventions with pyreadline to avoid this | |
|
384 | # platform-dependent check | |
|
385 | self.readline_startup_hook = readline.set_pre_input_hook | |
|
386 | else: | |
|
387 | self.readline_startup_hook = readline.set_startup_hook | |
|
388 | ||
|
389 | # Readline config order: | |
|
390 | # - IPython config (default value) | |
|
391 | # - custom inputrc | |
|
392 | # - IPython config (user customized) | |
|
393 | ||
|
394 | # load IPython config before inputrc if default | |
|
395 | # skip if libedit because parse_and_bind syntax is different | |
|
396 | if not self._custom_readline_config and not readline.uses_libedit: | |
|
397 | for rlcommand in self.readline_parse_and_bind: | |
|
398 | readline.parse_and_bind(rlcommand) | |
|
399 | ||
|
400 | # Load user's initrc file (readline config) | |
|
401 | # Or if libedit is used, load editrc. | |
|
402 | inputrc_name = os.environ.get('INPUTRC') | |
|
403 | if inputrc_name is None: | |
|
404 | inputrc_name = '.inputrc' | |
|
405 | if readline.uses_libedit: | |
|
406 | inputrc_name = '.editrc' | |
|
407 | inputrc_name = os.path.join(self.home_dir, inputrc_name) | |
|
408 | if os.path.isfile(inputrc_name): | |
|
409 | try: | |
|
410 | readline.read_init_file(inputrc_name) | |
|
411 | except: | |
|
412 | warn('Problems reading readline initialization file <%s>' | |
|
413 | % inputrc_name) | |
|
414 | ||
|
415 | # load IPython config after inputrc if user has customized | |
|
416 | if self._custom_readline_config: | |
|
417 | for rlcommand in self.readline_parse_and_bind: | |
|
418 | readline.parse_and_bind(rlcommand) | |
|
419 | ||
|
420 | # Remove some chars from the delimiters list. If we encounter | |
|
421 | # unicode chars, discard them. | |
|
422 | delims = readline.get_completer_delims() | |
|
423 | if not py3compat.PY3: | |
|
424 | delims = delims.encode("ascii", "ignore") | |
|
425 | for d in self.readline_remove_delims: | |
|
426 | delims = delims.replace(d, "") | |
|
427 | delims = delims.replace(ESC_MAGIC, '') | |
|
428 | readline.set_completer_delims(delims) | |
|
429 | # Store these so we can restore them if something like rpy2 modifies | |
|
430 | # them. | |
|
431 | self.readline_delims = delims | |
|
432 | # otherwise we end up with a monster history after a while: | |
|
433 | readline.set_history_length(self.history_length) | |
|
434 | ||
|
435 | self.refill_readline_hist() | |
|
436 | self.readline_no_record = ReadlineNoRecord(self) | |
|
437 | ||
|
438 | # Configure auto-indent for all platforms | |
|
439 | self.set_autoindent(self.autoindent) | |
|
440 | ||
|
441 | def init_completer(self): | |
|
442 | super(TerminalInteractiveShell, self).init_completer() | |
|
443 | ||
|
444 | # Only configure readline if we truly are using readline. | |
|
445 | if self.has_readline: | |
|
446 | self.set_readline_completer() | |
|
447 | ||
|
448 | def set_readline_completer(self): | |
|
449 | """Reset readline's completer to be our own.""" | |
|
450 | self.readline.set_completer(self.Completer.rlcomplete) | |
|
451 | ||
|
452 | ||
|
453 | def pre_readline(self): | |
|
454 | """readline hook to be used at the start of each line. | |
|
455 | ||
|
456 | It handles auto-indent and text from set_next_input.""" | |
|
457 | ||
|
458 | if self.rl_do_indent: | |
|
459 | self.readline.insert_text(self._indent_current_str()) | |
|
460 | if self.rl_next_input is not None: | |
|
461 | self.readline.insert_text(self.rl_next_input) | |
|
462 | self.rl_next_input = None | |
|
463 | ||
|
464 | def refill_readline_hist(self): | |
|
465 | # Load the last 1000 lines from history | |
|
466 | self.readline.clear_history() | |
|
467 | stdin_encoding = sys.stdin.encoding or "utf-8" | |
|
468 | last_cell = u"" | |
|
469 | for _, _, cell in self.history_manager.get_tail(self.history_load_length, | |
|
470 | include_latest=True): | |
|
471 | # Ignore blank lines and consecutive duplicates | |
|
472 | cell = cell.rstrip() | |
|
473 | if cell and (cell != last_cell): | |
|
474 | try: | |
|
475 | if self.multiline_history: | |
|
476 | self.readline.add_history(py3compat.unicode_to_str(cell, | |
|
477 | stdin_encoding)) | |
|
478 | else: | |
|
479 | for line in cell.splitlines(): | |
|
480 | self.readline.add_history(py3compat.unicode_to_str(line, | |
|
481 | stdin_encoding)) | |
|
482 | last_cell = cell | |
|
483 | ||
|
484 | except TypeError: | |
|
485 | # The history DB can get corrupted so it returns strings | |
|
486 | # containing null bytes, which readline objects to. | |
|
487 | continue | |
|
488 | ||
|
489 | #------------------------------------------------------------------------- | |
|
323 | 490 | # Things related to the terminal |
|
324 | 491 | #------------------------------------------------------------------------- |
|
325 | 492 |
@@ -1,22 +1,9 b'' | |||
|
1 | 1 | # encoding: utf-8 |
|
2 | """Miscellaneous context managers. | |
|
2 | 3 |
|
|
3 | Context managers for temporarily updating dictionaries. | |
|
4 | 4 | |
|
5 | Authors: | |
|
6 | ||
|
7 | * Bradley Froehle | |
|
8 | """ | |
|
9 | ||
|
10 | #----------------------------------------------------------------------------- | |
|
11 | # Copyright (C) 2012 The IPython Development Team | |
|
12 | # | |
|
13 | # Distributed under the terms of the BSD License. The full license is in | |
|
14 | # the file COPYING, distributed as part of this software. | |
|
15 | #----------------------------------------------------------------------------- | |
|
16 | ||
|
17 | #----------------------------------------------------------------------------- | |
|
18 | # Code | |
|
19 | #----------------------------------------------------------------------------- | |
|
5 | # Copyright (c) IPython Development Team. | |
|
6 | # Distributed under the terms of the Modified BSD License. | |
|
20 | 7 | |
|
21 | 8 | class preserve_keys(object): |
|
22 | 9 | """Preserve a set of keys in a dictionary. |
@@ -69,3 +56,9 b' class preserve_keys(object):' | |||
|
69 | 56 | for k in self.to_delete: |
|
70 | 57 | d.pop(k, None) |
|
71 | 58 | d.update(self.to_update) |
|
59 | ||
|
60 | ||
|
61 | class NoOpContext(object): | |
|
62 | """Context manager that does nothing.""" | |
|
63 | def __enter__(self): pass | |
|
64 | def __exit__(self, type, value, traceback): pass |
General Comments 0
You need to be logged in to leave comments.
Login now