##// END OF EJS Templates
add some infor in warning
Matthias Bussonnier -
Show More
@@ -1,195 +1,199 b''
1 """Compiler tools with improved interactive support.
1 """Compiler tools with improved interactive support.
2
2
3 Provides compilation machinery similar to codeop, but with caching support so
3 Provides compilation machinery similar to codeop, but with caching support so
4 we can provide interactive tracebacks.
4 we can provide interactive tracebacks.
5
5
6 Authors
6 Authors
7 -------
7 -------
8 * Robert Kern
8 * Robert Kern
9 * Fernando Perez
9 * Fernando Perez
10 * Thomas Kluyver
10 * Thomas Kluyver
11 """
11 """
12
12
13 # Note: though it might be more natural to name this module 'compiler', that
13 # Note: though it might be more natural to name this module 'compiler', that
14 # name is in the stdlib and name collisions with the stdlib tend to produce
14 # name is in the stdlib and name collisions with the stdlib tend to produce
15 # weird problems (often with third-party tools).
15 # weird problems (often with third-party tools).
16
16
17 #-----------------------------------------------------------------------------
17 #-----------------------------------------------------------------------------
18 # Copyright (C) 2010-2011 The IPython Development Team.
18 # Copyright (C) 2010-2011 The IPython Development Team.
19 #
19 #
20 # Distributed under the terms of the BSD License.
20 # Distributed under the terms of the BSD License.
21 #
21 #
22 # The full license is in the file COPYING.txt, distributed with this software.
22 # The full license is in the file COPYING.txt, distributed with this software.
23 #-----------------------------------------------------------------------------
23 #-----------------------------------------------------------------------------
24
24
25 #-----------------------------------------------------------------------------
25 #-----------------------------------------------------------------------------
26 # Imports
26 # Imports
27 #-----------------------------------------------------------------------------
27 #-----------------------------------------------------------------------------
28
28
29 # Stdlib imports
29 # Stdlib imports
30 import __future__
30 import __future__
31 from ast import PyCF_ONLY_AST
31 from ast import PyCF_ONLY_AST
32 import codeop
32 import codeop
33 import functools
33 import functools
34 import hashlib
34 import hashlib
35 import linecache
35 import linecache
36 import operator
36 import operator
37 import time
37 import time
38 from contextlib import contextmanager
38 from contextlib import contextmanager
39
39
40 #-----------------------------------------------------------------------------
40 #-----------------------------------------------------------------------------
41 # Constants
41 # Constants
42 #-----------------------------------------------------------------------------
42 #-----------------------------------------------------------------------------
43
43
44 # Roughly equal to PyCF_MASK | PyCF_MASK_OBSOLETE as defined in pythonrun.h,
44 # Roughly equal to PyCF_MASK | PyCF_MASK_OBSOLETE as defined in pythonrun.h,
45 # this is used as a bitmask to extract future-related code flags.
45 # this is used as a bitmask to extract future-related code flags.
46 PyCF_MASK = functools.reduce(operator.or_,
46 PyCF_MASK = functools.reduce(operator.or_,
47 (getattr(__future__, fname).compiler_flag
47 (getattr(__future__, fname).compiler_flag
48 for fname in __future__.all_feature_names))
48 for fname in __future__.all_feature_names))
49
49
50 #-----------------------------------------------------------------------------
50 #-----------------------------------------------------------------------------
51 # Local utilities
51 # Local utilities
52 #-----------------------------------------------------------------------------
52 #-----------------------------------------------------------------------------
53
53
54 def code_name(code, number=0):
54 def code_name(code, number=0):
55 """ Compute a (probably) unique name for code for caching.
55 """ Compute a (probably) unique name for code for caching.
56
56
57 This now expects code to be unicode.
57 This now expects code to be unicode.
58 """
58 """
59 hash_digest = hashlib.sha1(code.encode("utf-8")).hexdigest()
59 hash_digest = hashlib.sha1(code.encode("utf-8")).hexdigest()
60 # Include the number and 12 characters of the hash in the name. It's
60 # Include the number and 12 characters of the hash in the name. It's
61 # pretty much impossible that in a single session we'll have collisions
61 # pretty much impossible that in a single session we'll have collisions
62 # even with truncated hashes, and the full one makes tracebacks too long
62 # even with truncated hashes, and the full one makes tracebacks too long
63 return '<ipython-input-{0}-{1}>'.format(number, hash_digest[:12])
63 return '<ipython-input-{0}-{1}>'.format(number, hash_digest[:12])
64
64
65 #-----------------------------------------------------------------------------
65 #-----------------------------------------------------------------------------
66 # Classes and functions
66 # Classes and functions
67 #-----------------------------------------------------------------------------
67 #-----------------------------------------------------------------------------
68
68
69 class CachingCompiler(codeop.Compile):
69 class CachingCompiler(codeop.Compile):
70 """A compiler that caches code compiled from interactive statements.
70 """A compiler that caches code compiled from interactive statements.
71 """
71 """
72
72
73 def __init__(self):
73 def __init__(self):
74 codeop.Compile.__init__(self)
74 codeop.Compile.__init__(self)
75
75
76 # Caching a dictionary { filename: execution_count } for nicely
76 # Caching a dictionary { filename: execution_count } for nicely
77 # rendered tracebacks. The filename corresponds to the filename
77 # rendered tracebacks. The filename corresponds to the filename
78 # argument used for the builtins.compile function.
78 # argument used for the builtins.compile function.
79 self._filename_map = {}
79 self._filename_map = {}
80
80
81 def ast_parse(self, source, filename='<unknown>', symbol='exec'):
81 def ast_parse(self, source, filename='<unknown>', symbol='exec'):
82 """Parse code to an AST with the current compiler flags active.
82 """Parse code to an AST with the current compiler flags active.
83
83
84 Arguments are exactly the same as ast.parse (in the standard library),
84 Arguments are exactly the same as ast.parse (in the standard library),
85 and are passed to the built-in compile function."""
85 and are passed to the built-in compile function."""
86 return compile(source, filename, symbol, self.flags | PyCF_ONLY_AST, 1)
86 return compile(source, filename, symbol, self.flags | PyCF_ONLY_AST, 1)
87
87
88 def reset_compiler_flags(self):
88 def reset_compiler_flags(self):
89 """Reset compiler flags to default state."""
89 """Reset compiler flags to default state."""
90 # This value is copied from codeop.Compile.__init__, so if that ever
90 # This value is copied from codeop.Compile.__init__, so if that ever
91 # changes, it will need to be updated.
91 # changes, it will need to be updated.
92 self.flags = codeop.PyCF_DONT_IMPLY_DEDENT
92 self.flags = codeop.PyCF_DONT_IMPLY_DEDENT
93
93
94 @property
94 @property
95 def compiler_flags(self):
95 def compiler_flags(self):
96 """Flags currently active in the compilation process.
96 """Flags currently active in the compilation process.
97 """
97 """
98 return self.flags
98 return self.flags
99
99
100 def get_code_name(self, raw_code, transformed_code, number):
100 def get_code_name(self, raw_code, transformed_code, number):
101 """Compute filename given the code, and the cell number.
101 """Compute filename given the code, and the cell number.
102
102
103 Parameters
103 Parameters
104 ----------
104 ----------
105 raw_code : str
105 raw_code : str
106 The raw cell code.
106 The raw cell code.
107 transformed_code : str
107 transformed_code : str
108 The executable Python source code to cache and compile.
108 The executable Python source code to cache and compile.
109 number : int
109 number : int
110 A number which forms part of the code's name. Used for the execution
110 A number which forms part of the code's name. Used for the execution
111 counter.
111 counter.
112
112
113 Returns
113 Returns
114 -------
114 -------
115 The computed filename.
115 The computed filename.
116 """
116 """
117 return code_name(transformed_code, number)
117 return code_name(transformed_code, number)
118
118
119 def cache(self, transformed_code, number=0, raw_code=None):
119 def cache(self, transformed_code, number=0, raw_code=None):
120 """Make a name for a block of code, and cache the code.
120 """Make a name for a block of code, and cache the code.
121
121
122 Parameters
122 Parameters
123 ----------
123 ----------
124 transformed_code : str
124 transformed_code : str
125 The executable Python source code to cache and compile.
125 The executable Python source code to cache and compile.
126 number : int
126 number : int
127 A number which forms part of the code's name. Used for the execution
127 A number which forms part of the code's name. Used for the execution
128 counter.
128 counter.
129 raw_code : str
129 raw_code : str
130 The raw code before transformation, if None, set to `transformed_code`.
130 The raw code before transformation, if None, set to `transformed_code`.
131
131
132 Returns
132 Returns
133 -------
133 -------
134 The name of the cached code (as a string). Pass this as the filename
134 The name of the cached code (as a string). Pass this as the filename
135 argument to compilation, so that tracebacks are correctly hooked up.
135 argument to compilation, so that tracebacks are correctly hooked up.
136 """
136 """
137 if raw_code is None:
137 if raw_code is None:
138 raw_code = transformed_code
138 raw_code = transformed_code
139
139
140 name = self.get_code_name(raw_code, transformed_code, number)
140 name = self.get_code_name(raw_code, transformed_code, number)
141
141
142 # Save the execution count
142 # Save the execution count
143 self._filename_map[name] = number
143 self._filename_map[name] = number
144
144
145 # Since Python 2.5, setting mtime to `None` means the lines will
145 # Since Python 2.5, setting mtime to `None` means the lines will
146 # never be removed by `linecache.checkcache`. This means all the
146 # never be removed by `linecache.checkcache`. This means all the
147 # monkeypatching has *never* been necessary, since this code was
147 # monkeypatching has *never* been necessary, since this code was
148 # only added in 2010, at which point IPython had already stopped
148 # only added in 2010, at which point IPython had already stopped
149 # supporting Python 2.4.
149 # supporting Python 2.4.
150 #
150 #
151 # Note that `linecache.clearcache` and `linecache.updatecache` may
151 # Note that `linecache.clearcache` and `linecache.updatecache` may
152 # still remove our code from the cache, but those show explicit
152 # still remove our code from the cache, but those show explicit
153 # intent, and we should not try to interfere. Normally the former
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
154 # is never called except when out of memory, and the latter is only
155 # called for lines *not* in the cache.
155 # called for lines *not* in the cache.
156 entry = (
156 entry = (
157 len(transformed_code),
157 len(transformed_code),
158 None,
158 None,
159 [line + "\n" for line in transformed_code.splitlines()],
159 [line + "\n" for line in transformed_code.splitlines()],
160 name,
160 name,
161 )
161 )
162 linecache.cache[name] = entry
162 linecache.cache[name] = entry
163 return name
163 return name
164
164
165 @contextmanager
165 @contextmanager
166 def extra_flags(self, flags):
166 def extra_flags(self, flags):
167 ## bits that we'll set to 1
167 ## bits that we'll set to 1
168 turn_on_bits = ~self.flags & flags
168 turn_on_bits = ~self.flags & flags
169
169
170
170
171 self.flags = self.flags | flags
171 self.flags = self.flags | flags
172 try:
172 try:
173 yield
173 yield
174 finally:
174 finally:
175 # turn off only the bits we turned on so that something like
175 # turn off only the bits we turned on so that something like
176 # __future__ that set flags stays.
176 # __future__ that set flags stays.
177 self.flags &= ~turn_on_bits
177 self.flags &= ~turn_on_bits
178
178
179
179
180 def check_linecache_ipython(*args):
180 def check_linecache_ipython(*args):
181 """Deprecated since IPython 8.6. Call linecache.checkcache() directly.
181 """Deprecated since IPython 8.6. Call linecache.checkcache() directly.
182
182
183 It was already not necessary to call this function directly. If no
183 It was already not necessary to call this function directly. If no
184 CachingCompiler had been created, this function would fail badly. If
184 CachingCompiler had been created, this function would fail badly. If
185 an instance had been created, this function would've been monkeypatched
185 an instance had been created, this function would've been monkeypatched
186 into place.
186 into place.
187
187
188 As of IPython 8.6, the monkeypatching has gone away entirely. But there
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
189 were still internal callers of this function, so maybe external callers
190 also existed?
190 also existed?
191 """
191 """
192 import warnings
192 import warnings
193
193
194 warnings.warn("Just call linecache.checkcache() directly.", DeprecationWarning)
194 warnings.warn(
195 "Deprecated Since IPython 8.6, Just call linecache.checkcache() directly.",
196 DeprecationWarning,
197 stacklevel=2,
198 )
195 linecache.checkcache()
199 linecache.checkcache()
General Comments 0
You need to be logged in to leave comments. Login now