##// END OF EJS Templates
embed(): Default to the future compile flags of the calling frame.
Bradley M. Froehle -
Show More
@@ -1,131 +1,144 b''
1 1 """Compiler tools with improved interactive support.
2 2
3 3 Provides compilation machinery similar to codeop, but with caching support so
4 4 we can provide interactive tracebacks.
5 5
6 6 Authors
7 7 -------
8 8 * Robert Kern
9 9 * Fernando Perez
10 10 * Thomas Kluyver
11 11 """
12 12
13 13 # Note: though it might be more natural to name this module 'compiler', that
14 14 # name is in the stdlib and name collisions with the stdlib tend to produce
15 15 # weird problems (often with third-party tools).
16 16
17 17 #-----------------------------------------------------------------------------
18 18 # Copyright (C) 2010-2011 The IPython Development Team.
19 19 #
20 20 # Distributed under the terms of the BSD License.
21 21 #
22 22 # The full license is in the file COPYING.txt, distributed with this software.
23 23 #-----------------------------------------------------------------------------
24 24
25 25 #-----------------------------------------------------------------------------
26 26 # Imports
27 27 #-----------------------------------------------------------------------------
28 28 from __future__ import print_function
29 29
30 30 # Stdlib imports
31 import __future__
31 32 from ast import PyCF_ONLY_AST
32 33 import codeop
34 import functools
33 35 import hashlib
34 36 import linecache
37 import operator
35 38 import time
36 39
37 40 #-----------------------------------------------------------------------------
41 # Constants
42 #-----------------------------------------------------------------------------
43
44 # Roughtly 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.
46 PyCF_MASK = functools.reduce(operator.or_,
47 (getattr(__future__, fname).compiler_flag
48 for fname in __future__.all_feature_names))
49
50 #-----------------------------------------------------------------------------
38 51 # Local utilities
39 52 #-----------------------------------------------------------------------------
40 53
41 54 def code_name(code, number=0):
42 55 """ Compute a (probably) unique name for code for caching.
43 56
44 57 This now expects code to be unicode.
45 58 """
46 59 hash_digest = hashlib.md5(code.encode("utf-8")).hexdigest()
47 60 # Include the number and 12 characters of the hash in the name. It's
48 61 # pretty much impossible that in a single session we'll have collisions
49 62 # even with truncated hashes, and the full one makes tracebacks too long
50 63 return '<ipython-input-{0}-{1}>'.format(number, hash_digest[:12])
51 64
52 65 #-----------------------------------------------------------------------------
53 66 # Classes and functions
54 67 #-----------------------------------------------------------------------------
55 68
56 69 class CachingCompiler(codeop.Compile):
57 70 """A compiler that caches code compiled from interactive statements.
58 71 """
59 72
60 73 def __init__(self):
61 74 codeop.Compile.__init__(self)
62 75
63 76 # This is ugly, but it must be done this way to allow multiple
64 77 # simultaneous ipython instances to coexist. Since Python itself
65 78 # directly accesses the data structures in the linecache module, and
66 79 # the cache therein is global, we must work with that data structure.
67 80 # We must hold a reference to the original checkcache routine and call
68 81 # that in our own check_cache() below, but the special IPython cache
69 82 # must also be shared by all IPython instances. If we were to hold
70 83 # separate caches (one in each CachingCompiler instance), any call made
71 84 # by Python itself to linecache.checkcache() would obliterate the
72 85 # cached data from the other IPython instances.
73 86 if not hasattr(linecache, '_ipython_cache'):
74 87 linecache._ipython_cache = {}
75 88 if not hasattr(linecache, '_checkcache_ori'):
76 89 linecache._checkcache_ori = linecache.checkcache
77 90 # Now, we must monkeypatch the linecache directly so that parts of the
78 91 # stdlib that call it outside our control go through our codepath
79 92 # (otherwise we'd lose our tracebacks).
80 93 linecache.checkcache = self.check_cache
81 94
82 95 def ast_parse(self, source, filename='<unknown>', symbol='exec'):
83 96 """Parse code to an AST with the current compiler flags active.
84 97
85 98 Arguments are exactly the same as ast.parse (in the standard library),
86 99 and are passed to the built-in compile function."""
87 100 return compile(source, filename, symbol, self.flags | PyCF_ONLY_AST, 1)
88 101
89 102 def reset_compiler_flags(self):
90 103 """Reset compiler flags to default state."""
91 104 # This value is copied from codeop.Compile.__init__, so if that ever
92 105 # changes, it will need to be updated.
93 106 self.flags = codeop.PyCF_DONT_IMPLY_DEDENT
94 107
95 108 @property
96 109 def compiler_flags(self):
97 110 """Flags currently active in the compilation process.
98 111 """
99 112 return self.flags
100 113
101 114 def cache(self, code, number=0):
102 115 """Make a name for a block of code, and cache the code.
103 116
104 117 Parameters
105 118 ----------
106 119 code : str
107 120 The Python source code to cache.
108 121 number : int
109 122 A number which forms part of the code's name. Used for the execution
110 123 counter.
111 124
112 125 Returns
113 126 -------
114 127 The name of the cached code (as a string). Pass this as the filename
115 128 argument to compilation, so that tracebacks are correctly hooked up.
116 129 """
117 130 name = code_name(code, number)
118 131 entry = (len(code), time.time(),
119 132 [line+'\n' for line in code.splitlines()], name)
120 133 linecache.cache[name] = entry
121 134 linecache._ipython_cache[name] = entry
122 135 return name
123 136
124 137 def check_cache(self, *args):
125 138 """Call linecache.checkcache() safely protecting our cached values.
126 139 """
127 140 # First call the orignal checkcache as intended
128 141 linecache._checkcache_ori(*args)
129 142 # Then, update back the cache with our data, so that tracebacks related
130 143 # to our compiled codes can be produced.
131 144 linecache.cache.update(linecache._ipython_cache)
@@ -1,283 +1,296 b''
1 1 # encoding: utf-8
2 2 """
3 3 An embedded IPython shell.
4 4
5 5 Authors:
6 6
7 7 * Brian Granger
8 8 * Fernando Perez
9 9
10 10 Notes
11 11 -----
12 12 """
13 13
14 14 #-----------------------------------------------------------------------------
15 15 # Copyright (C) 2008-2011 The IPython Development Team
16 16 #
17 17 # Distributed under the terms of the BSD License. The full license is in
18 18 # the file COPYING, distributed as part of this software.
19 19 #-----------------------------------------------------------------------------
20 20
21 21 #-----------------------------------------------------------------------------
22 22 # Imports
23 23 #-----------------------------------------------------------------------------
24 24
25 25 from __future__ import with_statement
26 26
27 27 import sys
28 28 import warnings
29 29
30 30 # We need to use nested to support python 2.6, once we move to >=2.7, we can
31 31 # use the with keyword's new builtin support for nested managers
32 32 try:
33 33 from contextlib import nested
34 34 except:
35 35 from IPython.utils.nested_context import nested
36 36
37 from IPython.core import ultratb
37 from IPython.core import ultratb, compilerop
38 38 from IPython.core.magic import Magics, magics_class, line_magic
39 39 from IPython.frontend.terminal.interactiveshell import TerminalInteractiveShell
40 40 from IPython.frontend.terminal.ipapp import load_default_config
41 41
42 42 from IPython.utils.traitlets import Bool, CBool, Unicode
43 43 from IPython.utils.io import ask_yes_no
44 44
45 45
46 46 #-----------------------------------------------------------------------------
47 47 # Classes and functions
48 48 #-----------------------------------------------------------------------------
49 49
50 50 # This is an additional magic that is exposed in embedded shells.
51 51 @magics_class
52 52 class EmbeddedMagics(Magics):
53 53
54 54 @line_magic
55 55 def kill_embedded(self, parameter_s=''):
56 56 """%kill_embedded : deactivate for good the current embedded IPython.
57 57
58 58 This function (after asking for confirmation) sets an internal flag so
59 59 that an embedded IPython will never activate again. This is useful to
60 60 permanently disable a shell that is being called inside a loop: once
61 61 you've figured out what you needed from it, you may then kill it and
62 62 the program will then continue to run without the interactive shell
63 63 interfering again.
64 64 """
65 65
66 66 kill = ask_yes_no("Are you sure you want to kill this embedded instance "
67 67 "(y/n)? [y/N] ",'n')
68 68 if kill:
69 69 self.shell.embedded_active = False
70 70 print ("This embedded IPython will not reactivate anymore "
71 71 "once you exit.")
72 72
73 73
74 74 class InteractiveShellEmbed(TerminalInteractiveShell):
75 75
76 76 dummy_mode = Bool(False)
77 77 exit_msg = Unicode('')
78 78 embedded = CBool(True)
79 79 embedded_active = CBool(True)
80 80 # Like the base class display_banner is not configurable, but here it
81 81 # is True by default.
82 82 display_banner = CBool(True)
83 83
84 84 def __init__(self, config=None, ipython_dir=None, user_ns=None,
85 85 user_module=None, custom_exceptions=((),None),
86 86 usage=None, banner1=None, banner2=None,
87 87 display_banner=None, exit_msg=u'', user_global_ns=None):
88 88
89 89 if user_global_ns is not None:
90 90 warnings.warn("user_global_ns has been replaced by user_module. The\
91 91 parameter will be ignored.", DeprecationWarning)
92 92
93 93 super(InteractiveShellEmbed,self).__init__(
94 94 config=config, ipython_dir=ipython_dir, user_ns=user_ns,
95 95 user_module=user_module, custom_exceptions=custom_exceptions,
96 96 usage=usage, banner1=banner1, banner2=banner2,
97 97 display_banner=display_banner
98 98 )
99 99
100 100 self.exit_msg = exit_msg
101 101
102 102 # don't use the ipython crash handler so that user exceptions aren't
103 103 # trapped
104 104 sys.excepthook = ultratb.FormattedTB(color_scheme=self.colors,
105 105 mode=self.xmode,
106 106 call_pdb=self.pdb)
107 107
108 108 def init_sys_modules(self):
109 109 pass
110 110
111 111 def init_magics(self):
112 112 super(InteractiveShellEmbed, self).init_magics()
113 113 self.register_magics(EmbeddedMagics)
114 114
115 115 def __call__(self, header='', local_ns=None, module=None, dummy=None,
116 116 stack_depth=1, global_ns=None):
117 117 """Activate the interactive interpreter.
118 118
119 119 __call__(self,header='',local_ns=None,module=None,dummy=None) -> Start
120 120 the interpreter shell with the given local and global namespaces, and
121 121 optionally print a header string at startup.
122 122
123 123 The shell can be globally activated/deactivated using the
124 124 dummy_mode attribute. This allows you to turn off a shell used
125 125 for debugging globally.
126 126
127 127 However, *each* time you call the shell you can override the current
128 128 state of dummy_mode with the optional keyword parameter 'dummy'. For
129 129 example, if you set dummy mode on with IPShell.dummy_mode = True, you
130 130 can still have a specific call work by making it as IPShell(dummy=False).
131 131 """
132 132
133 133 # If the user has turned it off, go away
134 134 if not self.embedded_active:
135 135 return
136 136
137 137 # Normal exits from interactive mode set this flag, so the shell can't
138 138 # re-enter (it checks this variable at the start of interactive mode).
139 139 self.exit_now = False
140 140
141 141 # Allow the dummy parameter to override the global __dummy_mode
142 142 if dummy or (dummy != 0 and self.dummy_mode):
143 143 return
144 144
145 145 if self.has_readline:
146 146 self.set_readline_completer()
147 147
148 148 # self.banner is auto computed
149 149 if header:
150 150 self.old_banner2 = self.banner2
151 151 self.banner2 = self.banner2 + '\n' + header + '\n'
152 152 else:
153 153 self.old_banner2 = ''
154 154
155 155 # Call the embedding code with a stack depth of 1 so it can skip over
156 156 # our call and get the original caller's namespaces.
157 157 self.mainloop(local_ns, module, stack_depth=stack_depth, global_ns=global_ns)
158 158
159 159 self.banner2 = self.old_banner2
160 160
161 161 if self.exit_msg is not None:
162 162 print self.exit_msg
163 163
164 164 def mainloop(self, local_ns=None, module=None, stack_depth=0,
165 display_banner=None, global_ns=None):
165 display_banner=None, global_ns=None, compile_flags=None):
166 166 """Embeds IPython into a running python program.
167 167
168 168 Input:
169 169
170 170 - header: An optional header message can be specified.
171 171
172 172 - local_ns, module: working local namespace (a dict) and module (a
173 173 module or similar object). If given as None, they are automatically
174 174 taken from the scope where the shell was called, so that
175 175 program variables become visible.
176 176
177 177 - stack_depth: specifies how many levels in the stack to go to
178 178 looking for namespaces (when local_ns or module is None). This
179 179 allows an intermediate caller to make sure that this function gets
180 180 the namespace from the intended level in the stack. By default (0)
181 181 it will get its locals and globals from the immediate caller.
182 182
183 - compile_flags: A bit field identifying the __future__ features
184 that are enabled, as passed to the builtin `compile` function. If
185 given as None, they are automatically taken from the scope where the
186 shell was called.
187
183 188 Warning: it's possible to use this in a program which is being run by
184 189 IPython itself (via %run), but some funny things will happen (a few
185 190 globals get overwritten). In the future this will be cleaned up, as
186 191 there is no fundamental reason why it can't work perfectly."""
187 192
188 193 if (global_ns is not None) and (module is None):
189 194 class DummyMod(object):
190 195 """A dummy module object for embedded IPython."""
191 196 pass
192 197 warnings.warn("global_ns is deprecated, use module instead.", DeprecationWarning)
193 198 module = DummyMod()
194 199 module.__dict__ = global_ns
195 200
196 201 # Get locals and globals from caller
197 202 if (local_ns is None or module is None) and self.default_user_namespaces:
198 203 call_frame = sys._getframe(stack_depth).f_back
199 204
200 205 if local_ns is None:
201 206 local_ns = call_frame.f_locals
202 207 if module is None:
203 208 global_ns = call_frame.f_globals
204 209 module = sys.modules[global_ns['__name__']]
210 if compile_flags is None:
211 compile_flags = (call_frame.f_code.co_flags &
212 compilerop.PyCF_MASK)
205 213
206 214 # Save original namespace and module so we can restore them after
207 215 # embedding; otherwise the shell doesn't shut down correctly.
208 216 orig_user_module = self.user_module
209 217 orig_user_ns = self.user_ns
218 orig_compile_flags = self.compile.flags
210 219
211 220 # Update namespaces and fire up interpreter
212 221
213 222 # The global one is easy, we can just throw it in
214 223 if module is not None:
215 224 self.user_module = module
216 225
217 226 # But the user/local one is tricky: ipython needs it to store internal
218 227 # data, but we also need the locals. We'll throw our hidden variables
219 228 # like _ih and get_ipython() into the local namespace, but delete them
220 229 # later.
221 230 if local_ns is not None:
222 231 self.user_ns = local_ns
223 232 self.init_user_ns()
224 233
234 # Compiler flags
235 self.compile.flags = compile_flags
236
225 237 # Patch for global embedding to make sure that things don't overwrite
226 238 # user globals accidentally. Thanks to Richard <rxe@renre-europe.com>
227 239 # FIXME. Test this a bit more carefully (the if.. is new)
228 240 # N.B. This can't now ever be called. Not sure what it was for.
229 241 # And now, since it wasn't called in the previous version, I'm
230 242 # commenting out these lines so they can't be called with my new changes
231 243 # --TK, 2011-12-10
232 244 #if local_ns is None and module is None:
233 245 # self.user_global_ns.update(__main__.__dict__)
234 246
235 247 # make sure the tab-completer has the correct frame information, so it
236 248 # actually completes using the frame's locals/globals
237 249 self.set_completer_frame()
238 250
239 251 with nested(self.builtin_trap, self.display_trap):
240 252 self.interact(display_banner=display_banner)
241 253
242 254 # now, purge out the local namespace of IPython's hidden variables.
243 255 if local_ns is not None:
244 256 for name in self.user_ns_hidden:
245 257 local_ns.pop(name, None)
246 258
247 259 # Restore original namespace so shell can shut down when we exit.
248 260 self.user_module = orig_user_module
249 261 self.user_ns = orig_user_ns
262 self.compile.flags = orig_compile_flags
250 263
251 264 _embedded_shell = None
252 265
253 266
254 267 def embed(**kwargs):
255 268 """Call this to embed IPython at the current point in your program.
256 269
257 270 The first invocation of this will create an :class:`InteractiveShellEmbed`
258 271 instance and then call it. Consecutive calls just call the already
259 272 created instance.
260 273
261 274 Here is a simple example::
262 275
263 276 from IPython import embed
264 277 a = 10
265 278 b = 20
266 279 embed('First time')
267 280 c = 30
268 281 d = 40
269 282 embed
270 283
271 284 Full customization can be done by passing a :class:`Struct` in as the
272 285 config argument.
273 286 """
274 287 config = kwargs.get('config')
275 288 header = kwargs.pop('header', u'')
276 289 if config is None:
277 290 config = load_default_config()
278 291 config.InteractiveShellEmbed = config.TerminalInteractiveShell
279 292 kwargs['config'] = config
280 293 global _embedded_shell
281 294 if _embedded_shell is None:
282 295 _embedded_shell = InteractiveShellEmbed(**kwargs)
283 296 _embedded_shell(header=header, stack_depth=2)
General Comments 0
You need to be logged in to leave comments. Login now