Show More
@@ -73,25 +73,6 b' class CachingCompiler(codeop.Compile):' | |||||
73 | def __init__(self): |
|
73 | def __init__(self): | |
74 | codeop.Compile.__init__(self) |
|
74 | codeop.Compile.__init__(self) | |
75 |
|
75 | |||
76 | # This is ugly, but it must be done this way to allow multiple |
|
|||
77 | # simultaneous ipython instances to coexist. Since Python itself |
|
|||
78 | # directly accesses the data structures in the linecache module, and |
|
|||
79 | # the cache therein is global, we must work with that data structure. |
|
|||
80 | # We must hold a reference to the original checkcache routine and call |
|
|||
81 | # that in our own check_cache() below, but the special IPython cache |
|
|||
82 | # must also be shared by all IPython instances. If we were to hold |
|
|||
83 | # separate caches (one in each CachingCompiler instance), any call made |
|
|||
84 | # by Python itself to linecache.checkcache() would obliterate the |
|
|||
85 | # cached data from the other IPython instances. |
|
|||
86 | if not hasattr(linecache, '_ipython_cache'): |
|
|||
87 | linecache._ipython_cache = {} |
|
|||
88 | if not hasattr(linecache, '_checkcache_ori'): |
|
|||
89 | linecache._checkcache_ori = linecache.checkcache |
|
|||
90 | # Now, we must monkeypatch the linecache directly so that parts of the |
|
|||
91 | # stdlib that call it outside our control go through our codepath |
|
|||
92 | # (otherwise we'd lose our tracebacks). |
|
|||
93 | linecache.checkcache = check_linecache_ipython |
|
|||
94 |
|
||||
95 | # Caching a dictionary { filename: execution_count } for nicely |
|
76 | # Caching a dictionary { filename: execution_count } for nicely | |
96 | # rendered tracebacks. The filename corresponds to the filename |
|
77 | # rendered tracebacks. The filename corresponds to the filename | |
97 | # argument used for the builtins.compile function. |
|
78 | # argument used for the builtins.compile function. | |
@@ -161,14 +142,24 b' class CachingCompiler(codeop.Compile):' | |||||
161 | # Save the execution count |
|
142 | # Save the execution count | |
162 | self._filename_map[name] = number |
|
143 | self._filename_map[name] = number | |
163 |
|
144 | |||
|
145 | # Since Python 2.5, setting mtime to `None` means the lines will | |||
|
146 | # never be removed by `linecache.checkcache`. This means all the | |||
|
147 | # monkeypatching has *never* been necessary, since this code was | |||
|
148 | # only added in 2010, at which point IPython had already stopped | |||
|
149 | # supporting Python 2.4. | |||
|
150 | # | |||
|
151 | # Note that `linecache.clearcache` and `linecache.updatecache` may | |||
|
152 | # still remove our code from the cache, but those show explicit | |||
|
153 | # intent, and we should not try to interfere. Normally the former | |||
|
154 | # is never called except when out of memory, and the latter is only | |||
|
155 | # called for lines *not* in the cache. | |||
164 | entry = ( |
|
156 | entry = ( | |
165 | len(transformed_code), |
|
157 | len(transformed_code), | |
166 |
|
|
158 | None, | |
167 | [line + "\n" for line in transformed_code.splitlines()], |
|
159 | [line + "\n" for line in transformed_code.splitlines()], | |
168 | name, |
|
160 | name, | |
169 | ) |
|
161 | ) | |
170 | linecache.cache[name] = entry |
|
162 | linecache.cache[name] = entry | |
171 | linecache._ipython_cache[name] = entry |
|
|||
172 | return name |
|
163 | return name | |
173 |
|
164 | |||
174 | @contextmanager |
|
165 | @contextmanager | |
@@ -187,10 +178,20 b' class CachingCompiler(codeop.Compile):' | |||||
187 |
|
178 | |||
188 |
|
179 | |||
189 | def check_linecache_ipython(*args): |
|
180 | def check_linecache_ipython(*args): | |
190 | """Call linecache.checkcache() safely protecting our cached values. |
|
181 | """Deprecated since IPython 8.6. Call linecache.checkcache() directly. | |
|
182 | ||||
|
183 | It was already not necessary to call this function directly. If no | |||
|
184 | CachingCompiler had been created, this function would fail badly. If | |||
|
185 | an instance had been created, this function would've been monkeypatched | |||
|
186 | into place. | |||
|
187 | ||||
|
188 | As of IPython 8.6, the monkeypatching has gone away entirely. But there | |||
|
189 | were still internal callers of this function, so maybe external callers | |||
|
190 | also existed? | |||
191 | """ |
|
191 | """ | |
192 | # First call the original checkcache as intended |
|
192 | import warnings | |
193 | linecache._checkcache_ori(*args) |
|
193 | warnings.warn( | |
194 | # Then, update back the cache with our data, so that tracebacks related |
|
194 | 'Just call linecache.checkcache() directly.', | |
195 | # to our compiled codes can be produced. |
|
195 | DeprecationWarning | |
196 | linecache.cache.update(linecache._ipython_cache) |
|
196 | ) | |
|
197 | linecache.checkcache() |
@@ -61,7 +61,7 b' from IPython.core import magic, oinspect, page, prefilter, ultratb' | |||||
61 | from IPython.core.alias import Alias, AliasManager |
|
61 | from IPython.core.alias import Alias, AliasManager | |
62 | from IPython.core.autocall import ExitAutocall |
|
62 | from IPython.core.autocall import ExitAutocall | |
63 | from IPython.core.builtin_trap import BuiltinTrap |
|
63 | from IPython.core.builtin_trap import BuiltinTrap | |
64 |
from IPython.core.compilerop import CachingCompiler |
|
64 | from IPython.core.compilerop import CachingCompiler | |
65 | from IPython.core.debugger import InterruptiblePdb |
|
65 | from IPython.core.debugger import InterruptiblePdb | |
66 | from IPython.core.display_trap import DisplayTrap |
|
66 | from IPython.core.display_trap import DisplayTrap | |
67 | from IPython.core.displayhook import DisplayHook |
|
67 | from IPython.core.displayhook import DisplayHook | |
@@ -1810,7 +1810,6 b' class InteractiveShell(SingletonConfigurable):' | |||||
1810 | self.InteractiveTB = ultratb.AutoFormattedTB(mode = 'Plain', |
|
1810 | self.InteractiveTB = ultratb.AutoFormattedTB(mode = 'Plain', | |
1811 | color_scheme='NoColor', |
|
1811 | color_scheme='NoColor', | |
1812 | tb_offset = 1, |
|
1812 | tb_offset = 1, | |
1813 | check_cache=check_linecache_ipython, |
|
|||
1814 | debugger_cls=self.debugger_cls, parent=self) |
|
1813 | debugger_cls=self.debugger_cls, parent=self) | |
1815 |
|
1814 | |||
1816 | # The instance will store a pointer to the system-wide exception hook, |
|
1815 | # The instance will store a pointer to the system-wide exception hook, |
@@ -644,10 +644,8 b' class VerboseTB(TBTools):' | |||||
644 | self.long_header = long_header |
|
644 | self.long_header = long_header | |
645 | self.include_vars = include_vars |
|
645 | self.include_vars = include_vars | |
646 | # By default we use linecache.checkcache, but the user can provide a |
|
646 | # By default we use linecache.checkcache, but the user can provide a | |
647 |
# different check_cache implementation. This |
|
647 | # different check_cache implementation. This was formerly used by the | |
648 |
# |
|
648 | # IPython kernel for interactive code, but is no longer necessary. | |
649 | # by a compiler instance that flushes the linecache but preserves its |
|
|||
650 | # own code cache. |
|
|||
651 | if check_cache is None: |
|
649 | if check_cache is None: | |
652 | check_cache = linecache.checkcache |
|
650 | check_cache = linecache.checkcache | |
653 | self.check_cache = check_cache |
|
651 | self.check_cache = check_cache |
General Comments 0
You need to be logged in to leave comments.
Login now