##// END OF EJS Templates
Merging with upstream
Fernando Perez -
r1996:7a6a76a5 merge
parent child Browse files
Show More

The requested changes are too big and content was truncated. Show full diff

@@ -0,0 +1,37 b''
1 # encoding: utf-8
2 """
3 Test the LineFrontEnd
4 """
5
6 __docformat__ = "restructuredtext en"
7
8 #-------------------------------------------------------------------------------
9 # Copyright (C) 2008 The IPython Development Team
10 #
11 # Distributed under the terms of the BSD License. The full license is
12 # in the file COPYING, distributed as part of this software.
13 #-------------------------------------------------------------------------------
14
15 from IPython.frontend.linefrontendbase import LineFrontEndBase
16 from copy import deepcopy
17 import nose.tools as nt
18
19 class ConcreteLineFrontEnd(LineFrontEndBase):
20 """ A concrete class to test the LineFrontEndBase.
21 """
22 def capture_output(self):
23 pass
24
25 def release_output(self):
26 pass
27
28
29 def test_is_complete():
30 """ Tests line completion heuristic.
31 """
32 frontend = ConcreteLineFrontEnd()
33 yield nt.assert_true, not frontend.is_complete('for x in \\')
34 yield nt.assert_true, not frontend.is_complete('for x in (1, ):')
35 yield nt.assert_true, frontend.is_complete('for x in (1, ):\n pass')
36
37
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
@@ -1,75 +1,75 b''
1 """ Greedy completer extension for IPython
1 """ Greedy completer extension for IPython
2
2
3 Normal tab completer refuses to evaluate nonsafe stuff. This will evaluate
3 Normal tab completer refuses to evaluate nonsafe stuff. This will evaluate
4 everything, so you need to consider the consequences of pressing tab
4 everything, so you need to consider the consequences of pressing tab
5 yourself!
5 yourself!
6
6
7 Note that this extension simplifies readline interaction by setting
7 Note that this extension simplifies readline interaction by setting
8 only whitespace as completer delimiter. If this works well, we will
8 only whitespace as completer delimiter. If this works well, we will
9 do the same in default completer.
9 do the same in default completer.
10
10
11 """
11 """
12 from IPython import generics,ipapi
12 from IPython import generics,ipapi
13 from IPython.genutils import dir2
13 from IPython.genutils import dir2
14
14
15 def attr_matches(self, text):
15 def attr_matches(self, text):
16 """Compute matches when text contains a dot.
16 """Compute matches when text contains a dot.
17
17
18 MONKEYPATCHED VERSION (ipy_greedycompleter.py)
18 MONKEYPATCHED VERSION (ipy_greedycompleter.py)
19
19
20 Assuming the text is of the form NAME.NAME....[NAME], and is
20 Assuming the text is of the form NAME.NAME....[NAME], and is
21 evaluatable in self.namespace or self.global_namespace, it will be
21 evaluatable in self.namespace or self.global_namespace, it will be
22 evaluated and its attributes (as revealed by dir()) are used as
22 evaluated and its attributes (as revealed by dir()) are used as
23 possible completions. (For class instances, class members are are
23 possible completions. (For class instances, class members are are
24 also considered.)
24 also considered.)
25
25
26 WARNING: this can still invoke arbitrary C code, if an object
26 WARNING: this can still invoke arbitrary C code, if an object
27 with a __getattr__ hook is evaluated.
27 with a __getattr__ hook is evaluated.
28
28
29 """
29 """
30 import re
30 import re
31
31
32 force_complete = 1
32 force_complete = 1
33 # Another option, seems to work great. Catches things like ''.<tab>
33 # Another option, seems to work great. Catches things like ''.<tab>
34 m = re.match(r"(\S+(\.\w+)*)\.(\w*)$", text)
34 m = re.match(r"(\S+(\.\w+)*)\.(\w*)$", text)
35
35
36 if m:
36 if m:
37 expr, attr = m.group(1, 3)
37 expr, attr = m.group(1, 3)
38 else:
38 else:
39 # force match - eval anything that ends with colon
39 # force match - eval anything that ends with colon
40 if not force_complete:
40 if not force_complete:
41 return []
41 return []
42
42
43 m2 = re.match(r"(.+)\.(\w*)$", self.lbuf)
43 m2 = re.match(r"(.+)\.(\w*)$", self.lbuf)
44 if not m2:
44 if not m2:
45 return []
45 return []
46 expr, attr = m2.group(1,2)
46 expr, attr = m2.group(1,2)
47
47
48
48
49 try:
49 try:
50 obj = eval(expr, self.namespace)
50 obj = eval(expr, self.namespace)
51 except:
51 except:
52 try:
52 try:
53 obj = eval(expr, self.global_namespace)
53 obj = eval(expr, self.global_namespace)
54 except:
54 except:
55 return []
55 return []
56
56
57 words = dir2(obj)
57 words = dir2(obj)
58
58
59 try:
59 try:
60 words = generics.complete_object(obj, words)
60 words = generics.complete_object(obj, words)
61 except ipapi.TryNext:
61 except ipapi.TryNext:
62 pass
62 pass
63 # Build match list to return
63 # Build match list to return
64 n = len(attr)
64 n = len(attr)
65 res = ["%s.%s" % (expr, w) for w in words if w[:n] == attr ]
65 res = ["%s.%s" % (expr, w) for w in words if w[:n] == attr ]
66 return res
66 return res
67
67
68 def main():
68 def main():
69 import readline
69 import IPython.rlineimpl as readline
70 readline.set_completer_delims(" \n\t")
70 readline.set_completer_delims(" \n\t")
71 # monkeypatch - the code will be folded to normal completer later on
71 # monkeypatch - the code will be folded to normal completer later on
72 import IPython.completer
72 import IPython.completer
73 IPython.completer.Completer.attr_matches = attr_matches
73 IPython.completer.Completer.attr_matches = attr_matches
74
74
75 main() No newline at end of file
75 main()
@@ -1,116 +1,114 b''
1 """ User configuration file for IPython
1 """ User configuration file for IPython
2
2
3 This is a more flexible and safe way to configure ipython than *rc files
3 This is a more flexible and safe way to configure ipython than *rc files
4 (ipythonrc, ipythonrc-pysh etc.)
4 (ipythonrc, ipythonrc-pysh etc.)
5
5
6 This file is always imported on ipython startup. You can import the
6 This file is always imported on ipython startup. You can import the
7 ipython extensions you need here (see IPython/Extensions directory).
7 ipython extensions you need here (see IPython/Extensions directory).
8
8
9 Feel free to edit this file to customize your ipython experience.
9 Feel free to edit this file to customize your ipython experience.
10
10
11 Note that as such this file does nothing, for backwards compatibility.
11 Note that as such this file does nothing, for backwards compatibility.
12 Consult e.g. file 'ipy_profile_sh.py' for an example of the things
12 Consult e.g. file 'ipy_profile_sh.py' for an example of the things
13 you can do here.
13 you can do here.
14
14
15 See http://ipython.scipy.org/moin/IpythonExtensionApi for detailed
15 See http://ipython.scipy.org/moin/IpythonExtensionApi for detailed
16 description on what you could do here.
16 description on what you could do here.
17 """
17 """
18
18
19 # Most of your config files and extensions will probably start with this import
19 # Most of your config files and extensions will probably start with this import
20
20
21 import IPython.ipapi
21 import IPython.ipapi
22 ip = IPython.ipapi.get()
22 ip = IPython.ipapi.get()
23
23
24 # You probably want to uncomment this if you did %upgrade -nolegacy
24 # You probably want to uncomment this if you did %upgrade -nolegacy
25 # import ipy_defaults
25 # import ipy_defaults
26
26
27 import os
27 import os
28
28
29 def main():
29 def main():
30
30
31 # uncomment if you want to get ipython -p sh behaviour
31 # uncomment if you want to get ipython -p sh behaviour
32 # without having to use command line switches
32 # without having to use command line switches
33 # import ipy_profile_sh
33 # import ipy_profile_sh
34
34
35 # Configure your favourite editor?
35 # Configure your favourite editor?
36 # Good idea e.g. for %edit os.path.isfile
36 # Good idea e.g. for %edit os.path.isfile
37
37
38 #import ipy_editors
38 #import ipy_editors
39
39
40 # Choose one of these:
40 # Choose one of these:
41
41
42 #ipy_editors.scite()
42 #ipy_editors.scite()
43 #ipy_editors.scite('c:/opt/scite/scite.exe')
43 #ipy_editors.scite('c:/opt/scite/scite.exe')
44 #ipy_editors.komodo()
44 #ipy_editors.komodo()
45 #ipy_editors.idle()
45 #ipy_editors.idle()
46 # ... or many others, try 'ipy_editors??' after import to see them
46 # ... or many others, try 'ipy_editors??' after import to see them
47
47
48 # Or roll your own:
48 # Or roll your own:
49 #ipy_editors.install_editor("c:/opt/jed +$line $file")
49 #ipy_editors.install_editor("c:/opt/jed +$line $file")
50
50
51
51
52 o = ip.options
52 o = ip.options
53 # An example on how to set options
53 # An example on how to set options
54 #o.autocall = 1
54 #o.autocall = 1
55 o.system_verbose = 0
55 o.system_verbose = 0
56
56
57 #import_all("os sys")
57 #import_all("os sys")
58 #execf('~/_ipython/ns.py')
58 #execf('~/_ipython/ns.py')
59
59
60
60
61 # -- prompt
61 # -- prompt
62 # A different, more compact set of prompts from the default ones, that
62 # A different, more compact set of prompts from the default ones, that
63 # always show your current location in the filesystem:
63 # always show your current location in the filesystem:
64
64
65 #o.prompt_in1 = r'\C_LightBlue[\C_LightCyan\Y2\C_LightBlue]\C_Normal\n\C_Green|\#>'
65 #o.prompt_in1 = r'\C_LightBlue[\C_LightCyan\Y2\C_LightBlue]\C_Normal\n\C_Green|\#>'
66 #o.prompt_in2 = r'.\D: '
66 #o.prompt_in2 = r'.\D: '
67 #o.prompt_out = r'[\#] '
67 #o.prompt_out = r'[\#] '
68
68
69 # Try one of these color settings if you can't read the text easily
69 # Try one of these color settings if you can't read the text easily
70 # autoexec is a list of IPython commands to execute on startup
70 # autoexec is a list of IPython commands to execute on startup
71 #o.autoexec.append('%colors LightBG')
71 #o.autoexec.append('%colors LightBG')
72 #o.autoexec.append('%colors NoColor')
72 #o.autoexec.append('%colors NoColor')
73 #o.autoexec.append('%colors Linux')
73 #o.autoexec.append('%colors Linux')
74
74
75 # for sane integer division that converts to float (1/2 == 0.5)
75 # for sane integer division that converts to float (1/2 == 0.5)
76 #o.autoexec.append('from __future__ import division')
76 #o.autoexec.append('from __future__ import division')
77
77
78 # For %tasks and %kill
78 # For %tasks and %kill
79 #import jobctrl
79 #import jobctrl
80
80
81 # For autoreloading of modules (%autoreload, %aimport)
81 # For autoreloading of modules (%autoreload, %aimport)
82 #import ipy_autoreload
82 #import ipy_autoreload
83
83
84 # For winpdb support (%wdb)
84 # For winpdb support (%wdb)
85 #import ipy_winpdb
85 #import ipy_winpdb
86
86
87 # For bzr completer, requires bzrlib (the python installation of bzr)
87 # For bzr completer, requires bzrlib (the python installation of bzr)
88 #ip.load('ipy_bzr')
88 #ip.load('ipy_bzr')
89
89
90 # Tab completer that is not quite so picky (i.e.
90 # Tab completer that is not quite so picky (i.e.
91 # "foo".<TAB> and str(2).<TAB> will work). Complete
91 # "foo".<TAB> and str(2).<TAB> will work). Complete
92 # at your own risk!
92 # at your own risk!
93 #import ipy_greedycompleter
93 #import ipy_greedycompleter
94
94
95 # If you are on Linux, you may be annoyed by
95 # If you are on Linux, you may be annoyed by
96 # "Display all N possibilities? (y or n)" on tab completion,
96 # "Display all N possibilities? (y or n)" on tab completion,
97 # as well as the paging through "more". Uncomment the following
97 # as well as the paging through "more". Uncomment the following
98 # lines to disable that behaviour
98 # lines to disable that behaviour
99 #import readline
99 #import readline
100 #readline.parse_and_bind('set completion-query-items 1000')
100 #readline.parse_and_bind('set completion-query-items 1000')
101 #readline.parse_and_bind('set page-completions no')
101 #readline.parse_and_bind('set page-completions no')
102
102
103
103
104
105
106 # some config helper functions you can use
104 # some config helper functions you can use
107 def import_all(modules):
105 def import_all(modules):
108 """ Usage: import_all("os sys") """
106 """ Usage: import_all("os sys") """
109 for m in modules.split():
107 for m in modules.split():
110 ip.ex("from %s import *" % m)
108 ip.ex("from %s import *" % m)
111
109
112 def execf(fname):
110 def execf(fname):
113 """ Execute a file in user namespace """
111 """ Execute a file in user namespace """
114 ip.ex('execfile("%s")' % os.path.expanduser(fname))
112 ip.ex('execfile("%s")' % os.path.expanduser(fname))
115
113
116 main()
114 main()
@@ -1,76 +1,77 b''
1 """
1 """
2 Base front end class for all async frontends.
2 Base front end class for all async frontends.
3 """
3 """
4 __docformat__ = "restructuredtext en"
4 __docformat__ = "restructuredtext en"
5
5
6 #-------------------------------------------------------------------------------
6 #-------------------------------------------------------------------------------
7 # Copyright (C) 2008 The IPython Development Team
7 # Copyright (C) 2008 The IPython Development Team
8 #
8 #
9 # Distributed under the terms of the BSD License. The full license is in
9 # Distributed under the terms of the BSD License. The full license is in
10 # the file COPYING, distributed as part of this software.
10 # the file COPYING, distributed as part of this software.
11 #-------------------------------------------------------------------------------
11 #-------------------------------------------------------------------------------
12
12
13
13
14 #-------------------------------------------------------------------------------
14 #-------------------------------------------------------------------------------
15 # Imports
15 # Imports
16 #-------------------------------------------------------------------------------
16 #-------------------------------------------------------------------------------
17 from IPython.external import guid
18
17
18 from IPython.external import guid
19
19
20 from zope.interface import Interface, Attribute, implements, classProvides
20 from zope.interface import Interface, Attribute, implements, classProvides
21 from twisted.python.failure import Failure
21 from twisted.python.failure import Failure
22 from IPython.frontend.frontendbase import FrontEndBase, IFrontEnd, IFrontEndFactory
22 from IPython.frontend.frontendbase import (
23 FrontEndBase, IFrontEnd, IFrontEndFactory)
23 from IPython.kernel.core.history import FrontEndHistory
24 from IPython.kernel.core.history import FrontEndHistory
24 from IPython.kernel.engineservice import IEngineCore
25 from IPython.kernel.engineservice import IEngineCore
25
26
26
27
27 class AsyncFrontEndBase(FrontEndBase):
28 class AsyncFrontEndBase(FrontEndBase):
28 """
29 """
29 Overrides FrontEndBase to wrap execute in a deferred result.
30 Overrides FrontEndBase to wrap execute in a deferred result.
30 All callbacks are made as callbacks on the deferred result.
31 All callbacks are made as callbacks on the deferred result.
31 """
32 """
32
33
33 implements(IFrontEnd)
34 implements(IFrontEnd)
34 classProvides(IFrontEndFactory)
35 classProvides(IFrontEndFactory)
35
36
36 def __init__(self, engine=None, history=None):
37 def __init__(self, engine=None, history=None):
37 assert(engine==None or IEngineCore.providedBy(engine))
38 assert(engine==None or IEngineCore.providedBy(engine))
38 self.engine = IEngineCore(engine)
39 self.engine = IEngineCore(engine)
39 if history is None:
40 if history is None:
40 self.history = FrontEndHistory(input_cache=[''])
41 self.history = FrontEndHistory(input_cache=[''])
41 else:
42 else:
42 self.history = history
43 self.history = history
43
44
44
45
45 def execute(self, block, blockID=None):
46 def execute(self, block, blockID=None):
46 """Execute the block and return the deferred result.
47 """Execute the block and return the deferred result.
47
48
48 Parameters:
49 Parameters:
49 block : {str, AST}
50 block : {str, AST}
50 blockID : any
51 blockID : any
51 Caller may provide an ID to identify this block.
52 Caller may provide an ID to identify this block.
52 result['blockID'] := blockID
53 result['blockID'] := blockID
53
54
54 Result:
55 Result:
55 Deferred result of self.interpreter.execute
56 Deferred result of self.interpreter.execute
56 """
57 """
57
58
58 if(not self.is_complete(block)):
59 if(not self.is_complete(block)):
59 return Failure(Exception("Block is not compilable"))
60 return Failure(Exception("Block is not compilable"))
60
61
61 if(blockID == None):
62 if(blockID == None):
62 blockID = guid.generate()
63 blockID = guid.generate()
63
64
64 d = self.engine.execute(block)
65 d = self.engine.execute(block)
65 d.addCallback(self._add_history, block=block)
66 d.addCallback(self._add_history, block=block)
66 d.addCallbacks(self._add_block_id_for_result,
67 d.addCallbacks(self._add_block_id_for_result,
67 errback=self._add_block_id_for_failure,
68 errback=self._add_block_id_for_failure,
68 callbackArgs=(blockID,),
69 callbackArgs=(blockID,),
69 errbackArgs=(blockID,))
70 errbackArgs=(blockID,))
70 d.addBoth(self.update_cell_prompt, blockID=blockID)
71 d.addBoth(self.update_cell_prompt, blockID=blockID)
71 d.addCallbacks(self.render_result,
72 d.addCallbacks(self.render_result,
72 errback=self.render_error)
73 errback=self.render_error)
73
74
74 return d
75 return d
75
76
76
77
@@ -1,94 +1,100 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """This file contains unittests for the
2 """This file contains unittests for the
3 IPython.frontend.cocoa.cocoa_frontend module.
3 IPython.frontend.cocoa.cocoa_frontend module.
4 """
4 """
5 __docformat__ = "restructuredtext en"
5 __docformat__ = "restructuredtext en"
6
6
7 #---------------------------------------------------------------------------
7 #---------------------------------------------------------------------------
8 # Copyright (C) 2005 The IPython Development Team
8 # Copyright (C) 2005 The IPython Development Team
9 #
9 #
10 # Distributed under the terms of the BSD License. The full license is in
10 # Distributed under the terms of the BSD License. The full license is in
11 # the file COPYING, distributed as part of this software.
11 # the file COPYING, distributed as part of this software.
12 #---------------------------------------------------------------------------
12 #---------------------------------------------------------------------------
13
13
14 #---------------------------------------------------------------------------
14 #---------------------------------------------------------------------------
15 # Imports
15 # Imports
16 #---------------------------------------------------------------------------
16 #---------------------------------------------------------------------------
17
17
18 try:
18 # Tell nose to skip this module
19 __test__ = {}
20
21 from twisted.trial import unittest
22 from twisted.internet.defer import succeed
23
19 from IPython.kernel.core.interpreter import Interpreter
24 from IPython.kernel.core.interpreter import Interpreter
20 import IPython.kernel.engineservice as es
25 import IPython.kernel.engineservice as es
21 from IPython.testing.util import DeferredTestCase
26
22 from twisted.internet.defer import succeed
27 try:
23 from IPython.frontend.cocoa.cocoa_frontend import IPythonCocoaController
28 from IPython.frontend.cocoa.cocoa_frontend import IPythonCocoaController
24 from Foundation import NSMakeRect
29 from Foundation import NSMakeRect
25 from AppKit import NSTextView, NSScrollView
30 from AppKit import NSTextView, NSScrollView
26 except ImportError:
31 except ImportError:
27 import nose
32 # This tells twisted.trial to skip this module if PyObjC is not found
28 raise nose.SkipTest("This test requires zope.interface, Twisted, Foolscap and PyObjC")
33 skip = True
29
34
30 class TestIPythonCocoaControler(DeferredTestCase):
35 #---------------------------------------------------------------------------
36 # Tests
37 #---------------------------------------------------------------------------
38 class TestIPythonCocoaControler(unittest.TestCase):
31 """Tests for IPythonCocoaController"""
39 """Tests for IPythonCocoaController"""
32
40
33 def setUp(self):
41 def setUp(self):
34 self.controller = IPythonCocoaController.alloc().init()
42 self.controller = IPythonCocoaController.alloc().init()
35 self.engine = es.EngineService()
43 self.engine = es.EngineService()
36 self.engine.startService()
44 self.engine.startService()
37
45
38 def tearDown(self):
46 def tearDown(self):
39 self.controller = None
47 self.controller = None
40 self.engine.stopService()
48 self.engine.stopService()
41
49
42 def testControllerExecutesCode(self):
50 def testControllerExecutesCode(self):
43 code ="""5+5"""
51 code ="""5+5"""
44 expected = Interpreter().execute(code)
52 expected = Interpreter().execute(code)
45 del expected['number']
53 del expected['number']
46 def removeNumberAndID(result):
54 def removeNumberAndID(result):
47 del result['number']
55 del result['number']
48 del result['id']
56 del result['id']
49 return result
57 return result
50 self.assertDeferredEquals(
58 d = self.controller.execute(code)
51 self.controller.execute(code).addCallback(removeNumberAndID),
59 d.addCallback(removeNumberAndID)
52 expected)
60 d.addCallback(lambda r: self.assertEquals(r, expected))
53
61
54 def testControllerMirrorsUserNSWithValuesAsStrings(self):
62 def testControllerMirrorsUserNSWithValuesAsStrings(self):
55 code = """userns1=1;userns2=2"""
63 code = """userns1=1;userns2=2"""
56 def testControllerUserNS(result):
64 def testControllerUserNS(result):
57 self.assertEquals(self.controller.userNS['userns1'], 1)
65 self.assertEquals(self.controller.userNS['userns1'], 1)
58 self.assertEquals(self.controller.userNS['userns2'], 2)
66 self.assertEquals(self.controller.userNS['userns2'], 2)
59
60 self.controller.execute(code).addCallback(testControllerUserNS)
67 self.controller.execute(code).addCallback(testControllerUserNS)
61
68
62
63 def testControllerInstantiatesIEngine(self):
69 def testControllerInstantiatesIEngine(self):
64 self.assert_(es.IEngineBase.providedBy(self.controller.engine))
70 self.assert_(es.IEngineBase.providedBy(self.controller.engine))
65
71
66 def testControllerCompletesToken(self):
72 def testControllerCompletesToken(self):
67 code = """longNameVariable=10"""
73 code = """longNameVariable=10"""
68 def testCompletes(result):
74 def testCompletes(result):
69 self.assert_("longNameVariable" in result)
75 self.assert_("longNameVariable" in result)
70
76
71 def testCompleteToken(result):
77 def testCompleteToken(result):
72 self.controller.complete("longNa").addCallback(testCompletes)
78 self.controller.complete("longNa").addCallback(testCompletes)
73
79
74 self.controller.execute(code).addCallback(testCompletes)
80 self.controller.execute(code).addCallback(testCompletes)
75
81
76
82
77 def testCurrentIndent(self):
83 def testCurrentIndent(self):
78 """test that current_indent_string returns current indent or None.
84 """test that current_indent_string returns current indent or None.
79 Uses _indent_for_block for direct unit testing.
85 Uses _indent_for_block for direct unit testing.
80 """
86 """
81
87
82 self.controller.tabUsesSpaces = True
88 self.controller.tabUsesSpaces = True
83 self.assert_(self.controller._indent_for_block("""a=3""") == None)
89 self.assert_(self.controller._indent_for_block("""a=3""") == None)
84 self.assert_(self.controller._indent_for_block("") == None)
90 self.assert_(self.controller._indent_for_block("") == None)
85 block = """def test():\n a=3"""
91 block = """def test():\n a=3"""
86 self.assert_(self.controller._indent_for_block(block) == \
92 self.assert_(self.controller._indent_for_block(block) == \
87 ' ' * self.controller.tabSpaces)
93 ' ' * self.controller.tabSpaces)
88
94
89 block = """if(True):\n%sif(False):\n%spass""" % \
95 block = """if(True):\n%sif(False):\n%spass""" % \
90 (' '*self.controller.tabSpaces,
96 (' '*self.controller.tabSpaces,
91 2*' '*self.controller.tabSpaces)
97 2*' '*self.controller.tabSpaces)
92 self.assert_(self.controller._indent_for_block(block) == \
98 self.assert_(self.controller._indent_for_block(block) == \
93 2*(' '*self.controller.tabSpaces))
99 2*(' '*self.controller.tabSpaces))
94
100
@@ -1,333 +1,372 b''
1 """
1 """
2 Base front end class for all line-oriented frontends, rather than
2 Base front end class for all line-oriented frontends, rather than
3 block-oriented.
3 block-oriented.
4
4
5 Currently this focuses on synchronous frontends.
5 Currently this focuses on synchronous frontends.
6 """
6 """
7 __docformat__ = "restructuredtext en"
7 __docformat__ = "restructuredtext en"
8
8
9 #-------------------------------------------------------------------------------
9 #-------------------------------------------------------------------------------
10 # Copyright (C) 2008 The IPython Development Team
10 # Copyright (C) 2008 The IPython Development Team
11 #
11 #
12 # Distributed under the terms of the BSD License. The full license is in
12 # Distributed under the terms of the BSD License. The full license is in
13 # the file COPYING, distributed as part of this software.
13 # the file COPYING, distributed as part of this software.
14 #-------------------------------------------------------------------------------
14 #-------------------------------------------------------------------------------
15
15
16 #-------------------------------------------------------------------------------
16 #-------------------------------------------------------------------------------
17 # Imports
17 # Imports
18 #-------------------------------------------------------------------------------
18 #-------------------------------------------------------------------------------
19 import re
19 import re
20
20
21 import IPython
22 import sys
21 import sys
23 import codeop
22 import codeop
24 import traceback
25
23
26 from frontendbase import FrontEndBase
24 from frontendbase import FrontEndBase
27 from IPython.kernel.core.interpreter import Interpreter
25 from IPython.kernel.core.interpreter import Interpreter
28
26
29 def common_prefix(strings):
27 def common_prefix(strings):
30 """ Given a list of strings, return the common prefix between all
28 """ Given a list of strings, return the common prefix between all
31 these strings.
29 these strings.
32 """
30 """
33 ref = strings[0]
31 ref = strings[0]
34 prefix = ''
32 prefix = ''
35 for size in range(len(ref)):
33 for size in range(len(ref)):
36 test_prefix = ref[:size+1]
34 test_prefix = ref[:size+1]
37 for string in strings[1:]:
35 for string in strings[1:]:
38 if not string.startswith(test_prefix):
36 if not string.startswith(test_prefix):
39 return prefix
37 return prefix
40 prefix = test_prefix
38 prefix = test_prefix
41
39
42 return prefix
40 return prefix
43
41
44 #-------------------------------------------------------------------------------
42 #-------------------------------------------------------------------------------
45 # Base class for the line-oriented front ends
43 # Base class for the line-oriented front ends
46 #-------------------------------------------------------------------------------
44 #-------------------------------------------------------------------------------
47 class LineFrontEndBase(FrontEndBase):
45 class LineFrontEndBase(FrontEndBase):
48 """ Concrete implementation of the FrontEndBase class. This is meant
46 """ Concrete implementation of the FrontEndBase class. This is meant
49 to be the base class behind all the frontend that are line-oriented,
47 to be the base class behind all the frontend that are line-oriented,
50 rather than block-oriented.
48 rather than block-oriented.
51 """
49 """
52
50
53 # We need to keep the prompt number, to be able to increment
51 # We need to keep the prompt number, to be able to increment
54 # it when there is an exception.
52 # it when there is an exception.
55 prompt_number = 1
53 prompt_number = 1
56
54
57 # We keep a reference to the last result: it helps testing and
55 # We keep a reference to the last result: it helps testing and
58 # programatic control of the frontend.
56 # programatic control of the frontend.
59 last_result = dict(number=0)
57 last_result = dict(number=0)
60
58
59 # The last prompt displayed. Useful for continuation prompts.
60 last_prompt = ''
61
61 # The input buffer being edited
62 # The input buffer being edited
62 input_buffer = ''
63 input_buffer = ''
63
64
64 # Set to true for debug output
65 # Set to true for debug output
65 debug = False
66 debug = False
66
67
67 # A banner to print at startup
68 # A banner to print at startup
68 banner = None
69 banner = None
69
70
70 #--------------------------------------------------------------------------
71 #--------------------------------------------------------------------------
71 # FrontEndBase interface
72 # FrontEndBase interface
72 #--------------------------------------------------------------------------
73 #--------------------------------------------------------------------------
73
74
74 def __init__(self, shell=None, history=None, banner=None, *args, **kwargs):
75 def __init__(self, shell=None, history=None, banner=None, *args, **kwargs):
75 if shell is None:
76 if shell is None:
76 shell = Interpreter()
77 shell = Interpreter()
77 FrontEndBase.__init__(self, shell=shell, history=history)
78 FrontEndBase.__init__(self, shell=shell, history=history)
78
79
79 if banner is not None:
80 if banner is not None:
80 self.banner = banner
81 self.banner = banner
81
82
82 def start(self):
83 def start(self):
83 """ Put the frontend in a state where it is ready for user
84 """ Put the frontend in a state where it is ready for user
84 interaction.
85 interaction.
85 """
86 """
86 if self.banner is not None:
87 if self.banner is not None:
87 self.write(self.banner, refresh=False)
88 self.write(self.banner, refresh=False)
88
89
89 self.new_prompt(self.input_prompt_template.substitute(number=1))
90 self.new_prompt(self.input_prompt_template.substitute(number=1))
90
91
91
92
92 def complete(self, line):
93 def complete(self, line):
93 """Complete line in engine's user_ns
94 """Complete line in engine's user_ns
94
95
95 Parameters
96 Parameters
96 ----------
97 ----------
97 line : string
98 line : string
98
99
99 Result
100 Result
100 ------
101 ------
101 The replacement for the line and the list of possible completions.
102 The replacement for the line and the list of possible completions.
102 """
103 """
103 completions = self.shell.complete(line)
104 completions = self.shell.complete(line)
104 complete_sep = re.compile('[\s\{\}\[\]\(\)\=]')
105 complete_sep = re.compile('[\s\{\}\[\]\(\)\=]')
105 if completions:
106 if completions:
106 prefix = common_prefix(completions)
107 prefix = common_prefix(completions)
107 residual = complete_sep.split(line)[:-1]
108 residual = complete_sep.split(line)[:-1]
108 line = line[:-len(residual)] + prefix
109 line = line[:-len(residual)] + prefix
109 return line, completions
110 return line, completions
110
111
111
112
112 def render_result(self, result):
113 def render_result(self, result):
113 """ Frontend-specific rendering of the result of a calculation
114 """ Frontend-specific rendering of the result of a calculation
114 that has been sent to an engine.
115 that has been sent to an engine.
115 """
116 """
116 if 'stdout' in result and result['stdout']:
117 if 'stdout' in result and result['stdout']:
117 self.write('\n' + result['stdout'])
118 self.write('\n' + result['stdout'])
118 if 'display' in result and result['display']:
119 if 'display' in result and result['display']:
119 self.write("%s%s\n" % (
120 self.write("%s%s\n" % (
120 self.output_prompt_template.substitute(
121 self.output_prompt_template.substitute(
121 number=result['number']),
122 number=result['number']),
122 result['display']['pprint']
123 result['display']['pprint']
123 ) )
124 ) )
124
125
125
126
126 def render_error(self, failure):
127 def render_error(self, failure):
127 """ Frontend-specific rendering of error.
128 """ Frontend-specific rendering of error.
128 """
129 """
129 self.write('\n\n'+str(failure)+'\n\n')
130 self.write('\n\n'+str(failure)+'\n\n')
130 return failure
131 return failure
131
132
132
133
133 def is_complete(self, string):
134 def is_complete(self, string):
134 """ Check if a string forms a complete, executable set of
135 """ Check if a string forms a complete, executable set of
135 commands.
136 commands.
136
137
137 For the line-oriented frontend, multi-line code is not executed
138 For the line-oriented frontend, multi-line code is not executed
138 as soon as it is complete: the users has to enter two line
139 as soon as it is complete: the users has to enter two line
139 returns.
140 returns.
140 """
141 """
141 if string in ('', '\n'):
142 if string in ('', '\n'):
142 # Prefiltering, eg through ipython0, may return an empty
143 # Prefiltering, eg through ipython0, may return an empty
143 # string although some operations have been accomplished. We
144 # string although some operations have been accomplished. We
144 # thus want to consider an empty string as a complete
145 # thus want to consider an empty string as a complete
145 # statement.
146 # statement.
146 return True
147 return True
147 elif ( len(self.input_buffer.split('\n'))>2
148 elif ( len(self.input_buffer.split('\n'))>2
148 and not re.findall(r"\n[\t ]*\n[\t ]*$", string)):
149 and not re.findall(r"\n[\t ]*\n[\t ]*$", string)):
149 return False
150 return False
150 else:
151 else:
151 self.capture_output()
152 self.capture_output()
152 try:
153 try:
153 # Add line returns here, to make sure that the statement is
154 # Add line returns here, to make sure that the statement is
154 # complete.
155 # complete (except if '\' was used).
155 is_complete = codeop.compile_command(string.rstrip() + '\n\n',
156 # This should probably be done in a different place (like
157 # maybe 'prefilter_input' method? For now, this works.
158 clean_string = string.rstrip('\n')
159 if not clean_string.endswith('\\'): clean_string +='\n\n'
160 is_complete = codeop.compile_command(clean_string,
156 "<string>", "exec")
161 "<string>", "exec")
157 self.release_output()
162 self.release_output()
158 except Exception, e:
163 except Exception, e:
159 # XXX: Hack: return True so that the
164 # XXX: Hack: return True so that the
160 # code gets executed and the error captured.
165 # code gets executed and the error captured.
161 is_complete = True
166 is_complete = True
162 return is_complete
167 return is_complete
163
168
164
169
165 def write(self, string, refresh=True):
170 def write(self, string, refresh=True):
166 """ Write some characters to the display.
171 """ Write some characters to the display.
167
172
168 Subclass should overide this method.
173 Subclass should overide this method.
169
174
170 The refresh keyword argument is used in frontends with an
175 The refresh keyword argument is used in frontends with an
171 event loop, to choose whether the write should trigget an UI
176 event loop, to choose whether the write should trigget an UI
172 refresh, and thus be syncrhonous, or not.
177 refresh, and thus be syncrhonous, or not.
173 """
178 """
174 print >>sys.__stderr__, string
179 print >>sys.__stderr__, string
175
180
176
181
177 def execute(self, python_string, raw_string=None):
182 def execute(self, python_string, raw_string=None):
178 """ Stores the raw_string in the history, and sends the
183 """ Stores the raw_string in the history, and sends the
179 python string to the interpreter.
184 python string to the interpreter.
180 """
185 """
181 if raw_string is None:
186 if raw_string is None:
182 raw_string = python_string
187 raw_string = python_string
183 # Create a false result, in case there is an exception
188 # Create a false result, in case there is an exception
184 self.last_result = dict(number=self.prompt_number)
189 self.last_result = dict(number=self.prompt_number)
185
190
186 ## try:
187 ## self.history.input_cache[-1] = raw_string.rstrip()
188 ## result = self.shell.execute(python_string)
189 ## self.last_result = result
190 ## self.render_result(result)
191 ## except:
192 ## self.show_traceback()
193 ## finally:
194 ## self.after_execute()
195
196 try:
191 try:
197 try:
192 try:
198 self.history.input_cache[-1] = raw_string.rstrip()
193 self.history.input_cache[-1] = raw_string.rstrip()
199 result = self.shell.execute(python_string)
194 result = self.shell.execute(python_string)
200 self.last_result = result
195 self.last_result = result
201 self.render_result(result)
196 self.render_result(result)
202 except:
197 except:
203 self.show_traceback()
198 self.show_traceback()
204 finally:
199 finally:
205 self.after_execute()
200 self.after_execute()
206
201
207
202
208 #--------------------------------------------------------------------------
203 #--------------------------------------------------------------------------
209 # LineFrontEndBase interface
204 # LineFrontEndBase interface
210 #--------------------------------------------------------------------------
205 #--------------------------------------------------------------------------
211
206
212 def prefilter_input(self, string):
207 def prefilter_input(self, string):
213 """ Prefilter the input to turn it in valid python.
208 """ Prefilter the input to turn it in valid python.
214 """
209 """
215 string = string.replace('\r\n', '\n')
210 string = string.replace('\r\n', '\n')
216 string = string.replace('\t', 4*' ')
211 string = string.replace('\t', 4*' ')
217 # Clean the trailing whitespace
212 # Clean the trailing whitespace
218 string = '\n'.join(l.rstrip() for l in string.split('\n'))
213 string = '\n'.join(l.rstrip() for l in string.split('\n'))
219 return string
214 return string
220
215
221
216
222 def after_execute(self):
217 def after_execute(self):
223 """ All the operations required after an execution to put the
218 """ All the operations required after an execution to put the
224 terminal back in a shape where it is usable.
219 terminal back in a shape where it is usable.
225 """
220 """
226 self.prompt_number += 1
221 self.prompt_number += 1
227 self.new_prompt(self.input_prompt_template.substitute(
222 self.new_prompt(self.input_prompt_template.substitute(
228 number=(self.last_result['number'] + 1)))
223 number=(self.last_result['number'] + 1)))
229 # Start a new empty history entry
224 # Start a new empty history entry
230 self._add_history(None, '')
225 self._add_history(None, '')
231 self.history_cursor = len(self.history.input_cache) - 1
226 self.history_cursor = len(self.history.input_cache) - 1
232
227
233
228
234 def complete_current_input(self):
229 def complete_current_input(self):
235 """ Do code completion on current line.
230 """ Do code completion on current line.
236 """
231 """
237 if self.debug:
232 if self.debug:
238 print >>sys.__stdout__, "complete_current_input",
233 print >>sys.__stdout__, "complete_current_input",
239 line = self.input_buffer
234 line = self.input_buffer
240 new_line, completions = self.complete(line)
235 new_line, completions = self.complete(line)
241 if len(completions)>1:
236 if len(completions)>1:
242 self.write_completion(completions, new_line=new_line)
237 self.write_completion(completions, new_line=new_line)
243 elif not line == new_line:
238 elif not line == new_line:
244 self.input_buffer = new_line
239 self.input_buffer = new_line
245 if self.debug:
240 if self.debug:
246 print >>sys.__stdout__, 'line', line
241 print >>sys.__stdout__, 'line', line
247 print >>sys.__stdout__, 'new_line', new_line
242 print >>sys.__stdout__, 'new_line', new_line
248 print >>sys.__stdout__, completions
243 print >>sys.__stdout__, completions
249
244
250
245
251 def get_line_width(self):
246 def get_line_width(self):
252 """ Return the width of the line in characters.
247 """ Return the width of the line in characters.
253 """
248 """
254 return 80
249 return 80
255
250
256
251
257 def write_completion(self, possibilities, new_line=None):
252 def write_completion(self, possibilities, new_line=None):
258 """ Write the list of possible completions.
253 """ Write the list of possible completions.
259
254
260 new_line is the completed input line that should be displayed
255 new_line is the completed input line that should be displayed
261 after the completion are writen. If None, the input_buffer
256 after the completion are writen. If None, the input_buffer
262 before the completion is used.
257 before the completion is used.
263 """
258 """
264 if new_line is None:
259 if new_line is None:
265 new_line = self.input_buffer
260 new_line = self.input_buffer
266
261
267 self.write('\n')
262 self.write('\n')
268 max_len = len(max(possibilities, key=len)) + 1
263 max_len = len(max(possibilities, key=len)) + 1
269
264
270 # Now we check how much symbol we can put on a line...
265 # Now we check how much symbol we can put on a line...
271 chars_per_line = self.get_line_width()
266 chars_per_line = self.get_line_width()
272 symbols_per_line = max(1, chars_per_line/max_len)
267 symbols_per_line = max(1, chars_per_line/max_len)
273
268
274 pos = 1
269 pos = 1
275 buf = []
270 completion_string = []
276 for symbol in possibilities:
271 for symbol in possibilities:
277 if pos < symbols_per_line:
272 if pos < symbols_per_line:
278 buf.append(symbol.ljust(max_len))
273 completion_string.append(symbol.ljust(max_len))
279 pos += 1
274 pos += 1
280 else:
275 else:
281 buf.append(symbol.rstrip() + '\n')
276 completion_string.append(symbol.rstrip() + '\n')
282 pos = 1
277 pos = 1
283 self.write(''.join(buf))
278 self.write(''.join(completion_string))
284 self.new_prompt(self.input_prompt_template.substitute(
279 self.new_prompt(self.input_prompt_template.substitute(
285 number=self.last_result['number'] + 1))
280 number=self.last_result['number'] + 1))
286 self.input_buffer = new_line
281 self.input_buffer = new_line
287
282
288
283
289 def new_prompt(self, prompt):
284 def new_prompt(self, prompt):
290 """ Prints a prompt and starts a new editing buffer.
285 """ Prints a prompt and starts a new editing buffer.
291
286
292 Subclasses should use this method to make sure that the
287 Subclasses should use this method to make sure that the
293 terminal is put in a state favorable for a new line
288 terminal is put in a state favorable for a new line
294 input.
289 input.
295 """
290 """
296 self.input_buffer = ''
291 self.input_buffer = ''
297 self.write(prompt)
292 self.write(prompt)
298
293
299
294
295 def continuation_prompt(self):
296 """Returns the current continuation prompt.
297 """
298 return ("."*(len(self.last_prompt)-2) + ': ')
299
300
301 def execute_command(self, command, hidden=False):
302 """ Execute a command, not only in the model, but also in the
303 view, if any.
304 """
305 return self.shell.execute(command)
306
300 #--------------------------------------------------------------------------
307 #--------------------------------------------------------------------------
301 # Private API
308 # Private API
302 #--------------------------------------------------------------------------
309 #--------------------------------------------------------------------------
303
310
304 def _on_enter(self):
311 def _on_enter(self, new_line_pos=0):
305 """ Called when the return key is pressed in a line editing
312 """ Called when the return key is pressed in a line editing
306 buffer.
313 buffer.
314
315 Parameters
316 ----------
317 new_line_pos : integer, optional
318 Position of the new line to add, starting from the
319 end (0 adds a new line after the last line, -1 before
320 the last line...)
321
322 Returns
323 -------
324 True if execution is triggered
307 """
325 """
308 current_buffer = self.input_buffer
326 current_buffer = self.input_buffer
309 cleaned_buffer = self.prefilter_input(current_buffer)
327 # XXX: This string replace is ugly, but there should be no way it
328 # fails.
329 prompt_less_buffer = re.sub('^' + self.continuation_prompt(),
330 '', current_buffer).replace('\n' + self.continuation_prompt(),
331 '\n')
332 cleaned_buffer = self.prefilter_input(prompt_less_buffer)
310 if self.is_complete(cleaned_buffer):
333 if self.is_complete(cleaned_buffer):
311 self.execute(cleaned_buffer, raw_string=current_buffer)
334 self.execute(cleaned_buffer, raw_string=current_buffer)
335 return True
336 else:
337 # Start a new line.
338 new_line_pos = -new_line_pos
339 lines = current_buffer.split('\n')[:-1]
340 prompt_less_lines = prompt_less_buffer.split('\n')
341 # Create the new line, with the continuation prompt, and the
342 # same amount of indent than the line above it.
343 new_line = self.continuation_prompt() + \
344 self._get_indent_string('\n'.join(
345 prompt_less_lines[:new_line_pos-1]))
346 if len(lines) == 1:
347 # We are starting a first continuation line. Indent it.
348 new_line += '\t'
349 elif current_buffer[:-1].split('\n')[-1].rstrip().endswith(':'):
350 # The last line ends with ":", autoindent the new line.
351 new_line += '\t'
352
353 if new_line_pos == 0:
354 lines.append(new_line)
312 else:
355 else:
313 self.input_buffer += self._get_indent_string(
356 lines.insert(new_line_pos, new_line)
314 current_buffer[:-1])
357 self.input_buffer = '\n'.join(lines)
315 if len(current_buffer.split('\n')) == 2:
316 self.input_buffer += '\t\t'
317 if current_buffer[:-1].split('\n')[-1].rstrip().endswith(':'):
318 self.input_buffer += '\t'
319
358
320
359
321 def _get_indent_string(self, string):
360 def _get_indent_string(self, string):
322 """ Return the string of whitespace that prefixes a line. Used to
361 """ Return the string of whitespace that prefixes a line. Used to
323 add the right amount of indendation when creating a new line.
362 add the right amount of indendation when creating a new line.
324 """
363 """
325 string = string.replace('\t', ' '*4)
364 string = string.replace('\t', ' '*4)
326 string = string.split('\n')[-1]
365 string = string.split('\n')[-1]
327 indent_chars = len(string) - len(string.lstrip())
366 indent_chars = len(string) - len(string.lstrip())
328 indent_string = '\t'*(indent_chars // 4) + \
367 indent_string = '\t'*(indent_chars // 4) + \
329 ' '*(indent_chars % 4)
368 ' '*(indent_chars % 4)
330
369
331 return indent_string
370 return indent_string
332
371
333
372
@@ -1,246 +1,285 b''
1 """
1 """
2 Frontend class that uses IPython0 to prefilter the inputs.
2 Frontend class that uses IPython0 to prefilter the inputs.
3
3
4 Using the IPython0 mechanism gives us access to the magics.
4 Using the IPython0 mechanism gives us access to the magics.
5
5
6 This is a transitory class, used here to do the transition between
6 This is a transitory class, used here to do the transition between
7 ipython0 and ipython1. This class is meant to be short-lived as more
7 ipython0 and ipython1. This class is meant to be short-lived as more
8 functionnality is abstracted out of ipython0 in reusable functions and
8 functionnality is abstracted out of ipython0 in reusable functions and
9 is added on the interpreter. This class can be a used to guide this
9 is added on the interpreter. This class can be a used to guide this
10 refactoring.
10 refactoring.
11 """
11 """
12 __docformat__ = "restructuredtext en"
12 __docformat__ = "restructuredtext en"
13
13
14 #-------------------------------------------------------------------------------
14 #-------------------------------------------------------------------------------
15 # Copyright (C) 2008 The IPython Development Team
15 # Copyright (C) 2008 The IPython Development Team
16 #
16 #
17 # Distributed under the terms of the BSD License. The full license is in
17 # Distributed under the terms of the BSD License. The full license is in
18 # the file COPYING, distributed as part of this software.
18 # the file COPYING, distributed as part of this software.
19 #-------------------------------------------------------------------------------
19 #-------------------------------------------------------------------------------
20
20
21 #-------------------------------------------------------------------------------
21 #-------------------------------------------------------------------------------
22 # Imports
22 # Imports
23 #-------------------------------------------------------------------------------
23 #-------------------------------------------------------------------------------
24 import sys
24 import sys
25
25 import pydoc
26 from linefrontendbase import LineFrontEndBase, common_prefix
26 import os
27 from frontendbase import FrontEndBase
27 import re
28 import __builtin__
28
29
29 from IPython.ipmaker import make_IPython
30 from IPython.ipmaker import make_IPython
30 from IPython.ipapi import IPApi
31 from IPython.ipapi import IPApi
31 from IPython.kernel.core.redirector_output_trap import RedirectorOutputTrap
32 from IPython.kernel.core.redirector_output_trap import RedirectorOutputTrap
32
33
33 from IPython.kernel.core.sync_traceback_trap import SyncTracebackTrap
34 from IPython.kernel.core.sync_traceback_trap import SyncTracebackTrap
34
35
35 from IPython.genutils import Term
36 from IPython.genutils import Term
36 import pydoc
37
37 import os
38 from linefrontendbase import LineFrontEndBase, common_prefix
38 import sys
39
39
40
40
41 def mk_system_call(system_call_function, command):
41 def mk_system_call(system_call_function, command):
42 """ given a os.system replacement, and a leading string command,
42 """ given a os.system replacement, and a leading string command,
43 returns a function that will execute the command with the given
43 returns a function that will execute the command with the given
44 argument string.
44 argument string.
45 """
45 """
46 def my_system_call(args):
46 def my_system_call(args):
47 system_call_function("%s %s" % (command, args))
47 system_call_function("%s %s" % (command, args))
48
49 my_system_call.__doc__ = "Calls %s" % command
48 return my_system_call
50 return my_system_call
49
51
50 #-------------------------------------------------------------------------------
52 #-------------------------------------------------------------------------------
51 # Frontend class using ipython0 to do the prefiltering.
53 # Frontend class using ipython0 to do the prefiltering.
52 #-------------------------------------------------------------------------------
54 #-------------------------------------------------------------------------------
53 class PrefilterFrontEnd(LineFrontEndBase):
55 class PrefilterFrontEnd(LineFrontEndBase):
54 """ Class that uses ipython0 to do prefilter the input, do the
56 """ Class that uses ipython0 to do prefilter the input, do the
55 completion and the magics.
57 completion and the magics.
56
58
57 The core trick is to use an ipython0 instance to prefilter the
59 The core trick is to use an ipython0 instance to prefilter the
58 input, and share the namespace between the interpreter instance used
60 input, and share the namespace between the interpreter instance used
59 to execute the statements and the ipython0 used for code
61 to execute the statements and the ipython0 used for code
60 completion...
62 completion...
61 """
63 """
62
64
63 debug = False
65 debug = False
64
66
65 def __init__(self, ipython0=None, *args, **kwargs):
67 def __init__(self, ipython0=None, argv=None, *args, **kwargs):
66 """ Parameters:
68 """ Parameters:
67 -----------
69 -----------
68
70
69 ipython0: an optional ipython0 instance to use for command
71 ipython0: an optional ipython0 instance to use for command
70 prefiltering and completion.
72 prefiltering and completion.
73
74 argv : list, optional
75 Used as the instance's argv value. If not given, [] is used.
71 """
76 """
77 if argv is None:
78 argv = []
79 # This is a hack to avoid the IPython exception hook to trigger
80 # on exceptions (https://bugs.launchpad.net/bugs/337105)
81 # XXX: This is horrible: module-leve monkey patching -> side
82 # effects.
83 from IPython import iplib
84 iplib.InteractiveShell.isthreaded = True
85
72 LineFrontEndBase.__init__(self, *args, **kwargs)
86 LineFrontEndBase.__init__(self, *args, **kwargs)
73 self.shell.output_trap = RedirectorOutputTrap(
87 self.shell.output_trap = RedirectorOutputTrap(
74 out_callback=self.write,
88 out_callback=self.write,
75 err_callback=self.write,
89 err_callback=self.write,
76 )
90 )
77 self.shell.traceback_trap = SyncTracebackTrap(
91 self.shell.traceback_trap = SyncTracebackTrap(
78 formatters=self.shell.traceback_trap.formatters,
92 formatters=self.shell.traceback_trap.formatters,
79 )
93 )
80
94
81 # Start the ipython0 instance:
95 # Start the ipython0 instance:
82 self.save_output_hooks()
96 self.save_output_hooks()
83 if ipython0 is None:
97 if ipython0 is None:
84 # Instanciate an IPython0 interpreter to be able to use the
98 # Instanciate an IPython0 interpreter to be able to use the
85 # prefiltering.
99 # prefiltering.
100 # Suppress all key input, to avoid waiting
101 def my_rawinput(x=None):
102 return '\n'
103 old_rawinput = __builtin__.raw_input
104 __builtin__.raw_input = my_rawinput
86 # XXX: argv=[] is a bit bold.
105 # XXX: argv=[] is a bit bold.
87 ipython0 = make_IPython(argv=[],
106 ipython0 = make_IPython(argv=argv,
88 user_ns=self.shell.user_ns,
107 user_ns=self.shell.user_ns,
89 user_global_ns=self.shell.user_global_ns)
108 user_global_ns=self.shell.user_global_ns)
109 __builtin__.raw_input = old_rawinput
90 self.ipython0 = ipython0
110 self.ipython0 = ipython0
91 # Set the pager:
111 # Set the pager:
92 self.ipython0.set_hook('show_in_pager',
112 self.ipython0.set_hook('show_in_pager',
93 lambda s, string: self.write("\n" + string))
113 lambda s, string: self.write("\n" + string))
94 self.ipython0.write = self.write
114 self.ipython0.write = self.write
95 self._ip = _ip = IPApi(self.ipython0)
115 self._ip = _ip = IPApi(self.ipython0)
96 # Make sure the raw system call doesn't get called, as we don't
116 # Make sure the raw system call doesn't get called, as we don't
97 # have a stdin accessible.
117 # have a stdin accessible.
98 self._ip.system = self.system_call
118 self._ip.system = self.system_call
99 # XXX: Muck around with magics so that they work better
119 # XXX: Muck around with magics so that they work better
100 # in our environment
120 # in our environment
121 if not sys.platform.startswith('win'):
101 self.ipython0.magic_ls = mk_system_call(self.system_call,
122 self.ipython0.magic_ls = mk_system_call(self.system_call,
102 'ls -CF')
123 'ls -CF')
103 # And now clean up the mess created by ipython0
124 # And now clean up the mess created by ipython0
104 self.release_output()
125 self.release_output()
105
126
106
127
107 if not 'banner' in kwargs and self.banner is None:
128 if not 'banner' in kwargs and self.banner is None:
108 self.banner = self.ipython0.BANNER + """
129 self.banner = self.ipython0.BANNER
109 This is the wx frontend, by Gael Varoquaux. This is EXPERIMENTAL code."""
110
130
131 # FIXME: __init__ and start should be two different steps
111 self.start()
132 self.start()
112
133
113 #--------------------------------------------------------------------------
134 #--------------------------------------------------------------------------
114 # FrontEndBase interface
135 # FrontEndBase interface
115 #--------------------------------------------------------------------------
136 #--------------------------------------------------------------------------
116
137
117 def show_traceback(self):
138 def show_traceback(self):
118 """ Use ipython0 to capture the last traceback and display it.
139 """ Use ipython0 to capture the last traceback and display it.
119 """
140 """
120 self.capture_output()
141 # Don't do the capture; the except_hook has already done some
142 # modifications to the IO streams, if we store them, we'll be
143 # storing the wrong ones.
144 #self.capture_output()
121 self.ipython0.showtraceback(tb_offset=-1)
145 self.ipython0.showtraceback(tb_offset=-1)
122 self.release_output()
146 self.release_output()
123
147
124
148
125 def execute(self, python_string, raw_string=None):
149 def execute(self, python_string, raw_string=None):
126 if self.debug:
150 if self.debug:
127 print 'Executing Python code:', repr(python_string)
151 print 'Executing Python code:', repr(python_string)
128 self.capture_output()
152 self.capture_output()
129 LineFrontEndBase.execute(self, python_string,
153 LineFrontEndBase.execute(self, python_string,
130 raw_string=raw_string)
154 raw_string=raw_string)
131 self.release_output()
155 self.release_output()
132
156
133
157
134 def save_output_hooks(self):
158 def save_output_hooks(self):
135 """ Store all the output hooks we can think of, to be able to
159 """ Store all the output hooks we can think of, to be able to
136 restore them.
160 restore them.
137
161
138 We need to do this early, as starting the ipython0 instance will
162 We need to do this early, as starting the ipython0 instance will
139 screw ouput hooks.
163 screw ouput hooks.
140 """
164 """
141 self.__old_cout_write = Term.cout.write
165 self.__old_cout_write = Term.cout.write
142 self.__old_cerr_write = Term.cerr.write
166 self.__old_cerr_write = Term.cerr.write
143 self.__old_stdout = sys.stdout
167 self.__old_stdout = sys.stdout
144 self.__old_stderr= sys.stderr
168 self.__old_stderr= sys.stderr
145 self.__old_help_output = pydoc.help.output
169 self.__old_help_output = pydoc.help.output
146 self.__old_display_hook = sys.displayhook
170 self.__old_display_hook = sys.displayhook
147
171
148
172
149 def capture_output(self):
173 def capture_output(self):
150 """ Capture all the output mechanisms we can think of.
174 """ Capture all the output mechanisms we can think of.
151 """
175 """
152 self.save_output_hooks()
176 self.save_output_hooks()
153 Term.cout.write = self.write
177 Term.cout.write = self.write
154 Term.cerr.write = self.write
178 Term.cerr.write = self.write
155 sys.stdout = Term.cout
179 sys.stdout = Term.cout
156 sys.stderr = Term.cerr
180 sys.stderr = Term.cerr
157 pydoc.help.output = self.shell.output_trap.out
181 pydoc.help.output = self.shell.output_trap.out
158
182
159
183
160 def release_output(self):
184 def release_output(self):
161 """ Release all the different captures we have made.
185 """ Release all the different captures we have made.
162 """
186 """
163 Term.cout.write = self.__old_cout_write
187 Term.cout.write = self.__old_cout_write
164 Term.cerr.write = self.__old_cerr_write
188 Term.cerr.write = self.__old_cerr_write
165 sys.stdout = self.__old_stdout
189 sys.stdout = self.__old_stdout
166 sys.stderr = self.__old_stderr
190 sys.stderr = self.__old_stderr
167 pydoc.help.output = self.__old_help_output
191 pydoc.help.output = self.__old_help_output
168 sys.displayhook = self.__old_display_hook
192 sys.displayhook = self.__old_display_hook
169
193
170
194
171 def complete(self, line):
195 def complete(self, line):
172 # FIXME: This should be factored out in the linefrontendbase
196 # FIXME: This should be factored out in the linefrontendbase
173 # method.
197 # method.
174 word = line.split('\n')[-1].split(' ')[-1]
198 word = self._get_completion_text(line)
175 completions = self.ipython0.complete(word)
199 completions = self.ipython0.complete(word)
176 # FIXME: The proper sort should be done in the complete method.
200 # FIXME: The proper sort should be done in the complete method.
177 key = lambda x: x.replace('_', '')
201 key = lambda x: x.replace('_', '')
178 completions.sort(key=key)
202 completions.sort(key=key)
179 if completions:
203 if completions:
180 prefix = common_prefix(completions)
204 prefix = common_prefix(completions)
181 line = line[:-len(word)] + prefix
205 line = line[:-len(word)] + prefix
182 return line, completions
206 return line, completions
183
207
184
208
185 #--------------------------------------------------------------------------
209 #--------------------------------------------------------------------------
186 # LineFrontEndBase interface
210 # LineFrontEndBase interface
187 #--------------------------------------------------------------------------
211 #--------------------------------------------------------------------------
188
212
189 def prefilter_input(self, input_string):
213 def prefilter_input(self, input_string):
190 """ Using IPython0 to prefilter the commands to turn them
214 """ Using IPython0 to prefilter the commands to turn them
191 in executable statements that are valid Python strings.
215 in executable statements that are valid Python strings.
192 """
216 """
193 input_string = LineFrontEndBase.prefilter_input(self, input_string)
217 input_string = LineFrontEndBase.prefilter_input(self, input_string)
194 filtered_lines = []
218 filtered_lines = []
195 # The IPython0 prefilters sometime produce output. We need to
219 # The IPython0 prefilters sometime produce output. We need to
196 # capture it.
220 # capture it.
197 self.capture_output()
221 self.capture_output()
198 self.last_result = dict(number=self.prompt_number)
222 self.last_result = dict(number=self.prompt_number)
199
223
200 ## try:
224 ## try:
201 ## for line in input_string.split('\n'):
225 ## for line in input_string.split('\n'):
202 ## filtered_lines.append(
226 ## filtered_lines.append(
203 ## self.ipython0.prefilter(line, False).rstrip())
227 ## self.ipython0.prefilter(line, False).rstrip())
204 ## except:
228 ## except:
205 ## # XXX: probably not the right thing to do.
229 ## # XXX: probably not the right thing to do.
206 ## self.ipython0.showsyntaxerror()
230 ## self.ipython0.showsyntaxerror()
207 ## self.after_execute()
231 ## self.after_execute()
208 ## finally:
232 ## finally:
209 ## self.release_output()
233 ## self.release_output()
210
234
211
235
212 try:
236 try:
213 try:
237 try:
214 for line in input_string.split('\n'):
238 for line in input_string.split('\n'):
215 filtered_lines.append(
239 filtered_lines.append(
216 self.ipython0.prefilter(line, False).rstrip())
240 self.ipython0.prefilter(line, False).rstrip())
217 except:
241 except:
218 # XXX: probably not the right thing to do.
242 # XXX: probably not the right thing to do.
219 self.ipython0.showsyntaxerror()
243 self.ipython0.showsyntaxerror()
220 self.after_execute()
244 self.after_execute()
221 finally:
245 finally:
222 self.release_output()
246 self.release_output()
223
247
224
248
225
249
226 # Clean up the trailing whitespace, to avoid indentation errors
250 # Clean up the trailing whitespace, to avoid indentation errors
227 filtered_string = '\n'.join(filtered_lines)
251 filtered_string = '\n'.join(filtered_lines)
228 return filtered_string
252 return filtered_string
229
253
230
254
231 #--------------------------------------------------------------------------
255 #--------------------------------------------------------------------------
232 # PrefilterFrontEnd interface
256 # PrefilterFrontEnd interface
233 #--------------------------------------------------------------------------
257 #--------------------------------------------------------------------------
234
258
235 def system_call(self, command_string):
259 def system_call(self, command_string):
236 """ Allows for frontend to define their own system call, to be
260 """ Allows for frontend to define their own system call, to be
237 able capture output and redirect input.
261 able capture output and redirect input.
238 """
262 """
239 return os.system(command_string)
263 return os.system(command_string)
240
264
241
265
242 def do_exit(self):
266 def do_exit(self):
243 """ Exit the shell, cleanup and save the history.
267 """ Exit the shell, cleanup and save the history.
244 """
268 """
245 self.ipython0.atexit_operations()
269 self.ipython0.atexit_operations()
246
270
271
272 def _get_completion_text(self, line):
273 """ Returns the text to be completed by breaking the line at specified
274 delimiters.
275 """
276 # Break at: spaces, '=', all parentheses (except if balanced).
277 # FIXME2: In the future, we need to make the implementation similar to
278 # that in the 'pyreadline' module (modes/basemode.py) where we break at
279 # each delimiter and try to complete the residual line, until we get a
280 # successful list of completions.
281 expression = '\s|=|,|:|\((?!.*\))|\[(?!.*\])|\{(?!.*\})'
282 complete_sep = re.compile(expression)
283 text = complete_sep.split(line)[-1]
284 return text
285
1 NO CONTENT: file renamed from IPython/frontend/_process/__init__.py to IPython/frontend/process/__init__.py
NO CONTENT: file renamed from IPython/frontend/_process/__init__.py to IPython/frontend/process/__init__.py
@@ -1,179 +1,184 b''
1 # Addapted from killableprocess.py.
1 # Addapted from killableprocess.py.
2 #______________________________________________________________________________
2 #______________________________________________________________________________
3 #
3 #
4 # killableprocess - subprocesses which can be reliably killed
4 # killableprocess - subprocesses which can be reliably killed
5 #
5 #
6 # Parts of this module are copied from the subprocess.py file contained
6 # Parts of this module are copied from the subprocess.py file contained
7 # in the Python distribution.
7 # in the Python distribution.
8 #
8 #
9 # Copyright (c) 2003-2004 by Peter Astrand <astrand@lysator.liu.se>
9 # Copyright (c) 2003-2004 by Peter Astrand <astrand@lysator.liu.se>
10 #
10 #
11 # Additions and modifications written by Benjamin Smedberg
11 # Additions and modifications written by Benjamin Smedberg
12 # <benjamin@smedbergs.us> are Copyright (c) 2006 by the Mozilla Foundation
12 # <benjamin@smedbergs.us> are Copyright (c) 2006 by the Mozilla Foundation
13 # <http://www.mozilla.org/>
13 # <http://www.mozilla.org/>
14 #
14 #
15 # By obtaining, using, and/or copying this software and/or its
15 # By obtaining, using, and/or copying this software and/or its
16 # associated documentation, you agree that you have read, understood,
16 # associated documentation, you agree that you have read, understood,
17 # and will comply with the following terms and conditions:
17 # and will comply with the following terms and conditions:
18 #
18 #
19 # Permission to use, copy, modify, and distribute this software and
19 # Permission to use, copy, modify, and distribute this software and
20 # its associated documentation for any purpose and without fee is
20 # its associated documentation for any purpose and without fee is
21 # hereby granted, provided that the above copyright notice appears in
21 # hereby granted, provided that the above copyright notice appears in
22 # all copies, and that both that copyright notice and this permission
22 # all copies, and that both that copyright notice and this permission
23 # notice appear in supporting documentation, and that the name of the
23 # notice appear in supporting documentation, and that the name of the
24 # author not be used in advertising or publicity pertaining to
24 # author not be used in advertising or publicity pertaining to
25 # distribution of the software without specific, written prior
25 # distribution of the software without specific, written prior
26 # permission.
26 # permission.
27 #
27 #
28 # THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
28 # THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
29 # INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
29 # INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
30 # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR
30 # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR
31 # CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
31 # CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
32 # OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
32 # OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
33 # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
33 # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
34 # WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
34 # WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
35
35
36 r"""killableprocess - Subprocesses which can be reliably killed
36 r"""killableprocess - Subprocesses which can be reliably killed
37
37
38 This module is a subclass of the builtin "subprocess" module. It allows
38 This module is a subclass of the builtin "subprocess" module. It allows
39 processes that launch subprocesses to be reliably killed on Windows (via the Popen.kill() method.
39 processes that launch subprocesses to be reliably killed on Windows (via the Popen.kill() method.
40
40
41 It also adds a timeout argument to Wait() for a limited period of time before
41 It also adds a timeout argument to Wait() for a limited period of time before
42 forcefully killing the process.
42 forcefully killing the process.
43
43
44 Note: On Windows, this module requires Windows 2000 or higher (no support for
44 Note: On Windows, this module requires Windows 2000 or higher (no support for
45 Windows 95, 98, or NT 4.0). It also requires ctypes, which is bundled with
45 Windows 95, 98, or NT 4.0). It also requires ctypes, which is bundled with
46 Python 2.5+ or available from http://python.net/crew/theller/ctypes/
46 Python 2.5+ or available from http://python.net/crew/theller/ctypes/
47 """
47 """
48
48
49 import subprocess
49 import subprocess
50 from subprocess import PIPE
50 from subprocess import PIPE
51 import sys
51 import sys
52 import os
52 import os
53 import types
53 import types
54
54
55 try:
55 try:
56 from subprocess import CalledProcessError
56 from subprocess import CalledProcessError
57 except ImportError:
57 except ImportError:
58 # Python 2.4 doesn't implement CalledProcessError
58 # Python 2.4 doesn't implement CalledProcessError
59 class CalledProcessError(Exception):
59 class CalledProcessError(Exception):
60 """This exception is raised when a process run by check_call() returns
60 """This exception is raised when a process run by check_call() returns
61 a non-zero exit status. The exit status will be stored in the
61 a non-zero exit status. The exit status will be stored in the
62 returncode attribute."""
62 returncode attribute."""
63 def __init__(self, returncode, cmd):
63 def __init__(self, returncode, cmd):
64 self.returncode = returncode
64 self.returncode = returncode
65 self.cmd = cmd
65 self.cmd = cmd
66 def __str__(self):
66 def __str__(self):
67 return "Command '%s' returned non-zero exit status %d" % (self.cmd, self.returncode)
67 return "Command '%s' returned non-zero exit status %d" % (self.cmd, self.returncode)
68
68
69 mswindows = (sys.platform == "win32")
69 mswindows = (sys.platform == "win32")
70
70
71 skip = False
71 skip = False
72
72
73 if mswindows:
73 if mswindows:
74 import platform
74 import platform
75 if platform.uname()[3] == '' or platform.uname()[3] > '6.0.6000':
75 if platform.uname()[3] == '' or platform.uname()[3] > '6.0.6000':
76 # Killable process does not work under vista when starting for
76 # Killable process does not work under vista when starting for
77 # something else than cmd.
77 # something else than cmd.
78 skip = True
78 skip = True
79 else:
79 else:
80 import winprocess
80 import winprocess
81 else:
81 else:
82 import signal
82 import signal
83
83
84 if not mswindows:
84 if not mswindows:
85 def DoNothing(*args):
85 def DoNothing(*args):
86 pass
86 pass
87
87
88
88
89 if skip:
89 if skip:
90 Popen = subprocess.Popen
90 Popen = subprocess.Popen
91 else:
91 else:
92 class Popen(subprocess.Popen):
92 class Popen(subprocess.Popen):
93 if not mswindows:
93 if not mswindows:
94 # Override __init__ to set a preexec_fn
94 # Override __init__ to set a preexec_fn
95 def __init__(self, *args, **kwargs):
95 def __init__(self, *args, **kwargs):
96 if len(args) >= 7:
96 if len(args) >= 7:
97 raise Exception("Arguments preexec_fn and after must be passed by keyword.")
97 raise Exception("Arguments preexec_fn and after must be passed by keyword.")
98
98
99 real_preexec_fn = kwargs.pop("preexec_fn", None)
99 real_preexec_fn = kwargs.pop("preexec_fn", None)
100 def setpgid_preexec_fn():
100 def setpgid_preexec_fn():
101 os.setpgid(0, 0)
101 os.setpgid(0, 0)
102 if real_preexec_fn:
102 if real_preexec_fn:
103 apply(real_preexec_fn)
103 apply(real_preexec_fn)
104
104
105 kwargs['preexec_fn'] = setpgid_preexec_fn
105 kwargs['preexec_fn'] = setpgid_preexec_fn
106
106
107 subprocess.Popen.__init__(self, *args, **kwargs)
107 subprocess.Popen.__init__(self, *args, **kwargs)
108
108
109 if mswindows:
109 if mswindows:
110 def _execute_child(self, args, executable, preexec_fn, close_fds,
110 def _execute_child(self, args, executable, preexec_fn, close_fds,
111 cwd, env, universal_newlines, startupinfo,
111 cwd, env, universal_newlines, startupinfo,
112 creationflags, shell,
112 creationflags, shell,
113 p2cread, p2cwrite,
113 p2cread, p2cwrite,
114 c2pread, c2pwrite,
114 c2pread, c2pwrite,
115 errread, errwrite):
115 errread, errwrite):
116 if not isinstance(args, types.StringTypes):
116 if not isinstance(args, types.StringTypes):
117 args = subprocess.list2cmdline(args)
117 args = subprocess.list2cmdline(args)
118
118
119 if startupinfo is None:
119 if startupinfo is None:
120 startupinfo = winprocess.STARTUPINFO()
120 startupinfo = winprocess.STARTUPINFO()
121
121
122 if None not in (p2cread, c2pwrite, errwrite):
122 if None not in (p2cread, c2pwrite, errwrite):
123 startupinfo.dwFlags |= winprocess.STARTF_USESTDHANDLES
123 startupinfo.dwFlags |= winprocess.STARTF_USESTDHANDLES
124
124
125 startupinfo.hStdInput = int(p2cread)
125 startupinfo.hStdInput = int(p2cread)
126 startupinfo.hStdOutput = int(c2pwrite)
126 startupinfo.hStdOutput = int(c2pwrite)
127 startupinfo.hStdError = int(errwrite)
127 startupinfo.hStdError = int(errwrite)
128 if shell:
128 if shell:
129 startupinfo.dwFlags |= winprocess.STARTF_USESHOWWINDOW
129 startupinfo.dwFlags |= winprocess.STARTF_USESHOWWINDOW
130 startupinfo.wShowWindow = winprocess.SW_HIDE
130 startupinfo.wShowWindow = winprocess.SW_HIDE
131 comspec = os.environ.get("COMSPEC", "cmd.exe")
131 comspec = os.environ.get("COMSPEC", "cmd.exe")
132 args = comspec + " /c " + args
132 args = comspec + " /c " + args
133
133
134 # We create a new job for this process, so that we can kill
134 # We create a new job for this process, so that we can kill
135 # the process and any sub-processes
135 # the process and any sub-processes
136 self._job = winprocess.CreateJobObject()
136 self._job = winprocess.CreateJobObject()
137
137
138 creationflags |= winprocess.CREATE_SUSPENDED
138 creationflags |= winprocess.CREATE_SUSPENDED
139 creationflags |= winprocess.CREATE_UNICODE_ENVIRONMENT
139 creationflags |= winprocess.CREATE_UNICODE_ENVIRONMENT
140
140
141 hp, ht, pid, tid = winprocess.CreateProcess(
141 hp, ht, pid, tid = winprocess.CreateProcess(
142 executable, args,
142 executable, args,
143 None, None, # No special security
143 None, None, # No special security
144 1, # Must inherit handles!
144 1, # Must inherit handles!
145 creationflags,
145 creationflags,
146 winprocess.EnvironmentBlock(env),
146 winprocess.EnvironmentBlock(env),
147 cwd, startupinfo)
147 cwd, startupinfo)
148
148
149 self._child_created = True
149 self._child_created = True
150 self._handle = hp
150 self._handle = hp
151 self._thread = ht
151 self._thread = ht
152 self.pid = pid
152 self.pid = pid
153
153
154 # XXX: A try/except to fix UAC-related problems under
155 # Windows Vista, when reparenting jobs.
156 try:
154 winprocess.AssignProcessToJobObject(self._job, hp)
157 winprocess.AssignProcessToJobObject(self._job, hp)
158 except WindowsError:
159 pass
155 winprocess.ResumeThread(ht)
160 winprocess.ResumeThread(ht)
156
161
157 if p2cread is not None:
162 if p2cread is not None:
158 p2cread.Close()
163 p2cread.Close()
159 if c2pwrite is not None:
164 if c2pwrite is not None:
160 c2pwrite.Close()
165 c2pwrite.Close()
161 if errwrite is not None:
166 if errwrite is not None:
162 errwrite.Close()
167 errwrite.Close()
163
168
164 def kill(self, group=True):
169 def kill(self, group=True):
165 """Kill the process. If group=True, all sub-processes will also be killed."""
170 """Kill the process. If group=True, all sub-processes will also be killed."""
166 if mswindows:
171 if mswindows:
167 if group:
172 if group:
168 winprocess.TerminateJobObject(self._job, 127)
173 winprocess.TerminateJobObject(self._job, 127)
169 else:
174 else:
170 winprocess.TerminateProcess(self._handle, 127)
175 winprocess.TerminateProcess(self._handle, 127)
171 self.returncode = 127
176 self.returncode = 127
172 else:
177 else:
173 if group:
178 if group:
174 os.killpg(self.pid, signal.SIGKILL)
179 os.killpg(self.pid, signal.SIGKILL)
175 else:
180 else:
176 os.kill(self.pid, signal.SIGKILL)
181 os.kill(self.pid, signal.SIGKILL)
177 self.returncode = -9
182 self.returncode = -9
178
183
179
184
1 NO CONTENT: file renamed from IPython/frontend/_process/pipedprocess.py to IPython/frontend/process/pipedprocess.py
NO CONTENT: file renamed from IPython/frontend/_process/pipedprocess.py to IPython/frontend/process/pipedprocess.py
1 NO CONTENT: file renamed from IPython/frontend/_process/winprocess.py to IPython/frontend/process/winprocess.py
NO CONTENT: file renamed from IPython/frontend/_process/winprocess.py to IPython/frontend/process/winprocess.py
@@ -1,155 +1,109 b''
1 # encoding: utf-8
1 # encoding: utf-8
2
2
3 """This file contains unittests for the frontendbase module."""
3 """This file contains unittests for the asyncfrontendbase module."""
4
4
5 __docformat__ = "restructuredtext en"
5 __docformat__ = "restructuredtext en"
6
6
7 #---------------------------------------------------------------------------
7 #---------------------------------------------------------------------------
8 # Copyright (C) 2008 The IPython Development Team
8 # Copyright (C) 2008 The IPython Development Team
9 #
9 #
10 # Distributed under the terms of the BSD License. The full license is in
10 # Distributed under the terms of the BSD License. The full license is in
11 # the file COPYING, distributed as part of this software.
11 # the file COPYING, distributed as part of this software.
12 #---------------------------------------------------------------------------
12 #---------------------------------------------------------------------------
13
13
14 #---------------------------------------------------------------------------
14 #---------------------------------------------------------------------------
15 # Imports
15 # Imports
16 #---------------------------------------------------------------------------
16 #---------------------------------------------------------------------------
17
17
18 import unittest
18 # Tell nose to skip this module
19 __test__ = {}
19
20
20 try:
21 from twisted.trial import unittest
21 from IPython.frontend.asyncfrontendbase import AsyncFrontEndBase
22 from IPython.frontend.asyncfrontendbase import AsyncFrontEndBase
22 from IPython.frontend import frontendbase
23 from IPython.frontend import frontendbase
23 from IPython.kernel.engineservice import EngineService
24 from IPython.kernel.engineservice import EngineService
24 except ImportError:
25 from IPython.testing.parametric import Parametric, parametric
25 import nose
26 raise nose.SkipTest("This test requires zope.interface, Twisted and Foolscap")
27
26
28 from IPython.testing.decorators import skip
29
27
30 class FrontEndCallbackChecker(AsyncFrontEndBase):
28 class FrontEndCallbackChecker(AsyncFrontEndBase):
31 """FrontEndBase subclass for checking callbacks"""
29 """FrontEndBase subclass for checking callbacks"""
32 def __init__(self, engine=None, history=None):
30 def __init__(self, engine=None, history=None):
33 super(FrontEndCallbackChecker, self).__init__(engine=engine,
31 super(FrontEndCallbackChecker, self).__init__(engine=engine,
34 history=history)
32 history=history)
35 self.updateCalled = False
33 self.updateCalled = False
36 self.renderResultCalled = False
34 self.renderResultCalled = False
37 self.renderErrorCalled = False
35 self.renderErrorCalled = False
38
36
39 def update_cell_prompt(self, result, blockID=None):
37 def update_cell_prompt(self, result, blockID=None):
40 self.updateCalled = True
38 self.updateCalled = True
41 return result
39 return result
42
40
43 def render_result(self, result):
41 def render_result(self, result):
44 self.renderResultCalled = True
42 self.renderResultCalled = True
45 return result
43 return result
46
44
47
48 def render_error(self, failure):
45 def render_error(self, failure):
49 self.renderErrorCalled = True
46 self.renderErrorCalled = True
50 return failure
47 return failure
51
48
52
49
53
54
55 class TestAsyncFrontendBase(unittest.TestCase):
50 class TestAsyncFrontendBase(unittest.TestCase):
56 def setUp(self):
51 def setUp(self):
57 """Setup the EngineService and FrontEndBase"""
52 """Setup the EngineService and FrontEndBase"""
58
53
59 self.fb = FrontEndCallbackChecker(engine=EngineService())
54 self.fb = FrontEndCallbackChecker(engine=EngineService())
60
55
61 def test_implements_IFrontEnd(self):
56 def test_implements_IFrontEnd(self):
62 assert(frontendbase.IFrontEnd.implementedBy(
57 self.assert_(frontendbase.IFrontEnd.implementedBy(
63 AsyncFrontEndBase))
58 AsyncFrontEndBase))
64
59
65 def test_is_complete_returns_False_for_incomplete_block(self):
60 def test_is_complete_returns_False_for_incomplete_block(self):
66 """"""
67
68 block = """def test(a):"""
61 block = """def test(a):"""
69
62 self.assert_(self.fb.is_complete(block) == False)
70 assert(self.fb.is_complete(block) == False)
71
63
72 def test_is_complete_returns_True_for_complete_block(self):
64 def test_is_complete_returns_True_for_complete_block(self):
73 """"""
74
75 block = """def test(a): pass"""
65 block = """def test(a): pass"""
76
66 self.assert_(self.fb.is_complete(block))
77 assert(self.fb.is_complete(block))
78
79 block = """a=3"""
67 block = """a=3"""
80
68 self.assert_(self.fb.is_complete(block))
81 assert(self.fb.is_complete(block))
82
69
83 def test_blockID_added_to_result(self):
70 def test_blockID_added_to_result(self):
84 block = """3+3"""
71 block = """3+3"""
85
86 d = self.fb.execute(block, blockID='TEST_ID')
72 d = self.fb.execute(block, blockID='TEST_ID')
87
73 d.addCallback(lambda r: self.assert_(r['blockID']=='TEST_ID'))
88 d.addCallback(self.checkBlockID, expected='TEST_ID')
74 return d
89
75
90 def test_blockID_added_to_failure(self):
76 def test_blockID_added_to_failure(self):
91 block = "raise Exception()"
77 block = "raise Exception()"
92
93 d = self.fb.execute(block,blockID='TEST_ID')
78 d = self.fb.execute(block,blockID='TEST_ID')
94 d.addErrback(self.checkFailureID, expected='TEST_ID')
79 d.addErrback(lambda f: self.assert_(f.blockID=='TEST_ID'))
95
80 return d
96 def checkBlockID(self, result, expected=""):
97 assert(result['blockID'] == expected)
98
99
100 def checkFailureID(self, failure, expected=""):
101 assert(failure.blockID == expected)
102
103
81
104 def test_callbacks_added_to_execute(self):
82 def test_callbacks_added_to_execute(self):
105 """test that
106 update_cell_prompt
107 render_result
108
109 are added to execute request
110 """
111
112 d = self.fb.execute("10+10")
83 d = self.fb.execute("10+10")
113 d.addCallback(self.checkCallbacks)
84 d.addCallback(lambda r: self.assert_(self.fb.updateCalled and self.fb.renderResultCalled))
85 return d
114
86
115 def checkCallbacks(self, result):
116 assert(self.fb.updateCalled)
117 assert(self.fb.renderResultCalled)
118
119 @skip("This test fails and lead to an unhandled error in a Deferred.")
120 def test_error_callback_added_to_execute(self):
87 def test_error_callback_added_to_execute(self):
121 """test that render_error called on execution error"""
88 """Test that render_error called on execution error."""
122
89
123 d = self.fb.execute("raise Exception()")
90 d = self.fb.execute("raise Exception()")
124 d.addCallback(self.checkRenderError)
91 d.addErrback(lambda f: self.assert_(self.fb.renderErrorCalled))
125
92 return d
126 def checkRenderError(self, result):
127 assert(self.fb.renderErrorCalled)
128
93
129 def test_history_returns_expected_block(self):
94 def test_history_returns_expected_block(self):
130 """Make sure history browsing doesn't fail"""
95 """Make sure history browsing doesn't fail."""
131
96
132 blocks = ["a=1","a=2","a=3"]
97 blocks = ["a=1","a=2","a=3"]
133 for b in blocks:
98 d = self.fb.execute(blocks[0])
134 d = self.fb.execute(b)
99 d.addCallback(lambda _: self.fb.execute(blocks[1]))
135
100 d.addCallback(lambda _: self.fb.execute(blocks[2]))
136 # d is now the deferred for the last executed block
101 d.addCallback(lambda _: self.assert_(self.fb.get_history_previous("")==blocks[-2]))
137 d.addCallback(self.historyTests, blocks)
102 d.addCallback(lambda _: self.assert_(self.fb.get_history_previous("")==blocks[-3]))
138
103 d.addCallback(lambda _: self.assert_(self.fb.get_history_next()==blocks[-2]))
139
104 return d
140 def historyTests(self, result, blocks):
141 """historyTests"""
142
143 assert(len(blocks) >= 3)
144 assert(self.fb.get_history_previous("") == blocks[-2])
145 assert(self.fb.get_history_previous("") == blocks[-3])
146 assert(self.fb.get_history_next() == blocks[-2])
147
148
105
149 def test_history_returns_none_at_startup(self):
106 def test_history_returns_none_at_startup(self):
150 """test_history_returns_none_at_startup"""
107 self.assert_(self.fb.get_history_previous("")==None)
151
108 self.assert_(self.fb.get_history_next()==None)
152 assert(self.fb.get_history_previous("")==None)
153 assert(self.fb.get_history_next()==None)
154
155
109
@@ -1,180 +1,252 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 Test process execution and IO redirection.
3 Test process execution and IO redirection.
4 """
4 """
5
5
6 __docformat__ = "restructuredtext en"
6 __docformat__ = "restructuredtext en"
7
7
8 #-------------------------------------------------------------------------------
8 #-------------------------------------------------------------------------------
9 # Copyright (C) 2008 The IPython Development Team
9 # Copyright (C) 2008 The IPython Development Team
10 #
10 #
11 # Distributed under the terms of the BSD License. The full license is
11 # Distributed under the terms of the BSD License. The full license is
12 # in the file COPYING, distributed as part of this software.
12 # in the file COPYING, distributed as part of this software.
13 #-------------------------------------------------------------------------------
13 #-------------------------------------------------------------------------------
14
14
15 from copy import copy, deepcopy
15 from cStringIO import StringIO
16 from cStringIO import StringIO
16 import string
17 import string
17
18
18 from IPython.ipapi import get as get_ipython0
19 from nose.tools import assert_equal
20
19 from IPython.frontend.prefilterfrontend import PrefilterFrontEnd
21 from IPython.frontend.prefilterfrontend import PrefilterFrontEnd
20 from copy import deepcopy
22 from IPython.ipapi import get as get_ipython0
23 from IPython.testing.plugin.ipdoctest import default_argv
24
25
26 def safe_deepcopy(d):
27 """ Deep copy every key of the given dict, when possible. Elsewhere
28 do a copy.
29 """
30 copied_d = dict()
31 for key, value in d.iteritems():
32 try:
33 copied_d[key] = deepcopy(value)
34 except:
35 try:
36 copied_d[key] = copy(value)
37 except:
38 copied_d[key] = value
39 return copied_d
40
21
41
22 class TestPrefilterFrontEnd(PrefilterFrontEnd):
42 class TestPrefilterFrontEnd(PrefilterFrontEnd):
23
43
24 input_prompt_template = string.Template('')
44 input_prompt_template = string.Template('')
25 output_prompt_template = string.Template('')
45 output_prompt_template = string.Template('')
26 banner = ''
46 banner = ''
27
47
28 def __init__(self):
48 def __init__(self):
29 ipython0 = get_ipython0().IP
30 self.out = StringIO()
49 self.out = StringIO()
31 PrefilterFrontEnd.__init__(self, ipython0=ipython0)
50 PrefilterFrontEnd.__init__(self,argv=default_argv())
32 # Clean up the namespace for isolation between tests
33 user_ns = self.ipython0.user_ns
34 # We need to keep references to things so that they don't
35 # get garbage collected (this stinks).
36 self.shadow_ns = dict()
37 for i in self.ipython0.magic_who_ls():
38 self.shadow_ns[i] = user_ns.pop(i)
39 # Some more code for isolation (yeah, crazy)
51 # Some more code for isolation (yeah, crazy)
40 self._on_enter()
52 self._on_enter()
41 self.out.flush()
53 self.out.flush()
42 self.out.reset()
54 self.out.reset()
43 self.out.truncate()
55 self.out.truncate()
44
56
45 def write(self, string, *args, **kwargs):
57 def write(self, string, *args, **kwargs):
46 self.out.write(string)
58 self.out.write(string)
47
59
48 def _on_enter(self):
60 def _on_enter(self):
49 self.input_buffer += '\n'
61 self.input_buffer += '\n'
50 PrefilterFrontEnd._on_enter(self)
62 PrefilterFrontEnd._on_enter(self)
51
63
52
64
53 def isolate_ipython0(func):
65 def isolate_ipython0(func):
54 """ Decorator to isolate execution that involves an iptyhon0.
66 """ Decorator to isolate execution that involves an iptyhon0.
67
68 Notes
69 -----
70
71 Apply only to functions with no arguments. Nose skips functions
72 with arguments.
55 """
73 """
56 def my_func(*args, **kwargs):
74 def my_func():
57 ipython0 = get_ipython0().IP
75 iplib = get_ipython0()
58 user_ns = deepcopy(ipython0.user_ns)
76 if iplib is None:
59 global_ns = deepcopy(ipython0.global_ns)
77 return func()
78 ipython0 = iplib.IP
79 global_ns = safe_deepcopy(ipython0.user_global_ns)
80 user_ns = safe_deepcopy(ipython0.user_ns)
60 try:
81 try:
61 func(*args, **kwargs)
82 out = func()
62 finally:
83 finally:
63 ipython0.user_ns = user_ns
84 ipython0.user_ns = user_ns
64 ipython0.global_ns = global_ns
85 ipython0.user_global_ns = global_ns
86 # Undo the hack at creation of PrefilterFrontEnd
87 from IPython import iplib
88 iplib.InteractiveShell.isthreaded = False
89 return out
65
90
91 my_func.__name__ = func.__name__
66 return my_func
92 return my_func
67
93
68
94
69 @isolate_ipython0
95 @isolate_ipython0
70 def test_execution():
96 def test_execution():
71 """ Test execution of a command.
97 """ Test execution of a command.
72 """
98 """
73 f = TestPrefilterFrontEnd()
99 f = TestPrefilterFrontEnd()
74 f.input_buffer = 'print 1'
100 f.input_buffer = 'print 1'
75 f._on_enter()
101 f._on_enter()
76 out_value = f.out.getvalue()
102 out_value = f.out.getvalue()
77 assert out_value == '1\n'
103 assert_equal(out_value, '1\n')
78
104
79
105
80 @isolate_ipython0
106 @isolate_ipython0
81 def test_multiline():
107 def test_multiline():
82 """ Test execution of a multiline command.
108 """ Test execution of a multiline command.
83 """
109 """
84 f = TestPrefilterFrontEnd()
110 f = TestPrefilterFrontEnd()
85 f.input_buffer = 'if True:'
111 f.input_buffer = 'if True:'
86 f._on_enter()
112 f._on_enter()
87 f.input_buffer += 'print 1'
113 f.input_buffer += 'print 1'
88 f._on_enter()
114 f._on_enter()
89 out_value = f.out.getvalue()
115 out_value = f.out.getvalue()
90 assert out_value == ''
116 yield assert_equal, out_value, ''
91 f._on_enter()
117 f._on_enter()
92 out_value = f.out.getvalue()
118 out_value = f.out.getvalue()
93 assert out_value == '1\n'
119 yield assert_equal, out_value, '1\n'
94 f = TestPrefilterFrontEnd()
120 f = TestPrefilterFrontEnd()
95 f.input_buffer='(1 +'
121 f.input_buffer='(1 +'
96 f._on_enter()
122 f._on_enter()
97 f.input_buffer += '0)'
123 f.input_buffer += '0)'
98 f._on_enter()
124 f._on_enter()
99 out_value = f.out.getvalue()
125 out_value = f.out.getvalue()
100 assert out_value == ''
126 yield assert_equal, out_value, ''
101 f._on_enter()
127 f._on_enter()
102 out_value = f.out.getvalue()
128 out_value = f.out.getvalue()
103 assert out_value == '1\n'
129 yield assert_equal, out_value, '1\n'
104
130
105
131
106 @isolate_ipython0
132 @isolate_ipython0
107 def test_capture():
133 def test_capture():
108 """ Test the capture of output in different channels.
134 """ Test the capture of output in different channels.
109 """
135 """
110 # Test on the OS-level stdout, stderr.
136 # Test on the OS-level stdout, stderr.
111 f = TestPrefilterFrontEnd()
137 f = TestPrefilterFrontEnd()
112 f.input_buffer = \
138 f.input_buffer = \
113 'import os; out=os.fdopen(1, "w"); out.write("1") ; out.flush()'
139 'import os; out=os.fdopen(1, "w"); out.write("1") ; out.flush()'
114 f._on_enter()
140 f._on_enter()
115 out_value = f.out.getvalue()
141 out_value = f.out.getvalue()
116 assert out_value == '1'
142 yield assert_equal, out_value, '1'
117 f = TestPrefilterFrontEnd()
143 f = TestPrefilterFrontEnd()
118 f.input_buffer = \
144 f.input_buffer = \
119 'import os; out=os.fdopen(2, "w"); out.write("1") ; out.flush()'
145 'import os; out=os.fdopen(2, "w"); out.write("1") ; out.flush()'
120 f._on_enter()
146 f._on_enter()
121 out_value = f.out.getvalue()
147 out_value = f.out.getvalue()
122 assert out_value == '1'
148 yield assert_equal, out_value, '1'
123
149
124
150
125 @isolate_ipython0
151 @isolate_ipython0
126 def test_magic():
152 def test_magic():
127 """ Test the magic expansion and history.
153 """ Test the magic expansion and history.
128
154
129 This test is fairly fragile and will break when magics change.
155 This test is fairly fragile and will break when magics change.
130 """
156 """
131 f = TestPrefilterFrontEnd()
157 f = TestPrefilterFrontEnd()
158 # Before checking the interactive namespace, make sure it's clear (it can
159 # otherwise pick up things stored in the user's local db)
160 f.input_buffer += '%reset -f'
161 f._on_enter()
162 f.complete_current_input()
163 # Now, run the %who magic and check output
132 f.input_buffer += '%who'
164 f.input_buffer += '%who'
133 f._on_enter()
165 f._on_enter()
134 out_value = f.out.getvalue()
166 out_value = f.out.getvalue()
135 assert out_value == 'Interactive namespace is empty.\n'
167 assert_equal(out_value, 'Interactive namespace is empty.\n')
136
168
137
169
138 @isolate_ipython0
170 @isolate_ipython0
139 def test_help():
171 def test_help():
140 """ Test object inspection.
172 """ Test object inspection.
141 """
173 """
142 f = TestPrefilterFrontEnd()
174 f = TestPrefilterFrontEnd()
143 f.input_buffer += "def f():"
175 f.input_buffer += "def f():"
144 f._on_enter()
176 f._on_enter()
145 f.input_buffer += "'foobar'"
177 f.input_buffer += "'foobar'"
146 f._on_enter()
178 f._on_enter()
147 f.input_buffer += "pass"
179 f.input_buffer += "pass"
148 f._on_enter()
180 f._on_enter()
149 f._on_enter()
181 f._on_enter()
150 f.input_buffer += "f?"
182 f.input_buffer += "f?"
151 f._on_enter()
183 f._on_enter()
152 assert 'traceback' not in f.last_result
184 assert 'traceback' not in f.last_result
153 ## XXX: ipython doctest magic breaks this. I have no clue why
185 ## XXX: ipython doctest magic breaks this. I have no clue why
154 #out_value = f.out.getvalue()
186 #out_value = f.out.getvalue()
155 #assert out_value.split()[-1] == 'foobar'
187 #assert out_value.split()[-1] == 'foobar'
156
188
157
189
158 @isolate_ipython0
190 @isolate_ipython0
159 def test_completion():
191 def test_completion_simple():
160 """ Test command-line completion.
192 """ Test command-line completion on trivial examples.
161 """
193 """
162 f = TestPrefilterFrontEnd()
194 f = TestPrefilterFrontEnd()
163 f.input_buffer = 'zzza = 1'
195 f.input_buffer = 'zzza = 1'
164 f._on_enter()
196 f._on_enter()
165 f.input_buffer = 'zzzb = 2'
197 f.input_buffer = 'zzzb = 2'
166 f._on_enter()
198 f._on_enter()
167 f.input_buffer = 'zz'
199 f.input_buffer = 'zz'
168 f.complete_current_input()
200 f.complete_current_input()
169 out_value = f.out.getvalue()
201 out_value = f.out.getvalue()
170 assert out_value == '\nzzza zzzb '
202 yield assert_equal, out_value, '\nzzza zzzb '
171 assert f.input_buffer == 'zzz'
203 yield assert_equal, f.input_buffer, 'zzz'
204
205
206 @isolate_ipython0
207 def test_completion_parenthesis():
208 """ Test command-line completion when a parenthesis is open.
209 """
210 f = TestPrefilterFrontEnd()
211 f.input_buffer = 'zzza = 1'
212 f._on_enter()
213 f.input_buffer = 'zzzb = 2'
214 f._on_enter()
215 f.input_buffer = 'map(zz'
216 f.complete_current_input()
217 out_value = f.out.getvalue()
218 yield assert_equal, out_value, '\nzzza zzzb '
219 yield assert_equal, f.input_buffer, 'map(zzz'
220
221
222 @isolate_ipython0
223 def test_completion_indexing():
224 """ Test command-line completion when indexing on objects.
225 """
226 f = TestPrefilterFrontEnd()
227 f.input_buffer = 'a = [0]'
228 f._on_enter()
229 f.input_buffer = 'a[0].'
230 f.complete_current_input()
231 assert_equal(f.input_buffer, 'a[0].__')
232
233
234 @isolate_ipython0
235 def test_completion_equal():
236 """ Test command-line completion when the delimiter is "=", not " ".
237 """
238 f = TestPrefilterFrontEnd()
239 f.input_buffer = 'a=1.'
240 f.complete_current_input()
241 assert_equal(f.input_buffer, 'a=1.__')
242
172
243
173
244
174 if __name__ == '__main__':
245 if __name__ == '__main__':
175 test_magic()
246 test_magic()
176 test_help()
247 test_help()
177 test_execution()
248 test_execution()
178 test_multiline()
249 test_multiline()
179 test_capture()
250 test_capture()
180 test_completion()
251 test_completion_simple()
252 test_completion_complex()
@@ -1,67 +1,67 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 Test process execution and IO redirection.
3 Test process execution and IO redirection.
4 """
4 """
5
5
6 __docformat__ = "restructuredtext en"
6 __docformat__ = "restructuredtext en"
7
7
8 #-------------------------------------------------------------------------------
8 #-----------------------------------------------------------------------------
9 # Copyright (C) 2008 The IPython Development Team
9 # Copyright (C) 2008-2009 The IPython Development Team
10 #
10 #
11 # Distributed under the terms of the BSD License. The full license is
11 # Distributed under the terms of the BSD License. The full license is
12 # in the file COPYING, distributed as part of this software.
12 # in the file COPYING, distributed as part of this software.
13 #-------------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14
14
15 from cStringIO import StringIO
15 from cStringIO import StringIO
16 from time import sleep
16 from time import sleep
17 import sys
17 import sys
18
18
19 from IPython.frontend._process import PipedProcess
19 from IPython.frontend.process import PipedProcess
20 from IPython.testing import decorators as testdec
20 from IPython.testing import decorators as testdec
21
21
22
22
23 def test_capture_out():
23 def test_capture_out():
24 """ A simple test to see if we can execute a process and get the output.
24 """ A simple test to see if we can execute a process and get the output.
25 """
25 """
26 s = StringIO()
26 s = StringIO()
27 p = PipedProcess('echo 1', out_callback=s.write, )
27 p = PipedProcess('echo 1', out_callback=s.write, )
28 p.start()
28 p.start()
29 p.join()
29 p.join()
30 result = s.getvalue().rstrip()
30 result = s.getvalue().rstrip()
31 assert result == '1'
31 assert result == '1'
32
32
33
33
34 def test_io():
34 def test_io():
35 """ Checks that we can send characters on stdin to the process.
35 """ Checks that we can send characters on stdin to the process.
36 """
36 """
37 s = StringIO()
37 s = StringIO()
38 p = PipedProcess(sys.executable + ' -c "a = raw_input(); print a"',
38 p = PipedProcess(sys.executable + ' -c "a = raw_input(); print a"',
39 out_callback=s.write, )
39 out_callback=s.write, )
40 p.start()
40 p.start()
41 test_string = '12345\n'
41 test_string = '12345\n'
42 while not hasattr(p, 'process'):
42 while not hasattr(p, 'process'):
43 sleep(0.1)
43 sleep(0.1)
44 p.process.stdin.write(test_string)
44 p.process.stdin.write(test_string)
45 p.join()
45 p.join()
46 result = s.getvalue()
46 result = s.getvalue()
47 assert result == test_string
47 assert result == test_string
48
48
49
49
50 def test_kill():
50 def test_kill():
51 """ Check that we can kill a process, and its subprocess.
51 """ Check that we can kill a process, and its subprocess.
52 """
52 """
53 s = StringIO()
53 s = StringIO()
54 p = PipedProcess(sys.executable + ' -c "a = raw_input();"',
54 p = PipedProcess(sys.executable + ' -c "a = raw_input();"',
55 out_callback=s.write, )
55 out_callback=s.write, )
56 p.start()
56 p.start()
57 while not hasattr(p, 'process'):
57 while not hasattr(p, 'process'):
58 sleep(0.1)
58 sleep(0.1)
59 p.process.kill()
59 p.process.kill()
60 assert p.process.poll() is not None
60 assert p.process.poll() is not None
61
61
62
62
63 if __name__ == '__main__':
63 if __name__ == '__main__':
64 test_capture_out()
64 test_capture_out()
65 test_io()
65 test_io()
66 test_kill()
66 test_kill()
67
67
@@ -1,436 +1,625 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 A Wx widget to act as a console and input commands.
3 A Wx widget to act as a console and input commands.
4
4
5 This widget deals with prompts and provides an edit buffer
5 This widget deals with prompts and provides an edit buffer
6 restricted to after the last prompt.
6 restricted to after the last prompt.
7 """
7 """
8
8
9 __docformat__ = "restructuredtext en"
9 __docformat__ = "restructuredtext en"
10
10
11 #-------------------------------------------------------------------------------
11 #-------------------------------------------------------------------------------
12 # Copyright (C) 2008 The IPython Development Team
12 # Copyright (C) 2008 The IPython Development Team
13 #
13 #
14 # Distributed under the terms of the BSD License. The full license is
14 # Distributed under the terms of the BSD License. The full license is
15 # in the file COPYING, distributed as part of this software.
15 # in the file COPYING, distributed as part of this software.
16 #-------------------------------------------------------------------------------
16 #-------------------------------------------------------------------------------
17
17
18 #-------------------------------------------------------------------------------
18 #-------------------------------------------------------------------------------
19 # Imports
19 # Imports
20 #-------------------------------------------------------------------------------
20 #-------------------------------------------------------------------------------
21
21
22 import wx
22 import wx
23 import wx.stc as stc
23 import wx.stc as stc
24
24
25 from wx.py import editwindow
25 from wx.py import editwindow
26 import time
26 import time
27 import sys
27 import sys
28 import string
29
28 LINESEP = '\n'
30 LINESEP = '\n'
29 if sys.platform == 'win32':
31 if sys.platform == 'win32':
30 LINESEP = '\n\r'
32 LINESEP = '\n\r'
31
33
32 import re
34 import re
33
35
34 # FIXME: Need to provide an API for non user-generated display on the
36 # FIXME: Need to provide an API for non user-generated display on the
35 # screen: this should not be editable by the user.
37 # screen: this should not be editable by the user.
38 #-------------------------------------------------------------------------------
39 # Constants
40 #-------------------------------------------------------------------------------
41 _COMPLETE_BUFFER_MARKER = 31
42 _ERROR_MARKER = 30
43 _INPUT_MARKER = 29
36
44
37 _DEFAULT_SIZE = 10
45 _DEFAULT_SIZE = 10
38 if sys.platform == 'darwin':
46 if sys.platform == 'darwin':
39 _DEFAULT_SIZE = 12
47 _DEFAULT_SIZE = 12
40
48
41 _DEFAULT_STYLE = {
49 _DEFAULT_STYLE = {
42 'stdout' : 'fore:#0000FF',
50 #background definition
43 'stderr' : 'fore:#007f00',
44 'trace' : 'fore:#FF0000',
45
46 'default' : 'size:%d' % _DEFAULT_SIZE,
51 'default' : 'size:%d' % _DEFAULT_SIZE,
47 'bracegood' : 'fore:#00AA00,back:#000000,bold',
52 'bracegood' : 'fore:#00AA00,back:#000000,bold',
48 'bracebad' : 'fore:#FF0000,back:#000000,bold',
53 'bracebad' : 'fore:#FF0000,back:#000000,bold',
49
54
55 # Edge column: a number of None
56 'edge_column' : -1,
57
50 # properties for the various Python lexer styles
58 # properties for the various Python lexer styles
51 'comment' : 'fore:#007F00',
59 'comment' : 'fore:#007F00',
52 'number' : 'fore:#007F7F',
60 'number' : 'fore:#007F7F',
53 'string' : 'fore:#7F007F,italic',
61 'string' : 'fore:#7F007F,italic',
54 'char' : 'fore:#7F007F,italic',
62 'char' : 'fore:#7F007F,italic',
55 'keyword' : 'fore:#00007F,bold',
63 'keyword' : 'fore:#00007F,bold',
56 'triple' : 'fore:#7F0000',
64 'triple' : 'fore:#7F0000',
57 'tripledouble' : 'fore:#7F0000',
65 'tripledouble' : 'fore:#7F0000',
58 'class' : 'fore:#0000FF,bold,underline',
66 'class' : 'fore:#0000FF,bold,underline',
59 'def' : 'fore:#007F7F,bold',
67 'def' : 'fore:#007F7F,bold',
60 'operator' : 'bold'
68 'operator' : 'bold',
69
70 # Default colors
71 'trace' : '#FAFAF1', # Nice green
72 'stdout' : '#FDFFD3', # Nice yellow
73 'stderr' : '#FFF1F1', # Nice red
74
75 # Default scintilla settings
76 'antialiasing' : True,
77 'carret_color' : 'BLACK',
78 'background_color' :'WHITE',
79
80 #prompt definition
81 'prompt_in1' : \
82 '\n\x01\x1b[0;34m\x02In [\x01\x1b[1;34m\x02$number\x01\x1b[0;34m\x02]: \x01\x1b[0m\x02',
83
84 'prompt_out': \
85 '\x01\x1b[0;31m\x02Out[\x01\x1b[1;31m\x02$number\x01\x1b[0;31m\x02]: \x01\x1b[0m\x02',
61 }
86 }
62
87
63 # new style numbers
88 # new style numbers
64 _STDOUT_STYLE = 15
89 _STDOUT_STYLE = 15
65 _STDERR_STYLE = 16
90 _STDERR_STYLE = 16
66 _TRACE_STYLE = 17
91 _TRACE_STYLE = 17
67
92
68
93
69 # system colors
94 # system colors
70 #SYS_COLOUR_BACKGROUND = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BACKGROUND)
95 #SYS_COLOUR_BACKGROUND = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BACKGROUND)
71
96
97 # Translation table from ANSI escape sequences to color.
98 ANSI_STYLES = {'0;30': [0, 'BLACK'], '0;31': [1, 'RED'],
99 '0;32': [2, 'GREEN'], '0;33': [3, 'BROWN'],
100 '0;34': [4, 'BLUE'], '0;35': [5, 'PURPLE'],
101 '0;36': [6, 'CYAN'], '0;37': [7, 'LIGHT GREY'],
102 '1;30': [8, 'DARK GREY'], '1;31': [9, 'RED'],
103 '1;32': [10, 'SEA GREEN'], '1;33': [11, 'YELLOW'],
104 '1;34': [12, 'LIGHT BLUE'], '1;35':
105 [13, 'MEDIUM VIOLET RED'],
106 '1;36': [14, 'LIGHT STEEL BLUE'], '1;37': [15, 'YELLOW']}
107
108 # XXX: Maybe one day we should factor this code with ColorANSI. Right now
109 # ColorANSI is hard to reuse and makes our code more complex.
110
111 #we define platform specific fonts
112 if wx.Platform == '__WXMSW__':
113 FACES = { 'times': 'Times New Roman',
114 'mono' : 'Courier New',
115 'helv' : 'Arial',
116 'other': 'Comic Sans MS',
117 'size' : 10,
118 'size2': 8,
119 }
120 elif wx.Platform == '__WXMAC__':
121 FACES = { 'times': 'Times New Roman',
122 'mono' : 'Monaco',
123 'helv' : 'Arial',
124 'other': 'Comic Sans MS',
125 'size' : 10,
126 'size2': 8,
127 }
128 else:
129 FACES = { 'times': 'Times',
130 'mono' : 'Courier',
131 'helv' : 'Helvetica',
132 'other': 'new century schoolbook',
133 'size' : 10,
134 'size2': 8,
135 }
136
137
72 #-------------------------------------------------------------------------------
138 #-------------------------------------------------------------------------------
73 # The console widget class
139 # The console widget class
74 #-------------------------------------------------------------------------------
140 #-------------------------------------------------------------------------------
75 class ConsoleWidget(editwindow.EditWindow):
141 class ConsoleWidget(editwindow.EditWindow):
76 """ Specialized styled text control view for console-like workflow.
142 """ Specialized styled text control view for console-like workflow.
77
143
78 This widget is mainly interested in dealing with the prompt and
144 This widget is mainly interested in dealing with the prompt and
79 keeping the cursor inside the editing line.
145 keeping the cursor inside the editing line.
80 """
146 """
81
147
82 # This is where the title captured from the ANSI escape sequences are
148 # This is where the title captured from the ANSI escape sequences are
83 # stored.
149 # stored.
84 title = 'Console'
150 title = 'Console'
85
151
152 # Last prompt printed
153 last_prompt = ''
154
86 # The buffer being edited.
155 # The buffer being edited.
87 def _set_input_buffer(self, string):
156 def _set_input_buffer(self, string):
88 self.SetSelection(self.current_prompt_pos, self.GetLength())
157 self.SetSelection(self.current_prompt_pos, self.GetLength())
89 self.ReplaceSelection(string)
158 self.ReplaceSelection(string)
90 self.GotoPos(self.GetLength())
159 self.GotoPos(self.GetLength())
91
160
92 def _get_input_buffer(self):
161 def _get_input_buffer(self):
93 """ Returns the text in current edit buffer.
162 """ Returns the text in current edit buffer.
94 """
163 """
95 input_buffer = self.GetTextRange(self.current_prompt_pos,
164 input_buffer = self.GetTextRange(self.current_prompt_pos,
96 self.GetLength())
165 self.GetLength())
97 input_buffer = input_buffer.replace(LINESEP, '\n')
166 input_buffer = input_buffer.replace(LINESEP, '\n')
98 return input_buffer
167 return input_buffer
99
168
100 input_buffer = property(_get_input_buffer, _set_input_buffer)
169 input_buffer = property(_get_input_buffer, _set_input_buffer)
101
170
102 style = _DEFAULT_STYLE.copy()
171 style = _DEFAULT_STYLE.copy()
103
172
104 # Translation table from ANSI escape sequences to color. Override
173 # Translation table from ANSI escape sequences to color. Override
105 # this to specify your colors.
174 # this to specify your colors.
106 ANSI_STYLES = {'0;30': [0, 'BLACK'], '0;31': [1, 'RED'],
175 ANSI_STYLES = ANSI_STYLES.copy()
107 '0;32': [2, 'GREEN'], '0;33': [3, 'BROWN'],
108 '0;34': [4, 'BLUE'], '0;35': [5, 'PURPLE'],
109 '0;36': [6, 'CYAN'], '0;37': [7, 'LIGHT GREY'],
110 '1;30': [8, 'DARK GREY'], '1;31': [9, 'RED'],
111 '1;32': [10, 'SEA GREEN'], '1;33': [11, 'YELLOW'],
112 '1;34': [12, 'LIGHT BLUE'], '1;35':
113 [13, 'MEDIUM VIOLET RED'],
114 '1;36': [14, 'LIGHT STEEL BLUE'], '1;37': [15, 'YELLOW']}
115
176
116 # The color of the carret (call _apply_style() after setting)
177 # Font faces
117 carret_color = 'BLACK'
178 faces = FACES.copy()
118
179
119 # Store the last time a refresh was done
180 # Store the last time a refresh was done
120 _last_refresh_time = 0
181 _last_refresh_time = 0
121
182
122 #--------------------------------------------------------------------------
183 #--------------------------------------------------------------------------
123 # Public API
184 # Public API
124 #--------------------------------------------------------------------------
185 #--------------------------------------------------------------------------
125
186
126 def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition,
187 def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition,
127 size=wx.DefaultSize, style=wx.WANTS_CHARS, ):
188 size=wx.DefaultSize, style=wx.WANTS_CHARS, ):
128 editwindow.EditWindow.__init__(self, parent, id, pos, size, style)
189 editwindow.EditWindow.__init__(self, parent, id, pos, size, style)
129 self._configure_scintilla()
190 self.configure_scintilla()
191 # Track if 'enter' key as ever been processed
192 # This variable will only be reallowed until key goes up
193 self.enter_catched = False
194 self.current_prompt_pos = 0
130
195
131 self.Bind(wx.EVT_KEY_DOWN, self._on_key_down)
196 self.Bind(wx.EVT_KEY_DOWN, self._on_key_down)
132 self.Bind(wx.EVT_KEY_UP, self._on_key_up)
197 self.Bind(wx.EVT_KEY_UP, self._on_key_up)
133
198
134
199
135 def write(self, text, refresh=True):
200 def write(self, text, refresh=True):
136 """ Write given text to buffer, while translating the ansi escape
201 """ Write given text to buffer, while translating the ansi escape
137 sequences.
202 sequences.
138 """
203 """
139 # XXX: do not put print statements to sys.stdout/sys.stderr in
204 # XXX: do not put print statements to sys.stdout/sys.stderr in
140 # this method, the print statements will call this method, as
205 # this method, the print statements will call this method, as
141 # you will end up with an infinit loop
206 # you will end up with an infinit loop
142 title = self.title_pat.split(text)
207 title = self.title_pat.split(text)
143 if len(title)>1:
208 if len(title)>1:
144 self.title = title[-2]
209 self.title = title[-2]
145
210
146 text = self.title_pat.sub('', text)
211 text = self.title_pat.sub('', text)
147 segments = self.color_pat.split(text)
212 segments = self.color_pat.split(text)
148 segment = segments.pop(0)
213 segment = segments.pop(0)
149 self.GotoPos(self.GetLength())
214 self.GotoPos(self.GetLength())
150 self.StartStyling(self.GetLength(), 0xFF)
215 self.StartStyling(self.GetLength(), 0xFF)
151 try:
216 try:
152 self.AppendText(segment)
217 self.AppendText(segment)
153 except UnicodeDecodeError:
218 except UnicodeDecodeError:
154 # XXX: Do I really want to skip the exception?
219 # XXX: Do I really want to skip the exception?
155 pass
220 pass
156
221
157 if segments:
222 if segments:
158 for ansi_tag, text in zip(segments[::2], segments[1::2]):
223 for ansi_tag, text in zip(segments[::2], segments[1::2]):
159 self.StartStyling(self.GetLength(), 0xFF)
224 self.StartStyling(self.GetLength(), 0xFF)
160 try:
225 try:
161 self.AppendText(text)
226 self.AppendText(text)
162 except UnicodeDecodeError:
227 except UnicodeDecodeError:
163 # XXX: Do I really want to skip the exception?
228 # XXX: Do I really want to skip the exception?
164 pass
229 pass
165
230
166 if ansi_tag not in self.ANSI_STYLES:
231 if ansi_tag not in self.ANSI_STYLES:
167 style = 0
232 style = 0
168 else:
233 else:
169 style = self.ANSI_STYLES[ansi_tag][0]
234 style = self.ANSI_STYLES[ansi_tag][0]
170
235
171 self.SetStyling(len(text), style)
236 self.SetStyling(len(text), style)
172
237
173 self.GotoPos(self.GetLength())
238 self.GotoPos(self.GetLength())
174 if refresh:
239 if refresh:
175 current_time = time.time()
240 current_time = time.time()
176 if current_time - self._last_refresh_time > 0.03:
241 if current_time - self._last_refresh_time > 0.03:
177 if sys.platform == 'win32':
242 if sys.platform == 'win32':
178 wx.SafeYield()
243 wx.SafeYield()
179 else:
244 else:
180 wx.Yield()
245 wx.Yield()
181 # self.ProcessEvent(wx.PaintEvent())
246 # self.ProcessEvent(wx.PaintEvent())
182 self._last_refresh_time = current_time
247 self._last_refresh_time = current_time
183
248
184
249
185 def new_prompt(self, prompt):
250 def new_prompt(self, prompt):
186 """ Prints a prompt at start of line, and move the start of the
251 """ Prints a prompt at start of line, and move the start of the
187 current block there.
252 current block there.
188
253
189 The prompt can be given with ascii escape sequences.
254 The prompt can be given with ascii escape sequences.
190 """
255 """
191 self.write(prompt, refresh=False)
256 self.write(prompt, refresh=False)
192 # now we update our cursor giving end of prompt
257 # now we update our cursor giving end of prompt
193 self.current_prompt_pos = self.GetLength()
258 self.current_prompt_pos = self.GetLength()
194 self.current_prompt_line = self.GetCurrentLine()
259 self.current_prompt_line = self.GetCurrentLine()
195 self.EnsureCaretVisible()
260 self.EnsureCaretVisible()
261 self.last_prompt = prompt
262
263
264 def continuation_prompt(self):
265 """ Returns the current continuation prompt.
266 We need to implement this method here to deal with the
267 ascii escape sequences cleaning up.
268 """
269 # ASCII-less prompt
270 ascii_less = ''.join(self.color_pat.split(self.last_prompt)[2::2])
271 return "."*(len(ascii_less)-2) + ': '
196
272
197
273
198 def scroll_to_bottom(self):
274 def scroll_to_bottom(self):
199 maxrange = self.GetScrollRange(wx.VERTICAL)
275 maxrange = self.GetScrollRange(wx.VERTICAL)
200 self.ScrollLines(maxrange)
276 self.ScrollLines(maxrange)
201
277
202
278
203 def pop_completion(self, possibilities, offset=0):
279 def pop_completion(self, possibilities, offset=0):
204 """ Pops up an autocompletion menu. Offset is the offset
280 """ Pops up an autocompletion menu. Offset is the offset
205 in characters of the position at which the menu should
281 in characters of the position at which the menu should
206 appear, relativ to the cursor.
282 appear, relativ to the cursor.
207 """
283 """
208 self.AutoCompSetIgnoreCase(False)
284 self.AutoCompSetIgnoreCase(False)
209 self.AutoCompSetAutoHide(False)
285 self.AutoCompSetAutoHide(False)
210 self.AutoCompSetMaxHeight(len(possibilities))
286 self.AutoCompSetMaxHeight(len(possibilities))
211 self.AutoCompShow(offset, " ".join(possibilities))
287 self.AutoCompShow(offset, " ".join(possibilities))
212
288
213
289
214 def get_line_width(self):
290 def get_line_width(self):
215 """ Return the width of the line in characters.
291 """ Return the width of the line in characters.
216 """
292 """
217 return self.GetSize()[0]/self.GetCharWidth()
293 return self.GetSize()[0]/self.GetCharWidth()
218
294
219 #--------------------------------------------------------------------------
220 # EditWindow API
221 #--------------------------------------------------------------------------
222
223 def OnUpdateUI(self, event):
224 """ Override the OnUpdateUI of the EditWindow class, to prevent
225 syntax highlighting both for faster redraw, and for more
226 consistent look and feel.
227 """
228
229 #--------------------------------------------------------------------------
230 # Private API
231 #--------------------------------------------------------------------------
232
295
233 def _apply_style(self):
296 def configure_scintilla(self):
234 """ Applies the colors for the different text elements and the
297 """ Set up all the styling option of the embedded scintilla
235 carret.
298 widget.
236 """
299 """
237 self.SetCaretForeground(self.carret_color)
300 p = self.style.copy()
238
301
239 #self.StyleClearAll()
302 # Marker for complete buffer.
240 self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT,
303 self.MarkerDefine(_COMPLETE_BUFFER_MARKER, stc.STC_MARK_BACKGROUND,
241 "fore:#FF0000,back:#0000FF,bold")
304 background=p['trace'])
242 self.StyleSetSpec(stc.STC_STYLE_BRACEBAD,
243 "fore:#000000,back:#FF0000,bold")
244
305
245 for style in self.ANSI_STYLES.values():
306 # Marker for current input buffer.
246 self.StyleSetSpec(style[0], "bold,fore:%s" % style[1])
307 self.MarkerDefine(_INPUT_MARKER, stc.STC_MARK_BACKGROUND,
308 background=p['stdout'])
309 # Marker for tracebacks.
310 self.MarkerDefine(_ERROR_MARKER, stc.STC_MARK_BACKGROUND,
311 background=p['stderr'])
247
312
248
249 def _configure_scintilla(self):
250 self.SetEOLMode(stc.STC_EOL_LF)
313 self.SetEOLMode(stc.STC_EOL_LF)
251
314
252 # Ctrl"+" or Ctrl "-" can be used to zoomin/zoomout the text inside
315 # Ctrl"+" or Ctrl "-" can be used to zoomin/zoomout the text inside
253 # the widget
316 # the widget
254 self.CmdKeyAssign(ord('+'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMIN)
317 self.CmdKeyAssign(ord('+'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMIN)
255 self.CmdKeyAssign(ord('-'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMOUT)
318 self.CmdKeyAssign(ord('-'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMOUT)
256 # Also allow Ctrl Shift "=" for poor non US keyboard users.
319 # Also allow Ctrl Shift "=" for poor non US keyboard users.
257 self.CmdKeyAssign(ord('='), stc.STC_SCMOD_CTRL|stc.STC_SCMOD_SHIFT,
320 self.CmdKeyAssign(ord('='), stc.STC_SCMOD_CTRL|stc.STC_SCMOD_SHIFT,
258 stc.STC_CMD_ZOOMIN)
321 stc.STC_CMD_ZOOMIN)
259
322
260 # Keys: we need to clear some of the keys the that don't play
323 # Keys: we need to clear some of the keys the that don't play
261 # well with a console.
324 # well with a console.
262 self.CmdKeyClear(ord('D'), stc.STC_SCMOD_CTRL)
325 self.CmdKeyClear(ord('D'), stc.STC_SCMOD_CTRL)
263 self.CmdKeyClear(ord('L'), stc.STC_SCMOD_CTRL)
326 self.CmdKeyClear(ord('L'), stc.STC_SCMOD_CTRL)
264 self.CmdKeyClear(ord('T'), stc.STC_SCMOD_CTRL)
327 self.CmdKeyClear(ord('T'), stc.STC_SCMOD_CTRL)
265 self.CmdKeyClear(ord('A'), stc.STC_SCMOD_CTRL)
328 self.CmdKeyClear(ord('A'), stc.STC_SCMOD_CTRL)
266
329
267 self.SetEOLMode(stc.STC_EOL_CRLF)
330 self.SetEOLMode(stc.STC_EOL_CRLF)
268 self.SetWrapMode(stc.STC_WRAP_CHAR)
331 self.SetWrapMode(stc.STC_WRAP_CHAR)
269 self.SetWrapMode(stc.STC_WRAP_WORD)
332 self.SetWrapMode(stc.STC_WRAP_WORD)
270 self.SetBufferedDraw(True)
333 self.SetBufferedDraw(True)
271 self.SetUseAntiAliasing(True)
334
335 self.SetUseAntiAliasing(p['antialiasing'])
336
272 self.SetLayoutCache(stc.STC_CACHE_PAGE)
337 self.SetLayoutCache(stc.STC_CACHE_PAGE)
273 self.SetUndoCollection(False)
338 self.SetUndoCollection(False)
274 self.SetUseTabs(True)
339 self.SetUseTabs(True)
275 self.SetIndent(4)
340 self.SetIndent(4)
276 self.SetTabWidth(4)
341 self.SetTabWidth(4)
277
342
278 # we don't want scintilla's autocompletion to choose
343 # we don't want scintilla's autocompletion to choose
279 # automaticaly out of a single choice list, as we pop it up
344 # automaticaly out of a single choice list, as we pop it up
280 # automaticaly
345 # automaticaly
281 self.AutoCompSetChooseSingle(False)
346 self.AutoCompSetChooseSingle(False)
282 self.AutoCompSetMaxHeight(10)
347 self.AutoCompSetMaxHeight(10)
283 # XXX: this doesn't seem to have an effect.
348 # XXX: this doesn't seem to have an effect.
284 self.AutoCompSetFillUps('\n')
349 self.AutoCompSetFillUps('\n')
285
350
286 self.SetMargins(3, 3) #text is moved away from border with 3px
351 self.SetMargins(3, 3) #text is moved away from border with 3px
287 # Suppressing Scintilla margins
352 # Suppressing Scintilla margins
288 self.SetMarginWidth(0, 0)
353 self.SetMarginWidth(0, 0)
289 self.SetMarginWidth(1, 0)
354 self.SetMarginWidth(1, 0)
290 self.SetMarginWidth(2, 0)
355 self.SetMarginWidth(2, 0)
291
356
292 self._apply_style()
293
294 # Xterm escape sequences
357 # Xterm escape sequences
295 self.color_pat = re.compile('\x01?\x1b\[(.*?)m\x02?')
358 self.color_pat = re.compile('\x01?\x1b\[(.*?)m\x02?')
296 self.title_pat = re.compile('\x1b]0;(.*?)\x07')
359 self.title_pat = re.compile('\x1b]0;(.*?)\x07')
297
360
298 #self.SetEdgeMode(stc.STC_EDGE_LINE)
299 #self.SetEdgeColumn(80)
300
301 # styles
361 # styles
302 p = self.style
362
363 self.SetCaretForeground(p['carret_color'])
364
365 background_color = p['background_color']
366
367 if 'default' in p:
368 if 'back' not in p['default']:
369 p['default'] += ',back:%s' % background_color
370 if 'size' not in p['default']:
371 p['default'] += ',size:%s' % self.faces['size']
372 if 'face' not in p['default']:
373 p['default'] += ',face:%s' % self.faces['mono']
374
303 self.StyleSetSpec(stc.STC_STYLE_DEFAULT, p['default'])
375 self.StyleSetSpec(stc.STC_STYLE_DEFAULT, p['default'])
376 else:
377 self.StyleSetSpec(stc.STC_STYLE_DEFAULT,
378 "fore:%s,back:%s,size:%d,face:%s"
379 % (self.ANSI_STYLES['0;30'][1],
380 background_color,
381 self.faces['size'], self.faces['mono']))
382
304 self.StyleClearAll()
383 self.StyleClearAll()
384
385 # XXX: two lines below are usefull if not using the lexer
386 #for style in self.ANSI_STYLES.values():
387 # self.StyleSetSpec(style[0], "bold,fore:%s" % style[1])
388
389 # prompt definition
390 self.prompt_in1 = p['prompt_in1']
391 self.prompt_out = p['prompt_out']
392
393 self.output_prompt_template = string.Template(self.prompt_out)
394 self.input_prompt_template = string.Template(self.prompt_in1)
395
305 self.StyleSetSpec(_STDOUT_STYLE, p['stdout'])
396 self.StyleSetSpec(_STDOUT_STYLE, p['stdout'])
306 self.StyleSetSpec(_STDERR_STYLE, p['stderr'])
397 self.StyleSetSpec(_STDERR_STYLE, p['stderr'])
307 self.StyleSetSpec(_TRACE_STYLE, p['trace'])
398 self.StyleSetSpec(_TRACE_STYLE, p['trace'])
308
309 self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT, p['bracegood'])
399 self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT, p['bracegood'])
310 self.StyleSetSpec(stc.STC_STYLE_BRACEBAD, p['bracebad'])
400 self.StyleSetSpec(stc.STC_STYLE_BRACEBAD, p['bracebad'])
311 self.StyleSetSpec(stc.STC_P_COMMENTLINE, p['comment'])
401 self.StyleSetSpec(stc.STC_P_COMMENTLINE, p['comment'])
312 self.StyleSetSpec(stc.STC_P_NUMBER, p['number'])
402 self.StyleSetSpec(stc.STC_P_NUMBER, p['number'])
313 self.StyleSetSpec(stc.STC_P_STRING, p['string'])
403 self.StyleSetSpec(stc.STC_P_STRING, p['string'])
314 self.StyleSetSpec(stc.STC_P_CHARACTER, p['char'])
404 self.StyleSetSpec(stc.STC_P_CHARACTER, p['char'])
315 self.StyleSetSpec(stc.STC_P_WORD, p['keyword'])
405 self.StyleSetSpec(stc.STC_P_WORD, p['keyword'])
316 self.StyleSetSpec(stc.STC_P_WORD2, p['keyword'])
406 self.StyleSetSpec(stc.STC_P_WORD2, p['keyword'])
317 self.StyleSetSpec(stc.STC_P_TRIPLE, p['triple'])
407 self.StyleSetSpec(stc.STC_P_TRIPLE, p['triple'])
318 self.StyleSetSpec(stc.STC_P_TRIPLEDOUBLE, p['tripledouble'])
408 self.StyleSetSpec(stc.STC_P_TRIPLEDOUBLE, p['tripledouble'])
319 self.StyleSetSpec(stc.STC_P_CLASSNAME, p['class'])
409 self.StyleSetSpec(stc.STC_P_CLASSNAME, p['class'])
320 self.StyleSetSpec(stc.STC_P_DEFNAME, p['def'])
410 self.StyleSetSpec(stc.STC_P_DEFNAME, p['def'])
321 self.StyleSetSpec(stc.STC_P_OPERATOR, p['operator'])
411 self.StyleSetSpec(stc.STC_P_OPERATOR, p['operator'])
322 self.StyleSetSpec(stc.STC_P_COMMENTBLOCK, p['comment'])
412 self.StyleSetSpec(stc.STC_P_COMMENTBLOCK, p['comment'])
323
413
414 edge_column = p['edge_column']
415 if edge_column is not None and edge_column > 0:
416 #we add a vertical line to console widget
417 self.SetEdgeMode(stc.STC_EDGE_LINE)
418 self.SetEdgeColumn(edge_column)
419
420
421 #--------------------------------------------------------------------------
422 # EditWindow API
423 #--------------------------------------------------------------------------
424
425 def OnUpdateUI(self, event):
426 """ Override the OnUpdateUI of the EditWindow class, to prevent
427 syntax highlighting both for faster redraw, and for more
428 consistent look and feel.
429 """
430
431
432 #--------------------------------------------------------------------------
433 # Private API
434 #--------------------------------------------------------------------------
435
324 def _on_key_down(self, event, skip=True):
436 def _on_key_down(self, event, skip=True):
325 """ Key press callback used for correcting behavior for
437 """ Key press callback used for correcting behavior for
326 console-like interfaces: the cursor is constraint to be after
438 console-like interfaces: the cursor is constraint to be after
327 the last prompt.
439 the last prompt.
328
440
329 Return True if event as been catched.
441 Return True if event as been catched.
330 """
442 """
331 catched = True
443 catched = True
444 # XXX: Would the right way to do this be to have a
445 # dictionary at the instance level associating keys with
446 # callbacks? How would we deal with inheritance? And Do the
447 # different callbacks share local variables?
448
332 # Intercept some specific keys.
449 # Intercept some specific keys.
333 if event.KeyCode == ord('L') and event.ControlDown() :
450 if event.KeyCode == ord('L') and event.ControlDown() :
334 self.scroll_to_bottom()
451 self.scroll_to_bottom()
335 elif event.KeyCode == ord('K') and event.ControlDown() :
452 elif event.KeyCode == ord('K') and event.ControlDown() :
336 self.input_buffer = ''
453 self.input_buffer = ''
337 elif event.KeyCode == ord('A') and event.ControlDown() :
454 elif event.KeyCode == ord('A') and event.ControlDown() :
338 self.GotoPos(self.GetLength())
455 self.GotoPos(self.GetLength())
339 self.SetSelectionStart(self.current_prompt_pos)
456 self.SetSelectionStart(self.current_prompt_pos)
340 self.SetSelectionEnd(self.GetCurrentPos())
457 self.SetSelectionEnd(self.GetCurrentPos())
341 catched = True
458 catched = True
342 elif event.KeyCode == ord('E') and event.ControlDown() :
459 elif event.KeyCode == ord('E') and event.ControlDown() :
343 self.GotoPos(self.GetLength())
460 self.GotoPos(self.GetLength())
344 catched = True
461 catched = True
345 elif event.KeyCode == wx.WXK_PAGEUP:
462 elif event.KeyCode == wx.WXK_PAGEUP:
346 self.ScrollPages(-1)
463 self.ScrollPages(-1)
347 elif event.KeyCode == wx.WXK_PAGEDOWN:
464 elif event.KeyCode == wx.WXK_PAGEDOWN:
348 self.ScrollPages(1)
465 self.ScrollPages(1)
466 elif event.KeyCode == wx.WXK_HOME:
467 self.GotoPos(self.GetLength())
468 elif event.KeyCode == wx.WXK_END:
469 self.GotoPos(self.GetLength())
349 elif event.KeyCode == wx.WXK_UP and event.ShiftDown():
470 elif event.KeyCode == wx.WXK_UP and event.ShiftDown():
350 self.ScrollLines(-1)
471 self.ScrollLines(-1)
351 elif event.KeyCode == wx.WXK_DOWN and event.ShiftDown():
472 elif event.KeyCode == wx.WXK_DOWN and event.ShiftDown():
352 self.ScrollLines(1)
473 self.ScrollLines(1)
353 else:
474 else:
354 catched = False
475 catched = False
355
476
356 if self.AutoCompActive():
477 if self.AutoCompActive():
357 event.Skip()
478 event.Skip()
358 else:
479 else:
359 if event.KeyCode in (13, wx.WXK_NUMPAD_ENTER) and \
480 if event.KeyCode in (13, wx.WXK_NUMPAD_ENTER) and \
360 event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN):
481 event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN,
482 wx.MOD_SHIFT):
361 catched = True
483 catched = True
484 if not self.enter_catched:
362 self.CallTipCancel()
485 self.CallTipCancel()
363 self.write('\n', refresh=False)
486 if event.Modifiers == wx.MOD_SHIFT:
364 # Under windows scintilla seems to be doing funny stuff to the
487 # Try to force execution
365 # line returns here, but the getter for input_buffer filters
488 self.GotoPos(self.GetLength())
366 # this out.
489 self.write('\n' + self.continuation_prompt(),
367 if sys.platform == 'win32':
490 refresh=False)
368 self.input_buffer = self.input_buffer
491 self._on_enter()
492 else:
369 self._on_enter()
493 self._on_enter()
494 self.enter_catched = True
370
495
371 elif event.KeyCode == wx.WXK_HOME:
496 elif event.KeyCode == wx.WXK_HOME:
372 if event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN):
497 if event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN):
373 self.GotoPos(self.current_prompt_pos)
498 self.GotoPos(self.current_prompt_pos)
374 catched = True
499 catched = True
375
500
376 elif event.Modifiers == wx.MOD_SHIFT:
501 elif event.Modifiers == wx.MOD_SHIFT:
377 # FIXME: This behavior is not ideal: if the selection
502 # FIXME: This behavior is not ideal: if the selection
378 # is already started, it will jump.
503 # is already started, it will jump.
379 self.SetSelectionStart(self.current_prompt_pos)
504 self.SetSelectionStart(self.current_prompt_pos)
380 self.SetSelectionEnd(self.GetCurrentPos())
505 self.SetSelectionEnd(self.GetCurrentPos())
381 catched = True
506 catched = True
382
507
383 elif event.KeyCode == wx.WXK_UP:
508 elif event.KeyCode == wx.WXK_UP:
384 if self.GetCurrentLine() > self.current_prompt_line:
509 if self.GetCurrentLine() > self.current_prompt_line:
385 if self.GetCurrentLine() == self.current_prompt_line + 1 \
510 if self.GetCurrentLine() == self.current_prompt_line + 1 \
386 and self.GetColumn(self.GetCurrentPos()) < \
511 and self.GetColumn(self.GetCurrentPos()) < \
387 self.GetColumn(self.current_prompt_pos):
512 self.GetColumn(self.current_prompt_pos):
388 self.GotoPos(self.current_prompt_pos)
513 self.GotoPos(self.current_prompt_pos)
389 else:
514 else:
390 event.Skip()
515 event.Skip()
391 catched = True
516 catched = True
392
517
393 elif event.KeyCode in (wx.WXK_LEFT, wx.WXK_BACK):
518 elif event.KeyCode in (wx.WXK_LEFT, wx.WXK_BACK):
394 if self.GetCurrentPos() > self.current_prompt_pos:
519 if not self._keep_cursor_in_buffer(self.GetCurrentPos() - 1):
520 event.Skip()
521 catched = True
522
523 elif event.KeyCode == wx.WXK_RIGHT:
524 if not self._keep_cursor_in_buffer(self.GetCurrentPos() + 1):
525 event.Skip()
526 catched = True
527
528
529 elif event.KeyCode == wx.WXK_DELETE:
530 if not self._keep_cursor_in_buffer(self.GetCurrentPos() - 1):
395 event.Skip()
531 event.Skip()
396 catched = True
532 catched = True
397
533
398 if skip and not catched:
534 if skip and not catched:
399 # Put the cursor back in the edit region
535 # Put the cursor back in the edit region
400 if self.GetCurrentPos() < self.current_prompt_pos:
536 if not self._keep_cursor_in_buffer():
401 self.GotoPos(self.current_prompt_pos)
537 if not (self.GetCurrentPos() == self.GetLength()
402 else:
538 and event.KeyCode == wx.WXK_DELETE):
403 event.Skip()
539 event.Skip()
540 catched = True
404
541
405 return catched
542 return catched
406
543
407
544
408 def _on_key_up(self, event, skip=True):
545 def _on_key_up(self, event, skip=True):
409 """ If cursor is outside the editing region, put it back.
546 """ If cursor is outside the editing region, put it back.
410 """
547 """
548 if skip:
411 event.Skip()
549 event.Skip()
412 if self.GetCurrentPos() < self.current_prompt_pos:
550 self._keep_cursor_in_buffer()
413 self.GotoPos(self.current_prompt_pos)
551
552
553 # XXX: I need to avoid the problem of having an empty glass;
554 def _keep_cursor_in_buffer(self, pos=None):
555 """ Checks if the cursor is where it is allowed to be. If not,
556 put it back.
414
557
558 Returns
559 -------
560 cursor_moved: Boolean
561 whether or not the cursor was moved by this routine.
562
563 Notes
564 ------
565 WARNING: This does proper checks only for horizontal
566 movements.
567 """
568 if pos is None:
569 current_pos = self.GetCurrentPos()
570 else:
571 current_pos = pos
572 if current_pos < self.current_prompt_pos:
573 self.GotoPos(self.current_prompt_pos)
574 return True
575 line_num = self.LineFromPosition(current_pos)
576 if not current_pos > self.GetLength():
577 line_pos = self.GetColumn(current_pos)
578 else:
579 line_pos = self.GetColumn(self.GetLength())
580 line = self.GetLine(line_num)
581 # Jump the continuation prompt
582 continuation_prompt = self.continuation_prompt()
583 if ( line.startswith(continuation_prompt)
584 and line_pos < len(continuation_prompt)):
585 if line_pos < 2:
586 # We are at the beginning of the line, trying to move
587 # forward: jump forward.
588 self.GotoPos(current_pos + 1 +
589 len(continuation_prompt) - line_pos)
590 else:
591 # Jump back up
592 self.GotoPos(self.GetLineEndPosition(line_num-1))
593 return True
594 elif ( current_pos > self.GetLineEndPosition(line_num)
595 and not current_pos == self.GetLength()):
596 # Jump to next line
597 self.GotoPos(current_pos + 1 +
598 len(continuation_prompt))
599 return True
600
601 # We re-allow enter event processing
602 self.enter_catched = False
603 return False
415
604
416
605
417 if __name__ == '__main__':
606 if __name__ == '__main__':
418 # Some simple code to test the console widget.
607 # Some simple code to test the console widget.
419 class MainWindow(wx.Frame):
608 class MainWindow(wx.Frame):
420 def __init__(self, parent, id, title):
609 def __init__(self, parent, id, title):
421 wx.Frame.__init__(self, parent, id, title, size=(300,250))
610 wx.Frame.__init__(self, parent, id, title, size=(300, 250))
422 self._sizer = wx.BoxSizer(wx.VERTICAL)
611 self._sizer = wx.BoxSizer(wx.VERTICAL)
423 self.console_widget = ConsoleWidget(self)
612 self.console_widget = ConsoleWidget(self)
424 self._sizer.Add(self.console_widget, 1, wx.EXPAND)
613 self._sizer.Add(self.console_widget, 1, wx.EXPAND)
425 self.SetSizer(self._sizer)
614 self.SetSizer(self._sizer)
426 self.SetAutoLayout(1)
615 self.SetAutoLayout(1)
427 self.Show(True)
616 self.Show(True)
428
617
429 app = wx.PySimpleApp()
618 app = wx.PySimpleApp()
430 w = MainWindow(None, wx.ID_ANY, 'ConsoleWidget')
619 w = MainWindow(None, wx.ID_ANY, 'ConsoleWidget')
431 w.SetSize((780, 460))
620 w.SetSize((780, 460))
432 w.Show()
621 w.Show()
433
622
434 app.MainLoop()
623 app.MainLoop()
435
624
436
625
@@ -1,110 +1,119 b''
1 """
1 """
2 Entry point for a simple application giving a graphical frontend to
2 Entry point for a simple application giving a graphical frontend to
3 ipython.
3 ipython.
4 """
4 """
5
5
6 try:
6 try:
7 import wx
7 import wx
8 except ImportError, e:
8 except ImportError, e:
9 e.message = """%s
9 e.message = """%s
10 ________________________________________________________________________________
10 ________________________________________________________________________________
11 You need wxPython to run this application.
11 You need wxPython to run this application.
12 """ % e.message
12 """ % e.message
13 e.args = (e.message, ) + e.args[1:]
13 e.args = (e.message, ) + e.args[1:]
14 raise e
14 raise e
15
15
16 from wx_frontend import WxController
16 from wx_frontend import WxController
17 import __builtin__
17 import __builtin__
18
18
19
19
20 class IPythonXController(WxController):
20 class IPythonXController(WxController):
21 """ Sub class of WxController that adds some application-specific
21 """ Sub class of WxController that adds some application-specific
22 bindings.
22 bindings.
23 """
23 """
24
24
25 debug = False
25 debug = False
26
26
27 def __init__(self, *args, **kwargs):
27 def __init__(self, *args, **kwargs):
28 WxController.__init__(self, *args, **kwargs)
28 WxController.__init__(self, *args, **kwargs)
29 self.ipython0.ask_exit = self.do_exit
29 self.ipython0.ask_exit = self.do_exit
30 # Scroll to top
30 # Scroll to top
31 maxrange = self.GetScrollRange(wx.VERTICAL)
31 maxrange = self.GetScrollRange(wx.VERTICAL)
32 self.ScrollLines(-maxrange)
32 self.ScrollLines(-maxrange)
33
33
34
34
35 def _on_key_down(self, event, skip=True):
35 def _on_key_down(self, event, skip=True):
36 # Intercept Ctrl-D to quit
36 # Intercept Ctrl-D to quit
37 if event.KeyCode == ord('D') and event.ControlDown() and \
37 if event.KeyCode == ord('D') and event.ControlDown() and \
38 self.input_buffer == '' and \
38 self.input_buffer == '' and \
39 self._input_state == 'readline':
39 self._input_state == 'readline':
40 wx.CallAfter(self.ask_exit)
40 wx.CallAfter(self.ask_exit)
41 else:
41 else:
42 WxController._on_key_down(self, event, skip=skip)
42 WxController._on_key_down(self, event, skip=skip)
43
43
44
44
45 def ask_exit(self):
45 def ask_exit(self):
46 """ Ask the user whether to exit.
46 """ Ask the user whether to exit.
47 """
47 """
48 self._input_state = 'subprocess'
48 self._input_state = 'subprocess'
49 self.write('\n', refresh=False)
49 self.write('\n', refresh=False)
50 self.capture_output()
50 self.capture_output()
51 self.ipython0.shell.exit()
51 self.ipython0.shell.exit()
52 self.release_output()
52 self.release_output()
53 if not self.ipython0.exit_now:
53 if not self.ipython0.exit_now:
54 wx.CallAfter(self.new_prompt,
54 wx.CallAfter(self.new_prompt,
55 self.input_prompt_template.substitute(
55 self.input_prompt_template.substitute(
56 number=self.last_result['number'] + 1))
56 number=self.last_result['number'] + 1))
57 else:
57 else:
58 wx.CallAfter(wx.GetApp().Exit)
58 wx.CallAfter(wx.GetApp().Exit)
59 self.write('Exiting ...', refresh=False)
59 self.write('Exiting ...', refresh=False)
60
60
61
61
62 def do_exit(self):
62 def do_exit(self):
63 """ Exits the interpreter, kills the windows.
63 """ Exits the interpreter, kills the windows.
64 """
64 """
65 WxController.do_exit(self)
65 WxController.do_exit(self)
66 self.release_output()
66 self.release_output()
67 wx.CallAfter(wx.Exit)
67 wx.CallAfter(wx.Exit)
68
68
69
69
70
70
71 class IPythonX(wx.Frame):
71 class IPythonX(wx.Frame):
72 """ Main frame of the IPythonX app.
72 """ Main frame of the IPythonX app.
73 """
73 """
74
74
75 def __init__(self, parent, id, title, debug=False):
75 def __init__(self, parent, id, title, debug=False):
76 wx.Frame.__init__(self, parent, id, title, size=(300,250))
76 wx.Frame.__init__(self, parent, id, title, size=(300,250))
77 self._sizer = wx.BoxSizer(wx.VERTICAL)
77 self._sizer = wx.BoxSizer(wx.VERTICAL)
78 self.shell = IPythonXController(self, debug=debug)
78 self.shell = IPythonXController(self, debug=debug)
79 self._sizer.Add(self.shell, 1, wx.EXPAND)
79 self._sizer.Add(self.shell, 1, wx.EXPAND)
80 self.SetSizer(self._sizer)
80 self.SetSizer(self._sizer)
81 self.SetAutoLayout(1)
81 self.SetAutoLayout(1)
82 self.Show(True)
82 self.Show(True)
83 wx.EVT_CLOSE(self, self.on_close)
84
85
86 def on_close(self, event):
87 """ Called on closing the windows.
88
89 Stops the event loop, to close all the child windows.
90 """
91 wx.CallAfter(wx.Exit)
83
92
84
93
85 def main():
94 def main():
86 from optparse import OptionParser
95 from optparse import OptionParser
87 usage = """usage: %prog [options]
96 usage = """usage: %prog [options]
88
97
89 Simple graphical frontend to IPython, using WxWidgets."""
98 Simple graphical frontend to IPython, using WxWidgets."""
90 parser = OptionParser(usage=usage)
99 parser = OptionParser(usage=usage)
91 parser.add_option("-d", "--debug",
100 parser.add_option("-d", "--debug",
92 action="store_true", dest="debug", default=False,
101 action="store_true", dest="debug", default=False,
93 help="Enable debug message for the wx frontend.")
102 help="Enable debug message for the wx frontend.")
94
103
95 options, args = parser.parse_args()
104 options, args = parser.parse_args()
96
105
97 # Clear the options, to avoid having the ipython0 instance complain
106 # Clear the options, to avoid having the ipython0 instance complain
98 import sys
107 import sys
99 sys.argv = sys.argv[:1]
108 sys.argv = sys.argv[:1]
100
109
101 app = wx.PySimpleApp()
110 app = wx.PySimpleApp()
102 frame = IPythonX(None, wx.ID_ANY, 'IPythonX', debug=options.debug)
111 frame = IPythonX(None, wx.ID_ANY, 'IPythonX', debug=options.debug)
103 frame.shell.SetFocus()
112 frame.shell.SetFocus()
104 frame.shell.app = app
113 frame.shell.app = app
105 frame.SetSize((680, 460))
114 frame.SetSize((680, 460))
106
115
107 app.MainLoop()
116 app.MainLoop()
108
117
109 if __name__ == '__main__':
118 if __name__ == '__main__':
110 main()
119 main()
@@ -1,526 +1,601 b''
1 # encoding: utf-8 -*- test-case-name:
1 # encoding: utf-8 -*- test-case-name:
2 # FIXME: Need to add tests.
2 # FIXME: Need to add tests.
3 # ipython1.frontend.wx.tests.test_wx_frontend -*-
3 # ipython1.frontend.wx.tests.test_wx_frontend -*-
4
4
5 """Classes to provide a Wx frontend to the
5 """Classes to provide a Wx frontend to the
6 IPython.kernel.core.interpreter.
6 IPython.kernel.core.interpreter.
7
7
8 This class inherits from ConsoleWidget, that provides a console-like
8 This class inherits from ConsoleWidget, that provides a console-like
9 widget to provide a text-rendering widget suitable for a terminal.
9 widget to provide a text-rendering widget suitable for a terminal.
10 """
10 """
11
11
12 __docformat__ = "restructuredtext en"
12 __docformat__ = "restructuredtext en"
13
13
14 #-------------------------------------------------------------------------------
14 #-------------------------------------------------------------------------------
15 # Copyright (C) 2008 The IPython Development Team
15 # Copyright (C) 2008 The IPython Development Team
16 #
16 #
17 # Distributed under the terms of the BSD License. The full license is in
17 # Distributed under the terms of the BSD License. The full license is in
18 # the file COPYING, distributed as part of this software.
18 # the file COPYING, distributed as part of this software.
19 #-------------------------------------------------------------------------------
19 #-------------------------------------------------------------------------------
20
20
21 #-------------------------------------------------------------------------------
21 #-------------------------------------------------------------------------------
22 # Imports
22 # Imports
23 #-------------------------------------------------------------------------------
23 #-------------------------------------------------------------------------------
24
24
25 # Major library imports
25 # Major library imports
26 import re
26 import re
27 import __builtin__
27 import __builtin__
28 from time import sleep
29 import sys
28 import sys
30 from threading import Lock
29 from threading import Lock
31 import string
32
30
33 import wx
31 import wx
34 from wx import stc
32 from wx import stc
35
33
36 # Ipython-specific imports.
34 # Ipython-specific imports.
37 from IPython.frontend._process import PipedProcess
35 from IPython.frontend.process import PipedProcess
38 from console_widget import ConsoleWidget
36 from console_widget import ConsoleWidget, _COMPLETE_BUFFER_MARKER, \
37 _ERROR_MARKER, _INPUT_MARKER
39 from IPython.frontend.prefilterfrontend import PrefilterFrontEnd
38 from IPython.frontend.prefilterfrontend import PrefilterFrontEnd
40
39
41 #-------------------------------------------------------------------------------
40 #-------------------------------------------------------------------------------
42 # Constants
43 #-------------------------------------------------------------------------------
44
45 _COMPLETE_BUFFER_BG = '#FAFAF1' # Nice green
46 _INPUT_BUFFER_BG = '#FDFFD3' # Nice yellow
47 _ERROR_BG = '#FFF1F1' # Nice red
48
49 _COMPLETE_BUFFER_MARKER = 31
50 _ERROR_MARKER = 30
51 _INPUT_MARKER = 29
52
53 prompt_in1 = \
54 '\n\x01\x1b[0;34m\x02In [\x01\x1b[1;34m\x02$number\x01\x1b[0;34m\x02]: \x01\x1b[0m\x02'
55
56 prompt_out = \
57 '\x01\x1b[0;31m\x02Out[\x01\x1b[1;31m\x02$number\x01\x1b[0;31m\x02]: \x01\x1b[0m\x02'
58
59 #-------------------------------------------------------------------------------
60 # Classes to implement the Wx frontend
41 # Classes to implement the Wx frontend
61 #-------------------------------------------------------------------------------
42 #-------------------------------------------------------------------------------
62 class WxController(ConsoleWidget, PrefilterFrontEnd):
43 class WxController(ConsoleWidget, PrefilterFrontEnd):
63 """Classes to provide a Wx frontend to the
44 """Classes to provide a Wx frontend to the
64 IPython.kernel.core.interpreter.
45 IPython.kernel.core.interpreter.
65
46
66 This class inherits from ConsoleWidget, that provides a console-like
47 This class inherits from ConsoleWidget, that provides a console-like
67 widget to provide a text-rendering widget suitable for a terminal.
48 widget to provide a text-rendering widget suitable for a terminal.
68 """
49 """
69
50
70 output_prompt_template = string.Template(prompt_out)
71
72 input_prompt_template = string.Template(prompt_in1)
73
74 # Print debug info on what is happening to the console.
51 # Print debug info on what is happening to the console.
75 debug = False
52 debug = False
76
53
77 # The title of the terminal, as captured through the ANSI escape
54 # The title of the terminal, as captured through the ANSI escape
78 # sequences.
55 # sequences.
79 def _set_title(self, title):
56 def _set_title(self, title):
80 return self.Parent.SetTitle(title)
57 return self.Parent.SetTitle(title)
81
58
82 def _get_title(self):
59 def _get_title(self):
83 return self.Parent.GetTitle()
60 return self.Parent.GetTitle()
84
61
85 title = property(_get_title, _set_title)
62 title = property(_get_title, _set_title)
86
63
87
64
88 # The buffer being edited.
65 # The buffer being edited.
89 # We are duplicating the definition here because of multiple
66 # We are duplicating the definition here because of multiple
90 # inheritence
67 # inheritence
91 def _set_input_buffer(self, string):
68 def _set_input_buffer(self, string):
92 ConsoleWidget._set_input_buffer(self, string)
69 ConsoleWidget._set_input_buffer(self, string)
93 self._colorize_input_buffer()
70 self._colorize_input_buffer()
94
71
95 def _get_input_buffer(self):
72 def _get_input_buffer(self):
96 """ Returns the text in current edit buffer.
73 """ Returns the text in current edit buffer.
97 """
74 """
98 return ConsoleWidget._get_input_buffer(self)
75 return ConsoleWidget._get_input_buffer(self)
99
76
100 input_buffer = property(_get_input_buffer, _set_input_buffer)
77 input_buffer = property(_get_input_buffer, _set_input_buffer)
101
78
102
79
103 #--------------------------------------------------------------------------
80 #--------------------------------------------------------------------------
104 # Private Attributes
81 # Private Attributes
105 #--------------------------------------------------------------------------
82 #--------------------------------------------------------------------------
106
83
107 # A flag governing the behavior of the input. Can be:
84 # A flag governing the behavior of the input. Can be:
108 #
85 #
109 # 'readline' for readline-like behavior with a prompt
86 # 'readline' for readline-like behavior with a prompt
110 # and an edit buffer.
87 # and an edit buffer.
111 # 'raw_input' similar to readline, but triggered by a raw-input
88 # 'raw_input' similar to readline, but triggered by a raw-input
112 # call. Can be used by subclasses to act differently.
89 # call. Can be used by subclasses to act differently.
113 # 'subprocess' for sending the raw input directly to a
90 # 'subprocess' for sending the raw input directly to a
114 # subprocess.
91 # subprocess.
115 # 'buffering' for buffering of the input, that will be used
92 # 'buffering' for buffering of the input, that will be used
116 # when the input state switches back to another state.
93 # when the input state switches back to another state.
117 _input_state = 'readline'
94 _input_state = 'readline'
118
95
119 # Attribute to store reference to the pipes of a subprocess, if we
96 # Attribute to store reference to the pipes of a subprocess, if we
120 # are running any.
97 # are running any.
121 _running_process = False
98 _running_process = False
122
99
123 # A queue for writing fast streams to the screen without flooding the
100 # A queue for writing fast streams to the screen without flooding the
124 # event loop
101 # event loop
125 _out_buffer = []
102 _out_buffer = []
126
103
127 # A lock to lock the _out_buffer to make sure we don't empty it
104 # A lock to lock the _out_buffer to make sure we don't empty it
128 # while it is being swapped
105 # while it is being swapped
129 _out_buffer_lock = Lock()
106 _out_buffer_lock = Lock()
130
107
131 # The different line markers used to higlight the prompts.
108 # The different line markers used to higlight the prompts.
132 _markers = dict()
109 _markers = dict()
133
110
134 #--------------------------------------------------------------------------
111 #--------------------------------------------------------------------------
135 # Public API
112 # Public API
136 #--------------------------------------------------------------------------
113 #--------------------------------------------------------------------------
137
114
138 def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition,
115 def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition,
139 size=wx.DefaultSize,
116 size=wx.DefaultSize,
140 style=wx.CLIP_CHILDREN|wx.WANTS_CHARS,
117 style=wx.CLIP_CHILDREN|wx.WANTS_CHARS,
118 styledef=None,
141 *args, **kwds):
119 *args, **kwds):
142 """ Create Shell instance.
120 """ Create Shell instance.
121
122 Parameters
123 -----------
124 styledef : dict, optional
125 styledef is the dictionary of options used to define the
126 style.
143 """
127 """
128 if styledef is not None:
129 self.style = styledef
144 ConsoleWidget.__init__(self, parent, id, pos, size, style)
130 ConsoleWidget.__init__(self, parent, id, pos, size, style)
145 PrefilterFrontEnd.__init__(self, **kwds)
131 PrefilterFrontEnd.__init__(self, **kwds)
146
132
147 # Stick in our own raw_input:
133 # Stick in our own raw_input:
148 self.ipython0.raw_input = self.raw_input
134 self.ipython0.raw_input = self.raw_input
149
135
150 # Marker for complete buffer.
151 self.MarkerDefine(_COMPLETE_BUFFER_MARKER, stc.STC_MARK_BACKGROUND,
152 background=_COMPLETE_BUFFER_BG)
153 # Marker for current input buffer.
154 self.MarkerDefine(_INPUT_MARKER, stc.STC_MARK_BACKGROUND,
155 background=_INPUT_BUFFER_BG)
156 # Marker for tracebacks.
157 self.MarkerDefine(_ERROR_MARKER, stc.STC_MARK_BACKGROUND,
158 background=_ERROR_BG)
159
160 # A time for flushing the write buffer
136 # A time for flushing the write buffer
161 BUFFER_FLUSH_TIMER_ID = 100
137 BUFFER_FLUSH_TIMER_ID = 100
162 self._buffer_flush_timer = wx.Timer(self, BUFFER_FLUSH_TIMER_ID)
138 self._buffer_flush_timer = wx.Timer(self, BUFFER_FLUSH_TIMER_ID)
163 wx.EVT_TIMER(self, BUFFER_FLUSH_TIMER_ID, self._buffer_flush)
139 wx.EVT_TIMER(self, BUFFER_FLUSH_TIMER_ID, self._buffer_flush)
164
140
165 if 'debug' in kwds:
141 if 'debug' in kwds:
166 self.debug = kwds['debug']
142 self.debug = kwds['debug']
167 kwds.pop('debug')
143 kwds.pop('debug')
168
144
169 # Inject self in namespace, for debug
145 # Inject self in namespace, for debug
170 if self.debug:
146 if self.debug:
171 self.shell.user_ns['self'] = self
147 self.shell.user_ns['self'] = self
172 # Inject our own raw_input in namespace
148 # Inject our own raw_input in namespace
173 self.shell.user_ns['raw_input'] = self.raw_input
149 self.shell.user_ns['raw_input'] = self.raw_input
174
150
175
176 def raw_input(self, prompt=''):
151 def raw_input(self, prompt=''):
177 """ A replacement from python's raw_input.
152 """ A replacement from python's raw_input.
178 """
153 """
179 self.new_prompt(prompt)
154 self.new_prompt(prompt)
180 self._input_state = 'raw_input'
155 self._input_state = 'raw_input'
181 if hasattr(self, '_cursor'):
156 if hasattr(self, '_cursor'):
182 del self._cursor
157 del self._cursor
183 self.SetCursor(wx.StockCursor(wx.CURSOR_CROSS))
158 self.SetCursor(wx.StockCursor(wx.CURSOR_CROSS))
184 self.__old_on_enter = self._on_enter
159 self.__old_on_enter = self._on_enter
185 event_loop = wx.EventLoop()
160 event_loop = wx.EventLoop()
186 def my_on_enter():
161 def my_on_enter():
187 event_loop.Exit()
162 event_loop.Exit()
188 self._on_enter = my_on_enter
163 self._on_enter = my_on_enter
189 # XXX: Running a separate event_loop. Ugly.
164 # XXX: Running a separate event_loop. Ugly.
190 event_loop.Run()
165 event_loop.Run()
191 self._on_enter = self.__old_on_enter
166 self._on_enter = self.__old_on_enter
192 self._input_state = 'buffering'
167 self._input_state = 'buffering'
193 self._cursor = wx.BusyCursor()
168 self._cursor = wx.BusyCursor()
194 return self.input_buffer.rstrip('\n')
169 return self.input_buffer.rstrip('\n')
195
170
196
171
197 def system_call(self, command_string):
172 def system_call(self, command_string):
198 self._input_state = 'subprocess'
173 self._input_state = 'subprocess'
199 event_loop = wx.EventLoop()
174 event_loop = wx.EventLoop()
200 def _end_system_call():
175 def _end_system_call():
201 self._input_state = 'buffering'
176 self._input_state = 'buffering'
202 self._running_process = False
177 self._running_process = False
203 event_loop.Exit()
178 event_loop.Exit()
204
179
205 self._running_process = PipedProcess(command_string,
180 self._running_process = PipedProcess(command_string,
206 out_callback=self.buffered_write,
181 out_callback=self.buffered_write,
207 end_callback = _end_system_call)
182 end_callback = _end_system_call)
208 self._running_process.start()
183 self._running_process.start()
209 # XXX: Running a separate event_loop. Ugly.
184 # XXX: Running a separate event_loop. Ugly.
210 event_loop.Run()
185 event_loop.Run()
211 # Be sure to flush the buffer.
186 # Be sure to flush the buffer.
212 self._buffer_flush(event=None)
187 self._buffer_flush(event=None)
213
188
214
189
215 def do_calltip(self):
190 def do_calltip(self):
216 """ Analyse current and displays useful calltip for it.
191 """ Analyse current and displays useful calltip for it.
217 """
192 """
218 if self.debug:
193 if self.debug:
219 print >>sys.__stdout__, "do_calltip"
194 print >>sys.__stdout__, "do_calltip"
220 separators = re.compile('[\s\{\}\[\]\(\)\= ,:]')
195 separators = re.compile('[\s\{\}\[\]\(\)\= ,:]')
221 symbol = self.input_buffer
196 symbol = self.input_buffer
222 symbol_string = separators.split(symbol)[-1]
197 symbol_string = separators.split(symbol)[-1]
223 base_symbol_string = symbol_string.split('.')[0]
198 base_symbol_string = symbol_string.split('.')[0]
224 if base_symbol_string in self.shell.user_ns:
199 if base_symbol_string in self.shell.user_ns:
225 symbol = self.shell.user_ns[base_symbol_string]
200 symbol = self.shell.user_ns[base_symbol_string]
226 elif base_symbol_string in self.shell.user_global_ns:
201 elif base_symbol_string in self.shell.user_global_ns:
227 symbol = self.shell.user_global_ns[base_symbol_string]
202 symbol = self.shell.user_global_ns[base_symbol_string]
228 elif base_symbol_string in __builtin__.__dict__:
203 elif base_symbol_string in __builtin__.__dict__:
229 symbol = __builtin__.__dict__[base_symbol_string]
204 symbol = __builtin__.__dict__[base_symbol_string]
230 else:
205 else:
231 return False
206 return False
232 try:
207 try:
233 for name in symbol_string.split('.')[1:] + ['__doc__']:
208 for name in symbol_string.split('.')[1:] + ['__doc__']:
234 symbol = getattr(symbol, name)
209 symbol = getattr(symbol, name)
235 self.AutoCompCancel()
210 self.AutoCompCancel()
236 # Check that the symbol can indeed be converted to a string:
211 # Check that the symbol can indeed be converted to a string:
237 symbol += ''
212 symbol += ''
238 wx.CallAfter(self.CallTipShow, self.GetCurrentPos(), symbol)
213 wx.CallAfter(self.CallTipShow, self.GetCurrentPos(), symbol)
239 except:
214 except:
240 # The retrieve symbol couldn't be converted to a string
215 # The retrieve symbol couldn't be converted to a string
241 pass
216 pass
242
217
243
218
244 def _popup_completion(self, create=False):
219 def _popup_completion(self, create=False):
245 """ Updates the popup completion menu if it exists. If create is
220 """ Updates the popup completion menu if it exists. If create is
246 true, open the menu.
221 true, open the menu.
247 """
222 """
248 if self.debug:
223 if self.debug:
249 print >>sys.__stdout__, "_popup_completion"
224 print >>sys.__stdout__, "_popup_completion"
250 line = self.input_buffer
225 line = self.input_buffer
251 if (self.AutoCompActive() and line and not line[-1] == '.') \
226 if (self.AutoCompActive() and line and not line[-1] == '.') \
252 or create==True:
227 or create==True:
253 suggestion, completions = self.complete(line)
228 suggestion, completions = self.complete(line)
254 offset=0
255 if completions:
229 if completions:
256 complete_sep = re.compile('[\s\{\}\[\]\(\)\= ,:]')
230 offset = len(self._get_completion_text(line))
257 residual = complete_sep.split(line)[-1]
258 offset = len(residual)
259 self.pop_completion(completions, offset=offset)
231 self.pop_completion(completions, offset=offset)
260 if self.debug:
232 if self.debug:
261 print >>sys.__stdout__, completions
233 print >>sys.__stdout__, completions
262
234
263
235
264 def buffered_write(self, text):
236 def buffered_write(self, text):
265 """ A write method for streams, that caches the stream in order
237 """ A write method for streams, that caches the stream in order
266 to avoid flooding the event loop.
238 to avoid flooding the event loop.
267
239
268 This can be called outside of the main loop, in separate
240 This can be called outside of the main loop, in separate
269 threads.
241 threads.
270 """
242 """
271 self._out_buffer_lock.acquire()
243 self._out_buffer_lock.acquire()
272 self._out_buffer.append(text)
244 self._out_buffer.append(text)
273 self._out_buffer_lock.release()
245 self._out_buffer_lock.release()
274 if not self._buffer_flush_timer.IsRunning():
246 if not self._buffer_flush_timer.IsRunning():
275 wx.CallAfter(self._buffer_flush_timer.Start,
247 wx.CallAfter(self._buffer_flush_timer.Start,
276 milliseconds=100, oneShot=True)
248 milliseconds=100, oneShot=True)
277
249
278
250
251 def clear_screen(self):
252 """ Empty completely the widget.
253 """
254 self.ClearAll()
255 self.new_prompt(self.input_prompt_template.substitute(
256 number=(self.last_result['number'] + 1)))
257
258
279 #--------------------------------------------------------------------------
259 #--------------------------------------------------------------------------
280 # LineFrontEnd interface
260 # LineFrontEnd interface
281 #--------------------------------------------------------------------------
261 #--------------------------------------------------------------------------
282
262
283 def execute(self, python_string, raw_string=None):
263 def execute(self, python_string, raw_string=None):
284 self._input_state = 'buffering'
264 self._input_state = 'buffering'
285 self.CallTipCancel()
265 self.CallTipCancel()
286 self._cursor = wx.BusyCursor()
266 self._cursor = wx.BusyCursor()
287 if raw_string is None:
267 if raw_string is None:
288 raw_string = python_string
268 raw_string = python_string
289 end_line = self.current_prompt_line \
269 end_line = self.current_prompt_line \
290 + max(1, len(raw_string.split('\n'))-1)
270 + max(1, len(raw_string.split('\n'))-1)
291 for i in range(self.current_prompt_line, end_line):
271 for i in range(self.current_prompt_line, end_line):
292 if i in self._markers:
272 if i in self._markers:
293 self.MarkerDeleteHandle(self._markers[i])
273 self.MarkerDeleteHandle(self._markers[i])
294 self._markers[i] = self.MarkerAdd(i, _COMPLETE_BUFFER_MARKER)
274 self._markers[i] = self.MarkerAdd(i, _COMPLETE_BUFFER_MARKER)
295 # Use a callafter to update the display robustly under windows
275 # Use a callafter to update the display robustly under windows
296 def callback():
276 def callback():
297 self.GotoPos(self.GetLength())
277 self.GotoPos(self.GetLength())
298 PrefilterFrontEnd.execute(self, python_string,
278 PrefilterFrontEnd.execute(self, python_string,
299 raw_string=raw_string)
279 raw_string=raw_string)
300 wx.CallAfter(callback)
280 wx.CallAfter(callback)
301
281
282
283 def execute_command(self, command, hidden=False):
284 """ Execute a command, not only in the model, but also in the
285 view.
286 """
287 # XXX: This method needs to be integrated in the base fronted
288 # interface
289 if hidden:
290 return self.shell.execute(command)
291 else:
292 # XXX: we are not storing the input buffer previous to the
293 # execution, as this forces us to run the execution
294 # input_buffer a yield, which is not good.
295 ##current_buffer = self.shell.control.input_buffer
296 command = command.rstrip()
297 if len(command.split('\n')) > 1:
298 # The input command is several lines long, we need to
299 # force the execution to happen
300 command += '\n'
301 cleaned_command = self.prefilter_input(command)
302 self.input_buffer = command
303 # Do not use wx.Yield() (aka GUI.process_events()) to avoid
304 # recursive yields.
305 self.ProcessEvent(wx.PaintEvent())
306 self.write('\n')
307 if not self.is_complete(cleaned_command + '\n'):
308 self._colorize_input_buffer()
309 self.render_error('Incomplete or invalid input')
310 self.new_prompt(self.input_prompt_template.substitute(
311 number=(self.last_result['number'] + 1)))
312 return False
313 self._on_enter()
314 return True
315
316
302 def save_output_hooks(self):
317 def save_output_hooks(self):
303 self.__old_raw_input = __builtin__.raw_input
318 self.__old_raw_input = __builtin__.raw_input
304 PrefilterFrontEnd.save_output_hooks(self)
319 PrefilterFrontEnd.save_output_hooks(self)
305
320
306 def capture_output(self):
321 def capture_output(self):
307 self.SetLexer(stc.STC_LEX_NULL)
322 self.SetLexer(stc.STC_LEX_NULL)
308 PrefilterFrontEnd.capture_output(self)
323 PrefilterFrontEnd.capture_output(self)
309 __builtin__.raw_input = self.raw_input
324 __builtin__.raw_input = self.raw_input
310
325
311
326
312 def release_output(self):
327 def release_output(self):
313 __builtin__.raw_input = self.__old_raw_input
328 __builtin__.raw_input = self.__old_raw_input
314 PrefilterFrontEnd.release_output(self)
329 PrefilterFrontEnd.release_output(self)
315 self.SetLexer(stc.STC_LEX_PYTHON)
330 self.SetLexer(stc.STC_LEX_PYTHON)
316
331
317
332
318 def after_execute(self):
333 def after_execute(self):
319 PrefilterFrontEnd.after_execute(self)
334 PrefilterFrontEnd.after_execute(self)
320 # Clear the wait cursor
335 # Clear the wait cursor
321 if hasattr(self, '_cursor'):
336 if hasattr(self, '_cursor'):
322 del self._cursor
337 del self._cursor
323 self.SetCursor(wx.StockCursor(wx.CURSOR_CHAR))
338 self.SetCursor(wx.StockCursor(wx.CURSOR_CHAR))
324
339
325
340
326 def show_traceback(self):
341 def show_traceback(self):
327 start_line = self.GetCurrentLine()
342 start_line = self.GetCurrentLine()
328 PrefilterFrontEnd.show_traceback(self)
343 PrefilterFrontEnd.show_traceback(self)
329 self.ProcessEvent(wx.PaintEvent())
344 self.ProcessEvent(wx.PaintEvent())
330 #wx.Yield()
345 #wx.Yield()
331 for i in range(start_line, self.GetCurrentLine()):
346 for i in range(start_line, self.GetCurrentLine()):
332 self._markers[i] = self.MarkerAdd(i, _ERROR_MARKER)
347 self._markers[i] = self.MarkerAdd(i, _ERROR_MARKER)
333
348
334
349
335 #--------------------------------------------------------------------------
350 #--------------------------------------------------------------------------
336 # FrontEndBase interface
351 # FrontEndBase interface
337 #--------------------------------------------------------------------------
352 #--------------------------------------------------------------------------
338
353
339 def render_error(self, e):
354 def render_error(self, e):
340 start_line = self.GetCurrentLine()
355 start_line = self.GetCurrentLine()
341 self.write('\n' + e + '\n')
356 self.write('\n' + e + '\n')
342 for i in range(start_line, self.GetCurrentLine()):
357 for i in range(start_line, self.GetCurrentLine()):
343 self._markers[i] = self.MarkerAdd(i, _ERROR_MARKER)
358 self._markers[i] = self.MarkerAdd(i, _ERROR_MARKER)
344
359
345
360
346 #--------------------------------------------------------------------------
361 #--------------------------------------------------------------------------
347 # ConsoleWidget interface
362 # ConsoleWidget interface
348 #--------------------------------------------------------------------------
363 #--------------------------------------------------------------------------
349
364
350 def new_prompt(self, prompt):
365 def new_prompt(self, prompt):
351 """ Display a new prompt, and start a new input buffer.
366 """ Display a new prompt, and start a new input buffer.
352 """
367 """
353 self._input_state = 'readline'
368 self._input_state = 'readline'
354 ConsoleWidget.new_prompt(self, prompt)
369 ConsoleWidget.new_prompt(self, prompt)
355 i = self.current_prompt_line
370 i = self.current_prompt_line
356 self._markers[i] = self.MarkerAdd(i, _INPUT_MARKER)
371 self._markers[i] = self.MarkerAdd(i, _INPUT_MARKER)
357
372
358
373
374 def continuation_prompt(self, *args, **kwargs):
375 # Avoid multiple inheritence, be explicit about which
376 # parent method class gets called
377 return ConsoleWidget.continuation_prompt(self, *args, **kwargs)
378
379
359 def write(self, *args, **kwargs):
380 def write(self, *args, **kwargs):
360 # Avoid multiple inheritence, be explicit about which
381 # Avoid multiple inheritence, be explicit about which
361 # parent method class gets called
382 # parent method class gets called
362 ConsoleWidget.write(self, *args, **kwargs)
383 return ConsoleWidget.write(self, *args, **kwargs)
363
384
364
385
365 def _on_key_down(self, event, skip=True):
386 def _on_key_down(self, event, skip=True):
366 """ Capture the character events, let the parent
387 """ Capture the character events, let the parent
367 widget handle them, and put our logic afterward.
388 widget handle them, and put our logic afterward.
368 """
389 """
369 # FIXME: This method needs to be broken down in smaller ones.
390 # FIXME: This method needs to be broken down in smaller ones.
370 current_line_number = self.GetCurrentLine()
391 current_line_num = self.GetCurrentLine()
371 if event.KeyCode in (ord('c'), ord('C')) and event.ControlDown():
392 if event.KeyCode in (ord('c'), ord('C')) and event.ControlDown():
372 # Capture Control-C
393 # Capture Control-C
373 if self._input_state == 'subprocess':
394 if self._input_state == 'subprocess':
374 if self.debug:
395 if self.debug:
375 print >>sys.__stderr__, 'Killing running process'
396 print >>sys.__stderr__, 'Killing running process'
376 if hasattr(self._running_process, 'process'):
397 if hasattr(self._running_process, 'process'):
377 self._running_process.process.kill()
398 self._running_process.process.kill()
378 elif self._input_state == 'buffering':
399 elif self._input_state == 'buffering':
379 if self.debug:
400 if self.debug:
380 print >>sys.__stderr__, 'Raising KeyboardInterrupt'
401 print >>sys.__stderr__, 'Raising KeyboardInterrupt'
381 raise KeyboardInterrupt
402 raise KeyboardInterrupt
382 # XXX: We need to make really sure we
403 # XXX: We need to make really sure we
383 # get back to a prompt.
404 # get back to a prompt.
384 elif self._input_state == 'subprocess' and (
405 elif self._input_state == 'subprocess' and (
385 ( event.KeyCode<256 and
406 ( event.KeyCode<256 and
386 not event.ControlDown() )
407 not event.ControlDown() )
387 or
408 or
388 ( event.KeyCode in (ord('d'), ord('D')) and
409 ( event.KeyCode in (ord('d'), ord('D')) and
389 event.ControlDown())):
410 event.ControlDown())):
390 # We are running a process, we redirect keys.
411 # We are running a process, we redirect keys.
391 ConsoleWidget._on_key_down(self, event, skip=skip)
412 ConsoleWidget._on_key_down(self, event, skip=skip)
392 char = chr(event.KeyCode)
413 char = chr(event.KeyCode)
393 # Deal with some inconsistency in wx keycodes:
414 # Deal with some inconsistency in wx keycodes:
394 if char == '\r':
415 if char == '\r':
395 char = '\n'
416 char = '\n'
396 elif not event.ShiftDown():
417 elif not event.ShiftDown():
397 char = char.lower()
418 char = char.lower()
398 if event.ControlDown() and event.KeyCode in (ord('d'), ord('D')):
419 if event.ControlDown() and event.KeyCode in (ord('d'), ord('D')):
399 char = '\04'
420 char = '\04'
400 self._running_process.process.stdin.write(char)
421 self._running_process.process.stdin.write(char)
401 self._running_process.process.stdin.flush()
422 self._running_process.process.stdin.flush()
402 elif event.KeyCode in (ord('('), 57, 53):
423 elif event.KeyCode in (ord('('), 57, 53):
403 # Calltips
424 # Calltips
404 event.Skip()
425 event.Skip()
405 self.do_calltip()
426 self.do_calltip()
406 elif self.AutoCompActive() and not event.KeyCode == ord('\t'):
427 elif self.AutoCompActive() and not event.KeyCode == ord('\t'):
407 event.Skip()
428 event.Skip()
408 if event.KeyCode in (wx.WXK_BACK, wx.WXK_DELETE):
429 if event.KeyCode in (wx.WXK_BACK, wx.WXK_DELETE):
409 wx.CallAfter(self._popup_completion, create=True)
430 wx.CallAfter(self._popup_completion, create=True)
410 elif not event.KeyCode in (wx.WXK_UP, wx.WXK_DOWN, wx.WXK_LEFT,
431 elif not event.KeyCode in (wx.WXK_UP, wx.WXK_DOWN, wx.WXK_LEFT,
411 wx.WXK_RIGHT, wx.WXK_ESCAPE):
432 wx.WXK_RIGHT, wx.WXK_ESCAPE):
412 wx.CallAfter(self._popup_completion)
433 wx.CallAfter(self._popup_completion)
413 else:
434 else:
414 # Up history
435 # Up history
415 if event.KeyCode == wx.WXK_UP and (
436 if event.KeyCode == wx.WXK_UP and (
416 ( current_line_number == self.current_prompt_line and
437 ( current_line_num == self.current_prompt_line and
417 event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN) )
438 event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN) )
418 or event.ControlDown() ):
439 or event.ControlDown() ):
419 new_buffer = self.get_history_previous(
440 new_buffer = self.get_history_previous(
420 self.input_buffer)
441 self.input_buffer)
421 if new_buffer is not None:
442 if new_buffer is not None:
422 self.input_buffer = new_buffer
443 self.input_buffer = new_buffer
423 if self.GetCurrentLine() > self.current_prompt_line:
444 if self.GetCurrentLine() > self.current_prompt_line:
424 # Go to first line, for seemless history up.
445 # Go to first line, for seemless history up.
425 self.GotoPos(self.current_prompt_pos)
446 self.GotoPos(self.current_prompt_pos)
426 # Down history
447 # Down history
427 elif event.KeyCode == wx.WXK_DOWN and (
448 elif event.KeyCode == wx.WXK_DOWN and (
428 ( current_line_number == self.LineCount -1 and
449 ( current_line_num == self.LineCount -1 and
429 event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN) )
450 event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN) )
430 or event.ControlDown() ):
451 or event.ControlDown() ):
431 new_buffer = self.get_history_next()
452 new_buffer = self.get_history_next()
432 if new_buffer is not None:
453 if new_buffer is not None:
433 self.input_buffer = new_buffer
454 self.input_buffer = new_buffer
434 # Tab-completion
455 # Tab-completion
435 elif event.KeyCode == ord('\t'):
456 elif event.KeyCode == ord('\t'):
436 current_line, current_line_number = self.CurLine
457 current_line, current_line_num = self.CurLine
437 if not re.match(r'^\s*$', current_line):
458 if not re.match(r'^\s*$', current_line):
438 self.complete_current_input()
459 self.complete_current_input()
439 if self.AutoCompActive():
460 if self.AutoCompActive():
440 wx.CallAfter(self._popup_completion, create=True)
461 wx.CallAfter(self._popup_completion, create=True)
441 else:
462 else:
442 event.Skip()
463 event.Skip()
464 elif event.KeyCode == wx.WXK_BACK:
465 # If characters where erased, check if we have to
466 # remove a line.
467 # XXX: What about DEL?
468 # FIXME: This logics should be in ConsoleWidget, as it is
469 # independant of IPython
470 current_line, _ = self.CurLine
471 current_pos = self.GetCurrentPos()
472 current_line_num = self.LineFromPosition(current_pos)
473 current_col = self.GetColumn(current_pos)
474 len_prompt = len(self.continuation_prompt())
475 if ( current_line.startswith(self.continuation_prompt())
476 and current_col == len_prompt):
477 new_lines = []
478 for line_num, line in enumerate(
479 self.input_buffer.split('\n')):
480 if (line_num + self.current_prompt_line ==
481 current_line_num):
482 new_lines.append(line[len_prompt:])
483 else:
484 new_lines.append('\n'+line)
485 # The first character is '\n', due to the above
486 # code:
487 self.input_buffer = ''.join(new_lines)[1:]
488 self.GotoPos(current_pos - 1 - len_prompt)
443 else:
489 else:
444 ConsoleWidget._on_key_down(self, event, skip=skip)
490 ConsoleWidget._on_key_down(self, event, skip=skip)
491 else:
492 ConsoleWidget._on_key_down(self, event, skip=skip)
493
445
494
446
495
447 def _on_key_up(self, event, skip=True):
496 def _on_key_up(self, event, skip=True):
448 """ Called when any key is released.
497 """ Called when any key is released.
449 """
498 """
450 if event.KeyCode in (59, ord('.')):
499 if event.KeyCode in (59, ord('.')):
451 # Intercepting '.'
500 # Intercepting '.'
452 event.Skip()
501 event.Skip()
453 wx.CallAfter(self._popup_completion, create=True)
502 wx.CallAfter(self._popup_completion, create=True)
454 else:
503 else:
455 ConsoleWidget._on_key_up(self, event, skip=skip)
504 ConsoleWidget._on_key_up(self, event, skip=skip)
505 # Make sure the continuation_prompts are always followed by a
506 # whitespace
507 new_lines = []
508 if self._input_state == 'readline':
509 position = self.GetCurrentPos()
510 continuation_prompt = self.continuation_prompt()[:-1]
511 for line in self.input_buffer.split('\n'):
512 if not line == continuation_prompt:
513 new_lines.append(line)
514 self.input_buffer = '\n'.join(new_lines)
515 self.GotoPos(position)
456
516
457
517
458 def _on_enter(self):
518 def _on_enter(self):
459 """ Called on return key down, in readline input_state.
519 """ Called on return key down, in readline input_state.
460 """
520 """
521 last_line_num = self.LineFromPosition(self.GetLength())
522 current_line_num = self.LineFromPosition(self.GetCurrentPos())
523 new_line_pos = (last_line_num - current_line_num)
461 if self.debug:
524 if self.debug:
462 print >>sys.__stdout__, repr(self.input_buffer)
525 print >>sys.__stdout__, repr(self.input_buffer)
463 PrefilterFrontEnd._on_enter(self)
526 self.write('\n', refresh=False)
527 # Under windows scintilla seems to be doing funny
528 # stuff to the line returns here, but the getter for
529 # input_buffer filters this out.
530 if sys.platform == 'win32':
531 self.input_buffer = self.input_buffer
532 old_prompt_num = self.current_prompt_pos
533 has_executed = PrefilterFrontEnd._on_enter(self,
534 new_line_pos=new_line_pos)
535 if old_prompt_num == self.current_prompt_pos:
536 # No execution has happened
537 self.GotoPos(self.GetLineEndPosition(current_line_num + 1))
538 return has_executed
464
539
465
540
466 #--------------------------------------------------------------------------
541 #--------------------------------------------------------------------------
467 # EditWindow API
542 # EditWindow API
468 #--------------------------------------------------------------------------
543 #--------------------------------------------------------------------------
469
544
470 def OnUpdateUI(self, event):
545 def OnUpdateUI(self, event):
471 """ Override the OnUpdateUI of the EditWindow class, to prevent
546 """ Override the OnUpdateUI of the EditWindow class, to prevent
472 syntax highlighting both for faster redraw, and for more
547 syntax highlighting both for faster redraw, and for more
473 consistent look and feel.
548 consistent look and feel.
474 """
549 """
475 if not self._input_state == 'readline':
550 if not self._input_state == 'readline':
476 ConsoleWidget.OnUpdateUI(self, event)
551 ConsoleWidget.OnUpdateUI(self, event)
477
552
478 #--------------------------------------------------------------------------
553 #--------------------------------------------------------------------------
479 # Private API
554 # Private API
480 #--------------------------------------------------------------------------
555 #--------------------------------------------------------------------------
481
556
482 def _buffer_flush(self, event):
557 def _buffer_flush(self, event):
483 """ Called by the timer to flush the write buffer.
558 """ Called by the timer to flush the write buffer.
484
559
485 This is always called in the mainloop, by the wx timer.
560 This is always called in the mainloop, by the wx timer.
486 """
561 """
487 self._out_buffer_lock.acquire()
562 self._out_buffer_lock.acquire()
488 _out_buffer = self._out_buffer
563 _out_buffer = self._out_buffer
489 self._out_buffer = []
564 self._out_buffer = []
490 self._out_buffer_lock.release()
565 self._out_buffer_lock.release()
491 self.write(''.join(_out_buffer), refresh=False)
566 self.write(''.join(_out_buffer), refresh=False)
492
567
493
568
494 def _colorize_input_buffer(self):
569 def _colorize_input_buffer(self):
495 """ Keep the input buffer lines at a bright color.
570 """ Keep the input buffer lines at a bright color.
496 """
571 """
497 if not self._input_state in ('readline', 'raw_input'):
572 if not self._input_state in ('readline', 'raw_input'):
498 return
573 return
499 end_line = self.GetCurrentLine()
574 end_line = self.GetCurrentLine()
500 if not sys.platform == 'win32':
575 if not sys.platform == 'win32':
501 end_line += 1
576 end_line += 1
502 for i in range(self.current_prompt_line, end_line):
577 for i in range(self.current_prompt_line, end_line):
503 if i in self._markers:
578 if i in self._markers:
504 self.MarkerDeleteHandle(self._markers[i])
579 self.MarkerDeleteHandle(self._markers[i])
505 self._markers[i] = self.MarkerAdd(i, _INPUT_MARKER)
580 self._markers[i] = self.MarkerAdd(i, _INPUT_MARKER)
506
581
507
582
508 if __name__ == '__main__':
583 if __name__ == '__main__':
509 class MainWindow(wx.Frame):
584 class MainWindow(wx.Frame):
510 def __init__(self, parent, id, title):
585 def __init__(self, parent, id, title):
511 wx.Frame.__init__(self, parent, id, title, size=(300,250))
586 wx.Frame.__init__(self, parent, id, title, size=(300,250))
512 self._sizer = wx.BoxSizer(wx.VERTICAL)
587 self._sizer = wx.BoxSizer(wx.VERTICAL)
513 self.shell = WxController(self)
588 self.shell = WxController(self)
514 self._sizer.Add(self.shell, 1, wx.EXPAND)
589 self._sizer.Add(self.shell, 1, wx.EXPAND)
515 self.SetSizer(self._sizer)
590 self.SetSizer(self._sizer)
516 self.SetAutoLayout(1)
591 self.SetAutoLayout(1)
517 self.Show(True)
592 self.Show(True)
518
593
519 app = wx.PySimpleApp()
594 app = wx.PySimpleApp()
520 frame = MainWindow(None, wx.ID_ANY, 'Ipython')
595 frame = MainWindow(None, wx.ID_ANY, 'Ipython')
521 frame.shell.SetFocus()
596 frame.shell.SetFocus()
522 frame.SetSize((680, 460))
597 frame.SetSize((680, 460))
523 self = frame.shell
598 self = frame.shell
524
599
525 app.MainLoop()
600 app.MainLoop()
526
601
@@ -1,2161 +1,2171 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """General purpose utilities.
2 """General purpose utilities.
3
3
4 This is a grab-bag of stuff I find useful in most programs I write. Some of
4 This is a grab-bag of stuff I find useful in most programs I write. Some of
5 these things are also convenient when working at the command line.
5 these things are also convenient when working at the command line.
6 """
6 """
7
7
8 #*****************************************************************************
8 #*****************************************************************************
9 # Copyright (C) 2001-2006 Fernando Perez. <fperez@colorado.edu>
9 # Copyright (C) 2001-2006 Fernando Perez. <fperez@colorado.edu>
10 #
10 #
11 # Distributed under the terms of the BSD License. The full license is in
11 # Distributed under the terms of the BSD License. The full license is in
12 # the file COPYING, distributed as part of this software.
12 # the file COPYING, distributed as part of this software.
13 #*****************************************************************************
13 #*****************************************************************************
14
14
15 #****************************************************************************
15 #****************************************************************************
16 # required modules from the Python standard library
16 # required modules from the Python standard library
17 import __main__
17 import __main__
18 import commands
18 import commands
19 try:
19 try:
20 import doctest
20 import doctest
21 except ImportError:
21 except ImportError:
22 pass
22 pass
23 import os
23 import os
24 import platform
24 import platform
25 import re
25 import re
26 import shlex
26 import shlex
27 import shutil
27 import shutil
28 import subprocess
28 import subprocess
29 import sys
29 import sys
30 import tempfile
30 import tempfile
31 import time
31 import time
32 import types
32 import types
33 import warnings
33 import warnings
34
34
35 # Curses and termios are Unix-only modules
35 # Curses and termios are Unix-only modules
36 try:
36 try:
37 import curses
37 import curses
38 # We need termios as well, so if its import happens to raise, we bail on
38 # We need termios as well, so if its import happens to raise, we bail on
39 # using curses altogether.
39 # using curses altogether.
40 import termios
40 import termios
41 except ImportError:
41 except ImportError:
42 USE_CURSES = False
42 USE_CURSES = False
43 else:
43 else:
44 # Curses on Solaris may not be complete, so we can't use it there
44 # Curses on Solaris may not be complete, so we can't use it there
45 USE_CURSES = hasattr(curses,'initscr')
45 USE_CURSES = hasattr(curses,'initscr')
46
46
47 # Other IPython utilities
47 # Other IPython utilities
48 import IPython
48 import IPython
49 from IPython.Itpl import Itpl,itpl,printpl
49 from IPython.Itpl import Itpl,itpl,printpl
50 from IPython import DPyGetOpt, platutils
50 from IPython import DPyGetOpt, platutils
51 from IPython.generics import result_display
51 from IPython.generics import result_display
52 import IPython.ipapi
52 import IPython.ipapi
53 from IPython.external.path import path
53 from IPython.external.path import path
54 if os.name == "nt":
54 if os.name == "nt":
55 from IPython.winconsole import get_console_size
55 from IPython.winconsole import get_console_size
56
56
57 try:
57 try:
58 set
58 set
59 except:
59 except:
60 from sets import Set as set
60 from sets import Set as set
61
61
62
62
63 #****************************************************************************
63 #****************************************************************************
64 # Exceptions
64 # Exceptions
65 class Error(Exception):
65 class Error(Exception):
66 """Base class for exceptions in this module."""
66 """Base class for exceptions in this module."""
67 pass
67 pass
68
68
69 #----------------------------------------------------------------------------
69 #----------------------------------------------------------------------------
70 class IOStream:
70 class IOStream:
71 def __init__(self,stream,fallback):
71 def __init__(self,stream,fallback):
72 if not hasattr(stream,'write') or not hasattr(stream,'flush'):
72 if not hasattr(stream,'write') or not hasattr(stream,'flush'):
73 stream = fallback
73 stream = fallback
74 self.stream = stream
74 self.stream = stream
75 self._swrite = stream.write
75 self._swrite = stream.write
76 self.flush = stream.flush
76 self.flush = stream.flush
77
77
78 def write(self,data):
78 def write(self,data):
79 try:
79 try:
80 self._swrite(data)
80 self._swrite(data)
81 except:
81 except:
82 try:
82 try:
83 # print handles some unicode issues which may trip a plain
83 # print handles some unicode issues which may trip a plain
84 # write() call. Attempt to emulate write() by using a
84 # write() call. Attempt to emulate write() by using a
85 # trailing comma
85 # trailing comma
86 print >> self.stream, data,
86 print >> self.stream, data,
87 except:
87 except:
88 # if we get here, something is seriously broken.
88 # if we get here, something is seriously broken.
89 print >> sys.stderr, \
89 print >> sys.stderr, \
90 'ERROR - failed to write data to stream:', self.stream
90 'ERROR - failed to write data to stream:', self.stream
91
91
92 def close(self):
92 def close(self):
93 pass
93 pass
94
94
95
95
96 class IOTerm:
96 class IOTerm:
97 """ Term holds the file or file-like objects for handling I/O operations.
97 """ Term holds the file or file-like objects for handling I/O operations.
98
98
99 These are normally just sys.stdin, sys.stdout and sys.stderr but for
99 These are normally just sys.stdin, sys.stdout and sys.stderr but for
100 Windows they can can replaced to allow editing the strings before they are
100 Windows they can can replaced to allow editing the strings before they are
101 displayed."""
101 displayed."""
102
102
103 # In the future, having IPython channel all its I/O operations through
103 # In the future, having IPython channel all its I/O operations through
104 # this class will make it easier to embed it into other environments which
104 # this class will make it easier to embed it into other environments which
105 # are not a normal terminal (such as a GUI-based shell)
105 # are not a normal terminal (such as a GUI-based shell)
106 def __init__(self,cin=None,cout=None,cerr=None):
106 def __init__(self,cin=None,cout=None,cerr=None):
107 self.cin = IOStream(cin,sys.stdin)
107 self.cin = IOStream(cin,sys.stdin)
108 self.cout = IOStream(cout,sys.stdout)
108 self.cout = IOStream(cout,sys.stdout)
109 self.cerr = IOStream(cerr,sys.stderr)
109 self.cerr = IOStream(cerr,sys.stderr)
110
110
111 # Global variable to be used for all I/O
111 # Global variable to be used for all I/O
112 Term = IOTerm()
112 Term = IOTerm()
113
113
114 import IPython.rlineimpl as readline
114 import IPython.rlineimpl as readline
115 # Remake Term to use the readline i/o facilities
115 # Remake Term to use the readline i/o facilities
116 if sys.platform == 'win32' and readline.have_readline:
116 if sys.platform == 'win32' and readline.have_readline:
117
117
118 Term = IOTerm(cout=readline._outputfile,cerr=readline._outputfile)
118 Term = IOTerm(cout=readline._outputfile,cerr=readline._outputfile)
119
119
120
120
121 #****************************************************************************
121 #****************************************************************************
122 # Generic warning/error printer, used by everything else
122 # Generic warning/error printer, used by everything else
123 def warn(msg,level=2,exit_val=1):
123 def warn(msg,level=2,exit_val=1):
124 """Standard warning printer. Gives formatting consistency.
124 """Standard warning printer. Gives formatting consistency.
125
125
126 Output is sent to Term.cerr (sys.stderr by default).
126 Output is sent to Term.cerr (sys.stderr by default).
127
127
128 Options:
128 Options:
129
129
130 -level(2): allows finer control:
130 -level(2): allows finer control:
131 0 -> Do nothing, dummy function.
131 0 -> Do nothing, dummy function.
132 1 -> Print message.
132 1 -> Print message.
133 2 -> Print 'WARNING:' + message. (Default level).
133 2 -> Print 'WARNING:' + message. (Default level).
134 3 -> Print 'ERROR:' + message.
134 3 -> Print 'ERROR:' + message.
135 4 -> Print 'FATAL ERROR:' + message and trigger a sys.exit(exit_val).
135 4 -> Print 'FATAL ERROR:' + message and trigger a sys.exit(exit_val).
136
136
137 -exit_val (1): exit value returned by sys.exit() for a level 4
137 -exit_val (1): exit value returned by sys.exit() for a level 4
138 warning. Ignored for all other levels."""
138 warning. Ignored for all other levels."""
139
139
140 if level>0:
140 if level>0:
141 header = ['','','WARNING: ','ERROR: ','FATAL ERROR: ']
141 header = ['','','WARNING: ','ERROR: ','FATAL ERROR: ']
142 print >> Term.cerr, '%s%s' % (header[level],msg)
142 print >> Term.cerr, '%s%s' % (header[level],msg)
143 if level == 4:
143 if level == 4:
144 print >> Term.cerr,'Exiting.\n'
144 print >> Term.cerr,'Exiting.\n'
145 sys.exit(exit_val)
145 sys.exit(exit_val)
146
146
147 def info(msg):
147 def info(msg):
148 """Equivalent to warn(msg,level=1)."""
148 """Equivalent to warn(msg,level=1)."""
149
149
150 warn(msg,level=1)
150 warn(msg,level=1)
151
151
152 def error(msg):
152 def error(msg):
153 """Equivalent to warn(msg,level=3)."""
153 """Equivalent to warn(msg,level=3)."""
154
154
155 warn(msg,level=3)
155 warn(msg,level=3)
156
156
157 def fatal(msg,exit_val=1):
157 def fatal(msg,exit_val=1):
158 """Equivalent to warn(msg,exit_val=exit_val,level=4)."""
158 """Equivalent to warn(msg,exit_val=exit_val,level=4)."""
159
159
160 warn(msg,exit_val=exit_val,level=4)
160 warn(msg,exit_val=exit_val,level=4)
161
161
162 #---------------------------------------------------------------------------
162 #---------------------------------------------------------------------------
163 # Debugging routines
163 # Debugging routines
164 #
164 #
165 def debugx(expr,pre_msg=''):
165 def debugx(expr,pre_msg=''):
166 """Print the value of an expression from the caller's frame.
166 """Print the value of an expression from the caller's frame.
167
167
168 Takes an expression, evaluates it in the caller's frame and prints both
168 Takes an expression, evaluates it in the caller's frame and prints both
169 the given expression and the resulting value (as well as a debug mark
169 the given expression and the resulting value (as well as a debug mark
170 indicating the name of the calling function. The input must be of a form
170 indicating the name of the calling function. The input must be of a form
171 suitable for eval().
171 suitable for eval().
172
172
173 An optional message can be passed, which will be prepended to the printed
173 An optional message can be passed, which will be prepended to the printed
174 expr->value pair."""
174 expr->value pair."""
175
175
176 cf = sys._getframe(1)
176 cf = sys._getframe(1)
177 print '[DBG:%s] %s%s -> %r' % (cf.f_code.co_name,pre_msg,expr,
177 print '[DBG:%s] %s%s -> %r' % (cf.f_code.co_name,pre_msg,expr,
178 eval(expr,cf.f_globals,cf.f_locals))
178 eval(expr,cf.f_globals,cf.f_locals))
179
179
180 # deactivate it by uncommenting the following line, which makes it a no-op
180 # deactivate it by uncommenting the following line, which makes it a no-op
181 #def debugx(expr,pre_msg=''): pass
181 #def debugx(expr,pre_msg=''): pass
182
182
183 #----------------------------------------------------------------------------
183 #----------------------------------------------------------------------------
184 StringTypes = types.StringTypes
184 StringTypes = types.StringTypes
185
185
186 # Basic timing functionality
186 # Basic timing functionality
187
187
188 # If possible (Unix), use the resource module instead of time.clock()
188 # If possible (Unix), use the resource module instead of time.clock()
189 try:
189 try:
190 import resource
190 import resource
191 def clocku():
191 def clocku():
192 """clocku() -> floating point number
192 """clocku() -> floating point number
193
193
194 Return the *USER* CPU time in seconds since the start of the process.
194 Return the *USER* CPU time in seconds since the start of the process.
195 This is done via a call to resource.getrusage, so it avoids the
195 This is done via a call to resource.getrusage, so it avoids the
196 wraparound problems in time.clock()."""
196 wraparound problems in time.clock()."""
197
197
198 return resource.getrusage(resource.RUSAGE_SELF)[0]
198 return resource.getrusage(resource.RUSAGE_SELF)[0]
199
199
200 def clocks():
200 def clocks():
201 """clocks() -> floating point number
201 """clocks() -> floating point number
202
202
203 Return the *SYSTEM* CPU time in seconds since the start of the process.
203 Return the *SYSTEM* CPU time in seconds since the start of the process.
204 This is done via a call to resource.getrusage, so it avoids the
204 This is done via a call to resource.getrusage, so it avoids the
205 wraparound problems in time.clock()."""
205 wraparound problems in time.clock()."""
206
206
207 return resource.getrusage(resource.RUSAGE_SELF)[1]
207 return resource.getrusage(resource.RUSAGE_SELF)[1]
208
208
209 def clock():
209 def clock():
210 """clock() -> floating point number
210 """clock() -> floating point number
211
211
212 Return the *TOTAL USER+SYSTEM* CPU time in seconds since the start of
212 Return the *TOTAL USER+SYSTEM* CPU time in seconds since the start of
213 the process. This is done via a call to resource.getrusage, so it
213 the process. This is done via a call to resource.getrusage, so it
214 avoids the wraparound problems in time.clock()."""
214 avoids the wraparound problems in time.clock()."""
215
215
216 u,s = resource.getrusage(resource.RUSAGE_SELF)[:2]
216 u,s = resource.getrusage(resource.RUSAGE_SELF)[:2]
217 return u+s
217 return u+s
218
218
219 def clock2():
219 def clock2():
220 """clock2() -> (t_user,t_system)
220 """clock2() -> (t_user,t_system)
221
221
222 Similar to clock(), but return a tuple of user/system times."""
222 Similar to clock(), but return a tuple of user/system times."""
223 return resource.getrusage(resource.RUSAGE_SELF)[:2]
223 return resource.getrusage(resource.RUSAGE_SELF)[:2]
224
224
225 except ImportError:
225 except ImportError:
226 # There is no distinction of user/system time under windows, so we just use
226 # There is no distinction of user/system time under windows, so we just use
227 # time.clock() for everything...
227 # time.clock() for everything...
228 clocku = clocks = clock = time.clock
228 clocku = clocks = clock = time.clock
229 def clock2():
229 def clock2():
230 """Under windows, system CPU time can't be measured.
230 """Under windows, system CPU time can't be measured.
231
231
232 This just returns clock() and zero."""
232 This just returns clock() and zero."""
233 return time.clock(),0.0
233 return time.clock(),0.0
234
234
235 def timings_out(reps,func,*args,**kw):
235 def timings_out(reps,func,*args,**kw):
236 """timings_out(reps,func,*args,**kw) -> (t_total,t_per_call,output)
236 """timings_out(reps,func,*args,**kw) -> (t_total,t_per_call,output)
237
237
238 Execute a function reps times, return a tuple with the elapsed total
238 Execute a function reps times, return a tuple with the elapsed total
239 CPU time in seconds, the time per call and the function's output.
239 CPU time in seconds, the time per call and the function's output.
240
240
241 Under Unix, the return value is the sum of user+system time consumed by
241 Under Unix, the return value is the sum of user+system time consumed by
242 the process, computed via the resource module. This prevents problems
242 the process, computed via the resource module. This prevents problems
243 related to the wraparound effect which the time.clock() function has.
243 related to the wraparound effect which the time.clock() function has.
244
244
245 Under Windows the return value is in wall clock seconds. See the
245 Under Windows the return value is in wall clock seconds. See the
246 documentation for the time module for more details."""
246 documentation for the time module for more details."""
247
247
248 reps = int(reps)
248 reps = int(reps)
249 assert reps >=1, 'reps must be >= 1'
249 assert reps >=1, 'reps must be >= 1'
250 if reps==1:
250 if reps==1:
251 start = clock()
251 start = clock()
252 out = func(*args,**kw)
252 out = func(*args,**kw)
253 tot_time = clock()-start
253 tot_time = clock()-start
254 else:
254 else:
255 rng = xrange(reps-1) # the last time is executed separately to store output
255 rng = xrange(reps-1) # the last time is executed separately to store output
256 start = clock()
256 start = clock()
257 for dummy in rng: func(*args,**kw)
257 for dummy in rng: func(*args,**kw)
258 out = func(*args,**kw) # one last time
258 out = func(*args,**kw) # one last time
259 tot_time = clock()-start
259 tot_time = clock()-start
260 av_time = tot_time / reps
260 av_time = tot_time / reps
261 return tot_time,av_time,out
261 return tot_time,av_time,out
262
262
263 def timings(reps,func,*args,**kw):
263 def timings(reps,func,*args,**kw):
264 """timings(reps,func,*args,**kw) -> (t_total,t_per_call)
264 """timings(reps,func,*args,**kw) -> (t_total,t_per_call)
265
265
266 Execute a function reps times, return a tuple with the elapsed total CPU
266 Execute a function reps times, return a tuple with the elapsed total CPU
267 time in seconds and the time per call. These are just the first two values
267 time in seconds and the time per call. These are just the first two values
268 in timings_out()."""
268 in timings_out()."""
269
269
270 return timings_out(reps,func,*args,**kw)[0:2]
270 return timings_out(reps,func,*args,**kw)[0:2]
271
271
272 def timing(func,*args,**kw):
272 def timing(func,*args,**kw):
273 """timing(func,*args,**kw) -> t_total
273 """timing(func,*args,**kw) -> t_total
274
274
275 Execute a function once, return the elapsed total CPU time in
275 Execute a function once, return the elapsed total CPU time in
276 seconds. This is just the first value in timings_out()."""
276 seconds. This is just the first value in timings_out()."""
277
277
278 return timings_out(1,func,*args,**kw)[0]
278 return timings_out(1,func,*args,**kw)[0]
279
279
280 #****************************************************************************
280 #****************************************************************************
281 # file and system
281 # file and system
282
282
283 def arg_split(s,posix=False):
283 def arg_split(s,posix=False):
284 """Split a command line's arguments in a shell-like manner.
284 """Split a command line's arguments in a shell-like manner.
285
285
286 This is a modified version of the standard library's shlex.split()
286 This is a modified version of the standard library's shlex.split()
287 function, but with a default of posix=False for splitting, so that quotes
287 function, but with a default of posix=False for splitting, so that quotes
288 in inputs are respected."""
288 in inputs are respected."""
289
289
290 # XXX - there may be unicode-related problems here!!! I'm not sure that
290 # XXX - there may be unicode-related problems here!!! I'm not sure that
291 # shlex is truly unicode-safe, so it might be necessary to do
291 # shlex is truly unicode-safe, so it might be necessary to do
292 #
292 #
293 # s = s.encode(sys.stdin.encoding)
293 # s = s.encode(sys.stdin.encoding)
294 #
294 #
295 # first, to ensure that shlex gets a normal string. Input from anyone who
295 # first, to ensure that shlex gets a normal string. Input from anyone who
296 # knows more about unicode and shlex than I would be good to have here...
296 # knows more about unicode and shlex than I would be good to have here...
297 lex = shlex.shlex(s, posix=posix)
297 lex = shlex.shlex(s, posix=posix)
298 lex.whitespace_split = True
298 lex.whitespace_split = True
299 return list(lex)
299 return list(lex)
300
300
301 def system(cmd,verbose=0,debug=0,header=''):
301 def system(cmd,verbose=0,debug=0,header=''):
302 """Execute a system command, return its exit status.
302 """Execute a system command, return its exit status.
303
303
304 Options:
304 Options:
305
305
306 - verbose (0): print the command to be executed.
306 - verbose (0): print the command to be executed.
307
307
308 - debug (0): only print, do not actually execute.
308 - debug (0): only print, do not actually execute.
309
309
310 - header (''): Header to print on screen prior to the executed command (it
310 - header (''): Header to print on screen prior to the executed command (it
311 is only prepended to the command, no newlines are added).
311 is only prepended to the command, no newlines are added).
312
312
313 Note: a stateful version of this function is available through the
313 Note: a stateful version of this function is available through the
314 SystemExec class."""
314 SystemExec class."""
315
315
316 stat = 0
316 stat = 0
317 if verbose or debug: print header+cmd
317 if verbose or debug: print header+cmd
318 sys.stdout.flush()
318 sys.stdout.flush()
319 if not debug: stat = os.system(cmd)
319 if not debug: stat = os.system(cmd)
320 return stat
320 return stat
321
321
322 def abbrev_cwd():
322 def abbrev_cwd():
323 """ Return abbreviated version of cwd, e.g. d:mydir """
323 """ Return abbreviated version of cwd, e.g. d:mydir """
324 cwd = os.getcwd().replace('\\','/')
324 cwd = os.getcwd().replace('\\','/')
325 drivepart = ''
325 drivepart = ''
326 tail = cwd
326 tail = cwd
327 if sys.platform == 'win32':
327 if sys.platform == 'win32':
328 if len(cwd) < 4:
328 if len(cwd) < 4:
329 return cwd
329 return cwd
330 drivepart,tail = os.path.splitdrive(cwd)
330 drivepart,tail = os.path.splitdrive(cwd)
331
331
332
332
333 parts = tail.split('/')
333 parts = tail.split('/')
334 if len(parts) > 2:
334 if len(parts) > 2:
335 tail = '/'.join(parts[-2:])
335 tail = '/'.join(parts[-2:])
336
336
337 return (drivepart + (
337 return (drivepart + (
338 cwd == '/' and '/' or tail))
338 cwd == '/' and '/' or tail))
339
339
340
340
341 # This function is used by ipython in a lot of places to make system calls.
341 # This function is used by ipython in a lot of places to make system calls.
342 # We need it to be slightly different under win32, due to the vagaries of
342 # We need it to be slightly different under win32, due to the vagaries of
343 # 'network shares'. A win32 override is below.
343 # 'network shares'. A win32 override is below.
344
344
345 def shell(cmd,verbose=0,debug=0,header=''):
345 def shell(cmd,verbose=0,debug=0,header=''):
346 """Execute a command in the system shell, always return None.
346 """Execute a command in the system shell, always return None.
347
347
348 Options:
348 Options:
349
349
350 - verbose (0): print the command to be executed.
350 - verbose (0): print the command to be executed.
351
351
352 - debug (0): only print, do not actually execute.
352 - debug (0): only print, do not actually execute.
353
353
354 - header (''): Header to print on screen prior to the executed command (it
354 - header (''): Header to print on screen prior to the executed command (it
355 is only prepended to the command, no newlines are added).
355 is only prepended to the command, no newlines are added).
356
356
357 Note: this is similar to genutils.system(), but it returns None so it can
357 Note: this is similar to genutils.system(), but it returns None so it can
358 be conveniently used in interactive loops without getting the return value
358 be conveniently used in interactive loops without getting the return value
359 (typically 0) printed many times."""
359 (typically 0) printed many times."""
360
360
361 stat = 0
361 stat = 0
362 if verbose or debug: print header+cmd
362 if verbose or debug: print header+cmd
363 # flush stdout so we don't mangle python's buffering
363 # flush stdout so we don't mangle python's buffering
364 sys.stdout.flush()
364 sys.stdout.flush()
365
365
366 if not debug:
366 if not debug:
367 platutils.set_term_title("IPy " + cmd)
367 platutils.set_term_title("IPy " + cmd)
368 os.system(cmd)
368 os.system(cmd)
369 platutils.set_term_title("IPy " + abbrev_cwd())
369 platutils.set_term_title("IPy " + abbrev_cwd())
370
370
371 # override shell() for win32 to deal with network shares
371 # override shell() for win32 to deal with network shares
372 if os.name in ('nt','dos'):
372 if os.name in ('nt','dos'):
373
373
374 shell_ori = shell
374 shell_ori = shell
375
375
376 def shell(cmd,verbose=0,debug=0,header=''):
376 def shell(cmd,verbose=0,debug=0,header=''):
377 if os.getcwd().startswith(r"\\"):
377 if os.getcwd().startswith(r"\\"):
378 path = os.getcwd()
378 path = os.getcwd()
379 # change to c drive (cannot be on UNC-share when issuing os.system,
379 # change to c drive (cannot be on UNC-share when issuing os.system,
380 # as cmd.exe cannot handle UNC addresses)
380 # as cmd.exe cannot handle UNC addresses)
381 os.chdir("c:")
381 os.chdir("c:")
382 # issue pushd to the UNC-share and then run the command
382 # issue pushd to the UNC-share and then run the command
383 try:
383 try:
384 shell_ori('"pushd %s&&"'%path+cmd,verbose,debug,header)
384 shell_ori('"pushd %s&&"'%path+cmd,verbose,debug,header)
385 finally:
385 finally:
386 os.chdir(path)
386 os.chdir(path)
387 else:
387 else:
388 shell_ori(cmd,verbose,debug,header)
388 shell_ori(cmd,verbose,debug,header)
389
389
390 shell.__doc__ = shell_ori.__doc__
390 shell.__doc__ = shell_ori.__doc__
391
391
392 def getoutput(cmd,verbose=0,debug=0,header='',split=0):
392 def getoutput(cmd,verbose=0,debug=0,header='',split=0):
393 """Dummy substitute for perl's backquotes.
393 """Dummy substitute for perl's backquotes.
394
394
395 Executes a command and returns the output.
395 Executes a command and returns the output.
396
396
397 Accepts the same arguments as system(), plus:
397 Accepts the same arguments as system(), plus:
398
398
399 - split(0): if true, the output is returned as a list split on newlines.
399 - split(0): if true, the output is returned as a list split on newlines.
400
400
401 Note: a stateful version of this function is available through the
401 Note: a stateful version of this function is available through the
402 SystemExec class.
402 SystemExec class.
403
403
404 This is pretty much deprecated and rarely used,
404 This is pretty much deprecated and rarely used,
405 genutils.getoutputerror may be what you need.
405 genutils.getoutputerror may be what you need.
406
406
407 """
407 """
408
408
409 if verbose or debug: print header+cmd
409 if verbose or debug: print header+cmd
410 if not debug:
410 if not debug:
411 output = os.popen(cmd).read()
411 output = os.popen(cmd).read()
412 # stipping last \n is here for backwards compat.
412 # stipping last \n is here for backwards compat.
413 if output.endswith('\n'):
413 if output.endswith('\n'):
414 output = output[:-1]
414 output = output[:-1]
415 if split:
415 if split:
416 return output.split('\n')
416 return output.split('\n')
417 else:
417 else:
418 return output
418 return output
419
419
420 def getoutputerror(cmd,verbose=0,debug=0,header='',split=0):
420 def getoutputerror(cmd,verbose=0,debug=0,header='',split=0):
421 """Return (standard output,standard error) of executing cmd in a shell.
421 """Return (standard output,standard error) of executing cmd in a shell.
422
422
423 Accepts the same arguments as system(), plus:
423 Accepts the same arguments as system(), plus:
424
424
425 - split(0): if true, each of stdout/err is returned as a list split on
425 - split(0): if true, each of stdout/err is returned as a list split on
426 newlines.
426 newlines.
427
427
428 Note: a stateful version of this function is available through the
428 Note: a stateful version of this function is available through the
429 SystemExec class."""
429 SystemExec class."""
430
430
431 if verbose or debug: print header+cmd
431 if verbose or debug: print header+cmd
432 if not cmd:
432 if not cmd:
433 if split:
433 if split:
434 return [],[]
434 return [],[]
435 else:
435 else:
436 return '',''
436 return '',''
437 if not debug:
437 if not debug:
438 pin,pout,perr = os.popen3(cmd)
438 pin,pout,perr = os.popen3(cmd)
439 tout = pout.read().rstrip()
439 tout = pout.read().rstrip()
440 terr = perr.read().rstrip()
440 terr = perr.read().rstrip()
441 pin.close()
441 pin.close()
442 pout.close()
442 pout.close()
443 perr.close()
443 perr.close()
444 if split:
444 if split:
445 return tout.split('\n'),terr.split('\n')
445 return tout.split('\n'),terr.split('\n')
446 else:
446 else:
447 return tout,terr
447 return tout,terr
448
448
449 # for compatibility with older naming conventions
449 # for compatibility with older naming conventions
450 xsys = system
450 xsys = system
451 bq = getoutput
451 bq = getoutput
452
452
453 class SystemExec:
453 class SystemExec:
454 """Access the system and getoutput functions through a stateful interface.
454 """Access the system and getoutput functions through a stateful interface.
455
455
456 Note: here we refer to the system and getoutput functions from this
456 Note: here we refer to the system and getoutput functions from this
457 library, not the ones from the standard python library.
457 library, not the ones from the standard python library.
458
458
459 This class offers the system and getoutput functions as methods, but the
459 This class offers the system and getoutput functions as methods, but the
460 verbose, debug and header parameters can be set for the instance (at
460 verbose, debug and header parameters can be set for the instance (at
461 creation time or later) so that they don't need to be specified on each
461 creation time or later) so that they don't need to be specified on each
462 call.
462 call.
463
463
464 For efficiency reasons, there's no way to override the parameters on a
464 For efficiency reasons, there's no way to override the parameters on a
465 per-call basis other than by setting instance attributes. If you need
465 per-call basis other than by setting instance attributes. If you need
466 local overrides, it's best to directly call system() or getoutput().
466 local overrides, it's best to directly call system() or getoutput().
467
467
468 The following names are provided as alternate options:
468 The following names are provided as alternate options:
469 - xsys: alias to system
469 - xsys: alias to system
470 - bq: alias to getoutput
470 - bq: alias to getoutput
471
471
472 An instance can then be created as:
472 An instance can then be created as:
473 >>> sysexec = SystemExec(verbose=1,debug=0,header='Calling: ')
473 >>> sysexec = SystemExec(verbose=1,debug=0,header='Calling: ')
474 """
474 """
475
475
476 def __init__(self,verbose=0,debug=0,header='',split=0):
476 def __init__(self,verbose=0,debug=0,header='',split=0):
477 """Specify the instance's values for verbose, debug and header."""
477 """Specify the instance's values for verbose, debug and header."""
478 setattr_list(self,'verbose debug header split')
478 setattr_list(self,'verbose debug header split')
479
479
480 def system(self,cmd):
480 def system(self,cmd):
481 """Stateful interface to system(), with the same keyword parameters."""
481 """Stateful interface to system(), with the same keyword parameters."""
482
482
483 system(cmd,self.verbose,self.debug,self.header)
483 system(cmd,self.verbose,self.debug,self.header)
484
484
485 def shell(self,cmd):
485 def shell(self,cmd):
486 """Stateful interface to shell(), with the same keyword parameters."""
486 """Stateful interface to shell(), with the same keyword parameters."""
487
487
488 shell(cmd,self.verbose,self.debug,self.header)
488 shell(cmd,self.verbose,self.debug,self.header)
489
489
490 xsys = system # alias
490 xsys = system # alias
491
491
492 def getoutput(self,cmd):
492 def getoutput(self,cmd):
493 """Stateful interface to getoutput()."""
493 """Stateful interface to getoutput()."""
494
494
495 return getoutput(cmd,self.verbose,self.debug,self.header,self.split)
495 return getoutput(cmd,self.verbose,self.debug,self.header,self.split)
496
496
497 def getoutputerror(self,cmd):
497 def getoutputerror(self,cmd):
498 """Stateful interface to getoutputerror()."""
498 """Stateful interface to getoutputerror()."""
499
499
500 return getoutputerror(cmd,self.verbose,self.debug,self.header,self.split)
500 return getoutputerror(cmd,self.verbose,self.debug,self.header,self.split)
501
501
502 bq = getoutput # alias
502 bq = getoutput # alias
503
503
504 #-----------------------------------------------------------------------------
504 #-----------------------------------------------------------------------------
505 def mutex_opts(dict,ex_op):
505 def mutex_opts(dict,ex_op):
506 """Check for presence of mutually exclusive keys in a dict.
506 """Check for presence of mutually exclusive keys in a dict.
507
507
508 Call: mutex_opts(dict,[[op1a,op1b],[op2a,op2b]...]"""
508 Call: mutex_opts(dict,[[op1a,op1b],[op2a,op2b]...]"""
509 for op1,op2 in ex_op:
509 for op1,op2 in ex_op:
510 if op1 in dict and op2 in dict:
510 if op1 in dict and op2 in dict:
511 raise ValueError,'\n*** ERROR in Arguments *** '\
511 raise ValueError,'\n*** ERROR in Arguments *** '\
512 'Options '+op1+' and '+op2+' are mutually exclusive.'
512 'Options '+op1+' and '+op2+' are mutually exclusive.'
513
513
514 #-----------------------------------------------------------------------------
514 #-----------------------------------------------------------------------------
515 def get_py_filename(name):
515 def get_py_filename(name):
516 """Return a valid python filename in the current directory.
516 """Return a valid python filename in the current directory.
517
517
518 If the given name is not a file, it adds '.py' and searches again.
518 If the given name is not a file, it adds '.py' and searches again.
519 Raises IOError with an informative message if the file isn't found."""
519 Raises IOError with an informative message if the file isn't found."""
520
520
521 name = os.path.expanduser(name)
521 name = os.path.expanduser(name)
522 if not os.path.isfile(name) and not name.endswith('.py'):
522 if not os.path.isfile(name) and not name.endswith('.py'):
523 name += '.py'
523 name += '.py'
524 if os.path.isfile(name):
524 if os.path.isfile(name):
525 return name
525 return name
526 else:
526 else:
527 raise IOError,'File `%s` not found.' % name
527 raise IOError,'File `%s` not found.' % name
528
528
529 #-----------------------------------------------------------------------------
529 #-----------------------------------------------------------------------------
530 def filefind(fname,alt_dirs = None):
530 def filefind(fname,alt_dirs = None):
531 """Return the given filename either in the current directory, if it
531 """Return the given filename either in the current directory, if it
532 exists, or in a specified list of directories.
532 exists, or in a specified list of directories.
533
533
534 ~ expansion is done on all file and directory names.
534 ~ expansion is done on all file and directory names.
535
535
536 Upon an unsuccessful search, raise an IOError exception."""
536 Upon an unsuccessful search, raise an IOError exception."""
537
537
538 if alt_dirs is None:
538 if alt_dirs is None:
539 try:
539 try:
540 alt_dirs = get_home_dir()
540 alt_dirs = get_home_dir()
541 except HomeDirError:
541 except HomeDirError:
542 alt_dirs = os.getcwd()
542 alt_dirs = os.getcwd()
543 search = [fname] + list_strings(alt_dirs)
543 search = [fname] + list_strings(alt_dirs)
544 search = map(os.path.expanduser,search)
544 search = map(os.path.expanduser,search)
545 #print 'search list for',fname,'list:',search # dbg
545 #print 'search list for',fname,'list:',search # dbg
546 fname = search[0]
546 fname = search[0]
547 if os.path.isfile(fname):
547 if os.path.isfile(fname):
548 return fname
548 return fname
549 for direc in search[1:]:
549 for direc in search[1:]:
550 testname = os.path.join(direc,fname)
550 testname = os.path.join(direc,fname)
551 #print 'testname',testname # dbg
551 #print 'testname',testname # dbg
552 if os.path.isfile(testname):
552 if os.path.isfile(testname):
553 return testname
553 return testname
554 raise IOError,'File' + `fname` + \
554 raise IOError,'File' + `fname` + \
555 ' not found in current or supplied directories:' + `alt_dirs`
555 ' not found in current or supplied directories:' + `alt_dirs`
556
556
557 #----------------------------------------------------------------------------
557 #----------------------------------------------------------------------------
558 def file_read(filename):
558 def file_read(filename):
559 """Read a file and close it. Returns the file source."""
559 """Read a file and close it. Returns the file source."""
560 fobj = open(filename,'r');
560 fobj = open(filename,'r');
561 source = fobj.read();
561 source = fobj.read();
562 fobj.close()
562 fobj.close()
563 return source
563 return source
564
564
565 def file_readlines(filename):
565 def file_readlines(filename):
566 """Read a file and close it. Returns the file source using readlines()."""
566 """Read a file and close it. Returns the file source using readlines()."""
567 fobj = open(filename,'r');
567 fobj = open(filename,'r');
568 lines = fobj.readlines();
568 lines = fobj.readlines();
569 fobj.close()
569 fobj.close()
570 return lines
570 return lines
571
571
572 #----------------------------------------------------------------------------
572 #----------------------------------------------------------------------------
573 def target_outdated(target,deps):
573 def target_outdated(target,deps):
574 """Determine whether a target is out of date.
574 """Determine whether a target is out of date.
575
575
576 target_outdated(target,deps) -> 1/0
576 target_outdated(target,deps) -> 1/0
577
577
578 deps: list of filenames which MUST exist.
578 deps: list of filenames which MUST exist.
579 target: single filename which may or may not exist.
579 target: single filename which may or may not exist.
580
580
581 If target doesn't exist or is older than any file listed in deps, return
581 If target doesn't exist or is older than any file listed in deps, return
582 true, otherwise return false.
582 true, otherwise return false.
583 """
583 """
584 try:
584 try:
585 target_time = os.path.getmtime(target)
585 target_time = os.path.getmtime(target)
586 except os.error:
586 except os.error:
587 return 1
587 return 1
588 for dep in deps:
588 for dep in deps:
589 dep_time = os.path.getmtime(dep)
589 dep_time = os.path.getmtime(dep)
590 if dep_time > target_time:
590 if dep_time > target_time:
591 #print "For target",target,"Dep failed:",dep # dbg
591 #print "For target",target,"Dep failed:",dep # dbg
592 #print "times (dep,tar):",dep_time,target_time # dbg
592 #print "times (dep,tar):",dep_time,target_time # dbg
593 return 1
593 return 1
594 return 0
594 return 0
595
595
596 #-----------------------------------------------------------------------------
596 #-----------------------------------------------------------------------------
597 def target_update(target,deps,cmd):
597 def target_update(target,deps,cmd):
598 """Update a target with a given command given a list of dependencies.
598 """Update a target with a given command given a list of dependencies.
599
599
600 target_update(target,deps,cmd) -> runs cmd if target is outdated.
600 target_update(target,deps,cmd) -> runs cmd if target is outdated.
601
601
602 This is just a wrapper around target_outdated() which calls the given
602 This is just a wrapper around target_outdated() which calls the given
603 command if target is outdated."""
603 command if target is outdated."""
604
604
605 if target_outdated(target,deps):
605 if target_outdated(target,deps):
606 xsys(cmd)
606 xsys(cmd)
607
607
608 #----------------------------------------------------------------------------
608 #----------------------------------------------------------------------------
609 def unquote_ends(istr):
609 def unquote_ends(istr):
610 """Remove a single pair of quotes from the endpoints of a string."""
610 """Remove a single pair of quotes from the endpoints of a string."""
611
611
612 if not istr:
612 if not istr:
613 return istr
613 return istr
614 if (istr[0]=="'" and istr[-1]=="'") or \
614 if (istr[0]=="'" and istr[-1]=="'") or \
615 (istr[0]=='"' and istr[-1]=='"'):
615 (istr[0]=='"' and istr[-1]=='"'):
616 return istr[1:-1]
616 return istr[1:-1]
617 else:
617 else:
618 return istr
618 return istr
619
619
620 #----------------------------------------------------------------------------
620 #----------------------------------------------------------------------------
621 def process_cmdline(argv,names=[],defaults={},usage=''):
621 def process_cmdline(argv,names=[],defaults={},usage=''):
622 """ Process command-line options and arguments.
622 """ Process command-line options and arguments.
623
623
624 Arguments:
624 Arguments:
625
625
626 - argv: list of arguments, typically sys.argv.
626 - argv: list of arguments, typically sys.argv.
627
627
628 - names: list of option names. See DPyGetOpt docs for details on options
628 - names: list of option names. See DPyGetOpt docs for details on options
629 syntax.
629 syntax.
630
630
631 - defaults: dict of default values.
631 - defaults: dict of default values.
632
632
633 - usage: optional usage notice to print if a wrong argument is passed.
633 - usage: optional usage notice to print if a wrong argument is passed.
634
634
635 Return a dict of options and a list of free arguments."""
635 Return a dict of options and a list of free arguments."""
636
636
637 getopt = DPyGetOpt.DPyGetOpt()
637 getopt = DPyGetOpt.DPyGetOpt()
638 getopt.setIgnoreCase(0)
638 getopt.setIgnoreCase(0)
639 getopt.parseConfiguration(names)
639 getopt.parseConfiguration(names)
640
640
641 try:
641 try:
642 getopt.processArguments(argv)
642 getopt.processArguments(argv)
643 except DPyGetOpt.ArgumentError, exc:
643 except DPyGetOpt.ArgumentError, exc:
644 print usage
644 print usage
645 warn('"%s"' % exc,level=4)
645 warn('"%s"' % exc,level=4)
646
646
647 defaults.update(getopt.optionValues)
647 defaults.update(getopt.optionValues)
648 args = getopt.freeValues
648 args = getopt.freeValues
649
649
650 return defaults,args
650 return defaults,args
651
651
652 #----------------------------------------------------------------------------
652 #----------------------------------------------------------------------------
653 def optstr2types(ostr):
653 def optstr2types(ostr):
654 """Convert a string of option names to a dict of type mappings.
654 """Convert a string of option names to a dict of type mappings.
655
655
656 optstr2types(str) -> {None:'string_opts',int:'int_opts',float:'float_opts'}
656 optstr2types(str) -> {None:'string_opts',int:'int_opts',float:'float_opts'}
657
657
658 This is used to get the types of all the options in a string formatted
658 This is used to get the types of all the options in a string formatted
659 with the conventions of DPyGetOpt. The 'type' None is used for options
659 with the conventions of DPyGetOpt. The 'type' None is used for options
660 which are strings (they need no further conversion). This function's main
660 which are strings (they need no further conversion). This function's main
661 use is to get a typemap for use with read_dict().
661 use is to get a typemap for use with read_dict().
662 """
662 """
663
663
664 typeconv = {None:'',int:'',float:''}
664 typeconv = {None:'',int:'',float:''}
665 typemap = {'s':None,'i':int,'f':float}
665 typemap = {'s':None,'i':int,'f':float}
666 opt_re = re.compile(r'([\w]*)([^:=]*:?=?)([sif]?)')
666 opt_re = re.compile(r'([\w]*)([^:=]*:?=?)([sif]?)')
667
667
668 for w in ostr.split():
668 for w in ostr.split():
669 oname,alias,otype = opt_re.match(w).groups()
669 oname,alias,otype = opt_re.match(w).groups()
670 if otype == '' or alias == '!': # simple switches are integers too
670 if otype == '' or alias == '!': # simple switches are integers too
671 otype = 'i'
671 otype = 'i'
672 typeconv[typemap[otype]] += oname + ' '
672 typeconv[typemap[otype]] += oname + ' '
673 return typeconv
673 return typeconv
674
674
675 #----------------------------------------------------------------------------
675 #----------------------------------------------------------------------------
676 def read_dict(filename,type_conv=None,**opt):
676 def read_dict(filename,type_conv=None,**opt):
677 r"""Read a dictionary of key=value pairs from an input file, optionally
677 r"""Read a dictionary of key=value pairs from an input file, optionally
678 performing conversions on the resulting values.
678 performing conversions on the resulting values.
679
679
680 read_dict(filename,type_conv,**opt) -> dict
680 read_dict(filename,type_conv,**opt) -> dict
681
681
682 Only one value per line is accepted, the format should be
682 Only one value per line is accepted, the format should be
683 # optional comments are ignored
683 # optional comments are ignored
684 key value\n
684 key value\n
685
685
686 Args:
686 Args:
687
687
688 - type_conv: A dictionary specifying which keys need to be converted to
688 - type_conv: A dictionary specifying which keys need to be converted to
689 which types. By default all keys are read as strings. This dictionary
689 which types. By default all keys are read as strings. This dictionary
690 should have as its keys valid conversion functions for strings
690 should have as its keys valid conversion functions for strings
691 (int,long,float,complex, or your own). The value for each key
691 (int,long,float,complex, or your own). The value for each key
692 (converter) should be a whitespace separated string containing the names
692 (converter) should be a whitespace separated string containing the names
693 of all the entries in the file to be converted using that function. For
693 of all the entries in the file to be converted using that function. For
694 keys to be left alone, use None as the conversion function (only needed
694 keys to be left alone, use None as the conversion function (only needed
695 with purge=1, see below).
695 with purge=1, see below).
696
696
697 - opt: dictionary with extra options as below (default in parens)
697 - opt: dictionary with extra options as below (default in parens)
698
698
699 purge(0): if set to 1, all keys *not* listed in type_conv are purged out
699 purge(0): if set to 1, all keys *not* listed in type_conv are purged out
700 of the dictionary to be returned. If purge is going to be used, the
700 of the dictionary to be returned. If purge is going to be used, the
701 set of keys to be left as strings also has to be explicitly specified
701 set of keys to be left as strings also has to be explicitly specified
702 using the (non-existent) conversion function None.
702 using the (non-existent) conversion function None.
703
703
704 fs(None): field separator. This is the key/value separator to be used
704 fs(None): field separator. This is the key/value separator to be used
705 when parsing the file. The None default means any whitespace [behavior
705 when parsing the file. The None default means any whitespace [behavior
706 of string.split()].
706 of string.split()].
707
707
708 strip(0): if 1, strip string values of leading/trailinig whitespace.
708 strip(0): if 1, strip string values of leading/trailinig whitespace.
709
709
710 warn(1): warning level if requested keys are not found in file.
710 warn(1): warning level if requested keys are not found in file.
711 - 0: silently ignore.
711 - 0: silently ignore.
712 - 1: inform but proceed.
712 - 1: inform but proceed.
713 - 2: raise KeyError exception.
713 - 2: raise KeyError exception.
714
714
715 no_empty(0): if 1, remove keys with whitespace strings as a value.
715 no_empty(0): if 1, remove keys with whitespace strings as a value.
716
716
717 unique([]): list of keys (or space separated string) which can't be
717 unique([]): list of keys (or space separated string) which can't be
718 repeated. If one such key is found in the file, each new instance
718 repeated. If one such key is found in the file, each new instance
719 overwrites the previous one. For keys not listed here, the behavior is
719 overwrites the previous one. For keys not listed here, the behavior is
720 to make a list of all appearances.
720 to make a list of all appearances.
721
721
722 Example:
722 Example:
723
723
724 If the input file test.ini contains (we put it in a string to keep the test
724 If the input file test.ini contains (we put it in a string to keep the test
725 self-contained):
725 self-contained):
726
726
727 >>> test_ini = '''\
727 >>> test_ini = '''\
728 ... i 3
728 ... i 3
729 ... x 4.5
729 ... x 4.5
730 ... y 5.5
730 ... y 5.5
731 ... s hi ho'''
731 ... s hi ho'''
732
732
733 Then we can use it as follows:
733 Then we can use it as follows:
734 >>> type_conv={int:'i',float:'x',None:'s'}
734 >>> type_conv={int:'i',float:'x',None:'s'}
735
735
736 >>> d = read_dict(test_ini)
736 >>> d = read_dict(test_ini)
737
737
738 >>> sorted(d.items())
738 >>> sorted(d.items())
739 [('i', '3'), ('s', 'hi ho'), ('x', '4.5'), ('y', '5.5')]
739 [('i', '3'), ('s', 'hi ho'), ('x', '4.5'), ('y', '5.5')]
740
740
741 >>> d = read_dict(test_ini,type_conv)
741 >>> d = read_dict(test_ini,type_conv)
742
742
743 >>> sorted(d.items())
743 >>> sorted(d.items())
744 [('i', 3), ('s', 'hi ho'), ('x', 4.5), ('y', '5.5')]
744 [('i', 3), ('s', 'hi ho'), ('x', 4.5), ('y', '5.5')]
745
745
746 >>> d = read_dict(test_ini,type_conv,purge=True)
746 >>> d = read_dict(test_ini,type_conv,purge=True)
747
747
748 >>> sorted(d.items())
748 >>> sorted(d.items())
749 [('i', 3), ('s', 'hi ho'), ('x', 4.5)]
749 [('i', 3), ('s', 'hi ho'), ('x', 4.5)]
750 """
750 """
751
751
752 # starting config
752 # starting config
753 opt.setdefault('purge',0)
753 opt.setdefault('purge',0)
754 opt.setdefault('fs',None) # field sep defaults to any whitespace
754 opt.setdefault('fs',None) # field sep defaults to any whitespace
755 opt.setdefault('strip',0)
755 opt.setdefault('strip',0)
756 opt.setdefault('warn',1)
756 opt.setdefault('warn',1)
757 opt.setdefault('no_empty',0)
757 opt.setdefault('no_empty',0)
758 opt.setdefault('unique','')
758 opt.setdefault('unique','')
759 if type(opt['unique']) in StringTypes:
759 if type(opt['unique']) in StringTypes:
760 unique_keys = qw(opt['unique'])
760 unique_keys = qw(opt['unique'])
761 elif type(opt['unique']) in (types.TupleType,types.ListType):
761 elif type(opt['unique']) in (types.TupleType,types.ListType):
762 unique_keys = opt['unique']
762 unique_keys = opt['unique']
763 else:
763 else:
764 raise ValueError, 'Unique keys must be given as a string, List or Tuple'
764 raise ValueError, 'Unique keys must be given as a string, List or Tuple'
765
765
766 dict = {}
766 dict = {}
767
767
768 # first read in table of values as strings
768 # first read in table of values as strings
769 if '\n' in filename:
769 if '\n' in filename:
770 lines = filename.splitlines()
770 lines = filename.splitlines()
771 file = None
771 file = None
772 else:
772 else:
773 file = open(filename,'r')
773 file = open(filename,'r')
774 lines = file.readlines()
774 lines = file.readlines()
775 for line in lines:
775 for line in lines:
776 line = line.strip()
776 line = line.strip()
777 if len(line) and line[0]=='#': continue
777 if len(line) and line[0]=='#': continue
778 if len(line)>0:
778 if len(line)>0:
779 lsplit = line.split(opt['fs'],1)
779 lsplit = line.split(opt['fs'],1)
780 try:
780 try:
781 key,val = lsplit
781 key,val = lsplit
782 except ValueError:
782 except ValueError:
783 key,val = lsplit[0],''
783 key,val = lsplit[0],''
784 key = key.strip()
784 key = key.strip()
785 if opt['strip']: val = val.strip()
785 if opt['strip']: val = val.strip()
786 if val == "''" or val == '""': val = ''
786 if val == "''" or val == '""': val = ''
787 if opt['no_empty'] and (val=='' or val.isspace()):
787 if opt['no_empty'] and (val=='' or val.isspace()):
788 continue
788 continue
789 # if a key is found more than once in the file, build a list
789 # if a key is found more than once in the file, build a list
790 # unless it's in the 'unique' list. In that case, last found in file
790 # unless it's in the 'unique' list. In that case, last found in file
791 # takes precedence. User beware.
791 # takes precedence. User beware.
792 try:
792 try:
793 if dict[key] and key in unique_keys:
793 if dict[key] and key in unique_keys:
794 dict[key] = val
794 dict[key] = val
795 elif type(dict[key]) is types.ListType:
795 elif type(dict[key]) is types.ListType:
796 dict[key].append(val)
796 dict[key].append(val)
797 else:
797 else:
798 dict[key] = [dict[key],val]
798 dict[key] = [dict[key],val]
799 except KeyError:
799 except KeyError:
800 dict[key] = val
800 dict[key] = val
801 # purge if requested
801 # purge if requested
802 if opt['purge']:
802 if opt['purge']:
803 accepted_keys = qwflat(type_conv.values())
803 accepted_keys = qwflat(type_conv.values())
804 for key in dict.keys():
804 for key in dict.keys():
805 if key in accepted_keys: continue
805 if key in accepted_keys: continue
806 del(dict[key])
806 del(dict[key])
807 # now convert if requested
807 # now convert if requested
808 if type_conv==None: return dict
808 if type_conv==None: return dict
809 conversions = type_conv.keys()
809 conversions = type_conv.keys()
810 try: conversions.remove(None)
810 try: conversions.remove(None)
811 except: pass
811 except: pass
812 for convert in conversions:
812 for convert in conversions:
813 for val in qw(type_conv[convert]):
813 for val in qw(type_conv[convert]):
814 try:
814 try:
815 dict[val] = convert(dict[val])
815 dict[val] = convert(dict[val])
816 except KeyError,e:
816 except KeyError,e:
817 if opt['warn'] == 0:
817 if opt['warn'] == 0:
818 pass
818 pass
819 elif opt['warn'] == 1:
819 elif opt['warn'] == 1:
820 print >>sys.stderr, 'Warning: key',val,\
820 print >>sys.stderr, 'Warning: key',val,\
821 'not found in file',filename
821 'not found in file',filename
822 elif opt['warn'] == 2:
822 elif opt['warn'] == 2:
823 raise KeyError,e
823 raise KeyError,e
824 else:
824 else:
825 raise ValueError,'Warning level must be 0,1 or 2'
825 raise ValueError,'Warning level must be 0,1 or 2'
826
826
827 return dict
827 return dict
828
828
829 #----------------------------------------------------------------------------
829 #----------------------------------------------------------------------------
830 def flag_calls(func):
830 def flag_calls(func):
831 """Wrap a function to detect and flag when it gets called.
831 """Wrap a function to detect and flag when it gets called.
832
832
833 This is a decorator which takes a function and wraps it in a function with
833 This is a decorator which takes a function and wraps it in a function with
834 a 'called' attribute. wrapper.called is initialized to False.
834 a 'called' attribute. wrapper.called is initialized to False.
835
835
836 The wrapper.called attribute is set to False right before each call to the
836 The wrapper.called attribute is set to False right before each call to the
837 wrapped function, so if the call fails it remains False. After the call
837 wrapped function, so if the call fails it remains False. After the call
838 completes, wrapper.called is set to True and the output is returned.
838 completes, wrapper.called is set to True and the output is returned.
839
839
840 Testing for truth in wrapper.called allows you to determine if a call to
840 Testing for truth in wrapper.called allows you to determine if a call to
841 func() was attempted and succeeded."""
841 func() was attempted and succeeded."""
842
842
843 def wrapper(*args,**kw):
843 def wrapper(*args,**kw):
844 wrapper.called = False
844 wrapper.called = False
845 out = func(*args,**kw)
845 out = func(*args,**kw)
846 wrapper.called = True
846 wrapper.called = True
847 return out
847 return out
848
848
849 wrapper.called = False
849 wrapper.called = False
850 wrapper.__doc__ = func.__doc__
850 wrapper.__doc__ = func.__doc__
851 return wrapper
851 return wrapper
852
852
853 #----------------------------------------------------------------------------
853 #----------------------------------------------------------------------------
854 def dhook_wrap(func,*a,**k):
854 def dhook_wrap(func,*a,**k):
855 """Wrap a function call in a sys.displayhook controller.
855 """Wrap a function call in a sys.displayhook controller.
856
856
857 Returns a wrapper around func which calls func, with all its arguments and
857 Returns a wrapper around func which calls func, with all its arguments and
858 keywords unmodified, using the default sys.displayhook. Since IPython
858 keywords unmodified, using the default sys.displayhook. Since IPython
859 modifies sys.displayhook, it breaks the behavior of certain systems that
859 modifies sys.displayhook, it breaks the behavior of certain systems that
860 rely on the default behavior, notably doctest.
860 rely on the default behavior, notably doctest.
861 """
861 """
862
862
863 def f(*a,**k):
863 def f(*a,**k):
864
864
865 dhook_s = sys.displayhook
865 dhook_s = sys.displayhook
866 sys.displayhook = sys.__displayhook__
866 sys.displayhook = sys.__displayhook__
867 try:
867 try:
868 out = func(*a,**k)
868 out = func(*a,**k)
869 finally:
869 finally:
870 sys.displayhook = dhook_s
870 sys.displayhook = dhook_s
871
871
872 return out
872 return out
873
873
874 f.__doc__ = func.__doc__
874 f.__doc__ = func.__doc__
875 return f
875 return f
876
876
877 #----------------------------------------------------------------------------
877 #----------------------------------------------------------------------------
878 def doctest_reload():
878 def doctest_reload():
879 """Properly reload doctest to reuse it interactively.
879 """Properly reload doctest to reuse it interactively.
880
880
881 This routine:
881 This routine:
882
882
883 - reloads doctest
883 - reloads doctest
884
884
885 - resets its global 'master' attribute to None, so that multiple uses of
885 - resets its global 'master' attribute to None, so that multiple uses of
886 the module interactively don't produce cumulative reports.
886 the module interactively don't produce cumulative reports.
887
887
888 - Monkeypatches its core test runner method to protect it from IPython's
888 - Monkeypatches its core test runner method to protect it from IPython's
889 modified displayhook. Doctest expects the default displayhook behavior
889 modified displayhook. Doctest expects the default displayhook behavior
890 deep down, so our modification breaks it completely. For this reason, a
890 deep down, so our modification breaks it completely. For this reason, a
891 hard monkeypatch seems like a reasonable solution rather than asking
891 hard monkeypatch seems like a reasonable solution rather than asking
892 users to manually use a different doctest runner when under IPython."""
892 users to manually use a different doctest runner when under IPython."""
893
893
894 import doctest
894 import doctest
895 reload(doctest)
895 reload(doctest)
896 doctest.master=None
896 doctest.master=None
897
897
898 try:
898 try:
899 doctest.DocTestRunner
899 doctest.DocTestRunner
900 except AttributeError:
900 except AttributeError:
901 # This is only for python 2.3 compatibility, remove once we move to
901 # This is only for python 2.3 compatibility, remove once we move to
902 # 2.4 only.
902 # 2.4 only.
903 pass
903 pass
904 else:
904 else:
905 doctest.DocTestRunner.run = dhook_wrap(doctest.DocTestRunner.run)
905 doctest.DocTestRunner.run = dhook_wrap(doctest.DocTestRunner.run)
906
906
907 #----------------------------------------------------------------------------
907 #----------------------------------------------------------------------------
908 class HomeDirError(Error):
908 class HomeDirError(Error):
909 pass
909 pass
910
910
911 def get_home_dir():
911 def get_home_dir():
912 """Return the closest possible equivalent to a 'home' directory.
912 """Return the closest possible equivalent to a 'home' directory.
913
913
914 We first try $HOME. Absent that, on NT it's $HOMEDRIVE\$HOMEPATH.
914 We first try $HOME. Absent that, on NT it's $HOMEDRIVE\$HOMEPATH.
915
915
916 Currently only Posix and NT are implemented, a HomeDirError exception is
916 Currently only Posix and NT are implemented, a HomeDirError exception is
917 raised for all other OSes. """
917 raised for all other OSes. """
918
918
919 isdir = os.path.isdir
919 isdir = os.path.isdir
920 env = os.environ
920 env = os.environ
921
921
922 # first, check py2exe distribution root directory for _ipython.
922 # first, check py2exe distribution root directory for _ipython.
923 # This overrides all. Normally does not exist.
923 # This overrides all. Normally does not exist.
924
924
925 if hasattr(sys, "frozen"): #Is frozen by py2exe
925 if hasattr(sys, "frozen"): #Is frozen by py2exe
926 if '\\library.zip\\' in IPython.__file__.lower():#libraries compressed to zip-file
926 if '\\library.zip\\' in IPython.__file__.lower():#libraries compressed to zip-file
927 root, rest = IPython.__file__.lower().split('library.zip')
927 root, rest = IPython.__file__.lower().split('library.zip')
928 else:
928 else:
929 root=os.path.join(os.path.split(IPython.__file__)[0],"../../")
929 root=os.path.join(os.path.split(IPython.__file__)[0],"../../")
930 root=os.path.abspath(root).rstrip('\\')
930 root=os.path.abspath(root).rstrip('\\')
931 if isdir(os.path.join(root, '_ipython')):
931 if isdir(os.path.join(root, '_ipython')):
932 os.environ["IPYKITROOT"] = root
932 os.environ["IPYKITROOT"] = root
933 return root
933 return root
934 try:
934 try:
935 homedir = env['HOME']
935 homedir = env['HOME']
936 if not isdir(homedir):
936 if not isdir(homedir):
937 # in case a user stuck some string which does NOT resolve to a
937 # in case a user stuck some string which does NOT resolve to a
938 # valid path, it's as good as if we hadn't foud it
938 # valid path, it's as good as if we hadn't foud it
939 raise KeyError
939 raise KeyError
940 return homedir
940 return homedir
941 except KeyError:
941 except KeyError:
942 if os.name == 'posix':
942 if os.name == 'posix':
943 raise HomeDirError,'undefined $HOME, IPython can not proceed.'
943 raise HomeDirError,'undefined $HOME, IPython can not proceed.'
944 elif os.name == 'nt':
944 elif os.name == 'nt':
945 # For some strange reason, win9x returns 'nt' for os.name.
945 # For some strange reason, win9x returns 'nt' for os.name.
946 try:
946 try:
947 homedir = os.path.join(env['HOMEDRIVE'],env['HOMEPATH'])
947 homedir = os.path.join(env['HOMEDRIVE'],env['HOMEPATH'])
948 if not isdir(homedir):
948 if not isdir(homedir):
949 homedir = os.path.join(env['USERPROFILE'])
949 homedir = os.path.join(env['USERPROFILE'])
950 if not isdir(homedir):
950 if not isdir(homedir):
951 raise HomeDirError
951 raise HomeDirError
952 return homedir
952 return homedir
953 except KeyError:
953 except KeyError:
954 try:
954 try:
955 # Use the registry to get the 'My Documents' folder.
955 # Use the registry to get the 'My Documents' folder.
956 import _winreg as wreg
956 import _winreg as wreg
957 key = wreg.OpenKey(wreg.HKEY_CURRENT_USER,
957 key = wreg.OpenKey(wreg.HKEY_CURRENT_USER,
958 "Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders")
958 "Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders")
959 homedir = wreg.QueryValueEx(key,'Personal')[0]
959 homedir = wreg.QueryValueEx(key,'Personal')[0]
960 key.Close()
960 key.Close()
961 if not isdir(homedir):
961 if not isdir(homedir):
962 e = ('Invalid "Personal" folder registry key '
962 e = ('Invalid "Personal" folder registry key '
963 'typically "My Documents".\n'
963 'typically "My Documents".\n'
964 'Value: %s\n'
964 'Value: %s\n'
965 'This is not a valid directory on your system.' %
965 'This is not a valid directory on your system.' %
966 homedir)
966 homedir)
967 raise HomeDirError(e)
967 raise HomeDirError(e)
968 return homedir
968 return homedir
969 except HomeDirError:
969 except HomeDirError:
970 raise
970 raise
971 except:
971 except:
972 return 'C:\\'
972 return 'C:\\'
973 elif os.name == 'dos':
973 elif os.name == 'dos':
974 # Desperate, may do absurd things in classic MacOS. May work under DOS.
974 # Desperate, may do absurd things in classic MacOS. May work under DOS.
975 return 'C:\\'
975 return 'C:\\'
976 else:
976 else:
977 raise HomeDirError,'support for your operating system not implemented.'
977 raise HomeDirError,'support for your operating system not implemented.'
978
978
979
979
980 def get_ipython_dir():
980 def get_ipython_dir():
981 """Get the IPython directory for this platform and user.
981 """Get the IPython directory for this platform and user.
982
982
983 This uses the logic in `get_home_dir` to find the home directory
983 This uses the logic in `get_home_dir` to find the home directory
984 and the adds either .ipython or _ipython to the end of the path.
984 and the adds either .ipython or _ipython to the end of the path.
985 """
985 """
986 if os.name == 'posix':
986 if os.name == 'posix':
987 ipdir_def = '.ipython'
987 ipdir_def = '.ipython'
988 else:
988 else:
989 ipdir_def = '_ipython'
989 ipdir_def = '_ipython'
990 home_dir = get_home_dir()
990 home_dir = get_home_dir()
991 ipdir = os.path.abspath(os.environ.get('IPYTHONDIR',
991 ipdir = os.path.abspath(os.environ.get('IPYTHONDIR',
992 os.path.join(home_dir, ipdir_def)))
992 os.path.join(home_dir, ipdir_def)))
993 return ipdir.decode(sys.getfilesystemencoding())
993 return ipdir.decode(sys.getfilesystemencoding())
994
994
995 def get_security_dir():
995 def get_security_dir():
996 """Get the IPython security directory.
996 """Get the IPython security directory.
997
997
998 This directory is the default location for all security related files,
998 This directory is the default location for all security related files,
999 including SSL/TLS certificates and FURL files.
999 including SSL/TLS certificates and FURL files.
1000
1000
1001 If the directory does not exist, it is created with 0700 permissions.
1001 If the directory does not exist, it is created with 0700 permissions.
1002 If it exists, permissions are set to 0700.
1002 If it exists, permissions are set to 0700.
1003 """
1003 """
1004 security_dir = os.path.join(get_ipython_dir(), 'security')
1004 security_dir = os.path.join(get_ipython_dir(), 'security')
1005 if not os.path.isdir(security_dir):
1005 if not os.path.isdir(security_dir):
1006 os.mkdir(security_dir, 0700)
1006 os.mkdir(security_dir, 0700)
1007 else:
1007 else:
1008 os.chmod(security_dir, 0700)
1008 os.chmod(security_dir, 0700)
1009 return security_dir
1009 return security_dir
1010
1010
1011 def get_log_dir():
1012 """Get the IPython log directory.
1013
1014 If the log directory does not exist, it is created.
1015 """
1016 log_dir = os.path.join(get_ipython_dir(), 'log')
1017 if not os.path.isdir(log_dir):
1018 os.mkdir(log_dir, 0777)
1019 return log_dir
1020
1011 #****************************************************************************
1021 #****************************************************************************
1012 # strings and text
1022 # strings and text
1013
1023
1014 class LSString(str):
1024 class LSString(str):
1015 """String derivative with a special access attributes.
1025 """String derivative with a special access attributes.
1016
1026
1017 These are normal strings, but with the special attributes:
1027 These are normal strings, but with the special attributes:
1018
1028
1019 .l (or .list) : value as list (split on newlines).
1029 .l (or .list) : value as list (split on newlines).
1020 .n (or .nlstr): original value (the string itself).
1030 .n (or .nlstr): original value (the string itself).
1021 .s (or .spstr): value as whitespace-separated string.
1031 .s (or .spstr): value as whitespace-separated string.
1022 .p (or .paths): list of path objects
1032 .p (or .paths): list of path objects
1023
1033
1024 Any values which require transformations are computed only once and
1034 Any values which require transformations are computed only once and
1025 cached.
1035 cached.
1026
1036
1027 Such strings are very useful to efficiently interact with the shell, which
1037 Such strings are very useful to efficiently interact with the shell, which
1028 typically only understands whitespace-separated options for commands."""
1038 typically only understands whitespace-separated options for commands."""
1029
1039
1030 def get_list(self):
1040 def get_list(self):
1031 try:
1041 try:
1032 return self.__list
1042 return self.__list
1033 except AttributeError:
1043 except AttributeError:
1034 self.__list = self.split('\n')
1044 self.__list = self.split('\n')
1035 return self.__list
1045 return self.__list
1036
1046
1037 l = list = property(get_list)
1047 l = list = property(get_list)
1038
1048
1039 def get_spstr(self):
1049 def get_spstr(self):
1040 try:
1050 try:
1041 return self.__spstr
1051 return self.__spstr
1042 except AttributeError:
1052 except AttributeError:
1043 self.__spstr = self.replace('\n',' ')
1053 self.__spstr = self.replace('\n',' ')
1044 return self.__spstr
1054 return self.__spstr
1045
1055
1046 s = spstr = property(get_spstr)
1056 s = spstr = property(get_spstr)
1047
1057
1048 def get_nlstr(self):
1058 def get_nlstr(self):
1049 return self
1059 return self
1050
1060
1051 n = nlstr = property(get_nlstr)
1061 n = nlstr = property(get_nlstr)
1052
1062
1053 def get_paths(self):
1063 def get_paths(self):
1054 try:
1064 try:
1055 return self.__paths
1065 return self.__paths
1056 except AttributeError:
1066 except AttributeError:
1057 self.__paths = [path(p) for p in self.split('\n') if os.path.exists(p)]
1067 self.__paths = [path(p) for p in self.split('\n') if os.path.exists(p)]
1058 return self.__paths
1068 return self.__paths
1059
1069
1060 p = paths = property(get_paths)
1070 p = paths = property(get_paths)
1061
1071
1062 def print_lsstring(arg):
1072 def print_lsstring(arg):
1063 """ Prettier (non-repr-like) and more informative printer for LSString """
1073 """ Prettier (non-repr-like) and more informative printer for LSString """
1064 print "LSString (.p, .n, .l, .s available). Value:"
1074 print "LSString (.p, .n, .l, .s available). Value:"
1065 print arg
1075 print arg
1066
1076
1067 print_lsstring = result_display.when_type(LSString)(print_lsstring)
1077 print_lsstring = result_display.when_type(LSString)(print_lsstring)
1068
1078
1069 #----------------------------------------------------------------------------
1079 #----------------------------------------------------------------------------
1070 class SList(list):
1080 class SList(list):
1071 """List derivative with a special access attributes.
1081 """List derivative with a special access attributes.
1072
1082
1073 These are normal lists, but with the special attributes:
1083 These are normal lists, but with the special attributes:
1074
1084
1075 .l (or .list) : value as list (the list itself).
1085 .l (or .list) : value as list (the list itself).
1076 .n (or .nlstr): value as a string, joined on newlines.
1086 .n (or .nlstr): value as a string, joined on newlines.
1077 .s (or .spstr): value as a string, joined on spaces.
1087 .s (or .spstr): value as a string, joined on spaces.
1078 .p (or .paths): list of path objects
1088 .p (or .paths): list of path objects
1079
1089
1080 Any values which require transformations are computed only once and
1090 Any values which require transformations are computed only once and
1081 cached."""
1091 cached."""
1082
1092
1083 def get_list(self):
1093 def get_list(self):
1084 return self
1094 return self
1085
1095
1086 l = list = property(get_list)
1096 l = list = property(get_list)
1087
1097
1088 def get_spstr(self):
1098 def get_spstr(self):
1089 try:
1099 try:
1090 return self.__spstr
1100 return self.__spstr
1091 except AttributeError:
1101 except AttributeError:
1092 self.__spstr = ' '.join(self)
1102 self.__spstr = ' '.join(self)
1093 return self.__spstr
1103 return self.__spstr
1094
1104
1095 s = spstr = property(get_spstr)
1105 s = spstr = property(get_spstr)
1096
1106
1097 def get_nlstr(self):
1107 def get_nlstr(self):
1098 try:
1108 try:
1099 return self.__nlstr
1109 return self.__nlstr
1100 except AttributeError:
1110 except AttributeError:
1101 self.__nlstr = '\n'.join(self)
1111 self.__nlstr = '\n'.join(self)
1102 return self.__nlstr
1112 return self.__nlstr
1103
1113
1104 n = nlstr = property(get_nlstr)
1114 n = nlstr = property(get_nlstr)
1105
1115
1106 def get_paths(self):
1116 def get_paths(self):
1107 try:
1117 try:
1108 return self.__paths
1118 return self.__paths
1109 except AttributeError:
1119 except AttributeError:
1110 self.__paths = [path(p) for p in self if os.path.exists(p)]
1120 self.__paths = [path(p) for p in self if os.path.exists(p)]
1111 return self.__paths
1121 return self.__paths
1112
1122
1113 p = paths = property(get_paths)
1123 p = paths = property(get_paths)
1114
1124
1115 def grep(self, pattern, prune = False, field = None):
1125 def grep(self, pattern, prune = False, field = None):
1116 """ Return all strings matching 'pattern' (a regex or callable)
1126 """ Return all strings matching 'pattern' (a regex or callable)
1117
1127
1118 This is case-insensitive. If prune is true, return all items
1128 This is case-insensitive. If prune is true, return all items
1119 NOT matching the pattern.
1129 NOT matching the pattern.
1120
1130
1121 If field is specified, the match must occur in the specified
1131 If field is specified, the match must occur in the specified
1122 whitespace-separated field.
1132 whitespace-separated field.
1123
1133
1124 Examples::
1134 Examples::
1125
1135
1126 a.grep( lambda x: x.startswith('C') )
1136 a.grep( lambda x: x.startswith('C') )
1127 a.grep('Cha.*log', prune=1)
1137 a.grep('Cha.*log', prune=1)
1128 a.grep('chm', field=-1)
1138 a.grep('chm', field=-1)
1129 """
1139 """
1130
1140
1131 def match_target(s):
1141 def match_target(s):
1132 if field is None:
1142 if field is None:
1133 return s
1143 return s
1134 parts = s.split()
1144 parts = s.split()
1135 try:
1145 try:
1136 tgt = parts[field]
1146 tgt = parts[field]
1137 return tgt
1147 return tgt
1138 except IndexError:
1148 except IndexError:
1139 return ""
1149 return ""
1140
1150
1141 if isinstance(pattern, basestring):
1151 if isinstance(pattern, basestring):
1142 pred = lambda x : re.search(pattern, x, re.IGNORECASE)
1152 pred = lambda x : re.search(pattern, x, re.IGNORECASE)
1143 else:
1153 else:
1144 pred = pattern
1154 pred = pattern
1145 if not prune:
1155 if not prune:
1146 return SList([el for el in self if pred(match_target(el))])
1156 return SList([el for el in self if pred(match_target(el))])
1147 else:
1157 else:
1148 return SList([el for el in self if not pred(match_target(el))])
1158 return SList([el for el in self if not pred(match_target(el))])
1149 def fields(self, *fields):
1159 def fields(self, *fields):
1150 """ Collect whitespace-separated fields from string list
1160 """ Collect whitespace-separated fields from string list
1151
1161
1152 Allows quick awk-like usage of string lists.
1162 Allows quick awk-like usage of string lists.
1153
1163
1154 Example data (in var a, created by 'a = !ls -l')::
1164 Example data (in var a, created by 'a = !ls -l')::
1155 -rwxrwxrwx 1 ville None 18 Dec 14 2006 ChangeLog
1165 -rwxrwxrwx 1 ville None 18 Dec 14 2006 ChangeLog
1156 drwxrwxrwx+ 6 ville None 0 Oct 24 18:05 IPython
1166 drwxrwxrwx+ 6 ville None 0 Oct 24 18:05 IPython
1157
1167
1158 a.fields(0) is ['-rwxrwxrwx', 'drwxrwxrwx+']
1168 a.fields(0) is ['-rwxrwxrwx', 'drwxrwxrwx+']
1159 a.fields(1,0) is ['1 -rwxrwxrwx', '6 drwxrwxrwx+']
1169 a.fields(1,0) is ['1 -rwxrwxrwx', '6 drwxrwxrwx+']
1160 (note the joining by space).
1170 (note the joining by space).
1161 a.fields(-1) is ['ChangeLog', 'IPython']
1171 a.fields(-1) is ['ChangeLog', 'IPython']
1162
1172
1163 IndexErrors are ignored.
1173 IndexErrors are ignored.
1164
1174
1165 Without args, fields() just split()'s the strings.
1175 Without args, fields() just split()'s the strings.
1166 """
1176 """
1167 if len(fields) == 0:
1177 if len(fields) == 0:
1168 return [el.split() for el in self]
1178 return [el.split() for el in self]
1169
1179
1170 res = SList()
1180 res = SList()
1171 for el in [f.split() for f in self]:
1181 for el in [f.split() for f in self]:
1172 lineparts = []
1182 lineparts = []
1173
1183
1174 for fd in fields:
1184 for fd in fields:
1175 try:
1185 try:
1176 lineparts.append(el[fd])
1186 lineparts.append(el[fd])
1177 except IndexError:
1187 except IndexError:
1178 pass
1188 pass
1179 if lineparts:
1189 if lineparts:
1180 res.append(" ".join(lineparts))
1190 res.append(" ".join(lineparts))
1181
1191
1182 return res
1192 return res
1183 def sort(self,field= None, nums = False):
1193 def sort(self,field= None, nums = False):
1184 """ sort by specified fields (see fields())
1194 """ sort by specified fields (see fields())
1185
1195
1186 Example::
1196 Example::
1187 a.sort(1, nums = True)
1197 a.sort(1, nums = True)
1188
1198
1189 Sorts a by second field, in numerical order (so that 21 > 3)
1199 Sorts a by second field, in numerical order (so that 21 > 3)
1190
1200
1191 """
1201 """
1192
1202
1193 #decorate, sort, undecorate
1203 #decorate, sort, undecorate
1194 if field is not None:
1204 if field is not None:
1195 dsu = [[SList([line]).fields(field), line] for line in self]
1205 dsu = [[SList([line]).fields(field), line] for line in self]
1196 else:
1206 else:
1197 dsu = [[line, line] for line in self]
1207 dsu = [[line, line] for line in self]
1198 if nums:
1208 if nums:
1199 for i in range(len(dsu)):
1209 for i in range(len(dsu)):
1200 numstr = "".join([ch for ch in dsu[i][0] if ch.isdigit()])
1210 numstr = "".join([ch for ch in dsu[i][0] if ch.isdigit()])
1201 try:
1211 try:
1202 n = int(numstr)
1212 n = int(numstr)
1203 except ValueError:
1213 except ValueError:
1204 n = 0;
1214 n = 0;
1205 dsu[i][0] = n
1215 dsu[i][0] = n
1206
1216
1207
1217
1208 dsu.sort()
1218 dsu.sort()
1209 return SList([t[1] for t in dsu])
1219 return SList([t[1] for t in dsu])
1210
1220
1211 def print_slist(arg):
1221 def print_slist(arg):
1212 """ Prettier (non-repr-like) and more informative printer for SList """
1222 """ Prettier (non-repr-like) and more informative printer for SList """
1213 print "SList (.p, .n, .l, .s, .grep(), .fields(), sort() available):"
1223 print "SList (.p, .n, .l, .s, .grep(), .fields(), sort() available):"
1214 if hasattr(arg, 'hideonce') and arg.hideonce:
1224 if hasattr(arg, 'hideonce') and arg.hideonce:
1215 arg.hideonce = False
1225 arg.hideonce = False
1216 return
1226 return
1217
1227
1218 nlprint(arg)
1228 nlprint(arg)
1219
1229
1220 print_slist = result_display.when_type(SList)(print_slist)
1230 print_slist = result_display.when_type(SList)(print_slist)
1221
1231
1222
1232
1223
1233
1224 #----------------------------------------------------------------------------
1234 #----------------------------------------------------------------------------
1225 def esc_quotes(strng):
1235 def esc_quotes(strng):
1226 """Return the input string with single and double quotes escaped out"""
1236 """Return the input string with single and double quotes escaped out"""
1227
1237
1228 return strng.replace('"','\\"').replace("'","\\'")
1238 return strng.replace('"','\\"').replace("'","\\'")
1229
1239
1230 #----------------------------------------------------------------------------
1240 #----------------------------------------------------------------------------
1231 def make_quoted_expr(s):
1241 def make_quoted_expr(s):
1232 """Return string s in appropriate quotes, using raw string if possible.
1242 """Return string s in appropriate quotes, using raw string if possible.
1233
1243
1234 XXX - example removed because it caused encoding errors in documentation
1244 XXX - example removed because it caused encoding errors in documentation
1235 generation. We need a new example that doesn't contain invalid chars.
1245 generation. We need a new example that doesn't contain invalid chars.
1236
1246
1237 Note the use of raw string and padding at the end to allow trailing
1247 Note the use of raw string and padding at the end to allow trailing
1238 backslash.
1248 backslash.
1239 """
1249 """
1240
1250
1241 tail = ''
1251 tail = ''
1242 tailpadding = ''
1252 tailpadding = ''
1243 raw = ''
1253 raw = ''
1244 if "\\" in s:
1254 if "\\" in s:
1245 raw = 'r'
1255 raw = 'r'
1246 if s.endswith('\\'):
1256 if s.endswith('\\'):
1247 tail = '[:-1]'
1257 tail = '[:-1]'
1248 tailpadding = '_'
1258 tailpadding = '_'
1249 if '"' not in s:
1259 if '"' not in s:
1250 quote = '"'
1260 quote = '"'
1251 elif "'" not in s:
1261 elif "'" not in s:
1252 quote = "'"
1262 quote = "'"
1253 elif '"""' not in s and not s.endswith('"'):
1263 elif '"""' not in s and not s.endswith('"'):
1254 quote = '"""'
1264 quote = '"""'
1255 elif "'''" not in s and not s.endswith("'"):
1265 elif "'''" not in s and not s.endswith("'"):
1256 quote = "'''"
1266 quote = "'''"
1257 else:
1267 else:
1258 # give up, backslash-escaped string will do
1268 # give up, backslash-escaped string will do
1259 return '"%s"' % esc_quotes(s)
1269 return '"%s"' % esc_quotes(s)
1260 res = raw + quote + s + tailpadding + quote + tail
1270 res = raw + quote + s + tailpadding + quote + tail
1261 return res
1271 return res
1262
1272
1263
1273
1264 #----------------------------------------------------------------------------
1274 #----------------------------------------------------------------------------
1265 def raw_input_multi(header='', ps1='==> ', ps2='..> ',terminate_str = '.'):
1275 def raw_input_multi(header='', ps1='==> ', ps2='..> ',terminate_str = '.'):
1266 """Take multiple lines of input.
1276 """Take multiple lines of input.
1267
1277
1268 A list with each line of input as a separate element is returned when a
1278 A list with each line of input as a separate element is returned when a
1269 termination string is entered (defaults to a single '.'). Input can also
1279 termination string is entered (defaults to a single '.'). Input can also
1270 terminate via EOF (^D in Unix, ^Z-RET in Windows).
1280 terminate via EOF (^D in Unix, ^Z-RET in Windows).
1271
1281
1272 Lines of input which end in \\ are joined into single entries (and a
1282 Lines of input which end in \\ are joined into single entries (and a
1273 secondary continuation prompt is issued as long as the user terminates
1283 secondary continuation prompt is issued as long as the user terminates
1274 lines with \\). This allows entering very long strings which are still
1284 lines with \\). This allows entering very long strings which are still
1275 meant to be treated as single entities.
1285 meant to be treated as single entities.
1276 """
1286 """
1277
1287
1278 try:
1288 try:
1279 if header:
1289 if header:
1280 header += '\n'
1290 header += '\n'
1281 lines = [raw_input(header + ps1)]
1291 lines = [raw_input(header + ps1)]
1282 except EOFError:
1292 except EOFError:
1283 return []
1293 return []
1284 terminate = [terminate_str]
1294 terminate = [terminate_str]
1285 try:
1295 try:
1286 while lines[-1:] != terminate:
1296 while lines[-1:] != terminate:
1287 new_line = raw_input(ps1)
1297 new_line = raw_input(ps1)
1288 while new_line.endswith('\\'):
1298 while new_line.endswith('\\'):
1289 new_line = new_line[:-1] + raw_input(ps2)
1299 new_line = new_line[:-1] + raw_input(ps2)
1290 lines.append(new_line)
1300 lines.append(new_line)
1291
1301
1292 return lines[:-1] # don't return the termination command
1302 return lines[:-1] # don't return the termination command
1293 except EOFError:
1303 except EOFError:
1294 print
1304 print
1295 return lines
1305 return lines
1296
1306
1297 #----------------------------------------------------------------------------
1307 #----------------------------------------------------------------------------
1298 def raw_input_ext(prompt='', ps2='... '):
1308 def raw_input_ext(prompt='', ps2='... '):
1299 """Similar to raw_input(), but accepts extended lines if input ends with \\."""
1309 """Similar to raw_input(), but accepts extended lines if input ends with \\."""
1300
1310
1301 line = raw_input(prompt)
1311 line = raw_input(prompt)
1302 while line.endswith('\\'):
1312 while line.endswith('\\'):
1303 line = line[:-1] + raw_input(ps2)
1313 line = line[:-1] + raw_input(ps2)
1304 return line
1314 return line
1305
1315
1306 #----------------------------------------------------------------------------
1316 #----------------------------------------------------------------------------
1307 def ask_yes_no(prompt,default=None):
1317 def ask_yes_no(prompt,default=None):
1308 """Asks a question and returns a boolean (y/n) answer.
1318 """Asks a question and returns a boolean (y/n) answer.
1309
1319
1310 If default is given (one of 'y','n'), it is used if the user input is
1320 If default is given (one of 'y','n'), it is used if the user input is
1311 empty. Otherwise the question is repeated until an answer is given.
1321 empty. Otherwise the question is repeated until an answer is given.
1312
1322
1313 An EOF is treated as the default answer. If there is no default, an
1323 An EOF is treated as the default answer. If there is no default, an
1314 exception is raised to prevent infinite loops.
1324 exception is raised to prevent infinite loops.
1315
1325
1316 Valid answers are: y/yes/n/no (match is not case sensitive)."""
1326 Valid answers are: y/yes/n/no (match is not case sensitive)."""
1317
1327
1318 answers = {'y':True,'n':False,'yes':True,'no':False}
1328 answers = {'y':True,'n':False,'yes':True,'no':False}
1319 ans = None
1329 ans = None
1320 while ans not in answers.keys():
1330 while ans not in answers.keys():
1321 try:
1331 try:
1322 ans = raw_input(prompt+' ').lower()
1332 ans = raw_input(prompt+' ').lower()
1323 if not ans: # response was an empty string
1333 if not ans: # response was an empty string
1324 ans = default
1334 ans = default
1325 except KeyboardInterrupt:
1335 except KeyboardInterrupt:
1326 pass
1336 pass
1327 except EOFError:
1337 except EOFError:
1328 if default in answers.keys():
1338 if default in answers.keys():
1329 ans = default
1339 ans = default
1330 print
1340 print
1331 else:
1341 else:
1332 raise
1342 raise
1333
1343
1334 return answers[ans]
1344 return answers[ans]
1335
1345
1336 #----------------------------------------------------------------------------
1346 #----------------------------------------------------------------------------
1337 def marquee(txt='',width=78,mark='*'):
1347 def marquee(txt='',width=78,mark='*'):
1338 """Return the input string centered in a 'marquee'."""
1348 """Return the input string centered in a 'marquee'."""
1339 if not txt:
1349 if not txt:
1340 return (mark*width)[:width]
1350 return (mark*width)[:width]
1341 nmark = (width-len(txt)-2)/len(mark)/2
1351 nmark = (width-len(txt)-2)/len(mark)/2
1342 if nmark < 0: nmark =0
1352 if nmark < 0: nmark =0
1343 marks = mark*nmark
1353 marks = mark*nmark
1344 return '%s %s %s' % (marks,txt,marks)
1354 return '%s %s %s' % (marks,txt,marks)
1345
1355
1346 #----------------------------------------------------------------------------
1356 #----------------------------------------------------------------------------
1347 class EvalDict:
1357 class EvalDict:
1348 """
1358 """
1349 Emulate a dict which evaluates its contents in the caller's frame.
1359 Emulate a dict which evaluates its contents in the caller's frame.
1350
1360
1351 Usage:
1361 Usage:
1352 >>> number = 19
1362 >>> number = 19
1353
1363
1354 >>> text = "python"
1364 >>> text = "python"
1355
1365
1356 >>> print "%(text.capitalize())s %(number/9.0).1f rules!" % EvalDict()
1366 >>> print "%(text.capitalize())s %(number/9.0).1f rules!" % EvalDict()
1357 Python 2.1 rules!
1367 Python 2.1 rules!
1358 """
1368 """
1359
1369
1360 # This version is due to sismex01@hebmex.com on c.l.py, and is basically a
1370 # This version is due to sismex01@hebmex.com on c.l.py, and is basically a
1361 # modified (shorter) version of:
1371 # modified (shorter) version of:
1362 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66018 by
1372 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66018 by
1363 # Skip Montanaro (skip@pobox.com).
1373 # Skip Montanaro (skip@pobox.com).
1364
1374
1365 def __getitem__(self, name):
1375 def __getitem__(self, name):
1366 frame = sys._getframe(1)
1376 frame = sys._getframe(1)
1367 return eval(name, frame.f_globals, frame.f_locals)
1377 return eval(name, frame.f_globals, frame.f_locals)
1368
1378
1369 EvalString = EvalDict # for backwards compatibility
1379 EvalString = EvalDict # for backwards compatibility
1370 #----------------------------------------------------------------------------
1380 #----------------------------------------------------------------------------
1371 def qw(words,flat=0,sep=None,maxsplit=-1):
1381 def qw(words,flat=0,sep=None,maxsplit=-1):
1372 """Similar to Perl's qw() operator, but with some more options.
1382 """Similar to Perl's qw() operator, but with some more options.
1373
1383
1374 qw(words,flat=0,sep=' ',maxsplit=-1) -> words.split(sep,maxsplit)
1384 qw(words,flat=0,sep=' ',maxsplit=-1) -> words.split(sep,maxsplit)
1375
1385
1376 words can also be a list itself, and with flat=1, the output will be
1386 words can also be a list itself, and with flat=1, the output will be
1377 recursively flattened.
1387 recursively flattened.
1378
1388
1379 Examples:
1389 Examples:
1380
1390
1381 >>> qw('1 2')
1391 >>> qw('1 2')
1382 ['1', '2']
1392 ['1', '2']
1383
1393
1384 >>> qw(['a b','1 2',['m n','p q']])
1394 >>> qw(['a b','1 2',['m n','p q']])
1385 [['a', 'b'], ['1', '2'], [['m', 'n'], ['p', 'q']]]
1395 [['a', 'b'], ['1', '2'], [['m', 'n'], ['p', 'q']]]
1386
1396
1387 >>> qw(['a b','1 2',['m n','p q']],flat=1)
1397 >>> qw(['a b','1 2',['m n','p q']],flat=1)
1388 ['a', 'b', '1', '2', 'm', 'n', 'p', 'q']
1398 ['a', 'b', '1', '2', 'm', 'n', 'p', 'q']
1389 """
1399 """
1390
1400
1391 if type(words) in StringTypes:
1401 if type(words) in StringTypes:
1392 return [word.strip() for word in words.split(sep,maxsplit)
1402 return [word.strip() for word in words.split(sep,maxsplit)
1393 if word and not word.isspace() ]
1403 if word and not word.isspace() ]
1394 if flat:
1404 if flat:
1395 return flatten(map(qw,words,[1]*len(words)))
1405 return flatten(map(qw,words,[1]*len(words)))
1396 return map(qw,words)
1406 return map(qw,words)
1397
1407
1398 #----------------------------------------------------------------------------
1408 #----------------------------------------------------------------------------
1399 def qwflat(words,sep=None,maxsplit=-1):
1409 def qwflat(words,sep=None,maxsplit=-1):
1400 """Calls qw(words) in flat mode. It's just a convenient shorthand."""
1410 """Calls qw(words) in flat mode. It's just a convenient shorthand."""
1401 return qw(words,1,sep,maxsplit)
1411 return qw(words,1,sep,maxsplit)
1402
1412
1403 #----------------------------------------------------------------------------
1413 #----------------------------------------------------------------------------
1404 def qw_lol(indata):
1414 def qw_lol(indata):
1405 """qw_lol('a b') -> [['a','b']],
1415 """qw_lol('a b') -> [['a','b']],
1406 otherwise it's just a call to qw().
1416 otherwise it's just a call to qw().
1407
1417
1408 We need this to make sure the modules_some keys *always* end up as a
1418 We need this to make sure the modules_some keys *always* end up as a
1409 list of lists."""
1419 list of lists."""
1410
1420
1411 if type(indata) in StringTypes:
1421 if type(indata) in StringTypes:
1412 return [qw(indata)]
1422 return [qw(indata)]
1413 else:
1423 else:
1414 return qw(indata)
1424 return qw(indata)
1415
1425
1416 #-----------------------------------------------------------------------------
1426 #-----------------------------------------------------------------------------
1417 def list_strings(arg):
1427 def list_strings(arg):
1418 """Always return a list of strings, given a string or list of strings
1428 """Always return a list of strings, given a string or list of strings
1419 as input."""
1429 as input."""
1420
1430
1421 if type(arg) in StringTypes: return [arg]
1431 if type(arg) in StringTypes: return [arg]
1422 else: return arg
1432 else: return arg
1423
1433
1424 #----------------------------------------------------------------------------
1434 #----------------------------------------------------------------------------
1425 def grep(pat,list,case=1):
1435 def grep(pat,list,case=1):
1426 """Simple minded grep-like function.
1436 """Simple minded grep-like function.
1427 grep(pat,list) returns occurrences of pat in list, None on failure.
1437 grep(pat,list) returns occurrences of pat in list, None on failure.
1428
1438
1429 It only does simple string matching, with no support for regexps. Use the
1439 It only does simple string matching, with no support for regexps. Use the
1430 option case=0 for case-insensitive matching."""
1440 option case=0 for case-insensitive matching."""
1431
1441
1432 # This is pretty crude. At least it should implement copying only references
1442 # This is pretty crude. At least it should implement copying only references
1433 # to the original data in case it's big. Now it copies the data for output.
1443 # to the original data in case it's big. Now it copies the data for output.
1434 out=[]
1444 out=[]
1435 if case:
1445 if case:
1436 for term in list:
1446 for term in list:
1437 if term.find(pat)>-1: out.append(term)
1447 if term.find(pat)>-1: out.append(term)
1438 else:
1448 else:
1439 lpat=pat.lower()
1449 lpat=pat.lower()
1440 for term in list:
1450 for term in list:
1441 if term.lower().find(lpat)>-1: out.append(term)
1451 if term.lower().find(lpat)>-1: out.append(term)
1442
1452
1443 if len(out): return out
1453 if len(out): return out
1444 else: return None
1454 else: return None
1445
1455
1446 #----------------------------------------------------------------------------
1456 #----------------------------------------------------------------------------
1447 def dgrep(pat,*opts):
1457 def dgrep(pat,*opts):
1448 """Return grep() on dir()+dir(__builtins__).
1458 """Return grep() on dir()+dir(__builtins__).
1449
1459
1450 A very common use of grep() when working interactively."""
1460 A very common use of grep() when working interactively."""
1451
1461
1452 return grep(pat,dir(__main__)+dir(__main__.__builtins__),*opts)
1462 return grep(pat,dir(__main__)+dir(__main__.__builtins__),*opts)
1453
1463
1454 #----------------------------------------------------------------------------
1464 #----------------------------------------------------------------------------
1455 def idgrep(pat):
1465 def idgrep(pat):
1456 """Case-insensitive dgrep()"""
1466 """Case-insensitive dgrep()"""
1457
1467
1458 return dgrep(pat,0)
1468 return dgrep(pat,0)
1459
1469
1460 #----------------------------------------------------------------------------
1470 #----------------------------------------------------------------------------
1461 def igrep(pat,list):
1471 def igrep(pat,list):
1462 """Synonym for case-insensitive grep."""
1472 """Synonym for case-insensitive grep."""
1463
1473
1464 return grep(pat,list,case=0)
1474 return grep(pat,list,case=0)
1465
1475
1466 #----------------------------------------------------------------------------
1476 #----------------------------------------------------------------------------
1467 def indent(str,nspaces=4,ntabs=0):
1477 def indent(str,nspaces=4,ntabs=0):
1468 """Indent a string a given number of spaces or tabstops.
1478 """Indent a string a given number of spaces or tabstops.
1469
1479
1470 indent(str,nspaces=4,ntabs=0) -> indent str by ntabs+nspaces.
1480 indent(str,nspaces=4,ntabs=0) -> indent str by ntabs+nspaces.
1471 """
1481 """
1472 if str is None:
1482 if str is None:
1473 return
1483 return
1474 ind = '\t'*ntabs+' '*nspaces
1484 ind = '\t'*ntabs+' '*nspaces
1475 outstr = '%s%s' % (ind,str.replace(os.linesep,os.linesep+ind))
1485 outstr = '%s%s' % (ind,str.replace(os.linesep,os.linesep+ind))
1476 if outstr.endswith(os.linesep+ind):
1486 if outstr.endswith(os.linesep+ind):
1477 return outstr[:-len(ind)]
1487 return outstr[:-len(ind)]
1478 else:
1488 else:
1479 return outstr
1489 return outstr
1480
1490
1481 #-----------------------------------------------------------------------------
1491 #-----------------------------------------------------------------------------
1482 def native_line_ends(filename,backup=1):
1492 def native_line_ends(filename,backup=1):
1483 """Convert (in-place) a file to line-ends native to the current OS.
1493 """Convert (in-place) a file to line-ends native to the current OS.
1484
1494
1485 If the optional backup argument is given as false, no backup of the
1495 If the optional backup argument is given as false, no backup of the
1486 original file is left. """
1496 original file is left. """
1487
1497
1488 backup_suffixes = {'posix':'~','dos':'.bak','nt':'.bak','mac':'.bak'}
1498 backup_suffixes = {'posix':'~','dos':'.bak','nt':'.bak','mac':'.bak'}
1489
1499
1490 bak_filename = filename + backup_suffixes[os.name]
1500 bak_filename = filename + backup_suffixes[os.name]
1491
1501
1492 original = open(filename).read()
1502 original = open(filename).read()
1493 shutil.copy2(filename,bak_filename)
1503 shutil.copy2(filename,bak_filename)
1494 try:
1504 try:
1495 new = open(filename,'wb')
1505 new = open(filename,'wb')
1496 new.write(os.linesep.join(original.splitlines()))
1506 new.write(os.linesep.join(original.splitlines()))
1497 new.write(os.linesep) # ALWAYS put an eol at the end of the file
1507 new.write(os.linesep) # ALWAYS put an eol at the end of the file
1498 new.close()
1508 new.close()
1499 except:
1509 except:
1500 os.rename(bak_filename,filename)
1510 os.rename(bak_filename,filename)
1501 if not backup:
1511 if not backup:
1502 try:
1512 try:
1503 os.remove(bak_filename)
1513 os.remove(bak_filename)
1504 except:
1514 except:
1505 pass
1515 pass
1506
1516
1507 #----------------------------------------------------------------------------
1517 #----------------------------------------------------------------------------
1508 def get_pager_cmd(pager_cmd = None):
1518 def get_pager_cmd(pager_cmd = None):
1509 """Return a pager command.
1519 """Return a pager command.
1510
1520
1511 Makes some attempts at finding an OS-correct one."""
1521 Makes some attempts at finding an OS-correct one."""
1512
1522
1513 if os.name == 'posix':
1523 if os.name == 'posix':
1514 default_pager_cmd = 'less -r' # -r for color control sequences
1524 default_pager_cmd = 'less -r' # -r for color control sequences
1515 elif os.name in ['nt','dos']:
1525 elif os.name in ['nt','dos']:
1516 default_pager_cmd = 'type'
1526 default_pager_cmd = 'type'
1517
1527
1518 if pager_cmd is None:
1528 if pager_cmd is None:
1519 try:
1529 try:
1520 pager_cmd = os.environ['PAGER']
1530 pager_cmd = os.environ['PAGER']
1521 except:
1531 except:
1522 pager_cmd = default_pager_cmd
1532 pager_cmd = default_pager_cmd
1523 return pager_cmd
1533 return pager_cmd
1524
1534
1525 #-----------------------------------------------------------------------------
1535 #-----------------------------------------------------------------------------
1526 def get_pager_start(pager,start):
1536 def get_pager_start(pager,start):
1527 """Return the string for paging files with an offset.
1537 """Return the string for paging files with an offset.
1528
1538
1529 This is the '+N' argument which less and more (under Unix) accept.
1539 This is the '+N' argument which less and more (under Unix) accept.
1530 """
1540 """
1531
1541
1532 if pager in ['less','more']:
1542 if pager in ['less','more']:
1533 if start:
1543 if start:
1534 start_string = '+' + str(start)
1544 start_string = '+' + str(start)
1535 else:
1545 else:
1536 start_string = ''
1546 start_string = ''
1537 else:
1547 else:
1538 start_string = ''
1548 start_string = ''
1539 return start_string
1549 return start_string
1540
1550
1541 #----------------------------------------------------------------------------
1551 #----------------------------------------------------------------------------
1542 # (X)emacs on W32 doesn't like to be bypassed with msvcrt.getch()
1552 # (X)emacs on W32 doesn't like to be bypassed with msvcrt.getch()
1543 if os.name == 'nt' and os.environ.get('TERM','dumb') != 'emacs':
1553 if os.name == 'nt' and os.environ.get('TERM','dumb') != 'emacs':
1544 import msvcrt
1554 import msvcrt
1545 def page_more():
1555 def page_more():
1546 """ Smart pausing between pages
1556 """ Smart pausing between pages
1547
1557
1548 @return: True if need print more lines, False if quit
1558 @return: True if need print more lines, False if quit
1549 """
1559 """
1550 Term.cout.write('---Return to continue, q to quit--- ')
1560 Term.cout.write('---Return to continue, q to quit--- ')
1551 ans = msvcrt.getch()
1561 ans = msvcrt.getch()
1552 if ans in ("q", "Q"):
1562 if ans in ("q", "Q"):
1553 result = False
1563 result = False
1554 else:
1564 else:
1555 result = True
1565 result = True
1556 Term.cout.write("\b"*37 + " "*37 + "\b"*37)
1566 Term.cout.write("\b"*37 + " "*37 + "\b"*37)
1557 return result
1567 return result
1558 else:
1568 else:
1559 def page_more():
1569 def page_more():
1560 ans = raw_input('---Return to continue, q to quit--- ')
1570 ans = raw_input('---Return to continue, q to quit--- ')
1561 if ans.lower().startswith('q'):
1571 if ans.lower().startswith('q'):
1562 return False
1572 return False
1563 else:
1573 else:
1564 return True
1574 return True
1565
1575
1566 esc_re = re.compile(r"(\x1b[^m]+m)")
1576 esc_re = re.compile(r"(\x1b[^m]+m)")
1567
1577
1568 def page_dumb(strng,start=0,screen_lines=25):
1578 def page_dumb(strng,start=0,screen_lines=25):
1569 """Very dumb 'pager' in Python, for when nothing else works.
1579 """Very dumb 'pager' in Python, for when nothing else works.
1570
1580
1571 Only moves forward, same interface as page(), except for pager_cmd and
1581 Only moves forward, same interface as page(), except for pager_cmd and
1572 mode."""
1582 mode."""
1573
1583
1574 out_ln = strng.splitlines()[start:]
1584 out_ln = strng.splitlines()[start:]
1575 screens = chop(out_ln,screen_lines-1)
1585 screens = chop(out_ln,screen_lines-1)
1576 if len(screens) == 1:
1586 if len(screens) == 1:
1577 print >>Term.cout, os.linesep.join(screens[0])
1587 print >>Term.cout, os.linesep.join(screens[0])
1578 else:
1588 else:
1579 last_escape = ""
1589 last_escape = ""
1580 for scr in screens[0:-1]:
1590 for scr in screens[0:-1]:
1581 hunk = os.linesep.join(scr)
1591 hunk = os.linesep.join(scr)
1582 print >>Term.cout, last_escape + hunk
1592 print >>Term.cout, last_escape + hunk
1583 if not page_more():
1593 if not page_more():
1584 return
1594 return
1585 esc_list = esc_re.findall(hunk)
1595 esc_list = esc_re.findall(hunk)
1586 if len(esc_list) > 0:
1596 if len(esc_list) > 0:
1587 last_escape = esc_list[-1]
1597 last_escape = esc_list[-1]
1588 print >>Term.cout, last_escape + os.linesep.join(screens[-1])
1598 print >>Term.cout, last_escape + os.linesep.join(screens[-1])
1589
1599
1590 #----------------------------------------------------------------------------
1600 #----------------------------------------------------------------------------
1591 def page(strng,start=0,screen_lines=0,pager_cmd = None):
1601 def page(strng,start=0,screen_lines=0,pager_cmd = None):
1592 """Print a string, piping through a pager after a certain length.
1602 """Print a string, piping through a pager after a certain length.
1593
1603
1594 The screen_lines parameter specifies the number of *usable* lines of your
1604 The screen_lines parameter specifies the number of *usable* lines of your
1595 terminal screen (total lines minus lines you need to reserve to show other
1605 terminal screen (total lines minus lines you need to reserve to show other
1596 information).
1606 information).
1597
1607
1598 If you set screen_lines to a number <=0, page() will try to auto-determine
1608 If you set screen_lines to a number <=0, page() will try to auto-determine
1599 your screen size and will only use up to (screen_size+screen_lines) for
1609 your screen size and will only use up to (screen_size+screen_lines) for
1600 printing, paging after that. That is, if you want auto-detection but need
1610 printing, paging after that. That is, if you want auto-detection but need
1601 to reserve the bottom 3 lines of the screen, use screen_lines = -3, and for
1611 to reserve the bottom 3 lines of the screen, use screen_lines = -3, and for
1602 auto-detection without any lines reserved simply use screen_lines = 0.
1612 auto-detection without any lines reserved simply use screen_lines = 0.
1603
1613
1604 If a string won't fit in the allowed lines, it is sent through the
1614 If a string won't fit in the allowed lines, it is sent through the
1605 specified pager command. If none given, look for PAGER in the environment,
1615 specified pager command. If none given, look for PAGER in the environment,
1606 and ultimately default to less.
1616 and ultimately default to less.
1607
1617
1608 If no system pager works, the string is sent through a 'dumb pager'
1618 If no system pager works, the string is sent through a 'dumb pager'
1609 written in python, very simplistic.
1619 written in python, very simplistic.
1610 """
1620 """
1611
1621
1612 # Some routines may auto-compute start offsets incorrectly and pass a
1622 # Some routines may auto-compute start offsets incorrectly and pass a
1613 # negative value. Offset to 0 for robustness.
1623 # negative value. Offset to 0 for robustness.
1614 start = max(0,start)
1624 start = max(0,start)
1615
1625
1616 # first, try the hook
1626 # first, try the hook
1617 ip = IPython.ipapi.get()
1627 ip = IPython.ipapi.get()
1618 if ip:
1628 if ip:
1619 try:
1629 try:
1620 ip.IP.hooks.show_in_pager(strng)
1630 ip.IP.hooks.show_in_pager(strng)
1621 return
1631 return
1622 except IPython.ipapi.TryNext:
1632 except IPython.ipapi.TryNext:
1623 pass
1633 pass
1624
1634
1625 # Ugly kludge, but calling curses.initscr() flat out crashes in emacs
1635 # Ugly kludge, but calling curses.initscr() flat out crashes in emacs
1626 TERM = os.environ.get('TERM','dumb')
1636 TERM = os.environ.get('TERM','dumb')
1627 if TERM in ['dumb','emacs'] and os.name != 'nt':
1637 if TERM in ['dumb','emacs'] and os.name != 'nt':
1628 print strng
1638 print strng
1629 return
1639 return
1630 # chop off the topmost part of the string we don't want to see
1640 # chop off the topmost part of the string we don't want to see
1631 str_lines = strng.split(os.linesep)[start:]
1641 str_lines = strng.split(os.linesep)[start:]
1632 str_toprint = os.linesep.join(str_lines)
1642 str_toprint = os.linesep.join(str_lines)
1633 num_newlines = len(str_lines)
1643 num_newlines = len(str_lines)
1634 len_str = len(str_toprint)
1644 len_str = len(str_toprint)
1635
1645
1636 # Dumb heuristics to guesstimate number of on-screen lines the string
1646 # Dumb heuristics to guesstimate number of on-screen lines the string
1637 # takes. Very basic, but good enough for docstrings in reasonable
1647 # takes. Very basic, but good enough for docstrings in reasonable
1638 # terminals. If someone later feels like refining it, it's not hard.
1648 # terminals. If someone later feels like refining it, it's not hard.
1639 numlines = max(num_newlines,int(len_str/80)+1)
1649 numlines = max(num_newlines,int(len_str/80)+1)
1640
1650
1641 if os.name == "nt":
1651 if os.name == "nt":
1642 screen_lines_def = get_console_size(defaulty=25)[1]
1652 screen_lines_def = get_console_size(defaulty=25)[1]
1643 else:
1653 else:
1644 screen_lines_def = 25 # default value if we can't auto-determine
1654 screen_lines_def = 25 # default value if we can't auto-determine
1645
1655
1646 # auto-determine screen size
1656 # auto-determine screen size
1647 if screen_lines <= 0:
1657 if screen_lines <= 0:
1648 if TERM=='xterm':
1658 if TERM=='xterm':
1649 use_curses = USE_CURSES
1659 use_curses = USE_CURSES
1650 else:
1660 else:
1651 # curses causes problems on many terminals other than xterm.
1661 # curses causes problems on many terminals other than xterm.
1652 use_curses = False
1662 use_curses = False
1653 if use_curses:
1663 if use_curses:
1654 # There is a bug in curses, where *sometimes* it fails to properly
1664 # There is a bug in curses, where *sometimes* it fails to properly
1655 # initialize, and then after the endwin() call is made, the
1665 # initialize, and then after the endwin() call is made, the
1656 # terminal is left in an unusable state. Rather than trying to
1666 # terminal is left in an unusable state. Rather than trying to
1657 # check everytime for this (by requesting and comparing termios
1667 # check everytime for this (by requesting and comparing termios
1658 # flags each time), we just save the initial terminal state and
1668 # flags each time), we just save the initial terminal state and
1659 # unconditionally reset it every time. It's cheaper than making
1669 # unconditionally reset it every time. It's cheaper than making
1660 # the checks.
1670 # the checks.
1661 term_flags = termios.tcgetattr(sys.stdout)
1671 term_flags = termios.tcgetattr(sys.stdout)
1662 scr = curses.initscr()
1672 scr = curses.initscr()
1663 screen_lines_real,screen_cols = scr.getmaxyx()
1673 screen_lines_real,screen_cols = scr.getmaxyx()
1664 curses.endwin()
1674 curses.endwin()
1665 # Restore terminal state in case endwin() didn't.
1675 # Restore terminal state in case endwin() didn't.
1666 termios.tcsetattr(sys.stdout,termios.TCSANOW,term_flags)
1676 termios.tcsetattr(sys.stdout,termios.TCSANOW,term_flags)
1667 # Now we have what we needed: the screen size in rows/columns
1677 # Now we have what we needed: the screen size in rows/columns
1668 screen_lines += screen_lines_real
1678 screen_lines += screen_lines_real
1669 #print '***Screen size:',screen_lines_real,'lines x',\
1679 #print '***Screen size:',screen_lines_real,'lines x',\
1670 #screen_cols,'columns.' # dbg
1680 #screen_cols,'columns.' # dbg
1671 else:
1681 else:
1672 screen_lines += screen_lines_def
1682 screen_lines += screen_lines_def
1673
1683
1674 #print 'numlines',numlines,'screenlines',screen_lines # dbg
1684 #print 'numlines',numlines,'screenlines',screen_lines # dbg
1675 if numlines <= screen_lines :
1685 if numlines <= screen_lines :
1676 #print '*** normal print' # dbg
1686 #print '*** normal print' # dbg
1677 print >>Term.cout, str_toprint
1687 print >>Term.cout, str_toprint
1678 else:
1688 else:
1679 # Try to open pager and default to internal one if that fails.
1689 # Try to open pager and default to internal one if that fails.
1680 # All failure modes are tagged as 'retval=1', to match the return
1690 # All failure modes are tagged as 'retval=1', to match the return
1681 # value of a failed system command. If any intermediate attempt
1691 # value of a failed system command. If any intermediate attempt
1682 # sets retval to 1, at the end we resort to our own page_dumb() pager.
1692 # sets retval to 1, at the end we resort to our own page_dumb() pager.
1683 pager_cmd = get_pager_cmd(pager_cmd)
1693 pager_cmd = get_pager_cmd(pager_cmd)
1684 pager_cmd += ' ' + get_pager_start(pager_cmd,start)
1694 pager_cmd += ' ' + get_pager_start(pager_cmd,start)
1685 if os.name == 'nt':
1695 if os.name == 'nt':
1686 if pager_cmd.startswith('type'):
1696 if pager_cmd.startswith('type'):
1687 # The default WinXP 'type' command is failing on complex strings.
1697 # The default WinXP 'type' command is failing on complex strings.
1688 retval = 1
1698 retval = 1
1689 else:
1699 else:
1690 tmpname = tempfile.mktemp('.txt')
1700 tmpname = tempfile.mktemp('.txt')
1691 tmpfile = file(tmpname,'wt')
1701 tmpfile = file(tmpname,'wt')
1692 tmpfile.write(strng)
1702 tmpfile.write(strng)
1693 tmpfile.close()
1703 tmpfile.close()
1694 cmd = "%s < %s" % (pager_cmd,tmpname)
1704 cmd = "%s < %s" % (pager_cmd,tmpname)
1695 if os.system(cmd):
1705 if os.system(cmd):
1696 retval = 1
1706 retval = 1
1697 else:
1707 else:
1698 retval = None
1708 retval = None
1699 os.remove(tmpname)
1709 os.remove(tmpname)
1700 else:
1710 else:
1701 try:
1711 try:
1702 retval = None
1712 retval = None
1703 # if I use popen4, things hang. No idea why.
1713 # if I use popen4, things hang. No idea why.
1704 #pager,shell_out = os.popen4(pager_cmd)
1714 #pager,shell_out = os.popen4(pager_cmd)
1705 pager = os.popen(pager_cmd,'w')
1715 pager = os.popen(pager_cmd,'w')
1706 pager.write(strng)
1716 pager.write(strng)
1707 pager.close()
1717 pager.close()
1708 retval = pager.close() # success returns None
1718 retval = pager.close() # success returns None
1709 except IOError,msg: # broken pipe when user quits
1719 except IOError,msg: # broken pipe when user quits
1710 if msg.args == (32,'Broken pipe'):
1720 if msg.args == (32,'Broken pipe'):
1711 retval = None
1721 retval = None
1712 else:
1722 else:
1713 retval = 1
1723 retval = 1
1714 except OSError:
1724 except OSError:
1715 # Other strange problems, sometimes seen in Win2k/cygwin
1725 # Other strange problems, sometimes seen in Win2k/cygwin
1716 retval = 1
1726 retval = 1
1717 if retval is not None:
1727 if retval is not None:
1718 page_dumb(strng,screen_lines=screen_lines)
1728 page_dumb(strng,screen_lines=screen_lines)
1719
1729
1720 #----------------------------------------------------------------------------
1730 #----------------------------------------------------------------------------
1721 def page_file(fname,start = 0, pager_cmd = None):
1731 def page_file(fname,start = 0, pager_cmd = None):
1722 """Page a file, using an optional pager command and starting line.
1732 """Page a file, using an optional pager command and starting line.
1723 """
1733 """
1724
1734
1725 pager_cmd = get_pager_cmd(pager_cmd)
1735 pager_cmd = get_pager_cmd(pager_cmd)
1726 pager_cmd += ' ' + get_pager_start(pager_cmd,start)
1736 pager_cmd += ' ' + get_pager_start(pager_cmd,start)
1727
1737
1728 try:
1738 try:
1729 if os.environ['TERM'] in ['emacs','dumb']:
1739 if os.environ['TERM'] in ['emacs','dumb']:
1730 raise EnvironmentError
1740 raise EnvironmentError
1731 xsys(pager_cmd + ' ' + fname)
1741 xsys(pager_cmd + ' ' + fname)
1732 except:
1742 except:
1733 try:
1743 try:
1734 if start > 0:
1744 if start > 0:
1735 start -= 1
1745 start -= 1
1736 page(open(fname).read(),start)
1746 page(open(fname).read(),start)
1737 except:
1747 except:
1738 print 'Unable to show file',`fname`
1748 print 'Unable to show file',`fname`
1739
1749
1740
1750
1741 #----------------------------------------------------------------------------
1751 #----------------------------------------------------------------------------
1742 def snip_print(str,width = 75,print_full = 0,header = ''):
1752 def snip_print(str,width = 75,print_full = 0,header = ''):
1743 """Print a string snipping the midsection to fit in width.
1753 """Print a string snipping the midsection to fit in width.
1744
1754
1745 print_full: mode control:
1755 print_full: mode control:
1746 - 0: only snip long strings
1756 - 0: only snip long strings
1747 - 1: send to page() directly.
1757 - 1: send to page() directly.
1748 - 2: snip long strings and ask for full length viewing with page()
1758 - 2: snip long strings and ask for full length viewing with page()
1749 Return 1 if snipping was necessary, 0 otherwise."""
1759 Return 1 if snipping was necessary, 0 otherwise."""
1750
1760
1751 if print_full == 1:
1761 if print_full == 1:
1752 page(header+str)
1762 page(header+str)
1753 return 0
1763 return 0
1754
1764
1755 print header,
1765 print header,
1756 if len(str) < width:
1766 if len(str) < width:
1757 print str
1767 print str
1758 snip = 0
1768 snip = 0
1759 else:
1769 else:
1760 whalf = int((width -5)/2)
1770 whalf = int((width -5)/2)
1761 print str[:whalf] + ' <...> ' + str[-whalf:]
1771 print str[:whalf] + ' <...> ' + str[-whalf:]
1762 snip = 1
1772 snip = 1
1763 if snip and print_full == 2:
1773 if snip and print_full == 2:
1764 if raw_input(header+' Snipped. View (y/n)? [N]').lower() == 'y':
1774 if raw_input(header+' Snipped. View (y/n)? [N]').lower() == 'y':
1765 page(str)
1775 page(str)
1766 return snip
1776 return snip
1767
1777
1768 #****************************************************************************
1778 #****************************************************************************
1769 # lists, dicts and structures
1779 # lists, dicts and structures
1770
1780
1771 def belong(candidates,checklist):
1781 def belong(candidates,checklist):
1772 """Check whether a list of items appear in a given list of options.
1782 """Check whether a list of items appear in a given list of options.
1773
1783
1774 Returns a list of 1 and 0, one for each candidate given."""
1784 Returns a list of 1 and 0, one for each candidate given."""
1775
1785
1776 return [x in checklist for x in candidates]
1786 return [x in checklist for x in candidates]
1777
1787
1778 #----------------------------------------------------------------------------
1788 #----------------------------------------------------------------------------
1779 def uniq_stable(elems):
1789 def uniq_stable(elems):
1780 """uniq_stable(elems) -> list
1790 """uniq_stable(elems) -> list
1781
1791
1782 Return from an iterable, a list of all the unique elements in the input,
1792 Return from an iterable, a list of all the unique elements in the input,
1783 but maintaining the order in which they first appear.
1793 but maintaining the order in which they first appear.
1784
1794
1785 A naive solution to this problem which just makes a dictionary with the
1795 A naive solution to this problem which just makes a dictionary with the
1786 elements as keys fails to respect the stability condition, since
1796 elements as keys fails to respect the stability condition, since
1787 dictionaries are unsorted by nature.
1797 dictionaries are unsorted by nature.
1788
1798
1789 Note: All elements in the input must be valid dictionary keys for this
1799 Note: All elements in the input must be valid dictionary keys for this
1790 routine to work, as it internally uses a dictionary for efficiency
1800 routine to work, as it internally uses a dictionary for efficiency
1791 reasons."""
1801 reasons."""
1792
1802
1793 unique = []
1803 unique = []
1794 unique_dict = {}
1804 unique_dict = {}
1795 for nn in elems:
1805 for nn in elems:
1796 if nn not in unique_dict:
1806 if nn not in unique_dict:
1797 unique.append(nn)
1807 unique.append(nn)
1798 unique_dict[nn] = None
1808 unique_dict[nn] = None
1799 return unique
1809 return unique
1800
1810
1801 #----------------------------------------------------------------------------
1811 #----------------------------------------------------------------------------
1802 class NLprinter:
1812 class NLprinter:
1803 """Print an arbitrarily nested list, indicating index numbers.
1813 """Print an arbitrarily nested list, indicating index numbers.
1804
1814
1805 An instance of this class called nlprint is available and callable as a
1815 An instance of this class called nlprint is available and callable as a
1806 function.
1816 function.
1807
1817
1808 nlprint(list,indent=' ',sep=': ') -> prints indenting each level by 'indent'
1818 nlprint(list,indent=' ',sep=': ') -> prints indenting each level by 'indent'
1809 and using 'sep' to separate the index from the value. """
1819 and using 'sep' to separate the index from the value. """
1810
1820
1811 def __init__(self):
1821 def __init__(self):
1812 self.depth = 0
1822 self.depth = 0
1813
1823
1814 def __call__(self,lst,pos='',**kw):
1824 def __call__(self,lst,pos='',**kw):
1815 """Prints the nested list numbering levels."""
1825 """Prints the nested list numbering levels."""
1816 kw.setdefault('indent',' ')
1826 kw.setdefault('indent',' ')
1817 kw.setdefault('sep',': ')
1827 kw.setdefault('sep',': ')
1818 kw.setdefault('start',0)
1828 kw.setdefault('start',0)
1819 kw.setdefault('stop',len(lst))
1829 kw.setdefault('stop',len(lst))
1820 # we need to remove start and stop from kw so they don't propagate
1830 # we need to remove start and stop from kw so they don't propagate
1821 # into a recursive call for a nested list.
1831 # into a recursive call for a nested list.
1822 start = kw['start']; del kw['start']
1832 start = kw['start']; del kw['start']
1823 stop = kw['stop']; del kw['stop']
1833 stop = kw['stop']; del kw['stop']
1824 if self.depth == 0 and 'header' in kw.keys():
1834 if self.depth == 0 and 'header' in kw.keys():
1825 print kw['header']
1835 print kw['header']
1826
1836
1827 for idx in range(start,stop):
1837 for idx in range(start,stop):
1828 elem = lst[idx]
1838 elem = lst[idx]
1829 if type(elem)==type([]):
1839 if type(elem)==type([]):
1830 self.depth += 1
1840 self.depth += 1
1831 self.__call__(elem,itpl('$pos$idx,'),**kw)
1841 self.__call__(elem,itpl('$pos$idx,'),**kw)
1832 self.depth -= 1
1842 self.depth -= 1
1833 else:
1843 else:
1834 printpl(kw['indent']*self.depth+'$pos$idx$kw["sep"]$elem')
1844 printpl(kw['indent']*self.depth+'$pos$idx$kw["sep"]$elem')
1835
1845
1836 nlprint = NLprinter()
1846 nlprint = NLprinter()
1837 #----------------------------------------------------------------------------
1847 #----------------------------------------------------------------------------
1838 def all_belong(candidates,checklist):
1848 def all_belong(candidates,checklist):
1839 """Check whether a list of items ALL appear in a given list of options.
1849 """Check whether a list of items ALL appear in a given list of options.
1840
1850
1841 Returns a single 1 or 0 value."""
1851 Returns a single 1 or 0 value."""
1842
1852
1843 return 1-(0 in [x in checklist for x in candidates])
1853 return 1-(0 in [x in checklist for x in candidates])
1844
1854
1845 #----------------------------------------------------------------------------
1855 #----------------------------------------------------------------------------
1846 def sort_compare(lst1,lst2,inplace = 1):
1856 def sort_compare(lst1,lst2,inplace = 1):
1847 """Sort and compare two lists.
1857 """Sort and compare two lists.
1848
1858
1849 By default it does it in place, thus modifying the lists. Use inplace = 0
1859 By default it does it in place, thus modifying the lists. Use inplace = 0
1850 to avoid that (at the cost of temporary copy creation)."""
1860 to avoid that (at the cost of temporary copy creation)."""
1851 if not inplace:
1861 if not inplace:
1852 lst1 = lst1[:]
1862 lst1 = lst1[:]
1853 lst2 = lst2[:]
1863 lst2 = lst2[:]
1854 lst1.sort(); lst2.sort()
1864 lst1.sort(); lst2.sort()
1855 return lst1 == lst2
1865 return lst1 == lst2
1856
1866
1857 #----------------------------------------------------------------------------
1867 #----------------------------------------------------------------------------
1858 def list2dict(lst):
1868 def list2dict(lst):
1859 """Takes a list of (key,value) pairs and turns it into a dict."""
1869 """Takes a list of (key,value) pairs and turns it into a dict."""
1860
1870
1861 dic = {}
1871 dic = {}
1862 for k,v in lst: dic[k] = v
1872 for k,v in lst: dic[k] = v
1863 return dic
1873 return dic
1864
1874
1865 #----------------------------------------------------------------------------
1875 #----------------------------------------------------------------------------
1866 def list2dict2(lst,default=''):
1876 def list2dict2(lst,default=''):
1867 """Takes a list and turns it into a dict.
1877 """Takes a list and turns it into a dict.
1868 Much slower than list2dict, but more versatile. This version can take
1878 Much slower than list2dict, but more versatile. This version can take
1869 lists with sublists of arbitrary length (including sclars)."""
1879 lists with sublists of arbitrary length (including sclars)."""
1870
1880
1871 dic = {}
1881 dic = {}
1872 for elem in lst:
1882 for elem in lst:
1873 if type(elem) in (types.ListType,types.TupleType):
1883 if type(elem) in (types.ListType,types.TupleType):
1874 size = len(elem)
1884 size = len(elem)
1875 if size == 0:
1885 if size == 0:
1876 pass
1886 pass
1877 elif size == 1:
1887 elif size == 1:
1878 dic[elem] = default
1888 dic[elem] = default
1879 else:
1889 else:
1880 k,v = elem[0], elem[1:]
1890 k,v = elem[0], elem[1:]
1881 if len(v) == 1: v = v[0]
1891 if len(v) == 1: v = v[0]
1882 dic[k] = v
1892 dic[k] = v
1883 else:
1893 else:
1884 dic[elem] = default
1894 dic[elem] = default
1885 return dic
1895 return dic
1886
1896
1887 #----------------------------------------------------------------------------
1897 #----------------------------------------------------------------------------
1888 def flatten(seq):
1898 def flatten(seq):
1889 """Flatten a list of lists (NOT recursive, only works for 2d lists)."""
1899 """Flatten a list of lists (NOT recursive, only works for 2d lists)."""
1890
1900
1891 return [x for subseq in seq for x in subseq]
1901 return [x for subseq in seq for x in subseq]
1892
1902
1893 #----------------------------------------------------------------------------
1903 #----------------------------------------------------------------------------
1894 def get_slice(seq,start=0,stop=None,step=1):
1904 def get_slice(seq,start=0,stop=None,step=1):
1895 """Get a slice of a sequence with variable step. Specify start,stop,step."""
1905 """Get a slice of a sequence with variable step. Specify start,stop,step."""
1896 if stop == None:
1906 if stop == None:
1897 stop = len(seq)
1907 stop = len(seq)
1898 item = lambda i: seq[i]
1908 item = lambda i: seq[i]
1899 return map(item,xrange(start,stop,step))
1909 return map(item,xrange(start,stop,step))
1900
1910
1901 #----------------------------------------------------------------------------
1911 #----------------------------------------------------------------------------
1902 def chop(seq,size):
1912 def chop(seq,size):
1903 """Chop a sequence into chunks of the given size."""
1913 """Chop a sequence into chunks of the given size."""
1904 chunk = lambda i: seq[i:i+size]
1914 chunk = lambda i: seq[i:i+size]
1905 return map(chunk,xrange(0,len(seq),size))
1915 return map(chunk,xrange(0,len(seq),size))
1906
1916
1907 #----------------------------------------------------------------------------
1917 #----------------------------------------------------------------------------
1908 # with is a keyword as of python 2.5, so this function is renamed to withobj
1918 # with is a keyword as of python 2.5, so this function is renamed to withobj
1909 # from its old 'with' name.
1919 # from its old 'with' name.
1910 def with_obj(object, **args):
1920 def with_obj(object, **args):
1911 """Set multiple attributes for an object, similar to Pascal's with.
1921 """Set multiple attributes for an object, similar to Pascal's with.
1912
1922
1913 Example:
1923 Example:
1914 with_obj(jim,
1924 with_obj(jim,
1915 born = 1960,
1925 born = 1960,
1916 haircolour = 'Brown',
1926 haircolour = 'Brown',
1917 eyecolour = 'Green')
1927 eyecolour = 'Green')
1918
1928
1919 Credit: Greg Ewing, in
1929 Credit: Greg Ewing, in
1920 http://mail.python.org/pipermail/python-list/2001-May/040703.html.
1930 http://mail.python.org/pipermail/python-list/2001-May/040703.html.
1921
1931
1922 NOTE: up until IPython 0.7.2, this was called simply 'with', but 'with'
1932 NOTE: up until IPython 0.7.2, this was called simply 'with', but 'with'
1923 has become a keyword for Python 2.5, so we had to rename it."""
1933 has become a keyword for Python 2.5, so we had to rename it."""
1924
1934
1925 object.__dict__.update(args)
1935 object.__dict__.update(args)
1926
1936
1927 #----------------------------------------------------------------------------
1937 #----------------------------------------------------------------------------
1928 def setattr_list(obj,alist,nspace = None):
1938 def setattr_list(obj,alist,nspace = None):
1929 """Set a list of attributes for an object taken from a namespace.
1939 """Set a list of attributes for an object taken from a namespace.
1930
1940
1931 setattr_list(obj,alist,nspace) -> sets in obj all the attributes listed in
1941 setattr_list(obj,alist,nspace) -> sets in obj all the attributes listed in
1932 alist with their values taken from nspace, which must be a dict (something
1942 alist with their values taken from nspace, which must be a dict (something
1933 like locals() will often do) If nspace isn't given, locals() of the
1943 like locals() will often do) If nspace isn't given, locals() of the
1934 *caller* is used, so in most cases you can omit it.
1944 *caller* is used, so in most cases you can omit it.
1935
1945
1936 Note that alist can be given as a string, which will be automatically
1946 Note that alist can be given as a string, which will be automatically
1937 split into a list on whitespace. If given as a list, it must be a list of
1947 split into a list on whitespace. If given as a list, it must be a list of
1938 *strings* (the variable names themselves), not of variables."""
1948 *strings* (the variable names themselves), not of variables."""
1939
1949
1940 # this grabs the local variables from the *previous* call frame -- that is
1950 # this grabs the local variables from the *previous* call frame -- that is
1941 # the locals from the function that called setattr_list().
1951 # the locals from the function that called setattr_list().
1942 # - snipped from weave.inline()
1952 # - snipped from weave.inline()
1943 if nspace is None:
1953 if nspace is None:
1944 call_frame = sys._getframe().f_back
1954 call_frame = sys._getframe().f_back
1945 nspace = call_frame.f_locals
1955 nspace = call_frame.f_locals
1946
1956
1947 if type(alist) in StringTypes:
1957 if type(alist) in StringTypes:
1948 alist = alist.split()
1958 alist = alist.split()
1949 for attr in alist:
1959 for attr in alist:
1950 val = eval(attr,nspace)
1960 val = eval(attr,nspace)
1951 setattr(obj,attr,val)
1961 setattr(obj,attr,val)
1952
1962
1953 #----------------------------------------------------------------------------
1963 #----------------------------------------------------------------------------
1954 def getattr_list(obj,alist,*args):
1964 def getattr_list(obj,alist,*args):
1955 """getattr_list(obj,alist[, default]) -> attribute list.
1965 """getattr_list(obj,alist[, default]) -> attribute list.
1956
1966
1957 Get a list of named attributes for an object. When a default argument is
1967 Get a list of named attributes for an object. When a default argument is
1958 given, it is returned when the attribute doesn't exist; without it, an
1968 given, it is returned when the attribute doesn't exist; without it, an
1959 exception is raised in that case.
1969 exception is raised in that case.
1960
1970
1961 Note that alist can be given as a string, which will be automatically
1971 Note that alist can be given as a string, which will be automatically
1962 split into a list on whitespace. If given as a list, it must be a list of
1972 split into a list on whitespace. If given as a list, it must be a list of
1963 *strings* (the variable names themselves), not of variables."""
1973 *strings* (the variable names themselves), not of variables."""
1964
1974
1965 if type(alist) in StringTypes:
1975 if type(alist) in StringTypes:
1966 alist = alist.split()
1976 alist = alist.split()
1967 if args:
1977 if args:
1968 if len(args)==1:
1978 if len(args)==1:
1969 default = args[0]
1979 default = args[0]
1970 return map(lambda attr: getattr(obj,attr,default),alist)
1980 return map(lambda attr: getattr(obj,attr,default),alist)
1971 else:
1981 else:
1972 raise ValueError,'getattr_list() takes only one optional argument'
1982 raise ValueError,'getattr_list() takes only one optional argument'
1973 else:
1983 else:
1974 return map(lambda attr: getattr(obj,attr),alist)
1984 return map(lambda attr: getattr(obj,attr),alist)
1975
1985
1976 #----------------------------------------------------------------------------
1986 #----------------------------------------------------------------------------
1977 def map_method(method,object_list,*argseq,**kw):
1987 def map_method(method,object_list,*argseq,**kw):
1978 """map_method(method,object_list,*args,**kw) -> list
1988 """map_method(method,object_list,*args,**kw) -> list
1979
1989
1980 Return a list of the results of applying the methods to the items of the
1990 Return a list of the results of applying the methods to the items of the
1981 argument sequence(s). If more than one sequence is given, the method is
1991 argument sequence(s). If more than one sequence is given, the method is
1982 called with an argument list consisting of the corresponding item of each
1992 called with an argument list consisting of the corresponding item of each
1983 sequence. All sequences must be of the same length.
1993 sequence. All sequences must be of the same length.
1984
1994
1985 Keyword arguments are passed verbatim to all objects called.
1995 Keyword arguments are passed verbatim to all objects called.
1986
1996
1987 This is Python code, so it's not nearly as fast as the builtin map()."""
1997 This is Python code, so it's not nearly as fast as the builtin map()."""
1988
1998
1989 out_list = []
1999 out_list = []
1990 idx = 0
2000 idx = 0
1991 for object in object_list:
2001 for object in object_list:
1992 try:
2002 try:
1993 handler = getattr(object, method)
2003 handler = getattr(object, method)
1994 except AttributeError:
2004 except AttributeError:
1995 out_list.append(None)
2005 out_list.append(None)
1996 else:
2006 else:
1997 if argseq:
2007 if argseq:
1998 args = map(lambda lst:lst[idx],argseq)
2008 args = map(lambda lst:lst[idx],argseq)
1999 #print 'ob',object,'hand',handler,'ar',args # dbg
2009 #print 'ob',object,'hand',handler,'ar',args # dbg
2000 out_list.append(handler(args,**kw))
2010 out_list.append(handler(args,**kw))
2001 else:
2011 else:
2002 out_list.append(handler(**kw))
2012 out_list.append(handler(**kw))
2003 idx += 1
2013 idx += 1
2004 return out_list
2014 return out_list
2005
2015
2006 #----------------------------------------------------------------------------
2016 #----------------------------------------------------------------------------
2007 def get_class_members(cls):
2017 def get_class_members(cls):
2008 ret = dir(cls)
2018 ret = dir(cls)
2009 if hasattr(cls,'__bases__'):
2019 if hasattr(cls,'__bases__'):
2010 for base in cls.__bases__:
2020 for base in cls.__bases__:
2011 ret.extend(get_class_members(base))
2021 ret.extend(get_class_members(base))
2012 return ret
2022 return ret
2013
2023
2014 #----------------------------------------------------------------------------
2024 #----------------------------------------------------------------------------
2015 def dir2(obj):
2025 def dir2(obj):
2016 """dir2(obj) -> list of strings
2026 """dir2(obj) -> list of strings
2017
2027
2018 Extended version of the Python builtin dir(), which does a few extra
2028 Extended version of the Python builtin dir(), which does a few extra
2019 checks, and supports common objects with unusual internals that confuse
2029 checks, and supports common objects with unusual internals that confuse
2020 dir(), such as Traits and PyCrust.
2030 dir(), such as Traits and PyCrust.
2021
2031
2022 This version is guaranteed to return only a list of true strings, whereas
2032 This version is guaranteed to return only a list of true strings, whereas
2023 dir() returns anything that objects inject into themselves, even if they
2033 dir() returns anything that objects inject into themselves, even if they
2024 are later not really valid for attribute access (many extension libraries
2034 are later not really valid for attribute access (many extension libraries
2025 have such bugs).
2035 have such bugs).
2026 """
2036 """
2027
2037
2028 # Start building the attribute list via dir(), and then complete it
2038 # Start building the attribute list via dir(), and then complete it
2029 # with a few extra special-purpose calls.
2039 # with a few extra special-purpose calls.
2030 words = dir(obj)
2040 words = dir(obj)
2031
2041
2032 if hasattr(obj,'__class__'):
2042 if hasattr(obj,'__class__'):
2033 words.append('__class__')
2043 words.append('__class__')
2034 words.extend(get_class_members(obj.__class__))
2044 words.extend(get_class_members(obj.__class__))
2035 #if '__base__' in words: 1/0
2045 #if '__base__' in words: 1/0
2036
2046
2037 # Some libraries (such as traits) may introduce duplicates, we want to
2047 # Some libraries (such as traits) may introduce duplicates, we want to
2038 # track and clean this up if it happens
2048 # track and clean this up if it happens
2039 may_have_dupes = False
2049 may_have_dupes = False
2040
2050
2041 # this is the 'dir' function for objects with Enthought's traits
2051 # this is the 'dir' function for objects with Enthought's traits
2042 if hasattr(obj, 'trait_names'):
2052 if hasattr(obj, 'trait_names'):
2043 try:
2053 try:
2044 words.extend(obj.trait_names())
2054 words.extend(obj.trait_names())
2045 may_have_dupes = True
2055 may_have_dupes = True
2046 except TypeError:
2056 except TypeError:
2047 # This will happen if `obj` is a class and not an instance.
2057 # This will happen if `obj` is a class and not an instance.
2048 pass
2058 pass
2049
2059
2050 # Support for PyCrust-style _getAttributeNames magic method.
2060 # Support for PyCrust-style _getAttributeNames magic method.
2051 if hasattr(obj, '_getAttributeNames'):
2061 if hasattr(obj, '_getAttributeNames'):
2052 try:
2062 try:
2053 words.extend(obj._getAttributeNames())
2063 words.extend(obj._getAttributeNames())
2054 may_have_dupes = True
2064 may_have_dupes = True
2055 except TypeError:
2065 except TypeError:
2056 # `obj` is a class and not an instance. Ignore
2066 # `obj` is a class and not an instance. Ignore
2057 # this error.
2067 # this error.
2058 pass
2068 pass
2059
2069
2060 if may_have_dupes:
2070 if may_have_dupes:
2061 # eliminate possible duplicates, as some traits may also
2071 # eliminate possible duplicates, as some traits may also
2062 # appear as normal attributes in the dir() call.
2072 # appear as normal attributes in the dir() call.
2063 words = list(set(words))
2073 words = list(set(words))
2064 words.sort()
2074 words.sort()
2065
2075
2066 # filter out non-string attributes which may be stuffed by dir() calls
2076 # filter out non-string attributes which may be stuffed by dir() calls
2067 # and poor coding in third-party modules
2077 # and poor coding in third-party modules
2068 return [w for w in words if isinstance(w, basestring)]
2078 return [w for w in words if isinstance(w, basestring)]
2069
2079
2070 #----------------------------------------------------------------------------
2080 #----------------------------------------------------------------------------
2071 def import_fail_info(mod_name,fns=None):
2081 def import_fail_info(mod_name,fns=None):
2072 """Inform load failure for a module."""
2082 """Inform load failure for a module."""
2073
2083
2074 if fns == None:
2084 if fns == None:
2075 warn("Loading of %s failed.\n" % (mod_name,))
2085 warn("Loading of %s failed.\n" % (mod_name,))
2076 else:
2086 else:
2077 warn("Loading of %s from %s failed.\n" % (fns,mod_name))
2087 warn("Loading of %s from %s failed.\n" % (fns,mod_name))
2078
2088
2079 #----------------------------------------------------------------------------
2089 #----------------------------------------------------------------------------
2080 # Proposed popitem() extension, written as a method
2090 # Proposed popitem() extension, written as a method
2081
2091
2082
2092
2083 class NotGiven: pass
2093 class NotGiven: pass
2084
2094
2085 def popkey(dct,key,default=NotGiven):
2095 def popkey(dct,key,default=NotGiven):
2086 """Return dct[key] and delete dct[key].
2096 """Return dct[key] and delete dct[key].
2087
2097
2088 If default is given, return it if dct[key] doesn't exist, otherwise raise
2098 If default is given, return it if dct[key] doesn't exist, otherwise raise
2089 KeyError. """
2099 KeyError. """
2090
2100
2091 try:
2101 try:
2092 val = dct[key]
2102 val = dct[key]
2093 except KeyError:
2103 except KeyError:
2094 if default is NotGiven:
2104 if default is NotGiven:
2095 raise
2105 raise
2096 else:
2106 else:
2097 return default
2107 return default
2098 else:
2108 else:
2099 del dct[key]
2109 del dct[key]
2100 return val
2110 return val
2101
2111
2102 def wrap_deprecated(func, suggest = '<nothing>'):
2112 def wrap_deprecated(func, suggest = '<nothing>'):
2103 def newFunc(*args, **kwargs):
2113 def newFunc(*args, **kwargs):
2104 warnings.warn("Call to deprecated function %s, use %s instead" %
2114 warnings.warn("Call to deprecated function %s, use %s instead" %
2105 ( func.__name__, suggest),
2115 ( func.__name__, suggest),
2106 category=DeprecationWarning,
2116 category=DeprecationWarning,
2107 stacklevel = 2)
2117 stacklevel = 2)
2108 return func(*args, **kwargs)
2118 return func(*args, **kwargs)
2109 return newFunc
2119 return newFunc
2110
2120
2111
2121
2112 def _num_cpus_unix():
2122 def _num_cpus_unix():
2113 """Return the number of active CPUs on a Unix system."""
2123 """Return the number of active CPUs on a Unix system."""
2114 return os.sysconf("SC_NPROCESSORS_ONLN")
2124 return os.sysconf("SC_NPROCESSORS_ONLN")
2115
2125
2116
2126
2117 def _num_cpus_darwin():
2127 def _num_cpus_darwin():
2118 """Return the number of active CPUs on a Darwin system."""
2128 """Return the number of active CPUs on a Darwin system."""
2119 p = subprocess.Popen(['sysctl','-n','hw.ncpu'],stdout=subprocess.PIPE)
2129 p = subprocess.Popen(['sysctl','-n','hw.ncpu'],stdout=subprocess.PIPE)
2120 return p.stdout.read()
2130 return p.stdout.read()
2121
2131
2122
2132
2123 def _num_cpus_windows():
2133 def _num_cpus_windows():
2124 """Return the number of active CPUs on a Windows system."""
2134 """Return the number of active CPUs on a Windows system."""
2125 return os.environ.get("NUMBER_OF_PROCESSORS")
2135 return os.environ.get("NUMBER_OF_PROCESSORS")
2126
2136
2127
2137
2128 def num_cpus():
2138 def num_cpus():
2129 """Return the effective number of CPUs in the system as an integer.
2139 """Return the effective number of CPUs in the system as an integer.
2130
2140
2131 This cross-platform function makes an attempt at finding the total number of
2141 This cross-platform function makes an attempt at finding the total number of
2132 available CPUs in the system, as returned by various underlying system and
2142 available CPUs in the system, as returned by various underlying system and
2133 python calls.
2143 python calls.
2134
2144
2135 If it can't find a sensible answer, it returns 1 (though an error *may* make
2145 If it can't find a sensible answer, it returns 1 (though an error *may* make
2136 it return a large positive number that's actually incorrect).
2146 it return a large positive number that's actually incorrect).
2137 """
2147 """
2138
2148
2139 # Many thanks to the Parallel Python project (http://www.parallelpython.com)
2149 # Many thanks to the Parallel Python project (http://www.parallelpython.com)
2140 # for the names of the keys we needed to look up for this function. This
2150 # for the names of the keys we needed to look up for this function. This
2141 # code was inspired by their equivalent function.
2151 # code was inspired by their equivalent function.
2142
2152
2143 ncpufuncs = {'Linux':_num_cpus_unix,
2153 ncpufuncs = {'Linux':_num_cpus_unix,
2144 'Darwin':_num_cpus_darwin,
2154 'Darwin':_num_cpus_darwin,
2145 'Windows':_num_cpus_windows,
2155 'Windows':_num_cpus_windows,
2146 # On Vista, python < 2.5.2 has a bug and returns 'Microsoft'
2156 # On Vista, python < 2.5.2 has a bug and returns 'Microsoft'
2147 # See http://bugs.python.org/issue1082 for details.
2157 # See http://bugs.python.org/issue1082 for details.
2148 'Microsoft':_num_cpus_windows,
2158 'Microsoft':_num_cpus_windows,
2149 }
2159 }
2150
2160
2151 ncpufunc = ncpufuncs.get(platform.system(),
2161 ncpufunc = ncpufuncs.get(platform.system(),
2152 # default to unix version (Solaris, AIX, etc)
2162 # default to unix version (Solaris, AIX, etc)
2153 _num_cpus_unix)
2163 _num_cpus_unix)
2154
2164
2155 try:
2165 try:
2156 ncpus = max(1,int(ncpufunc()))
2166 ncpus = max(1,int(ncpufunc()))
2157 except:
2167 except:
2158 ncpus = 1
2168 ncpus = 1
2159 return ncpus
2169 return ncpus
2160
2170
2161 #*************************** end of file <genutils.py> **********************
2171 #*************************** end of file <genutils.py> **********************
@@ -1,2865 +1,2870 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 IPython -- An enhanced Interactive Python
3 IPython -- An enhanced Interactive Python
4
4
5 Requires Python 2.4 or newer.
5 Requires Python 2.4 or newer.
6
6
7 This file contains all the classes and helper functions specific to IPython.
7 This file contains all the classes and helper functions specific to IPython.
8 """
8 """
9
9
10 #*****************************************************************************
10 #*****************************************************************************
11 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de> and
11 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de> and
12 # Copyright (C) 2001-2006 Fernando Perez. <fperez@colorado.edu>
12 # Copyright (C) 2001-2006 Fernando Perez. <fperez@colorado.edu>
13 #
13 #
14 # Distributed under the terms of the BSD License. The full license is in
14 # Distributed under the terms of the BSD License. The full license is in
15 # the file COPYING, distributed as part of this software.
15 # the file COPYING, distributed as part of this software.
16 #
16 #
17 # Note: this code originally subclassed code.InteractiveConsole from the
17 # Note: this code originally subclassed code.InteractiveConsole from the
18 # Python standard library. Over time, all of that class has been copied
18 # Python standard library. Over time, all of that class has been copied
19 # verbatim here for modifications which could not be accomplished by
19 # verbatim here for modifications which could not be accomplished by
20 # subclassing. At this point, there are no dependencies at all on the code
20 # subclassing. At this point, there are no dependencies at all on the code
21 # module anymore (it is not even imported). The Python License (sec. 2)
21 # module anymore (it is not even imported). The Python License (sec. 2)
22 # allows for this, but it's always nice to acknowledge credit where credit is
22 # allows for this, but it's always nice to acknowledge credit where credit is
23 # due.
23 # due.
24 #*****************************************************************************
24 #*****************************************************************************
25
25
26 #****************************************************************************
26 #****************************************************************************
27 # Modules and globals
27 # Modules and globals
28
28
29 # Python standard modules
29 # Python standard modules
30 import __main__
30 import __main__
31 import __builtin__
31 import __builtin__
32 import StringIO
32 import StringIO
33 import bdb
33 import bdb
34 import cPickle as pickle
34 import cPickle as pickle
35 import codeop
35 import codeop
36 import exceptions
36 import exceptions
37 import glob
37 import glob
38 import inspect
38 import inspect
39 import keyword
39 import keyword
40 import new
40 import new
41 import os
41 import os
42 import pydoc
42 import pydoc
43 import re
43 import re
44 import shutil
44 import shutil
45 import string
45 import string
46 import sys
46 import sys
47 import tempfile
47 import tempfile
48 import traceback
48 import traceback
49 import types
49 import types
50 from pprint import pprint, pformat
50 from pprint import pprint, pformat
51
51
52 # IPython's own modules
52 # IPython's own modules
53 #import IPython
53 #import IPython
54 from IPython import Debugger,OInspect,PyColorize,ultraTB
54 from IPython import Debugger,OInspect,PyColorize,ultraTB
55 from IPython.ColorANSI import ColorScheme,ColorSchemeTable # too long names
55 from IPython.ColorANSI import ColorScheme,ColorSchemeTable # too long names
56 from IPython.Extensions import pickleshare
56 from IPython.Extensions import pickleshare
57 from IPython.FakeModule import FakeModule, init_fakemod_dict
57 from IPython.FakeModule import FakeModule, init_fakemod_dict
58 from IPython.Itpl import Itpl,itpl,printpl,ItplNS,itplns
58 from IPython.Itpl import Itpl,itpl,printpl,ItplNS,itplns
59 from IPython.Logger import Logger
59 from IPython.Logger import Logger
60 from IPython.Magic import Magic
60 from IPython.Magic import Magic
61 from IPython.Prompts import CachedOutput
61 from IPython.Prompts import CachedOutput
62 from IPython.ipstruct import Struct
62 from IPython.ipstruct import Struct
63 from IPython.background_jobs import BackgroundJobManager
63 from IPython.background_jobs import BackgroundJobManager
64 from IPython.usage import cmd_line_usage,interactive_usage
64 from IPython.usage import cmd_line_usage,interactive_usage
65 from IPython.genutils import *
65 from IPython.genutils import *
66 from IPython.strdispatch import StrDispatch
66 from IPython.strdispatch import StrDispatch
67 import IPython.ipapi
67 import IPython.ipapi
68 import IPython.history
68 import IPython.history
69 import IPython.prefilter as prefilter
69 import IPython.prefilter as prefilter
70 import IPython.shadowns
70 import IPython.shadowns
71 # Globals
71 # Globals
72
72
73 # store the builtin raw_input globally, and use this always, in case user code
73 # store the builtin raw_input globally, and use this always, in case user code
74 # overwrites it (like wx.py.PyShell does)
74 # overwrites it (like wx.py.PyShell does)
75 raw_input_original = raw_input
75 raw_input_original = raw_input
76
76
77 # compiled regexps for autoindent management
77 # compiled regexps for autoindent management
78 dedent_re = re.compile(r'^\s+raise|^\s+return|^\s+pass')
78 dedent_re = re.compile(r'^\s+raise|^\s+return|^\s+pass')
79
79
80
80
81 #****************************************************************************
81 #****************************************************************************
82 # Some utility function definitions
82 # Some utility function definitions
83
83
84 ini_spaces_re = re.compile(r'^(\s+)')
84 ini_spaces_re = re.compile(r'^(\s+)')
85
85
86 def num_ini_spaces(strng):
86 def num_ini_spaces(strng):
87 """Return the number of initial spaces in a string"""
87 """Return the number of initial spaces in a string"""
88
88
89 ini_spaces = ini_spaces_re.match(strng)
89 ini_spaces = ini_spaces_re.match(strng)
90 if ini_spaces:
90 if ini_spaces:
91 return ini_spaces.end()
91 return ini_spaces.end()
92 else:
92 else:
93 return 0
93 return 0
94
94
95 def softspace(file, newvalue):
95 def softspace(file, newvalue):
96 """Copied from code.py, to remove the dependency"""
96 """Copied from code.py, to remove the dependency"""
97
97
98 oldvalue = 0
98 oldvalue = 0
99 try:
99 try:
100 oldvalue = file.softspace
100 oldvalue = file.softspace
101 except AttributeError:
101 except AttributeError:
102 pass
102 pass
103 try:
103 try:
104 file.softspace = newvalue
104 file.softspace = newvalue
105 except (AttributeError, TypeError):
105 except (AttributeError, TypeError):
106 # "attribute-less object" or "read-only attributes"
106 # "attribute-less object" or "read-only attributes"
107 pass
107 pass
108 return oldvalue
108 return oldvalue
109
109
110
110
111 def user_setup(ipythondir,rc_suffix,mode='install',interactive=True):
111 def user_setup(ipythondir,rc_suffix,mode='install',interactive=True):
112 """Install or upgrade the user configuration directory.
112 """Install or upgrade the user configuration directory.
113
113
114 Can be called when running for the first time or to upgrade the user's
114 Can be called when running for the first time or to upgrade the user's
115 .ipython/ directory.
115 .ipython/ directory.
116
116
117 Parameters
117 Parameters
118 ----------
118 ----------
119 ipythondir : path
119 ipythondir : path
120 The directory to be used for installation/upgrade. In 'install' mode,
120 The directory to be used for installation/upgrade. In 'install' mode,
121 if this path already exists, the function exits immediately.
121 if this path already exists, the function exits immediately.
122
122
123 rc_suffix : str
123 rc_suffix : str
124 Extension for the config files. On *nix platforms it is typically the
124 Extension for the config files. On *nix platforms it is typically the
125 empty string, while Windows normally uses '.ini'.
125 empty string, while Windows normally uses '.ini'.
126
126
127 mode : str, optional
127 mode : str, optional
128 Valid modes are 'install' and 'upgrade'.
128 Valid modes are 'install' and 'upgrade'.
129
129
130 interactive : bool, optional
130 interactive : bool, optional
131 If False, do not wait for user input on any errors. Normally after
131 If False, do not wait for user input on any errors. Normally after
132 printing its status information, this function waits for the user to
132 printing its status information, this function waits for the user to
133 hit Return before proceeding. This is because the default use case is
133 hit Return before proceeding. This is because the default use case is
134 when first installing the IPython configuration, so we want the user to
134 when first installing the IPython configuration, so we want the user to
135 acknowledge the initial message, which contains some useful
135 acknowledge the initial message, which contains some useful
136 information.
136 information.
137 """
137 """
138
138
139 # For automatic use, deactivate all i/o
139 # For automatic use, deactivate all i/o
140 if interactive:
140 if interactive:
141 def wait():
141 def wait():
142 try:
142 try:
143 raw_input("Please press <RETURN> to start IPython.")
143 raw_input("Please press <RETURN> to start IPython.")
144 except EOFError:
144 except EOFError:
145 print >> Term.cout
145 print >> Term.cout
146 print '*'*70
146 print '*'*70
147
147
148 def printf(s):
148 def printf(s):
149 print s
149 print s
150 else:
150 else:
151 wait = lambda : None
151 wait = lambda : None
152 printf = lambda s : None
152 printf = lambda s : None
153
153
154 # Install mode should be re-entrant: if the install dir already exists,
154 # Install mode should be re-entrant: if the install dir already exists,
155 # bail out cleanly
155 # bail out cleanly.
156 # XXX. This is too hasty to return. We need to check to make sure that
157 # all the expected config files and directories are actually there. We
158 # currently have a failure mode if someone deletes a needed config file
159 # but still has the ipythondir.
156 if mode == 'install' and os.path.isdir(ipythondir):
160 if mode == 'install' and os.path.isdir(ipythondir):
157 return
161 return
158
162
159 cwd = os.getcwd() # remember where we started
163 cwd = os.getcwd() # remember where we started
160 glb = glob.glob
164 glb = glob.glob
161
165
162 printf('*'*70)
166 printf('*'*70)
163 if mode == 'install':
167 if mode == 'install':
164 printf(
168 printf(
165 """Welcome to IPython. I will try to create a personal configuration directory
169 """Welcome to IPython. I will try to create a personal configuration directory
166 where you can customize many aspects of IPython's functionality in:\n""")
170 where you can customize many aspects of IPython's functionality in:\n""")
167 else:
171 else:
168 printf('I am going to upgrade your configuration in:')
172 printf('I am going to upgrade your configuration in:')
169
173
170 printf(ipythondir)
174 printf(ipythondir)
171
175
172 rcdirend = os.path.join('IPython','UserConfig')
176 rcdirend = os.path.join('IPython','UserConfig')
173 cfg = lambda d: os.path.join(d,rcdirend)
177 cfg = lambda d: os.path.join(d,rcdirend)
174 try:
178 try:
175 rcdir = filter(os.path.isdir,map(cfg,sys.path))[0]
179 rcdir = filter(os.path.isdir,map(cfg,sys.path))[0]
176 printf("Initializing from configuration: %s" % rcdir)
180 printf("Initializing from configuration: %s" % rcdir)
177 except IndexError:
181 except IndexError:
178 warning = """
182 warning = """
179 Installation error. IPython's directory was not found.
183 Installation error. IPython's directory was not found.
180
184
181 Check the following:
185 Check the following:
182
186
183 The ipython/IPython directory should be in a directory belonging to your
187 The ipython/IPython directory should be in a directory belonging to your
184 PYTHONPATH environment variable (that is, it should be in a directory
188 PYTHONPATH environment variable (that is, it should be in a directory
185 belonging to sys.path). You can copy it explicitly there or just link to it.
189 belonging to sys.path). You can copy it explicitly there or just link to it.
186
190
187 IPython will create a minimal default configuration for you.
191 IPython will create a minimal default configuration for you.
188
192
189 """
193 """
190 warn(warning)
194 warn(warning)
191 wait()
195 wait()
192
196
193 if sys.platform =='win32':
197 if sys.platform =='win32':
194 inif = 'ipythonrc.ini'
198 inif = 'ipythonrc.ini'
195 else:
199 else:
196 inif = 'ipythonrc'
200 inif = 'ipythonrc'
197 minimal_setup = {'ipy_user_conf.py' : 'import ipy_defaults',
201 minimal_setup = {'ipy_user_conf.py' : 'import ipy_defaults',
198 inif : '# intentionally left blank' }
202 inif : '# intentionally left blank' }
199 os.makedirs(ipythondir, mode = 0777)
203 os.makedirs(ipythondir, mode = 0777)
200 for f, cont in minimal_setup.items():
204 for f, cont in minimal_setup.items():
201 # In 2.5, this can be more cleanly done using 'with'
205 # In 2.5, this can be more cleanly done using 'with'
202 fobj = file(ipythondir + '/' + f,'w')
206 fobj = file(ipythondir + '/' + f,'w')
203 fobj.write(cont)
207 fobj.write(cont)
204 fobj.close()
208 fobj.close()
205
209
206 return
210 return
207
211
208 if mode == 'install':
212 if mode == 'install':
209 try:
213 try:
210 shutil.copytree(rcdir,ipythondir)
214 shutil.copytree(rcdir,ipythondir)
211 os.chdir(ipythondir)
215 os.chdir(ipythondir)
212 rc_files = glb("ipythonrc*")
216 rc_files = glb("ipythonrc*")
213 for rc_file in rc_files:
217 for rc_file in rc_files:
214 os.rename(rc_file,rc_file+rc_suffix)
218 os.rename(rc_file,rc_file+rc_suffix)
215 except:
219 except:
216 warning = """
220 warning = """
217
221
218 There was a problem with the installation:
222 There was a problem with the installation:
219 %s
223 %s
220 Try to correct it or contact the developers if you think it's a bug.
224 Try to correct it or contact the developers if you think it's a bug.
221 IPython will proceed with builtin defaults.""" % sys.exc_info()[1]
225 IPython will proceed with builtin defaults.""" % sys.exc_info()[1]
222 warn(warning)
226 warn(warning)
223 wait()
227 wait()
224 return
228 return
225
229
226 elif mode == 'upgrade':
230 elif mode == 'upgrade':
227 try:
231 try:
228 os.chdir(ipythondir)
232 os.chdir(ipythondir)
229 except:
233 except:
230 printf("""
234 printf("""
231 Can not upgrade: changing to directory %s failed. Details:
235 Can not upgrade: changing to directory %s failed. Details:
232 %s
236 %s
233 """ % (ipythondir,sys.exc_info()[1]) )
237 """ % (ipythondir,sys.exc_info()[1]) )
234 wait()
238 wait()
235 return
239 return
236 else:
240 else:
237 sources = glb(os.path.join(rcdir,'[A-Za-z]*'))
241 sources = glb(os.path.join(rcdir,'[A-Za-z]*'))
238 for new_full_path in sources:
242 for new_full_path in sources:
239 new_filename = os.path.basename(new_full_path)
243 new_filename = os.path.basename(new_full_path)
240 if new_filename.startswith('ipythonrc'):
244 if new_filename.startswith('ipythonrc'):
241 new_filename = new_filename + rc_suffix
245 new_filename = new_filename + rc_suffix
242 # The config directory should only contain files, skip any
246 # The config directory should only contain files, skip any
243 # directories which may be there (like CVS)
247 # directories which may be there (like CVS)
244 if os.path.isdir(new_full_path):
248 if os.path.isdir(new_full_path):
245 continue
249 continue
246 if os.path.exists(new_filename):
250 if os.path.exists(new_filename):
247 old_file = new_filename+'.old'
251 old_file = new_filename+'.old'
248 if os.path.exists(old_file):
252 if os.path.exists(old_file):
249 os.remove(old_file)
253 os.remove(old_file)
250 os.rename(new_filename,old_file)
254 os.rename(new_filename,old_file)
251 shutil.copy(new_full_path,new_filename)
255 shutil.copy(new_full_path,new_filename)
252 else:
256 else:
253 raise ValueError('unrecognized mode for install: %r' % mode)
257 raise ValueError('unrecognized mode for install: %r' % mode)
254
258
255 # Fix line-endings to those native to each platform in the config
259 # Fix line-endings to those native to each platform in the config
256 # directory.
260 # directory.
257 try:
261 try:
258 os.chdir(ipythondir)
262 os.chdir(ipythondir)
259 except:
263 except:
260 printf("""
264 printf("""
261 Problem: changing to directory %s failed.
265 Problem: changing to directory %s failed.
262 Details:
266 Details:
263 %s
267 %s
264
268
265 Some configuration files may have incorrect line endings. This should not
269 Some configuration files may have incorrect line endings. This should not
266 cause any problems during execution. """ % (ipythondir,sys.exc_info()[1]) )
270 cause any problems during execution. """ % (ipythondir,sys.exc_info()[1]) )
267 wait()
271 wait()
268 else:
272 else:
269 for fname in glb('ipythonrc*'):
273 for fname in glb('ipythonrc*'):
270 try:
274 try:
271 native_line_ends(fname,backup=0)
275 native_line_ends(fname,backup=0)
272 except IOError:
276 except IOError:
273 pass
277 pass
274
278
275 if mode == 'install':
279 if mode == 'install':
276 printf("""
280 printf("""
277 Successful installation!
281 Successful installation!
278
282
279 Please read the sections 'Initial Configuration' and 'Quick Tips' in the
283 Please read the sections 'Initial Configuration' and 'Quick Tips' in the
280 IPython manual (there are both HTML and PDF versions supplied with the
284 IPython manual (there are both HTML and PDF versions supplied with the
281 distribution) to make sure that your system environment is properly configured
285 distribution) to make sure that your system environment is properly configured
282 to take advantage of IPython's features.
286 to take advantage of IPython's features.
283
287
284 Important note: the configuration system has changed! The old system is
288 Important note: the configuration system has changed! The old system is
285 still in place, but its setting may be partly overridden by the settings in
289 still in place, but its setting may be partly overridden by the settings in
286 "~/.ipython/ipy_user_conf.py" config file. Please take a look at the file
290 "~/.ipython/ipy_user_conf.py" config file. Please take a look at the file
287 if some of the new settings bother you.
291 if some of the new settings bother you.
288
292
289 """)
293 """)
290 else:
294 else:
291 printf("""
295 printf("""
292 Successful upgrade!
296 Successful upgrade!
293
297
294 All files in your directory:
298 All files in your directory:
295 %(ipythondir)s
299 %(ipythondir)s
296 which would have been overwritten by the upgrade were backed up with a .old
300 which would have been overwritten by the upgrade were backed up with a .old
297 extension. If you had made particular customizations in those files you may
301 extension. If you had made particular customizations in those files you may
298 want to merge them back into the new files.""" % locals() )
302 want to merge them back into the new files.""" % locals() )
299 wait()
303 wait()
300 os.chdir(cwd)
304 os.chdir(cwd)
301
305
302 #****************************************************************************
306 #****************************************************************************
303 # Local use exceptions
307 # Local use exceptions
304 class SpaceInInput(exceptions.Exception): pass
308 class SpaceInInput(exceptions.Exception): pass
305
309
306
310
307 #****************************************************************************
311 #****************************************************************************
308 # Local use classes
312 # Local use classes
309 class Bunch: pass
313 class Bunch: pass
310
314
311 class Undefined: pass
315 class Undefined: pass
312
316
313 class Quitter(object):
317 class Quitter(object):
314 """Simple class to handle exit, similar to Python 2.5's.
318 """Simple class to handle exit, similar to Python 2.5's.
315
319
316 It handles exiting in an ipython-safe manner, which the one in Python 2.5
320 It handles exiting in an ipython-safe manner, which the one in Python 2.5
317 doesn't do (obviously, since it doesn't know about ipython)."""
321 doesn't do (obviously, since it doesn't know about ipython)."""
318
322
319 def __init__(self,shell,name):
323 def __init__(self,shell,name):
320 self.shell = shell
324 self.shell = shell
321 self.name = name
325 self.name = name
322
326
323 def __repr__(self):
327 def __repr__(self):
324 return 'Type %s() to exit.' % self.name
328 return 'Type %s() to exit.' % self.name
325 __str__ = __repr__
329 __str__ = __repr__
326
330
327 def __call__(self):
331 def __call__(self):
328 self.shell.exit()
332 self.shell.exit()
329
333
330 class InputList(list):
334 class InputList(list):
331 """Class to store user input.
335 """Class to store user input.
332
336
333 It's basically a list, but slices return a string instead of a list, thus
337 It's basically a list, but slices return a string instead of a list, thus
334 allowing things like (assuming 'In' is an instance):
338 allowing things like (assuming 'In' is an instance):
335
339
336 exec In[4:7]
340 exec In[4:7]
337
341
338 or
342 or
339
343
340 exec In[5:9] + In[14] + In[21:25]"""
344 exec In[5:9] + In[14] + In[21:25]"""
341
345
342 def __getslice__(self,i,j):
346 def __getslice__(self,i,j):
343 return ''.join(list.__getslice__(self,i,j))
347 return ''.join(list.__getslice__(self,i,j))
344
348
345 class SyntaxTB(ultraTB.ListTB):
349 class SyntaxTB(ultraTB.ListTB):
346 """Extension which holds some state: the last exception value"""
350 """Extension which holds some state: the last exception value"""
347
351
348 def __init__(self,color_scheme = 'NoColor'):
352 def __init__(self,color_scheme = 'NoColor'):
349 ultraTB.ListTB.__init__(self,color_scheme)
353 ultraTB.ListTB.__init__(self,color_scheme)
350 self.last_syntax_error = None
354 self.last_syntax_error = None
351
355
352 def __call__(self, etype, value, elist):
356 def __call__(self, etype, value, elist):
353 self.last_syntax_error = value
357 self.last_syntax_error = value
354 ultraTB.ListTB.__call__(self,etype,value,elist)
358 ultraTB.ListTB.__call__(self,etype,value,elist)
355
359
356 def clear_err_state(self):
360 def clear_err_state(self):
357 """Return the current error state and clear it"""
361 """Return the current error state and clear it"""
358 e = self.last_syntax_error
362 e = self.last_syntax_error
359 self.last_syntax_error = None
363 self.last_syntax_error = None
360 return e
364 return e
361
365
362 #****************************************************************************
366 #****************************************************************************
363 # Main IPython class
367 # Main IPython class
364
368
365 # FIXME: the Magic class is a mixin for now, and will unfortunately remain so
369 # FIXME: the Magic class is a mixin for now, and will unfortunately remain so
366 # until a full rewrite is made. I've cleaned all cross-class uses of
370 # until a full rewrite is made. I've cleaned all cross-class uses of
367 # attributes and methods, but too much user code out there relies on the
371 # attributes and methods, but too much user code out there relies on the
368 # equlity %foo == __IP.magic_foo, so I can't actually remove the mixin usage.
372 # equlity %foo == __IP.magic_foo, so I can't actually remove the mixin usage.
369 #
373 #
370 # But at least now, all the pieces have been separated and we could, in
374 # But at least now, all the pieces have been separated and we could, in
371 # principle, stop using the mixin. This will ease the transition to the
375 # principle, stop using the mixin. This will ease the transition to the
372 # chainsaw branch.
376 # chainsaw branch.
373
377
374 # For reference, the following is the list of 'self.foo' uses in the Magic
378 # For reference, the following is the list of 'self.foo' uses in the Magic
375 # class as of 2005-12-28. These are names we CAN'T use in the main ipython
379 # class as of 2005-12-28. These are names we CAN'T use in the main ipython
376 # class, to prevent clashes.
380 # class, to prevent clashes.
377
381
378 # ['self.__class__', 'self.__dict__', 'self._inspect', 'self._ofind',
382 # ['self.__class__', 'self.__dict__', 'self._inspect', 'self._ofind',
379 # 'self.arg_err', 'self.extract_input', 'self.format_', 'self.lsmagic',
383 # 'self.arg_err', 'self.extract_input', 'self.format_', 'self.lsmagic',
380 # 'self.magic_', 'self.options_table', 'self.parse', 'self.shell',
384 # 'self.magic_', 'self.options_table', 'self.parse', 'self.shell',
381 # 'self.value']
385 # 'self.value']
382
386
383 class InteractiveShell(object,Magic):
387 class InteractiveShell(object,Magic):
384 """An enhanced console for Python."""
388 """An enhanced console for Python."""
385
389
386 # class attribute to indicate whether the class supports threads or not.
390 # class attribute to indicate whether the class supports threads or not.
387 # Subclasses with thread support should override this as needed.
391 # Subclasses with thread support should override this as needed.
388 isthreaded = False
392 isthreaded = False
389
393
390 def __init__(self,name,usage=None,rc=Struct(opts=None,args=None),
394 def __init__(self,name,usage=None,rc=Struct(opts=None,args=None),
391 user_ns=None,user_global_ns=None,banner2='',
395 user_ns=None,user_global_ns=None,banner2='',
392 custom_exceptions=((),None),embedded=False):
396 custom_exceptions=((),None),embedded=False):
393
397
394 # log system
398 # log system
395 self.logger = Logger(self,logfname='ipython_log.py',logmode='rotate')
399 self.logger = Logger(self,logfname='ipython_log.py',logmode='rotate')
396
400
397 # Job manager (for jobs run as background threads)
401 # Job manager (for jobs run as background threads)
398 self.jobs = BackgroundJobManager()
402 self.jobs = BackgroundJobManager()
399
403
400 # Store the actual shell's name
404 # Store the actual shell's name
401 self.name = name
405 self.name = name
402 self.more = False
406 self.more = False
403
407
404 # We need to know whether the instance is meant for embedding, since
408 # We need to know whether the instance is meant for embedding, since
405 # global/local namespaces need to be handled differently in that case
409 # global/local namespaces need to be handled differently in that case
406 self.embedded = embedded
410 self.embedded = embedded
407 if embedded:
411 if embedded:
408 # Control variable so users can, from within the embedded instance,
412 # Control variable so users can, from within the embedded instance,
409 # permanently deactivate it.
413 # permanently deactivate it.
410 self.embedded_active = True
414 self.embedded_active = True
411
415
412 # command compiler
416 # command compiler
413 self.compile = codeop.CommandCompiler()
417 self.compile = codeop.CommandCompiler()
414
418
415 # User input buffer
419 # User input buffer
416 self.buffer = []
420 self.buffer = []
417
421
418 # Default name given in compilation of code
422 # Default name given in compilation of code
419 self.filename = '<ipython console>'
423 self.filename = '<ipython console>'
420
424
421 # Install our own quitter instead of the builtins. For python2.3-2.4,
425 # Install our own quitter instead of the builtins. For python2.3-2.4,
422 # this brings in behavior like 2.5, and for 2.5 it's identical.
426 # this brings in behavior like 2.5, and for 2.5 it's identical.
423 __builtin__.exit = Quitter(self,'exit')
427 __builtin__.exit = Quitter(self,'exit')
424 __builtin__.quit = Quitter(self,'quit')
428 __builtin__.quit = Quitter(self,'quit')
425
429
426 # Make an empty namespace, which extension writers can rely on both
430 # Make an empty namespace, which extension writers can rely on both
427 # existing and NEVER being used by ipython itself. This gives them a
431 # existing and NEVER being used by ipython itself. This gives them a
428 # convenient location for storing additional information and state
432 # convenient location for storing additional information and state
429 # their extensions may require, without fear of collisions with other
433 # their extensions may require, without fear of collisions with other
430 # ipython names that may develop later.
434 # ipython names that may develop later.
431 self.meta = Struct()
435 self.meta = Struct()
432
436
433 # Create the namespace where the user will operate. user_ns is
437 # Create the namespace where the user will operate. user_ns is
434 # normally the only one used, and it is passed to the exec calls as
438 # normally the only one used, and it is passed to the exec calls as
435 # the locals argument. But we do carry a user_global_ns namespace
439 # the locals argument. But we do carry a user_global_ns namespace
436 # given as the exec 'globals' argument, This is useful in embedding
440 # given as the exec 'globals' argument, This is useful in embedding
437 # situations where the ipython shell opens in a context where the
441 # situations where the ipython shell opens in a context where the
438 # distinction between locals and globals is meaningful. For
442 # distinction between locals and globals is meaningful. For
439 # non-embedded contexts, it is just the same object as the user_ns dict.
443 # non-embedded contexts, it is just the same object as the user_ns dict.
440
444
441 # FIXME. For some strange reason, __builtins__ is showing up at user
445 # FIXME. For some strange reason, __builtins__ is showing up at user
442 # level as a dict instead of a module. This is a manual fix, but I
446 # level as a dict instead of a module. This is a manual fix, but I
443 # should really track down where the problem is coming from. Alex
447 # should really track down where the problem is coming from. Alex
444 # Schmolck reported this problem first.
448 # Schmolck reported this problem first.
445
449
446 # A useful post by Alex Martelli on this topic:
450 # A useful post by Alex Martelli on this topic:
447 # Re: inconsistent value from __builtins__
451 # Re: inconsistent value from __builtins__
448 # Von: Alex Martelli <aleaxit@yahoo.com>
452 # Von: Alex Martelli <aleaxit@yahoo.com>
449 # Datum: Freitag 01 Oktober 2004 04:45:34 nachmittags/abends
453 # Datum: Freitag 01 Oktober 2004 04:45:34 nachmittags/abends
450 # Gruppen: comp.lang.python
454 # Gruppen: comp.lang.python
451
455
452 # Michael Hohn <hohn@hooknose.lbl.gov> wrote:
456 # Michael Hohn <hohn@hooknose.lbl.gov> wrote:
453 # > >>> print type(builtin_check.get_global_binding('__builtins__'))
457 # > >>> print type(builtin_check.get_global_binding('__builtins__'))
454 # > <type 'dict'>
458 # > <type 'dict'>
455 # > >>> print type(__builtins__)
459 # > >>> print type(__builtins__)
456 # > <type 'module'>
460 # > <type 'module'>
457 # > Is this difference in return value intentional?
461 # > Is this difference in return value intentional?
458
462
459 # Well, it's documented that '__builtins__' can be either a dictionary
463 # Well, it's documented that '__builtins__' can be either a dictionary
460 # or a module, and it's been that way for a long time. Whether it's
464 # or a module, and it's been that way for a long time. Whether it's
461 # intentional (or sensible), I don't know. In any case, the idea is
465 # intentional (or sensible), I don't know. In any case, the idea is
462 # that if you need to access the built-in namespace directly, you
466 # that if you need to access the built-in namespace directly, you
463 # should start with "import __builtin__" (note, no 's') which will
467 # should start with "import __builtin__" (note, no 's') which will
464 # definitely give you a module. Yeah, it's somewhat confusing:-(.
468 # definitely give you a module. Yeah, it's somewhat confusing:-(.
465
469
466 # These routines return properly built dicts as needed by the rest of
470 # These routines return properly built dicts as needed by the rest of
467 # the code, and can also be used by extension writers to generate
471 # the code, and can also be used by extension writers to generate
468 # properly initialized namespaces.
472 # properly initialized namespaces.
469 user_ns, user_global_ns = IPython.ipapi.make_user_namespaces(user_ns,
473 user_ns, user_global_ns = IPython.ipapi.make_user_namespaces(user_ns,
470 user_global_ns)
474 user_global_ns)
471
475
472 # Assign namespaces
476 # Assign namespaces
473 # This is the namespace where all normal user variables live
477 # This is the namespace where all normal user variables live
474 self.user_ns = user_ns
478 self.user_ns = user_ns
475 self.user_global_ns = user_global_ns
479 self.user_global_ns = user_global_ns
476
480
477 # An auxiliary namespace that checks what parts of the user_ns were
481 # An auxiliary namespace that checks what parts of the user_ns were
478 # loaded at startup, so we can list later only variables defined in
482 # loaded at startup, so we can list later only variables defined in
479 # actual interactive use. Since it is always a subset of user_ns, it
483 # actual interactive use. Since it is always a subset of user_ns, it
480 # doesn't need to be seaparately tracked in the ns_table
484 # doesn't need to be seaparately tracked in the ns_table
481 self.user_config_ns = {}
485 self.user_config_ns = {}
482
486
483 # A namespace to keep track of internal data structures to prevent
487 # A namespace to keep track of internal data structures to prevent
484 # them from cluttering user-visible stuff. Will be updated later
488 # them from cluttering user-visible stuff. Will be updated later
485 self.internal_ns = {}
489 self.internal_ns = {}
486
490
487 # Namespace of system aliases. Each entry in the alias
491 # Namespace of system aliases. Each entry in the alias
488 # table must be a 2-tuple of the form (N,name), where N is the number
492 # table must be a 2-tuple of the form (N,name), where N is the number
489 # of positional arguments of the alias.
493 # of positional arguments of the alias.
490 self.alias_table = {}
494 self.alias_table = {}
491
495
492 # Now that FakeModule produces a real module, we've run into a nasty
496 # Now that FakeModule produces a real module, we've run into a nasty
493 # problem: after script execution (via %run), the module where the user
497 # problem: after script execution (via %run), the module where the user
494 # code ran is deleted. Now that this object is a true module (needed
498 # code ran is deleted. Now that this object is a true module (needed
495 # so docetst and other tools work correctly), the Python module
499 # so docetst and other tools work correctly), the Python module
496 # teardown mechanism runs over it, and sets to None every variable
500 # teardown mechanism runs over it, and sets to None every variable
497 # present in that module. Top-level references to objects from the
501 # present in that module. Top-level references to objects from the
498 # script survive, because the user_ns is updated with them. However,
502 # script survive, because the user_ns is updated with them. However,
499 # calling functions defined in the script that use other things from
503 # calling functions defined in the script that use other things from
500 # the script will fail, because the function's closure had references
504 # the script will fail, because the function's closure had references
501 # to the original objects, which are now all None. So we must protect
505 # to the original objects, which are now all None. So we must protect
502 # these modules from deletion by keeping a cache.
506 # these modules from deletion by keeping a cache.
503 #
507 #
504 # To avoid keeping stale modules around (we only need the one from the
508 # To avoid keeping stale modules around (we only need the one from the
505 # last run), we use a dict keyed with the full path to the script, so
509 # last run), we use a dict keyed with the full path to the script, so
506 # only the last version of the module is held in the cache. Note,
510 # only the last version of the module is held in the cache. Note,
507 # however, that we must cache the module *namespace contents* (their
511 # however, that we must cache the module *namespace contents* (their
508 # __dict__). Because if we try to cache the actual modules, old ones
512 # __dict__). Because if we try to cache the actual modules, old ones
509 # (uncached) could be destroyed while still holding references (such as
513 # (uncached) could be destroyed while still holding references (such as
510 # those held by GUI objects that tend to be long-lived)>
514 # those held by GUI objects that tend to be long-lived)>
511 #
515 #
512 # The %reset command will flush this cache. See the cache_main_mod()
516 # The %reset command will flush this cache. See the cache_main_mod()
513 # and clear_main_mod_cache() methods for details on use.
517 # and clear_main_mod_cache() methods for details on use.
514
518
515 # This is the cache used for 'main' namespaces
519 # This is the cache used for 'main' namespaces
516 self._main_ns_cache = {}
520 self._main_ns_cache = {}
517 # And this is the single instance of FakeModule whose __dict__ we keep
521 # And this is the single instance of FakeModule whose __dict__ we keep
518 # copying and clearing for reuse on each %run
522 # copying and clearing for reuse on each %run
519 self._user_main_module = FakeModule()
523 self._user_main_module = FakeModule()
520
524
521 # A table holding all the namespaces IPython deals with, so that
525 # A table holding all the namespaces IPython deals with, so that
522 # introspection facilities can search easily.
526 # introspection facilities can search easily.
523 self.ns_table = {'user':user_ns,
527 self.ns_table = {'user':user_ns,
524 'user_global':user_global_ns,
528 'user_global':user_global_ns,
525 'alias':self.alias_table,
529 'alias':self.alias_table,
526 'internal':self.internal_ns,
530 'internal':self.internal_ns,
527 'builtin':__builtin__.__dict__
531 'builtin':__builtin__.__dict__
528 }
532 }
529
533
530 # Similarly, track all namespaces where references can be held and that
534 # Similarly, track all namespaces where references can be held and that
531 # we can safely clear (so it can NOT include builtin). This one can be
535 # we can safely clear (so it can NOT include builtin). This one can be
532 # a simple list.
536 # a simple list.
533 self.ns_refs_table = [ user_ns, user_global_ns, self.user_config_ns,
537 self.ns_refs_table = [ user_ns, user_global_ns, self.user_config_ns,
534 self.alias_table, self.internal_ns,
538 self.alias_table, self.internal_ns,
535 self._main_ns_cache ]
539 self._main_ns_cache ]
536
540
537 # We need to insert into sys.modules something that looks like a
541 # We need to insert into sys.modules something that looks like a
538 # module but which accesses the IPython namespace, for shelve and
542 # module but which accesses the IPython namespace, for shelve and
539 # pickle to work interactively. Normally they rely on getting
543 # pickle to work interactively. Normally they rely on getting
540 # everything out of __main__, but for embedding purposes each IPython
544 # everything out of __main__, but for embedding purposes each IPython
541 # instance has its own private namespace, so we can't go shoving
545 # instance has its own private namespace, so we can't go shoving
542 # everything into __main__.
546 # everything into __main__.
543
547
544 # note, however, that we should only do this for non-embedded
548 # note, however, that we should only do this for non-embedded
545 # ipythons, which really mimic the __main__.__dict__ with their own
549 # ipythons, which really mimic the __main__.__dict__ with their own
546 # namespace. Embedded instances, on the other hand, should not do
550 # namespace. Embedded instances, on the other hand, should not do
547 # this because they need to manage the user local/global namespaces
551 # this because they need to manage the user local/global namespaces
548 # only, but they live within a 'normal' __main__ (meaning, they
552 # only, but they live within a 'normal' __main__ (meaning, they
549 # shouldn't overtake the execution environment of the script they're
553 # shouldn't overtake the execution environment of the script they're
550 # embedded in).
554 # embedded in).
551
555
552 if not embedded:
556 if not embedded:
553 try:
557 try:
554 main_name = self.user_ns['__name__']
558 main_name = self.user_ns['__name__']
555 except KeyError:
559 except KeyError:
556 raise KeyError,'user_ns dictionary MUST have a "__name__" key'
560 raise KeyError,'user_ns dictionary MUST have a "__name__" key'
557 else:
561 else:
558 #print "pickle hack in place" # dbg
562 #print "pickle hack in place" # dbg
559 #print 'main_name:',main_name # dbg
563 #print 'main_name:',main_name # dbg
560 sys.modules[main_name] = FakeModule(self.user_ns)
564 sys.modules[main_name] = FakeModule(self.user_ns)
561
565
562 # List of input with multi-line handling.
566 # List of input with multi-line handling.
563 self.input_hist = InputList()
567 self.input_hist = InputList()
564 # This one will hold the 'raw' input history, without any
568 # This one will hold the 'raw' input history, without any
565 # pre-processing. This will allow users to retrieve the input just as
569 # pre-processing. This will allow users to retrieve the input just as
566 # it was exactly typed in by the user, with %hist -r.
570 # it was exactly typed in by the user, with %hist -r.
567 self.input_hist_raw = InputList()
571 self.input_hist_raw = InputList()
568
572
569 # list of visited directories
573 # list of visited directories
570 try:
574 try:
571 self.dir_hist = [os.getcwd()]
575 self.dir_hist = [os.getcwd()]
572 except OSError:
576 except OSError:
573 self.dir_hist = []
577 self.dir_hist = []
574
578
575 # dict of output history
579 # dict of output history
576 self.output_hist = {}
580 self.output_hist = {}
577
581
578 # Get system encoding at startup time. Certain terminals (like Emacs
582 # Get system encoding at startup time. Certain terminals (like Emacs
579 # under Win32 have it set to None, and we need to have a known valid
583 # under Win32 have it set to None, and we need to have a known valid
580 # encoding to use in the raw_input() method
584 # encoding to use in the raw_input() method
581 try:
585 try:
582 self.stdin_encoding = sys.stdin.encoding or 'ascii'
586 self.stdin_encoding = sys.stdin.encoding or 'ascii'
583 except AttributeError:
587 except AttributeError:
584 self.stdin_encoding = 'ascii'
588 self.stdin_encoding = 'ascii'
585
589
586 # dict of things NOT to alias (keywords, builtins and some magics)
590 # dict of things NOT to alias (keywords, builtins and some magics)
587 no_alias = {}
591 no_alias = {}
588 no_alias_magics = ['cd','popd','pushd','dhist','alias','unalias']
592 no_alias_magics = ['cd','popd','pushd','dhist','alias','unalias']
589 for key in keyword.kwlist + no_alias_magics:
593 for key in keyword.kwlist + no_alias_magics:
590 no_alias[key] = 1
594 no_alias[key] = 1
591 no_alias.update(__builtin__.__dict__)
595 no_alias.update(__builtin__.__dict__)
592 self.no_alias = no_alias
596 self.no_alias = no_alias
593
597
594 # Object variable to store code object waiting execution. This is
598 # Object variable to store code object waiting execution. This is
595 # used mainly by the multithreaded shells, but it can come in handy in
599 # used mainly by the multithreaded shells, but it can come in handy in
596 # other situations. No need to use a Queue here, since it's a single
600 # other situations. No need to use a Queue here, since it's a single
597 # item which gets cleared once run.
601 # item which gets cleared once run.
598 self.code_to_run = None
602 self.code_to_run = None
599
603
600 # escapes for automatic behavior on the command line
604 # escapes for automatic behavior on the command line
601 self.ESC_SHELL = '!'
605 self.ESC_SHELL = '!'
602 self.ESC_SH_CAP = '!!'
606 self.ESC_SH_CAP = '!!'
603 self.ESC_HELP = '?'
607 self.ESC_HELP = '?'
604 self.ESC_MAGIC = '%'
608 self.ESC_MAGIC = '%'
605 self.ESC_QUOTE = ','
609 self.ESC_QUOTE = ','
606 self.ESC_QUOTE2 = ';'
610 self.ESC_QUOTE2 = ';'
607 self.ESC_PAREN = '/'
611 self.ESC_PAREN = '/'
608
612
609 # And their associated handlers
613 # And their associated handlers
610 self.esc_handlers = {self.ESC_PAREN : self.handle_auto,
614 self.esc_handlers = {self.ESC_PAREN : self.handle_auto,
611 self.ESC_QUOTE : self.handle_auto,
615 self.ESC_QUOTE : self.handle_auto,
612 self.ESC_QUOTE2 : self.handle_auto,
616 self.ESC_QUOTE2 : self.handle_auto,
613 self.ESC_MAGIC : self.handle_magic,
617 self.ESC_MAGIC : self.handle_magic,
614 self.ESC_HELP : self.handle_help,
618 self.ESC_HELP : self.handle_help,
615 self.ESC_SHELL : self.handle_shell_escape,
619 self.ESC_SHELL : self.handle_shell_escape,
616 self.ESC_SH_CAP : self.handle_shell_escape,
620 self.ESC_SH_CAP : self.handle_shell_escape,
617 }
621 }
618
622
619 # class initializations
623 # class initializations
620 Magic.__init__(self,self)
624 Magic.__init__(self,self)
621
625
622 # Python source parser/formatter for syntax highlighting
626 # Python source parser/formatter for syntax highlighting
623 pyformat = PyColorize.Parser().format
627 pyformat = PyColorize.Parser().format
624 self.pycolorize = lambda src: pyformat(src,'str',self.rc['colors'])
628 self.pycolorize = lambda src: pyformat(src,'str',self.rc['colors'])
625
629
626 # hooks holds pointers used for user-side customizations
630 # hooks holds pointers used for user-side customizations
627 self.hooks = Struct()
631 self.hooks = Struct()
628
632
629 self.strdispatchers = {}
633 self.strdispatchers = {}
630
634
631 # Set all default hooks, defined in the IPython.hooks module.
635 # Set all default hooks, defined in the IPython.hooks module.
632 hooks = IPython.hooks
636 hooks = IPython.hooks
633 for hook_name in hooks.__all__:
637 for hook_name in hooks.__all__:
634 # default hooks have priority 100, i.e. low; user hooks should have
638 # default hooks have priority 100, i.e. low; user hooks should have
635 # 0-100 priority
639 # 0-100 priority
636 self.set_hook(hook_name,getattr(hooks,hook_name), 100)
640 self.set_hook(hook_name,getattr(hooks,hook_name), 100)
637 #print "bound hook",hook_name
641 #print "bound hook",hook_name
638
642
639 # Flag to mark unconditional exit
643 # Flag to mark unconditional exit
640 self.exit_now = False
644 self.exit_now = False
641
645
642 self.usage_min = """\
646 self.usage_min = """\
643 An enhanced console for Python.
647 An enhanced console for Python.
644 Some of its features are:
648 Some of its features are:
645 - Readline support if the readline library is present.
649 - Readline support if the readline library is present.
646 - Tab completion in the local namespace.
650 - Tab completion in the local namespace.
647 - Logging of input, see command-line options.
651 - Logging of input, see command-line options.
648 - System shell escape via ! , eg !ls.
652 - System shell escape via ! , eg !ls.
649 - Magic commands, starting with a % (like %ls, %pwd, %cd, etc.)
653 - Magic commands, starting with a % (like %ls, %pwd, %cd, etc.)
650 - Keeps track of locally defined variables via %who, %whos.
654 - Keeps track of locally defined variables via %who, %whos.
651 - Show object information with a ? eg ?x or x? (use ?? for more info).
655 - Show object information with a ? eg ?x or x? (use ?? for more info).
652 """
656 """
653 if usage: self.usage = usage
657 if usage: self.usage = usage
654 else: self.usage = self.usage_min
658 else: self.usage = self.usage_min
655
659
656 # Storage
660 # Storage
657 self.rc = rc # This will hold all configuration information
661 self.rc = rc # This will hold all configuration information
658 self.pager = 'less'
662 self.pager = 'less'
659 # temporary files used for various purposes. Deleted at exit.
663 # temporary files used for various purposes. Deleted at exit.
660 self.tempfiles = []
664 self.tempfiles = []
661
665
662 # Keep track of readline usage (later set by init_readline)
666 # Keep track of readline usage (later set by init_readline)
663 self.has_readline = False
667 self.has_readline = False
664
668
665 # template for logfile headers. It gets resolved at runtime by the
669 # template for logfile headers. It gets resolved at runtime by the
666 # logstart method.
670 # logstart method.
667 self.loghead_tpl = \
671 self.loghead_tpl = \
668 """#log# Automatic Logger file. *** THIS MUST BE THE FIRST LINE ***
672 """#log# Automatic Logger file. *** THIS MUST BE THE FIRST LINE ***
669 #log# DO NOT CHANGE THIS LINE OR THE TWO BELOW
673 #log# DO NOT CHANGE THIS LINE OR THE TWO BELOW
670 #log# opts = %s
674 #log# opts = %s
671 #log# args = %s
675 #log# args = %s
672 #log# It is safe to make manual edits below here.
676 #log# It is safe to make manual edits below here.
673 #log#-----------------------------------------------------------------------
677 #log#-----------------------------------------------------------------------
674 """
678 """
675 # for pushd/popd management
679 # for pushd/popd management
676 try:
680 try:
677 self.home_dir = get_home_dir()
681 self.home_dir = get_home_dir()
678 except HomeDirError,msg:
682 except HomeDirError,msg:
679 fatal(msg)
683 fatal(msg)
680
684
681 self.dir_stack = []
685 self.dir_stack = []
682
686
683 # Functions to call the underlying shell.
687 # Functions to call the underlying shell.
684
688
685 # The first is similar to os.system, but it doesn't return a value,
689 # The first is similar to os.system, but it doesn't return a value,
686 # and it allows interpolation of variables in the user's namespace.
690 # and it allows interpolation of variables in the user's namespace.
687 self.system = lambda cmd: \
691 self.system = lambda cmd: \
688 self.hooks.shell_hook(self.var_expand(cmd,depth=2))
692 self.hooks.shell_hook(self.var_expand(cmd,depth=2))
689
693
690 # These are for getoutput and getoutputerror:
694 # These are for getoutput and getoutputerror:
691 self.getoutput = lambda cmd: \
695 self.getoutput = lambda cmd: \
692 getoutput(self.var_expand(cmd,depth=2),
696 getoutput(self.var_expand(cmd,depth=2),
693 header=self.rc.system_header,
697 header=self.rc.system_header,
694 verbose=self.rc.system_verbose)
698 verbose=self.rc.system_verbose)
695
699
696 self.getoutputerror = lambda cmd: \
700 self.getoutputerror = lambda cmd: \
697 getoutputerror(self.var_expand(cmd,depth=2),
701 getoutputerror(self.var_expand(cmd,depth=2),
698 header=self.rc.system_header,
702 header=self.rc.system_header,
699 verbose=self.rc.system_verbose)
703 verbose=self.rc.system_verbose)
700
704
701
705
702 # keep track of where we started running (mainly for crash post-mortem)
706 # keep track of where we started running (mainly for crash post-mortem)
703 self.starting_dir = os.getcwd()
707 self.starting_dir = os.getcwd()
704
708
705 # Various switches which can be set
709 # Various switches which can be set
706 self.CACHELENGTH = 5000 # this is cheap, it's just text
710 self.CACHELENGTH = 5000 # this is cheap, it's just text
707 self.BANNER = "Python %(version)s on %(platform)s\n" % sys.__dict__
711 self.BANNER = "Python %(version)s on %(platform)s\n" % sys.__dict__
708 self.banner2 = banner2
712 self.banner2 = banner2
709
713
710 # TraceBack handlers:
714 # TraceBack handlers:
711
715
712 # Syntax error handler.
716 # Syntax error handler.
713 self.SyntaxTB = SyntaxTB(color_scheme='NoColor')
717 self.SyntaxTB = SyntaxTB(color_scheme='NoColor')
714
718
715 # The interactive one is initialized with an offset, meaning we always
719 # The interactive one is initialized with an offset, meaning we always
716 # want to remove the topmost item in the traceback, which is our own
720 # want to remove the topmost item in the traceback, which is our own
717 # internal code. Valid modes: ['Plain','Context','Verbose']
721 # internal code. Valid modes: ['Plain','Context','Verbose']
718 self.InteractiveTB = ultraTB.AutoFormattedTB(mode = 'Plain',
722 self.InteractiveTB = ultraTB.AutoFormattedTB(mode = 'Plain',
719 color_scheme='NoColor',
723 color_scheme='NoColor',
720 tb_offset = 1)
724 tb_offset = 1)
721
725
722 # IPython itself shouldn't crash. This will produce a detailed
726 # IPython itself shouldn't crash. This will produce a detailed
723 # post-mortem if it does. But we only install the crash handler for
727 # post-mortem if it does. But we only install the crash handler for
724 # non-threaded shells, the threaded ones use a normal verbose reporter
728 # non-threaded shells, the threaded ones use a normal verbose reporter
725 # and lose the crash handler. This is because exceptions in the main
729 # and lose the crash handler. This is because exceptions in the main
726 # thread (such as in GUI code) propagate directly to sys.excepthook,
730 # thread (such as in GUI code) propagate directly to sys.excepthook,
727 # and there's no point in printing crash dumps for every user exception.
731 # and there's no point in printing crash dumps for every user exception.
728 if self.isthreaded:
732 if self.isthreaded:
729 ipCrashHandler = ultraTB.FormattedTB()
733 ipCrashHandler = ultraTB.FormattedTB()
730 else:
734 else:
731 from IPython import CrashHandler
735 from IPython import CrashHandler
732 ipCrashHandler = CrashHandler.IPythonCrashHandler(self)
736 ipCrashHandler = CrashHandler.IPythonCrashHandler(self)
733 self.set_crash_handler(ipCrashHandler)
737 self.set_crash_handler(ipCrashHandler)
734
738
735 # and add any custom exception handlers the user may have specified
739 # and add any custom exception handlers the user may have specified
736 self.set_custom_exc(*custom_exceptions)
740 self.set_custom_exc(*custom_exceptions)
737
741
738 # indentation management
742 # indentation management
739 self.autoindent = False
743 self.autoindent = False
740 self.indent_current_nsp = 0
744 self.indent_current_nsp = 0
741
745
742 # Make some aliases automatically
746 # Make some aliases automatically
743 # Prepare list of shell aliases to auto-define
747 # Prepare list of shell aliases to auto-define
744 if os.name == 'posix':
748 if os.name == 'posix':
745 auto_alias = ('mkdir mkdir', 'rmdir rmdir',
749 auto_alias = ('mkdir mkdir', 'rmdir rmdir',
746 'mv mv -i','rm rm -i','cp cp -i',
750 'mv mv -i','rm rm -i','cp cp -i',
747 'cat cat','less less','clear clear',
751 'cat cat','less less','clear clear',
748 # a better ls
752 # a better ls
749 'ls ls -F',
753 'ls ls -F',
750 # long ls
754 # long ls
751 'll ls -lF')
755 'll ls -lF')
752 # Extra ls aliases with color, which need special treatment on BSD
756 # Extra ls aliases with color, which need special treatment on BSD
753 # variants
757 # variants
754 ls_extra = ( # color ls
758 ls_extra = ( # color ls
755 'lc ls -F -o --color',
759 'lc ls -F -o --color',
756 # ls normal files only
760 # ls normal files only
757 'lf ls -F -o --color %l | grep ^-',
761 'lf ls -F -o --color %l | grep ^-',
758 # ls symbolic links
762 # ls symbolic links
759 'lk ls -F -o --color %l | grep ^l',
763 'lk ls -F -o --color %l | grep ^l',
760 # directories or links to directories,
764 # directories or links to directories,
761 'ldir ls -F -o --color %l | grep /$',
765 'ldir ls -F -o --color %l | grep /$',
762 # things which are executable
766 # things which are executable
763 'lx ls -F -o --color %l | grep ^-..x',
767 'lx ls -F -o --color %l | grep ^-..x',
764 )
768 )
765 # The BSDs don't ship GNU ls, so they don't understand the
769 # The BSDs don't ship GNU ls, so they don't understand the
766 # --color switch out of the box
770 # --color switch out of the box
767 if 'bsd' in sys.platform:
771 if 'bsd' in sys.platform:
768 ls_extra = ( # ls normal files only
772 ls_extra = ( # ls normal files only
769 'lf ls -lF | grep ^-',
773 'lf ls -lF | grep ^-',
770 # ls symbolic links
774 # ls symbolic links
771 'lk ls -lF | grep ^l',
775 'lk ls -lF | grep ^l',
772 # directories or links to directories,
776 # directories or links to directories,
773 'ldir ls -lF | grep /$',
777 'ldir ls -lF | grep /$',
774 # things which are executable
778 # things which are executable
775 'lx ls -lF | grep ^-..x',
779 'lx ls -lF | grep ^-..x',
776 )
780 )
777 auto_alias = auto_alias + ls_extra
781 auto_alias = auto_alias + ls_extra
778 elif os.name in ['nt','dos']:
782 elif os.name in ['nt','dos']:
779 auto_alias = ('ls dir /on',
783 auto_alias = ('ls dir /on',
780 'ddir dir /ad /on', 'ldir dir /ad /on',
784 'ddir dir /ad /on', 'ldir dir /ad /on',
781 'mkdir mkdir','rmdir rmdir','echo echo',
785 'mkdir mkdir','rmdir rmdir','echo echo',
782 'ren ren','cls cls','copy copy')
786 'ren ren','cls cls','copy copy')
783 else:
787 else:
784 auto_alias = ()
788 auto_alias = ()
785 self.auto_alias = [s.split(None,1) for s in auto_alias]
789 self.auto_alias = [s.split(None,1) for s in auto_alias]
786
790
787 # Produce a public API instance
791 # Produce a public API instance
788 self.api = IPython.ipapi.IPApi(self)
792 self.api = IPython.ipapi.IPApi(self)
789
793
790 # Initialize all user-visible namespaces
794 # Initialize all user-visible namespaces
791 self.init_namespaces()
795 self.init_namespaces()
792
796
793 # Call the actual (public) initializer
797 # Call the actual (public) initializer
794 self.init_auto_alias()
798 self.init_auto_alias()
795
799
796 # track which builtins we add, so we can clean up later
800 # track which builtins we add, so we can clean up later
797 self.builtins_added = {}
801 self.builtins_added = {}
798 # This method will add the necessary builtins for operation, but
802 # This method will add the necessary builtins for operation, but
799 # tracking what it did via the builtins_added dict.
803 # tracking what it did via the builtins_added dict.
800
804
801 #TODO: remove this, redundant
805 #TODO: remove this, redundant
802 self.add_builtins()
806 self.add_builtins()
803 # end __init__
807 # end __init__
804
808
805 def var_expand(self,cmd,depth=0):
809 def var_expand(self,cmd,depth=0):
806 """Expand python variables in a string.
810 """Expand python variables in a string.
807
811
808 The depth argument indicates how many frames above the caller should
812 The depth argument indicates how many frames above the caller should
809 be walked to look for the local namespace where to expand variables.
813 be walked to look for the local namespace where to expand variables.
810
814
811 The global namespace for expansion is always the user's interactive
815 The global namespace for expansion is always the user's interactive
812 namespace.
816 namespace.
813 """
817 """
814
818
815 return str(ItplNS(cmd,
819 return str(ItplNS(cmd,
816 self.user_ns, # globals
820 self.user_ns, # globals
817 # Skip our own frame in searching for locals:
821 # Skip our own frame in searching for locals:
818 sys._getframe(depth+1).f_locals # locals
822 sys._getframe(depth+1).f_locals # locals
819 ))
823 ))
820
824
821 def pre_config_initialization(self):
825 def pre_config_initialization(self):
822 """Pre-configuration init method
826 """Pre-configuration init method
823
827
824 This is called before the configuration files are processed to
828 This is called before the configuration files are processed to
825 prepare the services the config files might need.
829 prepare the services the config files might need.
826
830
827 self.rc already has reasonable default values at this point.
831 self.rc already has reasonable default values at this point.
828 """
832 """
829 rc = self.rc
833 rc = self.rc
830 try:
834 try:
831 self.db = pickleshare.PickleShareDB(rc.ipythondir + "/db")
835 self.db = pickleshare.PickleShareDB(rc.ipythondir + "/db")
832 except exceptions.UnicodeDecodeError:
836 except exceptions.UnicodeDecodeError:
833 print "Your ipythondir can't be decoded to unicode!"
837 print "Your ipythondir can't be decoded to unicode!"
834 print "Please set HOME environment variable to something that"
838 print "Please set HOME environment variable to something that"
835 print r"only has ASCII characters, e.g. c:\home"
839 print r"only has ASCII characters, e.g. c:\home"
836 print "Now it is",rc.ipythondir
840 print "Now it is",rc.ipythondir
837 sys.exit()
841 sys.exit()
838 self.shadowhist = IPython.history.ShadowHist(self.db)
842 self.shadowhist = IPython.history.ShadowHist(self.db)
839
843
840 def post_config_initialization(self):
844 def post_config_initialization(self):
841 """Post configuration init method
845 """Post configuration init method
842
846
843 This is called after the configuration files have been processed to
847 This is called after the configuration files have been processed to
844 'finalize' the initialization."""
848 'finalize' the initialization."""
845
849
846 rc = self.rc
850 rc = self.rc
847
851
848 # Object inspector
852 # Object inspector
849 self.inspector = OInspect.Inspector(OInspect.InspectColors,
853 self.inspector = OInspect.Inspector(OInspect.InspectColors,
850 PyColorize.ANSICodeColors,
854 PyColorize.ANSICodeColors,
851 'NoColor',
855 'NoColor',
852 rc.object_info_string_level)
856 rc.object_info_string_level)
853
857
854 self.rl_next_input = None
858 self.rl_next_input = None
855 self.rl_do_indent = False
859 self.rl_do_indent = False
856 # Load readline proper
860 # Load readline proper
857 if rc.readline:
861 if rc.readline:
858 self.init_readline()
862 self.init_readline()
859
863
860 # local shortcut, this is used a LOT
864 # local shortcut, this is used a LOT
861 self.log = self.logger.log
865 self.log = self.logger.log
862
866
863 # Initialize cache, set in/out prompts and printing system
867 # Initialize cache, set in/out prompts and printing system
864 self.outputcache = CachedOutput(self,
868 self.outputcache = CachedOutput(self,
865 rc.cache_size,
869 rc.cache_size,
866 rc.pprint,
870 rc.pprint,
867 input_sep = rc.separate_in,
871 input_sep = rc.separate_in,
868 output_sep = rc.separate_out,
872 output_sep = rc.separate_out,
869 output_sep2 = rc.separate_out2,
873 output_sep2 = rc.separate_out2,
870 ps1 = rc.prompt_in1,
874 ps1 = rc.prompt_in1,
871 ps2 = rc.prompt_in2,
875 ps2 = rc.prompt_in2,
872 ps_out = rc.prompt_out,
876 ps_out = rc.prompt_out,
873 pad_left = rc.prompts_pad_left)
877 pad_left = rc.prompts_pad_left)
874
878
875 # user may have over-ridden the default print hook:
879 # user may have over-ridden the default print hook:
876 try:
880 try:
877 self.outputcache.__class__.display = self.hooks.display
881 self.outputcache.__class__.display = self.hooks.display
878 except AttributeError:
882 except AttributeError:
879 pass
883 pass
880
884
881 # I don't like assigning globally to sys, because it means when
885 # I don't like assigning globally to sys, because it means when
882 # embedding instances, each embedded instance overrides the previous
886 # embedding instances, each embedded instance overrides the previous
883 # choice. But sys.displayhook seems to be called internally by exec,
887 # choice. But sys.displayhook seems to be called internally by exec,
884 # so I don't see a way around it. We first save the original and then
888 # so I don't see a way around it. We first save the original and then
885 # overwrite it.
889 # overwrite it.
886 self.sys_displayhook = sys.displayhook
890 self.sys_displayhook = sys.displayhook
887 sys.displayhook = self.outputcache
891 sys.displayhook = self.outputcache
888
892
889 # Do a proper resetting of doctest, including the necessary displayhook
893 # Do a proper resetting of doctest, including the necessary displayhook
890 # monkeypatching
894 # monkeypatching
891 try:
895 try:
892 doctest_reload()
896 doctest_reload()
893 except ImportError:
897 except ImportError:
894 warn("doctest module does not exist.")
898 warn("doctest module does not exist.")
895
899
896 # Set user colors (don't do it in the constructor above so that it
900 # Set user colors (don't do it in the constructor above so that it
897 # doesn't crash if colors option is invalid)
901 # doesn't crash if colors option is invalid)
898 self.magic_colors(rc.colors)
902 self.magic_colors(rc.colors)
899
903
900 # Set calling of pdb on exceptions
904 # Set calling of pdb on exceptions
901 self.call_pdb = rc.pdb
905 self.call_pdb = rc.pdb
902
906
903 # Load user aliases
907 # Load user aliases
904 for alias in rc.alias:
908 for alias in rc.alias:
905 self.magic_alias(alias)
909 self.magic_alias(alias)
906
910
907 self.hooks.late_startup_hook()
911 self.hooks.late_startup_hook()
908
912
909 for cmd in self.rc.autoexec:
913 for cmd in self.rc.autoexec:
910 #print "autoexec>",cmd #dbg
914 #print "autoexec>",cmd #dbg
911 self.api.runlines(cmd)
915 self.api.runlines(cmd)
912
916
913 batchrun = False
917 batchrun = False
914 for batchfile in [path(arg) for arg in self.rc.args
918 for batchfile in [path(arg) for arg in self.rc.args
915 if arg.lower().endswith('.ipy')]:
919 if arg.lower().endswith('.ipy')]:
916 if not batchfile.isfile():
920 if not batchfile.isfile():
917 print "No such batch file:", batchfile
921 print "No such batch file:", batchfile
918 continue
922 continue
919 self.api.runlines(batchfile.text())
923 self.api.runlines(batchfile.text())
920 batchrun = True
924 batchrun = True
921 # without -i option, exit after running the batch file
925 # without -i option, exit after running the batch file
922 if batchrun and not self.rc.interact:
926 if batchrun and not self.rc.interact:
923 self.ask_exit()
927 self.ask_exit()
924
928
925 def init_namespaces(self):
929 def init_namespaces(self):
926 """Initialize all user-visible namespaces to their minimum defaults.
930 """Initialize all user-visible namespaces to their minimum defaults.
927
931
928 Certain history lists are also initialized here, as they effectively
932 Certain history lists are also initialized here, as they effectively
929 act as user namespaces.
933 act as user namespaces.
930
934
931 Note
935 Note
932 ----
936 ----
933 All data structures here are only filled in, they are NOT reset by this
937 All data structures here are only filled in, they are NOT reset by this
934 method. If they were not empty before, data will simply be added to
938 method. If they were not empty before, data will simply be added to
935 therm.
939 therm.
936 """
940 """
937 # The user namespace MUST have a pointer to the shell itself.
941 # The user namespace MUST have a pointer to the shell itself.
938 self.user_ns[self.name] = self
942 self.user_ns[self.name] = self
939
943
940 # Store the public api instance
944 # Store the public api instance
941 self.user_ns['_ip'] = self.api
945 self.user_ns['_ip'] = self.api
942
946
943 # make global variables for user access to the histories
947 # make global variables for user access to the histories
944 self.user_ns['_ih'] = self.input_hist
948 self.user_ns['_ih'] = self.input_hist
945 self.user_ns['_oh'] = self.output_hist
949 self.user_ns['_oh'] = self.output_hist
946 self.user_ns['_dh'] = self.dir_hist
950 self.user_ns['_dh'] = self.dir_hist
947
951
948 # user aliases to input and output histories
952 # user aliases to input and output histories
949 self.user_ns['In'] = self.input_hist
953 self.user_ns['In'] = self.input_hist
950 self.user_ns['Out'] = self.output_hist
954 self.user_ns['Out'] = self.output_hist
951
955
952 self.user_ns['_sh'] = IPython.shadowns
956 self.user_ns['_sh'] = IPython.shadowns
953
957
954 # Fill the history zero entry, user counter starts at 1
958 # Fill the history zero entry, user counter starts at 1
955 self.input_hist.append('\n')
959 self.input_hist.append('\n')
956 self.input_hist_raw.append('\n')
960 self.input_hist_raw.append('\n')
957
961
958 def add_builtins(self):
962 def add_builtins(self):
959 """Store ipython references into the builtin namespace.
963 """Store ipython references into the builtin namespace.
960
964
961 Some parts of ipython operate via builtins injected here, which hold a
965 Some parts of ipython operate via builtins injected here, which hold a
962 reference to IPython itself."""
966 reference to IPython itself."""
963
967
964 # TODO: deprecate all of these, they are unsafe
968 # TODO: deprecate all of these, they are unsafe
965 builtins_new = dict(__IPYTHON__ = self,
969 builtins_new = dict(__IPYTHON__ = self,
966 ip_set_hook = self.set_hook,
970 ip_set_hook = self.set_hook,
967 jobs = self.jobs,
971 jobs = self.jobs,
968 ipmagic = wrap_deprecated(self.ipmagic,'_ip.magic()'),
972 ipmagic = wrap_deprecated(self.ipmagic,'_ip.magic()'),
969 ipalias = wrap_deprecated(self.ipalias),
973 ipalias = wrap_deprecated(self.ipalias),
970 ipsystem = wrap_deprecated(self.ipsystem,'_ip.system()'),
974 ipsystem = wrap_deprecated(self.ipsystem,'_ip.system()'),
971 #_ip = self.api
975 #_ip = self.api
972 )
976 )
973 for biname,bival in builtins_new.items():
977 for biname,bival in builtins_new.items():
974 try:
978 try:
975 # store the orignal value so we can restore it
979 # store the orignal value so we can restore it
976 self.builtins_added[biname] = __builtin__.__dict__[biname]
980 self.builtins_added[biname] = __builtin__.__dict__[biname]
977 except KeyError:
981 except KeyError:
978 # or mark that it wasn't defined, and we'll just delete it at
982 # or mark that it wasn't defined, and we'll just delete it at
979 # cleanup
983 # cleanup
980 self.builtins_added[biname] = Undefined
984 self.builtins_added[biname] = Undefined
981 __builtin__.__dict__[biname] = bival
985 __builtin__.__dict__[biname] = bival
982
986
983 # Keep in the builtins a flag for when IPython is active. We set it
987 # Keep in the builtins a flag for when IPython is active. We set it
984 # with setdefault so that multiple nested IPythons don't clobber one
988 # with setdefault so that multiple nested IPythons don't clobber one
985 # another. Each will increase its value by one upon being activated,
989 # another. Each will increase its value by one upon being activated,
986 # which also gives us a way to determine the nesting level.
990 # which also gives us a way to determine the nesting level.
987 __builtin__.__dict__.setdefault('__IPYTHON__active',0)
991 __builtin__.__dict__.setdefault('__IPYTHON__active',0)
988
992
989 def clean_builtins(self):
993 def clean_builtins(self):
990 """Remove any builtins which might have been added by add_builtins, or
994 """Remove any builtins which might have been added by add_builtins, or
991 restore overwritten ones to their previous values."""
995 restore overwritten ones to their previous values."""
992 for biname,bival in self.builtins_added.items():
996 for biname,bival in self.builtins_added.items():
993 if bival is Undefined:
997 if bival is Undefined:
994 del __builtin__.__dict__[biname]
998 del __builtin__.__dict__[biname]
995 else:
999 else:
996 __builtin__.__dict__[biname] = bival
1000 __builtin__.__dict__[biname] = bival
997 self.builtins_added.clear()
1001 self.builtins_added.clear()
998
1002
999 def set_hook(self,name,hook, priority = 50, str_key = None, re_key = None):
1003 def set_hook(self,name,hook, priority = 50, str_key = None, re_key = None):
1000 """set_hook(name,hook) -> sets an internal IPython hook.
1004 """set_hook(name,hook) -> sets an internal IPython hook.
1001
1005
1002 IPython exposes some of its internal API as user-modifiable hooks. By
1006 IPython exposes some of its internal API as user-modifiable hooks. By
1003 adding your function to one of these hooks, you can modify IPython's
1007 adding your function to one of these hooks, you can modify IPython's
1004 behavior to call at runtime your own routines."""
1008 behavior to call at runtime your own routines."""
1005
1009
1006 # At some point in the future, this should validate the hook before it
1010 # At some point in the future, this should validate the hook before it
1007 # accepts it. Probably at least check that the hook takes the number
1011 # accepts it. Probably at least check that the hook takes the number
1008 # of args it's supposed to.
1012 # of args it's supposed to.
1009
1013
1010 f = new.instancemethod(hook,self,self.__class__)
1014 f = new.instancemethod(hook,self,self.__class__)
1011
1015
1012 # check if the hook is for strdispatcher first
1016 # check if the hook is for strdispatcher first
1013 if str_key is not None:
1017 if str_key is not None:
1014 sdp = self.strdispatchers.get(name, StrDispatch())
1018 sdp = self.strdispatchers.get(name, StrDispatch())
1015 sdp.add_s(str_key, f, priority )
1019 sdp.add_s(str_key, f, priority )
1016 self.strdispatchers[name] = sdp
1020 self.strdispatchers[name] = sdp
1017 return
1021 return
1018 if re_key is not None:
1022 if re_key is not None:
1019 sdp = self.strdispatchers.get(name, StrDispatch())
1023 sdp = self.strdispatchers.get(name, StrDispatch())
1020 sdp.add_re(re.compile(re_key), f, priority )
1024 sdp.add_re(re.compile(re_key), f, priority )
1021 self.strdispatchers[name] = sdp
1025 self.strdispatchers[name] = sdp
1022 return
1026 return
1023
1027
1024 dp = getattr(self.hooks, name, None)
1028 dp = getattr(self.hooks, name, None)
1025 if name not in IPython.hooks.__all__:
1029 if name not in IPython.hooks.__all__:
1026 print "Warning! Hook '%s' is not one of %s" % (name, IPython.hooks.__all__ )
1030 print "Warning! Hook '%s' is not one of %s" % (name, IPython.hooks.__all__ )
1027 if not dp:
1031 if not dp:
1028 dp = IPython.hooks.CommandChainDispatcher()
1032 dp = IPython.hooks.CommandChainDispatcher()
1029
1033
1030 try:
1034 try:
1031 dp.add(f,priority)
1035 dp.add(f,priority)
1032 except AttributeError:
1036 except AttributeError:
1033 # it was not commandchain, plain old func - replace
1037 # it was not commandchain, plain old func - replace
1034 dp = f
1038 dp = f
1035
1039
1036 setattr(self.hooks,name, dp)
1040 setattr(self.hooks,name, dp)
1037
1041
1038
1042
1039 #setattr(self.hooks,name,new.instancemethod(hook,self,self.__class__))
1043 #setattr(self.hooks,name,new.instancemethod(hook,self,self.__class__))
1040
1044
1041 def set_crash_handler(self,crashHandler):
1045 def set_crash_handler(self,crashHandler):
1042 """Set the IPython crash handler.
1046 """Set the IPython crash handler.
1043
1047
1044 This must be a callable with a signature suitable for use as
1048 This must be a callable with a signature suitable for use as
1045 sys.excepthook."""
1049 sys.excepthook."""
1046
1050
1047 # Install the given crash handler as the Python exception hook
1051 # Install the given crash handler as the Python exception hook
1048 sys.excepthook = crashHandler
1052 sys.excepthook = crashHandler
1049
1053
1050 # The instance will store a pointer to this, so that runtime code
1054 # The instance will store a pointer to this, so that runtime code
1051 # (such as magics) can access it. This is because during the
1055 # (such as magics) can access it. This is because during the
1052 # read-eval loop, it gets temporarily overwritten (to deal with GUI
1056 # read-eval loop, it gets temporarily overwritten (to deal with GUI
1053 # frameworks).
1057 # frameworks).
1054 self.sys_excepthook = sys.excepthook
1058 self.sys_excepthook = sys.excepthook
1055
1059
1056
1060
1057 def set_custom_exc(self,exc_tuple,handler):
1061 def set_custom_exc(self,exc_tuple,handler):
1058 """set_custom_exc(exc_tuple,handler)
1062 """set_custom_exc(exc_tuple,handler)
1059
1063
1060 Set a custom exception handler, which will be called if any of the
1064 Set a custom exception handler, which will be called if any of the
1061 exceptions in exc_tuple occur in the mainloop (specifically, in the
1065 exceptions in exc_tuple occur in the mainloop (specifically, in the
1062 runcode() method.
1066 runcode() method.
1063
1067
1064 Inputs:
1068 Inputs:
1065
1069
1066 - exc_tuple: a *tuple* of valid exceptions to call the defined
1070 - exc_tuple: a *tuple* of valid exceptions to call the defined
1067 handler for. It is very important that you use a tuple, and NOT A
1071 handler for. It is very important that you use a tuple, and NOT A
1068 LIST here, because of the way Python's except statement works. If
1072 LIST here, because of the way Python's except statement works. If
1069 you only want to trap a single exception, use a singleton tuple:
1073 you only want to trap a single exception, use a singleton tuple:
1070
1074
1071 exc_tuple == (MyCustomException,)
1075 exc_tuple == (MyCustomException,)
1072
1076
1073 - handler: this must be defined as a function with the following
1077 - handler: this must be defined as a function with the following
1074 basic interface: def my_handler(self,etype,value,tb).
1078 basic interface: def my_handler(self,etype,value,tb).
1075
1079
1076 This will be made into an instance method (via new.instancemethod)
1080 This will be made into an instance method (via new.instancemethod)
1077 of IPython itself, and it will be called if any of the exceptions
1081 of IPython itself, and it will be called if any of the exceptions
1078 listed in the exc_tuple are caught. If the handler is None, an
1082 listed in the exc_tuple are caught. If the handler is None, an
1079 internal basic one is used, which just prints basic info.
1083 internal basic one is used, which just prints basic info.
1080
1084
1081 WARNING: by putting in your own exception handler into IPython's main
1085 WARNING: by putting in your own exception handler into IPython's main
1082 execution loop, you run a very good chance of nasty crashes. This
1086 execution loop, you run a very good chance of nasty crashes. This
1083 facility should only be used if you really know what you are doing."""
1087 facility should only be used if you really know what you are doing."""
1084
1088
1085 assert type(exc_tuple)==type(()) , \
1089 assert type(exc_tuple)==type(()) , \
1086 "The custom exceptions must be given AS A TUPLE."
1090 "The custom exceptions must be given AS A TUPLE."
1087
1091
1088 def dummy_handler(self,etype,value,tb):
1092 def dummy_handler(self,etype,value,tb):
1089 print '*** Simple custom exception handler ***'
1093 print '*** Simple custom exception handler ***'
1090 print 'Exception type :',etype
1094 print 'Exception type :',etype
1091 print 'Exception value:',value
1095 print 'Exception value:',value
1092 print 'Traceback :',tb
1096 print 'Traceback :',tb
1093 print 'Source code :','\n'.join(self.buffer)
1097 print 'Source code :','\n'.join(self.buffer)
1094
1098
1095 if handler is None: handler = dummy_handler
1099 if handler is None: handler = dummy_handler
1096
1100
1097 self.CustomTB = new.instancemethod(handler,self,self.__class__)
1101 self.CustomTB = new.instancemethod(handler,self,self.__class__)
1098 self.custom_exceptions = exc_tuple
1102 self.custom_exceptions = exc_tuple
1099
1103
1100 def set_custom_completer(self,completer,pos=0):
1104 def set_custom_completer(self,completer,pos=0):
1101 """set_custom_completer(completer,pos=0)
1105 """set_custom_completer(completer,pos=0)
1102
1106
1103 Adds a new custom completer function.
1107 Adds a new custom completer function.
1104
1108
1105 The position argument (defaults to 0) is the index in the completers
1109 The position argument (defaults to 0) is the index in the completers
1106 list where you want the completer to be inserted."""
1110 list where you want the completer to be inserted."""
1107
1111
1108 newcomp = new.instancemethod(completer,self.Completer,
1112 newcomp = new.instancemethod(completer,self.Completer,
1109 self.Completer.__class__)
1113 self.Completer.__class__)
1110 self.Completer.matchers.insert(pos,newcomp)
1114 self.Completer.matchers.insert(pos,newcomp)
1111
1115
1112 def set_completer(self):
1116 def set_completer(self):
1113 """reset readline's completer to be our own."""
1117 """reset readline's completer to be our own."""
1114 self.readline.set_completer(self.Completer.complete)
1118 self.readline.set_completer(self.Completer.complete)
1115
1119
1116 def _get_call_pdb(self):
1120 def _get_call_pdb(self):
1117 return self._call_pdb
1121 return self._call_pdb
1118
1122
1119 def _set_call_pdb(self,val):
1123 def _set_call_pdb(self,val):
1120
1124
1121 if val not in (0,1,False,True):
1125 if val not in (0,1,False,True):
1122 raise ValueError,'new call_pdb value must be boolean'
1126 raise ValueError,'new call_pdb value must be boolean'
1123
1127
1124 # store value in instance
1128 # store value in instance
1125 self._call_pdb = val
1129 self._call_pdb = val
1126
1130
1127 # notify the actual exception handlers
1131 # notify the actual exception handlers
1128 self.InteractiveTB.call_pdb = val
1132 self.InteractiveTB.call_pdb = val
1129 if self.isthreaded:
1133 if self.isthreaded:
1130 try:
1134 try:
1131 self.sys_excepthook.call_pdb = val
1135 self.sys_excepthook.call_pdb = val
1132 except:
1136 except:
1133 warn('Failed to activate pdb for threaded exception handler')
1137 warn('Failed to activate pdb for threaded exception handler')
1134
1138
1135 call_pdb = property(_get_call_pdb,_set_call_pdb,None,
1139 call_pdb = property(_get_call_pdb,_set_call_pdb,None,
1136 'Control auto-activation of pdb at exceptions')
1140 'Control auto-activation of pdb at exceptions')
1137
1141
1138 # These special functions get installed in the builtin namespace, to
1142 # These special functions get installed in the builtin namespace, to
1139 # provide programmatic (pure python) access to magics, aliases and system
1143 # provide programmatic (pure python) access to magics, aliases and system
1140 # calls. This is important for logging, user scripting, and more.
1144 # calls. This is important for logging, user scripting, and more.
1141
1145
1142 # We are basically exposing, via normal python functions, the three
1146 # We are basically exposing, via normal python functions, the three
1143 # mechanisms in which ipython offers special call modes (magics for
1147 # mechanisms in which ipython offers special call modes (magics for
1144 # internal control, aliases for direct system access via pre-selected
1148 # internal control, aliases for direct system access via pre-selected
1145 # names, and !cmd for calling arbitrary system commands).
1149 # names, and !cmd for calling arbitrary system commands).
1146
1150
1147 def ipmagic(self,arg_s):
1151 def ipmagic(self,arg_s):
1148 """Call a magic function by name.
1152 """Call a magic function by name.
1149
1153
1150 Input: a string containing the name of the magic function to call and any
1154 Input: a string containing the name of the magic function to call and any
1151 additional arguments to be passed to the magic.
1155 additional arguments to be passed to the magic.
1152
1156
1153 ipmagic('name -opt foo bar') is equivalent to typing at the ipython
1157 ipmagic('name -opt foo bar') is equivalent to typing at the ipython
1154 prompt:
1158 prompt:
1155
1159
1156 In[1]: %name -opt foo bar
1160 In[1]: %name -opt foo bar
1157
1161
1158 To call a magic without arguments, simply use ipmagic('name').
1162 To call a magic without arguments, simply use ipmagic('name').
1159
1163
1160 This provides a proper Python function to call IPython's magics in any
1164 This provides a proper Python function to call IPython's magics in any
1161 valid Python code you can type at the interpreter, including loops and
1165 valid Python code you can type at the interpreter, including loops and
1162 compound statements. It is added by IPython to the Python builtin
1166 compound statements. It is added by IPython to the Python builtin
1163 namespace upon initialization."""
1167 namespace upon initialization."""
1164
1168
1165 args = arg_s.split(' ',1)
1169 args = arg_s.split(' ',1)
1166 magic_name = args[0]
1170 magic_name = args[0]
1167 magic_name = magic_name.lstrip(self.ESC_MAGIC)
1171 magic_name = magic_name.lstrip(self.ESC_MAGIC)
1168
1172
1169 try:
1173 try:
1170 magic_args = args[1]
1174 magic_args = args[1]
1171 except IndexError:
1175 except IndexError:
1172 magic_args = ''
1176 magic_args = ''
1173 fn = getattr(self,'magic_'+magic_name,None)
1177 fn = getattr(self,'magic_'+magic_name,None)
1174 if fn is None:
1178 if fn is None:
1175 error("Magic function `%s` not found." % magic_name)
1179 error("Magic function `%s` not found." % magic_name)
1176 else:
1180 else:
1177 magic_args = self.var_expand(magic_args,1)
1181 magic_args = self.var_expand(magic_args,1)
1178 return fn(magic_args)
1182 return fn(magic_args)
1179
1183
1180 def ipalias(self,arg_s):
1184 def ipalias(self,arg_s):
1181 """Call an alias by name.
1185 """Call an alias by name.
1182
1186
1183 Input: a string containing the name of the alias to call and any
1187 Input: a string containing the name of the alias to call and any
1184 additional arguments to be passed to the magic.
1188 additional arguments to be passed to the magic.
1185
1189
1186 ipalias('name -opt foo bar') is equivalent to typing at the ipython
1190 ipalias('name -opt foo bar') is equivalent to typing at the ipython
1187 prompt:
1191 prompt:
1188
1192
1189 In[1]: name -opt foo bar
1193 In[1]: name -opt foo bar
1190
1194
1191 To call an alias without arguments, simply use ipalias('name').
1195 To call an alias without arguments, simply use ipalias('name').
1192
1196
1193 This provides a proper Python function to call IPython's aliases in any
1197 This provides a proper Python function to call IPython's aliases in any
1194 valid Python code you can type at the interpreter, including loops and
1198 valid Python code you can type at the interpreter, including loops and
1195 compound statements. It is added by IPython to the Python builtin
1199 compound statements. It is added by IPython to the Python builtin
1196 namespace upon initialization."""
1200 namespace upon initialization."""
1197
1201
1198 args = arg_s.split(' ',1)
1202 args = arg_s.split(' ',1)
1199 alias_name = args[0]
1203 alias_name = args[0]
1200 try:
1204 try:
1201 alias_args = args[1]
1205 alias_args = args[1]
1202 except IndexError:
1206 except IndexError:
1203 alias_args = ''
1207 alias_args = ''
1204 if alias_name in self.alias_table:
1208 if alias_name in self.alias_table:
1205 self.call_alias(alias_name,alias_args)
1209 self.call_alias(alias_name,alias_args)
1206 else:
1210 else:
1207 error("Alias `%s` not found." % alias_name)
1211 error("Alias `%s` not found." % alias_name)
1208
1212
1209 def ipsystem(self,arg_s):
1213 def ipsystem(self,arg_s):
1210 """Make a system call, using IPython."""
1214 """Make a system call, using IPython."""
1211
1215
1212 self.system(arg_s)
1216 self.system(arg_s)
1213
1217
1214 def complete(self,text):
1218 def complete(self,text):
1215 """Return a sorted list of all possible completions on text.
1219 """Return a sorted list of all possible completions on text.
1216
1220
1217 Inputs:
1221 Inputs:
1218
1222
1219 - text: a string of text to be completed on.
1223 - text: a string of text to be completed on.
1220
1224
1221 This is a wrapper around the completion mechanism, similar to what
1225 This is a wrapper around the completion mechanism, similar to what
1222 readline does at the command line when the TAB key is hit. By
1226 readline does at the command line when the TAB key is hit. By
1223 exposing it as a method, it can be used by other non-readline
1227 exposing it as a method, it can be used by other non-readline
1224 environments (such as GUIs) for text completion.
1228 environments (such as GUIs) for text completion.
1225
1229
1226 Simple usage example:
1230 Simple usage example:
1227
1231
1228 In [7]: x = 'hello'
1232 In [7]: x = 'hello'
1229
1233
1230 In [8]: x
1234 In [8]: x
1231 Out[8]: 'hello'
1235 Out[8]: 'hello'
1232
1236
1233 In [9]: print x
1237 In [9]: print x
1234 hello
1238 hello
1235
1239
1236 In [10]: _ip.IP.complete('x.l')
1240 In [10]: _ip.IP.complete('x.l')
1237 Out[10]: ['x.ljust', 'x.lower', 'x.lstrip']
1241 Out[10]: ['x.ljust', 'x.lower', 'x.lstrip']
1238 """
1242 """
1239
1243
1240 complete = self.Completer.complete
1244 complete = self.Completer.complete
1241 state = 0
1245 state = 0
1242 # use a dict so we get unique keys, since ipyhton's multiple
1246 # use a dict so we get unique keys, since ipyhton's multiple
1243 # completers can return duplicates. When we make 2.4 a requirement,
1247 # completers can return duplicates. When we make 2.4 a requirement,
1244 # start using sets instead, which are faster.
1248 # start using sets instead, which are faster.
1245 comps = {}
1249 comps = {}
1246 while True:
1250 while True:
1247 newcomp = complete(text,state,line_buffer=text)
1251 newcomp = complete(text,state,line_buffer=text)
1248 if newcomp is None:
1252 if newcomp is None:
1249 break
1253 break
1250 comps[newcomp] = 1
1254 comps[newcomp] = 1
1251 state += 1
1255 state += 1
1252 outcomps = comps.keys()
1256 outcomps = comps.keys()
1253 outcomps.sort()
1257 outcomps.sort()
1254 #print "T:",text,"OC:",outcomps # dbg
1258 #print "T:",text,"OC:",outcomps # dbg
1255 #print "vars:",self.user_ns.keys()
1259 #print "vars:",self.user_ns.keys()
1256 return outcomps
1260 return outcomps
1257
1261
1258 def set_completer_frame(self, frame=None):
1262 def set_completer_frame(self, frame=None):
1259 if frame:
1263 if frame:
1260 self.Completer.namespace = frame.f_locals
1264 self.Completer.namespace = frame.f_locals
1261 self.Completer.global_namespace = frame.f_globals
1265 self.Completer.global_namespace = frame.f_globals
1262 else:
1266 else:
1263 self.Completer.namespace = self.user_ns
1267 self.Completer.namespace = self.user_ns
1264 self.Completer.global_namespace = self.user_global_ns
1268 self.Completer.global_namespace = self.user_global_ns
1265
1269
1266 def init_auto_alias(self):
1270 def init_auto_alias(self):
1267 """Define some aliases automatically.
1271 """Define some aliases automatically.
1268
1272
1269 These are ALL parameter-less aliases"""
1273 These are ALL parameter-less aliases"""
1270
1274
1271 for alias,cmd in self.auto_alias:
1275 for alias,cmd in self.auto_alias:
1272 self.getapi().defalias(alias,cmd)
1276 self.getapi().defalias(alias,cmd)
1273
1277
1274
1278
1275 def alias_table_validate(self,verbose=0):
1279 def alias_table_validate(self,verbose=0):
1276 """Update information about the alias table.
1280 """Update information about the alias table.
1277
1281
1278 In particular, make sure no Python keywords/builtins are in it."""
1282 In particular, make sure no Python keywords/builtins are in it."""
1279
1283
1280 no_alias = self.no_alias
1284 no_alias = self.no_alias
1281 for k in self.alias_table.keys():
1285 for k in self.alias_table.keys():
1282 if k in no_alias:
1286 if k in no_alias:
1283 del self.alias_table[k]
1287 del self.alias_table[k]
1284 if verbose:
1288 if verbose:
1285 print ("Deleting alias <%s>, it's a Python "
1289 print ("Deleting alias <%s>, it's a Python "
1286 "keyword or builtin." % k)
1290 "keyword or builtin." % k)
1287
1291
1288 def set_autoindent(self,value=None):
1292 def set_autoindent(self,value=None):
1289 """Set the autoindent flag, checking for readline support.
1293 """Set the autoindent flag, checking for readline support.
1290
1294
1291 If called with no arguments, it acts as a toggle."""
1295 If called with no arguments, it acts as a toggle."""
1292
1296
1293 if not self.has_readline:
1297 if not self.has_readline:
1294 if os.name == 'posix':
1298 if os.name == 'posix':
1295 warn("The auto-indent feature requires the readline library")
1299 warn("The auto-indent feature requires the readline library")
1296 self.autoindent = 0
1300 self.autoindent = 0
1297 return
1301 return
1298 if value is None:
1302 if value is None:
1299 self.autoindent = not self.autoindent
1303 self.autoindent = not self.autoindent
1300 else:
1304 else:
1301 self.autoindent = value
1305 self.autoindent = value
1302
1306
1303 def rc_set_toggle(self,rc_field,value=None):
1307 def rc_set_toggle(self,rc_field,value=None):
1304 """Set or toggle a field in IPython's rc config. structure.
1308 """Set or toggle a field in IPython's rc config. structure.
1305
1309
1306 If called with no arguments, it acts as a toggle.
1310 If called with no arguments, it acts as a toggle.
1307
1311
1308 If called with a non-existent field, the resulting AttributeError
1312 If called with a non-existent field, the resulting AttributeError
1309 exception will propagate out."""
1313 exception will propagate out."""
1310
1314
1311 rc_val = getattr(self.rc,rc_field)
1315 rc_val = getattr(self.rc,rc_field)
1312 if value is None:
1316 if value is None:
1313 value = not rc_val
1317 value = not rc_val
1314 setattr(self.rc,rc_field,value)
1318 setattr(self.rc,rc_field,value)
1315
1319
1316 def user_setup(self,ipythondir,rc_suffix,mode='install'):
1320 def user_setup(self,ipythondir,rc_suffix,mode='install'):
1317 """Install the user configuration directory.
1321 """Install the user configuration directory.
1318
1322
1319 Note
1323 Note
1320 ----
1324 ----
1321 DEPRECATED: use the top-level user_setup() function instead.
1325 DEPRECATED: use the top-level user_setup() function instead.
1322 """
1326 """
1323 return user_setup(ipythondir,rc_suffix,mode)
1327 return user_setup(ipythondir,rc_suffix,mode)
1324
1328
1325 def atexit_operations(self):
1329 def atexit_operations(self):
1326 """This will be executed at the time of exit.
1330 """This will be executed at the time of exit.
1327
1331
1328 Saving of persistent data should be performed here. """
1332 Saving of persistent data should be performed here. """
1329
1333
1330 #print '*** IPython exit cleanup ***' # dbg
1334 #print '*** IPython exit cleanup ***' # dbg
1331 # input history
1335 # input history
1332 self.savehist()
1336 self.savehist()
1333
1337
1334 # Cleanup all tempfiles left around
1338 # Cleanup all tempfiles left around
1335 for tfile in self.tempfiles:
1339 for tfile in self.tempfiles:
1336 try:
1340 try:
1337 os.unlink(tfile)
1341 os.unlink(tfile)
1338 except OSError:
1342 except OSError:
1339 pass
1343 pass
1340
1344
1341 # Clear all user namespaces to release all references cleanly.
1345 # Clear all user namespaces to release all references cleanly.
1342 self.reset()
1346 self.reset()
1343
1347
1344 # Run user hooks
1348 # Run user hooks
1345 self.hooks.shutdown_hook()
1349 self.hooks.shutdown_hook()
1346
1350
1347 def reset(self):
1351 def reset(self):
1348 """Clear all internal namespaces.
1352 """Clear all internal namespaces.
1349
1353
1350 Note that this is much more aggressive than %reset, since it clears
1354 Note that this is much more aggressive than %reset, since it clears
1351 fully all namespaces, as well as all input/output lists.
1355 fully all namespaces, as well as all input/output lists.
1352 """
1356 """
1353 for ns in self.ns_refs_table:
1357 for ns in self.ns_refs_table:
1354 ns.clear()
1358 ns.clear()
1355
1359
1356 # Clear input and output histories
1360 # Clear input and output histories
1357 self.input_hist[:] = []
1361 self.input_hist[:] = []
1358 self.input_hist_raw[:] = []
1362 self.input_hist_raw[:] = []
1359 self.output_hist.clear()
1363 self.output_hist.clear()
1360 # Restore the user namespaces to minimal usability
1364 # Restore the user namespaces to minimal usability
1361 self.init_namespaces()
1365 self.init_namespaces()
1362
1366
1363 def savehist(self):
1367 def savehist(self):
1364 """Save input history to a file (via readline library)."""
1368 """Save input history to a file (via readline library)."""
1365
1369
1366 if not self.has_readline:
1370 if not self.has_readline:
1367 return
1371 return
1368
1372
1369 try:
1373 try:
1370 self.readline.write_history_file(self.histfile)
1374 self.readline.write_history_file(self.histfile)
1371 except:
1375 except:
1372 print 'Unable to save IPython command history to file: ' + \
1376 print 'Unable to save IPython command history to file: ' + \
1373 `self.histfile`
1377 `self.histfile`
1374
1378
1375 def reloadhist(self):
1379 def reloadhist(self):
1376 """Reload the input history from disk file."""
1380 """Reload the input history from disk file."""
1377
1381
1378 if self.has_readline:
1382 if self.has_readline:
1379 try:
1383 try:
1380 self.readline.clear_history()
1384 self.readline.clear_history()
1381 self.readline.read_history_file(self.shell.histfile)
1385 self.readline.read_history_file(self.shell.histfile)
1382 except AttributeError:
1386 except AttributeError:
1383 pass
1387 pass
1384
1388
1385
1389
1386 def history_saving_wrapper(self, func):
1390 def history_saving_wrapper(self, func):
1387 """ Wrap func for readline history saving
1391 """ Wrap func for readline history saving
1388
1392
1389 Convert func into callable that saves & restores
1393 Convert func into callable that saves & restores
1390 history around the call """
1394 history around the call """
1391
1395
1392 if not self.has_readline:
1396 if not self.has_readline:
1393 return func
1397 return func
1394
1398
1395 def wrapper():
1399 def wrapper():
1396 self.savehist()
1400 self.savehist()
1397 try:
1401 try:
1398 func()
1402 func()
1399 finally:
1403 finally:
1400 readline.read_history_file(self.histfile)
1404 readline.read_history_file(self.histfile)
1401 return wrapper
1405 return wrapper
1402
1406
1403 def pre_readline(self):
1407 def pre_readline(self):
1404 """readline hook to be used at the start of each line.
1408 """readline hook to be used at the start of each line.
1405
1409
1406 Currently it handles auto-indent only."""
1410 Currently it handles auto-indent only."""
1407
1411
1408 #debugx('self.indent_current_nsp','pre_readline:')
1412 #debugx('self.indent_current_nsp','pre_readline:')
1409
1413
1410 if self.rl_do_indent:
1414 if self.rl_do_indent:
1411 self.readline.insert_text(self.indent_current_str())
1415 self.readline.insert_text(self.indent_current_str())
1412 if self.rl_next_input is not None:
1416 if self.rl_next_input is not None:
1413 self.readline.insert_text(self.rl_next_input)
1417 self.readline.insert_text(self.rl_next_input)
1414 self.rl_next_input = None
1418 self.rl_next_input = None
1415
1419
1416 def init_readline(self):
1420 def init_readline(self):
1417 """Command history completion/saving/reloading."""
1421 """Command history completion/saving/reloading."""
1418
1422
1419
1423
1420 import IPython.rlineimpl as readline
1424 import IPython.rlineimpl as readline
1421
1425
1422 if not readline.have_readline:
1426 if not readline.have_readline:
1423 self.has_readline = 0
1427 self.has_readline = 0
1424 self.readline = None
1428 self.readline = None
1425 # no point in bugging windows users with this every time:
1429 # no point in bugging windows users with this every time:
1426 warn('Readline services not available on this platform.')
1430 warn('Readline services not available on this platform.')
1427 else:
1431 else:
1428 sys.modules['readline'] = readline
1432 sys.modules['readline'] = readline
1429 import atexit
1433 import atexit
1430 from IPython.completer import IPCompleter
1434 from IPython.completer import IPCompleter
1431 self.Completer = IPCompleter(self,
1435 self.Completer = IPCompleter(self,
1432 self.user_ns,
1436 self.user_ns,
1433 self.user_global_ns,
1437 self.user_global_ns,
1434 self.rc.readline_omit__names,
1438 self.rc.readline_omit__names,
1435 self.alias_table)
1439 self.alias_table)
1436 sdisp = self.strdispatchers.get('complete_command', StrDispatch())
1440 sdisp = self.strdispatchers.get('complete_command', StrDispatch())
1437 self.strdispatchers['complete_command'] = sdisp
1441 self.strdispatchers['complete_command'] = sdisp
1438 self.Completer.custom_completers = sdisp
1442 self.Completer.custom_completers = sdisp
1439 # Platform-specific configuration
1443 # Platform-specific configuration
1440 if os.name == 'nt':
1444 if os.name == 'nt':
1441 self.readline_startup_hook = readline.set_pre_input_hook
1445 self.readline_startup_hook = readline.set_pre_input_hook
1442 else:
1446 else:
1443 self.readline_startup_hook = readline.set_startup_hook
1447 self.readline_startup_hook = readline.set_startup_hook
1444
1448
1445 # Load user's initrc file (readline config)
1449 # Load user's initrc file (readline config)
1446 # Or if libedit is used, load editrc.
1450 # Or if libedit is used, load editrc.
1447 inputrc_name = os.environ.get('INPUTRC')
1451 inputrc_name = os.environ.get('INPUTRC')
1448 if inputrc_name is None:
1452 if inputrc_name is None:
1449 home_dir = get_home_dir()
1453 home_dir = get_home_dir()
1450 if home_dir is not None:
1454 if home_dir is not None:
1451 inputrc_name = '.inputrc'
1455 inputrc_name = '.inputrc'
1452 if readline.uses_libedit:
1456 if readline.uses_libedit:
1453 inputrc_name = '.editrc'
1457 inputrc_name = '.editrc'
1454 inputrc_name = os.path.join(home_dir, inputrc_name)
1458 inputrc_name = os.path.join(home_dir, inputrc_name)
1455 if os.path.isfile(inputrc_name):
1459 if os.path.isfile(inputrc_name):
1456 try:
1460 try:
1457 readline.read_init_file(inputrc_name)
1461 readline.read_init_file(inputrc_name)
1458 except:
1462 except:
1459 warn('Problems reading readline initialization file <%s>'
1463 warn('Problems reading readline initialization file <%s>'
1460 % inputrc_name)
1464 % inputrc_name)
1461
1465
1462 self.has_readline = 1
1466 self.has_readline = 1
1463 self.readline = readline
1467 self.readline = readline
1464 # save this in sys so embedded copies can restore it properly
1468 # save this in sys so embedded copies can restore it properly
1465 sys.ipcompleter = self.Completer.complete
1469 sys.ipcompleter = self.Completer.complete
1466 self.set_completer()
1470 self.set_completer()
1467
1471
1468 # Configure readline according to user's prefs
1472 # Configure readline according to user's prefs
1469 # This is only done if GNU readline is being used. If libedit
1473 # This is only done if GNU readline is being used. If libedit
1470 # is being used (as on Leopard) the readline config is
1474 # is being used (as on Leopard) the readline config is
1471 # not run as the syntax for libedit is different.
1475 # not run as the syntax for libedit is different.
1472 if not readline.uses_libedit:
1476 if not readline.uses_libedit:
1473 for rlcommand in self.rc.readline_parse_and_bind:
1477 for rlcommand in self.rc.readline_parse_and_bind:
1474 #print "loading rl:",rlcommand # dbg
1478 #print "loading rl:",rlcommand # dbg
1475 readline.parse_and_bind(rlcommand)
1479 readline.parse_and_bind(rlcommand)
1476
1480
1477 # remove some chars from the delimiters list
1481 # Remove some chars from the delimiters list. If we encounter
1478 delims = readline.get_completer_delims()
1482 # unicode chars, discard them.
1483 delims = readline.get_completer_delims().encode("ascii", "ignore")
1479 delims = delims.translate(string._idmap,
1484 delims = delims.translate(string._idmap,
1480 self.rc.readline_remove_delims)
1485 self.rc.readline_remove_delims)
1481 readline.set_completer_delims(delims)
1486 readline.set_completer_delims(delims)
1482 # otherwise we end up with a monster history after a while:
1487 # otherwise we end up with a monster history after a while:
1483 readline.set_history_length(1000)
1488 readline.set_history_length(1000)
1484 try:
1489 try:
1485 #print '*** Reading readline history' # dbg
1490 #print '*** Reading readline history' # dbg
1486 readline.read_history_file(self.histfile)
1491 readline.read_history_file(self.histfile)
1487 except IOError:
1492 except IOError:
1488 pass # It doesn't exist yet.
1493 pass # It doesn't exist yet.
1489
1494
1490 atexit.register(self.atexit_operations)
1495 atexit.register(self.atexit_operations)
1491 del atexit
1496 del atexit
1492
1497
1493 # Configure auto-indent for all platforms
1498 # Configure auto-indent for all platforms
1494 self.set_autoindent(self.rc.autoindent)
1499 self.set_autoindent(self.rc.autoindent)
1495
1500
1496 def ask_yes_no(self,prompt,default=True):
1501 def ask_yes_no(self,prompt,default=True):
1497 if self.rc.quiet:
1502 if self.rc.quiet:
1498 return True
1503 return True
1499 return ask_yes_no(prompt,default)
1504 return ask_yes_no(prompt,default)
1500
1505
1501 def new_main_mod(self,ns=None):
1506 def new_main_mod(self,ns=None):
1502 """Return a new 'main' module object for user code execution.
1507 """Return a new 'main' module object for user code execution.
1503 """
1508 """
1504 main_mod = self._user_main_module
1509 main_mod = self._user_main_module
1505 init_fakemod_dict(main_mod,ns)
1510 init_fakemod_dict(main_mod,ns)
1506 return main_mod
1511 return main_mod
1507
1512
1508 def cache_main_mod(self,ns,fname):
1513 def cache_main_mod(self,ns,fname):
1509 """Cache a main module's namespace.
1514 """Cache a main module's namespace.
1510
1515
1511 When scripts are executed via %run, we must keep a reference to the
1516 When scripts are executed via %run, we must keep a reference to the
1512 namespace of their __main__ module (a FakeModule instance) around so
1517 namespace of their __main__ module (a FakeModule instance) around so
1513 that Python doesn't clear it, rendering objects defined therein
1518 that Python doesn't clear it, rendering objects defined therein
1514 useless.
1519 useless.
1515
1520
1516 This method keeps said reference in a private dict, keyed by the
1521 This method keeps said reference in a private dict, keyed by the
1517 absolute path of the module object (which corresponds to the script
1522 absolute path of the module object (which corresponds to the script
1518 path). This way, for multiple executions of the same script we only
1523 path). This way, for multiple executions of the same script we only
1519 keep one copy of the namespace (the last one), thus preventing memory
1524 keep one copy of the namespace (the last one), thus preventing memory
1520 leaks from old references while allowing the objects from the last
1525 leaks from old references while allowing the objects from the last
1521 execution to be accessible.
1526 execution to be accessible.
1522
1527
1523 Note: we can not allow the actual FakeModule instances to be deleted,
1528 Note: we can not allow the actual FakeModule instances to be deleted,
1524 because of how Python tears down modules (it hard-sets all their
1529 because of how Python tears down modules (it hard-sets all their
1525 references to None without regard for reference counts). This method
1530 references to None without regard for reference counts). This method
1526 must therefore make a *copy* of the given namespace, to allow the
1531 must therefore make a *copy* of the given namespace, to allow the
1527 original module's __dict__ to be cleared and reused.
1532 original module's __dict__ to be cleared and reused.
1528
1533
1529
1534
1530 Parameters
1535 Parameters
1531 ----------
1536 ----------
1532 ns : a namespace (a dict, typically)
1537 ns : a namespace (a dict, typically)
1533
1538
1534 fname : str
1539 fname : str
1535 Filename associated with the namespace.
1540 Filename associated with the namespace.
1536
1541
1537 Examples
1542 Examples
1538 --------
1543 --------
1539
1544
1540 In [10]: import IPython
1545 In [10]: import IPython
1541
1546
1542 In [11]: _ip.IP.cache_main_mod(IPython.__dict__,IPython.__file__)
1547 In [11]: _ip.IP.cache_main_mod(IPython.__dict__,IPython.__file__)
1543
1548
1544 In [12]: IPython.__file__ in _ip.IP._main_ns_cache
1549 In [12]: IPython.__file__ in _ip.IP._main_ns_cache
1545 Out[12]: True
1550 Out[12]: True
1546 """
1551 """
1547 self._main_ns_cache[os.path.abspath(fname)] = ns.copy()
1552 self._main_ns_cache[os.path.abspath(fname)] = ns.copy()
1548
1553
1549 def clear_main_mod_cache(self):
1554 def clear_main_mod_cache(self):
1550 """Clear the cache of main modules.
1555 """Clear the cache of main modules.
1551
1556
1552 Mainly for use by utilities like %reset.
1557 Mainly for use by utilities like %reset.
1553
1558
1554 Examples
1559 Examples
1555 --------
1560 --------
1556
1561
1557 In [15]: import IPython
1562 In [15]: import IPython
1558
1563
1559 In [16]: _ip.IP.cache_main_mod(IPython.__dict__,IPython.__file__)
1564 In [16]: _ip.IP.cache_main_mod(IPython.__dict__,IPython.__file__)
1560
1565
1561 In [17]: len(_ip.IP._main_ns_cache) > 0
1566 In [17]: len(_ip.IP._main_ns_cache) > 0
1562 Out[17]: True
1567 Out[17]: True
1563
1568
1564 In [18]: _ip.IP.clear_main_mod_cache()
1569 In [18]: _ip.IP.clear_main_mod_cache()
1565
1570
1566 In [19]: len(_ip.IP._main_ns_cache) == 0
1571 In [19]: len(_ip.IP._main_ns_cache) == 0
1567 Out[19]: True
1572 Out[19]: True
1568 """
1573 """
1569 self._main_ns_cache.clear()
1574 self._main_ns_cache.clear()
1570
1575
1571 def _should_recompile(self,e):
1576 def _should_recompile(self,e):
1572 """Utility routine for edit_syntax_error"""
1577 """Utility routine for edit_syntax_error"""
1573
1578
1574 if e.filename in ('<ipython console>','<input>','<string>',
1579 if e.filename in ('<ipython console>','<input>','<string>',
1575 '<console>','<BackgroundJob compilation>',
1580 '<console>','<BackgroundJob compilation>',
1576 None):
1581 None):
1577
1582
1578 return False
1583 return False
1579 try:
1584 try:
1580 if (self.rc.autoedit_syntax and
1585 if (self.rc.autoedit_syntax and
1581 not self.ask_yes_no('Return to editor to correct syntax error? '
1586 not self.ask_yes_no('Return to editor to correct syntax error? '
1582 '[Y/n] ','y')):
1587 '[Y/n] ','y')):
1583 return False
1588 return False
1584 except EOFError:
1589 except EOFError:
1585 return False
1590 return False
1586
1591
1587 def int0(x):
1592 def int0(x):
1588 try:
1593 try:
1589 return int(x)
1594 return int(x)
1590 except TypeError:
1595 except TypeError:
1591 return 0
1596 return 0
1592 # always pass integer line and offset values to editor hook
1597 # always pass integer line and offset values to editor hook
1593 try:
1598 try:
1594 self.hooks.fix_error_editor(e.filename,
1599 self.hooks.fix_error_editor(e.filename,
1595 int0(e.lineno),int0(e.offset),e.msg)
1600 int0(e.lineno),int0(e.offset),e.msg)
1596 except IPython.ipapi.TryNext:
1601 except IPython.ipapi.TryNext:
1597 warn('Could not open editor')
1602 warn('Could not open editor')
1598 return False
1603 return False
1599 return True
1604 return True
1600
1605
1601 def edit_syntax_error(self):
1606 def edit_syntax_error(self):
1602 """The bottom half of the syntax error handler called in the main loop.
1607 """The bottom half of the syntax error handler called in the main loop.
1603
1608
1604 Loop until syntax error is fixed or user cancels.
1609 Loop until syntax error is fixed or user cancels.
1605 """
1610 """
1606
1611
1607 while self.SyntaxTB.last_syntax_error:
1612 while self.SyntaxTB.last_syntax_error:
1608 # copy and clear last_syntax_error
1613 # copy and clear last_syntax_error
1609 err = self.SyntaxTB.clear_err_state()
1614 err = self.SyntaxTB.clear_err_state()
1610 if not self._should_recompile(err):
1615 if not self._should_recompile(err):
1611 return
1616 return
1612 try:
1617 try:
1613 # may set last_syntax_error again if a SyntaxError is raised
1618 # may set last_syntax_error again if a SyntaxError is raised
1614 self.safe_execfile(err.filename,self.user_ns)
1619 self.safe_execfile(err.filename,self.user_ns)
1615 except:
1620 except:
1616 self.showtraceback()
1621 self.showtraceback()
1617 else:
1622 else:
1618 try:
1623 try:
1619 f = file(err.filename)
1624 f = file(err.filename)
1620 try:
1625 try:
1621 sys.displayhook(f.read())
1626 sys.displayhook(f.read())
1622 finally:
1627 finally:
1623 f.close()
1628 f.close()
1624 except:
1629 except:
1625 self.showtraceback()
1630 self.showtraceback()
1626
1631
1627 def showsyntaxerror(self, filename=None):
1632 def showsyntaxerror(self, filename=None):
1628 """Display the syntax error that just occurred.
1633 """Display the syntax error that just occurred.
1629
1634
1630 This doesn't display a stack trace because there isn't one.
1635 This doesn't display a stack trace because there isn't one.
1631
1636
1632 If a filename is given, it is stuffed in the exception instead
1637 If a filename is given, it is stuffed in the exception instead
1633 of what was there before (because Python's parser always uses
1638 of what was there before (because Python's parser always uses
1634 "<string>" when reading from a string).
1639 "<string>" when reading from a string).
1635 """
1640 """
1636 etype, value, last_traceback = sys.exc_info()
1641 etype, value, last_traceback = sys.exc_info()
1637
1642
1638 # See note about these variables in showtraceback() below
1643 # See note about these variables in showtraceback() below
1639 sys.last_type = etype
1644 sys.last_type = etype
1640 sys.last_value = value
1645 sys.last_value = value
1641 sys.last_traceback = last_traceback
1646 sys.last_traceback = last_traceback
1642
1647
1643 if filename and etype is SyntaxError:
1648 if filename and etype is SyntaxError:
1644 # Work hard to stuff the correct filename in the exception
1649 # Work hard to stuff the correct filename in the exception
1645 try:
1650 try:
1646 msg, (dummy_filename, lineno, offset, line) = value
1651 msg, (dummy_filename, lineno, offset, line) = value
1647 except:
1652 except:
1648 # Not the format we expect; leave it alone
1653 # Not the format we expect; leave it alone
1649 pass
1654 pass
1650 else:
1655 else:
1651 # Stuff in the right filename
1656 # Stuff in the right filename
1652 try:
1657 try:
1653 # Assume SyntaxError is a class exception
1658 # Assume SyntaxError is a class exception
1654 value = SyntaxError(msg, (filename, lineno, offset, line))
1659 value = SyntaxError(msg, (filename, lineno, offset, line))
1655 except:
1660 except:
1656 # If that failed, assume SyntaxError is a string
1661 # If that failed, assume SyntaxError is a string
1657 value = msg, (filename, lineno, offset, line)
1662 value = msg, (filename, lineno, offset, line)
1658 self.SyntaxTB(etype,value,[])
1663 self.SyntaxTB(etype,value,[])
1659
1664
1660 def debugger(self,force=False):
1665 def debugger(self,force=False):
1661 """Call the pydb/pdb debugger.
1666 """Call the pydb/pdb debugger.
1662
1667
1663 Keywords:
1668 Keywords:
1664
1669
1665 - force(False): by default, this routine checks the instance call_pdb
1670 - force(False): by default, this routine checks the instance call_pdb
1666 flag and does not actually invoke the debugger if the flag is false.
1671 flag and does not actually invoke the debugger if the flag is false.
1667 The 'force' option forces the debugger to activate even if the flag
1672 The 'force' option forces the debugger to activate even if the flag
1668 is false.
1673 is false.
1669 """
1674 """
1670
1675
1671 if not (force or self.call_pdb):
1676 if not (force or self.call_pdb):
1672 return
1677 return
1673
1678
1674 if not hasattr(sys,'last_traceback'):
1679 if not hasattr(sys,'last_traceback'):
1675 error('No traceback has been produced, nothing to debug.')
1680 error('No traceback has been produced, nothing to debug.')
1676 return
1681 return
1677
1682
1678 # use pydb if available
1683 # use pydb if available
1679 if Debugger.has_pydb:
1684 if Debugger.has_pydb:
1680 from pydb import pm
1685 from pydb import pm
1681 else:
1686 else:
1682 # fallback to our internal debugger
1687 # fallback to our internal debugger
1683 pm = lambda : self.InteractiveTB.debugger(force=True)
1688 pm = lambda : self.InteractiveTB.debugger(force=True)
1684 self.history_saving_wrapper(pm)()
1689 self.history_saving_wrapper(pm)()
1685
1690
1686 def showtraceback(self,exc_tuple = None,filename=None,tb_offset=None):
1691 def showtraceback(self,exc_tuple = None,filename=None,tb_offset=None):
1687 """Display the exception that just occurred.
1692 """Display the exception that just occurred.
1688
1693
1689 If nothing is known about the exception, this is the method which
1694 If nothing is known about the exception, this is the method which
1690 should be used throughout the code for presenting user tracebacks,
1695 should be used throughout the code for presenting user tracebacks,
1691 rather than directly invoking the InteractiveTB object.
1696 rather than directly invoking the InteractiveTB object.
1692
1697
1693 A specific showsyntaxerror() also exists, but this method can take
1698 A specific showsyntaxerror() also exists, but this method can take
1694 care of calling it if needed, so unless you are explicitly catching a
1699 care of calling it if needed, so unless you are explicitly catching a
1695 SyntaxError exception, don't try to analyze the stack manually and
1700 SyntaxError exception, don't try to analyze the stack manually and
1696 simply call this method."""
1701 simply call this method."""
1697
1702
1698
1703
1699 # Though this won't be called by syntax errors in the input line,
1704 # Though this won't be called by syntax errors in the input line,
1700 # there may be SyntaxError cases whith imported code.
1705 # there may be SyntaxError cases whith imported code.
1701
1706
1702 try:
1707 try:
1703 if exc_tuple is None:
1708 if exc_tuple is None:
1704 etype, value, tb = sys.exc_info()
1709 etype, value, tb = sys.exc_info()
1705 else:
1710 else:
1706 etype, value, tb = exc_tuple
1711 etype, value, tb = exc_tuple
1707
1712
1708 if etype is SyntaxError:
1713 if etype is SyntaxError:
1709 self.showsyntaxerror(filename)
1714 self.showsyntaxerror(filename)
1710 elif etype is IPython.ipapi.UsageError:
1715 elif etype is IPython.ipapi.UsageError:
1711 print "UsageError:", value
1716 print "UsageError:", value
1712 else:
1717 else:
1713 # WARNING: these variables are somewhat deprecated and not
1718 # WARNING: these variables are somewhat deprecated and not
1714 # necessarily safe to use in a threaded environment, but tools
1719 # necessarily safe to use in a threaded environment, but tools
1715 # like pdb depend on their existence, so let's set them. If we
1720 # like pdb depend on their existence, so let's set them. If we
1716 # find problems in the field, we'll need to revisit their use.
1721 # find problems in the field, we'll need to revisit their use.
1717 sys.last_type = etype
1722 sys.last_type = etype
1718 sys.last_value = value
1723 sys.last_value = value
1719 sys.last_traceback = tb
1724 sys.last_traceback = tb
1720
1725
1721 if etype in self.custom_exceptions:
1726 if etype in self.custom_exceptions:
1722 self.CustomTB(etype,value,tb)
1727 self.CustomTB(etype,value,tb)
1723 else:
1728 else:
1724 self.InteractiveTB(etype,value,tb,tb_offset=tb_offset)
1729 self.InteractiveTB(etype,value,tb,tb_offset=tb_offset)
1725 if self.InteractiveTB.call_pdb and self.has_readline:
1730 if self.InteractiveTB.call_pdb and self.has_readline:
1726 # pdb mucks up readline, fix it back
1731 # pdb mucks up readline, fix it back
1727 self.set_completer()
1732 self.set_completer()
1728 except KeyboardInterrupt:
1733 except KeyboardInterrupt:
1729 self.write("\nKeyboardInterrupt\n")
1734 self.write("\nKeyboardInterrupt\n")
1730
1735
1731 def mainloop(self,banner=None):
1736 def mainloop(self,banner=None):
1732 """Creates the local namespace and starts the mainloop.
1737 """Creates the local namespace and starts the mainloop.
1733
1738
1734 If an optional banner argument is given, it will override the
1739 If an optional banner argument is given, it will override the
1735 internally created default banner."""
1740 internally created default banner."""
1736
1741
1737 if self.rc.c: # Emulate Python's -c option
1742 if self.rc.c: # Emulate Python's -c option
1738 self.exec_init_cmd()
1743 self.exec_init_cmd()
1739 if banner is None:
1744 if banner is None:
1740 if not self.rc.banner:
1745 if not self.rc.banner:
1741 banner = ''
1746 banner = ''
1742 # banner is string? Use it directly!
1747 # banner is string? Use it directly!
1743 elif isinstance(self.rc.banner,basestring):
1748 elif isinstance(self.rc.banner,basestring):
1744 banner = self.rc.banner
1749 banner = self.rc.banner
1745 else:
1750 else:
1746 banner = self.BANNER+self.banner2
1751 banner = self.BANNER+self.banner2
1747
1752
1748 # if you run stuff with -c <cmd>, raw hist is not updated
1753 # if you run stuff with -c <cmd>, raw hist is not updated
1749 # ensure that it's in sync
1754 # ensure that it's in sync
1750 if len(self.input_hist) != len (self.input_hist_raw):
1755 if len(self.input_hist) != len (self.input_hist_raw):
1751 self.input_hist_raw = InputList(self.input_hist)
1756 self.input_hist_raw = InputList(self.input_hist)
1752
1757
1753 while 1:
1758 while 1:
1754 try:
1759 try:
1755 self.interact(banner)
1760 self.interact(banner)
1756 #self.interact_with_readline()
1761 #self.interact_with_readline()
1757
1762
1758 # XXX for testing of a readline-decoupled repl loop, call
1763 # XXX for testing of a readline-decoupled repl loop, call
1759 # interact_with_readline above
1764 # interact_with_readline above
1760
1765
1761 break
1766 break
1762 except KeyboardInterrupt:
1767 except KeyboardInterrupt:
1763 # this should not be necessary, but KeyboardInterrupt
1768 # this should not be necessary, but KeyboardInterrupt
1764 # handling seems rather unpredictable...
1769 # handling seems rather unpredictable...
1765 self.write("\nKeyboardInterrupt in interact()\n")
1770 self.write("\nKeyboardInterrupt in interact()\n")
1766
1771
1767 def exec_init_cmd(self):
1772 def exec_init_cmd(self):
1768 """Execute a command given at the command line.
1773 """Execute a command given at the command line.
1769
1774
1770 This emulates Python's -c option."""
1775 This emulates Python's -c option."""
1771
1776
1772 #sys.argv = ['-c']
1777 #sys.argv = ['-c']
1773 self.push(self.prefilter(self.rc.c, False))
1778 self.push(self.prefilter(self.rc.c, False))
1774 if not self.rc.interact:
1779 if not self.rc.interact:
1775 self.ask_exit()
1780 self.ask_exit()
1776
1781
1777 def embed_mainloop(self,header='',local_ns=None,global_ns=None,stack_depth=0):
1782 def embed_mainloop(self,header='',local_ns=None,global_ns=None,stack_depth=0):
1778 """Embeds IPython into a running python program.
1783 """Embeds IPython into a running python program.
1779
1784
1780 Input:
1785 Input:
1781
1786
1782 - header: An optional header message can be specified.
1787 - header: An optional header message can be specified.
1783
1788
1784 - local_ns, global_ns: working namespaces. If given as None, the
1789 - local_ns, global_ns: working namespaces. If given as None, the
1785 IPython-initialized one is updated with __main__.__dict__, so that
1790 IPython-initialized one is updated with __main__.__dict__, so that
1786 program variables become visible but user-specific configuration
1791 program variables become visible but user-specific configuration
1787 remains possible.
1792 remains possible.
1788
1793
1789 - stack_depth: specifies how many levels in the stack to go to
1794 - stack_depth: specifies how many levels in the stack to go to
1790 looking for namespaces (when local_ns and global_ns are None). This
1795 looking for namespaces (when local_ns and global_ns are None). This
1791 allows an intermediate caller to make sure that this function gets
1796 allows an intermediate caller to make sure that this function gets
1792 the namespace from the intended level in the stack. By default (0)
1797 the namespace from the intended level in the stack. By default (0)
1793 it will get its locals and globals from the immediate caller.
1798 it will get its locals and globals from the immediate caller.
1794
1799
1795 Warning: it's possible to use this in a program which is being run by
1800 Warning: it's possible to use this in a program which is being run by
1796 IPython itself (via %run), but some funny things will happen (a few
1801 IPython itself (via %run), but some funny things will happen (a few
1797 globals get overwritten). In the future this will be cleaned up, as
1802 globals get overwritten). In the future this will be cleaned up, as
1798 there is no fundamental reason why it can't work perfectly."""
1803 there is no fundamental reason why it can't work perfectly."""
1799
1804
1800 # Get locals and globals from caller
1805 # Get locals and globals from caller
1801 if local_ns is None or global_ns is None:
1806 if local_ns is None or global_ns is None:
1802 call_frame = sys._getframe(stack_depth).f_back
1807 call_frame = sys._getframe(stack_depth).f_back
1803
1808
1804 if local_ns is None:
1809 if local_ns is None:
1805 local_ns = call_frame.f_locals
1810 local_ns = call_frame.f_locals
1806 if global_ns is None:
1811 if global_ns is None:
1807 global_ns = call_frame.f_globals
1812 global_ns = call_frame.f_globals
1808
1813
1809 # Update namespaces and fire up interpreter
1814 # Update namespaces and fire up interpreter
1810
1815
1811 # The global one is easy, we can just throw it in
1816 # The global one is easy, we can just throw it in
1812 self.user_global_ns = global_ns
1817 self.user_global_ns = global_ns
1813
1818
1814 # but the user/local one is tricky: ipython needs it to store internal
1819 # but the user/local one is tricky: ipython needs it to store internal
1815 # data, but we also need the locals. We'll copy locals in the user
1820 # data, but we also need the locals. We'll copy locals in the user
1816 # one, but will track what got copied so we can delete them at exit.
1821 # one, but will track what got copied so we can delete them at exit.
1817 # This is so that a later embedded call doesn't see locals from a
1822 # This is so that a later embedded call doesn't see locals from a
1818 # previous call (which most likely existed in a separate scope).
1823 # previous call (which most likely existed in a separate scope).
1819 local_varnames = local_ns.keys()
1824 local_varnames = local_ns.keys()
1820 self.user_ns.update(local_ns)
1825 self.user_ns.update(local_ns)
1821 #self.user_ns['local_ns'] = local_ns # dbg
1826 #self.user_ns['local_ns'] = local_ns # dbg
1822
1827
1823 # Patch for global embedding to make sure that things don't overwrite
1828 # Patch for global embedding to make sure that things don't overwrite
1824 # user globals accidentally. Thanks to Richard <rxe@renre-europe.com>
1829 # user globals accidentally. Thanks to Richard <rxe@renre-europe.com>
1825 # FIXME. Test this a bit more carefully (the if.. is new)
1830 # FIXME. Test this a bit more carefully (the if.. is new)
1826 if local_ns is None and global_ns is None:
1831 if local_ns is None and global_ns is None:
1827 self.user_global_ns.update(__main__.__dict__)
1832 self.user_global_ns.update(__main__.__dict__)
1828
1833
1829 # make sure the tab-completer has the correct frame information, so it
1834 # make sure the tab-completer has the correct frame information, so it
1830 # actually completes using the frame's locals/globals
1835 # actually completes using the frame's locals/globals
1831 self.set_completer_frame()
1836 self.set_completer_frame()
1832
1837
1833 # before activating the interactive mode, we need to make sure that
1838 # before activating the interactive mode, we need to make sure that
1834 # all names in the builtin namespace needed by ipython point to
1839 # all names in the builtin namespace needed by ipython point to
1835 # ourselves, and not to other instances.
1840 # ourselves, and not to other instances.
1836 self.add_builtins()
1841 self.add_builtins()
1837
1842
1838 self.interact(header)
1843 self.interact(header)
1839
1844
1840 # now, purge out the user namespace from anything we might have added
1845 # now, purge out the user namespace from anything we might have added
1841 # from the caller's local namespace
1846 # from the caller's local namespace
1842 delvar = self.user_ns.pop
1847 delvar = self.user_ns.pop
1843 for var in local_varnames:
1848 for var in local_varnames:
1844 delvar(var,None)
1849 delvar(var,None)
1845 # and clean builtins we may have overridden
1850 # and clean builtins we may have overridden
1846 self.clean_builtins()
1851 self.clean_builtins()
1847
1852
1848 def interact_prompt(self):
1853 def interact_prompt(self):
1849 """ Print the prompt (in read-eval-print loop)
1854 """ Print the prompt (in read-eval-print loop)
1850
1855
1851 Provided for those who want to implement their own read-eval-print loop (e.g. GUIs), not
1856 Provided for those who want to implement their own read-eval-print loop (e.g. GUIs), not
1852 used in standard IPython flow.
1857 used in standard IPython flow.
1853 """
1858 """
1854 if self.more:
1859 if self.more:
1855 try:
1860 try:
1856 prompt = self.hooks.generate_prompt(True)
1861 prompt = self.hooks.generate_prompt(True)
1857 except:
1862 except:
1858 self.showtraceback()
1863 self.showtraceback()
1859 if self.autoindent:
1864 if self.autoindent:
1860 self.rl_do_indent = True
1865 self.rl_do_indent = True
1861
1866
1862 else:
1867 else:
1863 try:
1868 try:
1864 prompt = self.hooks.generate_prompt(False)
1869 prompt = self.hooks.generate_prompt(False)
1865 except:
1870 except:
1866 self.showtraceback()
1871 self.showtraceback()
1867 self.write(prompt)
1872 self.write(prompt)
1868
1873
1869 def interact_handle_input(self,line):
1874 def interact_handle_input(self,line):
1870 """ Handle the input line (in read-eval-print loop)
1875 """ Handle the input line (in read-eval-print loop)
1871
1876
1872 Provided for those who want to implement their own read-eval-print loop (e.g. GUIs), not
1877 Provided for those who want to implement their own read-eval-print loop (e.g. GUIs), not
1873 used in standard IPython flow.
1878 used in standard IPython flow.
1874 """
1879 """
1875 if line.lstrip() == line:
1880 if line.lstrip() == line:
1876 self.shadowhist.add(line.strip())
1881 self.shadowhist.add(line.strip())
1877 lineout = self.prefilter(line,self.more)
1882 lineout = self.prefilter(line,self.more)
1878
1883
1879 if line.strip():
1884 if line.strip():
1880 if self.more:
1885 if self.more:
1881 self.input_hist_raw[-1] += '%s\n' % line
1886 self.input_hist_raw[-1] += '%s\n' % line
1882 else:
1887 else:
1883 self.input_hist_raw.append('%s\n' % line)
1888 self.input_hist_raw.append('%s\n' % line)
1884
1889
1885
1890
1886 self.more = self.push(lineout)
1891 self.more = self.push(lineout)
1887 if (self.SyntaxTB.last_syntax_error and
1892 if (self.SyntaxTB.last_syntax_error and
1888 self.rc.autoedit_syntax):
1893 self.rc.autoedit_syntax):
1889 self.edit_syntax_error()
1894 self.edit_syntax_error()
1890
1895
1891 def interact_with_readline(self):
1896 def interact_with_readline(self):
1892 """ Demo of using interact_handle_input, interact_prompt
1897 """ Demo of using interact_handle_input, interact_prompt
1893
1898
1894 This is the main read-eval-print loop. If you need to implement your own (e.g. for GUI),
1899 This is the main read-eval-print loop. If you need to implement your own (e.g. for GUI),
1895 it should work like this.
1900 it should work like this.
1896 """
1901 """
1897 self.readline_startup_hook(self.pre_readline)
1902 self.readline_startup_hook(self.pre_readline)
1898 while not self.exit_now:
1903 while not self.exit_now:
1899 self.interact_prompt()
1904 self.interact_prompt()
1900 if self.more:
1905 if self.more:
1901 self.rl_do_indent = True
1906 self.rl_do_indent = True
1902 else:
1907 else:
1903 self.rl_do_indent = False
1908 self.rl_do_indent = False
1904 line = raw_input_original().decode(self.stdin_encoding)
1909 line = raw_input_original().decode(self.stdin_encoding)
1905 self.interact_handle_input(line)
1910 self.interact_handle_input(line)
1906
1911
1907
1912
1908 def interact(self, banner=None):
1913 def interact(self, banner=None):
1909 """Closely emulate the interactive Python console.
1914 """Closely emulate the interactive Python console.
1910
1915
1911 The optional banner argument specify the banner to print
1916 The optional banner argument specify the banner to print
1912 before the first interaction; by default it prints a banner
1917 before the first interaction; by default it prints a banner
1913 similar to the one printed by the real Python interpreter,
1918 similar to the one printed by the real Python interpreter,
1914 followed by the current class name in parentheses (so as not
1919 followed by the current class name in parentheses (so as not
1915 to confuse this with the real interpreter -- since it's so
1920 to confuse this with the real interpreter -- since it's so
1916 close!).
1921 close!).
1917
1922
1918 """
1923 """
1919
1924
1920 if self.exit_now:
1925 if self.exit_now:
1921 # batch run -> do not interact
1926 # batch run -> do not interact
1922 return
1927 return
1923 cprt = 'Type "copyright", "credits" or "license" for more information.'
1928 cprt = 'Type "copyright", "credits" or "license" for more information.'
1924 if banner is None:
1929 if banner is None:
1925 self.write("Python %s on %s\n%s\n(%s)\n" %
1930 self.write("Python %s on %s\n%s\n(%s)\n" %
1926 (sys.version, sys.platform, cprt,
1931 (sys.version, sys.platform, cprt,
1927 self.__class__.__name__))
1932 self.__class__.__name__))
1928 else:
1933 else:
1929 self.write(banner)
1934 self.write(banner)
1930
1935
1931 more = 0
1936 more = 0
1932
1937
1933 # Mark activity in the builtins
1938 # Mark activity in the builtins
1934 __builtin__.__dict__['__IPYTHON__active'] += 1
1939 __builtin__.__dict__['__IPYTHON__active'] += 1
1935
1940
1936 if self.has_readline:
1941 if self.has_readline:
1937 self.readline_startup_hook(self.pre_readline)
1942 self.readline_startup_hook(self.pre_readline)
1938 # exit_now is set by a call to %Exit or %Quit, through the
1943 # exit_now is set by a call to %Exit or %Quit, through the
1939 # ask_exit callback.
1944 # ask_exit callback.
1940
1945
1941 while not self.exit_now:
1946 while not self.exit_now:
1942 self.hooks.pre_prompt_hook()
1947 self.hooks.pre_prompt_hook()
1943 if more:
1948 if more:
1944 try:
1949 try:
1945 prompt = self.hooks.generate_prompt(True)
1950 prompt = self.hooks.generate_prompt(True)
1946 except:
1951 except:
1947 self.showtraceback()
1952 self.showtraceback()
1948 if self.autoindent:
1953 if self.autoindent:
1949 self.rl_do_indent = True
1954 self.rl_do_indent = True
1950
1955
1951 else:
1956 else:
1952 try:
1957 try:
1953 prompt = self.hooks.generate_prompt(False)
1958 prompt = self.hooks.generate_prompt(False)
1954 except:
1959 except:
1955 self.showtraceback()
1960 self.showtraceback()
1956 try:
1961 try:
1957 line = self.raw_input(prompt,more)
1962 line = self.raw_input(prompt,more)
1958 if self.exit_now:
1963 if self.exit_now:
1959 # quick exit on sys.std[in|out] close
1964 # quick exit on sys.std[in|out] close
1960 break
1965 break
1961 if self.autoindent:
1966 if self.autoindent:
1962 self.rl_do_indent = False
1967 self.rl_do_indent = False
1963
1968
1964 except KeyboardInterrupt:
1969 except KeyboardInterrupt:
1965 #double-guard against keyboardinterrupts during kbdint handling
1970 #double-guard against keyboardinterrupts during kbdint handling
1966 try:
1971 try:
1967 self.write('\nKeyboardInterrupt\n')
1972 self.write('\nKeyboardInterrupt\n')
1968 self.resetbuffer()
1973 self.resetbuffer()
1969 # keep cache in sync with the prompt counter:
1974 # keep cache in sync with the prompt counter:
1970 self.outputcache.prompt_count -= 1
1975 self.outputcache.prompt_count -= 1
1971
1976
1972 if self.autoindent:
1977 if self.autoindent:
1973 self.indent_current_nsp = 0
1978 self.indent_current_nsp = 0
1974 more = 0
1979 more = 0
1975 except KeyboardInterrupt:
1980 except KeyboardInterrupt:
1976 pass
1981 pass
1977 except EOFError:
1982 except EOFError:
1978 if self.autoindent:
1983 if self.autoindent:
1979 self.rl_do_indent = False
1984 self.rl_do_indent = False
1980 self.readline_startup_hook(None)
1985 self.readline_startup_hook(None)
1981 self.write('\n')
1986 self.write('\n')
1982 self.exit()
1987 self.exit()
1983 except bdb.BdbQuit:
1988 except bdb.BdbQuit:
1984 warn('The Python debugger has exited with a BdbQuit exception.\n'
1989 warn('The Python debugger has exited with a BdbQuit exception.\n'
1985 'Because of how pdb handles the stack, it is impossible\n'
1990 'Because of how pdb handles the stack, it is impossible\n'
1986 'for IPython to properly format this particular exception.\n'
1991 'for IPython to properly format this particular exception.\n'
1987 'IPython will resume normal operation.')
1992 'IPython will resume normal operation.')
1988 except:
1993 except:
1989 # exceptions here are VERY RARE, but they can be triggered
1994 # exceptions here are VERY RARE, but they can be triggered
1990 # asynchronously by signal handlers, for example.
1995 # asynchronously by signal handlers, for example.
1991 self.showtraceback()
1996 self.showtraceback()
1992 else:
1997 else:
1993 more = self.push(line)
1998 more = self.push(line)
1994 if (self.SyntaxTB.last_syntax_error and
1999 if (self.SyntaxTB.last_syntax_error and
1995 self.rc.autoedit_syntax):
2000 self.rc.autoedit_syntax):
1996 self.edit_syntax_error()
2001 self.edit_syntax_error()
1997
2002
1998 # We are off again...
2003 # We are off again...
1999 __builtin__.__dict__['__IPYTHON__active'] -= 1
2004 __builtin__.__dict__['__IPYTHON__active'] -= 1
2000
2005
2001 def excepthook(self, etype, value, tb):
2006 def excepthook(self, etype, value, tb):
2002 """One more defense for GUI apps that call sys.excepthook.
2007 """One more defense for GUI apps that call sys.excepthook.
2003
2008
2004 GUI frameworks like wxPython trap exceptions and call
2009 GUI frameworks like wxPython trap exceptions and call
2005 sys.excepthook themselves. I guess this is a feature that
2010 sys.excepthook themselves. I guess this is a feature that
2006 enables them to keep running after exceptions that would
2011 enables them to keep running after exceptions that would
2007 otherwise kill their mainloop. This is a bother for IPython
2012 otherwise kill their mainloop. This is a bother for IPython
2008 which excepts to catch all of the program exceptions with a try:
2013 which excepts to catch all of the program exceptions with a try:
2009 except: statement.
2014 except: statement.
2010
2015
2011 Normally, IPython sets sys.excepthook to a CrashHandler instance, so if
2016 Normally, IPython sets sys.excepthook to a CrashHandler instance, so if
2012 any app directly invokes sys.excepthook, it will look to the user like
2017 any app directly invokes sys.excepthook, it will look to the user like
2013 IPython crashed. In order to work around this, we can disable the
2018 IPython crashed. In order to work around this, we can disable the
2014 CrashHandler and replace it with this excepthook instead, which prints a
2019 CrashHandler and replace it with this excepthook instead, which prints a
2015 regular traceback using our InteractiveTB. In this fashion, apps which
2020 regular traceback using our InteractiveTB. In this fashion, apps which
2016 call sys.excepthook will generate a regular-looking exception from
2021 call sys.excepthook will generate a regular-looking exception from
2017 IPython, and the CrashHandler will only be triggered by real IPython
2022 IPython, and the CrashHandler will only be triggered by real IPython
2018 crashes.
2023 crashes.
2019
2024
2020 This hook should be used sparingly, only in places which are not likely
2025 This hook should be used sparingly, only in places which are not likely
2021 to be true IPython errors.
2026 to be true IPython errors.
2022 """
2027 """
2023 self.showtraceback((etype,value,tb),tb_offset=0)
2028 self.showtraceback((etype,value,tb),tb_offset=0)
2024
2029
2025 def expand_aliases(self,fn,rest):
2030 def expand_aliases(self,fn,rest):
2026 """ Expand multiple levels of aliases:
2031 """ Expand multiple levels of aliases:
2027
2032
2028 if:
2033 if:
2029
2034
2030 alias foo bar /tmp
2035 alias foo bar /tmp
2031 alias baz foo
2036 alias baz foo
2032
2037
2033 then:
2038 then:
2034
2039
2035 baz huhhahhei -> bar /tmp huhhahhei
2040 baz huhhahhei -> bar /tmp huhhahhei
2036
2041
2037 """
2042 """
2038 line = fn + " " + rest
2043 line = fn + " " + rest
2039
2044
2040 done = set()
2045 done = set()
2041 while 1:
2046 while 1:
2042 pre,fn,rest = prefilter.splitUserInput(line,
2047 pre,fn,rest = prefilter.splitUserInput(line,
2043 prefilter.shell_line_split)
2048 prefilter.shell_line_split)
2044 if fn in self.alias_table:
2049 if fn in self.alias_table:
2045 if fn in done:
2050 if fn in done:
2046 warn("Cyclic alias definition, repeated '%s'" % fn)
2051 warn("Cyclic alias definition, repeated '%s'" % fn)
2047 return ""
2052 return ""
2048 done.add(fn)
2053 done.add(fn)
2049
2054
2050 l2 = self.transform_alias(fn,rest)
2055 l2 = self.transform_alias(fn,rest)
2051 # dir -> dir
2056 # dir -> dir
2052 # print "alias",line, "->",l2 #dbg
2057 # print "alias",line, "->",l2 #dbg
2053 if l2 == line:
2058 if l2 == line:
2054 break
2059 break
2055 # ls -> ls -F should not recurse forever
2060 # ls -> ls -F should not recurse forever
2056 if l2.split(None,1)[0] == line.split(None,1)[0]:
2061 if l2.split(None,1)[0] == line.split(None,1)[0]:
2057 line = l2
2062 line = l2
2058 break
2063 break
2059
2064
2060 line=l2
2065 line=l2
2061
2066
2062
2067
2063 # print "al expand to",line #dbg
2068 # print "al expand to",line #dbg
2064 else:
2069 else:
2065 break
2070 break
2066
2071
2067 return line
2072 return line
2068
2073
2069 def transform_alias(self, alias,rest=''):
2074 def transform_alias(self, alias,rest=''):
2070 """ Transform alias to system command string.
2075 """ Transform alias to system command string.
2071 """
2076 """
2072 trg = self.alias_table[alias]
2077 trg = self.alias_table[alias]
2073
2078
2074 nargs,cmd = trg
2079 nargs,cmd = trg
2075 # print trg #dbg
2080 # print trg #dbg
2076 if ' ' in cmd and os.path.isfile(cmd):
2081 if ' ' in cmd and os.path.isfile(cmd):
2077 cmd = '"%s"' % cmd
2082 cmd = '"%s"' % cmd
2078
2083
2079 # Expand the %l special to be the user's input line
2084 # Expand the %l special to be the user's input line
2080 if cmd.find('%l') >= 0:
2085 if cmd.find('%l') >= 0:
2081 cmd = cmd.replace('%l',rest)
2086 cmd = cmd.replace('%l',rest)
2082 rest = ''
2087 rest = ''
2083 if nargs==0:
2088 if nargs==0:
2084 # Simple, argument-less aliases
2089 # Simple, argument-less aliases
2085 cmd = '%s %s' % (cmd,rest)
2090 cmd = '%s %s' % (cmd,rest)
2086 else:
2091 else:
2087 # Handle aliases with positional arguments
2092 # Handle aliases with positional arguments
2088 args = rest.split(None,nargs)
2093 args = rest.split(None,nargs)
2089 if len(args)< nargs:
2094 if len(args)< nargs:
2090 error('Alias <%s> requires %s arguments, %s given.' %
2095 error('Alias <%s> requires %s arguments, %s given.' %
2091 (alias,nargs,len(args)))
2096 (alias,nargs,len(args)))
2092 return None
2097 return None
2093 cmd = '%s %s' % (cmd % tuple(args[:nargs]),' '.join(args[nargs:]))
2098 cmd = '%s %s' % (cmd % tuple(args[:nargs]),' '.join(args[nargs:]))
2094 # Now call the macro, evaluating in the user's namespace
2099 # Now call the macro, evaluating in the user's namespace
2095 #print 'new command: <%r>' % cmd # dbg
2100 #print 'new command: <%r>' % cmd # dbg
2096 return cmd
2101 return cmd
2097
2102
2098 def call_alias(self,alias,rest=''):
2103 def call_alias(self,alias,rest=''):
2099 """Call an alias given its name and the rest of the line.
2104 """Call an alias given its name and the rest of the line.
2100
2105
2101 This is only used to provide backwards compatibility for users of
2106 This is only used to provide backwards compatibility for users of
2102 ipalias(), use of which is not recommended for anymore."""
2107 ipalias(), use of which is not recommended for anymore."""
2103
2108
2104 # Now call the macro, evaluating in the user's namespace
2109 # Now call the macro, evaluating in the user's namespace
2105 cmd = self.transform_alias(alias, rest)
2110 cmd = self.transform_alias(alias, rest)
2106 try:
2111 try:
2107 self.system(cmd)
2112 self.system(cmd)
2108 except:
2113 except:
2109 self.showtraceback()
2114 self.showtraceback()
2110
2115
2111 def indent_current_str(self):
2116 def indent_current_str(self):
2112 """return the current level of indentation as a string"""
2117 """return the current level of indentation as a string"""
2113 return self.indent_current_nsp * ' '
2118 return self.indent_current_nsp * ' '
2114
2119
2115 def autoindent_update(self,line):
2120 def autoindent_update(self,line):
2116 """Keep track of the indent level."""
2121 """Keep track of the indent level."""
2117
2122
2118 #debugx('line')
2123 #debugx('line')
2119 #debugx('self.indent_current_nsp')
2124 #debugx('self.indent_current_nsp')
2120 if self.autoindent:
2125 if self.autoindent:
2121 if line:
2126 if line:
2122 inisp = num_ini_spaces(line)
2127 inisp = num_ini_spaces(line)
2123 if inisp < self.indent_current_nsp:
2128 if inisp < self.indent_current_nsp:
2124 self.indent_current_nsp = inisp
2129 self.indent_current_nsp = inisp
2125
2130
2126 if line[-1] == ':':
2131 if line[-1] == ':':
2127 self.indent_current_nsp += 4
2132 self.indent_current_nsp += 4
2128 elif dedent_re.match(line):
2133 elif dedent_re.match(line):
2129 self.indent_current_nsp -= 4
2134 self.indent_current_nsp -= 4
2130 else:
2135 else:
2131 self.indent_current_nsp = 0
2136 self.indent_current_nsp = 0
2132
2137
2133 def runlines(self,lines):
2138 def runlines(self,lines):
2134 """Run a string of one or more lines of source.
2139 """Run a string of one or more lines of source.
2135
2140
2136 This method is capable of running a string containing multiple source
2141 This method is capable of running a string containing multiple source
2137 lines, as if they had been entered at the IPython prompt. Since it
2142 lines, as if they had been entered at the IPython prompt. Since it
2138 exposes IPython's processing machinery, the given strings can contain
2143 exposes IPython's processing machinery, the given strings can contain
2139 magic calls (%magic), special shell access (!cmd), etc."""
2144 magic calls (%magic), special shell access (!cmd), etc."""
2140
2145
2141 # We must start with a clean buffer, in case this is run from an
2146 # We must start with a clean buffer, in case this is run from an
2142 # interactive IPython session (via a magic, for example).
2147 # interactive IPython session (via a magic, for example).
2143 self.resetbuffer()
2148 self.resetbuffer()
2144 lines = lines.split('\n')
2149 lines = lines.split('\n')
2145 more = 0
2150 more = 0
2146
2151
2147 for line in lines:
2152 for line in lines:
2148 # skip blank lines so we don't mess up the prompt counter, but do
2153 # skip blank lines so we don't mess up the prompt counter, but do
2149 # NOT skip even a blank line if we are in a code block (more is
2154 # NOT skip even a blank line if we are in a code block (more is
2150 # true)
2155 # true)
2151
2156
2152 if line or more:
2157 if line or more:
2153 # push to raw history, so hist line numbers stay in sync
2158 # push to raw history, so hist line numbers stay in sync
2154 self.input_hist_raw.append("# " + line + "\n")
2159 self.input_hist_raw.append("# " + line + "\n")
2155 more = self.push(self.prefilter(line,more))
2160 more = self.push(self.prefilter(line,more))
2156 # IPython's runsource returns None if there was an error
2161 # IPython's runsource returns None if there was an error
2157 # compiling the code. This allows us to stop processing right
2162 # compiling the code. This allows us to stop processing right
2158 # away, so the user gets the error message at the right place.
2163 # away, so the user gets the error message at the right place.
2159 if more is None:
2164 if more is None:
2160 break
2165 break
2161 else:
2166 else:
2162 self.input_hist_raw.append("\n")
2167 self.input_hist_raw.append("\n")
2163 # final newline in case the input didn't have it, so that the code
2168 # final newline in case the input didn't have it, so that the code
2164 # actually does get executed
2169 # actually does get executed
2165 if more:
2170 if more:
2166 self.push('\n')
2171 self.push('\n')
2167
2172
2168 def runsource(self, source, filename='<input>', symbol='single'):
2173 def runsource(self, source, filename='<input>', symbol='single'):
2169 """Compile and run some source in the interpreter.
2174 """Compile and run some source in the interpreter.
2170
2175
2171 Arguments are as for compile_command().
2176 Arguments are as for compile_command().
2172
2177
2173 One several things can happen:
2178 One several things can happen:
2174
2179
2175 1) The input is incorrect; compile_command() raised an
2180 1) The input is incorrect; compile_command() raised an
2176 exception (SyntaxError or OverflowError). A syntax traceback
2181 exception (SyntaxError or OverflowError). A syntax traceback
2177 will be printed by calling the showsyntaxerror() method.
2182 will be printed by calling the showsyntaxerror() method.
2178
2183
2179 2) The input is incomplete, and more input is required;
2184 2) The input is incomplete, and more input is required;
2180 compile_command() returned None. Nothing happens.
2185 compile_command() returned None. Nothing happens.
2181
2186
2182 3) The input is complete; compile_command() returned a code
2187 3) The input is complete; compile_command() returned a code
2183 object. The code is executed by calling self.runcode() (which
2188 object. The code is executed by calling self.runcode() (which
2184 also handles run-time exceptions, except for SystemExit).
2189 also handles run-time exceptions, except for SystemExit).
2185
2190
2186 The return value is:
2191 The return value is:
2187
2192
2188 - True in case 2
2193 - True in case 2
2189
2194
2190 - False in the other cases, unless an exception is raised, where
2195 - False in the other cases, unless an exception is raised, where
2191 None is returned instead. This can be used by external callers to
2196 None is returned instead. This can be used by external callers to
2192 know whether to continue feeding input or not.
2197 know whether to continue feeding input or not.
2193
2198
2194 The return value can be used to decide whether to use sys.ps1 or
2199 The return value can be used to decide whether to use sys.ps1 or
2195 sys.ps2 to prompt the next line."""
2200 sys.ps2 to prompt the next line."""
2196
2201
2197 # if the source code has leading blanks, add 'if 1:\n' to it
2202 # if the source code has leading blanks, add 'if 1:\n' to it
2198 # this allows execution of indented pasted code. It is tempting
2203 # this allows execution of indented pasted code. It is tempting
2199 # to add '\n' at the end of source to run commands like ' a=1'
2204 # to add '\n' at the end of source to run commands like ' a=1'
2200 # directly, but this fails for more complicated scenarios
2205 # directly, but this fails for more complicated scenarios
2201 source=source.encode(self.stdin_encoding)
2206 source=source.encode(self.stdin_encoding)
2202 if source[:1] in [' ', '\t']:
2207 if source[:1] in [' ', '\t']:
2203 source = 'if 1:\n%s' % source
2208 source = 'if 1:\n%s' % source
2204
2209
2205 try:
2210 try:
2206 code = self.compile(source,filename,symbol)
2211 code = self.compile(source,filename,symbol)
2207 except (OverflowError, SyntaxError, ValueError, TypeError):
2212 except (OverflowError, SyntaxError, ValueError, TypeError):
2208 # Case 1
2213 # Case 1
2209 self.showsyntaxerror(filename)
2214 self.showsyntaxerror(filename)
2210 return None
2215 return None
2211
2216
2212 if code is None:
2217 if code is None:
2213 # Case 2
2218 # Case 2
2214 return True
2219 return True
2215
2220
2216 # Case 3
2221 # Case 3
2217 # We store the code object so that threaded shells and
2222 # We store the code object so that threaded shells and
2218 # custom exception handlers can access all this info if needed.
2223 # custom exception handlers can access all this info if needed.
2219 # The source corresponding to this can be obtained from the
2224 # The source corresponding to this can be obtained from the
2220 # buffer attribute as '\n'.join(self.buffer).
2225 # buffer attribute as '\n'.join(self.buffer).
2221 self.code_to_run = code
2226 self.code_to_run = code
2222 # now actually execute the code object
2227 # now actually execute the code object
2223 if self.runcode(code) == 0:
2228 if self.runcode(code) == 0:
2224 return False
2229 return False
2225 else:
2230 else:
2226 return None
2231 return None
2227
2232
2228 def runcode(self,code_obj):
2233 def runcode(self,code_obj):
2229 """Execute a code object.
2234 """Execute a code object.
2230
2235
2231 When an exception occurs, self.showtraceback() is called to display a
2236 When an exception occurs, self.showtraceback() is called to display a
2232 traceback.
2237 traceback.
2233
2238
2234 Return value: a flag indicating whether the code to be run completed
2239 Return value: a flag indicating whether the code to be run completed
2235 successfully:
2240 successfully:
2236
2241
2237 - 0: successful execution.
2242 - 0: successful execution.
2238 - 1: an error occurred.
2243 - 1: an error occurred.
2239 """
2244 """
2240
2245
2241 # Set our own excepthook in case the user code tries to call it
2246 # Set our own excepthook in case the user code tries to call it
2242 # directly, so that the IPython crash handler doesn't get triggered
2247 # directly, so that the IPython crash handler doesn't get triggered
2243 old_excepthook,sys.excepthook = sys.excepthook, self.excepthook
2248 old_excepthook,sys.excepthook = sys.excepthook, self.excepthook
2244
2249
2245 # we save the original sys.excepthook in the instance, in case config
2250 # we save the original sys.excepthook in the instance, in case config
2246 # code (such as magics) needs access to it.
2251 # code (such as magics) needs access to it.
2247 self.sys_excepthook = old_excepthook
2252 self.sys_excepthook = old_excepthook
2248 outflag = 1 # happens in more places, so it's easier as default
2253 outflag = 1 # happens in more places, so it's easier as default
2249 try:
2254 try:
2250 try:
2255 try:
2251 self.hooks.pre_runcode_hook()
2256 self.hooks.pre_runcode_hook()
2252 exec code_obj in self.user_global_ns, self.user_ns
2257 exec code_obj in self.user_global_ns, self.user_ns
2253 finally:
2258 finally:
2254 # Reset our crash handler in place
2259 # Reset our crash handler in place
2255 sys.excepthook = old_excepthook
2260 sys.excepthook = old_excepthook
2256 except SystemExit:
2261 except SystemExit:
2257 self.resetbuffer()
2262 self.resetbuffer()
2258 self.showtraceback()
2263 self.showtraceback()
2259 warn("Type %exit or %quit to exit IPython "
2264 warn("Type %exit or %quit to exit IPython "
2260 "(%Exit or %Quit do so unconditionally).",level=1)
2265 "(%Exit or %Quit do so unconditionally).",level=1)
2261 except self.custom_exceptions:
2266 except self.custom_exceptions:
2262 etype,value,tb = sys.exc_info()
2267 etype,value,tb = sys.exc_info()
2263 self.CustomTB(etype,value,tb)
2268 self.CustomTB(etype,value,tb)
2264 except:
2269 except:
2265 self.showtraceback()
2270 self.showtraceback()
2266 else:
2271 else:
2267 outflag = 0
2272 outflag = 0
2268 if softspace(sys.stdout, 0):
2273 if softspace(sys.stdout, 0):
2269 print
2274 print
2270 # Flush out code object which has been run (and source)
2275 # Flush out code object which has been run (and source)
2271 self.code_to_run = None
2276 self.code_to_run = None
2272 return outflag
2277 return outflag
2273
2278
2274 def push(self, line):
2279 def push(self, line):
2275 """Push a line to the interpreter.
2280 """Push a line to the interpreter.
2276
2281
2277 The line should not have a trailing newline; it may have
2282 The line should not have a trailing newline; it may have
2278 internal newlines. The line is appended to a buffer and the
2283 internal newlines. The line is appended to a buffer and the
2279 interpreter's runsource() method is called with the
2284 interpreter's runsource() method is called with the
2280 concatenated contents of the buffer as source. If this
2285 concatenated contents of the buffer as source. If this
2281 indicates that the command was executed or invalid, the buffer
2286 indicates that the command was executed or invalid, the buffer
2282 is reset; otherwise, the command is incomplete, and the buffer
2287 is reset; otherwise, the command is incomplete, and the buffer
2283 is left as it was after the line was appended. The return
2288 is left as it was after the line was appended. The return
2284 value is 1 if more input is required, 0 if the line was dealt
2289 value is 1 if more input is required, 0 if the line was dealt
2285 with in some way (this is the same as runsource()).
2290 with in some way (this is the same as runsource()).
2286 """
2291 """
2287
2292
2288 # autoindent management should be done here, and not in the
2293 # autoindent management should be done here, and not in the
2289 # interactive loop, since that one is only seen by keyboard input. We
2294 # interactive loop, since that one is only seen by keyboard input. We
2290 # need this done correctly even for code run via runlines (which uses
2295 # need this done correctly even for code run via runlines (which uses
2291 # push).
2296 # push).
2292
2297
2293 #print 'push line: <%s>' % line # dbg
2298 #print 'push line: <%s>' % line # dbg
2294 for subline in line.splitlines():
2299 for subline in line.splitlines():
2295 self.autoindent_update(subline)
2300 self.autoindent_update(subline)
2296 self.buffer.append(line)
2301 self.buffer.append(line)
2297 more = self.runsource('\n'.join(self.buffer), self.filename)
2302 more = self.runsource('\n'.join(self.buffer), self.filename)
2298 if not more:
2303 if not more:
2299 self.resetbuffer()
2304 self.resetbuffer()
2300 return more
2305 return more
2301
2306
2302 def split_user_input(self, line):
2307 def split_user_input(self, line):
2303 # This is really a hold-over to support ipapi and some extensions
2308 # This is really a hold-over to support ipapi and some extensions
2304 return prefilter.splitUserInput(line)
2309 return prefilter.splitUserInput(line)
2305
2310
2306 def resetbuffer(self):
2311 def resetbuffer(self):
2307 """Reset the input buffer."""
2312 """Reset the input buffer."""
2308 self.buffer[:] = []
2313 self.buffer[:] = []
2309
2314
2310 def raw_input(self,prompt='',continue_prompt=False):
2315 def raw_input(self,prompt='',continue_prompt=False):
2311 """Write a prompt and read a line.
2316 """Write a prompt and read a line.
2312
2317
2313 The returned line does not include the trailing newline.
2318 The returned line does not include the trailing newline.
2314 When the user enters the EOF key sequence, EOFError is raised.
2319 When the user enters the EOF key sequence, EOFError is raised.
2315
2320
2316 Optional inputs:
2321 Optional inputs:
2317
2322
2318 - prompt(''): a string to be printed to prompt the user.
2323 - prompt(''): a string to be printed to prompt the user.
2319
2324
2320 - continue_prompt(False): whether this line is the first one or a
2325 - continue_prompt(False): whether this line is the first one or a
2321 continuation in a sequence of inputs.
2326 continuation in a sequence of inputs.
2322 """
2327 """
2323
2328
2324 # Code run by the user may have modified the readline completer state.
2329 # Code run by the user may have modified the readline completer state.
2325 # We must ensure that our completer is back in place.
2330 # We must ensure that our completer is back in place.
2326 if self.has_readline:
2331 if self.has_readline:
2327 self.set_completer()
2332 self.set_completer()
2328
2333
2329 try:
2334 try:
2330 line = raw_input_original(prompt).decode(self.stdin_encoding)
2335 line = raw_input_original(prompt).decode(self.stdin_encoding)
2331 except ValueError:
2336 except ValueError:
2332 warn("\n********\nYou or a %run:ed script called sys.stdin.close()"
2337 warn("\n********\nYou or a %run:ed script called sys.stdin.close()"
2333 " or sys.stdout.close()!\nExiting IPython!")
2338 " or sys.stdout.close()!\nExiting IPython!")
2334 self.ask_exit()
2339 self.ask_exit()
2335 return ""
2340 return ""
2336
2341
2337 # Try to be reasonably smart about not re-indenting pasted input more
2342 # Try to be reasonably smart about not re-indenting pasted input more
2338 # than necessary. We do this by trimming out the auto-indent initial
2343 # than necessary. We do this by trimming out the auto-indent initial
2339 # spaces, if the user's actual input started itself with whitespace.
2344 # spaces, if the user's actual input started itself with whitespace.
2340 #debugx('self.buffer[-1]')
2345 #debugx('self.buffer[-1]')
2341
2346
2342 if self.autoindent:
2347 if self.autoindent:
2343 if num_ini_spaces(line) > self.indent_current_nsp:
2348 if num_ini_spaces(line) > self.indent_current_nsp:
2344 line = line[self.indent_current_nsp:]
2349 line = line[self.indent_current_nsp:]
2345 self.indent_current_nsp = 0
2350 self.indent_current_nsp = 0
2346
2351
2347 # store the unfiltered input before the user has any chance to modify
2352 # store the unfiltered input before the user has any chance to modify
2348 # it.
2353 # it.
2349 if line.strip():
2354 if line.strip():
2350 if continue_prompt:
2355 if continue_prompt:
2351 self.input_hist_raw[-1] += '%s\n' % line
2356 self.input_hist_raw[-1] += '%s\n' % line
2352 if self.has_readline: # and some config option is set?
2357 if self.has_readline: # and some config option is set?
2353 try:
2358 try:
2354 histlen = self.readline.get_current_history_length()
2359 histlen = self.readline.get_current_history_length()
2355 if histlen > 1:
2360 if histlen > 1:
2356 newhist = self.input_hist_raw[-1].rstrip()
2361 newhist = self.input_hist_raw[-1].rstrip()
2357 self.readline.remove_history_item(histlen-1)
2362 self.readline.remove_history_item(histlen-1)
2358 self.readline.replace_history_item(histlen-2,
2363 self.readline.replace_history_item(histlen-2,
2359 newhist.encode(self.stdin_encoding))
2364 newhist.encode(self.stdin_encoding))
2360 except AttributeError:
2365 except AttributeError:
2361 pass # re{move,place}_history_item are new in 2.4.
2366 pass # re{move,place}_history_item are new in 2.4.
2362 else:
2367 else:
2363 self.input_hist_raw.append('%s\n' % line)
2368 self.input_hist_raw.append('%s\n' % line)
2364 # only entries starting at first column go to shadow history
2369 # only entries starting at first column go to shadow history
2365 if line.lstrip() == line:
2370 if line.lstrip() == line:
2366 self.shadowhist.add(line.strip())
2371 self.shadowhist.add(line.strip())
2367 elif not continue_prompt:
2372 elif not continue_prompt:
2368 self.input_hist_raw.append('\n')
2373 self.input_hist_raw.append('\n')
2369 try:
2374 try:
2370 lineout = self.prefilter(line,continue_prompt)
2375 lineout = self.prefilter(line,continue_prompt)
2371 except:
2376 except:
2372 # blanket except, in case a user-defined prefilter crashes, so it
2377 # blanket except, in case a user-defined prefilter crashes, so it
2373 # can't take all of ipython with it.
2378 # can't take all of ipython with it.
2374 self.showtraceback()
2379 self.showtraceback()
2375 return ''
2380 return ''
2376 else:
2381 else:
2377 return lineout
2382 return lineout
2378
2383
2379 def _prefilter(self, line, continue_prompt):
2384 def _prefilter(self, line, continue_prompt):
2380 """Calls different preprocessors, depending on the form of line."""
2385 """Calls different preprocessors, depending on the form of line."""
2381
2386
2382 # All handlers *must* return a value, even if it's blank ('').
2387 # All handlers *must* return a value, even if it's blank ('').
2383
2388
2384 # Lines are NOT logged here. Handlers should process the line as
2389 # Lines are NOT logged here. Handlers should process the line as
2385 # needed, update the cache AND log it (so that the input cache array
2390 # needed, update the cache AND log it (so that the input cache array
2386 # stays synced).
2391 # stays synced).
2387
2392
2388 #.....................................................................
2393 #.....................................................................
2389 # Code begins
2394 # Code begins
2390
2395
2391 #if line.startswith('%crash'): raise RuntimeError,'Crash now!' # dbg
2396 #if line.startswith('%crash'): raise RuntimeError,'Crash now!' # dbg
2392
2397
2393 # save the line away in case we crash, so the post-mortem handler can
2398 # save the line away in case we crash, so the post-mortem handler can
2394 # record it
2399 # record it
2395 self._last_input_line = line
2400 self._last_input_line = line
2396
2401
2397 #print '***line: <%s>' % line # dbg
2402 #print '***line: <%s>' % line # dbg
2398
2403
2399 if not line:
2404 if not line:
2400 # Return immediately on purely empty lines, so that if the user
2405 # Return immediately on purely empty lines, so that if the user
2401 # previously typed some whitespace that started a continuation
2406 # previously typed some whitespace that started a continuation
2402 # prompt, he can break out of that loop with just an empty line.
2407 # prompt, he can break out of that loop with just an empty line.
2403 # This is how the default python prompt works.
2408 # This is how the default python prompt works.
2404
2409
2405 # Only return if the accumulated input buffer was just whitespace!
2410 # Only return if the accumulated input buffer was just whitespace!
2406 if ''.join(self.buffer).isspace():
2411 if ''.join(self.buffer).isspace():
2407 self.buffer[:] = []
2412 self.buffer[:] = []
2408 return ''
2413 return ''
2409
2414
2410 line_info = prefilter.LineInfo(line, continue_prompt)
2415 line_info = prefilter.LineInfo(line, continue_prompt)
2411
2416
2412 # the input history needs to track even empty lines
2417 # the input history needs to track even empty lines
2413 stripped = line.strip()
2418 stripped = line.strip()
2414
2419
2415 if not stripped:
2420 if not stripped:
2416 if not continue_prompt:
2421 if not continue_prompt:
2417 self.outputcache.prompt_count -= 1
2422 self.outputcache.prompt_count -= 1
2418 return self.handle_normal(line_info)
2423 return self.handle_normal(line_info)
2419
2424
2420 # print '***cont',continue_prompt # dbg
2425 # print '***cont',continue_prompt # dbg
2421 # special handlers are only allowed for single line statements
2426 # special handlers are only allowed for single line statements
2422 if continue_prompt and not self.rc.multi_line_specials:
2427 if continue_prompt and not self.rc.multi_line_specials:
2423 return self.handle_normal(line_info)
2428 return self.handle_normal(line_info)
2424
2429
2425
2430
2426 # See whether any pre-existing handler can take care of it
2431 # See whether any pre-existing handler can take care of it
2427 rewritten = self.hooks.input_prefilter(stripped)
2432 rewritten = self.hooks.input_prefilter(stripped)
2428 if rewritten != stripped: # ok, some prefilter did something
2433 if rewritten != stripped: # ok, some prefilter did something
2429 rewritten = line_info.pre + rewritten # add indentation
2434 rewritten = line_info.pre + rewritten # add indentation
2430 return self.handle_normal(prefilter.LineInfo(rewritten,
2435 return self.handle_normal(prefilter.LineInfo(rewritten,
2431 continue_prompt))
2436 continue_prompt))
2432
2437
2433 #print 'pre <%s> iFun <%s> rest <%s>' % (pre,iFun,theRest) # dbg
2438 #print 'pre <%s> iFun <%s> rest <%s>' % (pre,iFun,theRest) # dbg
2434
2439
2435 return prefilter.prefilter(line_info, self)
2440 return prefilter.prefilter(line_info, self)
2436
2441
2437
2442
2438 def _prefilter_dumb(self, line, continue_prompt):
2443 def _prefilter_dumb(self, line, continue_prompt):
2439 """simple prefilter function, for debugging"""
2444 """simple prefilter function, for debugging"""
2440 return self.handle_normal(line,continue_prompt)
2445 return self.handle_normal(line,continue_prompt)
2441
2446
2442
2447
2443 def multiline_prefilter(self, line, continue_prompt):
2448 def multiline_prefilter(self, line, continue_prompt):
2444 """ Run _prefilter for each line of input
2449 """ Run _prefilter for each line of input
2445
2450
2446 Covers cases where there are multiple lines in the user entry,
2451 Covers cases where there are multiple lines in the user entry,
2447 which is the case when the user goes back to a multiline history
2452 which is the case when the user goes back to a multiline history
2448 entry and presses enter.
2453 entry and presses enter.
2449
2454
2450 """
2455 """
2451 out = []
2456 out = []
2452 for l in line.rstrip('\n').split('\n'):
2457 for l in line.rstrip('\n').split('\n'):
2453 out.append(self._prefilter(l, continue_prompt))
2458 out.append(self._prefilter(l, continue_prompt))
2454 return '\n'.join(out)
2459 return '\n'.join(out)
2455
2460
2456 # Set the default prefilter() function (this can be user-overridden)
2461 # Set the default prefilter() function (this can be user-overridden)
2457 prefilter = multiline_prefilter
2462 prefilter = multiline_prefilter
2458
2463
2459 def handle_normal(self,line_info):
2464 def handle_normal(self,line_info):
2460 """Handle normal input lines. Use as a template for handlers."""
2465 """Handle normal input lines. Use as a template for handlers."""
2461
2466
2462 # With autoindent on, we need some way to exit the input loop, and I
2467 # With autoindent on, we need some way to exit the input loop, and I
2463 # don't want to force the user to have to backspace all the way to
2468 # don't want to force the user to have to backspace all the way to
2464 # clear the line. The rule will be in this case, that either two
2469 # clear the line. The rule will be in this case, that either two
2465 # lines of pure whitespace in a row, or a line of pure whitespace but
2470 # lines of pure whitespace in a row, or a line of pure whitespace but
2466 # of a size different to the indent level, will exit the input loop.
2471 # of a size different to the indent level, will exit the input loop.
2467 line = line_info.line
2472 line = line_info.line
2468 continue_prompt = line_info.continue_prompt
2473 continue_prompt = line_info.continue_prompt
2469
2474
2470 if (continue_prompt and self.autoindent and line.isspace() and
2475 if (continue_prompt and self.autoindent and line.isspace() and
2471 (0 < abs(len(line) - self.indent_current_nsp) <= 2 or
2476 (0 < abs(len(line) - self.indent_current_nsp) <= 2 or
2472 (self.buffer[-1]).isspace() )):
2477 (self.buffer[-1]).isspace() )):
2473 line = ''
2478 line = ''
2474
2479
2475 self.log(line,line,continue_prompt)
2480 self.log(line,line,continue_prompt)
2476 return line
2481 return line
2477
2482
2478 def handle_alias(self,line_info):
2483 def handle_alias(self,line_info):
2479 """Handle alias input lines. """
2484 """Handle alias input lines. """
2480 tgt = self.alias_table[line_info.iFun]
2485 tgt = self.alias_table[line_info.iFun]
2481 # print "=>",tgt #dbg
2486 # print "=>",tgt #dbg
2482 if callable(tgt):
2487 if callable(tgt):
2483 if '$' in line_info.line:
2488 if '$' in line_info.line:
2484 call_meth = '(_ip, _ip.itpl(%s))'
2489 call_meth = '(_ip, _ip.itpl(%s))'
2485 else:
2490 else:
2486 call_meth = '(_ip,%s)'
2491 call_meth = '(_ip,%s)'
2487 line_out = ("%s_sh.%s" + call_meth) % (line_info.preWhitespace,
2492 line_out = ("%s_sh.%s" + call_meth) % (line_info.preWhitespace,
2488 line_info.iFun,
2493 line_info.iFun,
2489 make_quoted_expr(line_info.line))
2494 make_quoted_expr(line_info.line))
2490 else:
2495 else:
2491 transformed = self.expand_aliases(line_info.iFun,line_info.theRest)
2496 transformed = self.expand_aliases(line_info.iFun,line_info.theRest)
2492
2497
2493 # pre is needed, because it carries the leading whitespace. Otherwise
2498 # pre is needed, because it carries the leading whitespace. Otherwise
2494 # aliases won't work in indented sections.
2499 # aliases won't work in indented sections.
2495 line_out = '%s_ip.system(%s)' % (line_info.preWhitespace,
2500 line_out = '%s_ip.system(%s)' % (line_info.preWhitespace,
2496 make_quoted_expr( transformed ))
2501 make_quoted_expr( transformed ))
2497
2502
2498 self.log(line_info.line,line_out,line_info.continue_prompt)
2503 self.log(line_info.line,line_out,line_info.continue_prompt)
2499 #print 'line out:',line_out # dbg
2504 #print 'line out:',line_out # dbg
2500 return line_out
2505 return line_out
2501
2506
2502 def handle_shell_escape(self, line_info):
2507 def handle_shell_escape(self, line_info):
2503 """Execute the line in a shell, empty return value"""
2508 """Execute the line in a shell, empty return value"""
2504 #print 'line in :', `line` # dbg
2509 #print 'line in :', `line` # dbg
2505 line = line_info.line
2510 line = line_info.line
2506 if line.lstrip().startswith('!!'):
2511 if line.lstrip().startswith('!!'):
2507 # rewrite LineInfo's line, iFun and theRest to properly hold the
2512 # rewrite LineInfo's line, iFun and theRest to properly hold the
2508 # call to %sx and the actual command to be executed, so
2513 # call to %sx and the actual command to be executed, so
2509 # handle_magic can work correctly. Note that this works even if
2514 # handle_magic can work correctly. Note that this works even if
2510 # the line is indented, so it handles multi_line_specials
2515 # the line is indented, so it handles multi_line_specials
2511 # properly.
2516 # properly.
2512 new_rest = line.lstrip()[2:]
2517 new_rest = line.lstrip()[2:]
2513 line_info.line = '%ssx %s' % (self.ESC_MAGIC,new_rest)
2518 line_info.line = '%ssx %s' % (self.ESC_MAGIC,new_rest)
2514 line_info.iFun = 'sx'
2519 line_info.iFun = 'sx'
2515 line_info.theRest = new_rest
2520 line_info.theRest = new_rest
2516 return self.handle_magic(line_info)
2521 return self.handle_magic(line_info)
2517 else:
2522 else:
2518 cmd = line.lstrip().lstrip('!')
2523 cmd = line.lstrip().lstrip('!')
2519 line_out = '%s_ip.system(%s)' % (line_info.preWhitespace,
2524 line_out = '%s_ip.system(%s)' % (line_info.preWhitespace,
2520 make_quoted_expr(cmd))
2525 make_quoted_expr(cmd))
2521 # update cache/log and return
2526 # update cache/log and return
2522 self.log(line,line_out,line_info.continue_prompt)
2527 self.log(line,line_out,line_info.continue_prompt)
2523 return line_out
2528 return line_out
2524
2529
2525 def handle_magic(self, line_info):
2530 def handle_magic(self, line_info):
2526 """Execute magic functions."""
2531 """Execute magic functions."""
2527 iFun = line_info.iFun
2532 iFun = line_info.iFun
2528 theRest = line_info.theRest
2533 theRest = line_info.theRest
2529 cmd = '%s_ip.magic(%s)' % (line_info.preWhitespace,
2534 cmd = '%s_ip.magic(%s)' % (line_info.preWhitespace,
2530 make_quoted_expr(iFun + " " + theRest))
2535 make_quoted_expr(iFun + " " + theRest))
2531 self.log(line_info.line,cmd,line_info.continue_prompt)
2536 self.log(line_info.line,cmd,line_info.continue_prompt)
2532 #print 'in handle_magic, cmd=<%s>' % cmd # dbg
2537 #print 'in handle_magic, cmd=<%s>' % cmd # dbg
2533 return cmd
2538 return cmd
2534
2539
2535 def handle_auto(self, line_info):
2540 def handle_auto(self, line_info):
2536 """Hande lines which can be auto-executed, quoting if requested."""
2541 """Hande lines which can be auto-executed, quoting if requested."""
2537
2542
2538 line = line_info.line
2543 line = line_info.line
2539 iFun = line_info.iFun
2544 iFun = line_info.iFun
2540 theRest = line_info.theRest
2545 theRest = line_info.theRest
2541 pre = line_info.pre
2546 pre = line_info.pre
2542 continue_prompt = line_info.continue_prompt
2547 continue_prompt = line_info.continue_prompt
2543 obj = line_info.ofind(self)['obj']
2548 obj = line_info.ofind(self)['obj']
2544
2549
2545 #print 'pre <%s> iFun <%s> rest <%s>' % (pre,iFun,theRest) # dbg
2550 #print 'pre <%s> iFun <%s> rest <%s>' % (pre,iFun,theRest) # dbg
2546
2551
2547 # This should only be active for single-line input!
2552 # This should only be active for single-line input!
2548 if continue_prompt:
2553 if continue_prompt:
2549 self.log(line,line,continue_prompt)
2554 self.log(line,line,continue_prompt)
2550 return line
2555 return line
2551
2556
2552 force_auto = isinstance(obj, IPython.ipapi.IPyAutocall)
2557 force_auto = isinstance(obj, IPython.ipapi.IPyAutocall)
2553 auto_rewrite = True
2558 auto_rewrite = True
2554
2559
2555 if pre == self.ESC_QUOTE:
2560 if pre == self.ESC_QUOTE:
2556 # Auto-quote splitting on whitespace
2561 # Auto-quote splitting on whitespace
2557 newcmd = '%s("%s")' % (iFun,'", "'.join(theRest.split()) )
2562 newcmd = '%s("%s")' % (iFun,'", "'.join(theRest.split()) )
2558 elif pre == self.ESC_QUOTE2:
2563 elif pre == self.ESC_QUOTE2:
2559 # Auto-quote whole string
2564 # Auto-quote whole string
2560 newcmd = '%s("%s")' % (iFun,theRest)
2565 newcmd = '%s("%s")' % (iFun,theRest)
2561 elif pre == self.ESC_PAREN:
2566 elif pre == self.ESC_PAREN:
2562 newcmd = '%s(%s)' % (iFun,",".join(theRest.split()))
2567 newcmd = '%s(%s)' % (iFun,",".join(theRest.split()))
2563 else:
2568 else:
2564 # Auto-paren.
2569 # Auto-paren.
2565 # We only apply it to argument-less calls if the autocall
2570 # We only apply it to argument-less calls if the autocall
2566 # parameter is set to 2. We only need to check that autocall is <
2571 # parameter is set to 2. We only need to check that autocall is <
2567 # 2, since this function isn't called unless it's at least 1.
2572 # 2, since this function isn't called unless it's at least 1.
2568 if not theRest and (self.rc.autocall < 2) and not force_auto:
2573 if not theRest and (self.rc.autocall < 2) and not force_auto:
2569 newcmd = '%s %s' % (iFun,theRest)
2574 newcmd = '%s %s' % (iFun,theRest)
2570 auto_rewrite = False
2575 auto_rewrite = False
2571 else:
2576 else:
2572 if not force_auto and theRest.startswith('['):
2577 if not force_auto and theRest.startswith('['):
2573 if hasattr(obj,'__getitem__'):
2578 if hasattr(obj,'__getitem__'):
2574 # Don't autocall in this case: item access for an object
2579 # Don't autocall in this case: item access for an object
2575 # which is BOTH callable and implements __getitem__.
2580 # which is BOTH callable and implements __getitem__.
2576 newcmd = '%s %s' % (iFun,theRest)
2581 newcmd = '%s %s' % (iFun,theRest)
2577 auto_rewrite = False
2582 auto_rewrite = False
2578 else:
2583 else:
2579 # if the object doesn't support [] access, go ahead and
2584 # if the object doesn't support [] access, go ahead and
2580 # autocall
2585 # autocall
2581 newcmd = '%s(%s)' % (iFun.rstrip(),theRest)
2586 newcmd = '%s(%s)' % (iFun.rstrip(),theRest)
2582 elif theRest.endswith(';'):
2587 elif theRest.endswith(';'):
2583 newcmd = '%s(%s);' % (iFun.rstrip(),theRest[:-1])
2588 newcmd = '%s(%s);' % (iFun.rstrip(),theRest[:-1])
2584 else:
2589 else:
2585 newcmd = '%s(%s)' % (iFun.rstrip(), theRest)
2590 newcmd = '%s(%s)' % (iFun.rstrip(), theRest)
2586
2591
2587 if auto_rewrite:
2592 if auto_rewrite:
2588 rw = self.outputcache.prompt1.auto_rewrite() + newcmd
2593 rw = self.outputcache.prompt1.auto_rewrite() + newcmd
2589
2594
2590 try:
2595 try:
2591 # plain ascii works better w/ pyreadline, on some machines, so
2596 # plain ascii works better w/ pyreadline, on some machines, so
2592 # we use it and only print uncolored rewrite if we have unicode
2597 # we use it and only print uncolored rewrite if we have unicode
2593 rw = str(rw)
2598 rw = str(rw)
2594 print >>Term.cout, rw
2599 print >>Term.cout, rw
2595 except UnicodeEncodeError:
2600 except UnicodeEncodeError:
2596 print "-------------->" + newcmd
2601 print "-------------->" + newcmd
2597
2602
2598 # log what is now valid Python, not the actual user input (without the
2603 # log what is now valid Python, not the actual user input (without the
2599 # final newline)
2604 # final newline)
2600 self.log(line,newcmd,continue_prompt)
2605 self.log(line,newcmd,continue_prompt)
2601 return newcmd
2606 return newcmd
2602
2607
2603 def handle_help(self, line_info):
2608 def handle_help(self, line_info):
2604 """Try to get some help for the object.
2609 """Try to get some help for the object.
2605
2610
2606 obj? or ?obj -> basic information.
2611 obj? or ?obj -> basic information.
2607 obj?? or ??obj -> more details.
2612 obj?? or ??obj -> more details.
2608 """
2613 """
2609
2614
2610 line = line_info.line
2615 line = line_info.line
2611 # We need to make sure that we don't process lines which would be
2616 # We need to make sure that we don't process lines which would be
2612 # otherwise valid python, such as "x=1 # what?"
2617 # otherwise valid python, such as "x=1 # what?"
2613 try:
2618 try:
2614 codeop.compile_command(line)
2619 codeop.compile_command(line)
2615 except SyntaxError:
2620 except SyntaxError:
2616 # We should only handle as help stuff which is NOT valid syntax
2621 # We should only handle as help stuff which is NOT valid syntax
2617 if line[0]==self.ESC_HELP:
2622 if line[0]==self.ESC_HELP:
2618 line = line[1:]
2623 line = line[1:]
2619 elif line[-1]==self.ESC_HELP:
2624 elif line[-1]==self.ESC_HELP:
2620 line = line[:-1]
2625 line = line[:-1]
2621 self.log(line,'#?'+line,line_info.continue_prompt)
2626 self.log(line,'#?'+line,line_info.continue_prompt)
2622 if line:
2627 if line:
2623 #print 'line:<%r>' % line # dbg
2628 #print 'line:<%r>' % line # dbg
2624 self.magic_pinfo(line)
2629 self.magic_pinfo(line)
2625 else:
2630 else:
2626 page(self.usage,screen_lines=self.rc.screen_length)
2631 page(self.usage,screen_lines=self.rc.screen_length)
2627 return '' # Empty string is needed here!
2632 return '' # Empty string is needed here!
2628 except:
2633 except:
2629 # Pass any other exceptions through to the normal handler
2634 # Pass any other exceptions through to the normal handler
2630 return self.handle_normal(line_info)
2635 return self.handle_normal(line_info)
2631 else:
2636 else:
2632 # If the code compiles ok, we should handle it normally
2637 # If the code compiles ok, we should handle it normally
2633 return self.handle_normal(line_info)
2638 return self.handle_normal(line_info)
2634
2639
2635 def getapi(self):
2640 def getapi(self):
2636 """ Get an IPApi object for this shell instance
2641 """ Get an IPApi object for this shell instance
2637
2642
2638 Getting an IPApi object is always preferable to accessing the shell
2643 Getting an IPApi object is always preferable to accessing the shell
2639 directly, but this holds true especially for extensions.
2644 directly, but this holds true especially for extensions.
2640
2645
2641 It should always be possible to implement an extension with IPApi
2646 It should always be possible to implement an extension with IPApi
2642 alone. If not, contact maintainer to request an addition.
2647 alone. If not, contact maintainer to request an addition.
2643
2648
2644 """
2649 """
2645 return self.api
2650 return self.api
2646
2651
2647 def handle_emacs(self, line_info):
2652 def handle_emacs(self, line_info):
2648 """Handle input lines marked by python-mode."""
2653 """Handle input lines marked by python-mode."""
2649
2654
2650 # Currently, nothing is done. Later more functionality can be added
2655 # Currently, nothing is done. Later more functionality can be added
2651 # here if needed.
2656 # here if needed.
2652
2657
2653 # The input cache shouldn't be updated
2658 # The input cache shouldn't be updated
2654 return line_info.line
2659 return line_info.line
2655
2660
2656
2661
2657 def mktempfile(self,data=None):
2662 def mktempfile(self,data=None):
2658 """Make a new tempfile and return its filename.
2663 """Make a new tempfile and return its filename.
2659
2664
2660 This makes a call to tempfile.mktemp, but it registers the created
2665 This makes a call to tempfile.mktemp, but it registers the created
2661 filename internally so ipython cleans it up at exit time.
2666 filename internally so ipython cleans it up at exit time.
2662
2667
2663 Optional inputs:
2668 Optional inputs:
2664
2669
2665 - data(None): if data is given, it gets written out to the temp file
2670 - data(None): if data is given, it gets written out to the temp file
2666 immediately, and the file is closed again."""
2671 immediately, and the file is closed again."""
2667
2672
2668 filename = tempfile.mktemp('.py','ipython_edit_')
2673 filename = tempfile.mktemp('.py','ipython_edit_')
2669 self.tempfiles.append(filename)
2674 self.tempfiles.append(filename)
2670
2675
2671 if data:
2676 if data:
2672 tmp_file = open(filename,'w')
2677 tmp_file = open(filename,'w')
2673 tmp_file.write(data)
2678 tmp_file.write(data)
2674 tmp_file.close()
2679 tmp_file.close()
2675 return filename
2680 return filename
2676
2681
2677 def write(self,data):
2682 def write(self,data):
2678 """Write a string to the default output"""
2683 """Write a string to the default output"""
2679 Term.cout.write(data)
2684 Term.cout.write(data)
2680
2685
2681 def write_err(self,data):
2686 def write_err(self,data):
2682 """Write a string to the default error output"""
2687 """Write a string to the default error output"""
2683 Term.cerr.write(data)
2688 Term.cerr.write(data)
2684
2689
2685 def ask_exit(self):
2690 def ask_exit(self):
2686 """ Call for exiting. Can be overiden and used as a callback. """
2691 """ Call for exiting. Can be overiden and used as a callback. """
2687 self.exit_now = True
2692 self.exit_now = True
2688
2693
2689 def exit(self):
2694 def exit(self):
2690 """Handle interactive exit.
2695 """Handle interactive exit.
2691
2696
2692 This method calls the ask_exit callback."""
2697 This method calls the ask_exit callback."""
2693
2698
2694 if self.rc.confirm_exit:
2699 if self.rc.confirm_exit:
2695 if self.ask_yes_no('Do you really want to exit ([y]/n)?','y'):
2700 if self.ask_yes_no('Do you really want to exit ([y]/n)?','y'):
2696 self.ask_exit()
2701 self.ask_exit()
2697 else:
2702 else:
2698 self.ask_exit()
2703 self.ask_exit()
2699
2704
2700 def safe_execfile(self,fname,*where,**kw):
2705 def safe_execfile(self,fname,*where,**kw):
2701 """A safe version of the builtin execfile().
2706 """A safe version of the builtin execfile().
2702
2707
2703 This version will never throw an exception, and knows how to handle
2708 This version will never throw an exception, and knows how to handle
2704 ipython logs as well.
2709 ipython logs as well.
2705
2710
2706 :Parameters:
2711 :Parameters:
2707 fname : string
2712 fname : string
2708 Name of the file to be executed.
2713 Name of the file to be executed.
2709
2714
2710 where : tuple
2715 where : tuple
2711 One or two namespaces, passed to execfile() as (globals,locals).
2716 One or two namespaces, passed to execfile() as (globals,locals).
2712 If only one is given, it is passed as both.
2717 If only one is given, it is passed as both.
2713
2718
2714 :Keywords:
2719 :Keywords:
2715 islog : boolean (False)
2720 islog : boolean (False)
2716
2721
2717 quiet : boolean (True)
2722 quiet : boolean (True)
2718
2723
2719 exit_ignore : boolean (False)
2724 exit_ignore : boolean (False)
2720 """
2725 """
2721
2726
2722 def syspath_cleanup():
2727 def syspath_cleanup():
2723 """Internal cleanup routine for sys.path."""
2728 """Internal cleanup routine for sys.path."""
2724 if add_dname:
2729 if add_dname:
2725 try:
2730 try:
2726 sys.path.remove(dname)
2731 sys.path.remove(dname)
2727 except ValueError:
2732 except ValueError:
2728 # For some reason the user has already removed it, ignore.
2733 # For some reason the user has already removed it, ignore.
2729 pass
2734 pass
2730
2735
2731 fname = os.path.expanduser(fname)
2736 fname = os.path.expanduser(fname)
2732
2737
2733 # Find things also in current directory. This is needed to mimic the
2738 # Find things also in current directory. This is needed to mimic the
2734 # behavior of running a script from the system command line, where
2739 # behavior of running a script from the system command line, where
2735 # Python inserts the script's directory into sys.path
2740 # Python inserts the script's directory into sys.path
2736 dname = os.path.dirname(os.path.abspath(fname))
2741 dname = os.path.dirname(os.path.abspath(fname))
2737 add_dname = False
2742 add_dname = False
2738 if dname not in sys.path:
2743 if dname not in sys.path:
2739 sys.path.insert(0,dname)
2744 sys.path.insert(0,dname)
2740 add_dname = True
2745 add_dname = True
2741
2746
2742 try:
2747 try:
2743 xfile = open(fname)
2748 xfile = open(fname)
2744 except:
2749 except:
2745 print >> Term.cerr, \
2750 print >> Term.cerr, \
2746 'Could not open file <%s> for safe execution.' % fname
2751 'Could not open file <%s> for safe execution.' % fname
2747 syspath_cleanup()
2752 syspath_cleanup()
2748 return None
2753 return None
2749
2754
2750 kw.setdefault('islog',0)
2755 kw.setdefault('islog',0)
2751 kw.setdefault('quiet',1)
2756 kw.setdefault('quiet',1)
2752 kw.setdefault('exit_ignore',0)
2757 kw.setdefault('exit_ignore',0)
2753
2758
2754 first = xfile.readline()
2759 first = xfile.readline()
2755 loghead = str(self.loghead_tpl).split('\n',1)[0].strip()
2760 loghead = str(self.loghead_tpl).split('\n',1)[0].strip()
2756 xfile.close()
2761 xfile.close()
2757 # line by line execution
2762 # line by line execution
2758 if first.startswith(loghead) or kw['islog']:
2763 if first.startswith(loghead) or kw['islog']:
2759 print 'Loading log file <%s> one line at a time...' % fname
2764 print 'Loading log file <%s> one line at a time...' % fname
2760 if kw['quiet']:
2765 if kw['quiet']:
2761 stdout_save = sys.stdout
2766 stdout_save = sys.stdout
2762 sys.stdout = StringIO.StringIO()
2767 sys.stdout = StringIO.StringIO()
2763 try:
2768 try:
2764 globs,locs = where[0:2]
2769 globs,locs = where[0:2]
2765 except:
2770 except:
2766 try:
2771 try:
2767 globs = locs = where[0]
2772 globs = locs = where[0]
2768 except:
2773 except:
2769 globs = locs = globals()
2774 globs = locs = globals()
2770 badblocks = []
2775 badblocks = []
2771
2776
2772 # we also need to identify indented blocks of code when replaying
2777 # we also need to identify indented blocks of code when replaying
2773 # logs and put them together before passing them to an exec
2778 # logs and put them together before passing them to an exec
2774 # statement. This takes a bit of regexp and look-ahead work in the
2779 # statement. This takes a bit of regexp and look-ahead work in the
2775 # file. It's easiest if we swallow the whole thing in memory
2780 # file. It's easiest if we swallow the whole thing in memory
2776 # first, and manually walk through the lines list moving the
2781 # first, and manually walk through the lines list moving the
2777 # counter ourselves.
2782 # counter ourselves.
2778 indent_re = re.compile('\s+\S')
2783 indent_re = re.compile('\s+\S')
2779 xfile = open(fname)
2784 xfile = open(fname)
2780 filelines = xfile.readlines()
2785 filelines = xfile.readlines()
2781 xfile.close()
2786 xfile.close()
2782 nlines = len(filelines)
2787 nlines = len(filelines)
2783 lnum = 0
2788 lnum = 0
2784 while lnum < nlines:
2789 while lnum < nlines:
2785 line = filelines[lnum]
2790 line = filelines[lnum]
2786 lnum += 1
2791 lnum += 1
2787 # don't re-insert logger status info into cache
2792 # don't re-insert logger status info into cache
2788 if line.startswith('#log#'):
2793 if line.startswith('#log#'):
2789 continue
2794 continue
2790 else:
2795 else:
2791 # build a block of code (maybe a single line) for execution
2796 # build a block of code (maybe a single line) for execution
2792 block = line
2797 block = line
2793 try:
2798 try:
2794 next = filelines[lnum] # lnum has already incremented
2799 next = filelines[lnum] # lnum has already incremented
2795 except:
2800 except:
2796 next = None
2801 next = None
2797 while next and indent_re.match(next):
2802 while next and indent_re.match(next):
2798 block += next
2803 block += next
2799 lnum += 1
2804 lnum += 1
2800 try:
2805 try:
2801 next = filelines[lnum]
2806 next = filelines[lnum]
2802 except:
2807 except:
2803 next = None
2808 next = None
2804 # now execute the block of one or more lines
2809 # now execute the block of one or more lines
2805 try:
2810 try:
2806 exec block in globs,locs
2811 exec block in globs,locs
2807 except SystemExit:
2812 except SystemExit:
2808 pass
2813 pass
2809 except:
2814 except:
2810 badblocks.append(block.rstrip())
2815 badblocks.append(block.rstrip())
2811 if kw['quiet']: # restore stdout
2816 if kw['quiet']: # restore stdout
2812 sys.stdout.close()
2817 sys.stdout.close()
2813 sys.stdout = stdout_save
2818 sys.stdout = stdout_save
2814 print 'Finished replaying log file <%s>' % fname
2819 print 'Finished replaying log file <%s>' % fname
2815 if badblocks:
2820 if badblocks:
2816 print >> sys.stderr, ('\nThe following lines/blocks in file '
2821 print >> sys.stderr, ('\nThe following lines/blocks in file '
2817 '<%s> reported errors:' % fname)
2822 '<%s> reported errors:' % fname)
2818
2823
2819 for badline in badblocks:
2824 for badline in badblocks:
2820 print >> sys.stderr, badline
2825 print >> sys.stderr, badline
2821 else: # regular file execution
2826 else: # regular file execution
2822 try:
2827 try:
2823 if sys.platform == 'win32' and sys.version_info < (2,5,1):
2828 if sys.platform == 'win32' and sys.version_info < (2,5,1):
2824 # Work around a bug in Python for Windows. The bug was
2829 # Work around a bug in Python for Windows. The bug was
2825 # fixed in in Python 2.5 r54159 and 54158, but that's still
2830 # fixed in in Python 2.5 r54159 and 54158, but that's still
2826 # SVN Python as of March/07. For details, see:
2831 # SVN Python as of March/07. For details, see:
2827 # http://projects.scipy.org/ipython/ipython/ticket/123
2832 # http://projects.scipy.org/ipython/ipython/ticket/123
2828 try:
2833 try:
2829 globs,locs = where[0:2]
2834 globs,locs = where[0:2]
2830 except:
2835 except:
2831 try:
2836 try:
2832 globs = locs = where[0]
2837 globs = locs = where[0]
2833 except:
2838 except:
2834 globs = locs = globals()
2839 globs = locs = globals()
2835 exec file(fname) in globs,locs
2840 exec file(fname) in globs,locs
2836 else:
2841 else:
2837 execfile(fname,*where)
2842 execfile(fname,*where)
2838 except SyntaxError:
2843 except SyntaxError:
2839 self.showsyntaxerror()
2844 self.showsyntaxerror()
2840 warn('Failure executing file: <%s>' % fname)
2845 warn('Failure executing file: <%s>' % fname)
2841 except SystemExit,status:
2846 except SystemExit,status:
2842 # Code that correctly sets the exit status flag to success (0)
2847 # Code that correctly sets the exit status flag to success (0)
2843 # shouldn't be bothered with a traceback. Note that a plain
2848 # shouldn't be bothered with a traceback. Note that a plain
2844 # sys.exit() does NOT set the message to 0 (it's empty) so that
2849 # sys.exit() does NOT set the message to 0 (it's empty) so that
2845 # will still get a traceback. Note that the structure of the
2850 # will still get a traceback. Note that the structure of the
2846 # SystemExit exception changed between Python 2.4 and 2.5, so
2851 # SystemExit exception changed between Python 2.4 and 2.5, so
2847 # the checks must be done in a version-dependent way.
2852 # the checks must be done in a version-dependent way.
2848 show = False
2853 show = False
2849
2854
2850 if sys.version_info[:2] > (2,5):
2855 if sys.version_info[:2] > (2,5):
2851 if status.message!=0 and not kw['exit_ignore']:
2856 if status.message!=0 and not kw['exit_ignore']:
2852 show = True
2857 show = True
2853 else:
2858 else:
2854 if status.code and not kw['exit_ignore']:
2859 if status.code and not kw['exit_ignore']:
2855 show = True
2860 show = True
2856 if show:
2861 if show:
2857 self.showtraceback()
2862 self.showtraceback()
2858 warn('Failure executing file: <%s>' % fname)
2863 warn('Failure executing file: <%s>' % fname)
2859 except:
2864 except:
2860 self.showtraceback()
2865 self.showtraceback()
2861 warn('Failure executing file: <%s>' % fname)
2866 warn('Failure executing file: <%s>' % fname)
2862
2867
2863 syspath_cleanup()
2868 syspath_cleanup()
2864
2869
2865 #************************* end of file <iplib.py> *****************************
2870 #************************* end of file <iplib.py> *****************************
@@ -1,773 +1,773 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 IPython -- An enhanced Interactive Python
3 IPython -- An enhanced Interactive Python
4
4
5 Requires Python 2.1 or better.
5 Requires Python 2.1 or better.
6
6
7 This file contains the main make_IPython() starter function.
7 This file contains the main make_IPython() starter function.
8 """
8 """
9
9
10 #*****************************************************************************
10 #*****************************************************************************
11 # Copyright (C) 2008-2009 The IPython Development Team
11 # Copyright (C) 2008-2009 The IPython Development Team
12 # Copyright (C) 2001-2007 Fernando Perez. <fperez@colorado.edu>
12 # Copyright (C) 2001-2007 Fernando Perez. <fperez@colorado.edu>
13 #
13 #
14 # Distributed under the terms of the BSD License. The full license is in
14 # Distributed under the terms of the BSD License. The full license is in
15 # the file COPYING, distributed as part of this software.
15 # the file COPYING, distributed as part of this software.
16 #*****************************************************************************
16 #*****************************************************************************
17
17
18 try:
18 try:
19 credits._Printer__data = """
19 credits._Printer__data = """
20 Python: %s
20 Python: %s
21
21
22 IPython: The IPython Development Team.
22 IPython: The IPython Development Team.
23 See http://ipython.scipy.org for more information.""" \
23 See http://ipython.scipy.org for more information.""" \
24 % credits._Printer__data
24 % credits._Printer__data
25
25
26 copyright._Printer__data += """
26 copyright._Printer__data += """
27
27
28 Copyright (c) 2008-2009 The IPython Development Team.
28 Copyright (c) 2008-2009 The IPython Development Team.
29 Copyright (c) 2001-2007 Fernando Perez, Janko Hauser, Nathan Gray.
29 Copyright (c) 2001-2007 Fernando Perez, Janko Hauser, Nathan Gray.
30 All Rights Reserved."""
30 All Rights Reserved."""
31 except NameError:
31 except NameError:
32 # Can happen if ipython was started with 'python -S', so that site.py is
32 # Can happen if ipython was started with 'python -S', so that site.py is
33 # not loaded
33 # not loaded
34 pass
34 pass
35
35
36 #****************************************************************************
36 #****************************************************************************
37 # Required modules
37 # Required modules
38
38
39 # From the standard library
39 # From the standard library
40 import __main__
40 import __main__
41 import __builtin__
41 import __builtin__
42 import os
42 import os
43 import re
43 import re
44 import sys
44 import sys
45 import types
45 import types
46 from pprint import pprint,pformat
46 from pprint import pprint,pformat
47
47
48 # Our own
48 # Our own
49 from IPython import DPyGetOpt
49 from IPython import DPyGetOpt
50 from IPython import Release
50 from IPython import Release
51 from IPython.ipstruct import Struct
51 from IPython.ipstruct import Struct
52 from IPython.OutputTrap import OutputTrap
52 from IPython.OutputTrap import OutputTrap
53 from IPython.ConfigLoader import ConfigLoader
53 from IPython.ConfigLoader import ConfigLoader
54 from IPython.iplib import InteractiveShell
54 from IPython.iplib import InteractiveShell
55 from IPython.usage import cmd_line_usage,interactive_usage
55 from IPython.usage import cmd_line_usage,interactive_usage
56 from IPython.genutils import *
56 from IPython.genutils import *
57
57
58 def force_import(modname):
58 def force_import(modname,force_reload=False):
59 if modname in sys.modules:
59 if modname in sys.modules and force_reload:
60 print "reload",modname
60 info("reloading: %s" % modname)
61 reload(sys.modules[modname])
61 reload(sys.modules[modname])
62 else:
62 else:
63 __import__(modname)
63 __import__(modname)
64
64
65
65
66 #-----------------------------------------------------------------------------
66 #-----------------------------------------------------------------------------
67 def make_IPython(argv=None,user_ns=None,user_global_ns=None,debug=1,
67 def make_IPython(argv=None,user_ns=None,user_global_ns=None,debug=1,
68 rc_override=None,shell_class=InteractiveShell,
68 rc_override=None,shell_class=InteractiveShell,
69 embedded=False,**kw):
69 embedded=False,**kw):
70 """This is a dump of IPython into a single function.
70 """This is a dump of IPython into a single function.
71
71
72 Later it will have to be broken up in a sensible manner.
72 Later it will have to be broken up in a sensible manner.
73
73
74 Arguments:
74 Arguments:
75
75
76 - argv: a list similar to sys.argv[1:]. It should NOT contain the desired
76 - argv: a list similar to sys.argv[1:]. It should NOT contain the desired
77 script name, b/c DPyGetOpt strips the first argument only for the real
77 script name, b/c DPyGetOpt strips the first argument only for the real
78 sys.argv.
78 sys.argv.
79
79
80 - user_ns: a dict to be used as the user's namespace."""
80 - user_ns: a dict to be used as the user's namespace."""
81
81
82 #----------------------------------------------------------------------
82 #----------------------------------------------------------------------
83 # Defaults and initialization
83 # Defaults and initialization
84
84
85 # For developer debugging, deactivates crash handler and uses pdb.
85 # For developer debugging, deactivates crash handler and uses pdb.
86 DEVDEBUG = False
86 DEVDEBUG = False
87
87
88 if argv is None:
88 if argv is None:
89 argv = sys.argv
89 argv = sys.argv
90
90
91 # __IP is the main global that lives throughout and represents the whole
91 # __IP is the main global that lives throughout and represents the whole
92 # application. If the user redefines it, all bets are off as to what
92 # application. If the user redefines it, all bets are off as to what
93 # happens.
93 # happens.
94
94
95 # __IP is the name of he global which the caller will have accessible as
95 # __IP is the name of he global which the caller will have accessible as
96 # __IP.name. We set its name via the first parameter passed to
96 # __IP.name. We set its name via the first parameter passed to
97 # InteractiveShell:
97 # InteractiveShell:
98
98
99 IP = shell_class('__IP',user_ns=user_ns,user_global_ns=user_global_ns,
99 IP = shell_class('__IP',user_ns=user_ns,user_global_ns=user_global_ns,
100 embedded=embedded,**kw)
100 embedded=embedded,**kw)
101
101
102 # Put 'help' in the user namespace
102 # Put 'help' in the user namespace
103 try:
103 try:
104 from site import _Helper
104 from site import _Helper
105 IP.user_ns['help'] = _Helper()
105 IP.user_ns['help'] = _Helper()
106 except ImportError:
106 except ImportError:
107 warn('help() not available - check site.py')
107 warn('help() not available - check site.py')
108
108
109 if DEVDEBUG:
109 if DEVDEBUG:
110 # For developer debugging only (global flag)
110 # For developer debugging only (global flag)
111 from IPython import ultraTB
111 from IPython import ultraTB
112 sys.excepthook = ultraTB.VerboseTB(call_pdb=1)
112 sys.excepthook = ultraTB.VerboseTB(call_pdb=1)
113
113
114 IP.BANNER_PARTS = ['Python %s\n'
114 IP.BANNER_PARTS = ['Python %s\n'
115 'Type "copyright", "credits" or "license" '
115 'Type "copyright", "credits" or "license" '
116 'for more information.\n'
116 'for more information.\n'
117 % (sys.version.split('\n')[0],),
117 % (sys.version.split('\n')[0],),
118 "IPython %s -- An enhanced Interactive Python."
118 "IPython %s -- An enhanced Interactive Python."
119 % (Release.version,),
119 % (Release.version,),
120 """\
120 """\
121 ? -> Introduction and overview of IPython's features.
121 ? -> Introduction and overview of IPython's features.
122 %quickref -> Quick reference.
122 %quickref -> Quick reference.
123 help -> Python's own help system.
123 help -> Python's own help system.
124 object? -> Details about 'object'. ?object also works, ?? prints more.
124 object? -> Details about 'object'. ?object also works, ?? prints more.
125 """ ]
125 """ ]
126
126
127 IP.usage = interactive_usage
127 IP.usage = interactive_usage
128
128
129 # Platform-dependent suffix.
129 # Platform-dependent suffix.
130 if os.name == 'posix':
130 if os.name == 'posix':
131 rc_suffix = ''
131 rc_suffix = ''
132 else:
132 else:
133 rc_suffix = '.ini'
133 rc_suffix = '.ini'
134
134
135 # default directory for configuration
135 # default directory for configuration
136 ipythondir_def = get_ipython_dir()
136 ipythondir_def = get_ipython_dir()
137
137
138 sys.path.insert(0, '') # add . to sys.path. Fix from Prabhu Ramachandran
138 sys.path.insert(0, '') # add . to sys.path. Fix from Prabhu Ramachandran
139
139
140 # we need the directory where IPython itself is installed
140 # we need the directory where IPython itself is installed
141 import IPython
141 import IPython
142 IPython_dir = os.path.dirname(IPython.__file__)
142 IPython_dir = os.path.dirname(IPython.__file__)
143 del IPython
143 del IPython
144
144
145 #-------------------------------------------------------------------------
145 #-------------------------------------------------------------------------
146 # Command line handling
146 # Command line handling
147
147
148 # Valid command line options (uses DPyGetOpt syntax, like Perl's
148 # Valid command line options (uses DPyGetOpt syntax, like Perl's
149 # GetOpt::Long)
149 # GetOpt::Long)
150
150
151 # Any key not listed here gets deleted even if in the file (like session
151 # Any key not listed here gets deleted even if in the file (like session
152 # or profile). That's deliberate, to maintain the rc namespace clean.
152 # or profile). That's deliberate, to maintain the rc namespace clean.
153
153
154 # Each set of options appears twice: under _conv only the names are
154 # Each set of options appears twice: under _conv only the names are
155 # listed, indicating which type they must be converted to when reading the
155 # listed, indicating which type they must be converted to when reading the
156 # ipythonrc file. And under DPyGetOpt they are listed with the regular
156 # ipythonrc file. And under DPyGetOpt they are listed with the regular
157 # DPyGetOpt syntax (=s,=i,:f,etc).
157 # DPyGetOpt syntax (=s,=i,:f,etc).
158
158
159 # Make sure there's a space before each end of line (they get auto-joined!)
159 # Make sure there's a space before each end of line (they get auto-joined!)
160 cmdline_opts = ('autocall=i autoindent! automagic! banner! cache_size|cs=i '
160 cmdline_opts = ('autocall=i autoindent! automagic! banner! cache_size|cs=i '
161 'c=s classic|cl color_info! colors=s confirm_exit! '
161 'c=s classic|cl color_info! colors=s confirm_exit! '
162 'debug! deep_reload! editor=s log|l messages! nosep '
162 'debug! deep_reload! editor=s log|l messages! nosep '
163 'object_info_string_level=i pdb! '
163 'object_info_string_level=i pdb! '
164 'pprint! prompt_in1|pi1=s prompt_in2|pi2=s prompt_out|po=s '
164 'pprint! prompt_in1|pi1=s prompt_in2|pi2=s prompt_out|po=s '
165 'pydb! '
165 'pydb! '
166 'pylab_import_all! '
166 'pylab_import_all! '
167 'quick screen_length|sl=i prompts_pad_left=i '
167 'quick screen_length|sl=i prompts_pad_left=i '
168 'logfile|lf=s logplay|lp=s profile|p=s '
168 'logfile|lf=s logplay|lp=s profile|p=s '
169 'readline! readline_merge_completions! '
169 'readline! readline_merge_completions! '
170 'readline_omit__names! '
170 'readline_omit__names! '
171 'rcfile=s separate_in|si=s separate_out|so=s '
171 'rcfile=s separate_in|si=s separate_out|so=s '
172 'separate_out2|so2=s xmode=s wildcards_case_sensitive! '
172 'separate_out2|so2=s xmode=s wildcards_case_sensitive! '
173 'magic_docstrings system_verbose! '
173 'magic_docstrings system_verbose! '
174 'multi_line_specials! '
174 'multi_line_specials! '
175 'term_title! wxversion=s '
175 'term_title! wxversion=s '
176 'autoedit_syntax!')
176 'autoedit_syntax!')
177
177
178 # Options that can *only* appear at the cmd line (not in rcfiles).
178 # Options that can *only* appear at the cmd line (not in rcfiles).
179
179
180 cmdline_only = ('help interact|i ipythondir=s Version upgrade '
180 cmdline_only = ('help interact|i ipythondir=s Version upgrade '
181 'gthread! qthread! q4thread! wthread! tkthread! pylab! tk! '
181 'gthread! qthread! q4thread! wthread! tkthread! pylab! tk! '
182 # 'twisted!' # disabled for now.
182 # 'twisted!' # disabled for now.
183 )
183 )
184
184
185 # Build the actual name list to be used by DPyGetOpt
185 # Build the actual name list to be used by DPyGetOpt
186 opts_names = qw(cmdline_opts) + qw(cmdline_only)
186 opts_names = qw(cmdline_opts) + qw(cmdline_only)
187
187
188 # Set sensible command line defaults.
188 # Set sensible command line defaults.
189 # This should have everything from cmdline_opts and cmdline_only
189 # This should have everything from cmdline_opts and cmdline_only
190 opts_def = Struct(autocall = 1,
190 opts_def = Struct(autocall = 1,
191 autoedit_syntax = 0,
191 autoedit_syntax = 0,
192 autoindent = 0,
192 autoindent = 0,
193 automagic = 1,
193 automagic = 1,
194 autoexec = [],
194 autoexec = [],
195 banner = 1,
195 banner = 1,
196 c = '',
196 c = '',
197 cache_size = 1000,
197 cache_size = 1000,
198 classic = 0,
198 classic = 0,
199 color_info = 0,
199 color_info = 0,
200 colors = 'NoColor',
200 colors = 'NoColor',
201 confirm_exit = 1,
201 confirm_exit = 1,
202 debug = 0,
202 debug = 0,
203 deep_reload = 0,
203 deep_reload = 0,
204 editor = '0',
204 editor = '0',
205 gthread = 0,
205 gthread = 0,
206 help = 0,
206 help = 0,
207 interact = 0,
207 interact = 0,
208 ipythondir = ipythondir_def,
208 ipythondir = ipythondir_def,
209 log = 0,
209 log = 0,
210 logfile = '',
210 logfile = '',
211 logplay = '',
211 logplay = '',
212 messages = 1,
212 messages = 1,
213 multi_line_specials = 1,
213 multi_line_specials = 1,
214 nosep = 0,
214 nosep = 0,
215 object_info_string_level = 0,
215 object_info_string_level = 0,
216 pdb = 0,
216 pdb = 0,
217 pprint = 0,
217 pprint = 0,
218 profile = '',
218 profile = '',
219 prompt_in1 = 'In [\\#]: ',
219 prompt_in1 = 'In [\\#]: ',
220 prompt_in2 = ' .\\D.: ',
220 prompt_in2 = ' .\\D.: ',
221 prompt_out = 'Out[\\#]: ',
221 prompt_out = 'Out[\\#]: ',
222 prompts_pad_left = 1,
222 prompts_pad_left = 1,
223 pydb = 0,
223 pydb = 0,
224 pylab = 0,
224 pylab = 0,
225 pylab_import_all = 1,
225 pylab_import_all = 1,
226 q4thread = 0,
226 q4thread = 0,
227 qthread = 0,
227 qthread = 0,
228 quick = 0,
228 quick = 0,
229 quiet = 0,
229 quiet = 0,
230 rcfile = 'ipythonrc' + rc_suffix,
230 rcfile = 'ipythonrc' + rc_suffix,
231 readline = 1,
231 readline = 1,
232 readline_merge_completions = 1,
232 readline_merge_completions = 1,
233 readline_omit__names = 0,
233 readline_omit__names = 0,
234 screen_length = 0,
234 screen_length = 0,
235 separate_in = '\n',
235 separate_in = '\n',
236 separate_out = '\n',
236 separate_out = '\n',
237 separate_out2 = '',
237 separate_out2 = '',
238 system_header = 'IPython system call: ',
238 system_header = 'IPython system call: ',
239 system_verbose = 0,
239 system_verbose = 0,
240 term_title = 1,
240 term_title = 1,
241 tk = 0,
241 tk = 0,
242 #twisted= 0, # disabled for now
242 #twisted= 0, # disabled for now
243 upgrade = 0,
243 upgrade = 0,
244 Version = 0,
244 Version = 0,
245 wildcards_case_sensitive = 1,
245 wildcards_case_sensitive = 1,
246 wthread = 0,
246 wthread = 0,
247 wxversion = '0',
247 wxversion = '0',
248 xmode = 'Context',
248 xmode = 'Context',
249 magic_docstrings = 0, # undocumented, for doc generation
249 magic_docstrings = 0, # undocumented, for doc generation
250 )
250 )
251
251
252 # Things that will *only* appear in rcfiles (not at the command line).
252 # Things that will *only* appear in rcfiles (not at the command line).
253 # Make sure there's a space before each end of line (they get auto-joined!)
253 # Make sure there's a space before each end of line (they get auto-joined!)
254 rcfile_opts = { qwflat: 'include import_mod import_all execfile ',
254 rcfile_opts = { qwflat: 'include import_mod import_all execfile ',
255 qw_lol: 'import_some ',
255 qw_lol: 'import_some ',
256 # for things with embedded whitespace:
256 # for things with embedded whitespace:
257 list_strings:'execute alias readline_parse_and_bind ',
257 list_strings:'execute alias readline_parse_and_bind ',
258 # Regular strings need no conversion:
258 # Regular strings need no conversion:
259 None:'readline_remove_delims ',
259 None:'readline_remove_delims ',
260 }
260 }
261 # Default values for these
261 # Default values for these
262 rc_def = Struct(include = [],
262 rc_def = Struct(include = [],
263 import_mod = [],
263 import_mod = [],
264 import_all = [],
264 import_all = [],
265 import_some = [[]],
265 import_some = [[]],
266 execute = [],
266 execute = [],
267 execfile = [],
267 execfile = [],
268 alias = [],
268 alias = [],
269 readline_parse_and_bind = [],
269 readline_parse_and_bind = [],
270 readline_remove_delims = '',
270 readline_remove_delims = '',
271 )
271 )
272
272
273 # Build the type conversion dictionary from the above tables:
273 # Build the type conversion dictionary from the above tables:
274 typeconv = rcfile_opts.copy()
274 typeconv = rcfile_opts.copy()
275 typeconv.update(optstr2types(cmdline_opts))
275 typeconv.update(optstr2types(cmdline_opts))
276
276
277 # FIXME: the None key appears in both, put that back together by hand. Ugly!
277 # FIXME: the None key appears in both, put that back together by hand. Ugly!
278 typeconv[None] += ' ' + rcfile_opts[None]
278 typeconv[None] += ' ' + rcfile_opts[None]
279
279
280 # Remove quotes at ends of all strings (used to protect spaces)
280 # Remove quotes at ends of all strings (used to protect spaces)
281 typeconv[unquote_ends] = typeconv[None]
281 typeconv[unquote_ends] = typeconv[None]
282 del typeconv[None]
282 del typeconv[None]
283
283
284 # Build the list we'll use to make all config decisions with defaults:
284 # Build the list we'll use to make all config decisions with defaults:
285 opts_all = opts_def.copy()
285 opts_all = opts_def.copy()
286 opts_all.update(rc_def)
286 opts_all.update(rc_def)
287
287
288 # Build conflict resolver for recursive loading of config files:
288 # Build conflict resolver for recursive loading of config files:
289 # - preserve means the outermost file maintains the value, it is not
289 # - preserve means the outermost file maintains the value, it is not
290 # overwritten if an included file has the same key.
290 # overwritten if an included file has the same key.
291 # - add_flip applies + to the two values, so it better make sense to add
291 # - add_flip applies + to the two values, so it better make sense to add
292 # those types of keys. But it flips them first so that things loaded
292 # those types of keys. But it flips them first so that things loaded
293 # deeper in the inclusion chain have lower precedence.
293 # deeper in the inclusion chain have lower precedence.
294 conflict = {'preserve': ' '.join([ typeconv[int],
294 conflict = {'preserve': ' '.join([ typeconv[int],
295 typeconv[unquote_ends] ]),
295 typeconv[unquote_ends] ]),
296 'add_flip': ' '.join([ typeconv[qwflat],
296 'add_flip': ' '.join([ typeconv[qwflat],
297 typeconv[qw_lol],
297 typeconv[qw_lol],
298 typeconv[list_strings] ])
298 typeconv[list_strings] ])
299 }
299 }
300
300
301 # Now actually process the command line
301 # Now actually process the command line
302 getopt = DPyGetOpt.DPyGetOpt()
302 getopt = DPyGetOpt.DPyGetOpt()
303 getopt.setIgnoreCase(0)
303 getopt.setIgnoreCase(0)
304
304
305 getopt.parseConfiguration(opts_names)
305 getopt.parseConfiguration(opts_names)
306
306
307 try:
307 try:
308 getopt.processArguments(argv)
308 getopt.processArguments(argv)
309 except DPyGetOpt.ArgumentError, exc:
309 except DPyGetOpt.ArgumentError, exc:
310 print cmd_line_usage
310 print cmd_line_usage
311 warn('\nError in Arguments: "%s"' % exc)
311 warn('\nError in Arguments: "%s"' % exc)
312 sys.exit(1)
312 sys.exit(1)
313
313
314 # convert the options dict to a struct for much lighter syntax later
314 # convert the options dict to a struct for much lighter syntax later
315 opts = Struct(getopt.optionValues)
315 opts = Struct(getopt.optionValues)
316 args = getopt.freeValues
316 args = getopt.freeValues
317
317
318 # this is the struct (which has default values at this point) with which
318 # this is the struct (which has default values at this point) with which
319 # we make all decisions:
319 # we make all decisions:
320 opts_all.update(opts)
320 opts_all.update(opts)
321
321
322 # Options that force an immediate exit
322 # Options that force an immediate exit
323 if opts_all.help:
323 if opts_all.help:
324 page(cmd_line_usage)
324 page(cmd_line_usage)
325 sys.exit()
325 sys.exit()
326
326
327 if opts_all.Version:
327 if opts_all.Version:
328 print Release.version
328 print Release.version
329 sys.exit()
329 sys.exit()
330
330
331 if opts_all.magic_docstrings:
331 if opts_all.magic_docstrings:
332 IP.magic_magic('-latex')
332 IP.magic_magic('-latex')
333 sys.exit()
333 sys.exit()
334
334
335 # add personal ipythondir to sys.path so that users can put things in
335 # add personal ipythondir to sys.path so that users can put things in
336 # there for customization
336 # there for customization
337 sys.path.append(os.path.abspath(opts_all.ipythondir))
337 sys.path.append(os.path.abspath(opts_all.ipythondir))
338
338
339 # Create user config directory if it doesn't exist. This must be done
339 # Create user config directory if it doesn't exist. This must be done
340 # *after* getting the cmd line options.
340 # *after* getting the cmd line options.
341 if not os.path.isdir(opts_all.ipythondir):
341 if not os.path.isdir(opts_all.ipythondir):
342 IP.user_setup(opts_all.ipythondir,rc_suffix,'install')
342 IP.user_setup(opts_all.ipythondir,rc_suffix,'install')
343
343
344 # upgrade user config files while preserving a copy of the originals
344 # upgrade user config files while preserving a copy of the originals
345 if opts_all.upgrade:
345 if opts_all.upgrade:
346 IP.user_setup(opts_all.ipythondir,rc_suffix,'upgrade')
346 IP.user_setup(opts_all.ipythondir,rc_suffix,'upgrade')
347
347
348 # check mutually exclusive options in the *original* command line
348 # check mutually exclusive options in the *original* command line
349 mutex_opts(opts,[qw('log logfile'),qw('rcfile profile'),
349 mutex_opts(opts,[qw('log logfile'),qw('rcfile profile'),
350 qw('classic profile'),qw('classic rcfile')])
350 qw('classic profile'),qw('classic rcfile')])
351
351
352 #---------------------------------------------------------------------------
352 #---------------------------------------------------------------------------
353 # Log replay
353 # Log replay
354
354
355 # if -logplay, we need to 'become' the other session. That basically means
355 # if -logplay, we need to 'become' the other session. That basically means
356 # replacing the current command line environment with that of the old
356 # replacing the current command line environment with that of the old
357 # session and moving on.
357 # session and moving on.
358
358
359 # this is needed so that later we know we're in session reload mode, as
359 # this is needed so that later we know we're in session reload mode, as
360 # opts_all will get overwritten:
360 # opts_all will get overwritten:
361 load_logplay = 0
361 load_logplay = 0
362
362
363 if opts_all.logplay:
363 if opts_all.logplay:
364 load_logplay = opts_all.logplay
364 load_logplay = opts_all.logplay
365 opts_debug_save = opts_all.debug
365 opts_debug_save = opts_all.debug
366 try:
366 try:
367 logplay = open(opts_all.logplay)
367 logplay = open(opts_all.logplay)
368 except IOError:
368 except IOError:
369 if opts_all.debug: IP.InteractiveTB()
369 if opts_all.debug: IP.InteractiveTB()
370 warn('Could not open logplay file '+`opts_all.logplay`)
370 warn('Could not open logplay file '+`opts_all.logplay`)
371 # restore state as if nothing had happened and move on, but make
371 # restore state as if nothing had happened and move on, but make
372 # sure that later we don't try to actually load the session file
372 # sure that later we don't try to actually load the session file
373 logplay = None
373 logplay = None
374 load_logplay = 0
374 load_logplay = 0
375 del opts_all.logplay
375 del opts_all.logplay
376 else:
376 else:
377 try:
377 try:
378 logplay.readline()
378 logplay.readline()
379 logplay.readline();
379 logplay.readline();
380 # this reloads that session's command line
380 # this reloads that session's command line
381 cmd = logplay.readline()[6:]
381 cmd = logplay.readline()[6:]
382 exec cmd
382 exec cmd
383 # restore the true debug flag given so that the process of
383 # restore the true debug flag given so that the process of
384 # session loading itself can be monitored.
384 # session loading itself can be monitored.
385 opts.debug = opts_debug_save
385 opts.debug = opts_debug_save
386 # save the logplay flag so later we don't overwrite the log
386 # save the logplay flag so later we don't overwrite the log
387 opts.logplay = load_logplay
387 opts.logplay = load_logplay
388 # now we must update our own structure with defaults
388 # now we must update our own structure with defaults
389 opts_all.update(opts)
389 opts_all.update(opts)
390 # now load args
390 # now load args
391 cmd = logplay.readline()[6:]
391 cmd = logplay.readline()[6:]
392 exec cmd
392 exec cmd
393 logplay.close()
393 logplay.close()
394 except:
394 except:
395 logplay.close()
395 logplay.close()
396 if opts_all.debug: IP.InteractiveTB()
396 if opts_all.debug: IP.InteractiveTB()
397 warn("Logplay file lacking full configuration information.\n"
397 warn("Logplay file lacking full configuration information.\n"
398 "I'll try to read it, but some things may not work.")
398 "I'll try to read it, but some things may not work.")
399
399
400 #-------------------------------------------------------------------------
400 #-------------------------------------------------------------------------
401 # set up output traps: catch all output from files, being run, modules
401 # set up output traps: catch all output from files, being run, modules
402 # loaded, etc. Then give it to the user in a clean form at the end.
402 # loaded, etc. Then give it to the user in a clean form at the end.
403
403
404 msg_out = 'Output messages. '
404 msg_out = 'Output messages. '
405 msg_err = 'Error messages. '
405 msg_err = 'Error messages. '
406 msg_sep = '\n'
406 msg_sep = '\n'
407 msg = Struct(config = OutputTrap('Configuration Loader',msg_out,
407 msg = Struct(config = OutputTrap('Configuration Loader',msg_out,
408 msg_err,msg_sep,debug,
408 msg_err,msg_sep,debug,
409 quiet_out=1),
409 quiet_out=1),
410 user_exec = OutputTrap('User File Execution',msg_out,
410 user_exec = OutputTrap('User File Execution',msg_out,
411 msg_err,msg_sep,debug),
411 msg_err,msg_sep,debug),
412 logplay = OutputTrap('Log Loader',msg_out,
412 logplay = OutputTrap('Log Loader',msg_out,
413 msg_err,msg_sep,debug),
413 msg_err,msg_sep,debug),
414 summary = ''
414 summary = ''
415 )
415 )
416
416
417 #-------------------------------------------------------------------------
417 #-------------------------------------------------------------------------
418 # Process user ipythonrc-type configuration files
418 # Process user ipythonrc-type configuration files
419
419
420 # turn on output trapping and log to msg.config
420 # turn on output trapping and log to msg.config
421 # remember that with debug on, trapping is actually disabled
421 # remember that with debug on, trapping is actually disabled
422 msg.config.trap_all()
422 msg.config.trap_all()
423
423
424 # look for rcfile in current or default directory
424 # look for rcfile in current or default directory
425 try:
425 try:
426 opts_all.rcfile = filefind(opts_all.rcfile,opts_all.ipythondir)
426 opts_all.rcfile = filefind(opts_all.rcfile,opts_all.ipythondir)
427 except IOError:
427 except IOError:
428 if opts_all.debug: IP.InteractiveTB()
428 if opts_all.debug: IP.InteractiveTB()
429 warn('Configuration file %s not found. Ignoring request.'
429 warn('Configuration file %s not found. Ignoring request.'
430 % (opts_all.rcfile) )
430 % (opts_all.rcfile) )
431
431
432 # 'profiles' are a shorthand notation for config filenames
432 # 'profiles' are a shorthand notation for config filenames
433 profile_handled_by_legacy = False
433 profile_handled_by_legacy = False
434 if opts_all.profile:
434 if opts_all.profile:
435
435
436 try:
436 try:
437 opts_all.rcfile = filefind('ipythonrc-' + opts_all.profile
437 opts_all.rcfile = filefind('ipythonrc-' + opts_all.profile
438 + rc_suffix,
438 + rc_suffix,
439 opts_all.ipythondir)
439 opts_all.ipythondir)
440 profile_handled_by_legacy = True
440 profile_handled_by_legacy = True
441 except IOError:
441 except IOError:
442 if opts_all.debug: IP.InteractiveTB()
442 if opts_all.debug: IP.InteractiveTB()
443 opts.profile = '' # remove profile from options if invalid
443 opts.profile = '' # remove profile from options if invalid
444 # We won't warn anymore, primary method is ipy_profile_PROFNAME
444 # We won't warn anymore, primary method is ipy_profile_PROFNAME
445 # which does trigger a warning.
445 # which does trigger a warning.
446
446
447 # load the config file
447 # load the config file
448 rcfiledata = None
448 rcfiledata = None
449 if opts_all.quick:
449 if opts_all.quick:
450 print 'Launching IPython in quick mode. No config file read.'
450 print 'Launching IPython in quick mode. No config file read.'
451 elif opts_all.rcfile:
451 elif opts_all.rcfile:
452 try:
452 try:
453 cfg_loader = ConfigLoader(conflict)
453 cfg_loader = ConfigLoader(conflict)
454 rcfiledata = cfg_loader.load(opts_all.rcfile,typeconv,
454 rcfiledata = cfg_loader.load(opts_all.rcfile,typeconv,
455 'include',opts_all.ipythondir,
455 'include',opts_all.ipythondir,
456 purge = 1,
456 purge = 1,
457 unique = conflict['preserve'])
457 unique = conflict['preserve'])
458 except:
458 except:
459 IP.InteractiveTB()
459 IP.InteractiveTB()
460 warn('Problems loading configuration file '+
460 warn('Problems loading configuration file '+
461 `opts_all.rcfile`+
461 `opts_all.rcfile`+
462 '\nStarting with default -bare bones- configuration.')
462 '\nStarting with default -bare bones- configuration.')
463 else:
463 else:
464 warn('No valid configuration file found in either currrent directory\n'+
464 warn('No valid configuration file found in either currrent directory\n'+
465 'or in the IPython config. directory: '+`opts_all.ipythondir`+
465 'or in the IPython config. directory: '+`opts_all.ipythondir`+
466 '\nProceeding with internal defaults.')
466 '\nProceeding with internal defaults.')
467
467
468 #------------------------------------------------------------------------
468 #------------------------------------------------------------------------
469 # Set exception handlers in mode requested by user.
469 # Set exception handlers in mode requested by user.
470 otrap = OutputTrap(trap_out=1) # trap messages from magic_xmode
470 otrap = OutputTrap(trap_out=1) # trap messages from magic_xmode
471 IP.magic_xmode(opts_all.xmode)
471 IP.magic_xmode(opts_all.xmode)
472 otrap.release_out()
472 otrap.release_out()
473
473
474 #------------------------------------------------------------------------
474 #------------------------------------------------------------------------
475 # Execute user config
475 # Execute user config
476
476
477 # Create a valid config structure with the right precedence order:
477 # Create a valid config structure with the right precedence order:
478 # defaults < rcfile < command line. This needs to be in the instance, so
478 # defaults < rcfile < command line. This needs to be in the instance, so
479 # that method calls below that rely on it find it.
479 # that method calls below that rely on it find it.
480 IP.rc = rc_def.copy()
480 IP.rc = rc_def.copy()
481
481
482 # Work with a local alias inside this routine to avoid unnecessary
482 # Work with a local alias inside this routine to avoid unnecessary
483 # attribute lookups.
483 # attribute lookups.
484 IP_rc = IP.rc
484 IP_rc = IP.rc
485
485
486 IP_rc.update(opts_def)
486 IP_rc.update(opts_def)
487 if rcfiledata:
487 if rcfiledata:
488 # now we can update
488 # now we can update
489 IP_rc.update(rcfiledata)
489 IP_rc.update(rcfiledata)
490 IP_rc.update(opts)
490 IP_rc.update(opts)
491 IP_rc.update(rc_override)
491 IP_rc.update(rc_override)
492
492
493 # Store the original cmd line for reference:
493 # Store the original cmd line for reference:
494 IP_rc.opts = opts
494 IP_rc.opts = opts
495 IP_rc.args = args
495 IP_rc.args = args
496
496
497 # create a *runtime* Struct like rc for holding parameters which may be
497 # create a *runtime* Struct like rc for holding parameters which may be
498 # created and/or modified by runtime user extensions.
498 # created and/or modified by runtime user extensions.
499 IP.runtime_rc = Struct()
499 IP.runtime_rc = Struct()
500
500
501 # from this point on, all config should be handled through IP_rc,
501 # from this point on, all config should be handled through IP_rc,
502 # opts* shouldn't be used anymore.
502 # opts* shouldn't be used anymore.
503
503
504
504
505 # update IP_rc with some special things that need manual
505 # update IP_rc with some special things that need manual
506 # tweaks. Basically options which affect other options. I guess this
506 # tweaks. Basically options which affect other options. I guess this
507 # should just be written so that options are fully orthogonal and we
507 # should just be written so that options are fully orthogonal and we
508 # wouldn't worry about this stuff!
508 # wouldn't worry about this stuff!
509
509
510 if IP_rc.classic:
510 if IP_rc.classic:
511 IP_rc.quick = 1
511 IP_rc.quick = 1
512 IP_rc.cache_size = 0
512 IP_rc.cache_size = 0
513 IP_rc.pprint = 0
513 IP_rc.pprint = 0
514 IP_rc.prompt_in1 = '>>> '
514 IP_rc.prompt_in1 = '>>> '
515 IP_rc.prompt_in2 = '... '
515 IP_rc.prompt_in2 = '... '
516 IP_rc.prompt_out = ''
516 IP_rc.prompt_out = ''
517 IP_rc.separate_in = IP_rc.separate_out = IP_rc.separate_out2 = '0'
517 IP_rc.separate_in = IP_rc.separate_out = IP_rc.separate_out2 = '0'
518 IP_rc.colors = 'NoColor'
518 IP_rc.colors = 'NoColor'
519 IP_rc.xmode = 'Plain'
519 IP_rc.xmode = 'Plain'
520
520
521 IP.pre_config_initialization()
521 IP.pre_config_initialization()
522 # configure readline
522 # configure readline
523
523
524 # update exception handlers with rc file status
524 # update exception handlers with rc file status
525 otrap.trap_out() # I don't want these messages ever.
525 otrap.trap_out() # I don't want these messages ever.
526 IP.magic_xmode(IP_rc.xmode)
526 IP.magic_xmode(IP_rc.xmode)
527 otrap.release_out()
527 otrap.release_out()
528
528
529 # activate logging if requested and not reloading a log
529 # activate logging if requested and not reloading a log
530 if IP_rc.logplay:
530 if IP_rc.logplay:
531 IP.magic_logstart(IP_rc.logplay + ' append')
531 IP.magic_logstart(IP_rc.logplay + ' append')
532 elif IP_rc.logfile:
532 elif IP_rc.logfile:
533 IP.magic_logstart(IP_rc.logfile)
533 IP.magic_logstart(IP_rc.logfile)
534 elif IP_rc.log:
534 elif IP_rc.log:
535 IP.magic_logstart()
535 IP.magic_logstart()
536
536
537 # find user editor so that it we don't have to look it up constantly
537 # find user editor so that it we don't have to look it up constantly
538 if IP_rc.editor.strip()=='0':
538 if IP_rc.editor.strip()=='0':
539 try:
539 try:
540 ed = os.environ['EDITOR']
540 ed = os.environ['EDITOR']
541 except KeyError:
541 except KeyError:
542 if os.name == 'posix':
542 if os.name == 'posix':
543 ed = 'vi' # the only one guaranteed to be there!
543 ed = 'vi' # the only one guaranteed to be there!
544 else:
544 else:
545 ed = 'notepad' # same in Windows!
545 ed = 'notepad' # same in Windows!
546 IP_rc.editor = ed
546 IP_rc.editor = ed
547
547
548 # Keep track of whether this is an embedded instance or not (useful for
548 # Keep track of whether this is an embedded instance or not (useful for
549 # post-mortems).
549 # post-mortems).
550 IP_rc.embedded = IP.embedded
550 IP_rc.embedded = IP.embedded
551
551
552 # Recursive reload
552 # Recursive reload
553 try:
553 try:
554 from IPython import deep_reload
554 from IPython import deep_reload
555 if IP_rc.deep_reload:
555 if IP_rc.deep_reload:
556 __builtin__.reload = deep_reload.reload
556 __builtin__.reload = deep_reload.reload
557 else:
557 else:
558 __builtin__.dreload = deep_reload.reload
558 __builtin__.dreload = deep_reload.reload
559 del deep_reload
559 del deep_reload
560 except ImportError:
560 except ImportError:
561 pass
561 pass
562
562
563 # Save the current state of our namespace so that the interactive shell
563 # Save the current state of our namespace so that the interactive shell
564 # can later know which variables have been created by us from config files
564 # can later know which variables have been created by us from config files
565 # and loading. This way, loading a file (in any way) is treated just like
565 # and loading. This way, loading a file (in any way) is treated just like
566 # defining things on the command line, and %who works as expected.
566 # defining things on the command line, and %who works as expected.
567
567
568 # DON'T do anything that affects the namespace beyond this point!
568 # DON'T do anything that affects the namespace beyond this point!
569 IP.internal_ns.update(__main__.__dict__)
569 IP.internal_ns.update(__main__.__dict__)
570
570
571 #IP.internal_ns.update(locals()) # so our stuff doesn't show up in %who
571 #IP.internal_ns.update(locals()) # so our stuff doesn't show up in %who
572
572
573 # Now run through the different sections of the users's config
573 # Now run through the different sections of the users's config
574 if IP_rc.debug:
574 if IP_rc.debug:
575 print 'Trying to execute the following configuration structure:'
575 print 'Trying to execute the following configuration structure:'
576 print '(Things listed first are deeper in the inclusion tree and get'
576 print '(Things listed first are deeper in the inclusion tree and get'
577 print 'loaded first).\n'
577 print 'loaded first).\n'
578 pprint(IP_rc.__dict__)
578 pprint(IP_rc.__dict__)
579
579
580 for mod in IP_rc.import_mod:
580 for mod in IP_rc.import_mod:
581 try:
581 try:
582 exec 'import '+mod in IP.user_ns
582 exec 'import '+mod in IP.user_ns
583 except :
583 except :
584 IP.InteractiveTB()
584 IP.InteractiveTB()
585 import_fail_info(mod)
585 import_fail_info(mod)
586
586
587 for mod_fn in IP_rc.import_some:
587 for mod_fn in IP_rc.import_some:
588 if not mod_fn == []:
588 if not mod_fn == []:
589 mod,fn = mod_fn[0],','.join(mod_fn[1:])
589 mod,fn = mod_fn[0],','.join(mod_fn[1:])
590 try:
590 try:
591 exec 'from '+mod+' import '+fn in IP.user_ns
591 exec 'from '+mod+' import '+fn in IP.user_ns
592 except :
592 except :
593 IP.InteractiveTB()
593 IP.InteractiveTB()
594 import_fail_info(mod,fn)
594 import_fail_info(mod,fn)
595
595
596 for mod in IP_rc.import_all:
596 for mod in IP_rc.import_all:
597 try:
597 try:
598 exec 'from '+mod+' import *' in IP.user_ns
598 exec 'from '+mod+' import *' in IP.user_ns
599 except :
599 except :
600 IP.InteractiveTB()
600 IP.InteractiveTB()
601 import_fail_info(mod)
601 import_fail_info(mod)
602
602
603 for code in IP_rc.execute:
603 for code in IP_rc.execute:
604 try:
604 try:
605 exec code in IP.user_ns
605 exec code in IP.user_ns
606 except:
606 except:
607 IP.InteractiveTB()
607 IP.InteractiveTB()
608 warn('Failure executing code: ' + `code`)
608 warn('Failure executing code: ' + `code`)
609
609
610 # Execute the files the user wants in ipythonrc
610 # Execute the files the user wants in ipythonrc
611 for file in IP_rc.execfile:
611 for file in IP_rc.execfile:
612 try:
612 try:
613 file = filefind(file,sys.path+[IPython_dir])
613 file = filefind(file,sys.path+[IPython_dir])
614 except IOError:
614 except IOError:
615 warn(itpl('File $file not found. Skipping it.'))
615 warn(itpl('File $file not found. Skipping it.'))
616 else:
616 else:
617 IP.safe_execfile(os.path.expanduser(file),IP.user_ns)
617 IP.safe_execfile(os.path.expanduser(file),IP.user_ns)
618
618
619 # finally, try importing ipy_*_conf for final configuration
619 # finally, try importing ipy_*_conf for final configuration
620 try:
620 try:
621 import ipy_system_conf
621 import ipy_system_conf
622 except ImportError:
622 except ImportError:
623 if opts_all.debug: IP.InteractiveTB()
623 if opts_all.debug: IP.InteractiveTB()
624 warn("Could not import 'ipy_system_conf'")
624 warn("Could not import 'ipy_system_conf'")
625 except:
625 except:
626 IP.InteractiveTB()
626 IP.InteractiveTB()
627 import_fail_info('ipy_system_conf')
627 import_fail_info('ipy_system_conf')
628
628
629 # only import prof module if ipythonrc-PROF was not found
629 # only import prof module if ipythonrc-PROF was not found
630 if opts_all.profile and not profile_handled_by_legacy:
630 if opts_all.profile and not profile_handled_by_legacy:
631 profmodname = 'ipy_profile_' + opts_all.profile
631 profmodname = 'ipy_profile_' + opts_all.profile
632 try:
632 try:
633
634 force_import(profmodname)
633 force_import(profmodname)
635 except:
634 except:
636 IP.InteractiveTB()
635 IP.InteractiveTB()
637 print "Error importing",profmodname,"- perhaps you should run %upgrade?"
636 print "Error importing",profmodname,\
637 "- perhaps you should run %upgrade?"
638 import_fail_info(profmodname)
638 import_fail_info(profmodname)
639 else:
639 else:
640 opts.profile = opts_all.profile
640 opts.profile = opts_all.profile
641 else:
641 else:
642 force_import('ipy_profile_none')
642 force_import('ipy_profile_none')
643 # XXX - this is wrong: ipy_user_conf should not be loaded unconditionally,
644 # since the user could have specified a config file path by hand.
643 try:
645 try:
644
645 force_import('ipy_user_conf')
646 force_import('ipy_user_conf')
646
647 except:
647 except:
648 conf = opts_all.ipythondir + "/ipy_user_conf.py"
648 conf = opts_all.ipythondir + "/ipy_user_conf.py"
649 IP.InteractiveTB()
649 IP.InteractiveTB()
650 if not os.path.isfile(conf):
650 if not os.path.isfile(conf):
651 warn(conf + ' does not exist, please run %upgrade!')
651 warn(conf + ' does not exist, please run %upgrade!')
652
652
653 import_fail_info("ipy_user_conf")
653 import_fail_info("ipy_user_conf")
654
654
655 # Define the history file for saving commands in between sessions
655 # Define the history file for saving commands in between sessions
656 try:
656 try:
657 histfname = 'history-%s' % opts.profile
657 histfname = 'history-%s' % opts.profile
658 except AttributeError:
658 except AttributeError:
659 histfname = 'history'
659 histfname = 'history'
660 IP.histfile = os.path.join(opts_all.ipythondir,histfname)
660 IP.histfile = os.path.join(opts_all.ipythondir,histfname)
661
661
662 # finally, push the argv to options again to ensure highest priority
662 # finally, push the argv to options again to ensure highest priority
663 IP_rc.update(opts)
663 IP_rc.update(opts)
664
664
665 # release stdout and stderr and save config log into a global summary
665 # release stdout and stderr and save config log into a global summary
666 msg.config.release_all()
666 msg.config.release_all()
667 if IP_rc.messages:
667 if IP_rc.messages:
668 msg.summary += msg.config.summary_all()
668 msg.summary += msg.config.summary_all()
669
669
670 #------------------------------------------------------------------------
670 #------------------------------------------------------------------------
671 # Setup interactive session
671 # Setup interactive session
672
672
673 # Now we should be fully configured. We can then execute files or load
673 # Now we should be fully configured. We can then execute files or load
674 # things only needed for interactive use. Then we'll open the shell.
674 # things only needed for interactive use. Then we'll open the shell.
675
675
676 # Take a snapshot of the user namespace before opening the shell. That way
676 # Take a snapshot of the user namespace before opening the shell. That way
677 # we'll be able to identify which things were interactively defined and
677 # we'll be able to identify which things were interactively defined and
678 # which were defined through config files.
678 # which were defined through config files.
679 IP.user_config_ns.update(IP.user_ns)
679 IP.user_config_ns.update(IP.user_ns)
680
680
681 # Force reading a file as if it were a session log. Slower but safer.
681 # Force reading a file as if it were a session log. Slower but safer.
682 if load_logplay:
682 if load_logplay:
683 print 'Replaying log...'
683 print 'Replaying log...'
684 try:
684 try:
685 if IP_rc.debug:
685 if IP_rc.debug:
686 logplay_quiet = 0
686 logplay_quiet = 0
687 else:
687 else:
688 logplay_quiet = 1
688 logplay_quiet = 1
689
689
690 msg.logplay.trap_all()
690 msg.logplay.trap_all()
691 IP.safe_execfile(load_logplay,IP.user_ns,
691 IP.safe_execfile(load_logplay,IP.user_ns,
692 islog = 1, quiet = logplay_quiet)
692 islog = 1, quiet = logplay_quiet)
693 msg.logplay.release_all()
693 msg.logplay.release_all()
694 if IP_rc.messages:
694 if IP_rc.messages:
695 msg.summary += msg.logplay.summary_all()
695 msg.summary += msg.logplay.summary_all()
696 except:
696 except:
697 warn('Problems replaying logfile %s.' % load_logplay)
697 warn('Problems replaying logfile %s.' % load_logplay)
698 IP.InteractiveTB()
698 IP.InteractiveTB()
699
699
700 # Load remaining files in command line
700 # Load remaining files in command line
701 msg.user_exec.trap_all()
701 msg.user_exec.trap_all()
702
702
703 # Do NOT execute files named in the command line as scripts to be loaded
703 # Do NOT execute files named in the command line as scripts to be loaded
704 # by embedded instances. Doing so has the potential for an infinite
704 # by embedded instances. Doing so has the potential for an infinite
705 # recursion if there are exceptions thrown in the process.
705 # recursion if there are exceptions thrown in the process.
706
706
707 # XXX FIXME: the execution of user files should be moved out to after
707 # XXX FIXME: the execution of user files should be moved out to after
708 # ipython is fully initialized, just as if they were run via %run at the
708 # ipython is fully initialized, just as if they were run via %run at the
709 # ipython prompt. This would also give them the benefit of ipython's
709 # ipython prompt. This would also give them the benefit of ipython's
710 # nice tracebacks.
710 # nice tracebacks.
711
711
712 if (not embedded and IP_rc.args and
712 if (not embedded and IP_rc.args and
713 not IP_rc.args[0].lower().endswith('.ipy')):
713 not IP_rc.args[0].lower().endswith('.ipy')):
714 name_save = IP.user_ns['__name__']
714 name_save = IP.user_ns['__name__']
715 IP.user_ns['__name__'] = '__main__'
715 IP.user_ns['__name__'] = '__main__'
716 # Set our own excepthook in case the user code tries to call it
716 # Set our own excepthook in case the user code tries to call it
717 # directly. This prevents triggering the IPython crash handler.
717 # directly. This prevents triggering the IPython crash handler.
718 old_excepthook,sys.excepthook = sys.excepthook, IP.excepthook
718 old_excepthook,sys.excepthook = sys.excepthook, IP.excepthook
719
719
720 save_argv = sys.argv[1:] # save it for later restoring
720 save_argv = sys.argv[1:] # save it for later restoring
721
721
722 sys.argv = args
722 sys.argv = args
723
723
724 try:
724 try:
725 IP.safe_execfile(args[0], IP.user_ns)
725 IP.safe_execfile(args[0], IP.user_ns)
726 finally:
726 finally:
727 # Reset our crash handler in place
727 # Reset our crash handler in place
728 sys.excepthook = old_excepthook
728 sys.excepthook = old_excepthook
729 sys.argv[:] = save_argv
729 sys.argv[:] = save_argv
730 IP.user_ns['__name__'] = name_save
730 IP.user_ns['__name__'] = name_save
731
731
732 msg.user_exec.release_all()
732 msg.user_exec.release_all()
733
733
734 if IP_rc.messages:
734 if IP_rc.messages:
735 msg.summary += msg.user_exec.summary_all()
735 msg.summary += msg.user_exec.summary_all()
736
736
737 # since we can't specify a null string on the cmd line, 0 is the equivalent:
737 # since we can't specify a null string on the cmd line, 0 is the equivalent:
738 if IP_rc.nosep:
738 if IP_rc.nosep:
739 IP_rc.separate_in = IP_rc.separate_out = IP_rc.separate_out2 = '0'
739 IP_rc.separate_in = IP_rc.separate_out = IP_rc.separate_out2 = '0'
740 if IP_rc.separate_in == '0': IP_rc.separate_in = ''
740 if IP_rc.separate_in == '0': IP_rc.separate_in = ''
741 if IP_rc.separate_out == '0': IP_rc.separate_out = ''
741 if IP_rc.separate_out == '0': IP_rc.separate_out = ''
742 if IP_rc.separate_out2 == '0': IP_rc.separate_out2 = ''
742 if IP_rc.separate_out2 == '0': IP_rc.separate_out2 = ''
743 IP_rc.separate_in = IP_rc.separate_in.replace('\\n','\n')
743 IP_rc.separate_in = IP_rc.separate_in.replace('\\n','\n')
744 IP_rc.separate_out = IP_rc.separate_out.replace('\\n','\n')
744 IP_rc.separate_out = IP_rc.separate_out.replace('\\n','\n')
745 IP_rc.separate_out2 = IP_rc.separate_out2.replace('\\n','\n')
745 IP_rc.separate_out2 = IP_rc.separate_out2.replace('\\n','\n')
746
746
747 # Determine how many lines at the bottom of the screen are needed for
747 # Determine how many lines at the bottom of the screen are needed for
748 # showing prompts, so we can know wheter long strings are to be printed or
748 # showing prompts, so we can know wheter long strings are to be printed or
749 # paged:
749 # paged:
750 num_lines_bot = IP_rc.separate_in.count('\n')+1
750 num_lines_bot = IP_rc.separate_in.count('\n')+1
751 IP_rc.screen_length = IP_rc.screen_length - num_lines_bot
751 IP_rc.screen_length = IP_rc.screen_length - num_lines_bot
752
752
753 # configure startup banner
753 # configure startup banner
754 if IP_rc.c: # regular python doesn't print the banner with -c
754 if IP_rc.c: # regular python doesn't print the banner with -c
755 IP_rc.banner = 0
755 IP_rc.banner = 0
756 if IP_rc.banner:
756 if IP_rc.banner:
757 BANN_P = IP.BANNER_PARTS
757 BANN_P = IP.BANNER_PARTS
758 else:
758 else:
759 BANN_P = []
759 BANN_P = []
760
760
761 if IP_rc.profile: BANN_P.append('IPython profile: %s\n' % IP_rc.profile)
761 if IP_rc.profile: BANN_P.append('IPython profile: %s\n' % IP_rc.profile)
762
762
763 # add message log (possibly empty)
763 # add message log (possibly empty)
764 if msg.summary: BANN_P.append(msg.summary)
764 if msg.summary: BANN_P.append(msg.summary)
765 # Final banner is a string
765 # Final banner is a string
766 IP.BANNER = '\n'.join(BANN_P)
766 IP.BANNER = '\n'.join(BANN_P)
767
767
768 # Finalize the IPython instance. This assumes the rc structure is fully
768 # Finalize the IPython instance. This assumes the rc structure is fully
769 # in place.
769 # in place.
770 IP.post_config_initialization()
770 IP.post_config_initialization()
771
771
772 return IP
772 return IP
773 #************************ end of file <ipmaker.py> **************************
773 #************************ end of file <ipmaker.py> **************************
@@ -1,24 +1,25 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """The IPython1 kernel.
2 """The IPython1 kernel.
3
3
4 The IPython kernel actually refers to three things:
4 The IPython kernel actually refers to three things:
5
5
6 * The IPython Engine
6 * The IPython Engine
7 * The IPython Controller
7 * The IPython Controller
8 * Clients to the IPython Controller
8 * Clients to the IPython Controller
9
9
10 The kernel module implements the engine, controller and client and all the
10 The kernel module implements the engine, controller and client and all the
11 network protocols needed for the various entities to talk to each other.
11 network protocols needed for the various entities to talk to each other.
12
12
13 An end user should probably begin by looking at the `client.py` module
13 An end user should probably begin by looking at the `client.py` module
14 if they need blocking clients or in `asyncclient.py` if they want asynchronous,
14 if they need blocking clients or in `asyncclient.py` if they want asynchronous,
15 deferred/Twisted using clients.
15 deferred/Twisted using clients.
16 """
16 """
17 __docformat__ = "restructuredtext en"
17 __docformat__ = "restructuredtext en"
18 #-------------------------------------------------------------------------------
18 #-----------------------------------------------------------------------------
19 # Copyright (C) 2008 The IPython Development Team
19 # Copyright (C) 2008 The IPython Development Team
20 #
20 #
21 # Distributed under the terms of the BSD License. The full license is in
21 # Distributed under the terms of the BSD License. The full license is in
22 # the file COPYING, distributed as part of this software.
22 # the file COPYING, distributed as part of this software.
23 #-------------------------------------------------------------------------------
23 #-----------------------------------------------------------------------------
24
24
25 from IPython.kernel.error import TaskRejectError No newline at end of file
@@ -1,124 +1,126 b''
1 # encoding: utf-8
1 # encoding: utf-8
2
2
3 """Default kernel configuration."""
3 """Default kernel configuration."""
4
4
5 __docformat__ = "restructuredtext en"
5 __docformat__ = "restructuredtext en"
6
6
7 #-------------------------------------------------------------------------------
7 #-------------------------------------------------------------------------------
8 # Copyright (C) 2008 The IPython Development Team
8 # Copyright (C) 2008 The IPython Development Team
9 #
9 #
10 # Distributed under the terms of the BSD License. The full license is in
10 # Distributed under the terms of the BSD License. The full license is in
11 # the file COPYING, distributed as part of this software.
11 # the file COPYING, distributed as part of this software.
12 #-------------------------------------------------------------------------------
12 #-------------------------------------------------------------------------------
13
13
14 #-------------------------------------------------------------------------------
14 #-------------------------------------------------------------------------------
15 # Imports
15 # Imports
16 #-------------------------------------------------------------------------------
16 #-------------------------------------------------------------------------------
17
17
18 import os, sys
18 from os.path import join as pjoin
19 from os.path import join as pjoin
19
20
20 from IPython.external.configobj import ConfigObj
21 from IPython.external.configobj import ConfigObj
21 from IPython.config.api import ConfigObjManager
22 from IPython.config.api import ConfigObjManager
22 from IPython.genutils import get_ipython_dir, get_security_dir
23 from IPython.genutils import get_ipython_dir, get_security_dir
23
24
24 default_kernel_config = ConfigObj()
25 default_kernel_config = ConfigObj()
25
26
27 # This will raise OSError if ipythondir doesn't exist.
26 security_dir = get_security_dir()
28 security_dir = get_security_dir()
27
29
28 #-------------------------------------------------------------------------------
30 #-------------------------------------------------------------------------------
29 # Engine Configuration
31 # Engine Configuration
30 #-------------------------------------------------------------------------------
32 #-------------------------------------------------------------------------------
31
33
32 engine_config = dict(
34 engine_config = dict(
33 logfile = '', # Empty means log to stdout
35 logfile = '', # Empty means log to stdout
34 furl_file = pjoin(security_dir, 'ipcontroller-engine.furl')
36 furl_file = pjoin(security_dir, 'ipcontroller-engine.furl')
35 )
37 )
36
38
37 #-------------------------------------------------------------------------------
39 #-------------------------------------------------------------------------------
38 # MPI Configuration
40 # MPI Configuration
39 #-------------------------------------------------------------------------------
41 #-------------------------------------------------------------------------------
40
42
41 mpi_config = dict(
43 mpi_config = dict(
42 mpi4py = """from mpi4py import MPI as mpi
44 mpi4py = """from mpi4py import MPI as mpi
43 mpi.size = mpi.COMM_WORLD.Get_size()
45 mpi.size = mpi.COMM_WORLD.Get_size()
44 mpi.rank = mpi.COMM_WORLD.Get_rank()
46 mpi.rank = mpi.COMM_WORLD.Get_rank()
45 """,
47 """,
46 pytrilinos = """from PyTrilinos import Epetra
48 pytrilinos = """from PyTrilinos import Epetra
47 class SimpleStruct:
49 class SimpleStruct:
48 pass
50 pass
49 mpi = SimpleStruct()
51 mpi = SimpleStruct()
50 mpi.rank = 0
52 mpi.rank = 0
51 mpi.size = 0
53 mpi.size = 0
52 """,
54 """,
53 default = ''
55 default = ''
54 )
56 )
55
57
56 #-------------------------------------------------------------------------------
58 #-------------------------------------------------------------------------------
57 # Controller Configuration
59 # Controller Configuration
58 #-------------------------------------------------------------------------------
60 #-------------------------------------------------------------------------------
59
61
60 controller_config = dict(
62 controller_config = dict(
61
63
62 logfile = '', # Empty means log to stdout
64 logfile = '', # Empty means log to stdout
63 import_statement = '',
65 import_statement = '',
64 reuse_furls = False, # If False, old furl files are deleted
66 reuse_furls = False, # If False, old furl files are deleted
65
67
66 engine_tub = dict(
68 engine_tub = dict(
67 ip = '', # Empty string means all interfaces
69 ip = '', # Empty string means all interfaces
68 port = 0, # 0 means pick a port for me
70 port = 0, # 0 means pick a port for me
69 location = '', # Empty string means try to set automatically
71 location = '', # Empty string means try to set automatically
70 secure = True,
72 secure = True,
71 cert_file = pjoin(security_dir, 'ipcontroller-engine.pem'),
73 cert_file = pjoin(security_dir, 'ipcontroller-engine.pem'),
72 ),
74 ),
73 engine_fc_interface = 'IPython.kernel.enginefc.IFCControllerBase',
75 engine_fc_interface = 'IPython.kernel.enginefc.IFCControllerBase',
74 engine_furl_file = pjoin(security_dir, 'ipcontroller-engine.furl'),
76 engine_furl_file = pjoin(security_dir, 'ipcontroller-engine.furl'),
75
77
76 controller_interfaces = dict(
78 controller_interfaces = dict(
77 # multiengine = dict(
79 # multiengine = dict(
78 # controller_interface = 'IPython.kernel.multiengine.IMultiEngine',
80 # controller_interface = 'IPython.kernel.multiengine.IMultiEngine',
79 # fc_interface = 'IPython.kernel.multienginefc.IFCMultiEngine',
81 # fc_interface = 'IPython.kernel.multienginefc.IFCMultiEngine',
80 # furl_file = 'ipcontroller-mec.furl'
82 # furl_file = 'ipcontroller-mec.furl'
81 # ),
83 # ),
82 task = dict(
84 task = dict(
83 controller_interface = 'IPython.kernel.task.ITaskController',
85 controller_interface = 'IPython.kernel.task.ITaskController',
84 fc_interface = 'IPython.kernel.taskfc.IFCTaskController',
86 fc_interface = 'IPython.kernel.taskfc.IFCTaskController',
85 furl_file = pjoin(security_dir, 'ipcontroller-tc.furl')
87 furl_file = pjoin(security_dir, 'ipcontroller-tc.furl')
86 ),
88 ),
87 multiengine = dict(
89 multiengine = dict(
88 controller_interface = 'IPython.kernel.multiengine.IMultiEngine',
90 controller_interface = 'IPython.kernel.multiengine.IMultiEngine',
89 fc_interface = 'IPython.kernel.multienginefc.IFCSynchronousMultiEngine',
91 fc_interface = 'IPython.kernel.multienginefc.IFCSynchronousMultiEngine',
90 furl_file = pjoin(security_dir, 'ipcontroller-mec.furl')
92 furl_file = pjoin(security_dir, 'ipcontroller-mec.furl')
91 )
93 )
92 ),
94 ),
93
95
94 client_tub = dict(
96 client_tub = dict(
95 ip = '', # Empty string means all interfaces
97 ip = '', # Empty string means all interfaces
96 port = 0, # 0 means pick a port for me
98 port = 0, # 0 means pick a port for me
97 location = '', # Empty string means try to set automatically
99 location = '', # Empty string means try to set automatically
98 secure = True,
100 secure = True,
99 cert_file = pjoin(security_dir, 'ipcontroller-client.pem')
101 cert_file = pjoin(security_dir, 'ipcontroller-client.pem')
100 )
102 )
101 )
103 )
102
104
103 #-------------------------------------------------------------------------------
105 #-------------------------------------------------------------------------------
104 # Client Configuration
106 # Client Configuration
105 #-------------------------------------------------------------------------------
107 #-------------------------------------------------------------------------------
106
108
107 client_config = dict(
109 client_config = dict(
108 client_interfaces = dict(
110 client_interfaces = dict(
109 task = dict(
111 task = dict(
110 furl_file = pjoin(security_dir, 'ipcontroller-tc.furl')
112 furl_file = pjoin(security_dir, 'ipcontroller-tc.furl')
111 ),
113 ),
112 multiengine = dict(
114 multiengine = dict(
113 furl_file = pjoin(security_dir, 'ipcontroller-mec.furl')
115 furl_file = pjoin(security_dir, 'ipcontroller-mec.furl')
114 )
116 )
115 )
117 )
116 )
118 )
117
119
118 default_kernel_config['engine'] = engine_config
120 default_kernel_config['engine'] = engine_config
119 default_kernel_config['mpi'] = mpi_config
121 default_kernel_config['mpi'] = mpi_config
120 default_kernel_config['controller'] = controller_config
122 default_kernel_config['controller'] = controller_config
121 default_kernel_config['client'] = client_config
123 default_kernel_config['client'] = client_config
122
124
123
125
124 config_manager = ConfigObjManager(default_kernel_config, 'IPython.kernel.ini') No newline at end of file
126 config_manager = ConfigObjManager(default_kernel_config, 'IPython.kernel.ini')
@@ -1,754 +1,761 b''
1 # encoding: utf-8
1 # encoding: utf-8
2
2
3 """Central interpreter object for an IPython engine.
3 """Central interpreter object for an IPython engine.
4
4
5 The interpreter is the object whose job is to process lines of user input and
5 The interpreter is the object whose job is to process lines of user input and
6 actually execute them in the user's namespace.
6 actually execute them in the user's namespace.
7 """
7 """
8
8
9 __docformat__ = "restructuredtext en"
9 __docformat__ = "restructuredtext en"
10
10
11 #-------------------------------------------------------------------------------
11 #-------------------------------------------------------------------------------
12 # Copyright (C) 2008 The IPython Development Team
12 # Copyright (C) 2008 The IPython Development Team
13 #
13 #
14 # Distributed under the terms of the BSD License. The full license is in
14 # Distributed under the terms of the BSD License. The full license is in
15 # the file COPYING, distributed as part of this software.
15 # the file COPYING, distributed as part of this software.
16 #-------------------------------------------------------------------------------
16 #-------------------------------------------------------------------------------
17
17
18 #-------------------------------------------------------------------------------
18 #-------------------------------------------------------------------------------
19 # Imports
19 # Imports
20 #-------------------------------------------------------------------------------
20 #-------------------------------------------------------------------------------
21
21
22 # Standard library imports.
22 # Standard library imports.
23 from types import FunctionType
23 from types import FunctionType
24
24
25 import __builtin__
25 import __builtin__
26 import codeop
26 import codeop
27 import compiler
27 import compiler
28 import sys
28 import sys
29 import traceback
29 import traceback
30
30
31 # Local imports.
31 # Local imports.
32 from IPython.kernel.core import ultraTB
32 from IPython.kernel.core import ultraTB
33 from IPython.kernel.core.display_trap import DisplayTrap
33 from IPython.kernel.core.display_trap import DisplayTrap
34 from IPython.kernel.core.macro import Macro
34 from IPython.kernel.core.macro import Macro
35 from IPython.kernel.core.prompts import CachedOutput
35 from IPython.kernel.core.prompts import CachedOutput
36 from IPython.kernel.core.traceback_trap import TracebackTrap
36 from IPython.kernel.core.traceback_trap import TracebackTrap
37 from IPython.kernel.core.util import Bunch, system_shell
37 from IPython.kernel.core.util import Bunch, system_shell
38 from IPython.external.Itpl import ItplNS
38 from IPython.external.Itpl import ItplNS
39
39
40 # Global constants
40 # Global constants
41 COMPILER_ERROR = 'error'
41 COMPILER_ERROR = 'error'
42 INCOMPLETE_INPUT = 'incomplete'
42 INCOMPLETE_INPUT = 'incomplete'
43 COMPLETE_INPUT = 'complete'
43 COMPLETE_INPUT = 'complete'
44
44
45 ##############################################################################
45 ##############################################################################
46 # TEMPORARY!!! fake configuration, while we decide whether to use tconfig or
46 # TEMPORARY!!! fake configuration, while we decide whether to use tconfig or
47 # not
47 # not
48
48
49 rc = Bunch()
49 rc = Bunch()
50 rc.cache_size = 100
50 rc.cache_size = 100
51 rc.pprint = True
51 rc.pprint = True
52 rc.separate_in = '\n'
52 rc.separate_in = '\n'
53 rc.separate_out = '\n'
53 rc.separate_out = '\n'
54 rc.separate_out2 = ''
54 rc.separate_out2 = ''
55 rc.prompt_in1 = r'In [\#]: '
55 rc.prompt_in1 = r'In [\#]: '
56 rc.prompt_in2 = r' .\\D.: '
56 rc.prompt_in2 = r' .\\D.: '
57 rc.prompt_out = ''
57 rc.prompt_out = ''
58 rc.prompts_pad_left = False
58 rc.prompts_pad_left = False
59
59
60 ##############################################################################
60 ##############################################################################
61
61
62 # Top-level utilities
62 # Top-level utilities
63 def default_display_formatters():
63 def default_display_formatters():
64 """ Return a list of default display formatters.
64 """ Return a list of default display formatters.
65 """
65 """
66
66
67 from display_formatter import PPrintDisplayFormatter, ReprDisplayFormatter
67 from display_formatter import PPrintDisplayFormatter, ReprDisplayFormatter
68 return [PPrintDisplayFormatter(), ReprDisplayFormatter()]
68 return [PPrintDisplayFormatter(), ReprDisplayFormatter()]
69
69
70 def default_traceback_formatters():
70 def default_traceback_formatters():
71 """ Return a list of default traceback formatters.
71 """ Return a list of default traceback formatters.
72 """
72 """
73
73
74 from traceback_formatter import PlainTracebackFormatter
74 from traceback_formatter import PlainTracebackFormatter
75 return [PlainTracebackFormatter()]
75 return [PlainTracebackFormatter()]
76
76
77 # Top-level classes
77 # Top-level classes
78 class NotDefined(object): pass
78 class NotDefined(object): pass
79
79
80 class Interpreter(object):
80 class Interpreter(object):
81 """ An interpreter object.
81 """ An interpreter object.
82
82
83 fixme: needs to negotiate available formatters with frontends.
83 fixme: needs to negotiate available formatters with frontends.
84
84
85 Important: the interpeter should be built so that it exposes a method
85 Important: the interpeter should be built so that it exposes a method
86 for each attribute/method of its sub-object. This way it can be
86 for each attribute/method of its sub-object. This way it can be
87 replaced by a network adapter.
87 replaced by a network adapter.
88 """
88 """
89
89
90 def __init__(self, user_ns=None, global_ns=None,translator=None,
90 def __init__(self, user_ns=None, global_ns=None,translator=None,
91 magic=None, display_formatters=None,
91 magic=None, display_formatters=None,
92 traceback_formatters=None, output_trap=None, history=None,
92 traceback_formatters=None, output_trap=None, history=None,
93 message_cache=None, filename='<string>', config=None):
93 message_cache=None, filename='<string>', config=None):
94
94
95 # The local/global namespaces for code execution
95 # The local/global namespaces for code execution
96 local_ns = user_ns # compatibility name
96 local_ns = user_ns # compatibility name
97 if local_ns is None:
97 if local_ns is None:
98 local_ns = {}
98 local_ns = {}
99 self.user_ns = local_ns
99 self.user_ns = local_ns
100 # The local namespace
100 # The local namespace
101 if global_ns is None:
101 if global_ns is None:
102 global_ns = {}
102 global_ns = {}
103 self.user_global_ns = global_ns
103 self.user_global_ns = global_ns
104
104
105 # An object that will translate commands into executable Python.
105 # An object that will translate commands into executable Python.
106 # The current translator does not work properly so for now we are going
106 # The current translator does not work properly so for now we are going
107 # without!
107 # without!
108 # if translator is None:
108 # if translator is None:
109 # from IPython.kernel.core.translator import IPythonTranslator
109 # from IPython.kernel.core.translator import IPythonTranslator
110 # translator = IPythonTranslator()
110 # translator = IPythonTranslator()
111 self.translator = translator
111 self.translator = translator
112
112
113 # An object that maintains magic commands.
113 # An object that maintains magic commands.
114 if magic is None:
114 if magic is None:
115 from IPython.kernel.core.magic import Magic
115 from IPython.kernel.core.magic import Magic
116 magic = Magic(self)
116 magic = Magic(self)
117 self.magic = magic
117 self.magic = magic
118
118
119 # A list of formatters for the displayhook.
119 # A list of formatters for the displayhook.
120 if display_formatters is None:
120 if display_formatters is None:
121 display_formatters = default_display_formatters()
121 display_formatters = default_display_formatters()
122 self.display_formatters = display_formatters
122 self.display_formatters = display_formatters
123
123
124 # A list of formatters for tracebacks.
124 # A list of formatters for tracebacks.
125 if traceback_formatters is None:
125 if traceback_formatters is None:
126 traceback_formatters = default_traceback_formatters()
126 traceback_formatters = default_traceback_formatters()
127 self.traceback_formatters = traceback_formatters
127 self.traceback_formatters = traceback_formatters
128
128
129 # The object trapping stdout/stderr.
129 # The object trapping stdout/stderr.
130 if output_trap is None:
130 if output_trap is None:
131 from IPython.kernel.core.output_trap import OutputTrap
131 from IPython.kernel.core.output_trap import OutputTrap
132 output_trap = OutputTrap()
132 output_trap = OutputTrap()
133 self.output_trap = output_trap
133 self.output_trap = output_trap
134
134
135 # An object that manages the history.
135 # An object that manages the history.
136 if history is None:
136 if history is None:
137 from IPython.kernel.core.history import InterpreterHistory
137 from IPython.kernel.core.history import InterpreterHistory
138 history = InterpreterHistory()
138 history = InterpreterHistory()
139 self.history = history
139 self.history = history
140 self.get_history_item = history.get_history_item
140 self.get_history_item = history.get_history_item
141 self.get_history_input_cache = history.get_input_cache
141 self.get_history_input_cache = history.get_input_cache
142 self.get_history_input_after = history.get_input_after
142 self.get_history_input_after = history.get_input_after
143
143
144 # An object that caches all of the return messages.
144 # An object that caches all of the return messages.
145 if message_cache is None:
145 if message_cache is None:
146 from IPython.kernel.core.message_cache import SimpleMessageCache
146 from IPython.kernel.core.message_cache import SimpleMessageCache
147 message_cache = SimpleMessageCache()
147 message_cache = SimpleMessageCache()
148 self.message_cache = message_cache
148 self.message_cache = message_cache
149
149
150 # The "filename" of the code that is executed in this interpreter.
150 # The "filename" of the code that is executed in this interpreter.
151 self.filename = filename
151 self.filename = filename
152
152
153 # An object that contains much configuration information.
153 # An object that contains much configuration information.
154 if config is None:
154 if config is None:
155 # fixme: Move this constant elsewhere!
155 # fixme: Move this constant elsewhere!
156 config = Bunch(ESC_MAGIC='%')
156 config = Bunch(ESC_MAGIC='%')
157 self.config = config
157 self.config = config
158
158
159 # Hook managers.
159 # Hook managers.
160 # fixme: make the display callbacks configurable. In the meantime,
160 # fixme: make the display callbacks configurable. In the meantime,
161 # enable macros.
161 # enable macros.
162 self.display_trap = DisplayTrap(
162 self.display_trap = DisplayTrap(
163 formatters=self.display_formatters,
163 formatters=self.display_formatters,
164 callbacks=[self._possible_macro],
164 callbacks=[self._possible_macro],
165 )
165 )
166 self.traceback_trap = TracebackTrap(
166 self.traceback_trap = TracebackTrap(
167 formatters=self.traceback_formatters)
167 formatters=self.traceback_formatters)
168
168
169 # This is used temporarily for reformating exceptions in certain
169 # This is used temporarily for reformating exceptions in certain
170 # cases. It will go away once the ultraTB stuff is ported
170 # cases. It will go away once the ultraTB stuff is ported
171 # to ipython1
171 # to ipython1
172 self.tbHandler = ultraTB.FormattedTB(color_scheme='NoColor',
172 self.tbHandler = ultraTB.FormattedTB(color_scheme='NoColor',
173 mode='Context',
173 mode='Context',
174 tb_offset=2)
174 tb_offset=2)
175
175
176 # An object that can compile commands and remember __future__
176 # An object that can compile commands and remember __future__
177 # statements.
177 # statements.
178 self.command_compiler = codeop.CommandCompiler()
178 self.command_compiler = codeop.CommandCompiler()
179
179
180 # A replacement for the raw_input() and input() builtins. Change these
180 # A replacement for the raw_input() and input() builtins. Change these
181 # attributes later to configure them.
181 # attributes later to configure them.
182 self.raw_input_builtin = raw_input
182 self.raw_input_builtin = raw_input
183 self.input_builtin = input
183 self.input_builtin = input
184
184
185 # The number of the current cell.
185 # The number of the current cell.
186 self.current_cell_number = 1
186 self.current_cell_number = 1
187
187
188 # Initialize cache, set in/out prompts and printing system
188 # Initialize cache, set in/out prompts and printing system
189 self.outputcache = CachedOutput(self,
189 self.outputcache = CachedOutput(self,
190 rc.cache_size,
190 rc.cache_size,
191 rc.pprint,
191 rc.pprint,
192 input_sep = rc.separate_in,
192 input_sep = rc.separate_in,
193 output_sep = rc.separate_out,
193 output_sep = rc.separate_out,
194 output_sep2 = rc.separate_out2,
194 output_sep2 = rc.separate_out2,
195 ps1 = rc.prompt_in1,
195 ps1 = rc.prompt_in1,
196 ps2 = rc.prompt_in2,
196 ps2 = rc.prompt_in2,
197 ps_out = rc.prompt_out,
197 ps_out = rc.prompt_out,
198 pad_left = rc.prompts_pad_left)
198 pad_left = rc.prompts_pad_left)
199
199
200 # Need to decide later if this is the right approach, but clients
200 # Need to decide later if this is the right approach, but clients
201 # commonly use sys.ps1/2, so it may be best to just set them here
201 # commonly use sys.ps1/2, so it may be best to just set them here
202 sys.ps1 = self.outputcache.prompt1.p_str
202 sys.ps1 = self.outputcache.prompt1.p_str
203 sys.ps2 = self.outputcache.prompt2.p_str
203 sys.ps2 = self.outputcache.prompt2.p_str
204
204
205 # This is the message dictionary assigned temporarily when running the
205 # This is the message dictionary assigned temporarily when running the
206 # code.
206 # code.
207 self.message = None
207 self.message = None
208
208
209 self.setup_namespace()
209 self.setup_namespace()
210
210
211
211
212 #### Public 'Interpreter' interface ########################################
212 #### Public 'Interpreter' interface ########################################
213
213
214 def formatTraceback(self, et, ev, tb, message=''):
214 def formatTraceback(self, et, ev, tb, message=''):
215 """Put a formatted version of the traceback into value and reraise.
215 """Put a formatted version of the traceback into value and reraise.
216
216
217 When exceptions have to be sent over the network, the traceback
217 When exceptions have to be sent over the network, the traceback
218 needs to be put into the value of the exception in a nicely
218 needs to be put into the value of the exception in a nicely
219 formatted way. The method takes the type, value and tb of an
219 formatted way. The method takes the type, value and tb of an
220 exception and puts a string representation of the tb into the
220 exception and puts a string representation of the tb into the
221 value of the exception and reraises it.
221 value of the exception and reraises it.
222
222
223 Currently this method uses the ultraTb formatter from IPython trunk.
223 Currently this method uses the ultraTb formatter from IPython trunk.
224 Eventually it should simply use the traceback formatters in core
224 Eventually it should simply use the traceback formatters in core
225 that are loaded into self.tracback_trap.formatters.
225 that are loaded into self.tracback_trap.formatters.
226 """
226 """
227 tbinfo = self.tbHandler.text(et,ev,tb)
227 tbinfo = self.tbHandler.text(et,ev,tb)
228 ev._ipython_traceback_text = tbinfo
228 ev._ipython_traceback_text = tbinfo
229 return et, ev, tb
229 return et, ev, tb
230
230
231 def execute(self, commands, raiseException=True):
231 def execute(self, commands, raiseException=True):
232 """ Execute some IPython commands.
232 """ Execute some IPython commands.
233
233
234 1. Translate them into Python.
234 1. Translate them into Python.
235 2. Run them.
235 2. Run them.
236 3. Trap stdout/stderr.
236 3. Trap stdout/stderr.
237 4. Trap sys.displayhook().
237 4. Trap sys.displayhook().
238 5. Trap exceptions.
238 5. Trap exceptions.
239 6. Return a message object.
239 6. Return a message object.
240
240
241 Parameters
241 Parameters
242 ----------
242 ----------
243 commands : str
243 commands : str
244 The raw commands that the user typed into the prompt.
244 The raw commands that the user typed into the prompt.
245
245
246 Returns
246 Returns
247 -------
247 -------
248 message : dict
248 message : dict
249 The dictionary of responses. See the README.txt in this directory
249 The dictionary of responses. See the README.txt in this directory
250 for an explanation of the format.
250 for an explanation of the format.
251 """
251 """
252
252
253 # Create a message dictionary with all of the information we will be
253 # Create a message dictionary with all of the information we will be
254 # returning to the frontend and other listeners.
254 # returning to the frontend and other listeners.
255 message = self.setup_message()
255 message = self.setup_message()
256
256
257 # Massage the input and store the raw and translated commands into
257 # Massage the input and store the raw and translated commands into
258 # a dict.
258 # a dict.
259 user_input = dict(raw=commands)
259 user_input = dict(raw=commands)
260 if self.translator is not None:
260 if self.translator is not None:
261 python = self.translator(commands, message)
261 python = self.translator(commands, message)
262 if python is None:
262 if python is None:
263 # Something went wrong with the translation. The translator
263 # Something went wrong with the translation. The translator
264 # should have added an appropriate entry to the message object.
264 # should have added an appropriate entry to the message object.
265 return message
265 return message
266 else:
266 else:
267 python = commands
267 python = commands
268 user_input['translated'] = python
268 user_input['translated'] = python
269 message['input'] = user_input
269 message['input'] = user_input
270
270
271 # Set the message object so that any magics executed in the code have
271 # Set the message object so that any magics executed in the code have
272 # access.
272 # access.
273 self.message = message
273 self.message = message
274
274
275 # Set all of the output/exception traps.
275 # Set all of the output/exception traps.
276 self.set_traps()
276 self.set_traps()
277
277
278 # Actually execute the Python code.
278 # Actually execute the Python code.
279 status = self.execute_python(python)
279 status = self.execute_python(python)
280
280
281 # Unset all of the traps.
281 # Unset all of the traps.
282 self.unset_traps()
282 self.unset_traps()
283
283
284 # Unset the message object.
284 # Unset the message object.
285 self.message = None
285 self.message = None
286
286
287 # Update the history variables in the namespace.
287 # Update the history variables in the namespace.
288 # E.g. In, Out, _, __, ___
288 # E.g. In, Out, _, __, ___
289 if self.history is not None:
289 if self.history is not None:
290 self.history.update_history(self, python)
290 self.history.update_history(self, python)
291
291
292 # Let all of the traps contribute to the message and then clear their
292 # Let all of the traps contribute to the message and then clear their
293 # stored information.
293 # stored information.
294 self.output_trap.add_to_message(message)
294 self.output_trap.add_to_message(message)
295 self.output_trap.clear()
295 self.output_trap.clear()
296 self.display_trap.add_to_message(message)
296 self.display_trap.add_to_message(message)
297 self.display_trap.clear()
297 self.display_trap.clear()
298 self.traceback_trap.add_to_message(message)
298 self.traceback_trap.add_to_message(message)
299 # Pull out the type, value and tb of the current exception
299 # Pull out the type, value and tb of the current exception
300 # before clearing it.
300 # before clearing it.
301 einfo = self.traceback_trap.args
301 einfo = self.traceback_trap.args
302 self.traceback_trap.clear()
302 self.traceback_trap.clear()
303
303
304 # Cache the message.
304 # Cache the message.
305 self.message_cache.add_message(self.current_cell_number, message)
305 self.message_cache.add_message(self.current_cell_number, message)
306
306
307 # Bump the number.
307 # Bump the number.
308 self.current_cell_number += 1
308 self.current_cell_number += 1
309
309
310 # This conditional lets the execute method either raise any
310 # This conditional lets the execute method either raise any
311 # exception that has occured in user code OR return the message
311 # exception that has occured in user code OR return the message
312 # dict containing the traceback and other useful info.
312 # dict containing the traceback and other useful info.
313 if raiseException and einfo:
313 if raiseException and einfo:
314 raise einfo[0],einfo[1],einfo[2]
314 raise einfo[0],einfo[1],einfo[2]
315 else:
315 else:
316 return message
316 return message
317
317
318 def generate_prompt(self, is_continuation):
318 def generate_prompt(self, is_continuation):
319 """Calculate and return a string with the prompt to display.
319 """Calculate and return a string with the prompt to display.
320
320
321 :Parameters:
321 :Parameters:
322 is_continuation : bool
322 is_continuation : bool
323 Whether the input line is continuing multiline input or not, so
323 Whether the input line is continuing multiline input or not, so
324 that a proper continuation prompt can be computed."""
324 that a proper continuation prompt can be computed."""
325
325
326 if is_continuation:
326 if is_continuation:
327 return str(self.outputcache.prompt2)
327 return str(self.outputcache.prompt2)
328 else:
328 else:
329 return str(self.outputcache.prompt1)
329 return str(self.outputcache.prompt1)
330
330
331 def execute_python(self, python):
331 def execute_python(self, python):
332 """ Actually run the Python code in the namespace.
332 """ Actually run the Python code in the namespace.
333
333
334 :Parameters:
334 :Parameters:
335
335
336 python : str
336 python : str
337 Pure, exec'able Python code. Special IPython commands should have
337 Pure, exec'able Python code. Special IPython commands should have
338 already been translated into pure Python.
338 already been translated into pure Python.
339 """
339 """
340
340
341 # We use a CommandCompiler instance to compile the code so as to keep
341 # We use a CommandCompiler instance to compile the code so as to keep
342 # track of __future__ imports.
342 # track of __future__ imports.
343 try:
343 try:
344 commands = self.split_commands(python)
344 commands = self.split_commands(python)
345 except (SyntaxError, IndentationError), e:
345 except (SyntaxError, IndentationError), e:
346 # Save the exc_info so compilation related exceptions can be
346 # Save the exc_info so compilation related exceptions can be
347 # reraised
347 # reraised
348 self.traceback_trap.args = sys.exc_info()
348 self.traceback_trap.args = sys.exc_info()
349 self.pack_exception(self.message,e)
349 self.pack_exception(self.message,e)
350 return None
350 return None
351
351
352 for cmd in commands:
352 for cmd in commands:
353 try:
353 try:
354 code = self.command_compiler(cmd, self.filename, 'single')
354 code = self.command_compiler(cmd, self.filename, 'single')
355 except (SyntaxError, OverflowError, ValueError), e:
355 except (SyntaxError, OverflowError, ValueError), e:
356 self.traceback_trap.args = sys.exc_info()
356 self.traceback_trap.args = sys.exc_info()
357 self.pack_exception(self.message,e)
357 self.pack_exception(self.message,e)
358 # No point in continuing if one block raised
358 # No point in continuing if one block raised
359 return None
359 return None
360 else:
360 else:
361 self.execute_block(code)
361 self.execute_block(code)
362
362
363 def execute_block(self,code):
363 def execute_block(self,code):
364 """Execute a single block of code in the user namespace.
364 """Execute a single block of code in the user namespace.
365
365
366 Return value: a flag indicating whether the code to be run completed
366 Return value: a flag indicating whether the code to be run completed
367 successfully:
367 successfully:
368
368
369 - 0: successful execution.
369 - 0: successful execution.
370 - 1: an error occurred.
370 - 1: an error occurred.
371 """
371 """
372
372
373 outflag = 1 # start by assuming error, success will reset it
373 outflag = 1 # start by assuming error, success will reset it
374 try:
374 try:
375 exec code in self.user_ns
375 exec code in self.user_ns
376 outflag = 0
376 outflag = 0
377 except SystemExit:
377 except SystemExit:
378 self.resetbuffer()
378 self.resetbuffer()
379 self.traceback_trap.args = sys.exc_info()
379 self.traceback_trap.args = sys.exc_info()
380 except:
380 except:
381 self.traceback_trap.args = sys.exc_info()
381 self.traceback_trap.args = sys.exc_info()
382
382
383 return outflag
383 return outflag
384
384
385 def execute_macro(self, macro):
385 def execute_macro(self, macro):
386 """ Execute the value of a macro.
386 """ Execute the value of a macro.
387
387
388 Parameters
388 Parameters
389 ----------
389 ----------
390 macro : Macro
390 macro : Macro
391 """
391 """
392
392
393 python = macro.value
393 python = macro.value
394 if self.translator is not None:
394 if self.translator is not None:
395 python = self.translator(python)
395 python = self.translator(python)
396 self.execute_python(python)
396 self.execute_python(python)
397
397
398 def getCommand(self, i=None):
398 def getCommand(self, i=None):
399 """Gets the ith message in the message_cache.
399 """Gets the ith message in the message_cache.
400
400
401 This is implemented here for compatibility with the old ipython1 shell
401 This is implemented here for compatibility with the old ipython1 shell
402 I am not sure we need this though. I even seem to remember that we
402 I am not sure we need this though. I even seem to remember that we
403 were going to get rid of it.
403 were going to get rid of it.
404 """
404 """
405 return self.message_cache.get_message(i)
405 return self.message_cache.get_message(i)
406
406
407 def reset(self):
407 def reset(self):
408 """Reset the interpreter.
408 """Reset the interpreter.
409
409
410 Currently this only resets the users variables in the namespace.
410 Currently this only resets the users variables in the namespace.
411 In the future we might want to also reset the other stateful
411 In the future we might want to also reset the other stateful
412 things like that the Interpreter has, like In, Out, etc.
412 things like that the Interpreter has, like In, Out, etc.
413 """
413 """
414 self.user_ns.clear()
414 self.user_ns.clear()
415 self.setup_namespace()
415 self.setup_namespace()
416
416
417 def complete(self,line,text=None, pos=None):
417 def complete(self,line,text=None, pos=None):
418 """Complete the given text.
418 """Complete the given text.
419
419
420 :Parameters:
420 :Parameters:
421
421
422 text : str
422 text : str
423 Text fragment to be completed on. Typically this is
423 Text fragment to be completed on. Typically this is
424 """
424 """
425 # fixme: implement
425 # fixme: implement
426 raise NotImplementedError
426 raise NotImplementedError
427
427
428 def push(self, ns):
428 def push(self, ns):
429 """ Put value into the namespace with name key.
429 """ Put value into the namespace with name key.
430
430
431 Parameters
431 Parameters
432 ----------
432 ----------
433 **kwds
433 **kwds
434 """
434 """
435
435
436 self.user_ns.update(ns)
436 self.user_ns.update(ns)
437
437
438 def push_function(self, ns):
438 def push_function(self, ns):
439 # First set the func_globals for all functions to self.user_ns
439 # First set the func_globals for all functions to self.user_ns
440 new_kwds = {}
440 new_kwds = {}
441 for k, v in ns.iteritems():
441 for k, v in ns.iteritems():
442 if not isinstance(v, FunctionType):
442 if not isinstance(v, FunctionType):
443 raise TypeError("function object expected")
443 raise TypeError("function object expected")
444 new_kwds[k] = FunctionType(v.func_code, self.user_ns)
444 new_kwds[k] = FunctionType(v.func_code, self.user_ns)
445 self.user_ns.update(new_kwds)
445 self.user_ns.update(new_kwds)
446
446
447 def pack_exception(self,message,exc):
447 def pack_exception(self,message,exc):
448 message['exception'] = exc.__class__
448 message['exception'] = exc.__class__
449 message['exception_value'] = \
449 message['exception_value'] = \
450 traceback.format_exception_only(exc.__class__, exc)
450 traceback.format_exception_only(exc.__class__, exc)
451
451
452 def feed_block(self, source, filename='<input>', symbol='single'):
452 def feed_block(self, source, filename='<input>', symbol='single'):
453 """Compile some source in the interpreter.
453 """Compile some source in the interpreter.
454
454
455 One several things can happen:
455 One several things can happen:
456
456
457 1) The input is incorrect; compile_command() raised an
457 1) The input is incorrect; compile_command() raised an
458 exception (SyntaxError or OverflowError).
458 exception (SyntaxError or OverflowError).
459
459
460 2) The input is incomplete, and more input is required;
460 2) The input is incomplete, and more input is required;
461 compile_command() returned None. Nothing happens.
461 compile_command() returned None. Nothing happens.
462
462
463 3) The input is complete; compile_command() returned a code
463 3) The input is complete; compile_command() returned a code
464 object. The code is executed by calling self.runcode() (which
464 object. The code is executed by calling self.runcode() (which
465 also handles run-time exceptions, except for SystemExit).
465 also handles run-time exceptions, except for SystemExit).
466
466
467 The return value is:
467 The return value is:
468
468
469 - True in case 2
469 - True in case 2
470
470
471 - False in the other cases, unless an exception is raised, where
471 - False in the other cases, unless an exception is raised, where
472 None is returned instead. This can be used by external callers to
472 None is returned instead. This can be used by external callers to
473 know whether to continue feeding input or not.
473 know whether to continue feeding input or not.
474
474
475 The return value can be used to decide whether to use sys.ps1 or
475 The return value can be used to decide whether to use sys.ps1 or
476 sys.ps2 to prompt the next line."""
476 sys.ps2 to prompt the next line."""
477
477
478 self.message = self.setup_message()
478 self.message = self.setup_message()
479
479
480 try:
480 try:
481 code = self.command_compiler(source,filename,symbol)
481 code = self.command_compiler(source,filename,symbol)
482 except (OverflowError, SyntaxError, IndentationError, ValueError ), e:
482 except (OverflowError, SyntaxError, IndentationError, ValueError ), e:
483 # Case 1
483 # Case 1
484 self.traceback_trap.args = sys.exc_info()
484 self.traceback_trap.args = sys.exc_info()
485 self.pack_exception(self.message,e)
485 self.pack_exception(self.message,e)
486 return COMPILER_ERROR,False
486 return COMPILER_ERROR,False
487
487
488 if code is None:
488 if code is None:
489 # Case 2: incomplete input. This means that the input can span
489 # Case 2: incomplete input. This means that the input can span
490 # multiple lines. But we still need to decide when to actually
490 # multiple lines. But we still need to decide when to actually
491 # stop taking user input. Later we'll add auto-indentation support
491 # stop taking user input. Later we'll add auto-indentation support
492 # somehow. In the meantime, we'll just stop if there are two lines
492 # somehow. In the meantime, we'll just stop if there are two lines
493 # of pure whitespace at the end.
493 # of pure whitespace at the end.
494 last_two = source.rsplit('\n',2)[-2:]
494 last_two = source.rsplit('\n',2)[-2:]
495 print 'last two:',last_two # dbg
495 print 'last two:',last_two # dbg
496 if len(last_two)==2 and all(s.isspace() for s in last_two):
496 if len(last_two)==2 and all(s.isspace() for s in last_two):
497 return COMPLETE_INPUT,False
497 return COMPLETE_INPUT,False
498 else:
498 else:
499 return INCOMPLETE_INPUT, True
499 return INCOMPLETE_INPUT, True
500 else:
500 else:
501 # Case 3
501 # Case 3
502 return COMPLETE_INPUT, False
502 return COMPLETE_INPUT, False
503
503
504 def pull(self, keys):
504 def pull(self, keys):
505 """ Get an item out of the namespace by key.
505 """ Get an item out of the namespace by key.
506
506
507 Parameters
507 Parameters
508 ----------
508 ----------
509 key : str
509 key : str
510
510
511 Returns
511 Returns
512 -------
512 -------
513 value : object
513 value : object
514
514
515 Raises
515 Raises
516 ------
516 ------
517 TypeError if the key is not a string.
517 TypeError if the key is not a string.
518 NameError if the object doesn't exist.
518 NameError if the object doesn't exist.
519 """
519 """
520
520
521 if isinstance(keys, str):
521 if isinstance(keys, str):
522 result = self.user_ns.get(keys, NotDefined())
522 result = self.user_ns.get(keys, NotDefined())
523 if isinstance(result, NotDefined):
523 if isinstance(result, NotDefined):
524 raise NameError('name %s is not defined' % keys)
524 raise NameError('name %s is not defined' % keys)
525 elif isinstance(keys, (list, tuple)):
525 elif isinstance(keys, (list, tuple)):
526 result = []
526 result = []
527 for key in keys:
527 for key in keys:
528 if not isinstance(key, str):
528 if not isinstance(key, str):
529 raise TypeError("objects must be keyed by strings.")
529 raise TypeError("objects must be keyed by strings.")
530 else:
530 else:
531 r = self.user_ns.get(key, NotDefined())
531 r = self.user_ns.get(key, NotDefined())
532 if isinstance(r, NotDefined):
532 if isinstance(r, NotDefined):
533 raise NameError('name %s is not defined' % key)
533 raise NameError('name %s is not defined' % key)
534 else:
534 else:
535 result.append(r)
535 result.append(r)
536 if len(keys)==1:
536 if len(keys)==1:
537 result = result[0]
537 result = result[0]
538 else:
538 else:
539 raise TypeError("keys must be a strong or a list/tuple of strings")
539 raise TypeError("keys must be a strong or a list/tuple of strings")
540 return result
540 return result
541
541
542 def pull_function(self, keys):
542 def pull_function(self, keys):
543 return self.pull(keys)
543 return self.pull(keys)
544
544
545 #### Interactive user API ##################################################
545 #### Interactive user API ##################################################
546
546
547 def ipsystem(self, command):
547 def ipsystem(self, command):
548 """ Execute a command in a system shell while expanding variables in the
548 """ Execute a command in a system shell while expanding variables in the
549 current namespace.
549 current namespace.
550
550
551 Parameters
551 Parameters
552 ----------
552 ----------
553 command : str
553 command : str
554 """
554 """
555
555
556 # Expand $variables.
556 # Expand $variables.
557 command = self.var_expand(command)
557 command = self.var_expand(command)
558
558
559 system_shell(command,
559 system_shell(command,
560 header='IPython system call: ',
560 header='IPython system call: ',
561 verbose=self.rc.system_verbose,
561 verbose=self.rc.system_verbose,
562 )
562 )
563
563
564 def ipmagic(self, arg_string):
564 def ipmagic(self, arg_string):
565 """ Call a magic function by name.
565 """ Call a magic function by name.
566
566
567 ipmagic('name -opt foo bar') is equivalent to typing at the ipython
567 ipmagic('name -opt foo bar') is equivalent to typing at the ipython
568 prompt:
568 prompt:
569
569
570 In[1]: %name -opt foo bar
570 In[1]: %name -opt foo bar
571
571
572 To call a magic without arguments, simply use ipmagic('name').
572 To call a magic without arguments, simply use ipmagic('name').
573
573
574 This provides a proper Python function to call IPython's magics in any
574 This provides a proper Python function to call IPython's magics in any
575 valid Python code you can type at the interpreter, including loops and
575 valid Python code you can type at the interpreter, including loops and
576 compound statements. It is added by IPython to the Python builtin
576 compound statements. It is added by IPython to the Python builtin
577 namespace upon initialization.
577 namespace upon initialization.
578
578
579 Parameters
579 Parameters
580 ----------
580 ----------
581 arg_string : str
581 arg_string : str
582 A string containing the name of the magic function to call and any
582 A string containing the name of the magic function to call and any
583 additional arguments to be passed to the magic.
583 additional arguments to be passed to the magic.
584
584
585 Returns
585 Returns
586 -------
586 -------
587 something : object
587 something : object
588 The return value of the actual object.
588 The return value of the actual object.
589 """
589 """
590
590
591 # Taken from IPython.
591 # Taken from IPython.
592 raise NotImplementedError('Not ported yet')
592 raise NotImplementedError('Not ported yet')
593
593
594 args = arg_string.split(' ', 1)
594 args = arg_string.split(' ', 1)
595 magic_name = args[0]
595 magic_name = args[0]
596 magic_name = magic_name.lstrip(self.config.ESC_MAGIC)
596 magic_name = magic_name.lstrip(self.config.ESC_MAGIC)
597
597
598 try:
598 try:
599 magic_args = args[1]
599 magic_args = args[1]
600 except IndexError:
600 except IndexError:
601 magic_args = ''
601 magic_args = ''
602 fn = getattr(self.magic, 'magic_'+magic_name, None)
602 fn = getattr(self.magic, 'magic_'+magic_name, None)
603 if fn is None:
603 if fn is None:
604 self.error("Magic function `%s` not found." % magic_name)
604 self.error("Magic function `%s` not found." % magic_name)
605 else:
605 else:
606 magic_args = self.var_expand(magic_args)
606 magic_args = self.var_expand(magic_args)
607 return fn(magic_args)
607 return fn(magic_args)
608
608
609
609
610 #### Private 'Interpreter' interface #######################################
610 #### Private 'Interpreter' interface #######################################
611
611
612 def setup_message(self):
612 def setup_message(self):
613 """Return a message object.
613 """Return a message object.
614
614
615 This method prepares and returns a message dictionary. This dict
615 This method prepares and returns a message dictionary. This dict
616 contains the various fields that are used to transfer information about
616 contains the various fields that are used to transfer information about
617 execution, results, tracebacks, etc, to clients (either in or out of
617 execution, results, tracebacks, etc, to clients (either in or out of
618 process ones). Because of the need to work with possibly out of
618 process ones). Because of the need to work with possibly out of
619 process clients, this dict MUST contain strictly pickle-safe values.
619 process clients, this dict MUST contain strictly pickle-safe values.
620 """
620 """
621
621
622 return dict(number=self.current_cell_number)
622 return dict(number=self.current_cell_number)
623
623
624 def setup_namespace(self):
624 def setup_namespace(self):
625 """ Add things to the namespace.
625 """ Add things to the namespace.
626 """
626 """
627
627
628 self.user_ns.setdefault('__name__', '__main__')
628 self.user_ns.setdefault('__name__', '__main__')
629 self.user_ns.setdefault('__builtins__', __builtin__)
629 self.user_ns.setdefault('__builtins__', __builtin__)
630 self.user_ns['__IP'] = self
630 self.user_ns['__IP'] = self
631 if self.raw_input_builtin is not None:
631 if self.raw_input_builtin is not None:
632 self.user_ns['raw_input'] = self.raw_input_builtin
632 self.user_ns['raw_input'] = self.raw_input_builtin
633 if self.input_builtin is not None:
633 if self.input_builtin is not None:
634 self.user_ns['input'] = self.input_builtin
634 self.user_ns['input'] = self.input_builtin
635
635
636 builtin_additions = dict(
636 builtin_additions = dict(
637 ipmagic=self.ipmagic,
637 ipmagic=self.ipmagic,
638 )
638 )
639 __builtin__.__dict__.update(builtin_additions)
639 __builtin__.__dict__.update(builtin_additions)
640
640
641 if self.history is not None:
641 if self.history is not None:
642 self.history.setup_namespace(self.user_ns)
642 self.history.setup_namespace(self.user_ns)
643
643
644 def set_traps(self):
644 def set_traps(self):
645 """ Set all of the output, display, and traceback traps.
645 """ Set all of the output, display, and traceback traps.
646 """
646 """
647
647
648 self.output_trap.set()
648 self.output_trap.set()
649 self.display_trap.set()
649 self.display_trap.set()
650 self.traceback_trap.set()
650 self.traceback_trap.set()
651
651
652 def unset_traps(self):
652 def unset_traps(self):
653 """ Unset all of the output, display, and traceback traps.
653 """ Unset all of the output, display, and traceback traps.
654 """
654 """
655
655
656 self.output_trap.unset()
656 self.output_trap.unset()
657 self.display_trap.unset()
657 self.display_trap.unset()
658 self.traceback_trap.unset()
658 self.traceback_trap.unset()
659
659
660 def split_commands(self, python):
660 def split_commands(self, python):
661 """ Split multiple lines of code into discrete commands that can be
661 """ Split multiple lines of code into discrete commands that can be
662 executed singly.
662 executed singly.
663
663
664 Parameters
664 Parameters
665 ----------
665 ----------
666 python : str
666 python : str
667 Pure, exec'able Python code.
667 Pure, exec'able Python code.
668
668
669 Returns
669 Returns
670 -------
670 -------
671 commands : list of str
671 commands : list of str
672 Separate commands that can be exec'ed independently.
672 Separate commands that can be exec'ed independently.
673 """
673 """
674
674
675 # compiler.parse treats trailing spaces after a newline as a
675 # compiler.parse treats trailing spaces after a newline as a
676 # SyntaxError. This is different than codeop.CommandCompiler, which
676 # SyntaxError. This is different than codeop.CommandCompiler, which
677 # will compile the trailng spaces just fine. We simply strip any
677 # will compile the trailng spaces just fine. We simply strip any
678 # trailing whitespace off. Passing a string with trailing whitespace
678 # trailing whitespace off. Passing a string with trailing whitespace
679 # to exec will fail however. There seems to be some inconsistency in
679 # to exec will fail however. There seems to be some inconsistency in
680 # how trailing whitespace is handled, but this seems to work.
680 # how trailing whitespace is handled, but this seems to work.
681 python = python.strip()
681 python = python.strip()
682
682
683 # The compiler module does not like unicode. We need to convert
683 # The compiler module does not like unicode. We need to convert
684 # it encode it:
684 # it encode it:
685 if isinstance(python, unicode):
685 if isinstance(python, unicode):
686 # Use the utf-8-sig BOM so the compiler detects this a UTF-8
686 # Use the utf-8-sig BOM so the compiler detects this a UTF-8
687 # encode string.
687 # encode string.
688 python = '\xef\xbb\xbf' + python.encode('utf-8')
688 python = '\xef\xbb\xbf' + python.encode('utf-8')
689
689
690 # The compiler module will parse the code into an abstract syntax tree.
690 # The compiler module will parse the code into an abstract syntax tree.
691 # This has a bug with str("a\nb"), but not str("""a\nb""")!!!
691 ast = compiler.parse(python)
692 ast = compiler.parse(python)
692
693
693 # Uncomment to help debug the ast tree
694 # Uncomment to help debug the ast tree
694 # for n in ast.node:
695 # for n in ast.node:
695 # print n.lineno,'->',n
696 # print n.lineno,'->',n
696
697
697 # Each separate command is available by iterating over ast.node. The
698 # Each separate command is available by iterating over ast.node. The
698 # lineno attribute is the line number (1-indexed) beginning the commands
699 # lineno attribute is the line number (1-indexed) beginning the commands
699 # suite.
700 # suite.
700 # lines ending with ";" yield a Discard Node that doesn't have a lineno
701 # lines ending with ";" yield a Discard Node that doesn't have a lineno
701 # attribute. These nodes can and should be discarded. But there are
702 # attribute. These nodes can and should be discarded. But there are
702 # other situations that cause Discard nodes that shouldn't be discarded.
703 # other situations that cause Discard nodes that shouldn't be discarded.
703 # We might eventually discover other cases where lineno is None and have
704 # We might eventually discover other cases where lineno is None and have
704 # to put in a more sophisticated test.
705 # to put in a more sophisticated test.
705 linenos = [x.lineno-1 for x in ast.node if x.lineno is not None]
706 linenos = [x.lineno-1 for x in ast.node if x.lineno is not None]
706
707
707 # When we finally get the slices, we will need to slice all the way to
708 # When we finally get the slices, we will need to slice all the way to
708 # the end even though we don't have a line number for it. Fortunately,
709 # the end even though we don't have a line number for it. Fortunately,
709 # None does the job nicely.
710 # None does the job nicely.
710 linenos.append(None)
711 linenos.append(None)
712
713 # Same problem at the other end: sometimes the ast tree has its
714 # first complete statement not starting on line 0. In this case
715 # we might miss part of it. This fixes ticket 266993. Thanks Gael!
716 linenos[0] = 0
717
711 lines = python.splitlines()
718 lines = python.splitlines()
712
719
713 # Create a list of atomic commands.
720 # Create a list of atomic commands.
714 cmds = []
721 cmds = []
715 for i, j in zip(linenos[:-1], linenos[1:]):
722 for i, j in zip(linenos[:-1], linenos[1:]):
716 cmd = lines[i:j]
723 cmd = lines[i:j]
717 if cmd:
724 if cmd:
718 cmds.append('\n'.join(cmd)+'\n')
725 cmds.append('\n'.join(cmd)+'\n')
719
726
720 return cmds
727 return cmds
721
728
722 def error(self, text):
729 def error(self, text):
723 """ Pass an error message back to the shell.
730 """ Pass an error message back to the shell.
724
731
725 Preconditions
732 Preconditions
726 -------------
733 -------------
727 This should only be called when self.message is set. In other words,
734 This should only be called when self.message is set. In other words,
728 when code is being executed.
735 when code is being executed.
729
736
730 Parameters
737 Parameters
731 ----------
738 ----------
732 text : str
739 text : str
733 """
740 """
734
741
735 errors = self.message.get('IPYTHON_ERROR', [])
742 errors = self.message.get('IPYTHON_ERROR', [])
736 errors.append(text)
743 errors.append(text)
737
744
738 def var_expand(self, template):
745 def var_expand(self, template):
739 """ Expand $variables in the current namespace using Itpl.
746 """ Expand $variables in the current namespace using Itpl.
740
747
741 Parameters
748 Parameters
742 ----------
749 ----------
743 template : str
750 template : str
744 """
751 """
745
752
746 return str(ItplNS(template, self.user_ns))
753 return str(ItplNS(template, self.user_ns))
747
754
748 def _possible_macro(self, obj):
755 def _possible_macro(self, obj):
749 """ If the object is a macro, execute it.
756 """ If the object is a macro, execute it.
750 """
757 """
751
758
752 if isinstance(obj, Macro):
759 if isinstance(obj, Macro):
753 self.execute_macro(obj)
760 self.execute_macro(obj)
754
761
@@ -1,123 +1,125 b''
1 # encoding: utf-8
1 # encoding: utf-8
2
2
3 """The IPython Core Notification Center.
3 """The IPython Core Notification Center.
4
4
5 See docs/source/development/notification_blueprint.txt for an overview of the
5 See docs/source/development/notification_blueprint.txt for an overview of the
6 notification module.
6 notification module.
7 """
7 """
8
8
9 __docformat__ = "restructuredtext en"
9 __docformat__ = "restructuredtext en"
10
10
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12 # Copyright (C) 2008 The IPython Development Team
12 # Copyright (C) 2008 The IPython Development Team
13 #
13 #
14 # Distributed under the terms of the BSD License. The full license is in
14 # Distributed under the terms of the BSD License. The full license is in
15 # the file COPYING, distributed as part of this software.
15 # the file COPYING, distributed as part of this software.
16 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
17
17
18 # Tell nose to skip the testing of this module
19 __test__ = {}
18
20
19 class NotificationCenter(object):
21 class NotificationCenter(object):
20 """Synchronous notification center
22 """Synchronous notification center
21
23
22 Example
24 Example
23 -------
25 -------
24 >>> import IPython.kernel.core.notification as notification
26 >>> import IPython.kernel.core.notification as notification
25 >>> def callback(theType, theSender, args={}):
27 >>> def callback(theType, theSender, args={}):
26 ... print theType,theSender,args
28 ... print theType,theSender,args
27 ...
29 ...
28 >>> notification.sharedCenter.add_observer(callback, 'NOTIFICATION_TYPE', None)
30 >>> notification.sharedCenter.add_observer(callback, 'NOTIFICATION_TYPE', None)
29 >>> notification.sharedCenter.post_notification('NOTIFICATION_TYPE', object()) # doctest:+ELLIPSIS
31 >>> notification.sharedCenter.post_notification('NOTIFICATION_TYPE', object()) # doctest:+ELLIPSIS
30 NOTIFICATION_TYPE ...
32 NOTIFICATION_TYPE ...
31
33
32 """
34 """
33 def __init__(self):
35 def __init__(self):
34 super(NotificationCenter, self).__init__()
36 super(NotificationCenter, self).__init__()
35 self._init_observers()
37 self._init_observers()
36
38
37
39
38 def _init_observers(self):
40 def _init_observers(self):
39 """Initialize observer storage"""
41 """Initialize observer storage"""
40
42
41 self.registered_types = set() #set of types that are observed
43 self.registered_types = set() #set of types that are observed
42 self.registered_senders = set() #set of senders that are observed
44 self.registered_senders = set() #set of senders that are observed
43 self.observers = {} #map (type,sender) => callback (callable)
45 self.observers = {} #map (type,sender) => callback (callable)
44
46
45
47
46 def post_notification(self, theType, sender, **kwargs):
48 def post_notification(self, theType, sender, **kwargs):
47 """Post notification (type,sender,**kwargs) to all registered
49 """Post notification (type,sender,**kwargs) to all registered
48 observers.
50 observers.
49
51
50 Implementation
52 Implementation
51 --------------
53 --------------
52 * If no registered observers, performance is O(1).
54 * If no registered observers, performance is O(1).
53 * Notificaiton order is undefined.
55 * Notificaiton order is undefined.
54 * Notifications are posted synchronously.
56 * Notifications are posted synchronously.
55 """
57 """
56
58
57 if(theType==None or sender==None):
59 if(theType==None or sender==None):
58 raise Exception("NotificationCenter.post_notification requires \
60 raise Exception("NotificationCenter.post_notification requires \
59 type and sender.")
61 type and sender.")
60
62
61 # If there are no registered observers for the type/sender pair
63 # If there are no registered observers for the type/sender pair
62 if((theType not in self.registered_types and
64 if((theType not in self.registered_types and
63 None not in self.registered_types) or
65 None not in self.registered_types) or
64 (sender not in self.registered_senders and
66 (sender not in self.registered_senders and
65 None not in self.registered_senders)):
67 None not in self.registered_senders)):
66 return
68 return
67
69
68 for o in self._observers_for_notification(theType, sender):
70 for o in self._observers_for_notification(theType, sender):
69 o(theType, sender, args=kwargs)
71 o(theType, sender, args=kwargs)
70
72
71
73
72 def _observers_for_notification(self, theType, sender):
74 def _observers_for_notification(self, theType, sender):
73 """Find all registered observers that should recieve notification"""
75 """Find all registered observers that should recieve notification"""
74
76
75 keys = (
77 keys = (
76 (theType,sender),
78 (theType,sender),
77 (theType, None),
79 (theType, None),
78 (None, sender),
80 (None, sender),
79 (None,None)
81 (None,None)
80 )
82 )
81
83
82
84
83 obs = set()
85 obs = set()
84 for k in keys:
86 for k in keys:
85 obs.update(self.observers.get(k, set()))
87 obs.update(self.observers.get(k, set()))
86
88
87 return obs
89 return obs
88
90
89
91
90 def add_observer(self, callback, theType, sender):
92 def add_observer(self, callback, theType, sender):
91 """Add an observer callback to this notification center.
93 """Add an observer callback to this notification center.
92
94
93 The given callback will be called upon posting of notifications of
95 The given callback will be called upon posting of notifications of
94 the given type/sender and will receive any additional kwargs passed
96 the given type/sender and will receive any additional kwargs passed
95 to post_notification.
97 to post_notification.
96
98
97 Parameters
99 Parameters
98 ----------
100 ----------
99 observerCallback : callable
101 observerCallback : callable
100 Callable. Must take at least two arguments::
102 Callable. Must take at least two arguments::
101 observerCallback(type, sender, args={})
103 observerCallback(type, sender, args={})
102
104
103 theType : hashable
105 theType : hashable
104 The notification type. If None, all notifications from sender
106 The notification type. If None, all notifications from sender
105 will be posted.
107 will be posted.
106
108
107 sender : hashable
109 sender : hashable
108 The notification sender. If None, all notifications of theType
110 The notification sender. If None, all notifications of theType
109 will be posted.
111 will be posted.
110 """
112 """
111 assert(callback != None)
113 assert(callback != None)
112 self.registered_types.add(theType)
114 self.registered_types.add(theType)
113 self.registered_senders.add(sender)
115 self.registered_senders.add(sender)
114 self.observers.setdefault((theType,sender), set()).add(callback)
116 self.observers.setdefault((theType,sender), set()).add(callback)
115
117
116 def remove_all_observers(self):
118 def remove_all_observers(self):
117 """Removes all observers from this notification center"""
119 """Removes all observers from this notification center"""
118
120
119 self._init_observers()
121 self._init_observers()
120
122
121
123
122
124
123 sharedCenter = NotificationCenter() No newline at end of file
125 sharedCenter = NotificationCenter()
@@ -1,26 +1,62 b''
1 # encoding: utf-8
1 # encoding: utf-8
2
2
3 """This file contains unittests for the interpreter.py module."""
3 """This file contains unittests for the interpreter.py module."""
4
4
5 __docformat__ = "restructuredtext en"
6
7 #-----------------------------------------------------------------------------
5 #-----------------------------------------------------------------------------
8 # Copyright (C) 2008 The IPython Development Team
6 # Copyright (C) 2008-2009 The IPython Development Team
9 #
7 #
10 # Distributed under the terms of the BSD License. The full license is in
8 # Distributed under the terms of the BSD License. The full license is
11 # the file COPYING, distributed as part of this software.
9 # in the file COPYING, distributed as part of this software.
12 #-----------------------------------------------------------------------------
10 #-----------------------------------------------------------------------------
13
11
14 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
15 # Imports
13 # Imports
16 #-----------------------------------------------------------------------------
14 #-----------------------------------------------------------------------------
17
15
16 # Tell nose to skip this module
17 __test__ = {}
18
19 from twisted.trial import unittest
18 from IPython.kernel.core.interpreter import Interpreter
20 from IPython.kernel.core.interpreter import Interpreter
19
21
20 def test_unicode():
22 #-----------------------------------------------------------------------------
21 """ Test unicode handling with the interpreter.
23 # Tests
22 """
24 #-----------------------------------------------------------------------------
25
26 class TestInterpreter(unittest.TestCase):
27
28 def test_unicode(self):
29 """ Test unicode handling with the interpreter."""
23 i = Interpreter()
30 i = Interpreter()
24 i.execute_python(u'print "ù"')
31 i.execute_python(u'print "ù"')
25 i.execute_python('print "ù"')
32 i.execute_python('print "ù"')
26
33
34 def test_ticket266993(self):
35 """ Test for ticket 266993."""
36 i = Interpreter()
37 i.execute('str("""a\nb""")')
38
39 def test_ticket364347(self):
40 """Test for ticket 364347."""
41 i = Interpreter()
42 i.split_commands('str("a\\nb")')
43
44 def test_split_commands(self):
45 """ Test that commands are indeed individually split."""
46 i = Interpreter()
47 test_atoms = [('(1\n + 1)', ),
48 ('1', '1', ),
49 ]
50 for atoms in test_atoms:
51 atoms = [atom.rstrip() + '\n' for atom in atoms]
52 self.assertEquals(i.split_commands(''.join(atoms)),atoms)
53
54 def test_long_lines(self):
55 """ Test for spurious syntax error created by the interpreter."""
56 test_strings = [u'( 1 +\n 1\n )\n\n',
57 u'(1 \n + 1\n )\n\n',
58 ]
59 i = Interpreter()
60 for s in test_strings:
61 i.execute(s)
62
@@ -1,171 +1,161 b''
1 # encoding: utf-8
1 # encoding: utf-8
2
2
3 """This file contains unittests for the notification.py module."""
3 """This file contains unittests for the notification.py module."""
4
4
5 __docformat__ = "restructuredtext en"
6
7 #-----------------------------------------------------------------------------
5 #-----------------------------------------------------------------------------
8 # Copyright (C) 2008 The IPython Development Team
6 # Copyright (C) 2008-2009 The IPython Development Team
9 #
7 #
10 # Distributed under the terms of the BSD License. The full license is in
8 # Distributed under the terms of the BSD License. The full license is
11 # the file COPYING, distributed as part of this software.
9 # in the file COPYING, distributed as part of this software.
12 #-----------------------------------------------------------------------------
10 #-----------------------------------------------------------------------------
13
11
14 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
15 # Imports
13 # Imports
16 #-----------------------------------------------------------------------------
14 #-----------------------------------------------------------------------------
17
15
18 import unittest
16 # Tell nose to skip this module
17 __test__ = {}
18
19 from twisted.trial import unittest
19 import IPython.kernel.core.notification as notification
20 import IPython.kernel.core.notification as notification
20 from nose.tools import timed
21
21
22 #
22 #-----------------------------------------------------------------------------
23 # Supporting test classes
23 # Support Classes
24 #
24 #-----------------------------------------------------------------------------
25
25
26 class Observer(object):
26 class Observer(object):
27 """docstring for Observer"""
27 """docstring for Observer"""
28 def __init__(self, expectedType, expectedSender,
28 def __init__(self, expectedType, expectedSender,
29 center=notification.sharedCenter, **kwargs):
29 center=notification.sharedCenter, **kwargs):
30 super(Observer, self).__init__()
30 super(Observer, self).__init__()
31 self.expectedType = expectedType
31 self.expectedType = expectedType
32 self.expectedSender = expectedSender
32 self.expectedSender = expectedSender
33 self.expectedKwArgs = kwargs
33 self.expectedKwArgs = kwargs
34 self.recieved = False
34 self.recieved = False
35 center.add_observer(self.callback,
35 center.add_observer(self.callback,
36 self.expectedType,
36 self.expectedType,
37 self.expectedSender)
37 self.expectedSender)
38
38
39
40 def callback(self, theType, sender, args={}):
39 def callback(self, theType, sender, args={}):
41 """callback"""
40 """callback"""
42
41
43 assert(theType == self.expectedType or
42 assert(theType == self.expectedType or
44 self.expectedType == None)
43 self.expectedType == None)
45 assert(sender == self.expectedSender or
44 assert(sender == self.expectedSender or
46 self.expectedSender == None)
45 self.expectedSender == None)
47 assert(args == self.expectedKwArgs)
46 assert(args == self.expectedKwArgs)
48 self.recieved = True
47 self.recieved = True
49
48
50
51 def verify(self):
49 def verify(self):
52 """verify"""
50 """verify"""
53
51
54 assert(self.recieved)
52 assert(self.recieved)
55
53
56 def reset(self):
54 def reset(self):
57 """reset"""
55 """reset"""
58
56
59 self.recieved = False
57 self.recieved = False
60
58
61
59
62
63 class Notifier(object):
60 class Notifier(object):
64 """docstring for Notifier"""
61 """docstring for Notifier"""
65 def __init__(self, theType, **kwargs):
62 def __init__(self, theType, **kwargs):
66 super(Notifier, self).__init__()
63 super(Notifier, self).__init__()
67 self.theType = theType
64 self.theType = theType
68 self.kwargs = kwargs
65 self.kwargs = kwargs
69
66
70 def post(self, center=notification.sharedCenter):
67 def post(self, center=notification.sharedCenter):
71 """fire"""
68 """fire"""
72
69
73 center.post_notification(self.theType, self,
70 center.post_notification(self.theType, self,
74 **self.kwargs)
71 **self.kwargs)
75
72
76
73 #-----------------------------------------------------------------------------
77 #
74 # Tests
78 # Test Cases
75 #-----------------------------------------------------------------------------
79 #
80
76
81 class NotificationTests(unittest.TestCase):
77 class NotificationTests(unittest.TestCase):
82 """docstring for NotificationTests"""
78 """docstring for NotificationTests"""
83
79
84 def tearDown(self):
80 def tearDown(self):
85 notification.sharedCenter.remove_all_observers()
81 notification.sharedCenter.remove_all_observers()
86
82
87 def test_notification_delivered(self):
83 def test_notification_delivered(self):
88 """Test that notifications are delivered"""
84 """Test that notifications are delivered"""
89 expectedType = 'EXPECTED_TYPE'
85 expectedType = 'EXPECTED_TYPE'
90 sender = Notifier(expectedType)
86 sender = Notifier(expectedType)
91 observer = Observer(expectedType, sender)
87 observer = Observer(expectedType, sender)
92
88
93 sender.post()
89 sender.post()
94
90
95 observer.verify()
91 observer.verify()
96
92
97
98 def test_type_specificity(self):
93 def test_type_specificity(self):
99 """Test that observers are registered by type"""
94 """Test that observers are registered by type"""
100
95
101 expectedType = 1
96 expectedType = 1
102 unexpectedType = "UNEXPECTED_TYPE"
97 unexpectedType = "UNEXPECTED_TYPE"
103 sender = Notifier(expectedType)
98 sender = Notifier(expectedType)
104 unexpectedSender = Notifier(unexpectedType)
99 unexpectedSender = Notifier(unexpectedType)
105 observer = Observer(expectedType, sender)
100 observer = Observer(expectedType, sender)
106
101
107 sender.post()
102 sender.post()
108 unexpectedSender.post()
103 unexpectedSender.post()
109
104
110 observer.verify()
105 observer.verify()
111
106
112
113 def test_sender_specificity(self):
107 def test_sender_specificity(self):
114 """Test that observers are registered by sender"""
108 """Test that observers are registered by sender"""
115
109
116 expectedType = "EXPECTED_TYPE"
110 expectedType = "EXPECTED_TYPE"
117 sender1 = Notifier(expectedType)
111 sender1 = Notifier(expectedType)
118 sender2 = Notifier(expectedType)
112 sender2 = Notifier(expectedType)
119 observer = Observer(expectedType, sender1)
113 observer = Observer(expectedType, sender1)
120
114
121 sender1.post()
115 sender1.post()
122 sender2.post()
116 sender2.post()
123
117
124 observer.verify()
118 observer.verify()
125
119
126
127 def test_remove_all_observers(self):
120 def test_remove_all_observers(self):
128 """White-box test for remove_all_observers"""
121 """White-box test for remove_all_observers"""
129
122
130 for i in xrange(10):
123 for i in xrange(10):
131 Observer('TYPE', None, center=notification.sharedCenter)
124 Observer('TYPE', None, center=notification.sharedCenter)
132
125
133 self.assert_(len(notification.sharedCenter.observers[('TYPE',None)]) >= 10,
126 self.assert_(len(notification.sharedCenter.observers[('TYPE',None)]) >= 10,
134 "observers registered")
127 "observers registered")
135
128
136 notification.sharedCenter.remove_all_observers()
129 notification.sharedCenter.remove_all_observers()
137
130
138 self.assert_(len(notification.sharedCenter.observers) == 0, "observers removed")
131 self.assert_(len(notification.sharedCenter.observers) == 0, "observers removed")
139
132
140
141 def test_any_sender(self):
133 def test_any_sender(self):
142 """test_any_sender"""
134 """test_any_sender"""
143
135
144 expectedType = "EXPECTED_TYPE"
136 expectedType = "EXPECTED_TYPE"
145 sender1 = Notifier(expectedType)
137 sender1 = Notifier(expectedType)
146 sender2 = Notifier(expectedType)
138 sender2 = Notifier(expectedType)
147 observer = Observer(expectedType, None)
139 observer = Observer(expectedType, None)
148
140
149
141
150 sender1.post()
142 sender1.post()
151 observer.verify()
143 observer.verify()
152
144
153 observer.reset()
145 observer.reset()
154 sender2.post()
146 sender2.post()
155 observer.verify()
147 observer.verify()
156
148
157
158 @timed(.01)
159 def test_post_performance(self):
149 def test_post_performance(self):
160 """Test that post_notification, even with many registered irrelevant
150 """Test that post_notification, even with many registered irrelevant
161 observers is fast"""
151 observers is fast"""
162
152
163 for i in xrange(10):
153 for i in xrange(10):
164 Observer("UNRELATED_TYPE", None)
154 Observer("UNRELATED_TYPE", None)
165
155
166 o = Observer('EXPECTED_TYPE', None)
156 o = Observer('EXPECTED_TYPE', None)
167
157
168 notification.sharedCenter.post_notification('EXPECTED_TYPE', self)
158 notification.sharedCenter.post_notification('EXPECTED_TYPE', self)
169
159
170 o.verify()
160 o.verify()
171
161
@@ -1,70 +1,78 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 Test the output capture at the OS level, using file descriptors.
3 Test the output capture at the OS level, using file descriptors.
4 """
4 """
5
5 #-----------------------------------------------------------------------------
6 __docformat__ = "restructuredtext en"
6 # Copyright (C) 2008-2009 The IPython Development Team
7
8 #-------------------------------------------------------------------------------
9 # Copyright (C) 2008 The IPython Development Team
10 #
7 #
11 # Distributed under the terms of the BSD License. The full license is
8 # Distributed under the terms of the BSD License. The full license is
12 # in the file COPYING, distributed as part of this software.
9 # in the file COPYING, distributed as part of this software.
13 #-------------------------------------------------------------------------------
10 #-----------------------------------------------------------------------------
14
11
12 #-----------------------------------------------------------------------------
13 # Imports
14 #-----------------------------------------------------------------------------
15
16 # Tell nose to skip this module
17 __test__ = {}
15
18
16 # Stdlib imports
17 import os
18 from cStringIO import StringIO
19 from cStringIO import StringIO
20 import os
21
22 from twisted.trial import unittest
19
23
20 # Our own imports
24 from IPython.testing import decorators_trial as dec
21 from IPython.testing import decorators as dec
22
25
23 #-----------------------------------------------------------------------------
26 #-----------------------------------------------------------------------------
24 # Test functions
27 # Tests
28 #-----------------------------------------------------------------------------
29
30
31 class TestRedirector(unittest.TestCase):
25
32
26 @dec.skip_win32
33 @dec.skip_win32
27 def test_redirector():
34 def test_redirector(self):
28 """ Checks that the redirector can be used to do synchronous capture.
35 """Checks that the redirector can be used to do synchronous capture.
29 """
36 """
30 from IPython.kernel.core.fd_redirector import FDRedirector
37 from IPython.kernel.core.fd_redirector import FDRedirector
31 r = FDRedirector()
38 r = FDRedirector()
32 out = StringIO()
39 out = StringIO()
33 try:
40 try:
34 r.start()
41 r.start()
35 for i in range(10):
42 for i in range(10):
36 os.system('echo %ic' % i)
43 os.system('echo %ic' % i)
37 print >>out, r.getvalue(),
44 print >>out, r.getvalue(),
38 print >>out, i
45 print >>out, i
39 except:
46 except:
40 r.stop()
47 r.stop()
41 raise
48 raise
42 r.stop()
49 r.stop()
43 result1 = out.getvalue()
50 result1 = out.getvalue()
44 result2 = "".join("%ic\n%i\n" %(i, i) for i in range(10))
51 result2 = "".join("%ic\n%i\n" %(i, i) for i in range(10))
45 assert result1 == result2
52 self.assertEquals(result1, result2)
46
47
53
48 @dec.skip_win32
54 @dec.skip_win32
49 def test_redirector_output_trap():
55 def test_redirector_output_trap(self):
50 """ This test check not only that the redirector_output_trap does
56 """Check the greedy trapping behavior of the traps.
57
58 This test check not only that the redirector_output_trap does
51 trap the output, but also that it does it in a gready way, that
59 trap the output, but also that it does it in a gready way, that
52 is by calling the callback ASAP.
60 is by calling the callback ASAP.
53 """
61 """
54 from IPython.kernel.core.redirector_output_trap import RedirectorOutputTrap
62 from IPython.kernel.core.redirector_output_trap import RedirectorOutputTrap
55 out = StringIO()
63 out = StringIO()
56 trap = RedirectorOutputTrap(out.write, out.write)
64 trap = RedirectorOutputTrap(out.write, out.write)
57 try:
65 try:
58 trap.set()
66 trap.set()
59 for i in range(10):
67 for i in range(10):
60 os.system('echo %ic' % i)
68 os.system('echo %ic' % i)
61 print "%ip" % i
69 print "%ip" % i
62 print >>out, i
70 print >>out, i
63 except:
71 except:
64 trap.unset()
72 trap.unset()
65 raise
73 raise
66 trap.unset()
74 trap.unset()
67 result1 = out.getvalue()
75 result1 = out.getvalue()
68 result2 = "".join("%ic\n%ip\n%i\n" %(i, i, i) for i in range(10))
76 result2 = "".join("%ic\n%ip\n%i\n" %(i, i, i) for i in range(10))
69 assert result1 == result2
77 self.assertEquals(result1, result2)
70
78
@@ -1,1056 +1,1066 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 ultraTB.py -- Spice up your tracebacks!
3 ultraTB.py -- Spice up your tracebacks!
4
4
5 * ColorTB
5 * ColorTB
6 I've always found it a bit hard to visually parse tracebacks in Python. The
6 I've always found it a bit hard to visually parse tracebacks in Python. The
7 ColorTB class is a solution to that problem. It colors the different parts of a
7 ColorTB class is a solution to that problem. It colors the different parts of a
8 traceback in a manner similar to what you would expect from a syntax-highlighting
8 traceback in a manner similar to what you would expect from a syntax-highlighting
9 text editor.
9 text editor.
10
10
11 Installation instructions for ColorTB:
11 Installation instructions for ColorTB:
12 import sys,ultraTB
12 import sys,ultraTB
13 sys.excepthook = ultraTB.ColorTB()
13 sys.excepthook = ultraTB.ColorTB()
14
14
15 * VerboseTB
15 * VerboseTB
16 I've also included a port of Ka-Ping Yee's "cgitb.py" that produces all kinds
16 I've also included a port of Ka-Ping Yee's "cgitb.py" that produces all kinds
17 of useful info when a traceback occurs. Ping originally had it spit out HTML
17 of useful info when a traceback occurs. Ping originally had it spit out HTML
18 and intended it for CGI programmers, but why should they have all the fun? I
18 and intended it for CGI programmers, but why should they have all the fun? I
19 altered it to spit out colored text to the terminal. It's a bit overwhelming,
19 altered it to spit out colored text to the terminal. It's a bit overwhelming,
20 but kind of neat, and maybe useful for long-running programs that you believe
20 but kind of neat, and maybe useful for long-running programs that you believe
21 are bug-free. If a crash *does* occur in that type of program you want details.
21 are bug-free. If a crash *does* occur in that type of program you want details.
22 Give it a shot--you'll love it or you'll hate it.
22 Give it a shot--you'll love it or you'll hate it.
23
23
24 Note:
24 Note:
25
25
26 The Verbose mode prints the variables currently visible where the exception
26 The Verbose mode prints the variables currently visible where the exception
27 happened (shortening their strings if too long). This can potentially be
27 happened (shortening their strings if too long). This can potentially be
28 very slow, if you happen to have a huge data structure whose string
28 very slow, if you happen to have a huge data structure whose string
29 representation is complex to compute. Your computer may appear to freeze for
29 representation is complex to compute. Your computer may appear to freeze for
30 a while with cpu usage at 100%. If this occurs, you can cancel the traceback
30 a while with cpu usage at 100%. If this occurs, you can cancel the traceback
31 with Ctrl-C (maybe hitting it more than once).
31 with Ctrl-C (maybe hitting it more than once).
32
32
33 If you encounter this kind of situation often, you may want to use the
33 If you encounter this kind of situation often, you may want to use the
34 Verbose_novars mode instead of the regular Verbose, which avoids formatting
34 Verbose_novars mode instead of the regular Verbose, which avoids formatting
35 variables (but otherwise includes the information and context given by
35 variables (but otherwise includes the information and context given by
36 Verbose).
36 Verbose).
37
37
38
38
39 Installation instructions for ColorTB:
39 Installation instructions for ColorTB:
40 import sys,ultraTB
40 import sys,ultraTB
41 sys.excepthook = ultraTB.VerboseTB()
41 sys.excepthook = ultraTB.VerboseTB()
42
42
43 Note: Much of the code in this module was lifted verbatim from the standard
43 Note: Much of the code in this module was lifted verbatim from the standard
44 library module 'traceback.py' and Ka-Ping Yee's 'cgitb.py'.
44 library module 'traceback.py' and Ka-Ping Yee's 'cgitb.py'.
45
45
46 * Color schemes
46 * Color schemes
47 The colors are defined in the class TBTools through the use of the
47 The colors are defined in the class TBTools through the use of the
48 ColorSchemeTable class. Currently the following exist:
48 ColorSchemeTable class. Currently the following exist:
49
49
50 - NoColor: allows all of this module to be used in any terminal (the color
50 - NoColor: allows all of this module to be used in any terminal (the color
51 escapes are just dummy blank strings).
51 escapes are just dummy blank strings).
52
52
53 - Linux: is meant to look good in a terminal like the Linux console (black
53 - Linux: is meant to look good in a terminal like the Linux console (black
54 or very dark background).
54 or very dark background).
55
55
56 - LightBG: similar to Linux but swaps dark/light colors to be more readable
56 - LightBG: similar to Linux but swaps dark/light colors to be more readable
57 in light background terminals.
57 in light background terminals.
58
58
59 You can implement other color schemes easily, the syntax is fairly
59 You can implement other color schemes easily, the syntax is fairly
60 self-explanatory. Please send back new schemes you develop to the author for
60 self-explanatory. Please send back new schemes you develop to the author for
61 possible inclusion in future releases.
61 possible inclusion in future releases.
62 """
62 """
63
63
64 #*****************************************************************************
64 #*****************************************************************************
65 # Copyright (C) 2001 Nathaniel Gray <n8gray@caltech.edu>
65 # Copyright (C) 2001 Nathaniel Gray <n8gray@caltech.edu>
66 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
66 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
67 #
67 #
68 # Distributed under the terms of the BSD License. The full license is in
68 # Distributed under the terms of the BSD License. The full license is in
69 # the file COPYING, distributed as part of this software.
69 # the file COPYING, distributed as part of this software.
70 #*****************************************************************************
70 #*****************************************************************************
71
71
72 # Required modules
72 # Required modules
73 import inspect
73 import inspect
74 import keyword
74 import keyword
75 import linecache
75 import linecache
76 import os
76 import os
77 import pydoc
77 import pydoc
78 import re
78 import re
79 import string
79 import string
80 import sys
80 import sys
81 import time
81 import time
82 import tokenize
82 import tokenize
83 import traceback
83 import traceback
84 import types
84 import types
85
85
86 # For purposes of monkeypatching inspect to fix a bug in it.
86 # For purposes of monkeypatching inspect to fix a bug in it.
87 from inspect import getsourcefile, getfile, getmodule,\
87 from inspect import getsourcefile, getfile, getmodule,\
88 ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode
88 ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode
89
89
90
90
91 # IPython's own modules
91 # IPython's own modules
92 # Modified pdb which doesn't damage IPython's readline handling
92 # Modified pdb which doesn't damage IPython's readline handling
93 from IPython import Debugger, PyColorize
93 from IPython import Debugger, PyColorize
94 from IPython.ipstruct import Struct
94 from IPython.ipstruct import Struct
95 from IPython.excolors import exception_colors
95 from IPython.excolors import exception_colors
96 from IPython.genutils import Term,uniq_stable,error,info
96 from IPython.genutils import Term,uniq_stable,error,info
97
97
98 # Globals
98 # Globals
99 # amount of space to put line numbers before verbose tracebacks
99 # amount of space to put line numbers before verbose tracebacks
100 INDENT_SIZE = 8
100 INDENT_SIZE = 8
101
101
102 # Default color scheme. This is used, for example, by the traceback
102 # Default color scheme. This is used, for example, by the traceback
103 # formatter. When running in an actual IPython instance, the user's rc.colors
103 # formatter. When running in an actual IPython instance, the user's rc.colors
104 # value is used, but havinga module global makes this functionality available
104 # value is used, but havinga module global makes this functionality available
105 # to users of ultraTB who are NOT running inside ipython.
105 # to users of ultraTB who are NOT running inside ipython.
106 DEFAULT_SCHEME = 'NoColor'
106 DEFAULT_SCHEME = 'NoColor'
107
107
108 #---------------------------------------------------------------------------
108 #---------------------------------------------------------------------------
109 # Code begins
109 # Code begins
110
110
111 # Utility functions
111 # Utility functions
112 def inspect_error():
112 def inspect_error():
113 """Print a message about internal inspect errors.
113 """Print a message about internal inspect errors.
114
114
115 These are unfortunately quite common."""
115 These are unfortunately quite common."""
116
116
117 error('Internal Python error in the inspect module.\n'
117 error('Internal Python error in the inspect module.\n'
118 'Below is the traceback from this internal error.\n')
118 'Below is the traceback from this internal error.\n')
119
119
120
120
121 def findsource(object):
121 def findsource(object):
122 """Return the entire source file and starting line number for an object.
122 """Return the entire source file and starting line number for an object.
123
123
124 The argument may be a module, class, method, function, traceback, frame,
124 The argument may be a module, class, method, function, traceback, frame,
125 or code object. The source code is returned as a list of all the lines
125 or code object. The source code is returned as a list of all the lines
126 in the file and the line number indexes a line in that list. An IOError
126 in the file and the line number indexes a line in that list. An IOError
127 is raised if the source code cannot be retrieved.
127 is raised if the source code cannot be retrieved.
128
128
129 FIXED version with which we monkeypatch the stdlib to work around a bug."""
129 FIXED version with which we monkeypatch the stdlib to work around a bug."""
130
130
131 file = getsourcefile(object) or getfile(object)
131 file = getsourcefile(object) or getfile(object)
132 # If the object is a frame, then trying to get the globals dict from its
132 # If the object is a frame, then trying to get the globals dict from its
133 # module won't work. Instead, the frame object itself has the globals
133 # module won't work. Instead, the frame object itself has the globals
134 # dictionary.
134 # dictionary.
135 globals_dict = None
135 globals_dict = None
136 if inspect.isframe(object):
136 if inspect.isframe(object):
137 # XXX: can this ever be false?
137 # XXX: can this ever be false?
138 globals_dict = object.f_globals
138 globals_dict = object.f_globals
139 else:
139 else:
140 module = getmodule(object, file)
140 module = getmodule(object, file)
141 if module:
141 if module:
142 globals_dict = module.__dict__
142 globals_dict = module.__dict__
143 lines = linecache.getlines(file, globals_dict)
143 lines = linecache.getlines(file, globals_dict)
144 if not lines:
144 if not lines:
145 raise IOError('could not get source code')
145 raise IOError('could not get source code')
146
146
147 if ismodule(object):
147 if ismodule(object):
148 return lines, 0
148 return lines, 0
149
149
150 if isclass(object):
150 if isclass(object):
151 name = object.__name__
151 name = object.__name__
152 pat = re.compile(r'^(\s*)class\s*' + name + r'\b')
152 pat = re.compile(r'^(\s*)class\s*' + name + r'\b')
153 # make some effort to find the best matching class definition:
153 # make some effort to find the best matching class definition:
154 # use the one with the least indentation, which is the one
154 # use the one with the least indentation, which is the one
155 # that's most probably not inside a function definition.
155 # that's most probably not inside a function definition.
156 candidates = []
156 candidates = []
157 for i in range(len(lines)):
157 for i in range(len(lines)):
158 match = pat.match(lines[i])
158 match = pat.match(lines[i])
159 if match:
159 if match:
160 # if it's at toplevel, it's already the best one
160 # if it's at toplevel, it's already the best one
161 if lines[i][0] == 'c':
161 if lines[i][0] == 'c':
162 return lines, i
162 return lines, i
163 # else add whitespace to candidate list
163 # else add whitespace to candidate list
164 candidates.append((match.group(1), i))
164 candidates.append((match.group(1), i))
165 if candidates:
165 if candidates:
166 # this will sort by whitespace, and by line number,
166 # this will sort by whitespace, and by line number,
167 # less whitespace first
167 # less whitespace first
168 candidates.sort()
168 candidates.sort()
169 return lines, candidates[0][1]
169 return lines, candidates[0][1]
170 else:
170 else:
171 raise IOError('could not find class definition')
171 raise IOError('could not find class definition')
172
172
173 if ismethod(object):
173 if ismethod(object):
174 object = object.im_func
174 object = object.im_func
175 if isfunction(object):
175 if isfunction(object):
176 object = object.func_code
176 object = object.func_code
177 if istraceback(object):
177 if istraceback(object):
178 object = object.tb_frame
178 object = object.tb_frame
179 if isframe(object):
179 if isframe(object):
180 object = object.f_code
180 object = object.f_code
181 if iscode(object):
181 if iscode(object):
182 if not hasattr(object, 'co_firstlineno'):
182 if not hasattr(object, 'co_firstlineno'):
183 raise IOError('could not find function definition')
183 raise IOError('could not find function definition')
184 pat = re.compile(r'^(\s*def\s)|(.*(?<!\w)lambda(:|\s))|^(\s*@)')
184 pat = re.compile(r'^(\s*def\s)|(.*(?<!\w)lambda(:|\s))|^(\s*@)')
185 pmatch = pat.match
185 pmatch = pat.match
186 # fperez - fix: sometimes, co_firstlineno can give a number larger than
186 # fperez - fix: sometimes, co_firstlineno can give a number larger than
187 # the length of lines, which causes an error. Safeguard against that.
187 # the length of lines, which causes an error. Safeguard against that.
188 lnum = min(object.co_firstlineno,len(lines))-1
188 lnum = min(object.co_firstlineno,len(lines))-1
189 while lnum > 0:
189 while lnum > 0:
190 if pmatch(lines[lnum]): break
190 if pmatch(lines[lnum]): break
191 lnum -= 1
191 lnum -= 1
192
192
193 return lines, lnum
193 return lines, lnum
194 raise IOError('could not find code object')
194 raise IOError('could not find code object')
195
195
196 # Monkeypatch inspect to apply our bugfix. This code only works with py25
196 # Monkeypatch inspect to apply our bugfix. This code only works with py25
197 if sys.version_info[:2] >= (2,5):
197 if sys.version_info[:2] >= (2,5):
198 inspect.findsource = findsource
198 inspect.findsource = findsource
199
199
200 def fix_frame_records_filenames(records):
200 def fix_frame_records_filenames(records):
201 """Try to fix the filenames in each record from inspect.getinnerframes().
201 """Try to fix the filenames in each record from inspect.getinnerframes().
202
202
203 Particularly, modules loaded from within zip files have useless filenames
203 Particularly, modules loaded from within zip files have useless filenames
204 attached to their code object, and inspect.getinnerframes() just uses it.
204 attached to their code object, and inspect.getinnerframes() just uses it.
205 """
205 """
206 fixed_records = []
206 fixed_records = []
207 for frame, filename, line_no, func_name, lines, index in records:
207 for frame, filename, line_no, func_name, lines, index in records:
208 # Look inside the frame's globals dictionary for __file__, which should
208 # Look inside the frame's globals dictionary for __file__, which should
209 # be better.
209 # be better.
210 better_fn = frame.f_globals.get('__file__', None)
210 better_fn = frame.f_globals.get('__file__', None)
211 if isinstance(better_fn, str):
211 if isinstance(better_fn, str):
212 # Check the type just in case someone did something weird with
212 # Check the type just in case someone did something weird with
213 # __file__. It might also be None if the error occurred during
213 # __file__. It might also be None if the error occurred during
214 # import.
214 # import.
215 filename = better_fn
215 filename = better_fn
216 fixed_records.append((frame, filename, line_no, func_name, lines, index))
216 fixed_records.append((frame, filename, line_no, func_name, lines, index))
217 return fixed_records
217 return fixed_records
218
218
219
219
220 def _fixed_getinnerframes(etb, context=1,tb_offset=0):
220 def _fixed_getinnerframes(etb, context=1,tb_offset=0):
221 import linecache
221 import linecache
222 LNUM_POS, LINES_POS, INDEX_POS = 2, 4, 5
222 LNUM_POS, LINES_POS, INDEX_POS = 2, 4, 5
223
223
224 records = fix_frame_records_filenames(inspect.getinnerframes(etb, context))
224 records = fix_frame_records_filenames(inspect.getinnerframes(etb, context))
225
225
226 # If the error is at the console, don't build any context, since it would
226 # If the error is at the console, don't build any context, since it would
227 # otherwise produce 5 blank lines printed out (there is no file at the
227 # otherwise produce 5 blank lines printed out (there is no file at the
228 # console)
228 # console)
229 rec_check = records[tb_offset:]
229 rec_check = records[tb_offset:]
230 try:
230 try:
231 rname = rec_check[0][1]
231 rname = rec_check[0][1]
232 if rname == '<ipython console>' or rname.endswith('<string>'):
232 if rname == '<ipython console>' or rname.endswith('<string>'):
233 return rec_check
233 return rec_check
234 except IndexError:
234 except IndexError:
235 pass
235 pass
236
236
237 aux = traceback.extract_tb(etb)
237 aux = traceback.extract_tb(etb)
238 assert len(records) == len(aux)
238 assert len(records) == len(aux)
239 for i, (file, lnum, _, _) in zip(range(len(records)), aux):
239 for i, (file, lnum, _, _) in zip(range(len(records)), aux):
240 maybeStart = lnum-1 - context//2
240 maybeStart = lnum-1 - context//2
241 start = max(maybeStart, 0)
241 start = max(maybeStart, 0)
242 end = start + context
242 end = start + context
243 lines = linecache.getlines(file)[start:end]
243 lines = linecache.getlines(file)[start:end]
244 # pad with empty lines if necessary
244 # pad with empty lines if necessary
245 if maybeStart < 0:
245 if maybeStart < 0:
246 lines = (['\n'] * -maybeStart) + lines
246 lines = (['\n'] * -maybeStart) + lines
247 if len(lines) < context:
247 if len(lines) < context:
248 lines += ['\n'] * (context - len(lines))
248 lines += ['\n'] * (context - len(lines))
249 buf = list(records[i])
249 buf = list(records[i])
250 buf[LNUM_POS] = lnum
250 buf[LNUM_POS] = lnum
251 buf[INDEX_POS] = lnum - 1 - start
251 buf[INDEX_POS] = lnum - 1 - start
252 buf[LINES_POS] = lines
252 buf[LINES_POS] = lines
253 records[i] = tuple(buf)
253 records[i] = tuple(buf)
254 return records[tb_offset:]
254 return records[tb_offset:]
255
255
256 # Helper function -- largely belongs to VerboseTB, but we need the same
256 # Helper function -- largely belongs to VerboseTB, but we need the same
257 # functionality to produce a pseudo verbose TB for SyntaxErrors, so that they
257 # functionality to produce a pseudo verbose TB for SyntaxErrors, so that they
258 # can be recognized properly by ipython.el's py-traceback-line-re
258 # can be recognized properly by ipython.el's py-traceback-line-re
259 # (SyntaxErrors have to be treated specially because they have no traceback)
259 # (SyntaxErrors have to be treated specially because they have no traceback)
260
260
261 _parser = PyColorize.Parser()
261 _parser = PyColorize.Parser()
262
262
263 def _formatTracebackLines(lnum, index, lines, Colors, lvals=None,scheme=None):
263 def _formatTracebackLines(lnum, index, lines, Colors, lvals=None,scheme=None):
264 numbers_width = INDENT_SIZE - 1
264 numbers_width = INDENT_SIZE - 1
265 res = []
265 res = []
266 i = lnum - index
266 i = lnum - index
267
267
268 # This lets us get fully syntax-highlighted tracebacks.
268 # This lets us get fully syntax-highlighted tracebacks.
269 if scheme is None:
269 if scheme is None:
270 try:
270 try:
271 # Again, reference to a global __IPYTHON__ that doesn't exist.
272 # XXX
271 scheme = __IPYTHON__.rc.colors
273 scheme = __IPYTHON__.rc.colors
272 except:
274 except:
273 scheme = DEFAULT_SCHEME
275 scheme = DEFAULT_SCHEME
274 _line_format = _parser.format2
276 _line_format = _parser.format2
275
277
276 for line in lines:
278 for line in lines:
277 new_line, err = _line_format(line,'str',scheme)
279 new_line, err = _line_format(line,'str',scheme)
278 if not err: line = new_line
280 if not err: line = new_line
279
281
280 if i == lnum:
282 if i == lnum:
281 # This is the line with the error
283 # This is the line with the error
282 pad = numbers_width - len(str(i))
284 pad = numbers_width - len(str(i))
283 if pad >= 3:
285 if pad >= 3:
284 marker = '-'*(pad-3) + '-> '
286 marker = '-'*(pad-3) + '-> '
285 elif pad == 2:
287 elif pad == 2:
286 marker = '> '
288 marker = '> '
287 elif pad == 1:
289 elif pad == 1:
288 marker = '>'
290 marker = '>'
289 else:
291 else:
290 marker = ''
292 marker = ''
291 num = marker + str(i)
293 num = marker + str(i)
292 line = '%s%s%s %s%s' %(Colors.linenoEm, num,
294 line = '%s%s%s %s%s' %(Colors.linenoEm, num,
293 Colors.line, line, Colors.Normal)
295 Colors.line, line, Colors.Normal)
294 else:
296 else:
295 num = '%*s' % (numbers_width,i)
297 num = '%*s' % (numbers_width,i)
296 line = '%s%s%s %s' %(Colors.lineno, num,
298 line = '%s%s%s %s' %(Colors.lineno, num,
297 Colors.Normal, line)
299 Colors.Normal, line)
298
300
299 res.append(line)
301 res.append(line)
300 if lvals and i == lnum:
302 if lvals and i == lnum:
301 res.append(lvals + '\n')
303 res.append(lvals + '\n')
302 i = i + 1
304 i = i + 1
303 return res
305 return res
304
306
305
307
306 #---------------------------------------------------------------------------
308 #---------------------------------------------------------------------------
307 # Module classes
309 # Module classes
308 class TBTools:
310 class TBTools:
309 """Basic tools used by all traceback printer classes."""
311 """Basic tools used by all traceback printer classes."""
310
312
311 def __init__(self,color_scheme = 'NoColor',call_pdb=False):
313 def __init__(self,color_scheme = 'NoColor',call_pdb=False):
312 # Whether to call the interactive pdb debugger after printing
314 # Whether to call the interactive pdb debugger after printing
313 # tracebacks or not
315 # tracebacks or not
314 self.call_pdb = call_pdb
316 self.call_pdb = call_pdb
315
317
316 # Create color table
318 # Create color table
317 self.color_scheme_table = exception_colors()
319 self.color_scheme_table = exception_colors()
318
320
319 self.set_colors(color_scheme)
321 self.set_colors(color_scheme)
320 self.old_scheme = color_scheme # save initial value for toggles
322 self.old_scheme = color_scheme # save initial value for toggles
321
323
322 if call_pdb:
324 if call_pdb:
323 self.pdb = Debugger.Pdb(self.color_scheme_table.active_scheme_name)
325 self.pdb = Debugger.Pdb(self.color_scheme_table.active_scheme_name)
324 else:
326 else:
325 self.pdb = None
327 self.pdb = None
326
328
327 def set_colors(self,*args,**kw):
329 def set_colors(self,*args,**kw):
328 """Shorthand access to the color table scheme selector method."""
330 """Shorthand access to the color table scheme selector method."""
329
331
330 # Set own color table
332 # Set own color table
331 self.color_scheme_table.set_active_scheme(*args,**kw)
333 self.color_scheme_table.set_active_scheme(*args,**kw)
332 # for convenience, set Colors to the active scheme
334 # for convenience, set Colors to the active scheme
333 self.Colors = self.color_scheme_table.active_colors
335 self.Colors = self.color_scheme_table.active_colors
334 # Also set colors of debugger
336 # Also set colors of debugger
335 if hasattr(self,'pdb') and self.pdb is not None:
337 if hasattr(self,'pdb') and self.pdb is not None:
336 self.pdb.set_colors(*args,**kw)
338 self.pdb.set_colors(*args,**kw)
337
339
338 def color_toggle(self):
340 def color_toggle(self):
339 """Toggle between the currently active color scheme and NoColor."""
341 """Toggle between the currently active color scheme and NoColor."""
340
342
341 if self.color_scheme_table.active_scheme_name == 'NoColor':
343 if self.color_scheme_table.active_scheme_name == 'NoColor':
342 self.color_scheme_table.set_active_scheme(self.old_scheme)
344 self.color_scheme_table.set_active_scheme(self.old_scheme)
343 self.Colors = self.color_scheme_table.active_colors
345 self.Colors = self.color_scheme_table.active_colors
344 else:
346 else:
345 self.old_scheme = self.color_scheme_table.active_scheme_name
347 self.old_scheme = self.color_scheme_table.active_scheme_name
346 self.color_scheme_table.set_active_scheme('NoColor')
348 self.color_scheme_table.set_active_scheme('NoColor')
347 self.Colors = self.color_scheme_table.active_colors
349 self.Colors = self.color_scheme_table.active_colors
348
350
349 #---------------------------------------------------------------------------
351 #---------------------------------------------------------------------------
350 class ListTB(TBTools):
352 class ListTB(TBTools):
351 """Print traceback information from a traceback list, with optional color.
353 """Print traceback information from a traceback list, with optional color.
352
354
353 Calling: requires 3 arguments:
355 Calling: requires 3 arguments:
354 (etype, evalue, elist)
356 (etype, evalue, elist)
355 as would be obtained by:
357 as would be obtained by:
356 etype, evalue, tb = sys.exc_info()
358 etype, evalue, tb = sys.exc_info()
357 if tb:
359 if tb:
358 elist = traceback.extract_tb(tb)
360 elist = traceback.extract_tb(tb)
359 else:
361 else:
360 elist = None
362 elist = None
361
363
362 It can thus be used by programs which need to process the traceback before
364 It can thus be used by programs which need to process the traceback before
363 printing (such as console replacements based on the code module from the
365 printing (such as console replacements based on the code module from the
364 standard library).
366 standard library).
365
367
366 Because they are meant to be called without a full traceback (only a
368 Because they are meant to be called without a full traceback (only a
367 list), instances of this class can't call the interactive pdb debugger."""
369 list), instances of this class can't call the interactive pdb debugger."""
368
370
369 def __init__(self,color_scheme = 'NoColor'):
371 def __init__(self,color_scheme = 'NoColor'):
370 TBTools.__init__(self,color_scheme = color_scheme,call_pdb=0)
372 TBTools.__init__(self,color_scheme = color_scheme,call_pdb=0)
371
373
372 def __call__(self, etype, value, elist):
374 def __call__(self, etype, value, elist):
373 Term.cout.flush()
375 Term.cout.flush()
374 print >> Term.cerr, self.text(etype,value,elist)
376 print >> Term.cerr, self.text(etype,value,elist)
375 Term.cerr.flush()
377 Term.cerr.flush()
376
378
377 def text(self,etype, value, elist,context=5):
379 def text(self,etype, value, elist,context=5):
378 """Return a color formatted string with the traceback info."""
380 """Return a color formatted string with the traceback info."""
379
381
380 Colors = self.Colors
382 Colors = self.Colors
381 out_string = ['%s%s%s\n' % (Colors.topline,'-'*60,Colors.Normal)]
383 out_string = ['%s%s%s\n' % (Colors.topline,'-'*60,Colors.Normal)]
382 if elist:
384 if elist:
383 out_string.append('Traceback %s(most recent call last)%s:' % \
385 out_string.append('Traceback %s(most recent call last)%s:' % \
384 (Colors.normalEm, Colors.Normal) + '\n')
386 (Colors.normalEm, Colors.Normal) + '\n')
385 out_string.extend(self._format_list(elist))
387 out_string.extend(self._format_list(elist))
386 lines = self._format_exception_only(etype, value)
388 lines = self._format_exception_only(etype, value)
387 for line in lines[:-1]:
389 for line in lines[:-1]:
388 out_string.append(" "+line)
390 out_string.append(" "+line)
389 out_string.append(lines[-1])
391 out_string.append(lines[-1])
390 return ''.join(out_string)
392 return ''.join(out_string)
391
393
392 def _format_list(self, extracted_list):
394 def _format_list(self, extracted_list):
393 """Format a list of traceback entry tuples for printing.
395 """Format a list of traceback entry tuples for printing.
394
396
395 Given a list of tuples as returned by extract_tb() or
397 Given a list of tuples as returned by extract_tb() or
396 extract_stack(), return a list of strings ready for printing.
398 extract_stack(), return a list of strings ready for printing.
397 Each string in the resulting list corresponds to the item with the
399 Each string in the resulting list corresponds to the item with the
398 same index in the argument list. Each string ends in a newline;
400 same index in the argument list. Each string ends in a newline;
399 the strings may contain internal newlines as well, for those items
401 the strings may contain internal newlines as well, for those items
400 whose source text line is not None.
402 whose source text line is not None.
401
403
402 Lifted almost verbatim from traceback.py
404 Lifted almost verbatim from traceback.py
403 """
405 """
404
406
405 Colors = self.Colors
407 Colors = self.Colors
406 list = []
408 list = []
407 for filename, lineno, name, line in extracted_list[:-1]:
409 for filename, lineno, name, line in extracted_list[:-1]:
408 item = ' File %s"%s"%s, line %s%d%s, in %s%s%s\n' % \
410 item = ' File %s"%s"%s, line %s%d%s, in %s%s%s\n' % \
409 (Colors.filename, filename, Colors.Normal,
411 (Colors.filename, filename, Colors.Normal,
410 Colors.lineno, lineno, Colors.Normal,
412 Colors.lineno, lineno, Colors.Normal,
411 Colors.name, name, Colors.Normal)
413 Colors.name, name, Colors.Normal)
412 if line:
414 if line:
413 item = item + ' %s\n' % line.strip()
415 item = item + ' %s\n' % line.strip()
414 list.append(item)
416 list.append(item)
415 # Emphasize the last entry
417 # Emphasize the last entry
416 filename, lineno, name, line = extracted_list[-1]
418 filename, lineno, name, line = extracted_list[-1]
417 item = '%s File %s"%s"%s, line %s%d%s, in %s%s%s%s\n' % \
419 item = '%s File %s"%s"%s, line %s%d%s, in %s%s%s%s\n' % \
418 (Colors.normalEm,
420 (Colors.normalEm,
419 Colors.filenameEm, filename, Colors.normalEm,
421 Colors.filenameEm, filename, Colors.normalEm,
420 Colors.linenoEm, lineno, Colors.normalEm,
422 Colors.linenoEm, lineno, Colors.normalEm,
421 Colors.nameEm, name, Colors.normalEm,
423 Colors.nameEm, name, Colors.normalEm,
422 Colors.Normal)
424 Colors.Normal)
423 if line:
425 if line:
424 item = item + '%s %s%s\n' % (Colors.line, line.strip(),
426 item = item + '%s %s%s\n' % (Colors.line, line.strip(),
425 Colors.Normal)
427 Colors.Normal)
426 list.append(item)
428 list.append(item)
427 return list
429 return list
428
430
429 def _format_exception_only(self, etype, value):
431 def _format_exception_only(self, etype, value):
430 """Format the exception part of a traceback.
432 """Format the exception part of a traceback.
431
433
432 The arguments are the exception type and value such as given by
434 The arguments are the exception type and value such as given by
433 sys.exc_info()[:2]. The return value is a list of strings, each ending
435 sys.exc_info()[:2]. The return value is a list of strings, each ending
434 in a newline. Normally, the list contains a single string; however,
436 in a newline. Normally, the list contains a single string; however,
435 for SyntaxError exceptions, it contains several lines that (when
437 for SyntaxError exceptions, it contains several lines that (when
436 printed) display detailed information about where the syntax error
438 printed) display detailed information about where the syntax error
437 occurred. The message indicating which exception occurred is the
439 occurred. The message indicating which exception occurred is the
438 always last string in the list.
440 always last string in the list.
439
441
440 Also lifted nearly verbatim from traceback.py
442 Also lifted nearly verbatim from traceback.py
441 """
443 """
442
444
443 have_filedata = False
445 have_filedata = False
444 Colors = self.Colors
446 Colors = self.Colors
445 list = []
447 list = []
446 try:
448 try:
447 stype = Colors.excName + etype.__name__ + Colors.Normal
449 stype = Colors.excName + etype.__name__ + Colors.Normal
448 except AttributeError:
450 except AttributeError:
449 stype = etype # String exceptions don't get special coloring
451 stype = etype # String exceptions don't get special coloring
450 if value is None:
452 if value is None:
451 list.append( str(stype) + '\n')
453 list.append( str(stype) + '\n')
452 else:
454 else:
453 if etype is SyntaxError:
455 if etype is SyntaxError:
454 try:
456 try:
455 msg, (filename, lineno, offset, line) = value
457 msg, (filename, lineno, offset, line) = value
456 except:
458 except:
457 have_filedata = False
459 have_filedata = False
458 else:
460 else:
459 have_filedata = True
461 have_filedata = True
460 #print 'filename is',filename # dbg
462 #print 'filename is',filename # dbg
461 if not filename: filename = "<string>"
463 if not filename: filename = "<string>"
462 list.append('%s File %s"%s"%s, line %s%d%s\n' % \
464 list.append('%s File %s"%s"%s, line %s%d%s\n' % \
463 (Colors.normalEm,
465 (Colors.normalEm,
464 Colors.filenameEm, filename, Colors.normalEm,
466 Colors.filenameEm, filename, Colors.normalEm,
465 Colors.linenoEm, lineno, Colors.Normal ))
467 Colors.linenoEm, lineno, Colors.Normal ))
466 if line is not None:
468 if line is not None:
467 i = 0
469 i = 0
468 while i < len(line) and line[i].isspace():
470 while i < len(line) and line[i].isspace():
469 i = i+1
471 i = i+1
470 list.append('%s %s%s\n' % (Colors.line,
472 list.append('%s %s%s\n' % (Colors.line,
471 line.strip(),
473 line.strip(),
472 Colors.Normal))
474 Colors.Normal))
473 if offset is not None:
475 if offset is not None:
474 s = ' '
476 s = ' '
475 for c in line[i:offset-1]:
477 for c in line[i:offset-1]:
476 if c.isspace():
478 if c.isspace():
477 s = s + c
479 s = s + c
478 else:
480 else:
479 s = s + ' '
481 s = s + ' '
480 list.append('%s%s^%s\n' % (Colors.caret, s,
482 list.append('%s%s^%s\n' % (Colors.caret, s,
481 Colors.Normal) )
483 Colors.Normal) )
482 value = msg
484 value = msg
483 s = self._some_str(value)
485 s = self._some_str(value)
484 if s:
486 if s:
485 list.append('%s%s:%s %s\n' % (str(stype), Colors.excName,
487 list.append('%s%s:%s %s\n' % (str(stype), Colors.excName,
486 Colors.Normal, s))
488 Colors.Normal, s))
487 else:
489 else:
488 list.append('%s\n' % str(stype))
490 list.append('%s\n' % str(stype))
489
491
490 # vds:>>
492 # This is being commented out for now as the __IPYTHON__ variable
491 if have_filedata:
493 # referenced here is not resolved and causes massive test failures
492 __IPYTHON__.hooks.synchronize_with_editor(filename, lineno, 0)
494 # and errors. B. Granger, 04/2009. XXX
493 # vds:<<
495 # See https://bugs.launchpad.net/bugs/362137
496 # # vds:>>
497 # if have_filedata:
498 # __IPYTHON__.hooks.synchronize_with_editor(filename, lineno, 0)
499 # # vds:<<
494
500
495 return list
501 return list
496
502
497 def _some_str(self, value):
503 def _some_str(self, value):
498 # Lifted from traceback.py
504 # Lifted from traceback.py
499 try:
505 try:
500 return str(value)
506 return str(value)
501 except:
507 except:
502 return '<unprintable %s object>' % type(value).__name__
508 return '<unprintable %s object>' % type(value).__name__
503
509
504 #----------------------------------------------------------------------------
510 #----------------------------------------------------------------------------
505 class VerboseTB(TBTools):
511 class VerboseTB(TBTools):
506 """A port of Ka-Ping Yee's cgitb.py module that outputs color text instead
512 """A port of Ka-Ping Yee's cgitb.py module that outputs color text instead
507 of HTML. Requires inspect and pydoc. Crazy, man.
513 of HTML. Requires inspect and pydoc. Crazy, man.
508
514
509 Modified version which optionally strips the topmost entries from the
515 Modified version which optionally strips the topmost entries from the
510 traceback, to be used with alternate interpreters (because their own code
516 traceback, to be used with alternate interpreters (because their own code
511 would appear in the traceback)."""
517 would appear in the traceback)."""
512
518
513 def __init__(self,color_scheme = 'Linux',tb_offset=0,long_header=0,
519 def __init__(self,color_scheme = 'Linux',tb_offset=0,long_header=0,
514 call_pdb = 0, include_vars=1):
520 call_pdb = 0, include_vars=1):
515 """Specify traceback offset, headers and color scheme.
521 """Specify traceback offset, headers and color scheme.
516
522
517 Define how many frames to drop from the tracebacks. Calling it with
523 Define how many frames to drop from the tracebacks. Calling it with
518 tb_offset=1 allows use of this handler in interpreters which will have
524 tb_offset=1 allows use of this handler in interpreters which will have
519 their own code at the top of the traceback (VerboseTB will first
525 their own code at the top of the traceback (VerboseTB will first
520 remove that frame before printing the traceback info)."""
526 remove that frame before printing the traceback info)."""
521 TBTools.__init__(self,color_scheme=color_scheme,call_pdb=call_pdb)
527 TBTools.__init__(self,color_scheme=color_scheme,call_pdb=call_pdb)
522 self.tb_offset = tb_offset
528 self.tb_offset = tb_offset
523 self.long_header = long_header
529 self.long_header = long_header
524 self.include_vars = include_vars
530 self.include_vars = include_vars
525
531
526 def text(self, etype, evalue, etb, context=5):
532 def text(self, etype, evalue, etb, context=5):
527 """Return a nice text document describing the traceback."""
533 """Return a nice text document describing the traceback."""
528
534
529 # some locals
535 # some locals
530 try:
536 try:
531 etype = etype.__name__
537 etype = etype.__name__
532 except AttributeError:
538 except AttributeError:
533 pass
539 pass
534 Colors = self.Colors # just a shorthand + quicker name lookup
540 Colors = self.Colors # just a shorthand + quicker name lookup
535 ColorsNormal = Colors.Normal # used a lot
541 ColorsNormal = Colors.Normal # used a lot
536 col_scheme = self.color_scheme_table.active_scheme_name
542 col_scheme = self.color_scheme_table.active_scheme_name
537 indent = ' '*INDENT_SIZE
543 indent = ' '*INDENT_SIZE
538 em_normal = '%s\n%s%s' % (Colors.valEm, indent,ColorsNormal)
544 em_normal = '%s\n%s%s' % (Colors.valEm, indent,ColorsNormal)
539 undefined = '%sundefined%s' % (Colors.em, ColorsNormal)
545 undefined = '%sundefined%s' % (Colors.em, ColorsNormal)
540 exc = '%s%s%s' % (Colors.excName,etype,ColorsNormal)
546 exc = '%s%s%s' % (Colors.excName,etype,ColorsNormal)
541
547
542 # some internal-use functions
548 # some internal-use functions
543 def text_repr(value):
549 def text_repr(value):
544 """Hopefully pretty robust repr equivalent."""
550 """Hopefully pretty robust repr equivalent."""
545 # this is pretty horrible but should always return *something*
551 # this is pretty horrible but should always return *something*
546 try:
552 try:
547 return pydoc.text.repr(value)
553 return pydoc.text.repr(value)
548 except KeyboardInterrupt:
554 except KeyboardInterrupt:
549 raise
555 raise
550 except:
556 except:
551 try:
557 try:
552 return repr(value)
558 return repr(value)
553 except KeyboardInterrupt:
559 except KeyboardInterrupt:
554 raise
560 raise
555 except:
561 except:
556 try:
562 try:
557 # all still in an except block so we catch
563 # all still in an except block so we catch
558 # getattr raising
564 # getattr raising
559 name = getattr(value, '__name__', None)
565 name = getattr(value, '__name__', None)
560 if name:
566 if name:
561 # ick, recursion
567 # ick, recursion
562 return text_repr(name)
568 return text_repr(name)
563 klass = getattr(value, '__class__', None)
569 klass = getattr(value, '__class__', None)
564 if klass:
570 if klass:
565 return '%s instance' % text_repr(klass)
571 return '%s instance' % text_repr(klass)
566 except KeyboardInterrupt:
572 except KeyboardInterrupt:
567 raise
573 raise
568 except:
574 except:
569 return 'UNRECOVERABLE REPR FAILURE'
575 return 'UNRECOVERABLE REPR FAILURE'
570 def eqrepr(value, repr=text_repr): return '=%s' % repr(value)
576 def eqrepr(value, repr=text_repr): return '=%s' % repr(value)
571 def nullrepr(value, repr=text_repr): return ''
577 def nullrepr(value, repr=text_repr): return ''
572
578
573 # meat of the code begins
579 # meat of the code begins
574 try:
580 try:
575 etype = etype.__name__
581 etype = etype.__name__
576 except AttributeError:
582 except AttributeError:
577 pass
583 pass
578
584
579 if self.long_header:
585 if self.long_header:
580 # Header with the exception type, python version, and date
586 # Header with the exception type, python version, and date
581 pyver = 'Python ' + string.split(sys.version)[0] + ': ' + sys.executable
587 pyver = 'Python ' + string.split(sys.version)[0] + ': ' + sys.executable
582 date = time.ctime(time.time())
588 date = time.ctime(time.time())
583
589
584 head = '%s%s%s\n%s%s%s\n%s' % (Colors.topline, '-'*75, ColorsNormal,
590 head = '%s%s%s\n%s%s%s\n%s' % (Colors.topline, '-'*75, ColorsNormal,
585 exc, ' '*(75-len(str(etype))-len(pyver)),
591 exc, ' '*(75-len(str(etype))-len(pyver)),
586 pyver, string.rjust(date, 75) )
592 pyver, string.rjust(date, 75) )
587 head += "\nA problem occured executing Python code. Here is the sequence of function"\
593 head += "\nA problem occured executing Python code. Here is the sequence of function"\
588 "\ncalls leading up to the error, with the most recent (innermost) call last."
594 "\ncalls leading up to the error, with the most recent (innermost) call last."
589 else:
595 else:
590 # Simplified header
596 # Simplified header
591 head = '%s%s%s\n%s%s' % (Colors.topline, '-'*75, ColorsNormal,exc,
597 head = '%s%s%s\n%s%s' % (Colors.topline, '-'*75, ColorsNormal,exc,
592 string.rjust('Traceback (most recent call last)',
598 string.rjust('Traceback (most recent call last)',
593 75 - len(str(etype)) ) )
599 75 - len(str(etype)) ) )
594 frames = []
600 frames = []
595 # Flush cache before calling inspect. This helps alleviate some of the
601 # Flush cache before calling inspect. This helps alleviate some of the
596 # problems with python 2.3's inspect.py.
602 # problems with python 2.3's inspect.py.
597 linecache.checkcache()
603 linecache.checkcache()
598 # Drop topmost frames if requested
604 # Drop topmost frames if requested
599 try:
605 try:
600 # Try the default getinnerframes and Alex's: Alex's fixes some
606 # Try the default getinnerframes and Alex's: Alex's fixes some
601 # problems, but it generates empty tracebacks for console errors
607 # problems, but it generates empty tracebacks for console errors
602 # (5 blanks lines) where none should be returned.
608 # (5 blanks lines) where none should be returned.
603 #records = inspect.getinnerframes(etb, context)[self.tb_offset:]
609 #records = inspect.getinnerframes(etb, context)[self.tb_offset:]
604 #print 'python records:', records # dbg
610 #print 'python records:', records # dbg
605 records = _fixed_getinnerframes(etb, context,self.tb_offset)
611 records = _fixed_getinnerframes(etb, context,self.tb_offset)
606 #print 'alex records:', records # dbg
612 #print 'alex records:', records # dbg
607 except:
613 except:
608
614
609 # FIXME: I've been getting many crash reports from python 2.3
615 # FIXME: I've been getting many crash reports from python 2.3
610 # users, traceable to inspect.py. If I can find a small test-case
616 # users, traceable to inspect.py. If I can find a small test-case
611 # to reproduce this, I should either write a better workaround or
617 # to reproduce this, I should either write a better workaround or
612 # file a bug report against inspect (if that's the real problem).
618 # file a bug report against inspect (if that's the real problem).
613 # So far, I haven't been able to find an isolated example to
619 # So far, I haven't been able to find an isolated example to
614 # reproduce the problem.
620 # reproduce the problem.
615 inspect_error()
621 inspect_error()
616 traceback.print_exc(file=Term.cerr)
622 traceback.print_exc(file=Term.cerr)
617 info('\nUnfortunately, your original traceback can not be constructed.\n')
623 info('\nUnfortunately, your original traceback can not be constructed.\n')
618 return ''
624 return ''
619
625
620 # build some color string templates outside these nested loops
626 # build some color string templates outside these nested loops
621 tpl_link = '%s%%s%s' % (Colors.filenameEm,ColorsNormal)
627 tpl_link = '%s%%s%s' % (Colors.filenameEm,ColorsNormal)
622 tpl_call = 'in %s%%s%s%%s%s' % (Colors.vName, Colors.valEm,
628 tpl_call = 'in %s%%s%s%%s%s' % (Colors.vName, Colors.valEm,
623 ColorsNormal)
629 ColorsNormal)
624 tpl_call_fail = 'in %s%%s%s(***failed resolving arguments***)%s' % \
630 tpl_call_fail = 'in %s%%s%s(***failed resolving arguments***)%s' % \
625 (Colors.vName, Colors.valEm, ColorsNormal)
631 (Colors.vName, Colors.valEm, ColorsNormal)
626 tpl_local_var = '%s%%s%s' % (Colors.vName, ColorsNormal)
632 tpl_local_var = '%s%%s%s' % (Colors.vName, ColorsNormal)
627 tpl_global_var = '%sglobal%s %s%%s%s' % (Colors.em, ColorsNormal,
633 tpl_global_var = '%sglobal%s %s%%s%s' % (Colors.em, ColorsNormal,
628 Colors.vName, ColorsNormal)
634 Colors.vName, ColorsNormal)
629 tpl_name_val = '%%s %s= %%s%s' % (Colors.valEm, ColorsNormal)
635 tpl_name_val = '%%s %s= %%s%s' % (Colors.valEm, ColorsNormal)
630 tpl_line = '%s%%s%s %%s' % (Colors.lineno, ColorsNormal)
636 tpl_line = '%s%%s%s %%s' % (Colors.lineno, ColorsNormal)
631 tpl_line_em = '%s%%s%s %%s%s' % (Colors.linenoEm,Colors.line,
637 tpl_line_em = '%s%%s%s %%s%s' % (Colors.linenoEm,Colors.line,
632 ColorsNormal)
638 ColorsNormal)
633
639
634 # now, loop over all records printing context and info
640 # now, loop over all records printing context and info
635 abspath = os.path.abspath
641 abspath = os.path.abspath
636 for frame, file, lnum, func, lines, index in records:
642 for frame, file, lnum, func, lines, index in records:
637 #print '*** record:',file,lnum,func,lines,index # dbg
643 #print '*** record:',file,lnum,func,lines,index # dbg
638 try:
644 try:
639 file = file and abspath(file) or '?'
645 file = file and abspath(file) or '?'
640 except OSError:
646 except OSError:
641 # if file is '<console>' or something not in the filesystem,
647 # if file is '<console>' or something not in the filesystem,
642 # the abspath call will throw an OSError. Just ignore it and
648 # the abspath call will throw an OSError. Just ignore it and
643 # keep the original file string.
649 # keep the original file string.
644 pass
650 pass
645 link = tpl_link % file
651 link = tpl_link % file
646 try:
652 try:
647 args, varargs, varkw, locals = inspect.getargvalues(frame)
653 args, varargs, varkw, locals = inspect.getargvalues(frame)
648 except:
654 except:
649 # This can happen due to a bug in python2.3. We should be
655 # This can happen due to a bug in python2.3. We should be
650 # able to remove this try/except when 2.4 becomes a
656 # able to remove this try/except when 2.4 becomes a
651 # requirement. Bug details at http://python.org/sf/1005466
657 # requirement. Bug details at http://python.org/sf/1005466
652 inspect_error()
658 inspect_error()
653 traceback.print_exc(file=Term.cerr)
659 traceback.print_exc(file=Term.cerr)
654 info("\nIPython's exception reporting continues...\n")
660 info("\nIPython's exception reporting continues...\n")
655
661
656 if func == '?':
662 if func == '?':
657 call = ''
663 call = ''
658 else:
664 else:
659 # Decide whether to include variable details or not
665 # Decide whether to include variable details or not
660 var_repr = self.include_vars and eqrepr or nullrepr
666 var_repr = self.include_vars and eqrepr or nullrepr
661 try:
667 try:
662 call = tpl_call % (func,inspect.formatargvalues(args,
668 call = tpl_call % (func,inspect.formatargvalues(args,
663 varargs, varkw,
669 varargs, varkw,
664 locals,formatvalue=var_repr))
670 locals,formatvalue=var_repr))
665 except KeyError:
671 except KeyError:
666 # Very odd crash from inspect.formatargvalues(). The
672 # Very odd crash from inspect.formatargvalues(). The
667 # scenario under which it appeared was a call to
673 # scenario under which it appeared was a call to
668 # view(array,scale) in NumTut.view.view(), where scale had
674 # view(array,scale) in NumTut.view.view(), where scale had
669 # been defined as a scalar (it should be a tuple). Somehow
675 # been defined as a scalar (it should be a tuple). Somehow
670 # inspect messes up resolving the argument list of view()
676 # inspect messes up resolving the argument list of view()
671 # and barfs out. At some point I should dig into this one
677 # and barfs out. At some point I should dig into this one
672 # and file a bug report about it.
678 # and file a bug report about it.
673 inspect_error()
679 inspect_error()
674 traceback.print_exc(file=Term.cerr)
680 traceback.print_exc(file=Term.cerr)
675 info("\nIPython's exception reporting continues...\n")
681 info("\nIPython's exception reporting continues...\n")
676 call = tpl_call_fail % func
682 call = tpl_call_fail % func
677
683
678 # Initialize a list of names on the current line, which the
684 # Initialize a list of names on the current line, which the
679 # tokenizer below will populate.
685 # tokenizer below will populate.
680 names = []
686 names = []
681
687
682 def tokeneater(token_type, token, start, end, line):
688 def tokeneater(token_type, token, start, end, line):
683 """Stateful tokeneater which builds dotted names.
689 """Stateful tokeneater which builds dotted names.
684
690
685 The list of names it appends to (from the enclosing scope) can
691 The list of names it appends to (from the enclosing scope) can
686 contain repeated composite names. This is unavoidable, since
692 contain repeated composite names. This is unavoidable, since
687 there is no way to disambguate partial dotted structures until
693 there is no way to disambguate partial dotted structures until
688 the full list is known. The caller is responsible for pruning
694 the full list is known. The caller is responsible for pruning
689 the final list of duplicates before using it."""
695 the final list of duplicates before using it."""
690
696
691 # build composite names
697 # build composite names
692 if token == '.':
698 if token == '.':
693 try:
699 try:
694 names[-1] += '.'
700 names[-1] += '.'
695 # store state so the next token is added for x.y.z names
701 # store state so the next token is added for x.y.z names
696 tokeneater.name_cont = True
702 tokeneater.name_cont = True
697 return
703 return
698 except IndexError:
704 except IndexError:
699 pass
705 pass
700 if token_type == tokenize.NAME and token not in keyword.kwlist:
706 if token_type == tokenize.NAME and token not in keyword.kwlist:
701 if tokeneater.name_cont:
707 if tokeneater.name_cont:
702 # Dotted names
708 # Dotted names
703 names[-1] += token
709 names[-1] += token
704 tokeneater.name_cont = False
710 tokeneater.name_cont = False
705 else:
711 else:
706 # Regular new names. We append everything, the caller
712 # Regular new names. We append everything, the caller
707 # will be responsible for pruning the list later. It's
713 # will be responsible for pruning the list later. It's
708 # very tricky to try to prune as we go, b/c composite
714 # very tricky to try to prune as we go, b/c composite
709 # names can fool us. The pruning at the end is easy
715 # names can fool us. The pruning at the end is easy
710 # to do (or the caller can print a list with repeated
716 # to do (or the caller can print a list with repeated
711 # names if so desired.
717 # names if so desired.
712 names.append(token)
718 names.append(token)
713 elif token_type == tokenize.NEWLINE:
719 elif token_type == tokenize.NEWLINE:
714 raise IndexError
720 raise IndexError
715 # we need to store a bit of state in the tokenizer to build
721 # we need to store a bit of state in the tokenizer to build
716 # dotted names
722 # dotted names
717 tokeneater.name_cont = False
723 tokeneater.name_cont = False
718
724
719 def linereader(file=file, lnum=[lnum], getline=linecache.getline):
725 def linereader(file=file, lnum=[lnum], getline=linecache.getline):
720 line = getline(file, lnum[0])
726 line = getline(file, lnum[0])
721 lnum[0] += 1
727 lnum[0] += 1
722 return line
728 return line
723
729
724 # Build the list of names on this line of code where the exception
730 # Build the list of names on this line of code where the exception
725 # occurred.
731 # occurred.
726 try:
732 try:
727 # This builds the names list in-place by capturing it from the
733 # This builds the names list in-place by capturing it from the
728 # enclosing scope.
734 # enclosing scope.
729 tokenize.tokenize(linereader, tokeneater)
735 tokenize.tokenize(linereader, tokeneater)
730 except IndexError:
736 except IndexError:
731 # signals exit of tokenizer
737 # signals exit of tokenizer
732 pass
738 pass
733 except tokenize.TokenError,msg:
739 except tokenize.TokenError,msg:
734 _m = ("An unexpected error occurred while tokenizing input\n"
740 _m = ("An unexpected error occurred while tokenizing input\n"
735 "The following traceback may be corrupted or invalid\n"
741 "The following traceback may be corrupted or invalid\n"
736 "The error message is: %s\n" % msg)
742 "The error message is: %s\n" % msg)
737 error(_m)
743 error(_m)
738
744
739 # prune names list of duplicates, but keep the right order
745 # prune names list of duplicates, but keep the right order
740 unique_names = uniq_stable(names)
746 unique_names = uniq_stable(names)
741
747
742 # Start loop over vars
748 # Start loop over vars
743 lvals = []
749 lvals = []
744 if self.include_vars:
750 if self.include_vars:
745 for name_full in unique_names:
751 for name_full in unique_names:
746 name_base = name_full.split('.',1)[0]
752 name_base = name_full.split('.',1)[0]
747 if name_base in frame.f_code.co_varnames:
753 if name_base in frame.f_code.co_varnames:
748 if locals.has_key(name_base):
754 if locals.has_key(name_base):
749 try:
755 try:
750 value = repr(eval(name_full,locals))
756 value = repr(eval(name_full,locals))
751 except:
757 except:
752 value = undefined
758 value = undefined
753 else:
759 else:
754 value = undefined
760 value = undefined
755 name = tpl_local_var % name_full
761 name = tpl_local_var % name_full
756 else:
762 else:
757 if frame.f_globals.has_key(name_base):
763 if frame.f_globals.has_key(name_base):
758 try:
764 try:
759 value = repr(eval(name_full,frame.f_globals))
765 value = repr(eval(name_full,frame.f_globals))
760 except:
766 except:
761 value = undefined
767 value = undefined
762 else:
768 else:
763 value = undefined
769 value = undefined
764 name = tpl_global_var % name_full
770 name = tpl_global_var % name_full
765 lvals.append(tpl_name_val % (name,value))
771 lvals.append(tpl_name_val % (name,value))
766 if lvals:
772 if lvals:
767 lvals = '%s%s' % (indent,em_normal.join(lvals))
773 lvals = '%s%s' % (indent,em_normal.join(lvals))
768 else:
774 else:
769 lvals = ''
775 lvals = ''
770
776
771 level = '%s %s\n' % (link,call)
777 level = '%s %s\n' % (link,call)
772
778
773 if index is None:
779 if index is None:
774 frames.append(level)
780 frames.append(level)
775 else:
781 else:
776 frames.append('%s%s' % (level,''.join(
782 frames.append('%s%s' % (level,''.join(
777 _formatTracebackLines(lnum,index,lines,Colors,lvals,
783 _formatTracebackLines(lnum,index,lines,Colors,lvals,
778 col_scheme))))
784 col_scheme))))
779
785
780 # Get (safely) a string form of the exception info
786 # Get (safely) a string form of the exception info
781 try:
787 try:
782 etype_str,evalue_str = map(str,(etype,evalue))
788 etype_str,evalue_str = map(str,(etype,evalue))
783 except:
789 except:
784 # User exception is improperly defined.
790 # User exception is improperly defined.
785 etype,evalue = str,sys.exc_info()[:2]
791 etype,evalue = str,sys.exc_info()[:2]
786 etype_str,evalue_str = map(str,(etype,evalue))
792 etype_str,evalue_str = map(str,(etype,evalue))
787 # ... and format it
793 # ... and format it
788 exception = ['%s%s%s: %s' % (Colors.excName, etype_str,
794 exception = ['%s%s%s: %s' % (Colors.excName, etype_str,
789 ColorsNormal, evalue_str)]
795 ColorsNormal, evalue_str)]
790 if type(evalue) is types.InstanceType:
796 if type(evalue) is types.InstanceType:
791 try:
797 try:
792 names = [w for w in dir(evalue) if isinstance(w, basestring)]
798 names = [w for w in dir(evalue) if isinstance(w, basestring)]
793 except:
799 except:
794 # Every now and then, an object with funny inernals blows up
800 # Every now and then, an object with funny inernals blows up
795 # when dir() is called on it. We do the best we can to report
801 # when dir() is called on it. We do the best we can to report
796 # the problem and continue
802 # the problem and continue
797 _m = '%sException reporting error (object with broken dir())%s:'
803 _m = '%sException reporting error (object with broken dir())%s:'
798 exception.append(_m % (Colors.excName,ColorsNormal))
804 exception.append(_m % (Colors.excName,ColorsNormal))
799 etype_str,evalue_str = map(str,sys.exc_info()[:2])
805 etype_str,evalue_str = map(str,sys.exc_info()[:2])
800 exception.append('%s%s%s: %s' % (Colors.excName,etype_str,
806 exception.append('%s%s%s: %s' % (Colors.excName,etype_str,
801 ColorsNormal, evalue_str))
807 ColorsNormal, evalue_str))
802 names = []
808 names = []
803 for name in names:
809 for name in names:
804 value = text_repr(getattr(evalue, name))
810 value = text_repr(getattr(evalue, name))
805 exception.append('\n%s%s = %s' % (indent, name, value))
811 exception.append('\n%s%s = %s' % (indent, name, value))
806
812
807 # vds: >>
813 # This is being commented out for now as the __IPYTHON__ variable
808 if records:
814 # referenced here is not resolved and causes massive test failures
809 filepath, lnum = records[-1][1:3]
815 # and errors. B. Granger, 04/2009. XXX
810 #print "file:", str(file), "linenb", str(lnum) # dbg
816 # See https://bugs.launchpad.net/bugs/362137
811 filepath = os.path.abspath(filepath)
817 # # vds: >>
812 __IPYTHON__.hooks.synchronize_with_editor(filepath, lnum, 0)
818 # if records:
813 # vds: <<
819 # filepath, lnum = records[-1][1:3]
820 # #print "file:", str(file), "linenb", str(lnum) # dbg
821 # filepath = os.path.abspath(filepath)
822 # __IPYTHON__.hooks.synchronize_with_editor(filepath, lnum, 0)
823 # # vds: <<
814
824
815 # return all our info assembled as a single string
825 # return all our info assembled as a single string
816 return '%s\n\n%s\n%s' % (head,'\n'.join(frames),''.join(exception[0]) )
826 return '%s\n\n%s\n%s' % (head,'\n'.join(frames),''.join(exception[0]) )
817
827
818 def debugger(self,force=False):
828 def debugger(self,force=False):
819 """Call up the pdb debugger if desired, always clean up the tb
829 """Call up the pdb debugger if desired, always clean up the tb
820 reference.
830 reference.
821
831
822 Keywords:
832 Keywords:
823
833
824 - force(False): by default, this routine checks the instance call_pdb
834 - force(False): by default, this routine checks the instance call_pdb
825 flag and does not actually invoke the debugger if the flag is false.
835 flag and does not actually invoke the debugger if the flag is false.
826 The 'force' option forces the debugger to activate even if the flag
836 The 'force' option forces the debugger to activate even if the flag
827 is false.
837 is false.
828
838
829 If the call_pdb flag is set, the pdb interactive debugger is
839 If the call_pdb flag is set, the pdb interactive debugger is
830 invoked. In all cases, the self.tb reference to the current traceback
840 invoked. In all cases, the self.tb reference to the current traceback
831 is deleted to prevent lingering references which hamper memory
841 is deleted to prevent lingering references which hamper memory
832 management.
842 management.
833
843
834 Note that each call to pdb() does an 'import readline', so if your app
844 Note that each call to pdb() does an 'import readline', so if your app
835 requires a special setup for the readline completers, you'll have to
845 requires a special setup for the readline completers, you'll have to
836 fix that by hand after invoking the exception handler."""
846 fix that by hand after invoking the exception handler."""
837
847
838 if force or self.call_pdb:
848 if force or self.call_pdb:
839 if self.pdb is None:
849 if self.pdb is None:
840 self.pdb = Debugger.Pdb(
850 self.pdb = Debugger.Pdb(
841 self.color_scheme_table.active_scheme_name)
851 self.color_scheme_table.active_scheme_name)
842 # the system displayhook may have changed, restore the original
852 # the system displayhook may have changed, restore the original
843 # for pdb
853 # for pdb
844 dhook = sys.displayhook
854 dhook = sys.displayhook
845 sys.displayhook = sys.__displayhook__
855 sys.displayhook = sys.__displayhook__
846 self.pdb.reset()
856 self.pdb.reset()
847 # Find the right frame so we don't pop up inside ipython itself
857 # Find the right frame so we don't pop up inside ipython itself
848 if hasattr(self,'tb'):
858 if hasattr(self,'tb'):
849 etb = self.tb
859 etb = self.tb
850 else:
860 else:
851 etb = self.tb = sys.last_traceback
861 etb = self.tb = sys.last_traceback
852 while self.tb.tb_next is not None:
862 while self.tb.tb_next is not None:
853 self.tb = self.tb.tb_next
863 self.tb = self.tb.tb_next
854 try:
864 try:
855 if etb and etb.tb_next:
865 if etb and etb.tb_next:
856 etb = etb.tb_next
866 etb = etb.tb_next
857 self.pdb.botframe = etb.tb_frame
867 self.pdb.botframe = etb.tb_frame
858 self.pdb.interaction(self.tb.tb_frame, self.tb)
868 self.pdb.interaction(self.tb.tb_frame, self.tb)
859 finally:
869 finally:
860 sys.displayhook = dhook
870 sys.displayhook = dhook
861
871
862 if hasattr(self,'tb'):
872 if hasattr(self,'tb'):
863 del self.tb
873 del self.tb
864
874
865 def handler(self, info=None):
875 def handler(self, info=None):
866 (etype, evalue, etb) = info or sys.exc_info()
876 (etype, evalue, etb) = info or sys.exc_info()
867 self.tb = etb
877 self.tb = etb
868 Term.cout.flush()
878 Term.cout.flush()
869 print >> Term.cerr, self.text(etype, evalue, etb)
879 print >> Term.cerr, self.text(etype, evalue, etb)
870 Term.cerr.flush()
880 Term.cerr.flush()
871
881
872 # Changed so an instance can just be called as VerboseTB_inst() and print
882 # Changed so an instance can just be called as VerboseTB_inst() and print
873 # out the right info on its own.
883 # out the right info on its own.
874 def __call__(self, etype=None, evalue=None, etb=None):
884 def __call__(self, etype=None, evalue=None, etb=None):
875 """This hook can replace sys.excepthook (for Python 2.1 or higher)."""
885 """This hook can replace sys.excepthook (for Python 2.1 or higher)."""
876 if etb is None:
886 if etb is None:
877 self.handler()
887 self.handler()
878 else:
888 else:
879 self.handler((etype, evalue, etb))
889 self.handler((etype, evalue, etb))
880 try:
890 try:
881 self.debugger()
891 self.debugger()
882 except KeyboardInterrupt:
892 except KeyboardInterrupt:
883 print "\nKeyboardInterrupt"
893 print "\nKeyboardInterrupt"
884
894
885 #----------------------------------------------------------------------------
895 #----------------------------------------------------------------------------
886 class FormattedTB(VerboseTB,ListTB):
896 class FormattedTB(VerboseTB,ListTB):
887 """Subclass ListTB but allow calling with a traceback.
897 """Subclass ListTB but allow calling with a traceback.
888
898
889 It can thus be used as a sys.excepthook for Python > 2.1.
899 It can thus be used as a sys.excepthook for Python > 2.1.
890
900
891 Also adds 'Context' and 'Verbose' modes, not available in ListTB.
901 Also adds 'Context' and 'Verbose' modes, not available in ListTB.
892
902
893 Allows a tb_offset to be specified. This is useful for situations where
903 Allows a tb_offset to be specified. This is useful for situations where
894 one needs to remove a number of topmost frames from the traceback (such as
904 one needs to remove a number of topmost frames from the traceback (such as
895 occurs with python programs that themselves execute other python code,
905 occurs with python programs that themselves execute other python code,
896 like Python shells). """
906 like Python shells). """
897
907
898 def __init__(self, mode = 'Plain', color_scheme='Linux',
908 def __init__(self, mode = 'Plain', color_scheme='Linux',
899 tb_offset = 0,long_header=0,call_pdb=0,include_vars=0):
909 tb_offset = 0,long_header=0,call_pdb=0,include_vars=0):
900
910
901 # NEVER change the order of this list. Put new modes at the end:
911 # NEVER change the order of this list. Put new modes at the end:
902 self.valid_modes = ['Plain','Context','Verbose']
912 self.valid_modes = ['Plain','Context','Verbose']
903 self.verbose_modes = self.valid_modes[1:3]
913 self.verbose_modes = self.valid_modes[1:3]
904
914
905 VerboseTB.__init__(self,color_scheme,tb_offset,long_header,
915 VerboseTB.__init__(self,color_scheme,tb_offset,long_header,
906 call_pdb=call_pdb,include_vars=include_vars)
916 call_pdb=call_pdb,include_vars=include_vars)
907 self.set_mode(mode)
917 self.set_mode(mode)
908
918
909 def _extract_tb(self,tb):
919 def _extract_tb(self,tb):
910 if tb:
920 if tb:
911 return traceback.extract_tb(tb)
921 return traceback.extract_tb(tb)
912 else:
922 else:
913 return None
923 return None
914
924
915 def text(self, etype, value, tb,context=5,mode=None):
925 def text(self, etype, value, tb,context=5,mode=None):
916 """Return formatted traceback.
926 """Return formatted traceback.
917
927
918 If the optional mode parameter is given, it overrides the current
928 If the optional mode parameter is given, it overrides the current
919 mode."""
929 mode."""
920
930
921 if mode is None:
931 if mode is None:
922 mode = self.mode
932 mode = self.mode
923 if mode in self.verbose_modes:
933 if mode in self.verbose_modes:
924 # verbose modes need a full traceback
934 # verbose modes need a full traceback
925 return VerboseTB.text(self,etype, value, tb,context=5)
935 return VerboseTB.text(self,etype, value, tb,context=5)
926 else:
936 else:
927 # We must check the source cache because otherwise we can print
937 # We must check the source cache because otherwise we can print
928 # out-of-date source code.
938 # out-of-date source code.
929 linecache.checkcache()
939 linecache.checkcache()
930 # Now we can extract and format the exception
940 # Now we can extract and format the exception
931 elist = self._extract_tb(tb)
941 elist = self._extract_tb(tb)
932 if len(elist) > self.tb_offset:
942 if len(elist) > self.tb_offset:
933 del elist[:self.tb_offset]
943 del elist[:self.tb_offset]
934 return ListTB.text(self,etype,value,elist)
944 return ListTB.text(self,etype,value,elist)
935
945
936 def set_mode(self,mode=None):
946 def set_mode(self,mode=None):
937 """Switch to the desired mode.
947 """Switch to the desired mode.
938
948
939 If mode is not specified, cycles through the available modes."""
949 If mode is not specified, cycles through the available modes."""
940
950
941 if not mode:
951 if not mode:
942 new_idx = ( self.valid_modes.index(self.mode) + 1 ) % \
952 new_idx = ( self.valid_modes.index(self.mode) + 1 ) % \
943 len(self.valid_modes)
953 len(self.valid_modes)
944 self.mode = self.valid_modes[new_idx]
954 self.mode = self.valid_modes[new_idx]
945 elif mode not in self.valid_modes:
955 elif mode not in self.valid_modes:
946 raise ValueError, 'Unrecognized mode in FormattedTB: <'+mode+'>\n'\
956 raise ValueError, 'Unrecognized mode in FormattedTB: <'+mode+'>\n'\
947 'Valid modes: '+str(self.valid_modes)
957 'Valid modes: '+str(self.valid_modes)
948 else:
958 else:
949 self.mode = mode
959 self.mode = mode
950 # include variable details only in 'Verbose' mode
960 # include variable details only in 'Verbose' mode
951 self.include_vars = (self.mode == self.valid_modes[2])
961 self.include_vars = (self.mode == self.valid_modes[2])
952
962
953 # some convenient shorcuts
963 # some convenient shorcuts
954 def plain(self):
964 def plain(self):
955 self.set_mode(self.valid_modes[0])
965 self.set_mode(self.valid_modes[0])
956
966
957 def context(self):
967 def context(self):
958 self.set_mode(self.valid_modes[1])
968 self.set_mode(self.valid_modes[1])
959
969
960 def verbose(self):
970 def verbose(self):
961 self.set_mode(self.valid_modes[2])
971 self.set_mode(self.valid_modes[2])
962
972
963 #----------------------------------------------------------------------------
973 #----------------------------------------------------------------------------
964 class AutoFormattedTB(FormattedTB):
974 class AutoFormattedTB(FormattedTB):
965 """A traceback printer which can be called on the fly.
975 """A traceback printer which can be called on the fly.
966
976
967 It will find out about exceptions by itself.
977 It will find out about exceptions by itself.
968
978
969 A brief example:
979 A brief example:
970
980
971 AutoTB = AutoFormattedTB(mode = 'Verbose',color_scheme='Linux')
981 AutoTB = AutoFormattedTB(mode = 'Verbose',color_scheme='Linux')
972 try:
982 try:
973 ...
983 ...
974 except:
984 except:
975 AutoTB() # or AutoTB(out=logfile) where logfile is an open file object
985 AutoTB() # or AutoTB(out=logfile) where logfile is an open file object
976 """
986 """
977 def __call__(self,etype=None,evalue=None,etb=None,
987 def __call__(self,etype=None,evalue=None,etb=None,
978 out=None,tb_offset=None):
988 out=None,tb_offset=None):
979 """Print out a formatted exception traceback.
989 """Print out a formatted exception traceback.
980
990
981 Optional arguments:
991 Optional arguments:
982 - out: an open file-like object to direct output to.
992 - out: an open file-like object to direct output to.
983
993
984 - tb_offset: the number of frames to skip over in the stack, on a
994 - tb_offset: the number of frames to skip over in the stack, on a
985 per-call basis (this overrides temporarily the instance's tb_offset
995 per-call basis (this overrides temporarily the instance's tb_offset
986 given at initialization time. """
996 given at initialization time. """
987
997
988 if out is None:
998 if out is None:
989 out = Term.cerr
999 out = Term.cerr
990 Term.cout.flush()
1000 Term.cout.flush()
991 if tb_offset is not None:
1001 if tb_offset is not None:
992 tb_offset, self.tb_offset = self.tb_offset, tb_offset
1002 tb_offset, self.tb_offset = self.tb_offset, tb_offset
993 print >> out, self.text(etype, evalue, etb)
1003 print >> out, self.text(etype, evalue, etb)
994 self.tb_offset = tb_offset
1004 self.tb_offset = tb_offset
995 else:
1005 else:
996 print >> out, self.text(etype, evalue, etb)
1006 print >> out, self.text(etype, evalue, etb)
997 out.flush()
1007 out.flush()
998 try:
1008 try:
999 self.debugger()
1009 self.debugger()
1000 except KeyboardInterrupt:
1010 except KeyboardInterrupt:
1001 print "\nKeyboardInterrupt"
1011 print "\nKeyboardInterrupt"
1002
1012
1003 def text(self,etype=None,value=None,tb=None,context=5,mode=None):
1013 def text(self,etype=None,value=None,tb=None,context=5,mode=None):
1004 if etype is None:
1014 if etype is None:
1005 etype,value,tb = sys.exc_info()
1015 etype,value,tb = sys.exc_info()
1006 self.tb = tb
1016 self.tb = tb
1007 return FormattedTB.text(self,etype,value,tb,context=5,mode=mode)
1017 return FormattedTB.text(self,etype,value,tb,context=5,mode=mode)
1008
1018
1009 #---------------------------------------------------------------------------
1019 #---------------------------------------------------------------------------
1010 # A simple class to preserve Nathan's original functionality.
1020 # A simple class to preserve Nathan's original functionality.
1011 class ColorTB(FormattedTB):
1021 class ColorTB(FormattedTB):
1012 """Shorthand to initialize a FormattedTB in Linux colors mode."""
1022 """Shorthand to initialize a FormattedTB in Linux colors mode."""
1013 def __init__(self,color_scheme='Linux',call_pdb=0):
1023 def __init__(self,color_scheme='Linux',call_pdb=0):
1014 FormattedTB.__init__(self,color_scheme=color_scheme,
1024 FormattedTB.__init__(self,color_scheme=color_scheme,
1015 call_pdb=call_pdb)
1025 call_pdb=call_pdb)
1016
1026
1017 #----------------------------------------------------------------------------
1027 #----------------------------------------------------------------------------
1018 # module testing (minimal)
1028 # module testing (minimal)
1019 if __name__ == "__main__":
1029 if __name__ == "__main__":
1020 def spam(c, (d, e)):
1030 def spam(c, (d, e)):
1021 x = c + d
1031 x = c + d
1022 y = c * d
1032 y = c * d
1023 foo(x, y)
1033 foo(x, y)
1024
1034
1025 def foo(a, b, bar=1):
1035 def foo(a, b, bar=1):
1026 eggs(a, b + bar)
1036 eggs(a, b + bar)
1027
1037
1028 def eggs(f, g, z=globals()):
1038 def eggs(f, g, z=globals()):
1029 h = f + g
1039 h = f + g
1030 i = f - g
1040 i = f - g
1031 return h / i
1041 return h / i
1032
1042
1033 print ''
1043 print ''
1034 print '*** Before ***'
1044 print '*** Before ***'
1035 try:
1045 try:
1036 print spam(1, (2, 3))
1046 print spam(1, (2, 3))
1037 except:
1047 except:
1038 traceback.print_exc()
1048 traceback.print_exc()
1039 print ''
1049 print ''
1040
1050
1041 handler = ColorTB()
1051 handler = ColorTB()
1042 print '*** ColorTB ***'
1052 print '*** ColorTB ***'
1043 try:
1053 try:
1044 print spam(1, (2, 3))
1054 print spam(1, (2, 3))
1045 except:
1055 except:
1046 apply(handler, sys.exc_info() )
1056 apply(handler, sys.exc_info() )
1047 print ''
1057 print ''
1048
1058
1049 handler = VerboseTB()
1059 handler = VerboseTB()
1050 print '*** VerboseTB ***'
1060 print '*** VerboseTB ***'
1051 try:
1061 try:
1052 print spam(1, (2, 3))
1062 print spam(1, (2, 3))
1053 except:
1063 except:
1054 apply(handler, sys.exc_info() )
1064 apply(handler, sys.exc_info() )
1055 print ''
1065 print ''
1056
1066
@@ -1,92 +1,92 b''
1 # encoding: utf-8
1 # encoding: utf-8
2
2
3 """A class that manages the engines connection to the controller."""
3 """A class that manages the engines connection to the controller."""
4
4
5 __docformat__ = "restructuredtext en"
5 __docformat__ = "restructuredtext en"
6
6
7 #-------------------------------------------------------------------------------
7 #-------------------------------------------------------------------------------
8 # Copyright (C) 2008 The IPython Development Team
8 # Copyright (C) 2008 The IPython Development Team
9 #
9 #
10 # Distributed under the terms of the BSD License. The full license is in
10 # Distributed under the terms of the BSD License. The full license is in
11 # the file COPYING, distributed as part of this software.
11 # the file COPYING, distributed as part of this software.
12 #-------------------------------------------------------------------------------
12 #-------------------------------------------------------------------------------
13
13
14 #-------------------------------------------------------------------------------
14 #-------------------------------------------------------------------------------
15 # Imports
15 # Imports
16 #-------------------------------------------------------------------------------
16 #-------------------------------------------------------------------------------
17
17
18 import os
18 import os
19 import cPickle as pickle
19 import cPickle as pickle
20
20
21 from twisted.python import log, failure
21 from twisted.python import log, failure
22 from twisted.internet import defer
22 from twisted.internet import defer
23
23
24 from IPython.kernel.fcutil import find_furl
24 from IPython.kernel.fcutil import find_furl
25 from IPython.kernel.enginefc import IFCEngine
25 from IPython.kernel.enginefc import IFCEngine
26
26
27 #-------------------------------------------------------------------------------
27 #-------------------------------------------------------------------------------
28 # The ClientConnector class
28 # The ClientConnector class
29 #-------------------------------------------------------------------------------
29 #-------------------------------------------------------------------------------
30
30
31 class EngineConnector(object):
31 class EngineConnector(object):
32 """Manage an engines connection to a controller.
32 """Manage an engines connection to a controller.
33
33
34 This class takes a foolscap `Tub` and provides a `connect_to_controller`
34 This class takes a foolscap `Tub` and provides a `connect_to_controller`
35 method that will use the `Tub` to connect to a controller and register
35 method that will use the `Tub` to connect to a controller and register
36 the engine with the controller.
36 the engine with the controller.
37 """
37 """
38
38
39 def __init__(self, tub):
39 def __init__(self, tub):
40 self.tub = tub
40 self.tub = tub
41
41
42 def connect_to_controller(self, engine_service, furl_or_file):
42 def connect_to_controller(self, engine_service, furl_or_file):
43 """
43 """
44 Make a connection to a controller specified by a furl.
44 Make a connection to a controller specified by a furl.
45
45
46 This method takes an `IEngineBase` instance and a foolcap URL and uses
46 This method takes an `IEngineBase` instance and a foolcap URL and uses
47 the `tub` attribute to make a connection to the controller. The
47 the `tub` attribute to make a connection to the controller. The
48 foolscap URL contains all the information needed to connect to the
48 foolscap URL contains all the information needed to connect to the
49 controller, including the ip and port as well as any encryption and
49 controller, including the ip and port as well as any encryption and
50 authentication information needed for the connection.
50 authentication information needed for the connection.
51
51
52 After getting a reference to the controller, this method calls the
52 After getting a reference to the controller, this method calls the
53 `register_engine` method of the controller to actually register the
53 `register_engine` method of the controller to actually register the
54 engine.
54 engine.
55
55
56 :Parameters:
56 :Parameters:
57 engine_service : IEngineBase
57 engine_service : IEngineBase
58 An instance of an `IEngineBase` implementer
58 An instance of an `IEngineBase` implementer
59 furl_or_file : str
59 furl_or_file : str
60 A furl or a filename containing a furl
60 A furl or a filename containing a furl
61 """
61 """
62 if not self.tub.running:
62 if not self.tub.running:
63 self.tub.startService()
63 self.tub.startService()
64 self.engine_service = engine_service
64 self.engine_service = engine_service
65 self.engine_reference = IFCEngine(self.engine_service)
65 self.engine_reference = IFCEngine(self.engine_service)
66 try:
66 try:
67 self.furl = find_furl(furl_or_file)
67 self.furl = find_furl(furl_or_file)
68 except ValueError:
68 except ValueError:
69 return defer.fail(failure.Failure())
69 return defer.fail(failure.Failure())
70 # return defer.fail(failure.Failure(ValueError('not a valid furl or furl file: %r' % furl_or_file)))
70 else:
71 d = self.tub.getReference(self.furl)
71 d = self.tub.getReference(self.furl)
72 d.addCallbacks(self._register, self._log_failure)
72 d.addCallbacks(self._register, self._log_failure)
73 return d
73 return d
74
74
75 def _log_failure(self, reason):
75 def _log_failure(self, reason):
76 log.err('EngineConnector: engine registration failed:')
76 log.err('EngineConnector: engine registration failed:')
77 log.err(reason)
77 log.err(reason)
78 return reason
78 return reason
79
79
80 def _register(self, rr):
80 def _register(self, rr):
81 self.remote_ref = rr
81 self.remote_ref = rr
82 # Now register myself with the controller
82 # Now register myself with the controller
83 desired_id = self.engine_service.id
83 desired_id = self.engine_service.id
84 d = self.remote_ref.callRemote('register_engine', self.engine_reference,
84 d = self.remote_ref.callRemote('register_engine', self.engine_reference,
85 desired_id, os.getpid(), pickle.dumps(self.engine_service.properties,2))
85 desired_id, os.getpid(), pickle.dumps(self.engine_service.properties,2))
86 return d.addCallbacks(self._reference_sent, self._log_failure)
86 return d.addCallbacks(self._reference_sent, self._log_failure)
87
87
88 def _reference_sent(self, registration_dict):
88 def _reference_sent(self, registration_dict):
89 self.engine_service.id = registration_dict['id']
89 self.engine_service.id = registration_dict['id']
90 log.msg("engine registration succeeded, got id: %r" % self.engine_service.id)
90 log.msg("engine registration succeeded, got id: %r" % self.engine_service.id)
91 return self.engine_service.id
91 return self.engine_service.id
92
92
@@ -1,903 +1,906 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 # -*- test-case-name: IPython.kernel.tests.test_engineservice -*-
2 # -*- test-case-name: IPython.kernel.tests.test_engineservice -*-
3
3
4 """A Twisted Service Representation of the IPython core.
4 """A Twisted Service Representation of the IPython core.
5
5
6 The IPython Core exposed to the network is called the Engine. Its
6 The IPython Core exposed to the network is called the Engine. Its
7 representation in Twisted in the EngineService. Interfaces and adapters
7 representation in Twisted in the EngineService. Interfaces and adapters
8 are used to abstract out the details of the actual network protocol used.
8 are used to abstract out the details of the actual network protocol used.
9 The EngineService is an Engine that knows nothing about the actual protocol
9 The EngineService is an Engine that knows nothing about the actual protocol
10 used.
10 used.
11
11
12 The EngineService is exposed with various network protocols in modules like:
12 The EngineService is exposed with various network protocols in modules like:
13
13
14 enginepb.py
14 enginepb.py
15 enginevanilla.py
15 enginevanilla.py
16
16
17 As of 12/12/06 the classes in this module have been simplified greatly. It was
17 As of 12/12/06 the classes in this module have been simplified greatly. It was
18 felt that we had over-engineered things. To improve the maintainability of the
18 felt that we had over-engineered things. To improve the maintainability of the
19 code we have taken out the ICompleteEngine interface and the completeEngine
19 code we have taken out the ICompleteEngine interface and the completeEngine
20 method that automatically added methods to engines.
20 method that automatically added methods to engines.
21
21
22 """
22 """
23
23
24 __docformat__ = "restructuredtext en"
24 __docformat__ = "restructuredtext en"
25
25
26 #-------------------------------------------------------------------------------
26 #-------------------------------------------------------------------------------
27 # Copyright (C) 2008 The IPython Development Team
27 # Copyright (C) 2008 The IPython Development Team
28 #
28 #
29 # Distributed under the terms of the BSD License. The full license is in
29 # Distributed under the terms of the BSD License. The full license is in
30 # the file COPYING, distributed as part of this software.
30 # the file COPYING, distributed as part of this software.
31 #-------------------------------------------------------------------------------
31 #-------------------------------------------------------------------------------
32
32
33 #-------------------------------------------------------------------------------
33 #-------------------------------------------------------------------------------
34 # Imports
34 # Imports
35 #-------------------------------------------------------------------------------
35 #-------------------------------------------------------------------------------
36
36
37 # Tell nose to skip the testing of this module
38 __test__ = {}
39
37 import os, sys, copy
40 import os, sys, copy
38 import cPickle as pickle
41 import cPickle as pickle
39 from new import instancemethod
42 from new import instancemethod
40
43
41 from twisted.application import service
44 from twisted.application import service
42 from twisted.internet import defer, reactor
45 from twisted.internet import defer, reactor
43 from twisted.python import log, failure, components
46 from twisted.python import log, failure, components
44 import zope.interface as zi
47 import zope.interface as zi
45
48
46 from IPython.kernel.core.interpreter import Interpreter
49 from IPython.kernel.core.interpreter import Interpreter
47 from IPython.kernel import newserialized, error, util
50 from IPython.kernel import newserialized, error, util
48 from IPython.kernel.util import printer
51 from IPython.kernel.util import printer
49 from IPython.kernel.twistedutil import gatherBoth, DeferredList
52 from IPython.kernel.twistedutil import gatherBoth, DeferredList
50 from IPython.kernel import codeutil
53 from IPython.kernel import codeutil
51
54
52
55
53 #-------------------------------------------------------------------------------
56 #-------------------------------------------------------------------------------
54 # Interface specification for the Engine
57 # Interface specification for the Engine
55 #-------------------------------------------------------------------------------
58 #-------------------------------------------------------------------------------
56
59
57 class IEngineCore(zi.Interface):
60 class IEngineCore(zi.Interface):
58 """The minimal required interface for the IPython Engine.
61 """The minimal required interface for the IPython Engine.
59
62
60 This interface provides a formal specification of the IPython core.
63 This interface provides a formal specification of the IPython core.
61 All these methods should return deferreds regardless of what side of a
64 All these methods should return deferreds regardless of what side of a
62 network connection they are on.
65 network connection they are on.
63
66
64 In general, this class simply wraps a shell class and wraps its return
67 In general, this class simply wraps a shell class and wraps its return
65 values as Deferred objects. If the underlying shell class method raises
68 values as Deferred objects. If the underlying shell class method raises
66 an exception, this class should convert it to a twisted.failure.Failure
69 an exception, this class should convert it to a twisted.failure.Failure
67 that will be propagated along the Deferred's errback chain.
70 that will be propagated along the Deferred's errback chain.
68
71
69 In addition, Failures are aggressive. By this, we mean that if a method
72 In addition, Failures are aggressive. By this, we mean that if a method
70 is performing multiple actions (like pulling multiple object) if any
73 is performing multiple actions (like pulling multiple object) if any
71 single one fails, the entire method will fail with that Failure. It is
74 single one fails, the entire method will fail with that Failure. It is
72 all or nothing.
75 all or nothing.
73 """
76 """
74
77
75 id = zi.interface.Attribute("the id of the Engine object")
78 id = zi.interface.Attribute("the id of the Engine object")
76 properties = zi.interface.Attribute("A dict of properties of the Engine")
79 properties = zi.interface.Attribute("A dict of properties of the Engine")
77
80
78 def execute(lines):
81 def execute(lines):
79 """Execute lines of Python code.
82 """Execute lines of Python code.
80
83
81 Returns a dictionary with keys (id, number, stdin, stdout, stderr)
84 Returns a dictionary with keys (id, number, stdin, stdout, stderr)
82 upon success.
85 upon success.
83
86
84 Returns a failure object if the execution of lines raises an exception.
87 Returns a failure object if the execution of lines raises an exception.
85 """
88 """
86
89
87 def push(namespace):
90 def push(namespace):
88 """Push dict namespace into the user's namespace.
91 """Push dict namespace into the user's namespace.
89
92
90 Returns a deferred to None or a failure.
93 Returns a deferred to None or a failure.
91 """
94 """
92
95
93 def pull(keys):
96 def pull(keys):
94 """Pulls values out of the user's namespace by keys.
97 """Pulls values out of the user's namespace by keys.
95
98
96 Returns a deferred to a tuple objects or a single object.
99 Returns a deferred to a tuple objects or a single object.
97
100
98 Raises NameError if any one of objects doess not exist.
101 Raises NameError if any one of objects doess not exist.
99 """
102 """
100
103
101 def push_function(namespace):
104 def push_function(namespace):
102 """Push a dict of key, function pairs into the user's namespace.
105 """Push a dict of key, function pairs into the user's namespace.
103
106
104 Returns a deferred to None or a failure."""
107 Returns a deferred to None or a failure."""
105
108
106 def pull_function(keys):
109 def pull_function(keys):
107 """Pulls functions out of the user's namespace by keys.
110 """Pulls functions out of the user's namespace by keys.
108
111
109 Returns a deferred to a tuple of functions or a single function.
112 Returns a deferred to a tuple of functions or a single function.
110
113
111 Raises NameError if any one of the functions does not exist.
114 Raises NameError if any one of the functions does not exist.
112 """
115 """
113
116
114 def get_result(i=None):
117 def get_result(i=None):
115 """Get the stdin/stdout/stderr of command i.
118 """Get the stdin/stdout/stderr of command i.
116
119
117 Returns a deferred to a dict with keys
120 Returns a deferred to a dict with keys
118 (id, number, stdin, stdout, stderr).
121 (id, number, stdin, stdout, stderr).
119
122
120 Raises IndexError if command i does not exist.
123 Raises IndexError if command i does not exist.
121 Raises TypeError if i in not an int.
124 Raises TypeError if i in not an int.
122 """
125 """
123
126
124 def reset():
127 def reset():
125 """Reset the shell.
128 """Reset the shell.
126
129
127 This clears the users namespace. Won't cause modules to be
130 This clears the users namespace. Won't cause modules to be
128 reloaded. Should also re-initialize certain variables like id.
131 reloaded. Should also re-initialize certain variables like id.
129 """
132 """
130
133
131 def kill():
134 def kill():
132 """Kill the engine by stopping the reactor."""
135 """Kill the engine by stopping the reactor."""
133
136
134 def keys():
137 def keys():
135 """Return the top level variables in the users namspace.
138 """Return the top level variables in the users namspace.
136
139
137 Returns a deferred to a dict."""
140 Returns a deferred to a dict."""
138
141
139
142
140 class IEngineSerialized(zi.Interface):
143 class IEngineSerialized(zi.Interface):
141 """Push/Pull methods that take Serialized objects.
144 """Push/Pull methods that take Serialized objects.
142
145
143 All methods should return deferreds.
146 All methods should return deferreds.
144 """
147 """
145
148
146 def push_serialized(namespace):
149 def push_serialized(namespace):
147 """Push a dict of keys and Serialized objects into the user's namespace."""
150 """Push a dict of keys and Serialized objects into the user's namespace."""
148
151
149 def pull_serialized(keys):
152 def pull_serialized(keys):
150 """Pull objects by key from the user's namespace as Serialized.
153 """Pull objects by key from the user's namespace as Serialized.
151
154
152 Returns a list of or one Serialized.
155 Returns a list of or one Serialized.
153
156
154 Raises NameError is any one of the objects does not exist.
157 Raises NameError is any one of the objects does not exist.
155 """
158 """
156
159
157
160
158 class IEngineProperties(zi.Interface):
161 class IEngineProperties(zi.Interface):
159 """Methods for access to the properties object of an Engine"""
162 """Methods for access to the properties object of an Engine"""
160
163
161 properties = zi.Attribute("A StrictDict object, containing the properties")
164 properties = zi.Attribute("A StrictDict object, containing the properties")
162
165
163 def set_properties(properties):
166 def set_properties(properties):
164 """set properties by key and value"""
167 """set properties by key and value"""
165
168
166 def get_properties(keys=None):
169 def get_properties(keys=None):
167 """get a list of properties by `keys`, if no keys specified, get all"""
170 """get a list of properties by `keys`, if no keys specified, get all"""
168
171
169 def del_properties(keys):
172 def del_properties(keys):
170 """delete properties by `keys`"""
173 """delete properties by `keys`"""
171
174
172 def has_properties(keys):
175 def has_properties(keys):
173 """get a list of bool values for whether `properties` has `keys`"""
176 """get a list of bool values for whether `properties` has `keys`"""
174
177
175 def clear_properties():
178 def clear_properties():
176 """clear the properties dict"""
179 """clear the properties dict"""
177
180
178 class IEngineBase(IEngineCore, IEngineSerialized, IEngineProperties):
181 class IEngineBase(IEngineCore, IEngineSerialized, IEngineProperties):
179 """The basic engine interface that EngineService will implement.
182 """The basic engine interface that EngineService will implement.
180
183
181 This exists so it is easy to specify adapters that adapt to and from the
184 This exists so it is easy to specify adapters that adapt to and from the
182 API that the basic EngineService implements.
185 API that the basic EngineService implements.
183 """
186 """
184 pass
187 pass
185
188
186 class IEngineQueued(IEngineBase):
189 class IEngineQueued(IEngineBase):
187 """Interface for adding a queue to an IEngineBase.
190 """Interface for adding a queue to an IEngineBase.
188
191
189 This interface extends the IEngineBase interface to add methods for managing
192 This interface extends the IEngineBase interface to add methods for managing
190 the engine's queue. The implicit details of this interface are that the
193 the engine's queue. The implicit details of this interface are that the
191 execution of all methods declared in IEngineBase should appropriately be
194 execution of all methods declared in IEngineBase should appropriately be
192 put through a queue before execution.
195 put through a queue before execution.
193
196
194 All methods should return deferreds.
197 All methods should return deferreds.
195 """
198 """
196
199
197 def clear_queue():
200 def clear_queue():
198 """Clear the queue."""
201 """Clear the queue."""
199
202
200 def queue_status():
203 def queue_status():
201 """Get the queued and pending commands in the queue."""
204 """Get the queued and pending commands in the queue."""
202
205
203 def register_failure_observer(obs):
206 def register_failure_observer(obs):
204 """Register an observer of pending Failures.
207 """Register an observer of pending Failures.
205
208
206 The observer must implement IFailureObserver.
209 The observer must implement IFailureObserver.
207 """
210 """
208
211
209 def unregister_failure_observer(obs):
212 def unregister_failure_observer(obs):
210 """Unregister an observer of pending Failures."""
213 """Unregister an observer of pending Failures."""
211
214
212
215
213 class IEngineThreaded(zi.Interface):
216 class IEngineThreaded(zi.Interface):
214 """A place holder for threaded commands.
217 """A place holder for threaded commands.
215
218
216 All methods should return deferreds.
219 All methods should return deferreds.
217 """
220 """
218 pass
221 pass
219
222
220
223
221 #-------------------------------------------------------------------------------
224 #-------------------------------------------------------------------------------
222 # Functions and classes to implement the EngineService
225 # Functions and classes to implement the EngineService
223 #-------------------------------------------------------------------------------
226 #-------------------------------------------------------------------------------
224
227
225
228
226 class StrictDict(dict):
229 class StrictDict(dict):
227 """This is a strict copying dictionary for use as the interface to the
230 """This is a strict copying dictionary for use as the interface to the
228 properties of an Engine.
231 properties of an Engine.
229
232
230 :IMPORTANT:
233 :IMPORTANT:
231 This object copies the values you set to it, and returns copies to you
234 This object copies the values you set to it, and returns copies to you
232 when you request them. The only way to change properties os explicitly
235 when you request them. The only way to change properties os explicitly
233 through the setitem and getitem of the dictionary interface.
236 through the setitem and getitem of the dictionary interface.
234
237
235 Example:
238 Example:
236 >>> e = get_engine(id)
239 >>> e = get_engine(id)
237 >>> L = [1,2,3]
240 >>> L = [1,2,3]
238 >>> e.properties['L'] = L
241 >>> e.properties['L'] = L
239 >>> L == e.properties['L']
242 >>> L == e.properties['L']
240 True
243 True
241 >>> L.append(99)
244 >>> L.append(99)
242 >>> L == e.properties['L']
245 >>> L == e.properties['L']
243 False
246 False
244
247
245 Note that getitem copies, so calls to methods of objects do not affect
248 Note that getitem copies, so calls to methods of objects do not affect
246 the properties, as seen here:
249 the properties, as seen here:
247
250
248 >>> e.properties[1] = range(2)
251 >>> e.properties[1] = range(2)
249 >>> print e.properties[1]
252 >>> print e.properties[1]
250 [0, 1]
253 [0, 1]
251 >>> e.properties[1].append(2)
254 >>> e.properties[1].append(2)
252 >>> print e.properties[1]
255 >>> print e.properties[1]
253 [0, 1]
256 [0, 1]
254 """
257 """
255 def __init__(self, *args, **kwargs):
258 def __init__(self, *args, **kwargs):
256 dict.__init__(self, *args, **kwargs)
259 dict.__init__(self, *args, **kwargs)
257 self.modified = True
260 self.modified = True
258
261
259 def __getitem__(self, key):
262 def __getitem__(self, key):
260 return copy.deepcopy(dict.__getitem__(self, key))
263 return copy.deepcopy(dict.__getitem__(self, key))
261
264
262 def __setitem__(self, key, value):
265 def __setitem__(self, key, value):
263 # check if this entry is valid for transport around the network
266 # check if this entry is valid for transport around the network
264 # and copying
267 # and copying
265 try:
268 try:
266 pickle.dumps(key, 2)
269 pickle.dumps(key, 2)
267 pickle.dumps(value, 2)
270 pickle.dumps(value, 2)
268 newvalue = copy.deepcopy(value)
271 newvalue = copy.deepcopy(value)
269 except:
272 except Exception, e:
270 raise error.InvalidProperty(value)
273 raise error.InvalidProperty("can't be a value: %r" % value)
271 dict.__setitem__(self, key, newvalue)
274 dict.__setitem__(self, key, newvalue)
272 self.modified = True
275 self.modified = True
273
276
274 def __delitem__(self, key):
277 def __delitem__(self, key):
275 dict.__delitem__(self, key)
278 dict.__delitem__(self, key)
276 self.modified = True
279 self.modified = True
277
280
278 def update(self, dikt):
281 def update(self, dikt):
279 for k,v in dikt.iteritems():
282 for k,v in dikt.iteritems():
280 self[k] = v
283 self[k] = v
281
284
282 def pop(self, key):
285 def pop(self, key):
283 self.modified = True
286 self.modified = True
284 return dict.pop(self, key)
287 return dict.pop(self, key)
285
288
286 def popitem(self):
289 def popitem(self):
287 self.modified = True
290 self.modified = True
288 return dict.popitem(self)
291 return dict.popitem(self)
289
292
290 def clear(self):
293 def clear(self):
291 self.modified = True
294 self.modified = True
292 dict.clear(self)
295 dict.clear(self)
293
296
294 def subDict(self, *keys):
297 def subDict(self, *keys):
295 d = {}
298 d = {}
296 for key in keys:
299 for key in keys:
297 d[key] = self[key]
300 d[key] = self[key]
298 return d
301 return d
299
302
300
303
301
304
302 class EngineAPI(object):
305 class EngineAPI(object):
303 """This is the object through which the user can edit the `properties`
306 """This is the object through which the user can edit the `properties`
304 attribute of an Engine.
307 attribute of an Engine.
305 The Engine Properties object copies all object in and out of itself.
308 The Engine Properties object copies all object in and out of itself.
306 See the EngineProperties object for details.
309 See the EngineProperties object for details.
307 """
310 """
308 _fix=False
311 _fix=False
309 def __init__(self, id):
312 def __init__(self, id):
310 self.id = id
313 self.id = id
311 self.properties = StrictDict()
314 self.properties = StrictDict()
312 self._fix=True
315 self._fix=True
313
316
314 def __setattr__(self, k,v):
317 def __setattr__(self, k,v):
315 if self._fix:
318 if self._fix:
316 raise error.KernelError("I am protected!")
319 raise error.KernelError("I am protected!")
317 else:
320 else:
318 object.__setattr__(self, k, v)
321 object.__setattr__(self, k, v)
319
322
320 def __delattr__(self, key):
323 def __delattr__(self, key):
321 raise error.KernelError("I am protected!")
324 raise error.KernelError("I am protected!")
322
325
323
326
324 _apiDict = {}
327 _apiDict = {}
325
328
326 def get_engine(id):
329 def get_engine(id):
327 """Get the Engine API object, whcih currently just provides the properties
330 """Get the Engine API object, whcih currently just provides the properties
328 object, by ID"""
331 object, by ID"""
329 global _apiDict
332 global _apiDict
330 if not _apiDict.get(id):
333 if not _apiDict.get(id):
331 _apiDict[id] = EngineAPI(id)
334 _apiDict[id] = EngineAPI(id)
332 return _apiDict[id]
335 return _apiDict[id]
333
336
334 def drop_engine(id):
337 def drop_engine(id):
335 """remove an engine"""
338 """remove an engine"""
336 global _apiDict
339 global _apiDict
337 if _apiDict.has_key(id):
340 if _apiDict.has_key(id):
338 del _apiDict[id]
341 del _apiDict[id]
339
342
340 class EngineService(object, service.Service):
343 class EngineService(object, service.Service):
341 """Adapt a IPython shell into a IEngine implementing Twisted Service."""
344 """Adapt a IPython shell into a IEngine implementing Twisted Service."""
342
345
343 zi.implements(IEngineBase)
346 zi.implements(IEngineBase)
344 name = 'EngineService'
347 name = 'EngineService'
345
348
346 def __init__(self, shellClass=Interpreter, mpi=None):
349 def __init__(self, shellClass=Interpreter, mpi=None):
347 """Create an EngineService.
350 """Create an EngineService.
348
351
349 shellClass: something that implements IInterpreter or core1
352 shellClass: something that implements IInterpreter or core1
350 mpi: an mpi module that has rank and size attributes
353 mpi: an mpi module that has rank and size attributes
351 """
354 """
352 self.shellClass = shellClass
355 self.shellClass = shellClass
353 self.shell = self.shellClass()
356 self.shell = self.shellClass()
354 self.mpi = mpi
357 self.mpi = mpi
355 self.id = None
358 self.id = None
356 self.properties = get_engine(self.id).properties
359 self.properties = get_engine(self.id).properties
357 if self.mpi is not None:
360 if self.mpi is not None:
358 log.msg("MPI started with rank = %i and size = %i" %
361 log.msg("MPI started with rank = %i and size = %i" %
359 (self.mpi.rank, self.mpi.size))
362 (self.mpi.rank, self.mpi.size))
360 self.id = self.mpi.rank
363 self.id = self.mpi.rank
361 self._seedNamespace()
364 self._seedNamespace()
362
365
363 # Make id a property so that the shell can get the updated id
366 # Make id a property so that the shell can get the updated id
364
367
365 def _setID(self, id):
368 def _setID(self, id):
366 self._id = id
369 self._id = id
367 self.properties = get_engine(id).properties
370 self.properties = get_engine(id).properties
368 self.shell.push({'id': id})
371 self.shell.push({'id': id})
369
372
370 def _getID(self):
373 def _getID(self):
371 return self._id
374 return self._id
372
375
373 id = property(_getID, _setID)
376 id = property(_getID, _setID)
374
377
375 def _seedNamespace(self):
378 def _seedNamespace(self):
376 self.shell.push({'mpi': self.mpi, 'id' : self.id})
379 self.shell.push({'mpi': self.mpi, 'id' : self.id})
377
380
378 def executeAndRaise(self, msg, callable, *args, **kwargs):
381 def executeAndRaise(self, msg, callable, *args, **kwargs):
379 """Call a method of self.shell and wrap any exception."""
382 """Call a method of self.shell and wrap any exception."""
380 d = defer.Deferred()
383 d = defer.Deferred()
381 try:
384 try:
382 result = callable(*args, **kwargs)
385 result = callable(*args, **kwargs)
383 except:
386 except:
384 # This gives the following:
387 # This gives the following:
385 # et=exception class
388 # et=exception class
386 # ev=exception class instance
389 # ev=exception class instance
387 # tb=traceback object
390 # tb=traceback object
388 et,ev,tb = sys.exc_info()
391 et,ev,tb = sys.exc_info()
389 # This call adds attributes to the exception value
392 # This call adds attributes to the exception value
390 et,ev,tb = self.shell.formatTraceback(et,ev,tb,msg)
393 et,ev,tb = self.shell.formatTraceback(et,ev,tb,msg)
391 # Add another attribute
394 # Add another attribute
392 ev._ipython_engine_info = msg
395 ev._ipython_engine_info = msg
393 f = failure.Failure(ev,et,None)
396 f = failure.Failure(ev,et,None)
394 d.errback(f)
397 d.errback(f)
395 else:
398 else:
396 d.callback(result)
399 d.callback(result)
397
400
398 return d
401 return d
399
402
400
403
401 # The IEngine methods. See the interface for documentation.
404 # The IEngine methods. See the interface for documentation.
402
405
403 def execute(self, lines):
406 def execute(self, lines):
404 msg = {'engineid':self.id,
407 msg = {'engineid':self.id,
405 'method':'execute',
408 'method':'execute',
406 'args':[lines]}
409 'args':[lines]}
407 d = self.executeAndRaise(msg, self.shell.execute, lines)
410 d = self.executeAndRaise(msg, self.shell.execute, lines)
408 d.addCallback(self.addIDToResult)
411 d.addCallback(self.addIDToResult)
409 return d
412 return d
410
413
411 def addIDToResult(self, result):
414 def addIDToResult(self, result):
412 result['id'] = self.id
415 result['id'] = self.id
413 return result
416 return result
414
417
415 def push(self, namespace):
418 def push(self, namespace):
416 msg = {'engineid':self.id,
419 msg = {'engineid':self.id,
417 'method':'push',
420 'method':'push',
418 'args':[repr(namespace.keys())]}
421 'args':[repr(namespace.keys())]}
419 d = self.executeAndRaise(msg, self.shell.push, namespace)
422 d = self.executeAndRaise(msg, self.shell.push, namespace)
420 return d
423 return d
421
424
422 def pull(self, keys):
425 def pull(self, keys):
423 msg = {'engineid':self.id,
426 msg = {'engineid':self.id,
424 'method':'pull',
427 'method':'pull',
425 'args':[repr(keys)]}
428 'args':[repr(keys)]}
426 d = self.executeAndRaise(msg, self.shell.pull, keys)
429 d = self.executeAndRaise(msg, self.shell.pull, keys)
427 return d
430 return d
428
431
429 def push_function(self, namespace):
432 def push_function(self, namespace):
430 msg = {'engineid':self.id,
433 msg = {'engineid':self.id,
431 'method':'push_function',
434 'method':'push_function',
432 'args':[repr(namespace.keys())]}
435 'args':[repr(namespace.keys())]}
433 d = self.executeAndRaise(msg, self.shell.push_function, namespace)
436 d = self.executeAndRaise(msg, self.shell.push_function, namespace)
434 return d
437 return d
435
438
436 def pull_function(self, keys):
439 def pull_function(self, keys):
437 msg = {'engineid':self.id,
440 msg = {'engineid':self.id,
438 'method':'pull_function',
441 'method':'pull_function',
439 'args':[repr(keys)]}
442 'args':[repr(keys)]}
440 d = self.executeAndRaise(msg, self.shell.pull_function, keys)
443 d = self.executeAndRaise(msg, self.shell.pull_function, keys)
441 return d
444 return d
442
445
443 def get_result(self, i=None):
446 def get_result(self, i=None):
444 msg = {'engineid':self.id,
447 msg = {'engineid':self.id,
445 'method':'get_result',
448 'method':'get_result',
446 'args':[repr(i)]}
449 'args':[repr(i)]}
447 d = self.executeAndRaise(msg, self.shell.getCommand, i)
450 d = self.executeAndRaise(msg, self.shell.getCommand, i)
448 d.addCallback(self.addIDToResult)
451 d.addCallback(self.addIDToResult)
449 return d
452 return d
450
453
451 def reset(self):
454 def reset(self):
452 msg = {'engineid':self.id,
455 msg = {'engineid':self.id,
453 'method':'reset',
456 'method':'reset',
454 'args':[]}
457 'args':[]}
455 del self.shell
458 del self.shell
456 self.shell = self.shellClass()
459 self.shell = self.shellClass()
457 self.properties.clear()
460 self.properties.clear()
458 d = self.executeAndRaise(msg, self._seedNamespace)
461 d = self.executeAndRaise(msg, self._seedNamespace)
459 return d
462 return d
460
463
461 def kill(self):
464 def kill(self):
462 drop_engine(self.id)
465 drop_engine(self.id)
463 try:
466 try:
464 reactor.stop()
467 reactor.stop()
465 except RuntimeError:
468 except RuntimeError:
466 log.msg('The reactor was not running apparently.')
469 log.msg('The reactor was not running apparently.')
467 return defer.fail()
470 return defer.fail()
468 else:
471 else:
469 return defer.succeed(None)
472 return defer.succeed(None)
470
473
471 def keys(self):
474 def keys(self):
472 """Return a list of variables names in the users top level namespace.
475 """Return a list of variables names in the users top level namespace.
473
476
474 This used to return a dict of all the keys/repr(values) in the
477 This used to return a dict of all the keys/repr(values) in the
475 user's namespace. This was too much info for the ControllerService
478 user's namespace. This was too much info for the ControllerService
476 to handle so it is now just a list of keys.
479 to handle so it is now just a list of keys.
477 """
480 """
478
481
479 remotes = []
482 remotes = []
480 for k in self.shell.user_ns.iterkeys():
483 for k in self.shell.user_ns.iterkeys():
481 if k not in ['__name__', '_ih', '_oh', '__builtins__',
484 if k not in ['__name__', '_ih', '_oh', '__builtins__',
482 'In', 'Out', '_', '__', '___', '__IP', 'input', 'raw_input']:
485 'In', 'Out', '_', '__', '___', '__IP', 'input', 'raw_input']:
483 remotes.append(k)
486 remotes.append(k)
484 return defer.succeed(remotes)
487 return defer.succeed(remotes)
485
488
486 def set_properties(self, properties):
489 def set_properties(self, properties):
487 msg = {'engineid':self.id,
490 msg = {'engineid':self.id,
488 'method':'set_properties',
491 'method':'set_properties',
489 'args':[repr(properties.keys())]}
492 'args':[repr(properties.keys())]}
490 return self.executeAndRaise(msg, self.properties.update, properties)
493 return self.executeAndRaise(msg, self.properties.update, properties)
491
494
492 def get_properties(self, keys=None):
495 def get_properties(self, keys=None):
493 msg = {'engineid':self.id,
496 msg = {'engineid':self.id,
494 'method':'get_properties',
497 'method':'get_properties',
495 'args':[repr(keys)]}
498 'args':[repr(keys)]}
496 if keys is None:
499 if keys is None:
497 keys = self.properties.keys()
500 keys = self.properties.keys()
498 return self.executeAndRaise(msg, self.properties.subDict, *keys)
501 return self.executeAndRaise(msg, self.properties.subDict, *keys)
499
502
500 def _doDel(self, keys):
503 def _doDel(self, keys):
501 for key in keys:
504 for key in keys:
502 del self.properties[key]
505 del self.properties[key]
503
506
504 def del_properties(self, keys):
507 def del_properties(self, keys):
505 msg = {'engineid':self.id,
508 msg = {'engineid':self.id,
506 'method':'del_properties',
509 'method':'del_properties',
507 'args':[repr(keys)]}
510 'args':[repr(keys)]}
508 return self.executeAndRaise(msg, self._doDel, keys)
511 return self.executeAndRaise(msg, self._doDel, keys)
509
512
510 def _doHas(self, keys):
513 def _doHas(self, keys):
511 return [self.properties.has_key(key) for key in keys]
514 return [self.properties.has_key(key) for key in keys]
512
515
513 def has_properties(self, keys):
516 def has_properties(self, keys):
514 msg = {'engineid':self.id,
517 msg = {'engineid':self.id,
515 'method':'has_properties',
518 'method':'has_properties',
516 'args':[repr(keys)]}
519 'args':[repr(keys)]}
517 return self.executeAndRaise(msg, self._doHas, keys)
520 return self.executeAndRaise(msg, self._doHas, keys)
518
521
519 def clear_properties(self):
522 def clear_properties(self):
520 msg = {'engineid':self.id,
523 msg = {'engineid':self.id,
521 'method':'clear_properties',
524 'method':'clear_properties',
522 'args':[]}
525 'args':[]}
523 return self.executeAndRaise(msg, self.properties.clear)
526 return self.executeAndRaise(msg, self.properties.clear)
524
527
525 def push_serialized(self, sNamespace):
528 def push_serialized(self, sNamespace):
526 msg = {'engineid':self.id,
529 msg = {'engineid':self.id,
527 'method':'push_serialized',
530 'method':'push_serialized',
528 'args':[repr(sNamespace.keys())]}
531 'args':[repr(sNamespace.keys())]}
529 ns = {}
532 ns = {}
530 for k,v in sNamespace.iteritems():
533 for k,v in sNamespace.iteritems():
531 try:
534 try:
532 unserialized = newserialized.IUnSerialized(v)
535 unserialized = newserialized.IUnSerialized(v)
533 ns[k] = unserialized.getObject()
536 ns[k] = unserialized.getObject()
534 except:
537 except:
535 return defer.fail()
538 return defer.fail()
536 return self.executeAndRaise(msg, self.shell.push, ns)
539 return self.executeAndRaise(msg, self.shell.push, ns)
537
540
538 def pull_serialized(self, keys):
541 def pull_serialized(self, keys):
539 msg = {'engineid':self.id,
542 msg = {'engineid':self.id,
540 'method':'pull_serialized',
543 'method':'pull_serialized',
541 'args':[repr(keys)]}
544 'args':[repr(keys)]}
542 if isinstance(keys, str):
545 if isinstance(keys, str):
543 keys = [keys]
546 keys = [keys]
544 if len(keys)==1:
547 if len(keys)==1:
545 d = self.executeAndRaise(msg, self.shell.pull, keys)
548 d = self.executeAndRaise(msg, self.shell.pull, keys)
546 d.addCallback(newserialized.serialize)
549 d.addCallback(newserialized.serialize)
547 return d
550 return d
548 elif len(keys)>1:
551 elif len(keys)>1:
549 d = self.executeAndRaise(msg, self.shell.pull, keys)
552 d = self.executeAndRaise(msg, self.shell.pull, keys)
550 @d.addCallback
553 @d.addCallback
551 def packThemUp(values):
554 def packThemUp(values):
552 serials = []
555 serials = []
553 for v in values:
556 for v in values:
554 try:
557 try:
555 serials.append(newserialized.serialize(v))
558 serials.append(newserialized.serialize(v))
556 except:
559 except:
557 return defer.fail(failure.Failure())
560 return defer.fail(failure.Failure())
558 return serials
561 return serials
559 return packThemUp
562 return packThemUp
560
563
561
564
562 def queue(methodToQueue):
565 def queue(methodToQueue):
563 def queuedMethod(this, *args, **kwargs):
566 def queuedMethod(this, *args, **kwargs):
564 name = methodToQueue.__name__
567 name = methodToQueue.__name__
565 return this.submitCommand(Command(name, *args, **kwargs))
568 return this.submitCommand(Command(name, *args, **kwargs))
566 return queuedMethod
569 return queuedMethod
567
570
568 class QueuedEngine(object):
571 class QueuedEngine(object):
569 """Adapt an IEngineBase to an IEngineQueued by wrapping it.
572 """Adapt an IEngineBase to an IEngineQueued by wrapping it.
570
573
571 The resulting object will implement IEngineQueued which extends
574 The resulting object will implement IEngineQueued which extends
572 IEngineCore which extends (IEngineBase, IEngineSerialized).
575 IEngineCore which extends (IEngineBase, IEngineSerialized).
573
576
574 This seems like the best way of handling it, but I am not sure. The
577 This seems like the best way of handling it, but I am not sure. The
575 other option is to have the various base interfaces be used like
578 other option is to have the various base interfaces be used like
576 mix-in intefaces. The problem I have with this is adpatation is
579 mix-in intefaces. The problem I have with this is adpatation is
577 more difficult and complicated because there can be can multiple
580 more difficult and complicated because there can be can multiple
578 original and final Interfaces.
581 original and final Interfaces.
579 """
582 """
580
583
581 zi.implements(IEngineQueued)
584 zi.implements(IEngineQueued)
582
585
583 def __init__(self, engine):
586 def __init__(self, engine):
584 """Create a QueuedEngine object from an engine
587 """Create a QueuedEngine object from an engine
585
588
586 engine: An implementor of IEngineCore and IEngineSerialized
589 engine: An implementor of IEngineCore and IEngineSerialized
587 keepUpToDate: whether to update the remote status when the
590 keepUpToDate: whether to update the remote status when the
588 queue is empty. Defaults to False.
591 queue is empty. Defaults to False.
589 """
592 """
590
593
591 # This is the right way to do these tests rather than
594 # This is the right way to do these tests rather than
592 # IEngineCore in list(zi.providedBy(engine)) which will only
595 # IEngineCore in list(zi.providedBy(engine)) which will only
593 # picks of the interfaces that are directly declared by engine.
596 # picks of the interfaces that are directly declared by engine.
594 assert IEngineBase.providedBy(engine), \
597 assert IEngineBase.providedBy(engine), \
595 "engine passed to QueuedEngine doesn't provide IEngineBase"
598 "engine passed to QueuedEngine doesn't provide IEngineBase"
596
599
597 self.engine = engine
600 self.engine = engine
598 self.id = engine.id
601 self.id = engine.id
599 self.queued = []
602 self.queued = []
600 self.history = {}
603 self.history = {}
601 self.engineStatus = {}
604 self.engineStatus = {}
602 self.currentCommand = None
605 self.currentCommand = None
603 self.failureObservers = []
606 self.failureObservers = []
604
607
605 def _get_properties(self):
608 def _get_properties(self):
606 return self.engine.properties
609 return self.engine.properties
607
610
608 properties = property(_get_properties, lambda self, _: None)
611 properties = property(_get_properties, lambda self, _: None)
609 # Queue management methods. You should not call these directly
612 # Queue management methods. You should not call these directly
610
613
611 def submitCommand(self, cmd):
614 def submitCommand(self, cmd):
612 """Submit command to queue."""
615 """Submit command to queue."""
613
616
614 d = defer.Deferred()
617 d = defer.Deferred()
615 cmd.setDeferred(d)
618 cmd.setDeferred(d)
616 if self.currentCommand is not None:
619 if self.currentCommand is not None:
617 if self.currentCommand.finished:
620 if self.currentCommand.finished:
618 # log.msg("Running command immediately: %r" % cmd)
621 # log.msg("Running command immediately: %r" % cmd)
619 self.currentCommand = cmd
622 self.currentCommand = cmd
620 self.runCurrentCommand()
623 self.runCurrentCommand()
621 else: # command is still running
624 else: # command is still running
622 # log.msg("Command is running: %r" % self.currentCommand)
625 # log.msg("Command is running: %r" % self.currentCommand)
623 # log.msg("Queueing: %r" % cmd)
626 # log.msg("Queueing: %r" % cmd)
624 self.queued.append(cmd)
627 self.queued.append(cmd)
625 else:
628 else:
626 # log.msg("No current commands, running: %r" % cmd)
629 # log.msg("No current commands, running: %r" % cmd)
627 self.currentCommand = cmd
630 self.currentCommand = cmd
628 self.runCurrentCommand()
631 self.runCurrentCommand()
629 return d
632 return d
630
633
631 def runCurrentCommand(self):
634 def runCurrentCommand(self):
632 """Run current command."""
635 """Run current command."""
633
636
634 cmd = self.currentCommand
637 cmd = self.currentCommand
635 f = getattr(self.engine, cmd.remoteMethod, None)
638 f = getattr(self.engine, cmd.remoteMethod, None)
636 if f:
639 if f:
637 d = f(*cmd.args, **cmd.kwargs)
640 d = f(*cmd.args, **cmd.kwargs)
638 if cmd.remoteMethod is 'execute':
641 if cmd.remoteMethod is 'execute':
639 d.addCallback(self.saveResult)
642 d.addCallback(self.saveResult)
640 d.addCallback(self.finishCommand)
643 d.addCallback(self.finishCommand)
641 d.addErrback(self.abortCommand)
644 d.addErrback(self.abortCommand)
642 else:
645 else:
643 return defer.fail(AttributeError(cmd.remoteMethod))
646 return defer.fail(AttributeError(cmd.remoteMethod))
644
647
645 def _flushQueue(self):
648 def _flushQueue(self):
646 """Pop next command in queue and run it."""
649 """Pop next command in queue and run it."""
647
650
648 if len(self.queued) > 0:
651 if len(self.queued) > 0:
649 self.currentCommand = self.queued.pop(0)
652 self.currentCommand = self.queued.pop(0)
650 self.runCurrentCommand()
653 self.runCurrentCommand()
651
654
652 def saveResult(self, result):
655 def saveResult(self, result):
653 """Put the result in the history."""
656 """Put the result in the history."""
654 self.history[result['number']] = result
657 self.history[result['number']] = result
655 return result
658 return result
656
659
657 def finishCommand(self, result):
660 def finishCommand(self, result):
658 """Finish currrent command."""
661 """Finish currrent command."""
659
662
660 # The order of these commands is absolutely critical.
663 # The order of these commands is absolutely critical.
661 self.currentCommand.handleResult(result)
664 self.currentCommand.handleResult(result)
662 self.currentCommand.finished = True
665 self.currentCommand.finished = True
663 self._flushQueue()
666 self._flushQueue()
664 return result
667 return result
665
668
666 def abortCommand(self, reason):
669 def abortCommand(self, reason):
667 """Abort current command.
670 """Abort current command.
668
671
669 This eats the Failure but first passes it onto the Deferred that the
672 This eats the Failure but first passes it onto the Deferred that the
670 user has.
673 user has.
671
674
672 It also clear out the queue so subsequence commands don't run.
675 It also clear out the queue so subsequence commands don't run.
673 """
676 """
674
677
675 # The order of these 3 commands is absolutely critical. The currentCommand
678 # The order of these 3 commands is absolutely critical. The currentCommand
676 # must first be marked as finished BEFORE the queue is cleared and before
679 # must first be marked as finished BEFORE the queue is cleared and before
677 # the current command is sent the failure.
680 # the current command is sent the failure.
678 # Also, the queue must be cleared BEFORE the current command is sent the Failure
681 # Also, the queue must be cleared BEFORE the current command is sent the Failure
679 # otherwise the errback chain could trigger new commands to be added to the
682 # otherwise the errback chain could trigger new commands to be added to the
680 # queue before we clear it. We should clear ONLY the commands that were in
683 # queue before we clear it. We should clear ONLY the commands that were in
681 # the queue when the error occured.
684 # the queue when the error occured.
682 self.currentCommand.finished = True
685 self.currentCommand.finished = True
683 s = "%r %r %r" % (self.currentCommand.remoteMethod, self.currentCommand.args, self.currentCommand.kwargs)
686 s = "%r %r %r" % (self.currentCommand.remoteMethod, self.currentCommand.args, self.currentCommand.kwargs)
684 self.clear_queue(msg=s)
687 self.clear_queue(msg=s)
685 self.currentCommand.handleError(reason)
688 self.currentCommand.handleError(reason)
686
689
687 return None
690 return None
688
691
689 #---------------------------------------------------------------------------
692 #---------------------------------------------------------------------------
690 # IEngineCore methods
693 # IEngineCore methods
691 #---------------------------------------------------------------------------
694 #---------------------------------------------------------------------------
692
695
693 @queue
696 @queue
694 def execute(self, lines):
697 def execute(self, lines):
695 pass
698 pass
696
699
697 @queue
700 @queue
698 def push(self, namespace):
701 def push(self, namespace):
699 pass
702 pass
700
703
701 @queue
704 @queue
702 def pull(self, keys):
705 def pull(self, keys):
703 pass
706 pass
704
707
705 @queue
708 @queue
706 def push_function(self, namespace):
709 def push_function(self, namespace):
707 pass
710 pass
708
711
709 @queue
712 @queue
710 def pull_function(self, keys):
713 def pull_function(self, keys):
711 pass
714 pass
712
715
713 def get_result(self, i=None):
716 def get_result(self, i=None):
714 if i is None:
717 if i is None:
715 i = max(self.history.keys()+[None])
718 i = max(self.history.keys()+[None])
716
719
717 cmd = self.history.get(i, None)
720 cmd = self.history.get(i, None)
718 # Uncomment this line to disable chaching of results
721 # Uncomment this line to disable chaching of results
719 #cmd = None
722 #cmd = None
720 if cmd is None:
723 if cmd is None:
721 return self.submitCommand(Command('get_result', i))
724 return self.submitCommand(Command('get_result', i))
722 else:
725 else:
723 return defer.succeed(cmd)
726 return defer.succeed(cmd)
724
727
725 def reset(self):
728 def reset(self):
726 self.clear_queue()
729 self.clear_queue()
727 self.history = {} # reset the cache - I am not sure we should do this
730 self.history = {} # reset the cache - I am not sure we should do this
728 return self.submitCommand(Command('reset'))
731 return self.submitCommand(Command('reset'))
729
732
730 def kill(self):
733 def kill(self):
731 self.clear_queue()
734 self.clear_queue()
732 return self.submitCommand(Command('kill'))
735 return self.submitCommand(Command('kill'))
733
736
734 @queue
737 @queue
735 def keys(self):
738 def keys(self):
736 pass
739 pass
737
740
738 #---------------------------------------------------------------------------
741 #---------------------------------------------------------------------------
739 # IEngineSerialized methods
742 # IEngineSerialized methods
740 #---------------------------------------------------------------------------
743 #---------------------------------------------------------------------------
741
744
742 @queue
745 @queue
743 def push_serialized(self, namespace):
746 def push_serialized(self, namespace):
744 pass
747 pass
745
748
746 @queue
749 @queue
747 def pull_serialized(self, keys):
750 def pull_serialized(self, keys):
748 pass
751 pass
749
752
750 #---------------------------------------------------------------------------
753 #---------------------------------------------------------------------------
751 # IEngineProperties methods
754 # IEngineProperties methods
752 #---------------------------------------------------------------------------
755 #---------------------------------------------------------------------------
753
756
754 @queue
757 @queue
755 def set_properties(self, namespace):
758 def set_properties(self, namespace):
756 pass
759 pass
757
760
758 @queue
761 @queue
759 def get_properties(self, keys=None):
762 def get_properties(self, keys=None):
760 pass
763 pass
761
764
762 @queue
765 @queue
763 def del_properties(self, keys):
766 def del_properties(self, keys):
764 pass
767 pass
765
768
766 @queue
769 @queue
767 def has_properties(self, keys):
770 def has_properties(self, keys):
768 pass
771 pass
769
772
770 @queue
773 @queue
771 def clear_properties(self):
774 def clear_properties(self):
772 pass
775 pass
773
776
774 #---------------------------------------------------------------------------
777 #---------------------------------------------------------------------------
775 # IQueuedEngine methods
778 # IQueuedEngine methods
776 #---------------------------------------------------------------------------
779 #---------------------------------------------------------------------------
777
780
778 def clear_queue(self, msg=''):
781 def clear_queue(self, msg=''):
779 """Clear the queue, but doesn't cancel the currently running commmand."""
782 """Clear the queue, but doesn't cancel the currently running commmand."""
780
783
781 for cmd in self.queued:
784 for cmd in self.queued:
782 cmd.deferred.errback(failure.Failure(error.QueueCleared(msg)))
785 cmd.deferred.errback(failure.Failure(error.QueueCleared(msg)))
783 self.queued = []
786 self.queued = []
784 return defer.succeed(None)
787 return defer.succeed(None)
785
788
786 def queue_status(self):
789 def queue_status(self):
787 if self.currentCommand is not None:
790 if self.currentCommand is not None:
788 if self.currentCommand.finished:
791 if self.currentCommand.finished:
789 pending = repr(None)
792 pending = repr(None)
790 else:
793 else:
791 pending = repr(self.currentCommand)
794 pending = repr(self.currentCommand)
792 else:
795 else:
793 pending = repr(None)
796 pending = repr(None)
794 dikt = {'queue':map(repr,self.queued), 'pending':pending}
797 dikt = {'queue':map(repr,self.queued), 'pending':pending}
795 return defer.succeed(dikt)
798 return defer.succeed(dikt)
796
799
797 def register_failure_observer(self, obs):
800 def register_failure_observer(self, obs):
798 self.failureObservers.append(obs)
801 self.failureObservers.append(obs)
799
802
800 def unregister_failure_observer(self, obs):
803 def unregister_failure_observer(self, obs):
801 self.failureObservers.remove(obs)
804 self.failureObservers.remove(obs)
802
805
803
806
804 # Now register QueuedEngine as an adpater class that makes an IEngineBase into a
807 # Now register QueuedEngine as an adpater class that makes an IEngineBase into a
805 # IEngineQueued.
808 # IEngineQueued.
806 components.registerAdapter(QueuedEngine, IEngineBase, IEngineQueued)
809 components.registerAdapter(QueuedEngine, IEngineBase, IEngineQueued)
807
810
808
811
809 class Command(object):
812 class Command(object):
810 """A command object that encapslates queued commands.
813 """A command object that encapslates queued commands.
811
814
812 This class basically keeps track of a command that has been queued
815 This class basically keeps track of a command that has been queued
813 in a QueuedEngine. It manages the deferreds and hold the method to be called
816 in a QueuedEngine. It manages the deferreds and hold the method to be called
814 and the arguments to that method.
817 and the arguments to that method.
815 """
818 """
816
819
817
820
818 def __init__(self, remoteMethod, *args, **kwargs):
821 def __init__(self, remoteMethod, *args, **kwargs):
819 """Build a new Command object."""
822 """Build a new Command object."""
820
823
821 self.remoteMethod = remoteMethod
824 self.remoteMethod = remoteMethod
822 self.args = args
825 self.args = args
823 self.kwargs = kwargs
826 self.kwargs = kwargs
824 self.finished = False
827 self.finished = False
825
828
826 def setDeferred(self, d):
829 def setDeferred(self, d):
827 """Sets the deferred attribute of the Command."""
830 """Sets the deferred attribute of the Command."""
828
831
829 self.deferred = d
832 self.deferred = d
830
833
831 def __repr__(self):
834 def __repr__(self):
832 if not self.args:
835 if not self.args:
833 args = ''
836 args = ''
834 else:
837 else:
835 args = str(self.args)[1:-2] #cut off (...,)
838 args = str(self.args)[1:-2] #cut off (...,)
836 for k,v in self.kwargs.iteritems():
839 for k,v in self.kwargs.iteritems():
837 if args:
840 if args:
838 args += ', '
841 args += ', '
839 args += '%s=%r' %(k,v)
842 args += '%s=%r' %(k,v)
840 return "%s(%s)" %(self.remoteMethod, args)
843 return "%s(%s)" %(self.remoteMethod, args)
841
844
842 def handleResult(self, result):
845 def handleResult(self, result):
843 """When the result is ready, relay it to self.deferred."""
846 """When the result is ready, relay it to self.deferred."""
844
847
845 self.deferred.callback(result)
848 self.deferred.callback(result)
846
849
847 def handleError(self, reason):
850 def handleError(self, reason):
848 """When an error has occured, relay it to self.deferred."""
851 """When an error has occured, relay it to self.deferred."""
849
852
850 self.deferred.errback(reason)
853 self.deferred.errback(reason)
851
854
852 class ThreadedEngineService(EngineService):
855 class ThreadedEngineService(EngineService):
853 """An EngineService subclass that defers execute commands to a separate
856 """An EngineService subclass that defers execute commands to a separate
854 thread.
857 thread.
855
858
856 ThreadedEngineService uses twisted.internet.threads.deferToThread to
859 ThreadedEngineService uses twisted.internet.threads.deferToThread to
857 defer execute requests to a separate thread. GUI frontends may want to
860 defer execute requests to a separate thread. GUI frontends may want to
858 use ThreadedEngineService as the engine in an
861 use ThreadedEngineService as the engine in an
859 IPython.frontend.frontendbase.FrontEndBase subclass to prevent
862 IPython.frontend.frontendbase.FrontEndBase subclass to prevent
860 block execution from blocking the GUI thread.
863 block execution from blocking the GUI thread.
861 """
864 """
862
865
863 zi.implements(IEngineBase)
866 zi.implements(IEngineBase)
864
867
865 def __init__(self, shellClass=Interpreter, mpi=None):
868 def __init__(self, shellClass=Interpreter, mpi=None):
866 EngineService.__init__(self, shellClass, mpi)
869 EngineService.__init__(self, shellClass, mpi)
867
870
868 def wrapped_execute(self, msg, lines):
871 def wrapped_execute(self, msg, lines):
869 """Wrap self.shell.execute to add extra information to tracebacks"""
872 """Wrap self.shell.execute to add extra information to tracebacks"""
870
873
871 try:
874 try:
872 result = self.shell.execute(lines)
875 result = self.shell.execute(lines)
873 except Exception,e:
876 except Exception,e:
874 # This gives the following:
877 # This gives the following:
875 # et=exception class
878 # et=exception class
876 # ev=exception class instance
879 # ev=exception class instance
877 # tb=traceback object
880 # tb=traceback object
878 et,ev,tb = sys.exc_info()
881 et,ev,tb = sys.exc_info()
879 # This call adds attributes to the exception value
882 # This call adds attributes to the exception value
880 et,ev,tb = self.shell.formatTraceback(et,ev,tb,msg)
883 et,ev,tb = self.shell.formatTraceback(et,ev,tb,msg)
881 # Add another attribute
884 # Add another attribute
882
885
883 # Create a new exception with the new attributes
886 # Create a new exception with the new attributes
884 e = et(ev._ipython_traceback_text)
887 e = et(ev._ipython_traceback_text)
885 e._ipython_engine_info = msg
888 e._ipython_engine_info = msg
886
889
887 # Re-raise
890 # Re-raise
888 raise e
891 raise e
889
892
890 return result
893 return result
891
894
892
895
893 def execute(self, lines):
896 def execute(self, lines):
894 # Only import this if we are going to use this class
897 # Only import this if we are going to use this class
895 from twisted.internet import threads
898 from twisted.internet import threads
896
899
897 msg = {'engineid':self.id,
900 msg = {'engineid':self.id,
898 'method':'execute',
901 'method':'execute',
899 'args':[lines]}
902 'args':[lines]}
900
903
901 d = threads.deferToThread(self.wrapped_execute, msg, lines)
904 d = threads.deferToThread(self.wrapped_execute, msg, lines)
902 d.addCallback(self.addIDToResult)
905 d.addCallback(self.addIDToResult)
903 return d
906 return d
@@ -1,185 +1,202 b''
1 # encoding: utf-8
1 # encoding: utf-8
2
2
3 """Classes and functions for kernel related errors and exceptions."""
3 """Classes and functions for kernel related errors and exceptions."""
4
4
5 __docformat__ = "restructuredtext en"
5 __docformat__ = "restructuredtext en"
6
6
7 #-------------------------------------------------------------------------------
7 #-------------------------------------------------------------------------------
8 # Copyright (C) 2008 The IPython Development Team
8 # Copyright (C) 2008 The IPython Development Team
9 #
9 #
10 # Distributed under the terms of the BSD License. The full license is in
10 # Distributed under the terms of the BSD License. The full license is in
11 # the file COPYING, distributed as part of this software.
11 # the file COPYING, distributed as part of this software.
12 #-------------------------------------------------------------------------------
12 #-------------------------------------------------------------------------------
13
13
14 #-------------------------------------------------------------------------------
14 #-------------------------------------------------------------------------------
15 # Imports
15 # Imports
16 #-------------------------------------------------------------------------------
16 #-------------------------------------------------------------------------------
17
17
18 from IPython.kernel.core import error
18 from IPython.kernel.core import error
19 from twisted.python import failure
19 from twisted.python import failure
20
20
21 #-------------------------------------------------------------------------------
21 #-------------------------------------------------------------------------------
22 # Error classes
22 # Error classes
23 #-------------------------------------------------------------------------------
23 #-------------------------------------------------------------------------------
24
24
25 class KernelError(error.IPythonError):
25 class KernelError(error.IPythonError):
26 pass
26 pass
27
27
28 class NotDefined(KernelError):
28 class NotDefined(KernelError):
29 def __init__(self, name):
29 def __init__(self, name):
30 self.name = name
30 self.name = name
31 self.args = (name,)
31 self.args = (name,)
32
32
33 def __repr__(self):
33 def __repr__(self):
34 return '<NotDefined: %s>' % self.name
34 return '<NotDefined: %s>' % self.name
35
35
36 __str__ = __repr__
36 __str__ = __repr__
37
37
38 class QueueCleared(KernelError):
38 class QueueCleared(KernelError):
39 pass
39 pass
40
40
41 class IdInUse(KernelError):
41 class IdInUse(KernelError):
42 pass
42 pass
43
43
44 class ProtocolError(KernelError):
44 class ProtocolError(KernelError):
45 pass
45 pass
46
46
47 class ConnectionError(KernelError):
47 class ConnectionError(KernelError):
48 pass
48 pass
49
49
50 class InvalidEngineID(KernelError):
50 class InvalidEngineID(KernelError):
51 pass
51 pass
52
52
53 class NoEnginesRegistered(KernelError):
53 class NoEnginesRegistered(KernelError):
54 pass
54 pass
55
55
56 class InvalidClientID(KernelError):
56 class InvalidClientID(KernelError):
57 pass
57 pass
58
58
59 class InvalidDeferredID(KernelError):
59 class InvalidDeferredID(KernelError):
60 pass
60 pass
61
61
62 class SerializationError(KernelError):
62 class SerializationError(KernelError):
63 pass
63 pass
64
64
65 class MessageSizeError(KernelError):
65 class MessageSizeError(KernelError):
66 pass
66 pass
67
67
68 class PBMessageSizeError(MessageSizeError):
68 class PBMessageSizeError(MessageSizeError):
69 pass
69 pass
70
70
71 class ResultNotCompleted(KernelError):
71 class ResultNotCompleted(KernelError):
72 pass
72 pass
73
73
74 class ResultAlreadyRetrieved(KernelError):
74 class ResultAlreadyRetrieved(KernelError):
75 pass
75 pass
76
76
77 class ClientError(KernelError):
77 class ClientError(KernelError):
78 pass
78 pass
79
79
80 class TaskAborted(KernelError):
80 class TaskAborted(KernelError):
81 pass
81 pass
82
82
83 class TaskTimeout(KernelError):
83 class TaskTimeout(KernelError):
84 pass
84 pass
85
85
86 class NotAPendingResult(KernelError):
86 class NotAPendingResult(KernelError):
87 pass
87 pass
88
88
89 class UnpickleableException(KernelError):
89 class UnpickleableException(KernelError):
90 pass
90 pass
91
91
92 class AbortedPendingDeferredError(KernelError):
92 class AbortedPendingDeferredError(KernelError):
93 pass
93 pass
94
94
95 class InvalidProperty(KernelError):
95 class InvalidProperty(KernelError):
96 pass
96 pass
97
97
98 class MissingBlockArgument(KernelError):
98 class MissingBlockArgument(KernelError):
99 pass
99 pass
100
100
101 class StopLocalExecution(KernelError):
101 class StopLocalExecution(KernelError):
102 pass
102 pass
103
103
104 class SecurityError(KernelError):
104 class SecurityError(KernelError):
105 pass
105 pass
106
106
107 class FileTimeoutError(KernelError):
108 pass
109
110 class TaskRejectError(KernelError):
111 """Exception to raise when a task should be rejected by an engine.
112
113 This exception can be used to allow a task running on an engine to test
114 if the engine (or the user's namespace on the engine) has the needed
115 task dependencies. If not, the task should raise this exception. For
116 the task to be retried on another engine, the task should be created
117 with the `retries` argument > 1.
118
119 The advantage of this approach over our older properties system is that
120 tasks have full access to the user's namespace on the engines and the
121 properties don't have to be managed or tested by the controller.
122 """
123
107 class CompositeError(KernelError):
124 class CompositeError(KernelError):
108 def __init__(self, message, elist):
125 def __init__(self, message, elist):
109 Exception.__init__(self, *(message, elist))
126 Exception.__init__(self, *(message, elist))
110 self.message = message
127 self.message = message
111 self.elist = elist
128 self.elist = elist
112
129
113 def _get_engine_str(self, ev):
130 def _get_engine_str(self, ev):
114 try:
131 try:
115 ei = ev._ipython_engine_info
132 ei = ev._ipython_engine_info
116 except AttributeError:
133 except AttributeError:
117 return '[Engine Exception]'
134 return '[Engine Exception]'
118 else:
135 else:
119 return '[%i:%s]: ' % (ei['engineid'], ei['method'])
136 return '[%i:%s]: ' % (ei['engineid'], ei['method'])
120
137
121 def _get_traceback(self, ev):
138 def _get_traceback(self, ev):
122 try:
139 try:
123 tb = ev._ipython_traceback_text
140 tb = ev._ipython_traceback_text
124 except AttributeError:
141 except AttributeError:
125 return 'No traceback available'
142 return 'No traceback available'
126 else:
143 else:
127 return tb
144 return tb
128
145
129 def __str__(self):
146 def __str__(self):
130 s = str(self.message)
147 s = str(self.message)
131 for et, ev, etb in self.elist:
148 for et, ev, etb in self.elist:
132 engine_str = self._get_engine_str(ev)
149 engine_str = self._get_engine_str(ev)
133 s = s + '\n' + engine_str + str(et.__name__) + ': ' + str(ev)
150 s = s + '\n' + engine_str + str(et.__name__) + ': ' + str(ev)
134 return s
151 return s
135
152
136 def print_tracebacks(self, excid=None):
153 def print_tracebacks(self, excid=None):
137 if excid is None:
154 if excid is None:
138 for (et,ev,etb) in self.elist:
155 for (et,ev,etb) in self.elist:
139 print self._get_engine_str(ev)
156 print self._get_engine_str(ev)
140 print self._get_traceback(ev)
157 print self._get_traceback(ev)
141 print
158 print
142 else:
159 else:
143 try:
160 try:
144 et,ev,etb = self.elist[excid]
161 et,ev,etb = self.elist[excid]
145 except:
162 except:
146 raise IndexError("an exception with index %i does not exist"%excid)
163 raise IndexError("an exception with index %i does not exist"%excid)
147 else:
164 else:
148 print self._get_engine_str(ev)
165 print self._get_engine_str(ev)
149 print self._get_traceback(ev)
166 print self._get_traceback(ev)
150
167
151 def raise_exception(self, excid=0):
168 def raise_exception(self, excid=0):
152 try:
169 try:
153 et,ev,etb = self.elist[excid]
170 et,ev,etb = self.elist[excid]
154 except:
171 except:
155 raise IndexError("an exception with index %i does not exist"%excid)
172 raise IndexError("an exception with index %i does not exist"%excid)
156 else:
173 else:
157 raise et, ev, etb
174 raise et, ev, etb
158
175
159 def collect_exceptions(rlist, method):
176 def collect_exceptions(rlist, method):
160 elist = []
177 elist = []
161 for r in rlist:
178 for r in rlist:
162 if isinstance(r, failure.Failure):
179 if isinstance(r, failure.Failure):
163 r.cleanFailure()
180 r.cleanFailure()
164 et, ev, etb = r.type, r.value, r.tb
181 et, ev, etb = r.type, r.value, r.tb
165 # Sometimes we could have CompositeError in our list. Just take
182 # Sometimes we could have CompositeError in our list. Just take
166 # the errors out of them and put them in our new list. This
183 # the errors out of them and put them in our new list. This
167 # has the effect of flattening lists of CompositeErrors into one
184 # has the effect of flattening lists of CompositeErrors into one
168 # CompositeError
185 # CompositeError
169 if et==CompositeError:
186 if et==CompositeError:
170 for e in ev.elist:
187 for e in ev.elist:
171 elist.append(e)
188 elist.append(e)
172 else:
189 else:
173 elist.append((et, ev, etb))
190 elist.append((et, ev, etb))
174 if len(elist)==0:
191 if len(elist)==0:
175 return rlist
192 return rlist
176 else:
193 else:
177 msg = "one or more exceptions from call to method: %s" % (method)
194 msg = "one or more exceptions from call to method: %s" % (method)
178 # This silliness is needed so the debugger has access to the exception
195 # This silliness is needed so the debugger has access to the exception
179 # instance (e in this case)
196 # instance (e in this case)
180 try:
197 try:
181 raise CompositeError(msg, elist)
198 raise CompositeError(msg, elist)
182 except CompositeError, e:
199 except CompositeError, e:
183 raise e
200 raise e
184
201
185
202
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
General Comments 0
You need to be logged in to leave comments. Login now