##// END OF EJS Templates
Remove 2.3 compatibility, minor cleanups.
Fernando Perez -
Show More
@@ -1,608 +1,606 b''
1 ''' IPython customization API
1 """IPython customization API
2 2
3 3 Your one-stop module for configuring & extending ipython
4 4
5 5 The API will probably break when ipython 1.0 is released, but so
6 6 will the other configuration method (rc files).
7 7
8 8 All names prefixed by underscores are for internal use, not part
9 9 of the public api.
10 10
11 11 Below is an example that you can just put to a module and import from ipython.
12 12
13 13 A good practice is to install the config script below as e.g.
14 14
15 15 ~/.ipython/my_private_conf.py
16 16
17 17 And do
18 18
19 19 import_mod my_private_conf
20 20
21 21 in ~/.ipython/ipythonrc
22 22
23 23 That way the module is imported at startup and you can have all your
24 24 personal configuration (as opposed to boilerplate ipythonrc-PROFILENAME
25 25 stuff) in there.
26 26
27 27 -----------------------------------------------
28 28 import IPython.ipapi
29 29 ip = IPython.ipapi.get()
30 30
31 31 def ankka_f(self, arg):
32 32 print "Ankka",self,"says uppercase:",arg.upper()
33 33
34 34 ip.expose_magic("ankka",ankka_f)
35 35
36 36 ip.magic('alias sayhi echo "Testing, hi ok"')
37 37 ip.magic('alias helloworld echo "Hello world"')
38 38 ip.system('pwd')
39 39
40 40 ip.ex('import re')
41 41 ip.ex("""
42 42 def funcci(a,b):
43 43 print a+b
44 44 print funcci(3,4)
45 45 """)
46 46 ip.ex("funcci(348,9)")
47 47
48 48 def jed_editor(self,filename, linenum=None):
49 49 print "Calling my own editor, jed ... via hook!"
50 50 import os
51 51 if linenum is None: linenum = 0
52 52 os.system('jed +%d %s' % (linenum, filename))
53 53 print "exiting jed"
54 54
55 55 ip.set_hook('editor',jed_editor)
56 56
57 57 o = ip.options
58 58 o.autocall = 2 # FULL autocall mode
59 59
60 60 print "done!"
61 '''
61 """
62
63 #-----------------------------------------------------------------------------
64 # Modules and globals
62 65
63 66 # stdlib imports
64 67 import __builtin__
65 68 import sys
66 69
67 try: # Python 2.3 compatibility
68 set
69 except NameError:
70 import sets
71 set = sets.Set
70 # contains the most recently instantiated IPApi
71 _RECENT_IP = None
72
73 #-----------------------------------------------------------------------------
74 # Code begins
72 75
73 # our own
74 #from IPython.genutils import warn,error
75
76 76 class TryNext(Exception):
77 77 """Try next hook exception.
78 78
79 79 Raise this in your hook function to indicate that the next hook handler
80 80 should be used to handle the operation. If you pass arguments to the
81 81 constructor those arguments will be used by the next hook instead of the
82 82 original ones.
83 83 """
84 84
85 85 def __init__(self, *args, **kwargs):
86 86 self.args = args
87 87 self.kwargs = kwargs
88 88
89 89 class UsageError(Exception):
90 90 """ Error in magic function arguments, etc.
91 91
92 92 Something that probably won't warrant a full traceback, but should
93 93 nevertheless interrupt a macro / batch file.
94 94 """
95 95
96 96 class IPyAutocall:
97 97 """ Instances of this class are always autocalled
98 98
99 99 This happens regardless of 'autocall' variable state. Use this to
100 100 develop macro-like mechanisms.
101 101 """
102 102
103 103 def set_ip(self,ip):
104 104 """ Will be used to set _ip point to current ipython instance b/f call
105 105
106 106 Override this method if you don't want this to happen.
107 107
108 108 """
109 109 self._ip = ip
110 110
111 111
112 # contains the most recently instantiated IPApi
113 112
114 113 class IPythonNotRunning:
115 114 """Dummy do-nothing class.
116 115
117 116 Instances of this class return a dummy attribute on all accesses, which
118 117 can be called and warns. This makes it easier to write scripts which use
119 118 the ipapi.get() object for informational purposes to operate both with and
120 119 without ipython. Obviously code which uses the ipython object for
121 120 computations will not work, but this allows a wider range of code to
122 121 transparently work whether ipython is being used or not."""
123 122
124 123 def __init__(self,warn=True):
125 124 if warn:
126 125 self.dummy = self._dummy_warn
127 126 else:
128 127 self.dummy = self._dummy_silent
129 128
130 129 def __str__(self):
131 130 return "<IPythonNotRunning>"
132 131
133 132 __repr__ = __str__
134 133
135 134 def __getattr__(self,name):
136 135 return self.dummy
137 136
138 137 def _dummy_warn(self,*args,**kw):
139 138 """Dummy function, which doesn't do anything but warn."""
140 139
141 140 print ("IPython is not running, this is a dummy no-op function")
142 141
143 142 def _dummy_silent(self,*args,**kw):
144 143 """Dummy function, which doesn't do anything and emits no warnings."""
145 144 pass
146 145
147 _recent = None
148
149 146
150 147 def get(allow_dummy=False,dummy_warn=True):
151 148 """Get an IPApi object.
152 149
153 150 If allow_dummy is true, returns an instance of IPythonNotRunning
154 151 instead of None if not running under IPython.
155 152
156 153 If dummy_warn is false, the dummy instance will be completely silent.
157 154
158 155 Running this should be the first thing you do when writing extensions that
159 156 can be imported as normal modules. You can then direct all the
160 157 configuration operations against the returned object.
161 158 """
162 global _recent
163 if allow_dummy and not _recent:
164 _recent = IPythonNotRunning(dummy_warn)
165 return _recent
159 global _RECENT_IP
160 if allow_dummy and not _RECENT_IP:
161 _RECENT_IP = IPythonNotRunning(dummy_warn)
162 return _RECENT_IP
166 163
167 164 class IPApi:
168 165 """ The actual API class for configuring IPython
169 166
170 167 You should do all of the IPython configuration by getting an IPApi object
171 168 with IPython.ipapi.get() and using the attributes and methods of the
172 169 returned object."""
173 170
174 171 def __init__(self,ip):
175 172
173 global _RECENT_IP
174
176 175 # All attributes exposed here are considered to be the public API of
177 176 # IPython. As needs dictate, some of these may be wrapped as
178 177 # properties.
179 178
180 179 self.magic = ip.ipmagic
181 180
182 181 self.system = ip.system
183 182
184 183 self.set_hook = ip.set_hook
185 184
186 185 self.set_custom_exc = ip.set_custom_exc
187 186
188 187 self.user_ns = ip.user_ns
189 188 self.user_ns['_ip'] = self
190 189
191 190 self.set_crash_handler = ip.set_crash_handler
192 191
193 192 # Session-specific data store, which can be used to store
194 193 # data that should persist through the ipython session.
195 194 self.meta = ip.meta
196 195
197 196 # The ipython instance provided
198 197 self.IP = ip
199 198
200 199 self.extensions = {}
201 200
202 201 self.dbg = DebugTools(self)
203 202
204 global _recent
205 _recent = self
203 _RECENT_IP = self
206 204
207 205 # Use a property for some things which are added to the instance very
208 206 # late. I don't have time right now to disentangle the initialization
209 207 # order issues, so a property lets us delay item extraction while
210 208 # providing a normal attribute API.
211 209 def get_db(self):
212 210 """A handle to persistent dict-like database (a PickleShareDB object)"""
213 211 return self.IP.db
214 212
215 213 db = property(get_db,None,None,get_db.__doc__)
216 214
217 215 def get_options(self):
218 216 """All configurable variables."""
219 217
220 218 # catch typos by disabling new attribute creation. If new attr creation
221 # is in fact wanted (e.g. when exposing new options), do allow_new_attr(True)
222 # for the received rc struct.
219 # is in fact wanted (e.g. when exposing new options), do
220 # allow_new_attr(True) for the received rc struct.
223 221
224 222 self.IP.rc.allow_new_attr(False)
225 223 return self.IP.rc
226 224
227 225 options = property(get_options,None,None,get_options.__doc__)
228 226
229 227 def expose_magic(self,magicname, func):
230 228 ''' Expose own function as magic function for ipython
231 229
232 230 def foo_impl(self,parameter_s=''):
233 231 """My very own magic!. (Use docstrings, IPython reads them)."""
234 232 print 'Magic function. Passed parameter is between < >: <'+parameter_s+'>'
235 233 print 'The self object is:',self
236 234
237 235 ipapi.expose_magic("foo",foo_impl)
238 236 '''
239 237
240 238 import new
241 239 im = new.instancemethod(func,self.IP, self.IP.__class__)
242 240 old = getattr(self.IP, "magic_" + magicname, None)
243 241 if old:
244 242 self.dbg.debug_stack("Magic redefinition '%s', old %s" % (magicname,
245 243 old))
246 244
247 245 setattr(self.IP, "magic_" + magicname, im)
248 246
249 247 def ex(self,cmd):
250 248 """ Execute a normal python statement in user namespace """
251 249 exec cmd in self.user_ns
252 250
253 251 def ev(self,expr):
254 252 """ Evaluate python expression expr in user namespace
255 253
256 254 Returns the result of evaluation"""
257 255 return eval(expr,self.user_ns)
258 256
259 257 def runlines(self,lines):
260 258 """ Run the specified lines in interpreter, honoring ipython directives.
261 259
262 260 This allows %magic and !shell escape notations.
263 261
264 262 Takes either all lines in one string or list of lines.
265 263 """
266 264
267 265 def cleanup_ipy_script(script):
268 266 """ Make a script safe for _ip.runlines()
269 267
270 - Removes empty lines
271 - Suffixes all indented blocks that end with unindented lines with empty lines
272
268 - Removes empty lines Suffixes all indented blocks that end with
269 - unindented lines with empty lines
273 270 """
271
274 272 res = []
275 273 lines = script.splitlines()
276 274
277 275 level = 0
278 276 for l in lines:
279 277 lstripped = l.lstrip()
280 278 stripped = l.strip()
281 279 if not stripped:
282 280 continue
283 281 newlevel = len(l) - len(lstripped)
284 282 def is_secondary_block_start(s):
285 283 if not s.endswith(':'):
286 284 return False
287 285 if (s.startswith('elif') or
288 286 s.startswith('else') or
289 287 s.startswith('except') or
290 288 s.startswith('finally')):
291 289 return True
292 290
293 if level > 0 and newlevel == 0 and not is_secondary_block_start(stripped):
291 if level > 0 and newlevel == 0 and \
292 not is_secondary_block_start(stripped):
294 293 # add empty line
295 294 res.append('')
296 295
297 296 res.append(l)
298 297 level = newlevel
299 298 return '\n'.join(res) + '\n'
300 299
301 300 if isinstance(lines,basestring):
302 301 script = lines
303 302 else:
304 303 script = '\n'.join(lines)
305 304 clean=cleanup_ipy_script(script)
306 # print "_ip.runlines() script:\n",clean #dbg
305 # print "_ip.runlines() script:\n",clean # dbg
307 306 self.IP.runlines(clean)
307
308 308 def to_user_ns(self,vars, interactive = True):
309 309 """Inject a group of variables into the IPython user namespace.
310 310
311 311 Inputs:
312 312
313 313 - vars: string with variable names separated by whitespace, or a
314 314 dict with name/value pairs.
315 315
316 316 - interactive: if True (default), the var will be listed with
317 317 %whos et. al.
318 318
319 319 This utility routine is meant to ease interactive debugging work,
320 320 where you want to easily propagate some internal variable in your code
321 321 up to the interactive namespace for further exploration.
322 322
323 323 When you run code via %run, globals in your script become visible at
324 324 the interactive prompt, but this doesn't happen for locals inside your
325 325 own functions and methods. Yet when debugging, it is common to want
326 326 to explore some internal variables further at the interactive propmt.
327 327
328 328 Examples:
329 329
330 330 To use this, you first must obtain a handle on the ipython object as
331 331 indicated above, via:
332 332
333 333 import IPython.ipapi
334 334 ip = IPython.ipapi.get()
335 335
336 336 Once this is done, inside a routine foo() where you want to expose
337 337 variables x and y, you do the following:
338 338
339 339 def foo():
340 340 ...
341 341 x = your_computation()
342 342 y = something_else()
343 343
344 344 # This pushes x and y to the interactive prompt immediately, even
345 345 # if this routine crashes on the next line after:
346 346 ip.to_user_ns('x y')
347 347 ...
348 348
349 349 # To expose *ALL* the local variables from the function, use:
350 350 ip.to_user_ns(locals())
351 351
352 352 ...
353 353 # return
354 354
355 355
356 356 If you need to rename variables, the dict input makes it easy. For
357 357 example, this call exposes variables 'foo' as 'x' and 'bar' as 'y'
358 358 in IPython user namespace:
359 359
360 360 ip.to_user_ns(dict(x=foo,y=bar))
361 361 """
362 362
363 363 # print 'vars given:',vars # dbg
364 364
365 365 # We need a dict of name/value pairs to do namespace updates.
366 366 if isinstance(vars,dict):
367 367 # If a dict was given, no need to change anything.
368 368 vdict = vars
369 369 elif isinstance(vars,basestring):
370 370 # If a string with names was given, get the caller's frame to
371 371 # evaluate the given names in
372 372 cf = sys._getframe(1)
373 373 vdict = {}
374 374 for name in vars.split():
375 375 try:
376 376 vdict[name] = eval(name,cf.f_globals,cf.f_locals)
377 377 except:
378 378 print ('could not get var. %s from %s' %
379 379 (name,cf.f_code.co_name))
380 380 else:
381 381 raise ValueError('vars must be a string or a dict')
382 382
383 383 # Propagate variables to user namespace
384 384 self.user_ns.update(vdict)
385 385
386 386 # And configure interactive visibility
387 387 config_ns = self.IP.user_config_ns
388 388 if interactive:
389 389 for name,val in vdict.iteritems():
390 390 config_ns.pop(name,None)
391 391 else:
392 392 for name,val in vdict.iteritems():
393 393 config_ns[name] = val
394 394
395
396 395 def expand_alias(self,line):
397 396 """ Expand an alias in the command line
398 397
399 398 Returns the provided command line, possibly with the first word
400 399 (command) translated according to alias expansion rules.
401 400
402 401 [ipython]|16> _ip.expand_aliases("np myfile.txt")
403 402 <16> 'q:/opt/np/notepad++.exe myfile.txt'
404 403 """
405 404
406 405 pre,fn,rest = self.IP.split_user_input(line)
407 406 res = pre + self.IP.expand_aliases(fn,rest)
408 407 return res
409 408
410 409 def itpl(self, s, depth = 1):
411 410 """ Expand Itpl format string s.
412 411
413 412 Only callable from command line (i.e. prefilter results);
414 413 If you use in your scripts, you need to use a bigger depth!
415 414 """
416 415 return self.IP.var_expand(s, depth)
417 416
418 417 def defalias(self, name, cmd):
419 418 """ Define a new alias
420 419
421 420 _ip.defalias('bb','bldmake bldfiles')
422 421
423 422 Creates a new alias named 'bb' in ipython user namespace
424 423 """
425 424
426 425 self.dbg.check_hotname(name)
427 426
428
429 427 if name in self.IP.alias_table:
430 self.dbg.debug_stack("Alias redefinition: '%s' => '%s' (old '%s')" %
431 (name, cmd, self.IP.alias_table[name]))
432
428 self.dbg.debug_stack("Alias redefinition: '%s' => '%s' (old '%s')"
429 % (name, cmd, self.IP.alias_table[name]))
433 430
434 431 if callable(cmd):
435 432 self.IP.alias_table[name] = cmd
436 433 import IPython.shadowns
437 434 setattr(IPython.shadowns, name,cmd)
438 435 return
439 436
440 437 if isinstance(cmd,basestring):
441 438 nargs = cmd.count('%s')
442 439 if nargs>0 and cmd.find('%l')>=0:
443 raise Exception('The %s and %l specifiers are mutually exclusive '
444 'in alias definitions.')
440 raise Exception('The %s and %l specifiers are mutually '
441 'exclusive in alias definitions.')
445 442
446 443 self.IP.alias_table[name] = (nargs,cmd)
447 444 return
448 445
449 446 # just put it in - it's probably (0,'foo')
450 447 self.IP.alias_table[name] = cmd
451 448
452 449 def defmacro(self, *args):
453 450 """ Define a new macro
454 451
455 452 2 forms of calling:
456 453
457 454 mac = _ip.defmacro('print "hello"\nprint "world"')
458 455
459 456 (doesn't put the created macro on user namespace)
460 457
461 458 _ip.defmacro('build', 'bldmake bldfiles\nabld build winscw udeb')
462 459
463 460 (creates a macro named 'build' in user namespace)
464 461 """
465 462
466 463 import IPython.macro
467 464
468 465 if len(args) == 1:
469 466 return IPython.macro.Macro(args[0])
470 467 elif len(args) == 2:
471 468 self.user_ns[args[0]] = IPython.macro.Macro(args[1])
472 469 else:
473 470 return Exception("_ip.defmacro must be called with 1 or 2 arguments")
474 471
475 472 def set_next_input(self, s):
476 473 """ Sets the 'default' input string for the next command line.
477 474
478 475 Requires readline.
479 476
480 477 Example:
481 478
482 479 [D:\ipython]|1> _ip.set_next_input("Hello Word")
483 480 [D:\ipython]|2> Hello Word_ # cursor is here
484 481 """
485 482
486 483 self.IP.rl_next_input = s
487 484
488 485 def load(self, mod):
489 486 """ Load an extension.
490 487
491 488 Some modules should (or must) be 'load()':ed, rather than just imported.
492 489
493 490 Loading will do:
494 491
495 492 - run init_ipython(ip)
496 493 - run ipython_firstrun(ip)
497
498 494 """
495
499 496 if mod in self.extensions:
500 497 # just to make sure we don't init it twice
501 498 # note that if you 'load' a module that has already been
502 499 # imported, init_ipython gets run anyway
503 500
504 501 return self.extensions[mod]
505 502 __import__(mod)
506 503 m = sys.modules[mod]
507 504 if hasattr(m,'init_ipython'):
508 505 m.init_ipython(self)
509 506
510 507 if hasattr(m,'ipython_firstrun'):
511 508 already_loaded = self.db.get('firstrun_done', set())
512 509 if mod not in already_loaded:
513 510 m.ipython_firstrun(self)
514 511 already_loaded.add(mod)
515 512 self.db['firstrun_done'] = already_loaded
516 513
517 514 self.extensions[mod] = m
518 515 return m
519 516
520 517
521 518 class DebugTools:
522 519 """ Used for debugging mishaps in api usage
523 520
524 521 So far, tracing redefinitions is supported.
525 522 """
526 523
527 524 def __init__(self, ip):
528 525 self.ip = ip
529 526 self.debugmode = False
530 527 self.hotnames = set()
531 528
532 529 def hotname(self, name_to_catch):
533 530 self.hotnames.add(name_to_catch)
534 531
535 532 def debug_stack(self, msg = None):
536 533 if not self.debugmode:
537 534 return
538 535
539 536 import traceback
540 537 if msg is not None:
541 538 print '====== %s ========' % msg
542 539 traceback.print_stack()
543 540
544 541 def check_hotname(self,name):
545 542 if name in self.hotnames:
546 543 self.debug_stack( "HotName '%s' caught" % name)
547 544
545
548 546 def launch_new_instance(user_ns = None,shellclass = None):
549 547 """ Make and start a new ipython instance.
550 548
551 549 This can be called even without having an already initialized
552 550 ipython session running.
553 551
554 552 This is also used as the egg entry point for the 'ipython' script.
555 553
556 554 """
557 555 ses = make_session(user_ns,shellclass)
558 556 ses.mainloop()
559 557
560 558
561 559 def make_user_ns(user_ns = None):
562 560 """Return a valid user interactive namespace.
563 561
564 562 This builds a dict with the minimal information needed to operate as a
565 563 valid IPython user namespace, which you can pass to the various embedding
566 564 classes in ipython.
567 565 """
568 566
569 567 if user_ns is None:
570 568 # Set __name__ to __main__ to better match the behavior of the
571 569 # normal interpreter.
572 570 user_ns = {'__name__' :'__main__',
573 571 '__builtins__' : __builtin__,
574 572 }
575 573 else:
576 574 user_ns.setdefault('__name__','__main__')
577 575 user_ns.setdefault('__builtins__',__builtin__)
578 576
579 577 return user_ns
580 578
581 579
582 580 def make_user_global_ns(ns = None):
583 581 """Return a valid user global namespace.
584 582
585 583 Similar to make_user_ns(), but global namespaces are really only needed in
586 584 embedded applications, where there is a distinction between the user's
587 585 interactive namespace and the global one where ipython is running."""
588 586
589 587 if ns is None: ns = {}
590 588 return ns
591 589
592 590
593 591 def make_session(user_ns = None, shellclass = None):
594 592 """Makes, but does not launch an IPython session.
595 593
596 594 Later on you can call obj.mainloop() on the returned object.
597 595
598 596 Inputs:
599 597
600 598 - user_ns(None): a dict to be used as the user's namespace with initial
601 599 data.
602 600
603 601 WARNING: This should *not* be run when a session exists already."""
604 602
605 603 import IPython.Shell
606 604 if shellclass is None:
607 605 return IPython.Shell.start(user_ns)
608 606 return shellclass(user_ns = user_ns)
General Comments 0
You need to be logged in to leave comments. Login now