##// END OF EJS Templates
Merge branch 'configurable' into trunk
Brian Granger -
r2750:bb29f349 merge
parent child Browse files
Show More

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

@@ -0,0 +1,139 b''
1 #!/usr/bin/env python
2 # encoding: utf-8
3 """
4 A base class for objects that are configurable.
5
6 Authors:
7
8 * Brian Granger
9 * Fernando Perez
10 """
11
12 #-----------------------------------------------------------------------------
13 # Copyright (C) 2008-2010 The IPython Development Team
14 #
15 # Distributed under the terms of the BSD License. The full license is in
16 # the file COPYING, distributed as part of this software.
17 #-----------------------------------------------------------------------------
18
19 #-----------------------------------------------------------------------------
20 # Imports
21 #-----------------------------------------------------------------------------
22
23 from copy import deepcopy
24 import datetime
25 from weakref import WeakValueDictionary
26
27 from IPython.utils.importstring import import_item
28 from loader import Config
29 from IPython.utils.traitlets import HasTraits, Instance
30
31
32 #-----------------------------------------------------------------------------
33 # Helper classes for Configurables
34 #-----------------------------------------------------------------------------
35
36
37 class ConfigurableError(Exception):
38 pass
39
40
41 #-----------------------------------------------------------------------------
42 # Configurable implementation
43 #-----------------------------------------------------------------------------
44
45
46 class Configurable(HasTraits):
47
48 config = Instance(Config,(),{})
49 created = None
50
51 def __init__(self, **kwargs):
52 """Create a conigurable given a config config.
53
54 Parameters
55 ----------
56 config : Config
57 If this is empty, default values are used. If config is a
58 :class:`Config` instance, it will be used to configure the
59 instance.
60
61 Notes
62 -----
63 Subclasses of Configurable must call the :meth:`__init__` method of
64 :class:`Configurable` *before* doing anything else and using
65 :func:`super`::
66
67 class MyConfigurable(Configurable):
68 def __init__(self, config=None):
69 super(MyConfigurable, self).__init__(config)
70 # Then any other code you need to finish initialization.
71
72 This ensures that instances will be configured properly.
73 """
74 config = kwargs.pop('config', None)
75 if config is not None:
76 # We used to deepcopy, but for now we are trying to just save
77 # by reference. This *could* have side effects as all components
78 # will share config. In fact, I did find such a side effect in
79 # _config_changed below. If a config attribute value was a mutable type
80 # all instances of a component were getting the same copy, effectively
81 # making that a class attribute.
82 # self.config = deepcopy(config)
83 self.config = config
84 # This should go second so individual keyword arguments override
85 # the values in config.
86 super(Configurable, self).__init__(**kwargs)
87 self.created = datetime.datetime.now()
88
89 #-------------------------------------------------------------------------
90 # Static trait notifiations
91 #-------------------------------------------------------------------------
92
93 def _config_changed(self, name, old, new):
94 """Update all the class traits having ``config=True`` as metadata.
95
96 For any class trait with a ``config`` metadata attribute that is
97 ``True``, we update the trait with the value of the corresponding
98 config entry.
99 """
100 # Get all traits with a config metadata entry that is True
101 traits = self.traits(config=True)
102
103 # We auto-load config section for this class as well as any parent
104 # classes that are Configurable subclasses. This starts with Configurable
105 # and works down the mro loading the config for each section.
106 section_names = [cls.__name__ for cls in \
107 reversed(self.__class__.__mro__) if
108 issubclass(cls, Configurable) and issubclass(self.__class__, cls)]
109
110 for sname in section_names:
111 # Don't do a blind getattr as that would cause the config to
112 # dynamically create the section with name self.__class__.__name__.
113 if new._has_section(sname):
114 my_config = new[sname]
115 for k, v in traits.items():
116 # Don't allow traitlets with config=True to start with
117 # uppercase. Otherwise, they are confused with Config
118 # subsections. But, developers shouldn't have uppercase
119 # attributes anyways! (PEP 6)
120 if k[0].upper()==k[0] and not k.startswith('_'):
121 raise ConfigurableError('Configurable traitlets with '
122 'config=True must start with a lowercase so they are '
123 'not confused with Config subsections: %s.%s' % \
124 (self.__class__.__name__, k))
125 try:
126 # Here we grab the value from the config
127 # If k has the naming convention of a config
128 # section, it will be auto created.
129 config_value = my_config[k]
130 except KeyError:
131 pass
132 else:
133 # print "Setting %s.%s from %s.%s=%r" % \
134 # (self.__class__.__name__,k,sname,k,config_value)
135 # We have to do a deepcopy here if we don't deepcopy the entire
136 # config object. If we don't, a mutable config_value will be
137 # shared by all instances, effectively making it a class attribute.
138 setattr(self, k, deepcopy(config_value))
139
@@ -0,0 +1,124 b''
1 #!/usr/bin/env python
2 # encoding: utf-8
3 """
4 Tests for IPython.config.configurable
5
6 Authors:
7
8 * Brian Granger
9 * Fernando Perez (design help)
10 """
11
12 #-----------------------------------------------------------------------------
13 # Copyright (C) 2008-2010 The IPython Development Team
14 #
15 # Distributed under the terms of the BSD License. The full license is in
16 # the file COPYING, distributed as part of this software.
17 #-----------------------------------------------------------------------------
18
19 #-----------------------------------------------------------------------------
20 # Imports
21 #-----------------------------------------------------------------------------
22
23 from unittest import TestCase
24
25 from IPython.config.configurable import Configurable, ConfigurableError
26 from IPython.utils.traitlets import (
27 TraitError, Int, Float, Str
28 )
29 from IPython.config.loader import Config
30
31
32 #-----------------------------------------------------------------------------
33 # Test cases
34 #-----------------------------------------------------------------------------
35
36
37 class MyConfigurable(Configurable):
38 a = Int(1, config=True)
39 b = Float(1.0, config=True)
40 c = Str('no config')
41
42
43 class Foo(Configurable):
44 a = Int(0, config=True)
45 b = Str('nope', config=True)
46
47
48 class Bar(Foo):
49 b = Str('gotit', config=False)
50 c = Float(config=True)
51
52
53 class TestConfigurableConfig(TestCase):
54
55 def test_default(self):
56 c1 = Configurable()
57 c2 = Configurable(config=c1.config)
58 c3 = Configurable(config=c2.config)
59 self.assertEquals(c1.config, c2.config)
60 self.assertEquals(c2.config, c3.config)
61
62 def test_custom(self):
63 config = Config()
64 config.foo = 'foo'
65 config.bar = 'bar'
66 c1 = Configurable(config=config)
67 c2 = Configurable(config=c1.config)
68 c3 = Configurable(config=c2.config)
69 self.assertEquals(c1.config, config)
70 self.assertEquals(c2.config, config)
71 self.assertEquals(c3.config, config)
72 # Test that copies are not made
73 self.assert_(c1.config is config)
74 self.assert_(c2.config is config)
75 self.assert_(c3.config is config)
76 self.assert_(c1.config is c2.config)
77 self.assert_(c2.config is c3.config)
78
79 def test_inheritance(self):
80 config = Config()
81 config.MyConfigurable.a = 2
82 config.MyConfigurable.b = 2.0
83 c1 = MyConfigurable(config=config)
84 c2 = MyConfigurable(config=c1.config)
85 self.assertEquals(c1.a, config.MyConfigurable.a)
86 self.assertEquals(c1.b, config.MyConfigurable.b)
87 self.assertEquals(c2.a, config.MyConfigurable.a)
88 self.assertEquals(c2.b, config.MyConfigurable.b)
89
90 def test_parent(self):
91 config = Config()
92 config.Foo.a = 10
93 config.Foo.b = "wow"
94 config.Bar.b = 'later'
95 config.Bar.c = 100.0
96 f = Foo(config=config)
97 b = Bar(config=f.config)
98 self.assertEquals(f.a, 10)
99 self.assertEquals(f.b, 'wow')
100 self.assertEquals(b.b, 'gotit')
101 self.assertEquals(b.c, 100.0)
102
103 def test_override1(self):
104 config = Config()
105 config.MyConfigurable.a = 2
106 config.MyConfigurable.b = 2.0
107 c = MyConfigurable(a=3, config=config)
108 self.assertEquals(c.a, 3)
109 self.assertEquals(c.b, config.MyConfigurable.b)
110 self.assertEquals(c.c, 'no config')
111
112 def test_override2(self):
113 config = Config()
114 config.Foo.a = 1
115 config.Bar.b = 'or' # Up above b is config=False, so this won't do it.
116 config.Bar.c = 10.0
117 c = Bar(config=config)
118 self.assertEquals(c.a, config.Foo.a)
119 self.assertEquals(c.b, 'gotit')
120 self.assertEquals(c.c, config.Bar.c)
121 c = Bar(a=2, b='and', c=20.0, config=config)
122 self.assertEquals(c.a, 2)
123 self.assertEquals(c.b, 'and')
124 self.assertEquals(c.c, 20.0)
@@ -0,0 +1,125 b''
1 # encoding: utf-8
2 """A class for managing IPython extensions.
3
4 Authors:
5
6 * Brian Granger
7 """
8
9 #-----------------------------------------------------------------------------
10 # Copyright (C) 2010 The IPython Development Team
11 #
12 # Distributed under the terms of the BSD License. The full license is in
13 # the file COPYING, distributed as part of this software.
14 #-----------------------------------------------------------------------------
15
16 #-----------------------------------------------------------------------------
17 # Imports
18 #-----------------------------------------------------------------------------
19
20 import os
21 import sys
22
23 from IPython.config.configurable import Configurable
24 from IPython.utils.traitlets import Instance
25
26 #-----------------------------------------------------------------------------
27 # Main class
28 #-----------------------------------------------------------------------------
29
30 class ExtensionManager(Configurable):
31 """A class to manage IPython extensions.
32
33 An IPython extension is an importable Python module that has
34 a function with the signature::
35
36 def load_ipython_extension(ipython):
37 # Do things with ipython
38
39 This function is called after your extension is imported and the
40 currently active :class:`InteractiveShell` instance is passed as
41 the only argument. You can do anything you want with IPython at
42 that point, including defining new magic and aliases, adding new
43 components, etc.
44
45 The :func:`load_ipython_extension` will be called again is you
46 load or reload the extension again. It is up to the extension
47 author to add code to manage that.
48
49 You can put your extension modules anywhere you want, as long as
50 they can be imported by Python's standard import mechanism. However,
51 to make it easy to write extensions, you can also put your extensions
52 in ``os.path.join(self.ipython_dir, 'extensions')``. This directory
53 is added to ``sys.path`` automatically.
54 """
55
56 shell = Instance('IPython.core.iplib.InteractiveShellABC')
57
58 def __init__(self, shell=None, config=None):
59 super(ExtensionManager, self).__init__(shell=shell, config=config)
60 self.shell.on_trait_change(
61 self._on_ipython_dir_changed, 'ipython_dir'
62 )
63
64 def __del__(self):
65 self.shell.on_trait_change(
66 self._on_ipython_dir_changed, 'ipython_dir', remove=True
67 )
68
69 @property
70 def ipython_extension_dir(self):
71 return os.path.join(self.shell.ipython_dir, u'extensions')
72
73 def _on_ipython_dir_changed(self):
74 if not os.path.isdir(self.ipython_extension_dir):
75 os.makedirs(self.ipython_extension_dir, mode = 0777)
76
77 def load_extension(self, module_str):
78 """Load an IPython extension by its module name.
79
80 If :func:`load_ipython_extension` returns anything, this function
81 will return that object.
82 """
83 from IPython.utils.syspathcontext import prepended_to_syspath
84
85 if module_str not in sys.modules:
86 with prepended_to_syspath(self.ipython_extension_dir):
87 __import__(module_str)
88 mod = sys.modules[module_str]
89 return self._call_load_ipython_extension(mod)
90
91 def unload_extension(self, module_str):
92 """Unload an IPython extension by its module name.
93
94 This function looks up the extension's name in ``sys.modules`` and
95 simply calls ``mod.unload_ipython_extension(self)``.
96 """
97 if module_str in sys.modules:
98 mod = sys.modules[module_str]
99 self._call_unload_ipython_extension(mod)
100
101 def reload_extension(self, module_str):
102 """Reload an IPython extension by calling reload.
103
104 If the module has not been loaded before,
105 :meth:`InteractiveShell.load_extension` is called. Otherwise
106 :func:`reload` is called and then the :func:`load_ipython_extension`
107 function of the module, if it exists is called.
108 """
109 from IPython.utils.syspathcontext import prepended_to_syspath
110
111 with prepended_to_syspath(self.ipython_extension_dir):
112 if module_str in sys.modules:
113 mod = sys.modules[module_str]
114 reload(mod)
115 self._call_load_ipython_extension(mod)
116 else:
117 self.load_extension(module_str)
118
119 def _call_load_ipython_extension(self, mod):
120 if hasattr(mod, 'load_ipython_extension'):
121 return mod.load_ipython_extension(self.shell)
122
123 def _call_unload_ipython_extension(self, mod):
124 if hasattr(mod, 'unload_ipython_extension'):
125 return mod.unload_ipython_extension(self.shell)
@@ -0,0 +1,51 b''
1 # encoding: utf-8
2 """IPython plugins.
3
4 Authors:
5
6 * Brian Granger
7 """
8
9 #-----------------------------------------------------------------------------
10 # Copyright (C) 2010 The IPython Development Team
11 #
12 # Distributed under the terms of the BSD License. The full license is in
13 # the file COPYING, distributed as part of this software.
14 #-----------------------------------------------------------------------------
15
16 #-----------------------------------------------------------------------------
17 # Imports
18 #-----------------------------------------------------------------------------
19
20 from IPython.config.configurable import Configurable
21 from IPython.utils.traitlets import Dict
22
23 #-----------------------------------------------------------------------------
24 # Main class
25 #-----------------------------------------------------------------------------
26
27 class PluginManager(Configurable):
28 """A manager for IPython plugins."""
29
30 plugins = Dict({})
31
32 def __init__(self, config=None):
33 super(PluginManager, self).__init__(config=config)
34
35 def register_plugin(self, name, plugin):
36 if not isinstance(plugin, Plugin):
37 raise TypeError('Expected Plugin, got: %r' % plugin)
38 if self.plugins.has_key(name):
39 raise KeyError('Plugin with name already exists: %r' % name)
40 self.plugins[name] = plugin
41
42 def unregister_plugin(self, name):
43 del self.plugins[name]
44
45 def get_plugin(self, name, default=None):
46 return self.plugins.get(name, default)
47
48
49 class Plugin(Configurable):
50 """Base class for IPython plugins."""
51 pass
@@ -0,0 +1,46 b''
1 """Tests for plugin.py"""
2
3 #-----------------------------------------------------------------------------
4 # Imports
5 #-----------------------------------------------------------------------------
6
7 from unittest import TestCase
8
9 from IPython.core.plugin import Plugin, PluginManager
10
11 #-----------------------------------------------------------------------------
12 # Tests
13 #-----------------------------------------------------------------------------
14
15 class FooPlugin(Plugin):
16 pass
17
18
19 class BarPlugin(Plugin):
20 pass
21
22
23 class BadPlugin(object):
24 pass
25
26
27 class PluginTest(TestCase):
28
29 def setUp(self):
30 self.manager = PluginManager()
31
32 def test_register_get(self):
33 self.assertEquals(None, self.manager.get_plugin('foo'))
34 foo = FooPlugin()
35 self.manager.register_plugin('foo', foo)
36 self.assertEquals(foo, self.manager.get_plugin('foo'))
37 bar = BarPlugin()
38 self.assertRaises(KeyError, self.manager.register_plugin, 'foo', bar)
39 bad = BadPlugin()
40 self.assertRaises(TypeError, self.manager.register_plugin, 'bad')
41
42 def test_unregister(self):
43 foo = FooPlugin()
44 self.manager.register_plugin('foo', foo)
45 self.manager.unregister_plugin('foo')
46 self.assertEquals(None, self.manager.get_plugin('foo'))
1 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
The requested commit or file is too big and content was truncated. Show full diff
@@ -1,66 +1,66 b''
1 1 #!/usr/bin/env python
2 2 # encoding: utf-8
3 3 """
4 4 IPython.
5 5
6 6 IPython is a set of tools for interactive and exploratory computing in Python.
7 7 """
8 8 #-----------------------------------------------------------------------------
9 9 # Copyright (C) 2008-2009 The IPython Development Team
10 10 #
11 11 # Distributed under the terms of the BSD License. The full license is in
12 12 # the file COPYING, distributed as part of this software.
13 13 #-----------------------------------------------------------------------------
14 14
15 15 #-----------------------------------------------------------------------------
16 16 # Imports
17 17 #-----------------------------------------------------------------------------
18 18 from __future__ import absolute_import
19 19
20 20 import os
21 21 import sys
22 22
23 23 #-----------------------------------------------------------------------------
24 24 # Setup everything
25 25 #-----------------------------------------------------------------------------
26 26
27 if sys.version[0:3] < '2.5':
28 raise ImportError('Python Version 2.5 or above is required for IPython.')
27 if sys.version[0:3] < '2.6':
28 raise ImportError('Python Version 2.6 or above is required for IPython.')
29 29
30 30
31 31 # Make it easy to import extensions - they are always directly on pythonpath.
32 32 # Therefore, non-IPython modules can be added to extensions directory.
33 33 # This should probably be in ipapp.py.
34 34 sys.path.append(os.path.join(os.path.dirname(__file__), "extensions"))
35 35
36 36 #-----------------------------------------------------------------------------
37 37 # Setup the top level names
38 38 #-----------------------------------------------------------------------------
39 39
40 40 from .config.loader import Config
41 41 from .core import release
42 42 from .core.application import Application
43 43 from .core.ipapp import IPythonApp
44 44 from .core.embed import embed
45 45 from .core.error import TryNext
46 46 from .core.iplib import InteractiveShell
47 47 from .testing import test
48 48
49 49 from .lib import (
50 50 enable_wx, disable_wx,
51 51 enable_gtk, disable_gtk,
52 52 enable_qt4, disable_qt4,
53 53 enable_tk, disable_tk,
54 54 set_inputhook, clear_inputhook,
55 55 current_gui, spin,
56 56 appstart_qt4, appstart_wx,
57 57 appstart_gtk, appstart_tk
58 58 )
59 59
60 60 # Release data
61 61 __author__ = ''
62 62 for author, email in release.authors.values():
63 63 __author__ += author + ' <' + email + '>\n'
64 64 __license__ = release.license
65 65 __version__ = release.version
66 66 __revision__ = release.revision
@@ -1,262 +1,258 b''
1 1 #!/usr/bin/env python
2 2 # encoding: utf-8
3 3 """
4 IPython's alias component
4 System command aliases.
5 5
6 6 Authors:
7 7
8 * Fernando Perez
8 9 * Brian Granger
9 10 """
10 11
11 12 #-----------------------------------------------------------------------------
12 13 # Copyright (C) 2008-2009 The IPython Development Team
13 14 #
14 15 # Distributed under the terms of the BSD License. The full license is in
15 16 # the file COPYING, distributed as part of this software.
16 17 #-----------------------------------------------------------------------------
17 18
18 19 #-----------------------------------------------------------------------------
19 20 # Imports
20 21 #-----------------------------------------------------------------------------
21 22
22 23 import __builtin__
23 24 import keyword
24 25 import os
25 26 import re
26 27 import sys
27 28
28 from IPython.core.component import Component
29 from IPython.config.configurable import Configurable
29 30 from IPython.core.splitinput import split_user_input
30 31
31 from IPython.utils.traitlets import List
32 from IPython.utils.traitlets import List, Instance
32 33 from IPython.utils.autoattr import auto_attr
33 34 from IPython.utils.warn import warn, error
34 35
35 36 #-----------------------------------------------------------------------------
36 37 # Utilities
37 38 #-----------------------------------------------------------------------------
38 39
39 40 # This is used as the pattern for calls to split_user_input.
40 41 shell_line_split = re.compile(r'^(\s*)(\S*\s*)(.*$)')
41 42
42 43 def default_aliases():
43 44 # Make some aliases automatically
44 45 # Prepare list of shell aliases to auto-define
45 46 if os.name == 'posix':
46 47 default_aliases = ('mkdir mkdir', 'rmdir rmdir',
47 48 'mv mv -i','rm rm -i','cp cp -i',
48 49 'cat cat','less less','clear clear',
49 50 # a better ls
50 51 'ls ls -F',
51 52 # long ls
52 53 'll ls -lF')
53 54 # Extra ls aliases with color, which need special treatment on BSD
54 55 # variants
55 56 ls_extra = ( # color ls
56 57 'lc ls -F -o --color',
57 58 # ls normal files only
58 59 'lf ls -F -o --color %l | grep ^-',
59 60 # ls symbolic links
60 61 'lk ls -F -o --color %l | grep ^l',
61 62 # directories or links to directories,
62 63 'ldir ls -F -o --color %l | grep /$',
63 64 # things which are executable
64 65 'lx ls -F -o --color %l | grep ^-..x',
65 66 )
66 67 # The BSDs don't ship GNU ls, so they don't understand the
67 68 # --color switch out of the box
68 69 if 'bsd' in sys.platform:
69 70 ls_extra = ( # ls normal files only
70 71 'lf ls -lF | grep ^-',
71 72 # ls symbolic links
72 73 'lk ls -lF | grep ^l',
73 74 # directories or links to directories,
74 75 'ldir ls -lF | grep /$',
75 76 # things which are executable
76 77 'lx ls -lF | grep ^-..x',
77 78 )
78 79 default_aliases = default_aliases + ls_extra
79 80 elif os.name in ['nt','dos']:
80 81 default_aliases = ('ls dir /on',
81 82 'ddir dir /ad /on', 'ldir dir /ad /on',
82 83 'mkdir mkdir','rmdir rmdir','echo echo',
83 84 'ren ren','cls cls','copy copy')
84 85 else:
85 86 default_aliases = ()
86 87 return [s.split(None,1) for s in default_aliases]
87 88
88 89
89 90 class AliasError(Exception):
90 91 pass
91 92
92 93
93 94 class InvalidAliasError(AliasError):
94 95 pass
95 96
96 97
97 98 #-----------------------------------------------------------------------------
98 99 # Main AliasManager class
99 100 #-----------------------------------------------------------------------------
100 101
101 102
102 class AliasManager(Component):
103 class AliasManager(Configurable):
103 104
104 105 default_aliases = List(default_aliases(), config=True)
105 106 user_aliases = List(default_value=[], config=True)
107 shell = Instance('IPython.core.iplib.InteractiveShellABC')
106 108
107 def __init__(self, parent, config=None):
108 super(AliasManager, self).__init__(parent, config=config)
109 def __init__(self, shell=None, config=None):
110 super(AliasManager, self).__init__(shell=shell, config=config)
109 111 self.alias_table = {}
110 112 self.exclude_aliases()
111 113 self.init_aliases()
112 114
113 @auto_attr
114 def shell(self):
115 return Component.get_instances(
116 root=self.root,
117 klass='IPython.core.iplib.InteractiveShell')[0]
118
119 115 def __contains__(self, name):
120 116 if name in self.alias_table:
121 117 return True
122 118 else:
123 119 return False
124 120
125 121 @property
126 122 def aliases(self):
127 123 return [(item[0], item[1][1]) for item in self.alias_table.iteritems()]
128 124
129 125 def exclude_aliases(self):
130 126 # set of things NOT to alias (keywords, builtins and some magics)
131 127 no_alias = set(['cd','popd','pushd','dhist','alias','unalias'])
132 128 no_alias.update(set(keyword.kwlist))
133 129 no_alias.update(set(__builtin__.__dict__.keys()))
134 130 self.no_alias = no_alias
135 131
136 132 def init_aliases(self):
137 133 # Load default aliases
138 134 for name, cmd in self.default_aliases:
139 135 self.soft_define_alias(name, cmd)
140 136
141 137 # Load user aliases
142 138 for name, cmd in self.user_aliases:
143 139 self.soft_define_alias(name, cmd)
144 140
145 141 def clear_aliases(self):
146 142 self.alias_table.clear()
147 143
148 144 def soft_define_alias(self, name, cmd):
149 145 """Define an alias, but don't raise on an AliasError."""
150 146 try:
151 147 self.define_alias(name, cmd)
152 148 except AliasError, e:
153 149 error("Invalid alias: %s" % e)
154 150
155 151 def define_alias(self, name, cmd):
156 152 """Define a new alias after validating it.
157 153
158 154 This will raise an :exc:`AliasError` if there are validation
159 155 problems.
160 156 """
161 157 nargs = self.validate_alias(name, cmd)
162 158 self.alias_table[name] = (nargs, cmd)
163 159
164 160 def undefine_alias(self, name):
165 161 if self.alias_table.has_key(name):
166 162 del self.alias_table[name]
167 163
168 164 def validate_alias(self, name, cmd):
169 165 """Validate an alias and return the its number of arguments."""
170 166 if name in self.no_alias:
171 167 raise InvalidAliasError("The name %s can't be aliased "
172 168 "because it is a keyword or builtin." % name)
173 169 if not (isinstance(cmd, basestring)):
174 170 raise InvalidAliasError("An alias command must be a string, "
175 171 "got: %r" % name)
176 172 nargs = cmd.count('%s')
177 173 if nargs>0 and cmd.find('%l')>=0:
178 174 raise InvalidAliasError('The %s and %l specifiers are mutually '
179 175 'exclusive in alias definitions.')
180 176 return nargs
181 177
182 178 def call_alias(self, alias, rest=''):
183 179 """Call an alias given its name and the rest of the line."""
184 180 cmd = self.transform_alias(alias, rest)
185 181 try:
186 182 self.shell.system(cmd)
187 183 except:
188 184 self.shell.showtraceback()
189 185
190 186 def transform_alias(self, alias,rest=''):
191 187 """Transform alias to system command string."""
192 188 nargs, cmd = self.alias_table[alias]
193 189
194 190 if ' ' in cmd and os.path.isfile(cmd):
195 191 cmd = '"%s"' % cmd
196 192
197 193 # Expand the %l special to be the user's input line
198 194 if cmd.find('%l') >= 0:
199 195 cmd = cmd.replace('%l', rest)
200 196 rest = ''
201 197 if nargs==0:
202 198 # Simple, argument-less aliases
203 199 cmd = '%s %s' % (cmd, rest)
204 200 else:
205 201 # Handle aliases with positional arguments
206 202 args = rest.split(None, nargs)
207 203 if len(args) < nargs:
208 204 raise AliasError('Alias <%s> requires %s arguments, %s given.' %
209 205 (alias, nargs, len(args)))
210 206 cmd = '%s %s' % (cmd % tuple(args[:nargs]),' '.join(args[nargs:]))
211 207 return cmd
212 208
213 209 def expand_alias(self, line):
214 210 """ Expand an alias in the command line
215 211
216 212 Returns the provided command line, possibly with the first word
217 213 (command) translated according to alias expansion rules.
218 214
219 215 [ipython]|16> _ip.expand_aliases("np myfile.txt")
220 216 <16> 'q:/opt/np/notepad++.exe myfile.txt'
221 217 """
222 218
223 219 pre,fn,rest = split_user_input(line)
224 220 res = pre + self.expand_aliases(fn, rest)
225 221 return res
226 222
227 223 def expand_aliases(self, fn, rest):
228 224 """Expand multiple levels of aliases:
229 225
230 226 if:
231 227
232 228 alias foo bar /tmp
233 229 alias baz foo
234 230
235 231 then:
236 232
237 233 baz huhhahhei -> bar /tmp huhhahhei
238 234
239 235 """
240 236 line = fn + " " + rest
241 237
242 238 done = set()
243 239 while 1:
244 240 pre,fn,rest = split_user_input(line, shell_line_split)
245 241 if fn in self.alias_table:
246 242 if fn in done:
247 243 warn("Cyclic alias definition, repeated '%s'" % fn)
248 244 return ""
249 245 done.add(fn)
250 246
251 247 l2 = self.transform_alias(fn, rest)
252 248 if l2 == line:
253 249 break
254 250 # ls -> ls -F should not recurse forever
255 251 if l2.split(None,1)[0] == line.split(None,1)[0]:
256 252 line = l2
257 253 break
258 254 line=l2
259 255 else:
260 256 break
261 257
262 258 return line
@@ -1,453 +1,453 b''
1 1 # encoding: utf-8
2 2 """
3 3 An application for IPython.
4 4
5 5 All top-level applications should use the classes in this module for
6 6 handling configuration and creating componenets.
7 7
8 8 The job of an :class:`Application` is to create the master configuration
9 object and then create the components, passing the config to them.
9 object and then create the configurable objects, passing the config to them.
10 10
11 11 Authors:
12 12
13 13 * Brian Granger
14 14 * Fernando Perez
15 15
16 16 Notes
17 17 -----
18 18 """
19 19
20 20 #-----------------------------------------------------------------------------
21 21 # Copyright (C) 2008-2009 The IPython Development Team
22 22 #
23 23 # Distributed under the terms of the BSD License. The full license is in
24 24 # the file COPYING, distributed as part of this software.
25 25 #-----------------------------------------------------------------------------
26 26
27 27 #-----------------------------------------------------------------------------
28 28 # Imports
29 29 #-----------------------------------------------------------------------------
30 30
31 31 import logging
32 32 import os
33 33 import sys
34 34
35 35 from IPython.core import release, crashhandler
36 36 from IPython.utils.path import get_ipython_dir, get_ipython_package_dir
37 37 from IPython.config.loader import (
38 38 PyFileConfigLoader,
39 39 ArgParseConfigLoader,
40 40 Config,
41 41 )
42 42
43 43 #-----------------------------------------------------------------------------
44 44 # Classes and functions
45 45 #-----------------------------------------------------------------------------
46 46
47 47 class ApplicationError(Exception):
48 48 pass
49 49
50 50
51 51 class BaseAppConfigLoader(ArgParseConfigLoader):
52 52 """Default command line options for IPython based applications."""
53 53
54 54 def _add_ipython_dir(self, parser):
55 55 """Add the --ipython-dir option to the parser."""
56 56 paa = parser.add_argument
57 57 paa('--ipython-dir',
58 58 dest='Global.ipython_dir',type=unicode,
59 59 help=
60 60 """Set to override default location of the IPython directory
61 61 IPYTHON_DIR, stored as Global.ipython_dir. This can also be
62 62 specified through the environment variable IPYTHON_DIR.""",
63 63 metavar='Global.ipython_dir')
64 64
65 65 def _add_log_level(self, parser):
66 66 """Add the --log-level option to the parser."""
67 67 paa = parser.add_argument
68 68 paa('--log-level',
69 69 dest="Global.log_level",type=int,
70 70 help='Set the log level (0,10,20,30,40,50). Default is 30.',
71 71 metavar='Global.log_level')
72 72
73 73 def _add_arguments(self):
74 74 self._add_ipython_dir(self.parser)
75 75 self._add_log_level(self.parser)
76 76
77 77
78 78 class Application(object):
79 """Load a config, construct components and set them running.
79 """Load a config, construct configurables and set them running.
80 80
81 81 The configuration of an application can be done via three different Config
82 82 objects, which are loaded and ultimately merged into a single one used
83 83 from that point on by the app. These are:
84 84
85 85 1. default_config: internal defaults, implemented in code.
86 86 2. file_config: read from the filesystem.
87 87 3. command_line_config: read from the system's command line flags.
88 88
89 89 During initialization, 3 is actually read before 2, since at the
90 90 command-line one may override the location of the file to be read. But the
91 91 above is the order in which the merge is made.
92 92 """
93 93
94 94 name = u'ipython'
95 95 description = 'IPython: an enhanced interactive Python shell.'
96 96 #: Usage message printed by argparse. If None, auto-generate
97 97 usage = None
98 98 #: The command line config loader. Subclass of ArgParseConfigLoader.
99 99 command_line_loader = BaseAppConfigLoader
100 100 #: The name of the config file to load, determined at runtime
101 101 config_file_name = None
102 102 #: The name of the default config file. Track separately from the actual
103 103 #: name because some logic happens only if we aren't using the default.
104 104 default_config_file_name = u'ipython_config.py'
105 105 default_log_level = logging.WARN
106 106 #: Set by --profile option
107 107 profile_name = None
108 108 #: User's ipython directory, typically ~/.ipython/
109 109 ipython_dir = None
110 110 #: Internal defaults, implemented in code.
111 111 default_config = None
112 112 #: Read from the filesystem.
113 113 file_config = None
114 114 #: Read from the system's command line flags.
115 115 command_line_config = None
116 #: The final config that will be passed to the component.
116 #: The final config that will be passed to the main object.
117 117 master_config = None
118 118 #: A reference to the argv to be used (typically ends up being sys.argv[1:])
119 119 argv = None
120 120 #: extra arguments computed by the command-line loader
121 121 extra_args = None
122 122 #: The class to use as the crash handler.
123 123 crash_handler_class = crashhandler.CrashHandler
124 124
125 125 # Private attributes
126 126 _exiting = False
127 127 _initialized = False
128 128
129 129 def __init__(self, argv=None):
130 130 self.argv = sys.argv[1:] if argv is None else argv
131 131 self.init_logger()
132 132
133 133 def init_logger(self):
134 134 self.log = logging.getLogger(self.__class__.__name__)
135 135 # This is used as the default until the command line arguments are read.
136 136 self.log.setLevel(self.default_log_level)
137 137 self._log_handler = logging.StreamHandler()
138 138 self._log_formatter = logging.Formatter("[%(name)s] %(message)s")
139 139 self._log_handler.setFormatter(self._log_formatter)
140 140 self.log.addHandler(self._log_handler)
141 141
142 142 def _set_log_level(self, level):
143 143 self.log.setLevel(level)
144 144
145 145 def _get_log_level(self):
146 146 return self.log.level
147 147
148 148 log_level = property(_get_log_level, _set_log_level)
149 149
150 150 def initialize(self):
151 151 """Initialize the application.
152 152
153 153 Loads all configuration information and sets all application state, but
154 154 does not start any relevant processing (typically some kind of event
155 155 loop).
156 156
157 157 Once this method has been called, the application is flagged as
158 158 initialized and the method becomes a no-op."""
159 159
160 160 if self._initialized:
161 161 return
162 162
163 163 # The first part is protected with an 'attempt' wrapper, that will log
164 164 # failures with the basic system traceback machinery. Once our crash
165 165 # handler is in place, we can let any subsequent exception propagate,
166 166 # as our handler will log it with much better detail than the default.
167 167 self.attempt(self.create_crash_handler)
168 168
169 169 # Configuration phase
170 170 # Default config (internally hardwired in application code)
171 171 self.create_default_config()
172 172 self.log_default_config()
173 173 self.set_default_config_log_level()
174 174
175 175 # Command-line config
176 176 self.pre_load_command_line_config()
177 177 self.load_command_line_config()
178 178 self.set_command_line_config_log_level()
179 179 self.post_load_command_line_config()
180 180 self.log_command_line_config()
181 181
182 182 # Find resources needed for filesystem access, using information from
183 183 # the above two
184 184 self.find_ipython_dir()
185 185 self.find_resources()
186 186 self.find_config_file_name()
187 187 self.find_config_file_paths()
188 188
189 189 # File-based config
190 190 self.pre_load_file_config()
191 191 self.load_file_config()
192 192 self.set_file_config_log_level()
193 193 self.post_load_file_config()
194 194 self.log_file_config()
195 195
196 196 # Merge all config objects into a single one the app can then use
197 197 self.merge_configs()
198 198 self.log_master_config()
199 199
200 200 # Construction phase
201 201 self.pre_construct()
202 202 self.construct()
203 203 self.post_construct()
204 204
205 205 # Done, flag as such and
206 206 self._initialized = True
207 207
208 208 def start(self):
209 209 """Start the application."""
210 210 self.initialize()
211 211 self.start_app()
212 212
213 213 #-------------------------------------------------------------------------
214 214 # Various stages of Application creation
215 215 #-------------------------------------------------------------------------
216 216
217 217 def create_crash_handler(self):
218 218 """Create a crash handler, typically setting sys.excepthook to it."""
219 219 self.crash_handler = self.crash_handler_class(self)
220 220 sys.excepthook = self.crash_handler
221 221
222 222 def create_default_config(self):
223 223 """Create defaults that can't be set elsewhere.
224 224
225 225 For the most part, we try to set default in the class attributes
226 of Components. But, defaults the top-level Application (which is
227 not a HasTraits or Component) are not set in this way. Instead
226 of Configurables. But, defaults the top-level Application (which is
227 not a HasTraits or Configurables) are not set in this way. Instead
228 228 we set them here. The Global section is for variables like this that
229 don't belong to a particular component.
229 don't belong to a particular configurable.
230 230 """
231 231 c = Config()
232 232 c.Global.ipython_dir = get_ipython_dir()
233 233 c.Global.log_level = self.log_level
234 234 self.default_config = c
235 235
236 236 def log_default_config(self):
237 237 self.log.debug('Default config loaded:')
238 238 self.log.debug(repr(self.default_config))
239 239
240 240 def set_default_config_log_level(self):
241 241 try:
242 242 self.log_level = self.default_config.Global.log_level
243 243 except AttributeError:
244 244 # Fallback to the default_log_level class attribute
245 245 pass
246 246
247 247 def create_command_line_config(self):
248 248 """Create and return a command line config loader."""
249 249 return self.command_line_loader(
250 250 self.argv,
251 251 description=self.description,
252 252 version=release.version,
253 253 usage=self.usage
254 254 )
255 255
256 256 def pre_load_command_line_config(self):
257 257 """Do actions just before loading the command line config."""
258 258 pass
259 259
260 260 def load_command_line_config(self):
261 261 """Load the command line config."""
262 262 loader = self.create_command_line_config()
263 263 self.command_line_config = loader.load_config()
264 264 self.extra_args = loader.get_extra_args()
265 265
266 266 def set_command_line_config_log_level(self):
267 267 try:
268 268 self.log_level = self.command_line_config.Global.log_level
269 269 except AttributeError:
270 270 pass
271 271
272 272 def post_load_command_line_config(self):
273 273 """Do actions just after loading the command line config."""
274 274 pass
275 275
276 276 def log_command_line_config(self):
277 277 self.log.debug("Command line config loaded:")
278 278 self.log.debug(repr(self.command_line_config))
279 279
280 280 def find_ipython_dir(self):
281 281 """Set the IPython directory.
282 282
283 283 This sets ``self.ipython_dir``, but the actual value that is passed to
284 284 the application is kept in either ``self.default_config`` or
285 285 ``self.command_line_config``. This also adds ``self.ipython_dir`` to
286 286 ``sys.path`` so config files there can be referenced by other config
287 287 files.
288 288 """
289 289
290 290 try:
291 291 self.ipython_dir = self.command_line_config.Global.ipython_dir
292 292 except AttributeError:
293 293 self.ipython_dir = self.default_config.Global.ipython_dir
294 294 sys.path.append(os.path.abspath(self.ipython_dir))
295 295 if not os.path.isdir(self.ipython_dir):
296 296 os.makedirs(self.ipython_dir, mode=0777)
297 297 self.log.debug("IPYTHON_DIR set to: %s" % self.ipython_dir)
298 298
299 299 def find_resources(self):
300 300 """Find other resources that need to be in place.
301 301
302 302 Things like cluster directories need to be in place to find the
303 303 config file. These happen right after the IPython directory has
304 304 been set.
305 305 """
306 306 pass
307 307
308 308 def find_config_file_name(self):
309 309 """Find the config file name for this application.
310 310
311 311 This must set ``self.config_file_name`` to the filename of the
312 312 config file to use (just the filename). The search paths for the
313 313 config file are set in :meth:`find_config_file_paths` and then passed
314 314 to the config file loader where they are resolved to an absolute path.
315 315
316 316 If a profile has been set at the command line, this will resolve it.
317 317 """
318 318 try:
319 319 self.config_file_name = self.command_line_config.Global.config_file
320 320 except AttributeError:
321 321 pass
322 322 else:
323 323 return
324 324
325 325 try:
326 326 self.profile_name = self.command_line_config.Global.profile
327 327 except AttributeError:
328 328 # Just use the default as there is no profile
329 329 self.config_file_name = self.default_config_file_name
330 330 else:
331 331 # Use the default config file name and profile name if set
332 332 # to determine the used config file name.
333 333 name_parts = self.default_config_file_name.split('.')
334 334 name_parts.insert(1, u'_' + self.profile_name + u'.')
335 335 self.config_file_name = ''.join(name_parts)
336 336
337 337 def find_config_file_paths(self):
338 338 """Set the search paths for resolving the config file.
339 339
340 340 This must set ``self.config_file_paths`` to a sequence of search
341 341 paths to pass to the config file loader.
342 342 """
343 343 # Include our own profiles directory last, so that users can still find
344 344 # our shipped copies of builtin profiles even if they don't have them
345 345 # in their local ipython directory.
346 346 prof_dir = os.path.join(get_ipython_package_dir(), 'config', 'profile')
347 347 self.config_file_paths = (os.getcwd(), self.ipython_dir, prof_dir)
348 348
349 349 def pre_load_file_config(self):
350 350 """Do actions before the config file is loaded."""
351 351 pass
352 352
353 353 def load_file_config(self):
354 354 """Load the config file.
355 355
356 356 This tries to load the config file from disk. If successful, the
357 357 ``CONFIG_FILE`` config variable is set to the resolved config file
358 358 location. If not successful, an empty config is used.
359 359 """
360 360 self.log.debug("Attempting to load config file: %s" %
361 361 self.config_file_name)
362 362 loader = PyFileConfigLoader(self.config_file_name,
363 363 path=self.config_file_paths)
364 364 try:
365 365 self.file_config = loader.load_config()
366 366 self.file_config.Global.config_file = loader.full_filename
367 367 except IOError:
368 368 # Only warn if the default config file was NOT being used.
369 369 if not self.config_file_name==self.default_config_file_name:
370 370 self.log.warn("Config file not found, skipping: %s" %
371 371 self.config_file_name, exc_info=True)
372 372 self.file_config = Config()
373 373 except:
374 374 self.log.warn("Error loading config file: %s" %
375 375 self.config_file_name, exc_info=True)
376 376 self.file_config = Config()
377 377
378 378 def set_file_config_log_level(self):
379 379 # We need to keeep self.log_level updated. But we only use the value
380 380 # of the file_config if a value was not specified at the command
381 381 # line, because the command line overrides everything.
382 382 if not hasattr(self.command_line_config.Global, 'log_level'):
383 383 try:
384 384 self.log_level = self.file_config.Global.log_level
385 385 except AttributeError:
386 386 pass # Use existing value
387 387
388 388 def post_load_file_config(self):
389 389 """Do actions after the config file is loaded."""
390 390 pass
391 391
392 392 def log_file_config(self):
393 393 if hasattr(self.file_config.Global, 'config_file'):
394 394 self.log.debug("Config file loaded: %s" %
395 395 self.file_config.Global.config_file)
396 396 self.log.debug(repr(self.file_config))
397 397
398 398 def merge_configs(self):
399 399 """Merge the default, command line and file config objects."""
400 400 config = Config()
401 401 config._merge(self.default_config)
402 402 config._merge(self.file_config)
403 403 config._merge(self.command_line_config)
404 404
405 405 # XXX fperez - propose to Brian we rename master_config to simply
406 406 # config, I think this is going to be heavily used in examples and
407 407 # application code and the name is shorter/easier to find/remember.
408 408 # For now, just alias it...
409 409 self.master_config = config
410 410 self.config = config
411 411
412 412 def log_master_config(self):
413 413 self.log.debug("Master config created:")
414 414 self.log.debug(repr(self.master_config))
415 415
416 416 def pre_construct(self):
417 417 """Do actions after the config has been built, but before construct."""
418 418 pass
419 419
420 420 def construct(self):
421 """Construct the main components that make up this app."""
422 self.log.debug("Constructing components for application")
421 """Construct the main objects that make up this app."""
422 self.log.debug("Constructing main objects for application")
423 423
424 424 def post_construct(self):
425 425 """Do actions after construct, but before starting the app."""
426 426 pass
427 427
428 428 def start_app(self):
429 429 """Actually start the app."""
430 430 self.log.debug("Starting application")
431 431
432 432 #-------------------------------------------------------------------------
433 433 # Utility methods
434 434 #-------------------------------------------------------------------------
435 435
436 436 def exit(self, exit_status=0):
437 437 if self._exiting:
438 438 pass
439 439 else:
440 440 self.log.debug("Exiting application: %s" % self.name)
441 441 self._exiting = True
442 442 sys.exit(exit_status)
443 443
444 444 def attempt(self, func):
445 445 try:
446 446 func()
447 447 except SystemExit:
448 448 raise
449 449 except:
450 450 self.log.critical("Aborting application: %s" % self.name,
451 451 exc_info=True)
452 452 self.exit(0)
453 453
@@ -1,118 +1,115 b''
1 1 #!/usr/bin/env python
2 2 # encoding: utf-8
3 3 """
4 4 A context manager for managing things injected into :mod:`__builtin__`.
5 5
6 6 Authors:
7 7
8 8 * Brian Granger
9 9 """
10 10
11 11 #-----------------------------------------------------------------------------
12 12 # Copyright (C) 2008-2009 The IPython Development Team
13 13 #
14 14 # Distributed under the terms of the BSD License. The full license is in
15 15 # the file COPYING, distributed as part of this software.
16 16 #-----------------------------------------------------------------------------
17 17
18 18 #-----------------------------------------------------------------------------
19 19 # Imports
20 20 #-----------------------------------------------------------------------------
21 21
22 22 import __builtin__
23 23
24 from IPython.core.component import Component
24 from IPython.config.configurable import Configurable
25 25 from IPython.core.quitter import Quitter
26 26
27 from IPython.utils.autoattr import auto_attr
27 from IPython.utils.traitlets import Instance
28 28
29 29 #-----------------------------------------------------------------------------
30 30 # Classes and functions
31 31 #-----------------------------------------------------------------------------
32 32
33 33
34 34 class __BuiltinUndefined(object): pass
35 35 BuiltinUndefined = __BuiltinUndefined()
36 36
37 37
38 class BuiltinTrap(Component):
38 class BuiltinTrap(Configurable):
39 39
40 def __init__(self, parent):
41 super(BuiltinTrap, self).__init__(parent, None, None)
40 shell = Instance('IPython.core.iplib.InteractiveShellABC')
41
42 def __init__(self, shell=None):
43 super(BuiltinTrap, self).__init__(shell=shell, config=None)
42 44 self._orig_builtins = {}
43 45 # We define this to track if a single BuiltinTrap is nested.
44 46 # Only turn off the trap when the outermost call to __exit__ is made.
45 47 self._nested_level = 0
46
47 @auto_attr
48 def shell(self):
49 return Component.get_instances(
50 root=self.root,
51 klass='IPython.core.iplib.InteractiveShell')[0]
48 self.shell = shell
52 49
53 50 def __enter__(self):
54 51 if self._nested_level == 0:
55 52 self.set()
56 53 self._nested_level += 1
57 54 # I return self, so callers can use add_builtin in a with clause.
58 55 return self
59 56
60 57 def __exit__(self, type, value, traceback):
61 58 if self._nested_level == 1:
62 59 self.unset()
63 60 self._nested_level -= 1
64 61 # Returning False will cause exceptions to propagate
65 62 return False
66 63
67 64 def add_builtin(self, key, value):
68 65 """Add a builtin and save the original."""
69 66 orig = __builtin__.__dict__.get(key, BuiltinUndefined)
70 67 self._orig_builtins[key] = orig
71 68 __builtin__.__dict__[key] = value
72 69
73 70 def remove_builtin(self, key):
74 71 """Remove an added builtin and re-set the original."""
75 72 try:
76 73 orig = self._orig_builtins.pop(key)
77 74 except KeyError:
78 75 pass
79 76 else:
80 77 if orig is BuiltinUndefined:
81 78 del __builtin__.__dict__[key]
82 79 else:
83 80 __builtin__.__dict__[key] = orig
84 81
85 82 def set(self):
86 83 """Store ipython references in the __builtin__ namespace."""
87 84 self.add_builtin('exit', Quitter(self.shell, 'exit'))
88 85 self.add_builtin('quit', Quitter(self.shell, 'quit'))
89 86 self.add_builtin('get_ipython', self.shell.get_ipython)
90 87
91 88 # Recursive reload function
92 89 try:
93 90 from IPython.lib import deepreload
94 91 if self.shell.deep_reload:
95 92 self.add_builtin('reload', deepreload.reload)
96 93 else:
97 94 self.add_builtin('dreload', deepreload.reload)
98 95 del deepreload
99 96 except ImportError:
100 97 pass
101 98
102 99 # Keep in the builtins a flag for when IPython is active. We set it
103 100 # with setdefault so that multiple nested IPythons don't clobber one
104 101 # another. Each will increase its value by one upon being activated,
105 102 # which also gives us a way to determine the nesting level.
106 103 __builtin__.__dict__.setdefault('__IPYTHON__active',0)
107 104
108 105 def unset(self):
109 106 """Remove any builtins which might have been added by add_builtins, or
110 107 restore overwritten ones to their previous values."""
111 108 for key in self._orig_builtins.keys():
112 109 self.remove_builtin(key)
113 110 self._orig_builtins.clear()
114 111 self._builtins_added = False
115 112 try:
116 113 del __builtin__.__dict__['__IPYTHON__active']
117 114 except KeyError:
118 115 pass
@@ -1,75 +1,71 b''
1 1 #!/usr/bin/env python
2 2 # encoding: utf-8
3 3 """
4 4 A context manager for handling sys.displayhook.
5 5
6 6 Authors:
7 7
8 8 * Robert Kern
9 9 * Brian Granger
10 10 """
11 11
12 12 #-----------------------------------------------------------------------------
13 13 # Copyright (C) 2008-2009 The IPython Development Team
14 14 #
15 15 # Distributed under the terms of the BSD License. The full license is in
16 16 # the file COPYING, distributed as part of this software.
17 17 #-----------------------------------------------------------------------------
18 18
19 19 #-----------------------------------------------------------------------------
20 20 # Imports
21 21 #-----------------------------------------------------------------------------
22 22
23 23 import sys
24 24
25 from IPython.core.component import Component
25 from IPython.config.configurable import Configurable
26 from IPython.utils.traitlets import Any
26 27
27 28 #-----------------------------------------------------------------------------
28 29 # Classes and functions
29 30 #-----------------------------------------------------------------------------
30 31
31 32
32 class DisplayTrap(Component):
33 class DisplayTrap(Configurable):
33 34 """Object to manage sys.displayhook.
34 35
35 36 This came from IPython.core.kernel.display_hook, but is simplified
36 37 (no callbacks or formatters) until more of the core is refactored.
37 38 """
38 39
39 def __init__(self, parent, hook):
40 super(DisplayTrap, self).__init__(parent, None, None)
41 self.hook = hook
40 hook = Any
41
42 def __init__(self, hook=None):
43 super(DisplayTrap, self).__init__(hook=hook, config=None)
42 44 self.old_hook = None
43 45 # We define this to track if a single BuiltinTrap is nested.
44 46 # Only turn off the trap when the outermost call to __exit__ is made.
45 47 self._nested_level = 0
46 48
47 # @auto_attr
48 # def shell(self):
49 # return Component.get_instances(
50 # root=self.root,
51 # klass='IPython.core.iplib.InteractiveShell')[0]
52
53 49 def __enter__(self):
54 50 if self._nested_level == 0:
55 51 self.set()
56 52 self._nested_level += 1
57 53 return self
58 54
59 55 def __exit__(self, type, value, traceback):
60 56 if self._nested_level == 1:
61 57 self.unset()
62 58 self._nested_level -= 1
63 59 # Returning False will cause exceptions to propagate
64 60 return False
65 61
66 62 def set(self):
67 63 """Set the hook."""
68 64 if sys.displayhook is not self.hook:
69 65 self.old_hook = sys.displayhook
70 66 sys.displayhook = self.hook
71 67
72 68 def unset(self):
73 69 """Unset the hook."""
74 70 sys.displayhook = self.old_hook
75 71
@@ -1,36 +1,30 b''
1 1 #!/usr/bin/env python
2 2 # encoding: utf-8
3 3 """
4 4 This module is *completely* deprecated and should no longer be used for
5 5 any purpose. Currently, we have a few parts of the core that have
6 6 not been componentized and thus, still rely on this module. When everything
7 7 has been made into a component, this module will be sent to deathrow.
8 8 """
9 9
10 10 #-----------------------------------------------------------------------------
11 11 # Copyright (C) 2008-2009 The IPython Development Team
12 12 #
13 13 # Distributed under the terms of the BSD License. The full license is in
14 14 # the file COPYING, distributed as part of this software.
15 15 #-----------------------------------------------------------------------------
16 16
17 17 #-----------------------------------------------------------------------------
18 18 # Imports
19 19 #-----------------------------------------------------------------------------
20 20
21 21 #-----------------------------------------------------------------------------
22 22 # Classes and functions
23 23 #-----------------------------------------------------------------------------
24 24
25 25
26 26 def get():
27 """Get the most recently created InteractiveShell instance."""
27 """Get the global InteractiveShell instance."""
28 28 from IPython.core.iplib import InteractiveShell
29 insts = InteractiveShell.get_instances()
30 if len(insts)==0:
31 return None
32 most_recent = insts[0]
33 for inst in insts[1:]:
34 if inst.created > most_recent.created:
35 most_recent = inst
36 return most_recent
29 return InteractiveShell.instance()
30
@@ -1,665 +1,665 b''
1 1 #!/usr/bin/env python
2 2 # encoding: utf-8
3 3 """
4 4 The :class:`~IPython.core.application.Application` object for the command
5 5 line :command:`ipython` program.
6 6
7 7 Authors
8 8 -------
9 9
10 10 * Brian Granger
11 11 * Fernando Perez
12 12 """
13 13
14 14 #-----------------------------------------------------------------------------
15 15 # Copyright (C) 2008-2010 The IPython Development Team
16 16 #
17 17 # Distributed under the terms of the BSD License. The full license is in
18 18 # the file COPYING, distributed as part of this software.
19 19 #-----------------------------------------------------------------------------
20 20
21 21 #-----------------------------------------------------------------------------
22 22 # Imports
23 23 #-----------------------------------------------------------------------------
24 24
25 25 from __future__ import absolute_import
26 26
27 27 import logging
28 28 import os
29 29 import sys
30 30
31 31 from IPython.core import release
32 32 from IPython.core.crashhandler import CrashHandler
33 33 from IPython.core.application import Application, BaseAppConfigLoader
34 34 from IPython.core.iplib import InteractiveShell
35 35 from IPython.config.loader import (
36 36 Config,
37 37 PyFileConfigLoader
38 38 )
39 39 from IPython.lib import inputhook
40 40 from IPython.utils.path import filefind, get_ipython_dir
41 41 from . import usage
42 42
43 43 #-----------------------------------------------------------------------------
44 44 # Globals, utilities and helpers
45 45 #-----------------------------------------------------------------------------
46 46
47 47 #: The default config file name for this application.
48 48 default_config_file_name = u'ipython_config.py'
49 49
50 50
51 51 class IPAppConfigLoader(BaseAppConfigLoader):
52 52
53 53 def _add_arguments(self):
54 54 super(IPAppConfigLoader, self)._add_arguments()
55 55 paa = self.parser.add_argument
56 56 paa('-p',
57 57 '--profile', dest='Global.profile', type=unicode,
58 58 help=
59 59 """The string name of the ipython profile to be used. Assume that your
60 60 config file is ipython_config-<name>.py (looks in current dir first,
61 61 then in IPYTHON_DIR). This is a quick way to keep and load multiple
62 62 config files for different tasks, especially if include your basic one
63 63 in your more specialized ones. You can keep a basic
64 64 IPYTHON_DIR/ipython_config.py file and then have other 'profiles' which
65 65 include this one and load extra things for particular tasks.""",
66 66 metavar='Global.profile')
67 67 paa('--config-file',
68 68 dest='Global.config_file', type=unicode,
69 69 help=
70 70 """Set the config file name to override default. Normally IPython
71 71 loads ipython_config.py (from current directory) or
72 72 IPYTHON_DIR/ipython_config.py. If the loading of your config file
73 73 fails, IPython starts with a bare bones configuration (no modules
74 74 loaded at all).""",
75 75 metavar='Global.config_file')
76 76 paa('--autocall',
77 77 dest='InteractiveShell.autocall', type=int,
78 78 help=
79 79 """Make IPython automatically call any callable object even if you
80 80 didn't type explicit parentheses. For example, 'str 43' becomes
81 81 'str(43)' automatically. The value can be '0' to disable the feature,
82 82 '1' for 'smart' autocall, where it is not applied if there are no more
83 83 arguments on the line, and '2' for 'full' autocall, where all callable
84 84 objects are automatically called (even if no arguments are present).
85 85 The default is '1'.""",
86 86 metavar='InteractiveShell.autocall')
87 87 paa('--autoindent',
88 88 action='store_true', dest='InteractiveShell.autoindent',
89 89 help='Turn on autoindenting.')
90 90 paa('--no-autoindent',
91 91 action='store_false', dest='InteractiveShell.autoindent',
92 92 help='Turn off autoindenting.')
93 93 paa('--automagic',
94 94 action='store_true', dest='InteractiveShell.automagic',
95 95 help=
96 96 """Turn on the auto calling of magic commands. Type %%magic at the
97 97 IPython prompt for more information.""")
98 98 paa('--no-automagic',
99 99 action='store_false', dest='InteractiveShell.automagic',
100 100 help='Turn off the auto calling of magic commands.')
101 101 paa('--autoedit-syntax',
102 102 action='store_true', dest='InteractiveShell.autoedit_syntax',
103 103 help='Turn on auto editing of files with syntax errors.')
104 104 paa('--no-autoedit-syntax',
105 105 action='store_false', dest='InteractiveShell.autoedit_syntax',
106 106 help='Turn off auto editing of files with syntax errors.')
107 107 paa('--banner',
108 108 action='store_true', dest='Global.display_banner',
109 109 help='Display a banner upon starting IPython.')
110 110 paa('--no-banner',
111 111 action='store_false', dest='Global.display_banner',
112 112 help="Don't display a banner upon starting IPython.")
113 113 paa('--cache-size',
114 114 type=int, dest='InteractiveShell.cache_size',
115 115 help=
116 116 """Set the size of the output cache. The default is 1000, you can
117 117 change it permanently in your config file. Setting it to 0 completely
118 118 disables the caching system, and the minimum value accepted is 20 (if
119 119 you provide a value less than 20, it is reset to 0 and a warning is
120 120 issued). This limit is defined because otherwise you'll spend more
121 121 time re-flushing a too small cache than working""",
122 122 metavar='InteractiveShell.cache_size')
123 123 paa('--classic',
124 124 action='store_true', dest='Global.classic',
125 125 help="Gives IPython a similar feel to the classic Python prompt.")
126 126 paa('--colors',
127 127 type=str, dest='InteractiveShell.colors',
128 128 help="Set the color scheme (NoColor, Linux, and LightBG).",
129 129 metavar='InteractiveShell.colors')
130 130 paa('--color-info',
131 131 action='store_true', dest='InteractiveShell.color_info',
132 132 help=
133 133 """IPython can display information about objects via a set of func-
134 134 tions, and optionally can use colors for this, syntax highlighting
135 135 source code and various other elements. However, because this
136 136 information is passed through a pager (like 'less') and many pagers get
137 137 confused with color codes, this option is off by default. You can test
138 138 it and turn it on permanently in your ipython_config.py file if it
139 139 works for you. Test it and turn it on permanently if it works with
140 140 your system. The magic function %%color_info allows you to toggle this
141 141 inter- actively for testing.""")
142 142 paa('--no-color-info',
143 143 action='store_false', dest='InteractiveShell.color_info',
144 144 help="Disable using colors for info related things.")
145 145 paa('--confirm-exit',
146 146 action='store_true', dest='InteractiveShell.confirm_exit',
147 147 help=
148 148 """Set to confirm when you try to exit IPython with an EOF (Control-D
149 149 in Unix, Control-Z/Enter in Windows). By typing 'exit', 'quit' or
150 150 '%%Exit', you can force a direct exit without any confirmation.""")
151 151 paa('--no-confirm-exit',
152 152 action='store_false', dest='InteractiveShell.confirm_exit',
153 153 help="Don't prompt the user when exiting.")
154 154 paa('--deep-reload',
155 155 action='store_true', dest='InteractiveShell.deep_reload',
156 156 help=
157 157 """Enable deep (recursive) reloading by default. IPython can use the
158 158 deep_reload module which reloads changes in modules recursively (it
159 159 replaces the reload() function, so you don't need to change anything to
160 160 use it). deep_reload() forces a full reload of modules whose code may
161 161 have changed, which the default reload() function does not. When
162 162 deep_reload is off, IPython will use the normal reload(), but
163 163 deep_reload will still be available as dreload(). This fea- ture is off
164 164 by default [which means that you have both normal reload() and
165 165 dreload()].""")
166 166 paa('--no-deep-reload',
167 167 action='store_false', dest='InteractiveShell.deep_reload',
168 168 help="Disable deep (recursive) reloading by default.")
169 169 paa('--editor',
170 170 type=str, dest='InteractiveShell.editor',
171 171 help="Set the editor used by IPython (default to $EDITOR/vi/notepad).",
172 172 metavar='InteractiveShell.editor')
173 173 paa('--log','-l',
174 174 action='store_true', dest='InteractiveShell.logstart',
175 175 help="Start logging to the default log file (./ipython_log.py).")
176 176 paa('--logfile','-lf',
177 177 type=unicode, dest='InteractiveShell.logfile',
178 178 help="Start logging to logfile with this name.",
179 179 metavar='InteractiveShell.logfile')
180 180 paa('--log-append','-la',
181 181 type=unicode, dest='InteractiveShell.logappend',
182 182 help="Start logging to the given file in append mode.",
183 183 metavar='InteractiveShell.logfile')
184 184 paa('--pdb',
185 185 action='store_true', dest='InteractiveShell.pdb',
186 186 help="Enable auto calling the pdb debugger after every exception.")
187 187 paa('--no-pdb',
188 188 action='store_false', dest='InteractiveShell.pdb',
189 189 help="Disable auto calling the pdb debugger after every exception.")
190 190 paa('--pprint',
191 191 action='store_true', dest='InteractiveShell.pprint',
192 192 help="Enable auto pretty printing of results.")
193 193 paa('--no-pprint',
194 194 action='store_false', dest='InteractiveShell.pprint',
195 195 help="Disable auto auto pretty printing of results.")
196 196 paa('--prompt-in1','-pi1',
197 197 type=str, dest='InteractiveShell.prompt_in1',
198 198 help=
199 199 """Set the main input prompt ('In [\#]: '). Note that if you are using
200 200 numbered prompts, the number is represented with a '\#' in the string.
201 201 Don't forget to quote strings with spaces embedded in them. Most
202 202 bash-like escapes can be used to customize IPython's prompts, as well
203 203 as a few additional ones which are IPython-spe- cific. All valid
204 204 prompt escapes are described in detail in the Customization section of
205 205 the IPython manual.""",
206 206 metavar='InteractiveShell.prompt_in1')
207 207 paa('--prompt-in2','-pi2',
208 208 type=str, dest='InteractiveShell.prompt_in2',
209 209 help=
210 210 """Set the secondary input prompt (' .\D.: '). Similar to the previous
211 211 option, but used for the continuation prompts. The special sequence
212 212 '\D' is similar to '\#', but with all digits replaced by dots (so you
213 213 can have your continuation prompt aligned with your input prompt).
214 214 Default: ' .\D.: ' (note three spaces at the start for alignment with
215 215 'In [\#]')""",
216 216 metavar='InteractiveShell.prompt_in2')
217 217 paa('--prompt-out','-po',
218 218 type=str, dest='InteractiveShell.prompt_out',
219 219 help="Set the output prompt ('Out[\#]:')",
220 220 metavar='InteractiveShell.prompt_out')
221 221 paa('--quick',
222 222 action='store_true', dest='Global.quick',
223 223 help="Enable quick startup with no config files.")
224 224 paa('--readline',
225 225 action='store_true', dest='InteractiveShell.readline_use',
226 226 help="Enable readline for command line usage.")
227 227 paa('--no-readline',
228 228 action='store_false', dest='InteractiveShell.readline_use',
229 229 help="Disable readline for command line usage.")
230 230 paa('--screen-length','-sl',
231 231 type=int, dest='InteractiveShell.screen_length',
232 232 help=
233 233 """Number of lines of your screen, used to control printing of very
234 234 long strings. Strings longer than this number of lines will be sent
235 235 through a pager instead of directly printed. The default value for
236 236 this is 0, which means IPython will auto-detect your screen size every
237 237 time it needs to print certain potentially long strings (this doesn't
238 238 change the behavior of the 'print' keyword, it's only triggered
239 239 internally). If for some reason this isn't working well (it needs
240 240 curses support), specify it yourself. Otherwise don't change the
241 241 default.""",
242 242 metavar='InteractiveShell.screen_length')
243 243 paa('--separate-in','-si',
244 244 type=str, dest='InteractiveShell.separate_in',
245 245 help="Separator before input prompts. Default '\\n'.",
246 246 metavar='InteractiveShell.separate_in')
247 247 paa('--separate-out','-so',
248 248 type=str, dest='InteractiveShell.separate_out',
249 249 help="Separator before output prompts. Default 0 (nothing).",
250 250 metavar='InteractiveShell.separate_out')
251 251 paa('--separate-out2','-so2',
252 252 type=str, dest='InteractiveShell.separate_out2',
253 253 help="Separator after output prompts. Default 0 (nonight).",
254 254 metavar='InteractiveShell.separate_out2')
255 255 paa('--no-sep',
256 256 action='store_true', dest='Global.nosep',
257 257 help="Eliminate all spacing between prompts.")
258 258 paa('--term-title',
259 259 action='store_true', dest='InteractiveShell.term_title',
260 260 help="Enable auto setting the terminal title.")
261 261 paa('--no-term-title',
262 262 action='store_false', dest='InteractiveShell.term_title',
263 263 help="Disable auto setting the terminal title.")
264 264 paa('--xmode',
265 265 type=str, dest='InteractiveShell.xmode',
266 266 help=
267 267 """Exception reporting mode ('Plain','Context','Verbose'). Plain:
268 268 similar to python's normal traceback printing. Context: prints 5 lines
269 269 of context source code around each line in the traceback. Verbose:
270 270 similar to Context, but additionally prints the variables currently
271 271 visible where the exception happened (shortening their strings if too
272 272 long). This can potentially be very slow, if you happen to have a huge
273 273 data structure whose string representation is complex to compute.
274 274 Your computer may appear to freeze for a while with cpu usage at 100%%.
275 275 If this occurs, you can cancel the traceback with Ctrl-C (maybe hitting
276 276 it more than once).
277 277 """,
278 278 metavar='InteractiveShell.xmode')
279 279 paa('--ext',
280 280 type=str, dest='Global.extra_extension',
281 281 help="The dotted module name of an IPython extension to load.",
282 282 metavar='Global.extra_extension')
283 283 paa('-c',
284 284 type=str, dest='Global.code_to_run',
285 285 help="Execute the given command string.",
286 286 metavar='Global.code_to_run')
287 287 paa('-i',
288 288 action='store_true', dest='Global.force_interact',
289 289 help=
290 290 "If running code from the command line, become interactive afterwards.")
291 291
292 292 # Options to start with GUI control enabled from the beginning
293 293 paa('--gui',
294 294 type=str, dest='Global.gui',
295 295 help="Enable GUI event loop integration ('qt', 'wx', 'gtk').",
296 296 metavar='gui-mode')
297 297 paa('--pylab','-pylab',
298 298 type=str, dest='Global.pylab',
299 299 nargs='?', const='auto', metavar='gui-mode',
300 300 help="Pre-load matplotlib and numpy for interactive use. "+
301 301 "If no value is given, the gui backend is matplotlib's, else use "+
302 302 "one of: ['tk', 'qt', 'wx', 'gtk'].")
303 303
304 304 # Legacy GUI options. Leave them in for backwards compatibility, but the
305 305 # 'thread' names are really a misnomer now.
306 306 paa('--wthread', '-wthread',
307 307 action='store_true', dest='Global.wthread',
308 308 help=
309 309 """Enable wxPython event loop integration. (DEPRECATED, use --gui wx)""")
310 310 paa('--q4thread', '--qthread', '-q4thread', '-qthread',
311 311 action='store_true', dest='Global.q4thread',
312 312 help=
313 313 """Enable Qt4 event loop integration. Qt3 is no longer supported.
314 314 (DEPRECATED, use --gui qt)""")
315 315 paa('--gthread', '-gthread',
316 316 action='store_true', dest='Global.gthread',
317 317 help=
318 318 """Enable GTK event loop integration. (DEPRECATED, use --gui gtk)""")
319 319
320 320
321 321 #-----------------------------------------------------------------------------
322 322 # Crash handler for this application
323 323 #-----------------------------------------------------------------------------
324 324
325 325
326 326 _message_template = """\
327 327 Oops, $self.app_name crashed. We do our best to make it stable, but...
328 328
329 329 A crash report was automatically generated with the following information:
330 330 - A verbatim copy of the crash traceback.
331 331 - A copy of your input history during this session.
332 332 - Data on your current $self.app_name configuration.
333 333
334 334 It was left in the file named:
335 335 \t'$self.crash_report_fname'
336 336 If you can email this file to the developers, the information in it will help
337 337 them in understanding and correcting the problem.
338 338
339 339 You can mail it to: $self.contact_name at $self.contact_email
340 340 with the subject '$self.app_name Crash Report'.
341 341
342 342 If you want to do it now, the following command will work (under Unix):
343 343 mail -s '$self.app_name Crash Report' $self.contact_email < $self.crash_report_fname
344 344
345 345 To ensure accurate tracking of this issue, please file a report about it at:
346 346 $self.bug_tracker
347 347 """
348 348
349 349 class IPAppCrashHandler(CrashHandler):
350 350 """sys.excepthook for IPython itself, leaves a detailed report on disk."""
351 351
352 352 message_template = _message_template
353 353
354 354 def __init__(self, app):
355 355 contact_name = release.authors['Fernando'][0]
356 356 contact_email = release.authors['Fernando'][1]
357 357 bug_tracker = 'https://bugs.launchpad.net/ipython/+filebug'
358 358 super(IPAppCrashHandler,self).__init__(
359 359 app, contact_name, contact_email, bug_tracker
360 360 )
361 361
362 362 def make_report(self,traceback):
363 363 """Return a string containing a crash report."""
364 364
365 365 sec_sep = self.section_sep
366 366 # Start with parent report
367 367 report = [super(IPAppCrashHandler, self).make_report(traceback)]
368 368 # Add interactive-specific info we may have
369 369 rpt_add = report.append
370 370 try:
371 371 rpt_add(sec_sep+"History of session input:")
372 372 for line in self.app.shell.user_ns['_ih']:
373 373 rpt_add(line)
374 374 rpt_add('\n*** Last line of input (may not be in above history):\n')
375 375 rpt_add(self.app.shell._last_input_line+'\n')
376 376 except:
377 377 pass
378 378
379 379 return ''.join(report)
380 380
381 381
382 382 #-----------------------------------------------------------------------------
383 383 # Main classes and functions
384 384 #-----------------------------------------------------------------------------
385 385
386 386 class IPythonApp(Application):
387 387 name = u'ipython'
388 388 #: argparse formats better the 'usage' than the 'description' field
389 389 description = None
390 390 usage = usage.cl_usage
391 391 command_line_loader = IPAppConfigLoader
392 392 default_config_file_name = default_config_file_name
393 393 crash_handler_class = IPAppCrashHandler
394 394
395 395 def create_default_config(self):
396 396 super(IPythonApp, self).create_default_config()
397 397 # Eliminate multiple lookups
398 398 Global = self.default_config.Global
399 399
400 400 # Set all default values
401 401 Global.display_banner = True
402 402
403 403 # If the -c flag is given or a file is given to run at the cmd line
404 404 # like "ipython foo.py", normally we exit without starting the main
405 405 # loop. The force_interact config variable allows a user to override
406 406 # this and interact. It is also set by the -i cmd line flag, just
407 407 # like Python.
408 408 Global.force_interact = False
409 409
410 410 # By default always interact by starting the IPython mainloop.
411 411 Global.interact = True
412 412
413 413 # No GUI integration by default
414 414 Global.gui = False
415 415 # Pylab off by default
416 416 Global.pylab = False
417 417
418 418 # Deprecated versions of gui support that used threading, we support
419 419 # them just for bacwards compatibility as an alternate spelling for
420 420 # '--gui X'
421 421 Global.qthread = False
422 422 Global.q4thread = False
423 423 Global.wthread = False
424 424 Global.gthread = False
425 425
426 426 def load_file_config(self):
427 427 if hasattr(self.command_line_config.Global, 'quick'):
428 428 if self.command_line_config.Global.quick:
429 429 self.file_config = Config()
430 430 return
431 431 super(IPythonApp, self).load_file_config()
432 432
433 433 def post_load_file_config(self):
434 434 if hasattr(self.command_line_config.Global, 'extra_extension'):
435 435 if not hasattr(self.file_config.Global, 'extensions'):
436 436 self.file_config.Global.extensions = []
437 437 self.file_config.Global.extensions.append(
438 438 self.command_line_config.Global.extra_extension)
439 439 del self.command_line_config.Global.extra_extension
440 440
441 441 def pre_construct(self):
442 442 config = self.master_config
443 443
444 444 if hasattr(config.Global, 'classic'):
445 445 if config.Global.classic:
446 446 config.InteractiveShell.cache_size = 0
447 447 config.InteractiveShell.pprint = 0
448 448 config.InteractiveShell.prompt_in1 = '>>> '
449 449 config.InteractiveShell.prompt_in2 = '... '
450 450 config.InteractiveShell.prompt_out = ''
451 451 config.InteractiveShell.separate_in = \
452 452 config.InteractiveShell.separate_out = \
453 453 config.InteractiveShell.separate_out2 = ''
454 454 config.InteractiveShell.colors = 'NoColor'
455 455 config.InteractiveShell.xmode = 'Plain'
456 456
457 457 if hasattr(config.Global, 'nosep'):
458 458 if config.Global.nosep:
459 459 config.InteractiveShell.separate_in = \
460 460 config.InteractiveShell.separate_out = \
461 461 config.InteractiveShell.separate_out2 = ''
462 462
463 463 # if there is code of files to run from the cmd line, don't interact
464 464 # unless the -i flag (Global.force_interact) is true.
465 465 code_to_run = config.Global.get('code_to_run','')
466 466 file_to_run = False
467 467 if self.extra_args and self.extra_args[0]:
468 468 file_to_run = True
469 469 if file_to_run or code_to_run:
470 470 if not config.Global.force_interact:
471 471 config.Global.interact = False
472 472
473 473 def construct(self):
474 474 # I am a little hesitant to put these into InteractiveShell itself.
475 475 # But that might be the place for them
476 476 sys.path.insert(0, '')
477 477
478 # Create an InteractiveShell instance
479 self.shell = InteractiveShell(None, self.master_config)
478 # Create an InteractiveShell instance.
479 self.shell = InteractiveShell.instance(config=self.master_config)
480 480
481 481 def post_construct(self):
482 482 """Do actions after construct, but before starting the app."""
483 483 config = self.master_config
484 484
485 485 # shell.display_banner should always be False for the terminal
486 486 # based app, because we call shell.show_banner() by hand below
487 487 # so the banner shows *before* all extension loading stuff.
488 488 self.shell.display_banner = False
489 489 if config.Global.display_banner and \
490 490 config.Global.interact:
491 491 self.shell.show_banner()
492 492
493 493 # Make sure there is a space below the banner.
494 494 if self.log_level <= logging.INFO: print
495 495
496 496 # Now a variety of things that happen after the banner is printed.
497 497 self._enable_gui_pylab()
498 498 self._load_extensions()
499 499 self._run_exec_lines()
500 500 self._run_exec_files()
501 501 self._run_cmd_line_code()
502 502
503 503 def _enable_gui_pylab(self):
504 504 """Enable GUI event loop integration, taking pylab into account."""
505 505 Global = self.master_config.Global
506 506
507 507 # Select which gui to use
508 508 if Global.gui:
509 509 gui = Global.gui
510 510 # The following are deprecated, but there's likely to be a lot of use
511 511 # of this form out there, so we might as well support it for now. But
512 512 # the --gui option above takes precedence.
513 513 elif Global.wthread:
514 514 gui = inputhook.GUI_WX
515 515 elif Global.qthread:
516 516 gui = inputhook.GUI_QT
517 517 elif Global.gthread:
518 518 gui = inputhook.GUI_GTK
519 519 else:
520 520 gui = None
521 521
522 522 # Using --pylab will also require gui activation, though which toolkit
523 523 # to use may be chosen automatically based on mpl configuration.
524 524 if Global.pylab:
525 525 activate = self.shell.enable_pylab
526 526 if Global.pylab == 'auto':
527 527 gui = None
528 528 else:
529 529 gui = Global.pylab
530 530 else:
531 531 # Enable only GUI integration, no pylab
532 532 activate = inputhook.enable_gui
533 533
534 534 if gui or Global.pylab:
535 535 try:
536 536 self.log.info("Enabling GUI event loop integration, "
537 537 "toolkit=%s, pylab=%s" % (gui, Global.pylab) )
538 538 activate(gui)
539 539 except:
540 540 self.log.warn("Error in enabling GUI event loop integration:")
541 541 self.shell.showtraceback()
542 542
543 543 def _load_extensions(self):
544 544 """Load all IPython extensions in Global.extensions.
545 545
546 This uses the :meth:`InteractiveShell.load_extensions` to load all
546 This uses the :meth:`ExtensionManager.load_extensions` to load all
547 547 the extensions listed in ``self.master_config.Global.extensions``.
548 548 """
549 549 try:
550 550 if hasattr(self.master_config.Global, 'extensions'):
551 551 self.log.debug("Loading IPython extensions...")
552 552 extensions = self.master_config.Global.extensions
553 553 for ext in extensions:
554 554 try:
555 555 self.log.info("Loading IPython extension: %s" % ext)
556 self.shell.load_extension(ext)
556 self.shell.extension_manager.load_extension(ext)
557 557 except:
558 558 self.log.warn("Error in loading extension: %s" % ext)
559 559 self.shell.showtraceback()
560 560 except:
561 561 self.log.warn("Unknown error in loading extensions:")
562 562 self.shell.showtraceback()
563 563
564 564 def _run_exec_lines(self):
565 565 """Run lines of code in Global.exec_lines in the user's namespace."""
566 566 try:
567 567 if hasattr(self.master_config.Global, 'exec_lines'):
568 568 self.log.debug("Running code from Global.exec_lines...")
569 569 exec_lines = self.master_config.Global.exec_lines
570 570 for line in exec_lines:
571 571 try:
572 572 self.log.info("Running code in user namespace: %s" %
573 573 line)
574 574 self.shell.runlines(line)
575 575 except:
576 576 self.log.warn("Error in executing line in user "
577 577 "namespace: %s" % line)
578 578 self.shell.showtraceback()
579 579 except:
580 580 self.log.warn("Unknown error in handling Global.exec_lines:")
581 581 self.shell.showtraceback()
582 582
583 583 def _exec_file(self, fname):
584 584 full_filename = filefind(fname, [u'.', self.ipython_dir])
585 585 if os.path.isfile(full_filename):
586 586 if full_filename.endswith(u'.py'):
587 587 self.log.info("Running file in user namespace: %s" %
588 588 full_filename)
589 589 # Ensure that __file__ is always defined to match Python behavior
590 590 self.shell.user_ns['__file__'] = fname
591 591 try:
592 592 self.shell.safe_execfile(full_filename, self.shell.user_ns)
593 593 finally:
594 594 del self.shell.user_ns['__file__']
595 595 elif full_filename.endswith('.ipy'):
596 596 self.log.info("Running file in user namespace: %s" %
597 597 full_filename)
598 598 self.shell.safe_execfile_ipy(full_filename)
599 599 else:
600 600 self.log.warn("File does not have a .py or .ipy extension: <%s>"
601 601 % full_filename)
602 602 def _run_exec_files(self):
603 603 try:
604 604 if hasattr(self.master_config.Global, 'exec_files'):
605 605 self.log.debug("Running files in Global.exec_files...")
606 606 exec_files = self.master_config.Global.exec_files
607 607 for fname in exec_files:
608 608 self._exec_file(fname)
609 609 except:
610 610 self.log.warn("Unknown error in handling Global.exec_files:")
611 611 self.shell.showtraceback()
612 612
613 613 def _run_cmd_line_code(self):
614 614 if hasattr(self.master_config.Global, 'code_to_run'):
615 615 line = self.master_config.Global.code_to_run
616 616 try:
617 617 self.log.info("Running code given at command line (-c): %s" %
618 618 line)
619 619 self.shell.runlines(line)
620 620 except:
621 621 self.log.warn("Error in executing line in user namespace: %s" %
622 622 line)
623 623 self.shell.showtraceback()
624 624 return
625 625 # Like Python itself, ignore the second if the first of these is present
626 626 try:
627 627 fname = self.extra_args[0]
628 628 except:
629 629 pass
630 630 else:
631 631 try:
632 632 self._exec_file(fname)
633 633 except:
634 634 self.log.warn("Error in executing file in user namespace: %s" %
635 635 fname)
636 636 self.shell.showtraceback()
637 637
638 638 def start_app(self):
639 639 if self.master_config.Global.interact:
640 640 self.log.debug("Starting IPython's mainloop...")
641 641 self.shell.mainloop()
642 642 else:
643 643 self.log.debug("IPython not interactive, start_app is no-op...")
644 644
645 645
646 646 def load_default_config(ipython_dir=None):
647 647 """Load the default config file from the default ipython_dir.
648 648
649 649 This is useful for embedded shells.
650 650 """
651 651 if ipython_dir is None:
652 652 ipython_dir = get_ipython_dir()
653 653 cl = PyFileConfigLoader(default_config_file_name, ipython_dir)
654 654 config = cl.load_config()
655 655 return config
656 656
657 657
658 658 def launch_new_instance():
659 659 """Create and run a full blown IPython instance"""
660 660 app = IPythonApp()
661 661 app.start()
662 662
663 663
664 664 if __name__ == '__main__':
665 665 launch_new_instance()
@@ -1,2582 +1,2523 b''
1 1 # -*- coding: utf-8 -*-
2 """
3 Main IPython Component
4 """
2 """Main IPython class."""
5 3
6 4 #-----------------------------------------------------------------------------
7 5 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de>
8 6 # Copyright (C) 2001-2007 Fernando Perez. <fperez@colorado.edu>
9 # Copyright (C) 2008-2009 The IPython Development Team
7 # Copyright (C) 2008-2010 The IPython Development Team
10 8 #
11 9 # Distributed under the terms of the BSD License. The full license is in
12 10 # the file COPYING, distributed as part of this software.
13 11 #-----------------------------------------------------------------------------
14 12
15 13 #-----------------------------------------------------------------------------
16 14 # Imports
17 15 #-----------------------------------------------------------------------------
18 16
19 17 from __future__ import with_statement
20 18 from __future__ import absolute_import
21 19
22 20 import __builtin__
21 import abc
23 22 import bdb
24 23 import codeop
25 24 import exceptions
26 25 import new
27 26 import os
28 27 import re
29 28 import string
30 29 import sys
31 30 import tempfile
32 31 from contextlib import nested
33 32
34 33 from IPython.core import debugger, oinspect
35 34 from IPython.core import history as ipcorehist
36 35 from IPython.core import prefilter
37 36 from IPython.core import shadowns
38 37 from IPython.core import ultratb
39 38 from IPython.core.alias import AliasManager
40 39 from IPython.core.builtin_trap import BuiltinTrap
41 from IPython.core.component import Component
40 from IPython.config.configurable import Configurable
42 41 from IPython.core.display_trap import DisplayTrap
43 42 from IPython.core.error import TryNext, UsageError
43 from IPython.core.extensions import ExtensionManager
44 44 from IPython.core.fakemodule import FakeModule, init_fakemod_dict
45 45 from IPython.core.logger import Logger
46 46 from IPython.core.magic import Magic
47 from IPython.core.plugin import PluginManager
47 48 from IPython.core.prefilter import PrefilterManager
48 49 from IPython.core.prompts import CachedOutput
49 50 from IPython.core.usage import interactive_usage, default_banner
50 51 import IPython.core.hooks
51 52 from IPython.external.Itpl import ItplNS
52 53 from IPython.lib.inputhook import enable_gui
53 54 from IPython.lib.backgroundjobs import BackgroundJobManager
54 55 from IPython.lib.pylabtools import pylab_activate
55 56 from IPython.utils import PyColorize
56 57 from IPython.utils import pickleshare
57 58 from IPython.utils.doctestreload import doctest_reload
58 59 from IPython.utils.ipstruct import Struct
59 60 from IPython.utils.io import Term, ask_yes_no
60 61 from IPython.utils.path import get_home_dir, get_ipython_dir, HomeDirError
61 62 from IPython.utils.process import (
62 63 abbrev_cwd,
63 64 getoutput,
64 65 getoutputerror
65 66 )
66 67 # import IPython.utils.rlineimpl as readline
67 68 from IPython.utils.strdispatch import StrDispatch
68 69 from IPython.utils.syspathcontext import prepended_to_syspath
69 70 from IPython.utils.terminal import toggle_set_term_title, set_term_title
70 71 from IPython.utils.warn import warn, error, fatal
71 72 from IPython.utils.traitlets import (
72 Int, Str, CBool, CaselessStrEnum, Enum, List, Unicode
73 Int, Str, CBool, CaselessStrEnum, Enum, List, Unicode, Instance
73 74 )
74 75
75 76 # from IPython.utils import growl
76 77 # growl.start("IPython")
77 78
78 79 #-----------------------------------------------------------------------------
79 80 # Globals
80 81 #-----------------------------------------------------------------------------
81 82
82 83 # store the builtin raw_input globally, and use this always, in case user code
83 84 # overwrites it (like wx.py.PyShell does)
84 85 raw_input_original = raw_input
85 86
86 87 # compiled regexps for autoindent management
87 88 dedent_re = re.compile(r'^\s+raise|^\s+return|^\s+pass')
88 89
89 90 #-----------------------------------------------------------------------------
90 91 # Utilities
91 92 #-----------------------------------------------------------------------------
92 93
93 94 ini_spaces_re = re.compile(r'^(\s+)')
94 95
95 96
96 97 def num_ini_spaces(strng):
97 98 """Return the number of initial spaces in a string"""
98 99
99 100 ini_spaces = ini_spaces_re.match(strng)
100 101 if ini_spaces:
101 102 return ini_spaces.end()
102 103 else:
103 104 return 0
104 105
105 106
106 107 def softspace(file, newvalue):
107 108 """Copied from code.py, to remove the dependency"""
108 109
109 110 oldvalue = 0
110 111 try:
111 112 oldvalue = file.softspace
112 113 except AttributeError:
113 114 pass
114 115 try:
115 116 file.softspace = newvalue
116 117 except (AttributeError, TypeError):
117 118 # "attribute-less object" or "read-only attributes"
118 119 pass
119 120 return oldvalue
120 121
121 122
122 123 def no_op(*a, **kw): pass
123 124
124 125 class SpaceInInput(exceptions.Exception): pass
125 126
126 127 class Bunch: pass
127 128
128 129 class InputList(list):
129 130 """Class to store user input.
130 131
131 132 It's basically a list, but slices return a string instead of a list, thus
132 133 allowing things like (assuming 'In' is an instance):
133 134
134 135 exec In[4:7]
135 136
136 137 or
137 138
138 139 exec In[5:9] + In[14] + In[21:25]"""
139 140
140 141 def __getslice__(self,i,j):
141 142 return ''.join(list.__getslice__(self,i,j))
142 143
143 144
144 145 class SyntaxTB(ultratb.ListTB):
145 146 """Extension which holds some state: the last exception value"""
146 147
147 148 def __init__(self,color_scheme = 'NoColor'):
148 149 ultratb.ListTB.__init__(self,color_scheme)
149 150 self.last_syntax_error = None
150 151
151 152 def __call__(self, etype, value, elist):
152 153 self.last_syntax_error = value
153 154 ultratb.ListTB.__call__(self,etype,value,elist)
154 155
155 156 def clear_err_state(self):
156 157 """Return the current error state and clear it"""
157 158 e = self.last_syntax_error
158 159 self.last_syntax_error = None
159 160 return e
160 161
161 162
162 163 def get_default_editor():
163 164 try:
164 165 ed = os.environ['EDITOR']
165 166 except KeyError:
166 167 if os.name == 'posix':
167 168 ed = 'vi' # the only one guaranteed to be there!
168 169 else:
169 170 ed = 'notepad' # same in Windows!
170 171 return ed
171 172
172 173
173 174 def get_default_colors():
174 175 if sys.platform=='darwin':
175 176 return "LightBG"
176 177 elif os.name=='nt':
177 178 return 'Linux'
178 179 else:
179 180 return 'Linux'
180 181
181 182
182 183 class SeparateStr(Str):
183 184 """A Str subclass to validate separate_in, separate_out, etc.
184 185
185 186 This is a Str based trait that converts '0'->'' and '\\n'->'\n'.
186 187 """
187 188
188 189 def validate(self, obj, value):
189 190 if value == '0': value = ''
190 191 value = value.replace('\\n','\n')
191 192 return super(SeparateStr, self).validate(obj, value)
192 193
193 194
194 195 #-----------------------------------------------------------------------------
195 196 # Main IPython class
196 197 #-----------------------------------------------------------------------------
197 198
198 199
199 class InteractiveShell(Component, Magic):
200 class InteractiveShell(Configurable, Magic):
200 201 """An enhanced, interactive shell for Python."""
201 202
202 203 autocall = Enum((0,1,2), default_value=1, config=True)
203 204 autoedit_syntax = CBool(False, config=True)
204 205 autoindent = CBool(True, config=True)
205 206 automagic = CBool(True, config=True)
206 207 banner = Str('')
207 208 banner1 = Str(default_banner, config=True)
208 209 banner2 = Str('', config=True)
209 210 cache_size = Int(1000, config=True)
210 211 color_info = CBool(True, config=True)
211 212 colors = CaselessStrEnum(('NoColor','LightBG','Linux'),
212 213 default_value=get_default_colors(), config=True)
213 214 confirm_exit = CBool(True, config=True)
214 215 debug = CBool(False, config=True)
215 216 deep_reload = CBool(False, config=True)
216 217 # This display_banner only controls whether or not self.show_banner()
217 218 # is called when mainloop/interact are called. The default is False
218 219 # because for the terminal based application, the banner behavior
219 220 # is controlled by Global.display_banner, which IPythonApp looks at
220 221 # to determine if *it* should call show_banner() by hand or not.
221 222 display_banner = CBool(False) # This isn't configurable!
222 223 embedded = CBool(False)
223 224 embedded_active = CBool(False)
224 225 editor = Str(get_default_editor(), config=True)
225 226 filename = Str("<ipython console>")
226 227 ipython_dir= Unicode('', config=True) # Set to get_ipython_dir() in __init__
227 228 logstart = CBool(False, config=True)
228 229 logfile = Str('', config=True)
229 230 logappend = Str('', config=True)
230 231 object_info_string_level = Enum((0,1,2), default_value=0,
231 232 config=True)
232 233 pager = Str('less', config=True)
233 234 pdb = CBool(False, config=True)
234 235 pprint = CBool(True, config=True)
235 236 profile = Str('', config=True)
236 237 prompt_in1 = Str('In [\\#]: ', config=True)
237 238 prompt_in2 = Str(' .\\D.: ', config=True)
238 239 prompt_out = Str('Out[\\#]: ', config=True)
239 240 prompts_pad_left = CBool(True, config=True)
240 241 quiet = CBool(False, config=True)
241 242
242 243 readline_use = CBool(True, config=True)
243 244 readline_merge_completions = CBool(True, config=True)
244 245 readline_omit__names = Enum((0,1,2), default_value=0, config=True)
245 246 readline_remove_delims = Str('-/~', config=True)
246 247 readline_parse_and_bind = List([
247 248 'tab: complete',
248 249 '"\C-l": clear-screen',
249 250 'set show-all-if-ambiguous on',
250 251 '"\C-o": tab-insert',
251 252 '"\M-i": " "',
252 253 '"\M-o": "\d\d\d\d"',
253 254 '"\M-I": "\d\d\d\d"',
254 255 '"\C-r": reverse-search-history',
255 256 '"\C-s": forward-search-history',
256 257 '"\C-p": history-search-backward',
257 258 '"\C-n": history-search-forward',
258 259 '"\e[A": history-search-backward',
259 260 '"\e[B": history-search-forward',
260 261 '"\C-k": kill-line',
261 262 '"\C-u": unix-line-discard',
262 263 ], allow_none=False, config=True)
263 264
264 265 screen_length = Int(0, config=True)
265 266
266 267 # Use custom TraitTypes that convert '0'->'' and '\\n'->'\n'
267 268 separate_in = SeparateStr('\n', config=True)
268 269 separate_out = SeparateStr('', config=True)
269 270 separate_out2 = SeparateStr('', config=True)
270 271
271 272 system_header = Str('IPython system call: ', config=True)
272 273 system_verbose = CBool(False, config=True)
273 274 term_title = CBool(False, config=True)
274 275 wildcards_case_sensitive = CBool(True, config=True)
275 276 xmode = CaselessStrEnum(('Context','Plain', 'Verbose'),
276 277 default_value='Context', config=True)
277 278
278 279 autoexec = List(allow_none=False)
279 280
280 281 # class attribute to indicate whether the class supports threads or not.
281 282 # Subclasses with thread support should override this as needed.
282 283 isthreaded = False
283 284
284 def __init__(self, parent=None, config=None, ipython_dir=None, usage=None,
285 # Subcomponents of InteractiveShell
286 alias_manager = Instance('IPython.core.alias.AliasManager')
287 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager')
288 builtin_trap = Instance('IPython.core.builtin_trap.BuiltinTrap')
289 display_trap = Instance('IPython.core.display_trap.DisplayTrap')
290 extension_manager = Instance('IPython.core.extensions.ExtensionManager')
291 plugin_manager = Instance('IPython.core.plugin.PluginManager')
292
293 def __init__(self, config=None, ipython_dir=None, usage=None,
285 294 user_ns=None, user_global_ns=None,
286 295 banner1=None, banner2=None, display_banner=None,
287 296 custom_exceptions=((),None)):
288 297
289 298 # This is where traits with a config_key argument are updated
290 299 # from the values on config.
291 super(InteractiveShell, self).__init__(parent, config=config)
300 super(InteractiveShell, self).__init__(config=config)
292 301
293 302 # These are relatively independent and stateless
294 303 self.init_ipython_dir(ipython_dir)
295 304 self.init_instance_attrs()
296 305 self.init_term_title()
297 306 self.init_usage(usage)
298 307 self.init_banner(banner1, banner2, display_banner)
299 308
300 309 # Create namespaces (user_ns, user_global_ns, etc.)
301 310 self.init_create_namespaces(user_ns, user_global_ns)
302 311 # This has to be done after init_create_namespaces because it uses
303 312 # something in self.user_ns, but before init_sys_modules, which
304 313 # is the first thing to modify sys.
305 314 self.save_sys_module_state()
306 315 self.init_sys_modules()
307 316
308 317 self.init_history()
309 318 self.init_encoding()
310 319 self.init_prefilter()
311 320
312 321 Magic.__init__(self, self)
313 322
314 323 self.init_syntax_highlighting()
315 324 self.init_hooks()
316 325 self.init_pushd_popd_magic()
317 326 self.init_traceback_handlers(custom_exceptions)
318 327 self.init_user_ns()
319 328 self.init_logger()
320 329 self.init_alias()
321 330 self.init_builtins()
322 331
323 332 # pre_config_initialization
324 333 self.init_shadow_hist()
325 334
326 335 # The next section should contain averything that was in ipmaker.
327 336 self.init_logstart()
328 337
329 338 # The following was in post_config_initialization
330 339 self.init_inspector()
331 340 self.init_readline()
332 341 self.init_prompts()
333 342 self.init_displayhook()
334 343 self.init_reload_doctest()
335 344 self.init_magics()
336 345 self.init_pdb()
346 self.init_extension_manager()
347 self.init_plugin_manager()
337 348 self.hooks.late_startup_hook()
338 349
350 @classmethod
351 def instance(cls, *args, **kwargs):
352 """Returns a global InteractiveShell instance."""
353 if not hasattr(cls, "_instance"):
354 cls._instance = cls(*args, **kwargs)
355 return cls._instance
356
357 @classmethod
358 def initialized(cls):
359 return hasattr(cls, "_instance")
360
339 361 def get_ipython(self):
340 362 """Return the currently running IPython instance."""
341 363 return self
342 364
343 365 #-------------------------------------------------------------------------
344 366 # Trait changed handlers
345 367 #-------------------------------------------------------------------------
346 368
347 369 def _banner1_changed(self):
348 370 self.compute_banner()
349 371
350 372 def _banner2_changed(self):
351 373 self.compute_banner()
352 374
353 375 def _ipython_dir_changed(self, name, new):
354 376 if not os.path.isdir(new):
355 377 os.makedirs(new, mode = 0777)
356 if not os.path.isdir(self.ipython_extension_dir):
357 os.makedirs(self.ipython_extension_dir, mode = 0777)
358
359 @property
360 def ipython_extension_dir(self):
361 return os.path.join(self.ipython_dir, 'extensions')
362 378
363 379 @property
364 380 def usable_screen_length(self):
365 381 if self.screen_length == 0:
366 382 return 0
367 383 else:
368 384 num_lines_bot = self.separate_in.count('\n')+1
369 385 return self.screen_length - num_lines_bot
370 386
371 387 def _term_title_changed(self, name, new_value):
372 388 self.init_term_title()
373 389
374 390 def set_autoindent(self,value=None):
375 391 """Set the autoindent flag, checking for readline support.
376 392
377 393 If called with no arguments, it acts as a toggle."""
378 394
379 395 if not self.has_readline:
380 396 if os.name == 'posix':
381 397 warn("The auto-indent feature requires the readline library")
382 398 self.autoindent = 0
383 399 return
384 400 if value is None:
385 401 self.autoindent = not self.autoindent
386 402 else:
387 403 self.autoindent = value
388 404
389 405 #-------------------------------------------------------------------------
390 406 # init_* methods called by __init__
391 407 #-------------------------------------------------------------------------
392 408
393 409 def init_ipython_dir(self, ipython_dir):
394 410 if ipython_dir is not None:
395 411 self.ipython_dir = ipython_dir
396 412 self.config.Global.ipython_dir = self.ipython_dir
397 413 return
398 414
399 415 if hasattr(self.config.Global, 'ipython_dir'):
400 416 self.ipython_dir = self.config.Global.ipython_dir
401 417 else:
402 418 self.ipython_dir = get_ipython_dir()
403 419
404 420 # All children can just read this
405 421 self.config.Global.ipython_dir = self.ipython_dir
406 422
407 423 def init_instance_attrs(self):
408 424 self.jobs = BackgroundJobManager()
409 425 self.more = False
410 426
411 427 # command compiler
412 428 self.compile = codeop.CommandCompiler()
413 429
414 430 # User input buffer
415 431 self.buffer = []
416 432
417 433 # Make an empty namespace, which extension writers can rely on both
418 434 # existing and NEVER being used by ipython itself. This gives them a
419 435 # convenient location for storing additional information and state
420 436 # their extensions may require, without fear of collisions with other
421 437 # ipython names that may develop later.
422 438 self.meta = Struct()
423 439
424 440 # Object variable to store code object waiting execution. This is
425 441 # used mainly by the multithreaded shells, but it can come in handy in
426 442 # other situations. No need to use a Queue here, since it's a single
427 443 # item which gets cleared once run.
428 444 self.code_to_run = None
429 445
430 446 # Flag to mark unconditional exit
431 447 self.exit_now = False
432 448
433 449 # Temporary files used for various purposes. Deleted at exit.
434 450 self.tempfiles = []
435 451
436 452 # Keep track of readline usage (later set by init_readline)
437 453 self.has_readline = False
438 454
439 455 # keep track of where we started running (mainly for crash post-mortem)
440 456 # This is not being used anywhere currently.
441 457 self.starting_dir = os.getcwd()
442 458
443 459 # Indentation management
444 460 self.indent_current_nsp = 0
445 461
446 462 def init_term_title(self):
447 463 # Enable or disable the terminal title.
448 464 if self.term_title:
449 465 toggle_set_term_title(True)
450 466 set_term_title('IPython: ' + abbrev_cwd())
451 467 else:
452 468 toggle_set_term_title(False)
453 469
454 470 def init_usage(self, usage=None):
455 471 if usage is None:
456 472 self.usage = interactive_usage
457 473 else:
458 474 self.usage = usage
459 475
460 476 def init_encoding(self):
461 477 # Get system encoding at startup time. Certain terminals (like Emacs
462 478 # under Win32 have it set to None, and we need to have a known valid
463 479 # encoding to use in the raw_input() method
464 480 try:
465 481 self.stdin_encoding = sys.stdin.encoding or 'ascii'
466 482 except AttributeError:
467 483 self.stdin_encoding = 'ascii'
468 484
469 485 def init_syntax_highlighting(self):
470 486 # Python source parser/formatter for syntax highlighting
471 487 pyformat = PyColorize.Parser().format
472 488 self.pycolorize = lambda src: pyformat(src,'str',self.colors)
473 489
474 490 def init_pushd_popd_magic(self):
475 491 # for pushd/popd management
476 492 try:
477 493 self.home_dir = get_home_dir()
478 494 except HomeDirError, msg:
479 495 fatal(msg)
480 496
481 497 self.dir_stack = []
482 498
483 499 def init_logger(self):
484 500 self.logger = Logger(self, logfname='ipython_log.py', logmode='rotate')
485 501 # local shortcut, this is used a LOT
486 502 self.log = self.logger.log
487 503
488 504 def init_logstart(self):
489 505 if self.logappend:
490 506 self.magic_logstart(self.logappend + ' append')
491 507 elif self.logfile:
492 508 self.magic_logstart(self.logfile)
493 509 elif self.logstart:
494 510 self.magic_logstart()
495 511
496 512 def init_builtins(self):
497 self.builtin_trap = BuiltinTrap(self)
513 self.builtin_trap = BuiltinTrap(shell=self)
498 514
499 515 def init_inspector(self):
500 516 # Object inspector
501 517 self.inspector = oinspect.Inspector(oinspect.InspectColors,
502 518 PyColorize.ANSICodeColors,
503 519 'NoColor',
504 520 self.object_info_string_level)
505 521
506 522 def init_prompts(self):
507 523 # Initialize cache, set in/out prompts and printing system
508 524 self.outputcache = CachedOutput(self,
509 525 self.cache_size,
510 526 self.pprint,
511 527 input_sep = self.separate_in,
512 528 output_sep = self.separate_out,
513 529 output_sep2 = self.separate_out2,
514 530 ps1 = self.prompt_in1,
515 531 ps2 = self.prompt_in2,
516 532 ps_out = self.prompt_out,
517 533 pad_left = self.prompts_pad_left)
518 534
519 535 # user may have over-ridden the default print hook:
520 536 try:
521 537 self.outputcache.__class__.display = self.hooks.display
522 538 except AttributeError:
523 539 pass
524 540
525 541 def init_displayhook(self):
526 self.display_trap = DisplayTrap(self, self.outputcache)
542 self.display_trap = DisplayTrap(hook=self.outputcache)
527 543
528 544 def init_reload_doctest(self):
529 545 # Do a proper resetting of doctest, including the necessary displayhook
530 546 # monkeypatching
531 547 try:
532 548 doctest_reload()
533 549 except ImportError:
534 550 warn("doctest module does not exist.")
535 551
536 552 #-------------------------------------------------------------------------
537 553 # Things related to the banner
538 554 #-------------------------------------------------------------------------
539 555
540 556 def init_banner(self, banner1, banner2, display_banner):
541 557 if banner1 is not None:
542 558 self.banner1 = banner1
543 559 if banner2 is not None:
544 560 self.banner2 = banner2
545 561 if display_banner is not None:
546 562 self.display_banner = display_banner
547 563 self.compute_banner()
548 564
549 565 def show_banner(self, banner=None):
550 566 if banner is None:
551 567 banner = self.banner
552 568 self.write(banner)
553 569
554 570 def compute_banner(self):
555 571 self.banner = self.banner1 + '\n'
556 572 if self.profile:
557 573 self.banner += '\nIPython profile: %s\n' % self.profile
558 574 if self.banner2:
559 575 self.banner += '\n' + self.banner2 + '\n'
560 576
561 577 #-------------------------------------------------------------------------
562 578 # Things related to injections into the sys module
563 579 #-------------------------------------------------------------------------
564 580
565 581 def save_sys_module_state(self):
566 582 """Save the state of hooks in the sys module.
567 583
568 584 This has to be called after self.user_ns is created.
569 585 """
570 586 self._orig_sys_module_state = {}
571 587 self._orig_sys_module_state['stdin'] = sys.stdin
572 588 self._orig_sys_module_state['stdout'] = sys.stdout
573 589 self._orig_sys_module_state['stderr'] = sys.stderr
574 590 self._orig_sys_module_state['excepthook'] = sys.excepthook
575 591 try:
576 592 self._orig_sys_modules_main_name = self.user_ns['__name__']
577 593 except KeyError:
578 594 pass
579 595
580 596 def restore_sys_module_state(self):
581 597 """Restore the state of the sys module."""
582 598 try:
583 599 for k, v in self._orig_sys_module_state.items():
584 600 setattr(sys, k, v)
585 601 except AttributeError:
586 602 pass
587 603 try:
588 604 delattr(sys, 'ipcompleter')
589 605 except AttributeError:
590 606 pass
591 607 # Reset what what done in self.init_sys_modules
592 608 try:
593 609 sys.modules[self.user_ns['__name__']] = self._orig_sys_modules_main_name
594 610 except (AttributeError, KeyError):
595 611 pass
596 612
597 613 #-------------------------------------------------------------------------
598 614 # Things related to hooks
599 615 #-------------------------------------------------------------------------
600 616
601 617 def init_hooks(self):
602 618 # hooks holds pointers used for user-side customizations
603 619 self.hooks = Struct()
604 620
605 621 self.strdispatchers = {}
606 622
607 623 # Set all default hooks, defined in the IPython.hooks module.
608 624 hooks = IPython.core.hooks
609 625 for hook_name in hooks.__all__:
610 626 # default hooks have priority 100, i.e. low; user hooks should have
611 627 # 0-100 priority
612 628 self.set_hook(hook_name,getattr(hooks,hook_name), 100)
613 629
614 630 def set_hook(self,name,hook, priority = 50, str_key = None, re_key = None):
615 631 """set_hook(name,hook) -> sets an internal IPython hook.
616 632
617 633 IPython exposes some of its internal API as user-modifiable hooks. By
618 634 adding your function to one of these hooks, you can modify IPython's
619 635 behavior to call at runtime your own routines."""
620 636
621 637 # At some point in the future, this should validate the hook before it
622 638 # accepts it. Probably at least check that the hook takes the number
623 639 # of args it's supposed to.
624 640
625 641 f = new.instancemethod(hook,self,self.__class__)
626 642
627 643 # check if the hook is for strdispatcher first
628 644 if str_key is not None:
629 645 sdp = self.strdispatchers.get(name, StrDispatch())
630 646 sdp.add_s(str_key, f, priority )
631 647 self.strdispatchers[name] = sdp
632 648 return
633 649 if re_key is not None:
634 650 sdp = self.strdispatchers.get(name, StrDispatch())
635 651 sdp.add_re(re.compile(re_key), f, priority )
636 652 self.strdispatchers[name] = sdp
637 653 return
638 654
639 655 dp = getattr(self.hooks, name, None)
640 656 if name not in IPython.core.hooks.__all__:
641 657 print "Warning! Hook '%s' is not one of %s" % (name, IPython.core.hooks.__all__ )
642 658 if not dp:
643 659 dp = IPython.core.hooks.CommandChainDispatcher()
644 660
645 661 try:
646 662 dp.add(f,priority)
647 663 except AttributeError:
648 664 # it was not commandchain, plain old func - replace
649 665 dp = f
650 666
651 667 setattr(self.hooks,name, dp)
652 668
653 669 #-------------------------------------------------------------------------
654 670 # Things related to the "main" module
655 671 #-------------------------------------------------------------------------
656 672
657 673 def new_main_mod(self,ns=None):
658 674 """Return a new 'main' module object for user code execution.
659 675 """
660 676 main_mod = self._user_main_module
661 677 init_fakemod_dict(main_mod,ns)
662 678 return main_mod
663 679
664 680 def cache_main_mod(self,ns,fname):
665 681 """Cache a main module's namespace.
666 682
667 683 When scripts are executed via %run, we must keep a reference to the
668 684 namespace of their __main__ module (a FakeModule instance) around so
669 685 that Python doesn't clear it, rendering objects defined therein
670 686 useless.
671 687
672 688 This method keeps said reference in a private dict, keyed by the
673 689 absolute path of the module object (which corresponds to the script
674 690 path). This way, for multiple executions of the same script we only
675 691 keep one copy of the namespace (the last one), thus preventing memory
676 692 leaks from old references while allowing the objects from the last
677 693 execution to be accessible.
678 694
679 695 Note: we can not allow the actual FakeModule instances to be deleted,
680 696 because of how Python tears down modules (it hard-sets all their
681 697 references to None without regard for reference counts). This method
682 698 must therefore make a *copy* of the given namespace, to allow the
683 699 original module's __dict__ to be cleared and reused.
684 700
685 701
686 702 Parameters
687 703 ----------
688 704 ns : a namespace (a dict, typically)
689 705
690 706 fname : str
691 707 Filename associated with the namespace.
692 708
693 709 Examples
694 710 --------
695 711
696 712 In [10]: import IPython
697 713
698 714 In [11]: _ip.cache_main_mod(IPython.__dict__,IPython.__file__)
699 715
700 716 In [12]: IPython.__file__ in _ip._main_ns_cache
701 717 Out[12]: True
702 718 """
703 719 self._main_ns_cache[os.path.abspath(fname)] = ns.copy()
704 720
705 721 def clear_main_mod_cache(self):
706 722 """Clear the cache of main modules.
707 723
708 724 Mainly for use by utilities like %reset.
709 725
710 726 Examples
711 727 --------
712 728
713 729 In [15]: import IPython
714 730
715 731 In [16]: _ip.cache_main_mod(IPython.__dict__,IPython.__file__)
716 732
717 733 In [17]: len(_ip._main_ns_cache) > 0
718 734 Out[17]: True
719 735
720 736 In [18]: _ip.clear_main_mod_cache()
721 737
722 738 In [19]: len(_ip._main_ns_cache) == 0
723 739 Out[19]: True
724 740 """
725 741 self._main_ns_cache.clear()
726 742
727 743 #-------------------------------------------------------------------------
728 744 # Things related to debugging
729 745 #-------------------------------------------------------------------------
730 746
731 747 def init_pdb(self):
732 748 # Set calling of pdb on exceptions
733 749 # self.call_pdb is a property
734 750 self.call_pdb = self.pdb
735 751
736 752 def _get_call_pdb(self):
737 753 return self._call_pdb
738 754
739 755 def _set_call_pdb(self,val):
740 756
741 757 if val not in (0,1,False,True):
742 758 raise ValueError,'new call_pdb value must be boolean'
743 759
744 760 # store value in instance
745 761 self._call_pdb = val
746 762
747 763 # notify the actual exception handlers
748 764 self.InteractiveTB.call_pdb = val
749 765 if self.isthreaded:
750 766 try:
751 767 self.sys_excepthook.call_pdb = val
752 768 except:
753 769 warn('Failed to activate pdb for threaded exception handler')
754 770
755 771 call_pdb = property(_get_call_pdb,_set_call_pdb,None,
756 772 'Control auto-activation of pdb at exceptions')
757 773
758 774 def debugger(self,force=False):
759 775 """Call the pydb/pdb debugger.
760 776
761 777 Keywords:
762 778
763 779 - force(False): by default, this routine checks the instance call_pdb
764 780 flag and does not actually invoke the debugger if the flag is false.
765 781 The 'force' option forces the debugger to activate even if the flag
766 782 is false.
767 783 """
768 784
769 785 if not (force or self.call_pdb):
770 786 return
771 787
772 788 if not hasattr(sys,'last_traceback'):
773 789 error('No traceback has been produced, nothing to debug.')
774 790 return
775 791
776 792 # use pydb if available
777 793 if debugger.has_pydb:
778 794 from pydb import pm
779 795 else:
780 796 # fallback to our internal debugger
781 797 pm = lambda : self.InteractiveTB.debugger(force=True)
782 798 self.history_saving_wrapper(pm)()
783 799
784 800 #-------------------------------------------------------------------------
785 801 # Things related to IPython's various namespaces
786 802 #-------------------------------------------------------------------------
787 803
788 804 def init_create_namespaces(self, user_ns=None, user_global_ns=None):
789 805 # Create the namespace where the user will operate. user_ns is
790 806 # normally the only one used, and it is passed to the exec calls as
791 807 # the locals argument. But we do carry a user_global_ns namespace
792 808 # given as the exec 'globals' argument, This is useful in embedding
793 809 # situations where the ipython shell opens in a context where the
794 810 # distinction between locals and globals is meaningful. For
795 811 # non-embedded contexts, it is just the same object as the user_ns dict.
796 812
797 813 # FIXME. For some strange reason, __builtins__ is showing up at user
798 814 # level as a dict instead of a module. This is a manual fix, but I
799 815 # should really track down where the problem is coming from. Alex
800 816 # Schmolck reported this problem first.
801 817
802 818 # A useful post by Alex Martelli on this topic:
803 819 # Re: inconsistent value from __builtins__
804 820 # Von: Alex Martelli <aleaxit@yahoo.com>
805 821 # Datum: Freitag 01 Oktober 2004 04:45:34 nachmittags/abends
806 822 # Gruppen: comp.lang.python
807 823
808 824 # Michael Hohn <hohn@hooknose.lbl.gov> wrote:
809 825 # > >>> print type(builtin_check.get_global_binding('__builtins__'))
810 826 # > <type 'dict'>
811 827 # > >>> print type(__builtins__)
812 828 # > <type 'module'>
813 829 # > Is this difference in return value intentional?
814 830
815 831 # Well, it's documented that '__builtins__' can be either a dictionary
816 832 # or a module, and it's been that way for a long time. Whether it's
817 833 # intentional (or sensible), I don't know. In any case, the idea is
818 834 # that if you need to access the built-in namespace directly, you
819 835 # should start with "import __builtin__" (note, no 's') which will
820 836 # definitely give you a module. Yeah, it's somewhat confusing:-(.
821 837
822 838 # These routines return properly built dicts as needed by the rest of
823 839 # the code, and can also be used by extension writers to generate
824 840 # properly initialized namespaces.
825 841 user_ns, user_global_ns = self.make_user_namespaces(user_ns, user_global_ns)
826 842
827 843 # Assign namespaces
828 844 # This is the namespace where all normal user variables live
829 845 self.user_ns = user_ns
830 846 self.user_global_ns = user_global_ns
831 847
832 848 # An auxiliary namespace that checks what parts of the user_ns were
833 849 # loaded at startup, so we can list later only variables defined in
834 850 # actual interactive use. Since it is always a subset of user_ns, it
835 851 # doesn't need to be separately tracked in the ns_table.
836 852 self.user_ns_hidden = {}
837 853
838 854 # A namespace to keep track of internal data structures to prevent
839 855 # them from cluttering user-visible stuff. Will be updated later
840 856 self.internal_ns = {}
841 857
842 858 # Now that FakeModule produces a real module, we've run into a nasty
843 859 # problem: after script execution (via %run), the module where the user
844 860 # code ran is deleted. Now that this object is a true module (needed
845 861 # so docetst and other tools work correctly), the Python module
846 862 # teardown mechanism runs over it, and sets to None every variable
847 863 # present in that module. Top-level references to objects from the
848 864 # script survive, because the user_ns is updated with them. However,
849 865 # calling functions defined in the script that use other things from
850 866 # the script will fail, because the function's closure had references
851 867 # to the original objects, which are now all None. So we must protect
852 868 # these modules from deletion by keeping a cache.
853 869 #
854 870 # To avoid keeping stale modules around (we only need the one from the
855 871 # last run), we use a dict keyed with the full path to the script, so
856 872 # only the last version of the module is held in the cache. Note,
857 873 # however, that we must cache the module *namespace contents* (their
858 874 # __dict__). Because if we try to cache the actual modules, old ones
859 875 # (uncached) could be destroyed while still holding references (such as
860 876 # those held by GUI objects that tend to be long-lived)>
861 877 #
862 878 # The %reset command will flush this cache. See the cache_main_mod()
863 879 # and clear_main_mod_cache() methods for details on use.
864 880
865 881 # This is the cache used for 'main' namespaces
866 882 self._main_ns_cache = {}
867 883 # And this is the single instance of FakeModule whose __dict__ we keep
868 884 # copying and clearing for reuse on each %run
869 885 self._user_main_module = FakeModule()
870 886
871 887 # A table holding all the namespaces IPython deals with, so that
872 888 # introspection facilities can search easily.
873 889 self.ns_table = {'user':user_ns,
874 890 'user_global':user_global_ns,
875 891 'internal':self.internal_ns,
876 892 'builtin':__builtin__.__dict__
877 893 }
878 894
879 895 # Similarly, track all namespaces where references can be held and that
880 896 # we can safely clear (so it can NOT include builtin). This one can be
881 897 # a simple list.
882 898 self.ns_refs_table = [ user_ns, user_global_ns, self.user_ns_hidden,
883 899 self.internal_ns, self._main_ns_cache ]
884 900
885 901 def make_user_namespaces(self, user_ns=None, user_global_ns=None):
886 902 """Return a valid local and global user interactive namespaces.
887 903
888 904 This builds a dict with the minimal information needed to operate as a
889 905 valid IPython user namespace, which you can pass to the various
890 906 embedding classes in ipython. The default implementation returns the
891 907 same dict for both the locals and the globals to allow functions to
892 908 refer to variables in the namespace. Customized implementations can
893 909 return different dicts. The locals dictionary can actually be anything
894 910 following the basic mapping protocol of a dict, but the globals dict
895 911 must be a true dict, not even a subclass. It is recommended that any
896 912 custom object for the locals namespace synchronize with the globals
897 913 dict somehow.
898 914
899 915 Raises TypeError if the provided globals namespace is not a true dict.
900 916
901 917 Parameters
902 918 ----------
903 919 user_ns : dict-like, optional
904 920 The current user namespace. The items in this namespace should
905 921 be included in the output. If None, an appropriate blank
906 922 namespace should be created.
907 923 user_global_ns : dict, optional
908 924 The current user global namespace. The items in this namespace
909 925 should be included in the output. If None, an appropriate
910 926 blank namespace should be created.
911 927
912 928 Returns
913 929 -------
914 930 A pair of dictionary-like object to be used as the local namespace
915 931 of the interpreter and a dict to be used as the global namespace.
916 932 """
917 933
918 934
919 935 # We must ensure that __builtin__ (without the final 's') is always
920 936 # available and pointing to the __builtin__ *module*. For more details:
921 937 # http://mail.python.org/pipermail/python-dev/2001-April/014068.html
922 938
923 939 if user_ns is None:
924 940 # Set __name__ to __main__ to better match the behavior of the
925 941 # normal interpreter.
926 942 user_ns = {'__name__' :'__main__',
927 943 '__builtin__' : __builtin__,
928 944 '__builtins__' : __builtin__,
929 945 }
930 946 else:
931 947 user_ns.setdefault('__name__','__main__')
932 948 user_ns.setdefault('__builtin__',__builtin__)
933 949 user_ns.setdefault('__builtins__',__builtin__)
934 950
935 951 if user_global_ns is None:
936 952 user_global_ns = user_ns
937 953 if type(user_global_ns) is not dict:
938 954 raise TypeError("user_global_ns must be a true dict; got %r"
939 955 % type(user_global_ns))
940 956
941 957 return user_ns, user_global_ns
942 958
943 959 def init_sys_modules(self):
944 960 # We need to insert into sys.modules something that looks like a
945 961 # module but which accesses the IPython namespace, for shelve and
946 962 # pickle to work interactively. Normally they rely on getting
947 963 # everything out of __main__, but for embedding purposes each IPython
948 964 # instance has its own private namespace, so we can't go shoving
949 965 # everything into __main__.
950 966
951 967 # note, however, that we should only do this for non-embedded
952 968 # ipythons, which really mimic the __main__.__dict__ with their own
953 969 # namespace. Embedded instances, on the other hand, should not do
954 970 # this because they need to manage the user local/global namespaces
955 971 # only, but they live within a 'normal' __main__ (meaning, they
956 972 # shouldn't overtake the execution environment of the script they're
957 973 # embedded in).
958 974
959 975 # This is overridden in the InteractiveShellEmbed subclass to a no-op.
960 976
961 977 try:
962 978 main_name = self.user_ns['__name__']
963 979 except KeyError:
964 980 raise KeyError('user_ns dictionary MUST have a "__name__" key')
965 981 else:
966 982 sys.modules[main_name] = FakeModule(self.user_ns)
967 983
968 984 def init_user_ns(self):
969 985 """Initialize all user-visible namespaces to their minimum defaults.
970 986
971 987 Certain history lists are also initialized here, as they effectively
972 988 act as user namespaces.
973 989
974 990 Notes
975 991 -----
976 992 All data structures here are only filled in, they are NOT reset by this
977 993 method. If they were not empty before, data will simply be added to
978 994 therm.
979 995 """
980 996 # This function works in two parts: first we put a few things in
981 997 # user_ns, and we sync that contents into user_ns_hidden so that these
982 998 # initial variables aren't shown by %who. After the sync, we add the
983 999 # rest of what we *do* want the user to see with %who even on a new
984 1000 # session (probably nothing, so theye really only see their own stuff)
985 1001
986 1002 # The user dict must *always* have a __builtin__ reference to the
987 1003 # Python standard __builtin__ namespace, which must be imported.
988 1004 # This is so that certain operations in prompt evaluation can be
989 1005 # reliably executed with builtins. Note that we can NOT use
990 1006 # __builtins__ (note the 's'), because that can either be a dict or a
991 1007 # module, and can even mutate at runtime, depending on the context
992 1008 # (Python makes no guarantees on it). In contrast, __builtin__ is
993 1009 # always a module object, though it must be explicitly imported.
994 1010
995 1011 # For more details:
996 1012 # http://mail.python.org/pipermail/python-dev/2001-April/014068.html
997 1013 ns = dict(__builtin__ = __builtin__)
998 1014
999 1015 # Put 'help' in the user namespace
1000 1016 try:
1001 1017 from site import _Helper
1002 1018 ns['help'] = _Helper()
1003 1019 except ImportError:
1004 1020 warn('help() not available - check site.py')
1005 1021
1006 1022 # make global variables for user access to the histories
1007 1023 ns['_ih'] = self.input_hist
1008 1024 ns['_oh'] = self.output_hist
1009 1025 ns['_dh'] = self.dir_hist
1010 1026
1011 1027 ns['_sh'] = shadowns
1012 1028
1013 1029 # user aliases to input and output histories. These shouldn't show up
1014 1030 # in %who, as they can have very large reprs.
1015 1031 ns['In'] = self.input_hist
1016 1032 ns['Out'] = self.output_hist
1017 1033
1018 1034 # Store myself as the public api!!!
1019 1035 ns['get_ipython'] = self.get_ipython
1020 1036
1021 1037 # Sync what we've added so far to user_ns_hidden so these aren't seen
1022 1038 # by %who
1023 1039 self.user_ns_hidden.update(ns)
1024 1040
1025 1041 # Anything put into ns now would show up in %who. Think twice before
1026 1042 # putting anything here, as we really want %who to show the user their
1027 1043 # stuff, not our variables.
1028 1044
1029 1045 # Finally, update the real user's namespace
1030 1046 self.user_ns.update(ns)
1031 1047
1032 1048
1033 1049 def reset(self):
1034 1050 """Clear all internal namespaces.
1035 1051
1036 1052 Note that this is much more aggressive than %reset, since it clears
1037 1053 fully all namespaces, as well as all input/output lists.
1038 1054 """
1039 1055 for ns in self.ns_refs_table:
1040 1056 ns.clear()
1041 1057
1042 1058 self.alias_manager.clear_aliases()
1043 1059
1044 1060 # Clear input and output histories
1045 1061 self.input_hist[:] = []
1046 1062 self.input_hist_raw[:] = []
1047 1063 self.output_hist.clear()
1048 1064
1049 1065 # Restore the user namespaces to minimal usability
1050 1066 self.init_user_ns()
1051 1067
1052 1068 # Restore the default and user aliases
1053 1069 self.alias_manager.init_aliases()
1054 1070
1055 1071 def reset_selective(self, regex=None):
1056 1072 """Clear selective variables from internal namespaces based on a specified regular expression.
1057 1073
1058 1074 Parameters
1059 1075 ----------
1060 1076 regex : string or compiled pattern, optional
1061 1077 A regular expression pattern that will be used in searching variable names in the users
1062 1078 namespaces.
1063 1079 """
1064 1080 if regex is not None:
1065 1081 try:
1066 1082 m = re.compile(regex)
1067 1083 except TypeError:
1068 1084 raise TypeError('regex must be a string or compiled pattern')
1069 1085 # Search for keys in each namespace that match the given regex
1070 1086 # If a match is found, delete the key/value pair.
1071 1087 for ns in self.ns_refs_table:
1072 1088 for var in ns:
1073 1089 if m.search(var):
1074 1090 del ns[var]
1075 1091
1076 1092 def push(self, variables, interactive=True):
1077 1093 """Inject a group of variables into the IPython user namespace.
1078 1094
1079 1095 Parameters
1080 1096 ----------
1081 1097 variables : dict, str or list/tuple of str
1082 1098 The variables to inject into the user's namespace. If a dict,
1083 1099 a simple update is done. If a str, the string is assumed to
1084 1100 have variable names separated by spaces. A list/tuple of str
1085 1101 can also be used to give the variable names. If just the variable
1086 1102 names are give (list/tuple/str) then the variable values looked
1087 1103 up in the callers frame.
1088 1104 interactive : bool
1089 1105 If True (default), the variables will be listed with the ``who``
1090 1106 magic.
1091 1107 """
1092 1108 vdict = None
1093 1109
1094 1110 # We need a dict of name/value pairs to do namespace updates.
1095 1111 if isinstance(variables, dict):
1096 1112 vdict = variables
1097 1113 elif isinstance(variables, (basestring, list, tuple)):
1098 1114 if isinstance(variables, basestring):
1099 1115 vlist = variables.split()
1100 1116 else:
1101 1117 vlist = variables
1102 1118 vdict = {}
1103 1119 cf = sys._getframe(1)
1104 1120 for name in vlist:
1105 1121 try:
1106 1122 vdict[name] = eval(name, cf.f_globals, cf.f_locals)
1107 1123 except:
1108 1124 print ('Could not get variable %s from %s' %
1109 1125 (name,cf.f_code.co_name))
1110 1126 else:
1111 1127 raise ValueError('variables must be a dict/str/list/tuple')
1112 1128
1113 1129 # Propagate variables to user namespace
1114 1130 self.user_ns.update(vdict)
1115 1131
1116 1132 # And configure interactive visibility
1117 1133 config_ns = self.user_ns_hidden
1118 1134 if interactive:
1119 1135 for name, val in vdict.iteritems():
1120 1136 config_ns.pop(name, None)
1121 1137 else:
1122 1138 for name,val in vdict.iteritems():
1123 1139 config_ns[name] = val
1124 1140
1125 1141 #-------------------------------------------------------------------------
1126 1142 # Things related to history management
1127 1143 #-------------------------------------------------------------------------
1128 1144
1129 1145 def init_history(self):
1130 1146 # List of input with multi-line handling.
1131 1147 self.input_hist = InputList()
1132 1148 # This one will hold the 'raw' input history, without any
1133 1149 # pre-processing. This will allow users to retrieve the input just as
1134 1150 # it was exactly typed in by the user, with %hist -r.
1135 1151 self.input_hist_raw = InputList()
1136 1152
1137 1153 # list of visited directories
1138 1154 try:
1139 1155 self.dir_hist = [os.getcwd()]
1140 1156 except OSError:
1141 1157 self.dir_hist = []
1142 1158
1143 1159 # dict of output history
1144 1160 self.output_hist = {}
1145 1161
1146 1162 # Now the history file
1147 1163 if self.profile:
1148 1164 histfname = 'history-%s' % self.profile
1149 1165 else:
1150 1166 histfname = 'history'
1151 1167 self.histfile = os.path.join(self.ipython_dir, histfname)
1152 1168
1153 1169 # Fill the history zero entry, user counter starts at 1
1154 1170 self.input_hist.append('\n')
1155 1171 self.input_hist_raw.append('\n')
1156 1172
1157 1173 def init_shadow_hist(self):
1158 1174 try:
1159 1175 self.db = pickleshare.PickleShareDB(self.ipython_dir + "/db")
1160 1176 except exceptions.UnicodeDecodeError:
1161 1177 print "Your ipython_dir can't be decoded to unicode!"
1162 1178 print "Please set HOME environment variable to something that"
1163 1179 print r"only has ASCII characters, e.g. c:\home"
1164 1180 print "Now it is", self.ipython_dir
1165 1181 sys.exit()
1166 1182 self.shadowhist = ipcorehist.ShadowHist(self.db)
1167 1183
1168 1184 def savehist(self):
1169 1185 """Save input history to a file (via readline library)."""
1170 1186
1171 1187 try:
1172 1188 self.readline.write_history_file(self.histfile)
1173 1189 except:
1174 1190 print 'Unable to save IPython command history to file: ' + \
1175 1191 `self.histfile`
1176 1192
1177 1193 def reloadhist(self):
1178 1194 """Reload the input history from disk file."""
1179 1195
1180 1196 try:
1181 1197 self.readline.clear_history()
1182 1198 self.readline.read_history_file(self.shell.histfile)
1183 1199 except AttributeError:
1184 1200 pass
1185 1201
1186 1202 def history_saving_wrapper(self, func):
1187 1203 """ Wrap func for readline history saving
1188 1204
1189 1205 Convert func into callable that saves & restores
1190 1206 history around the call """
1191 1207
1192 1208 if self.has_readline:
1193 1209 from IPython.utils import rlineimpl as readline
1194 1210 else:
1195 1211 return func
1196 1212
1197 1213 def wrapper():
1198 1214 self.savehist()
1199 1215 try:
1200 1216 func()
1201 1217 finally:
1202 1218 readline.read_history_file(self.histfile)
1203 1219 return wrapper
1204 1220
1205 1221 #-------------------------------------------------------------------------
1206 1222 # Things related to exception handling and tracebacks (not debugging)
1207 1223 #-------------------------------------------------------------------------
1208 1224
1209 1225 def init_traceback_handlers(self, custom_exceptions):
1210 1226 # Syntax error handler.
1211 1227 self.SyntaxTB = SyntaxTB(color_scheme='NoColor')
1212 1228
1213 1229 # The interactive one is initialized with an offset, meaning we always
1214 1230 # want to remove the topmost item in the traceback, which is our own
1215 1231 # internal code. Valid modes: ['Plain','Context','Verbose']
1216 1232 self.InteractiveTB = ultratb.AutoFormattedTB(mode = 'Plain',
1217 1233 color_scheme='NoColor',
1218 1234 tb_offset = 1)
1219 1235
1220 1236 # The instance will store a pointer to the system-wide exception hook,
1221 1237 # so that runtime code (such as magics) can access it. This is because
1222 1238 # during the read-eval loop, it may get temporarily overwritten.
1223 1239 self.sys_excepthook = sys.excepthook
1224 1240
1225 1241 # and add any custom exception handlers the user may have specified
1226 1242 self.set_custom_exc(*custom_exceptions)
1227 1243
1228 1244 # Set the exception mode
1229 1245 self.InteractiveTB.set_mode(mode=self.xmode)
1230 1246
1231 1247 def set_custom_exc(self,exc_tuple,handler):
1232 1248 """set_custom_exc(exc_tuple,handler)
1233 1249
1234 1250 Set a custom exception handler, which will be called if any of the
1235 1251 exceptions in exc_tuple occur in the mainloop (specifically, in the
1236 1252 runcode() method.
1237 1253
1238 1254 Inputs:
1239 1255
1240 1256 - exc_tuple: a *tuple* of valid exceptions to call the defined
1241 1257 handler for. It is very important that you use a tuple, and NOT A
1242 1258 LIST here, because of the way Python's except statement works. If
1243 1259 you only want to trap a single exception, use a singleton tuple:
1244 1260
1245 1261 exc_tuple == (MyCustomException,)
1246 1262
1247 1263 - handler: this must be defined as a function with the following
1248 1264 basic interface: def my_handler(self,etype,value,tb).
1249 1265
1250 1266 This will be made into an instance method (via new.instancemethod)
1251 1267 of IPython itself, and it will be called if any of the exceptions
1252 1268 listed in the exc_tuple are caught. If the handler is None, an
1253 1269 internal basic one is used, which just prints basic info.
1254 1270
1255 1271 WARNING: by putting in your own exception handler into IPython's main
1256 1272 execution loop, you run a very good chance of nasty crashes. This
1257 1273 facility should only be used if you really know what you are doing."""
1258 1274
1259 1275 assert type(exc_tuple)==type(()) , \
1260 1276 "The custom exceptions must be given AS A TUPLE."
1261 1277
1262 1278 def dummy_handler(self,etype,value,tb):
1263 1279 print '*** Simple custom exception handler ***'
1264 1280 print 'Exception type :',etype
1265 1281 print 'Exception value:',value
1266 1282 print 'Traceback :',tb
1267 1283 print 'Source code :','\n'.join(self.buffer)
1268 1284
1269 1285 if handler is None: handler = dummy_handler
1270 1286
1271 1287 self.CustomTB = new.instancemethod(handler,self,self.__class__)
1272 1288 self.custom_exceptions = exc_tuple
1273 1289
1274 1290 def excepthook(self, etype, value, tb):
1275 1291 """One more defense for GUI apps that call sys.excepthook.
1276 1292
1277 1293 GUI frameworks like wxPython trap exceptions and call
1278 1294 sys.excepthook themselves. I guess this is a feature that
1279 1295 enables them to keep running after exceptions that would
1280 1296 otherwise kill their mainloop. This is a bother for IPython
1281 1297 which excepts to catch all of the program exceptions with a try:
1282 1298 except: statement.
1283 1299
1284 1300 Normally, IPython sets sys.excepthook to a CrashHandler instance, so if
1285 1301 any app directly invokes sys.excepthook, it will look to the user like
1286 1302 IPython crashed. In order to work around this, we can disable the
1287 1303 CrashHandler and replace it with this excepthook instead, which prints a
1288 1304 regular traceback using our InteractiveTB. In this fashion, apps which
1289 1305 call sys.excepthook will generate a regular-looking exception from
1290 1306 IPython, and the CrashHandler will only be triggered by real IPython
1291 1307 crashes.
1292 1308
1293 1309 This hook should be used sparingly, only in places which are not likely
1294 1310 to be true IPython errors.
1295 1311 """
1296 1312 self.showtraceback((etype,value,tb),tb_offset=0)
1297 1313
1298 1314 def showtraceback(self,exc_tuple = None,filename=None,tb_offset=None,
1299 1315 exception_only=False):
1300 1316 """Display the exception that just occurred.
1301 1317
1302 1318 If nothing is known about the exception, this is the method which
1303 1319 should be used throughout the code for presenting user tracebacks,
1304 1320 rather than directly invoking the InteractiveTB object.
1305 1321
1306 1322 A specific showsyntaxerror() also exists, but this method can take
1307 1323 care of calling it if needed, so unless you are explicitly catching a
1308 1324 SyntaxError exception, don't try to analyze the stack manually and
1309 1325 simply call this method."""
1310 1326
1311 1327 try:
1312 1328 if exc_tuple is None:
1313 1329 etype, value, tb = sys.exc_info()
1314 1330 else:
1315 1331 etype, value, tb = exc_tuple
1316 1332
1317 1333 if etype is None:
1318 1334 if hasattr(sys, 'last_type'):
1319 1335 etype, value, tb = sys.last_type, sys.last_value, \
1320 1336 sys.last_traceback
1321 1337 else:
1322 1338 self.write('No traceback available to show.\n')
1323 1339 return
1324 1340
1325 1341 if etype is SyntaxError:
1326 1342 # Though this won't be called by syntax errors in the input
1327 1343 # line, there may be SyntaxError cases whith imported code.
1328 1344 self.showsyntaxerror(filename)
1329 1345 elif etype is UsageError:
1330 1346 print "UsageError:", value
1331 1347 else:
1332 1348 # WARNING: these variables are somewhat deprecated and not
1333 1349 # necessarily safe to use in a threaded environment, but tools
1334 1350 # like pdb depend on their existence, so let's set them. If we
1335 1351 # find problems in the field, we'll need to revisit their use.
1336 1352 sys.last_type = etype
1337 1353 sys.last_value = value
1338 1354 sys.last_traceback = tb
1339 1355
1340 1356 if etype in self.custom_exceptions:
1341 1357 self.CustomTB(etype,value,tb)
1342 1358 else:
1343 1359 if exception_only:
1344 1360 m = ('An exception has occurred, use %tb to see the '
1345 1361 'full traceback.')
1346 1362 print m
1347 1363 self.InteractiveTB.show_exception_only(etype, value)
1348 1364 else:
1349 1365 self.InteractiveTB(etype,value,tb,tb_offset=tb_offset)
1350 1366 if self.InteractiveTB.call_pdb:
1351 1367 # pdb mucks up readline, fix it back
1352 1368 self.set_completer()
1353 1369
1354 1370 except KeyboardInterrupt:
1355 1371 self.write("\nKeyboardInterrupt\n")
1356 1372
1357 1373
1358 1374 def showsyntaxerror(self, filename=None):
1359 1375 """Display the syntax error that just occurred.
1360 1376
1361 1377 This doesn't display a stack trace because there isn't one.
1362 1378
1363 1379 If a filename is given, it is stuffed in the exception instead
1364 1380 of what was there before (because Python's parser always uses
1365 1381 "<string>" when reading from a string).
1366 1382 """
1367 1383 etype, value, last_traceback = sys.exc_info()
1368 1384
1369 1385 # See note about these variables in showtraceback() above
1370 1386 sys.last_type = etype
1371 1387 sys.last_value = value
1372 1388 sys.last_traceback = last_traceback
1373 1389
1374 1390 if filename and etype is SyntaxError:
1375 1391 # Work hard to stuff the correct filename in the exception
1376 1392 try:
1377 1393 msg, (dummy_filename, lineno, offset, line) = value
1378 1394 except:
1379 1395 # Not the format we expect; leave it alone
1380 1396 pass
1381 1397 else:
1382 1398 # Stuff in the right filename
1383 1399 try:
1384 1400 # Assume SyntaxError is a class exception
1385 1401 value = SyntaxError(msg, (filename, lineno, offset, line))
1386 1402 except:
1387 1403 # If that failed, assume SyntaxError is a string
1388 1404 value = msg, (filename, lineno, offset, line)
1389 1405 self.SyntaxTB(etype,value,[])
1390 1406
1391 1407 def edit_syntax_error(self):
1392 1408 """The bottom half of the syntax error handler called in the main loop.
1393 1409
1394 1410 Loop until syntax error is fixed or user cancels.
1395 1411 """
1396 1412
1397 1413 while self.SyntaxTB.last_syntax_error:
1398 1414 # copy and clear last_syntax_error
1399 1415 err = self.SyntaxTB.clear_err_state()
1400 1416 if not self._should_recompile(err):
1401 1417 return
1402 1418 try:
1403 1419 # may set last_syntax_error again if a SyntaxError is raised
1404 1420 self.safe_execfile(err.filename,self.user_ns)
1405 1421 except:
1406 1422 self.showtraceback()
1407 1423 else:
1408 1424 try:
1409 1425 f = file(err.filename)
1410 1426 try:
1411 1427 # This should be inside a display_trap block and I
1412 1428 # think it is.
1413 1429 sys.displayhook(f.read())
1414 1430 finally:
1415 1431 f.close()
1416 1432 except:
1417 1433 self.showtraceback()
1418 1434
1419 1435 def _should_recompile(self,e):
1420 1436 """Utility routine for edit_syntax_error"""
1421 1437
1422 1438 if e.filename in ('<ipython console>','<input>','<string>',
1423 1439 '<console>','<BackgroundJob compilation>',
1424 1440 None):
1425 1441
1426 1442 return False
1427 1443 try:
1428 1444 if (self.autoedit_syntax and
1429 1445 not self.ask_yes_no('Return to editor to correct syntax error? '
1430 1446 '[Y/n] ','y')):
1431 1447 return False
1432 1448 except EOFError:
1433 1449 return False
1434 1450
1435 1451 def int0(x):
1436 1452 try:
1437 1453 return int(x)
1438 1454 except TypeError:
1439 1455 return 0
1440 1456 # always pass integer line and offset values to editor hook
1441 1457 try:
1442 1458 self.hooks.fix_error_editor(e.filename,
1443 1459 int0(e.lineno),int0(e.offset),e.msg)
1444 1460 except TryNext:
1445 1461 warn('Could not open editor')
1446 1462 return False
1447 1463 return True
1448 1464
1449 1465 #-------------------------------------------------------------------------
1450 1466 # Things related to tab completion
1451 1467 #-------------------------------------------------------------------------
1452 1468
1453 1469 def complete(self, text):
1454 1470 """Return a sorted list of all possible completions on text.
1455 1471
1456 1472 Inputs:
1457 1473
1458 1474 - text: a string of text to be completed on.
1459 1475
1460 1476 This is a wrapper around the completion mechanism, similar to what
1461 1477 readline does at the command line when the TAB key is hit. By
1462 1478 exposing it as a method, it can be used by other non-readline
1463 1479 environments (such as GUIs) for text completion.
1464 1480
1465 1481 Simple usage example:
1466 1482
1467 1483 In [7]: x = 'hello'
1468 1484
1469 1485 In [8]: x
1470 1486 Out[8]: 'hello'
1471 1487
1472 1488 In [9]: print x
1473 1489 hello
1474 1490
1475 1491 In [10]: _ip.complete('x.l')
1476 1492 Out[10]: ['x.ljust', 'x.lower', 'x.lstrip']
1477 1493 """
1478 1494
1479 1495 # Inject names into __builtin__ so we can complete on the added names.
1480 1496 with self.builtin_trap:
1481 1497 complete = self.Completer.complete
1482 1498 state = 0
1483 1499 # use a dict so we get unique keys, since ipyhton's multiple
1484 1500 # completers can return duplicates. When we make 2.4 a requirement,
1485 1501 # start using sets instead, which are faster.
1486 1502 comps = {}
1487 1503 while True:
1488 1504 newcomp = complete(text,state,line_buffer=text)
1489 1505 if newcomp is None:
1490 1506 break
1491 1507 comps[newcomp] = 1
1492 1508 state += 1
1493 1509 outcomps = comps.keys()
1494 1510 outcomps.sort()
1495 1511 #print "T:",text,"OC:",outcomps # dbg
1496 1512 #print "vars:",self.user_ns.keys()
1497 1513 return outcomps
1498 1514
1499 1515 def set_custom_completer(self,completer,pos=0):
1500 1516 """Adds a new custom completer function.
1501 1517
1502 1518 The position argument (defaults to 0) is the index in the completers
1503 1519 list where you want the completer to be inserted."""
1504 1520
1505 1521 newcomp = new.instancemethod(completer,self.Completer,
1506 1522 self.Completer.__class__)
1507 1523 self.Completer.matchers.insert(pos,newcomp)
1508 1524
1509 1525 def set_completer(self):
1510 1526 """Reset readline's completer to be our own."""
1511 1527 self.readline.set_completer(self.Completer.complete)
1512 1528
1513 1529 def set_completer_frame(self, frame=None):
1514 1530 """Set the frame of the completer."""
1515 1531 if frame:
1516 1532 self.Completer.namespace = frame.f_locals
1517 1533 self.Completer.global_namespace = frame.f_globals
1518 1534 else:
1519 1535 self.Completer.namespace = self.user_ns
1520 1536 self.Completer.global_namespace = self.user_global_ns
1521 1537
1522 1538 #-------------------------------------------------------------------------
1523 1539 # Things related to readline
1524 1540 #-------------------------------------------------------------------------
1525 1541
1526 1542 def init_readline(self):
1527 1543 """Command history completion/saving/reloading."""
1528 1544
1529 1545 if self.readline_use:
1530 1546 import IPython.utils.rlineimpl as readline
1531 1547
1532 1548 self.rl_next_input = None
1533 1549 self.rl_do_indent = False
1534 1550
1535 1551 if not self.readline_use or not readline.have_readline:
1536 1552 self.has_readline = False
1537 1553 self.readline = None
1538 1554 # Set a number of methods that depend on readline to be no-op
1539 1555 self.savehist = no_op
1540 1556 self.reloadhist = no_op
1541 1557 self.set_completer = no_op
1542 1558 self.set_custom_completer = no_op
1543 1559 self.set_completer_frame = no_op
1544 1560 warn('Readline services not available or not loaded.')
1545 1561 else:
1546 1562 self.has_readline = True
1547 1563 self.readline = readline
1548 1564 sys.modules['readline'] = readline
1549 1565 import atexit
1550 1566 from IPython.core.completer import IPCompleter
1551 1567 self.Completer = IPCompleter(self,
1552 1568 self.user_ns,
1553 1569 self.user_global_ns,
1554 1570 self.readline_omit__names,
1555 1571 self.alias_manager.alias_table)
1556 1572 sdisp = self.strdispatchers.get('complete_command', StrDispatch())
1557 1573 self.strdispatchers['complete_command'] = sdisp
1558 1574 self.Completer.custom_completers = sdisp
1559 1575 # Platform-specific configuration
1560 1576 if os.name == 'nt':
1561 1577 self.readline_startup_hook = readline.set_pre_input_hook
1562 1578 else:
1563 1579 self.readline_startup_hook = readline.set_startup_hook
1564 1580
1565 1581 # Load user's initrc file (readline config)
1566 1582 # Or if libedit is used, load editrc.
1567 1583 inputrc_name = os.environ.get('INPUTRC')
1568 1584 if inputrc_name is None:
1569 1585 home_dir = get_home_dir()
1570 1586 if home_dir is not None:
1571 1587 inputrc_name = '.inputrc'
1572 1588 if readline.uses_libedit:
1573 1589 inputrc_name = '.editrc'
1574 1590 inputrc_name = os.path.join(home_dir, inputrc_name)
1575 1591 if os.path.isfile(inputrc_name):
1576 1592 try:
1577 1593 readline.read_init_file(inputrc_name)
1578 1594 except:
1579 1595 warn('Problems reading readline initialization file <%s>'
1580 1596 % inputrc_name)
1581 1597
1582 1598 # save this in sys so embedded copies can restore it properly
1583 1599 sys.ipcompleter = self.Completer.complete
1584 1600 self.set_completer()
1585 1601
1586 1602 # Configure readline according to user's prefs
1587 1603 # This is only done if GNU readline is being used. If libedit
1588 1604 # is being used (as on Leopard) the readline config is
1589 1605 # not run as the syntax for libedit is different.
1590 1606 if not readline.uses_libedit:
1591 1607 for rlcommand in self.readline_parse_and_bind:
1592 1608 #print "loading rl:",rlcommand # dbg
1593 1609 readline.parse_and_bind(rlcommand)
1594 1610
1595 1611 # Remove some chars from the delimiters list. If we encounter
1596 1612 # unicode chars, discard them.
1597 1613 delims = readline.get_completer_delims().encode("ascii", "ignore")
1598 1614 delims = delims.translate(string._idmap,
1599 1615 self.readline_remove_delims)
1600 1616 readline.set_completer_delims(delims)
1601 1617 # otherwise we end up with a monster history after a while:
1602 1618 readline.set_history_length(1000)
1603 1619 try:
1604 1620 #print '*** Reading readline history' # dbg
1605 1621 readline.read_history_file(self.histfile)
1606 1622 except IOError:
1607 1623 pass # It doesn't exist yet.
1608 1624
1609 1625 atexit.register(self.atexit_operations)
1610 1626 del atexit
1611 1627
1612 1628 # Configure auto-indent for all platforms
1613 1629 self.set_autoindent(self.autoindent)
1614 1630
1615 1631 def set_next_input(self, s):
1616 1632 """ Sets the 'default' input string for the next command line.
1617 1633
1618 1634 Requires readline.
1619 1635
1620 1636 Example:
1621 1637
1622 1638 [D:\ipython]|1> _ip.set_next_input("Hello Word")
1623 1639 [D:\ipython]|2> Hello Word_ # cursor is here
1624 1640 """
1625 1641
1626 1642 self.rl_next_input = s
1627 1643
1628 1644 def pre_readline(self):
1629 1645 """readline hook to be used at the start of each line.
1630 1646
1631 1647 Currently it handles auto-indent only."""
1632 1648
1633 1649 #debugx('self.indent_current_nsp','pre_readline:')
1634 1650
1635 1651 if self.rl_do_indent:
1636 1652 self.readline.insert_text(self._indent_current_str())
1637 1653 if self.rl_next_input is not None:
1638 1654 self.readline.insert_text(self.rl_next_input)
1639 1655 self.rl_next_input = None
1640 1656
1641 1657 def _indent_current_str(self):
1642 1658 """return the current level of indentation as a string"""
1643 1659 return self.indent_current_nsp * ' '
1644 1660
1645 1661 #-------------------------------------------------------------------------
1646 1662 # Things related to magics
1647 1663 #-------------------------------------------------------------------------
1648 1664
1649 1665 def init_magics(self):
1650 1666 # Set user colors (don't do it in the constructor above so that it
1651 1667 # doesn't crash if colors option is invalid)
1652 1668 self.magic_colors(self.colors)
1653 1669 # History was moved to a separate module
1654 1670 from . import history
1655 1671 history.init_ipython(self)
1656 1672
1657 1673 def magic(self,arg_s):
1658 1674 """Call a magic function by name.
1659 1675
1660 1676 Input: a string containing the name of the magic function to call and any
1661 1677 additional arguments to be passed to the magic.
1662 1678
1663 1679 magic('name -opt foo bar') is equivalent to typing at the ipython
1664 1680 prompt:
1665 1681
1666 1682 In[1]: %name -opt foo bar
1667 1683
1668 1684 To call a magic without arguments, simply use magic('name').
1669 1685
1670 1686 This provides a proper Python function to call IPython's magics in any
1671 1687 valid Python code you can type at the interpreter, including loops and
1672 1688 compound statements.
1673 1689 """
1674 1690 args = arg_s.split(' ',1)
1675 1691 magic_name = args[0]
1676 1692 magic_name = magic_name.lstrip(prefilter.ESC_MAGIC)
1677 1693
1678 1694 try:
1679 1695 magic_args = args[1]
1680 1696 except IndexError:
1681 1697 magic_args = ''
1682 1698 fn = getattr(self,'magic_'+magic_name,None)
1683 1699 if fn is None:
1684 1700 error("Magic function `%s` not found." % magic_name)
1685 1701 else:
1686 1702 magic_args = self.var_expand(magic_args,1)
1687 1703 with nested(self.builtin_trap,):
1688 1704 result = fn(magic_args)
1689 1705 return result
1690 1706
1691 1707 def define_magic(self, magicname, func):
1692 1708 """Expose own function as magic function for ipython
1693 1709
1694 1710 def foo_impl(self,parameter_s=''):
1695 1711 'My very own magic!. (Use docstrings, IPython reads them).'
1696 1712 print 'Magic function. Passed parameter is between < >:'
1697 1713 print '<%s>' % parameter_s
1698 1714 print 'The self object is:',self
1699 1715
1700 1716 self.define_magic('foo',foo_impl)
1701 1717 """
1702 1718
1703 1719 import new
1704 1720 im = new.instancemethod(func,self, self.__class__)
1705 1721 old = getattr(self, "magic_" + magicname, None)
1706 1722 setattr(self, "magic_" + magicname, im)
1707 1723 return old
1708 1724
1709 1725 #-------------------------------------------------------------------------
1710 1726 # Things related to macros
1711 1727 #-------------------------------------------------------------------------
1712 1728
1713 1729 def define_macro(self, name, themacro):
1714 1730 """Define a new macro
1715 1731
1716 1732 Parameters
1717 1733 ----------
1718 1734 name : str
1719 1735 The name of the macro.
1720 1736 themacro : str or Macro
1721 1737 The action to do upon invoking the macro. If a string, a new
1722 1738 Macro object is created by passing the string to it.
1723 1739 """
1724 1740
1725 1741 from IPython.core import macro
1726 1742
1727 1743 if isinstance(themacro, basestring):
1728 1744 themacro = macro.Macro(themacro)
1729 1745 if not isinstance(themacro, macro.Macro):
1730 1746 raise ValueError('A macro must be a string or a Macro instance.')
1731 1747 self.user_ns[name] = themacro
1732 1748
1733 1749 #-------------------------------------------------------------------------
1734 1750 # Things related to the running of system commands
1735 1751 #-------------------------------------------------------------------------
1736 1752
1737 1753 def system(self, cmd):
1738 1754 """Make a system call, using IPython."""
1739 1755 return self.hooks.shell_hook(self.var_expand(cmd, depth=2))
1740 1756
1741 1757 #-------------------------------------------------------------------------
1742 1758 # Things related to aliases
1743 1759 #-------------------------------------------------------------------------
1744 1760
1745 1761 def init_alias(self):
1746 self.alias_manager = AliasManager(self, config=self.config)
1762 self.alias_manager = AliasManager(shell=self, config=self.config)
1747 1763 self.ns_table['alias'] = self.alias_manager.alias_table,
1748 1764
1749 1765 #-------------------------------------------------------------------------
1766 # Things related to extensions and plugins
1767 #-------------------------------------------------------------------------
1768
1769 def init_extension_manager(self):
1770 self.extension_manager = ExtensionManager(shell=self, config=self.config)
1771
1772 def init_plugin_manager(self):
1773 self.plugin_manager = PluginManager(config=self.config)
1774
1775 #-------------------------------------------------------------------------
1750 1776 # Things related to the running of code
1751 1777 #-------------------------------------------------------------------------
1752 1778
1753 1779 def ex(self, cmd):
1754 1780 """Execute a normal python statement in user namespace."""
1755 1781 with nested(self.builtin_trap,):
1756 1782 exec cmd in self.user_global_ns, self.user_ns
1757 1783
1758 1784 def ev(self, expr):
1759 1785 """Evaluate python expression expr in user namespace.
1760 1786
1761 1787 Returns the result of evaluation
1762 1788 """
1763 1789 with nested(self.builtin_trap,):
1764 1790 return eval(expr, self.user_global_ns, self.user_ns)
1765 1791
1766 1792 def mainloop(self, display_banner=None):
1767 1793 """Start the mainloop.
1768 1794
1769 1795 If an optional banner argument is given, it will override the
1770 1796 internally created default banner.
1771 1797 """
1772 1798
1773 1799 with nested(self.builtin_trap, self.display_trap):
1774 1800
1775 1801 # if you run stuff with -c <cmd>, raw hist is not updated
1776 1802 # ensure that it's in sync
1777 1803 if len(self.input_hist) != len (self.input_hist_raw):
1778 1804 self.input_hist_raw = InputList(self.input_hist)
1779 1805
1780 1806 while 1:
1781 1807 try:
1782 1808 self.interact(display_banner=display_banner)
1783 1809 #self.interact_with_readline()
1784 1810 # XXX for testing of a readline-decoupled repl loop, call
1785 1811 # interact_with_readline above
1786 1812 break
1787 1813 except KeyboardInterrupt:
1788 1814 # this should not be necessary, but KeyboardInterrupt
1789 1815 # handling seems rather unpredictable...
1790 1816 self.write("\nKeyboardInterrupt in interact()\n")
1791 1817
1792 1818 def interact_prompt(self):
1793 1819 """ Print the prompt (in read-eval-print loop)
1794 1820
1795 1821 Provided for those who want to implement their own read-eval-print loop (e.g. GUIs), not
1796 1822 used in standard IPython flow.
1797 1823 """
1798 1824 if self.more:
1799 1825 try:
1800 1826 prompt = self.hooks.generate_prompt(True)
1801 1827 except:
1802 1828 self.showtraceback()
1803 1829 if self.autoindent:
1804 1830 self.rl_do_indent = True
1805 1831
1806 1832 else:
1807 1833 try:
1808 1834 prompt = self.hooks.generate_prompt(False)
1809 1835 except:
1810 1836 self.showtraceback()
1811 1837 self.write(prompt)
1812 1838
1813 1839 def interact_handle_input(self,line):
1814 1840 """ Handle the input line (in read-eval-print loop)
1815 1841
1816 1842 Provided for those who want to implement their own read-eval-print loop (e.g. GUIs), not
1817 1843 used in standard IPython flow.
1818 1844 """
1819 1845 if line.lstrip() == line:
1820 1846 self.shadowhist.add(line.strip())
1821 1847 lineout = self.prefilter_manager.prefilter_lines(line,self.more)
1822 1848
1823 1849 if line.strip():
1824 1850 if self.more:
1825 1851 self.input_hist_raw[-1] += '%s\n' % line
1826 1852 else:
1827 1853 self.input_hist_raw.append('%s\n' % line)
1828 1854
1829 1855
1830 1856 self.more = self.push_line(lineout)
1831 1857 if (self.SyntaxTB.last_syntax_error and
1832 1858 self.autoedit_syntax):
1833 1859 self.edit_syntax_error()
1834 1860
1835 1861 def interact_with_readline(self):
1836 1862 """ Demo of using interact_handle_input, interact_prompt
1837 1863
1838 1864 This is the main read-eval-print loop. If you need to implement your own (e.g. for GUI),
1839 1865 it should work like this.
1840 1866 """
1841 1867 self.readline_startup_hook(self.pre_readline)
1842 1868 while not self.exit_now:
1843 1869 self.interact_prompt()
1844 1870 if self.more:
1845 1871 self.rl_do_indent = True
1846 1872 else:
1847 1873 self.rl_do_indent = False
1848 1874 line = raw_input_original().decode(self.stdin_encoding)
1849 1875 self.interact_handle_input(line)
1850 1876
1851 1877 def interact(self, display_banner=None):
1852 1878 """Closely emulate the interactive Python console."""
1853 1879
1854 1880 # batch run -> do not interact
1855 1881 if self.exit_now:
1856 1882 return
1857 1883
1858 1884 if display_banner is None:
1859 1885 display_banner = self.display_banner
1860 1886 if display_banner:
1861 1887 self.show_banner()
1862 1888
1863 1889 more = 0
1864 1890
1865 1891 # Mark activity in the builtins
1866 1892 __builtin__.__dict__['__IPYTHON__active'] += 1
1867 1893
1868 1894 if self.has_readline:
1869 1895 self.readline_startup_hook(self.pre_readline)
1870 1896 # exit_now is set by a call to %Exit or %Quit, through the
1871 1897 # ask_exit callback.
1872 1898
1873 1899 while not self.exit_now:
1874 1900 self.hooks.pre_prompt_hook()
1875 1901 if more:
1876 1902 try:
1877 1903 prompt = self.hooks.generate_prompt(True)
1878 1904 except:
1879 1905 self.showtraceback()
1880 1906 if self.autoindent:
1881 1907 self.rl_do_indent = True
1882 1908
1883 1909 else:
1884 1910 try:
1885 1911 prompt = self.hooks.generate_prompt(False)
1886 1912 except:
1887 1913 self.showtraceback()
1888 1914 try:
1889 1915 line = self.raw_input(prompt, more)
1890 1916 if self.exit_now:
1891 1917 # quick exit on sys.std[in|out] close
1892 1918 break
1893 1919 if self.autoindent:
1894 1920 self.rl_do_indent = False
1895 1921
1896 1922 except KeyboardInterrupt:
1897 1923 #double-guard against keyboardinterrupts during kbdint handling
1898 1924 try:
1899 1925 self.write('\nKeyboardInterrupt\n')
1900 1926 self.resetbuffer()
1901 1927 # keep cache in sync with the prompt counter:
1902 1928 self.outputcache.prompt_count -= 1
1903 1929
1904 1930 if self.autoindent:
1905 1931 self.indent_current_nsp = 0
1906 1932 more = 0
1907 1933 except KeyboardInterrupt:
1908 1934 pass
1909 1935 except EOFError:
1910 1936 if self.autoindent:
1911 1937 self.rl_do_indent = False
1912 1938 if self.has_readline:
1913 1939 self.readline_startup_hook(None)
1914 1940 self.write('\n')
1915 1941 self.exit()
1916 1942 except bdb.BdbQuit:
1917 1943 warn('The Python debugger has exited with a BdbQuit exception.\n'
1918 1944 'Because of how pdb handles the stack, it is impossible\n'
1919 1945 'for IPython to properly format this particular exception.\n'
1920 1946 'IPython will resume normal operation.')
1921 1947 except:
1922 1948 # exceptions here are VERY RARE, but they can be triggered
1923 1949 # asynchronously by signal handlers, for example.
1924 1950 self.showtraceback()
1925 1951 else:
1926 1952 more = self.push_line(line)
1927 1953 if (self.SyntaxTB.last_syntax_error and
1928 1954 self.autoedit_syntax):
1929 1955 self.edit_syntax_error()
1930 1956
1931 1957 # We are off again...
1932 1958 __builtin__.__dict__['__IPYTHON__active'] -= 1
1933 1959
1934 1960 # Turn off the exit flag, so the mainloop can be restarted if desired
1935 1961 self.exit_now = False
1936 1962
1937 1963 def safe_execfile(self, fname, *where, **kw):
1938 1964 """A safe version of the builtin execfile().
1939 1965
1940 1966 This version will never throw an exception, but instead print
1941 1967 helpful error messages to the screen. This only works on pure
1942 1968 Python files with the .py extension.
1943 1969
1944 1970 Parameters
1945 1971 ----------
1946 1972 fname : string
1947 1973 The name of the file to be executed.
1948 1974 where : tuple
1949 1975 One or two namespaces, passed to execfile() as (globals,locals).
1950 1976 If only one is given, it is passed as both.
1951 1977 exit_ignore : bool (False)
1952 1978 If True, then silence SystemExit for non-zero status (it is always
1953 1979 silenced for zero status, as it is so common).
1954 1980 """
1955 1981 kw.setdefault('exit_ignore', False)
1956 1982
1957 1983 fname = os.path.abspath(os.path.expanduser(fname))
1958 1984
1959 1985 # Make sure we have a .py file
1960 1986 if not fname.endswith('.py'):
1961 1987 warn('File must end with .py to be run using execfile: <%s>' % fname)
1962 1988
1963 1989 # Make sure we can open the file
1964 1990 try:
1965 1991 with open(fname) as thefile:
1966 1992 pass
1967 1993 except:
1968 1994 warn('Could not open file <%s> for safe execution.' % fname)
1969 1995 return
1970 1996
1971 1997 # Find things also in current directory. This is needed to mimic the
1972 1998 # behavior of running a script from the system command line, where
1973 1999 # Python inserts the script's directory into sys.path
1974 2000 dname = os.path.dirname(fname)
1975 2001
1976 2002 with prepended_to_syspath(dname):
1977 2003 try:
1978 2004 execfile(fname,*where)
1979 2005 except SystemExit, status:
1980 2006 # If the call was made with 0 or None exit status (sys.exit(0)
1981 2007 # or sys.exit() ), don't bother showing a traceback, as both of
1982 2008 # these are considered normal by the OS:
1983 2009 # > python -c'import sys;sys.exit(0)'; echo $?
1984 2010 # 0
1985 2011 # > python -c'import sys;sys.exit()'; echo $?
1986 2012 # 0
1987 2013 # For other exit status, we show the exception unless
1988 2014 # explicitly silenced, but only in short form.
1989 2015 if status.code not in (0, None) and not kw['exit_ignore']:
1990 2016 self.showtraceback(exception_only=True)
1991 2017 except:
1992 2018 self.showtraceback()
1993 2019
1994 2020 def safe_execfile_ipy(self, fname):
1995 2021 """Like safe_execfile, but for .ipy files with IPython syntax.
1996 2022
1997 2023 Parameters
1998 2024 ----------
1999 2025 fname : str
2000 2026 The name of the file to execute. The filename must have a
2001 2027 .ipy extension.
2002 2028 """
2003 2029 fname = os.path.abspath(os.path.expanduser(fname))
2004 2030
2005 2031 # Make sure we have a .py file
2006 2032 if not fname.endswith('.ipy'):
2007 2033 warn('File must end with .py to be run using execfile: <%s>' % fname)
2008 2034
2009 2035 # Make sure we can open the file
2010 2036 try:
2011 2037 with open(fname) as thefile:
2012 2038 pass
2013 2039 except:
2014 2040 warn('Could not open file <%s> for safe execution.' % fname)
2015 2041 return
2016 2042
2017 2043 # Find things also in current directory. This is needed to mimic the
2018 2044 # behavior of running a script from the system command line, where
2019 2045 # Python inserts the script's directory into sys.path
2020 2046 dname = os.path.dirname(fname)
2021 2047
2022 2048 with prepended_to_syspath(dname):
2023 2049 try:
2024 2050 with open(fname) as thefile:
2025 2051 script = thefile.read()
2026 2052 # self.runlines currently captures all exceptions
2027 2053 # raise in user code. It would be nice if there were
2028 2054 # versions of runlines, execfile that did raise, so
2029 2055 # we could catch the errors.
2030 2056 self.runlines(script, clean=True)
2031 2057 except:
2032 2058 self.showtraceback()
2033 2059 warn('Unknown failure executing file: <%s>' % fname)
2034 2060
2035 2061 def _is_secondary_block_start(self, s):
2036 2062 if not s.endswith(':'):
2037 2063 return False
2038 2064 if (s.startswith('elif') or
2039 2065 s.startswith('else') or
2040 2066 s.startswith('except') or
2041 2067 s.startswith('finally')):
2042 2068 return True
2043 2069
2044 2070 def cleanup_ipy_script(self, script):
2045 2071 """Make a script safe for self.runlines()
2046 2072
2047 2073 Currently, IPython is lines based, with blocks being detected by
2048 2074 empty lines. This is a problem for block based scripts that may
2049 2075 not have empty lines after blocks. This script adds those empty
2050 2076 lines to make scripts safe for running in the current line based
2051 2077 IPython.
2052 2078 """
2053 2079 res = []
2054 2080 lines = script.splitlines()
2055 2081 level = 0
2056 2082
2057 2083 for l in lines:
2058 2084 lstripped = l.lstrip()
2059 2085 stripped = l.strip()
2060 2086 if not stripped:
2061 2087 continue
2062 2088 newlevel = len(l) - len(lstripped)
2063 2089 if level > 0 and newlevel == 0 and \
2064 2090 not self._is_secondary_block_start(stripped):
2065 2091 # add empty line
2066 2092 res.append('')
2067 2093 res.append(l)
2068 2094 level = newlevel
2069 2095
2070 2096 return '\n'.join(res) + '\n'
2071 2097
2072 2098 def runlines(self, lines, clean=False):
2073 2099 """Run a string of one or more lines of source.
2074 2100
2075 2101 This method is capable of running a string containing multiple source
2076 2102 lines, as if they had been entered at the IPython prompt. Since it
2077 2103 exposes IPython's processing machinery, the given strings can contain
2078 2104 magic calls (%magic), special shell access (!cmd), etc.
2079 2105 """
2080 2106
2081 2107 if isinstance(lines, (list, tuple)):
2082 2108 lines = '\n'.join(lines)
2083 2109
2084 2110 if clean:
2085 2111 lines = self.cleanup_ipy_script(lines)
2086 2112
2087 2113 # We must start with a clean buffer, in case this is run from an
2088 2114 # interactive IPython session (via a magic, for example).
2089 2115 self.resetbuffer()
2090 2116 lines = lines.splitlines()
2091 2117 more = 0
2092 2118
2093 2119 with nested(self.builtin_trap, self.display_trap):
2094 2120 for line in lines:
2095 2121 # skip blank lines so we don't mess up the prompt counter, but do
2096 2122 # NOT skip even a blank line if we are in a code block (more is
2097 2123 # true)
2098 2124
2099 2125 if line or more:
2100 2126 # push to raw history, so hist line numbers stay in sync
2101 2127 self.input_hist_raw.append("# " + line + "\n")
2102 2128 prefiltered = self.prefilter_manager.prefilter_lines(line,more)
2103 2129 more = self.push_line(prefiltered)
2104 2130 # IPython's runsource returns None if there was an error
2105 2131 # compiling the code. This allows us to stop processing right
2106 2132 # away, so the user gets the error message at the right place.
2107 2133 if more is None:
2108 2134 break
2109 2135 else:
2110 2136 self.input_hist_raw.append("\n")
2111 2137 # final newline in case the input didn't have it, so that the code
2112 2138 # actually does get executed
2113 2139 if more:
2114 2140 self.push_line('\n')
2115 2141
2116 2142 def runsource(self, source, filename='<input>', symbol='single'):
2117 2143 """Compile and run some source in the interpreter.
2118 2144
2119 2145 Arguments are as for compile_command().
2120 2146
2121 2147 One several things can happen:
2122 2148
2123 2149 1) The input is incorrect; compile_command() raised an
2124 2150 exception (SyntaxError or OverflowError). A syntax traceback
2125 2151 will be printed by calling the showsyntaxerror() method.
2126 2152
2127 2153 2) The input is incomplete, and more input is required;
2128 2154 compile_command() returned None. Nothing happens.
2129 2155
2130 2156 3) The input is complete; compile_command() returned a code
2131 2157 object. The code is executed by calling self.runcode() (which
2132 2158 also handles run-time exceptions, except for SystemExit).
2133 2159
2134 2160 The return value is:
2135 2161
2136 2162 - True in case 2
2137 2163
2138 2164 - False in the other cases, unless an exception is raised, where
2139 2165 None is returned instead. This can be used by external callers to
2140 2166 know whether to continue feeding input or not.
2141 2167
2142 2168 The return value can be used to decide whether to use sys.ps1 or
2143 2169 sys.ps2 to prompt the next line."""
2144 2170
2145 2171 # if the source code has leading blanks, add 'if 1:\n' to it
2146 2172 # this allows execution of indented pasted code. It is tempting
2147 2173 # to add '\n' at the end of source to run commands like ' a=1'
2148 2174 # directly, but this fails for more complicated scenarios
2149 2175 source=source.encode(self.stdin_encoding)
2150 2176 if source[:1] in [' ', '\t']:
2151 2177 source = 'if 1:\n%s' % source
2152 2178
2153 2179 try:
2154 2180 code = self.compile(source,filename,symbol)
2155 2181 except (OverflowError, SyntaxError, ValueError, TypeError, MemoryError):
2156 2182 # Case 1
2157 2183 self.showsyntaxerror(filename)
2158 2184 return None
2159 2185
2160 2186 if code is None:
2161 2187 # Case 2
2162 2188 return True
2163 2189
2164 2190 # Case 3
2165 2191 # We store the code object so that threaded shells and
2166 2192 # custom exception handlers can access all this info if needed.
2167 2193 # The source corresponding to this can be obtained from the
2168 2194 # buffer attribute as '\n'.join(self.buffer).
2169 2195 self.code_to_run = code
2170 2196 # now actually execute the code object
2171 2197 if self.runcode(code) == 0:
2172 2198 return False
2173 2199 else:
2174 2200 return None
2175 2201
2176 2202 def runcode(self,code_obj):
2177 2203 """Execute a code object.
2178 2204
2179 2205 When an exception occurs, self.showtraceback() is called to display a
2180 2206 traceback.
2181 2207
2182 2208 Return value: a flag indicating whether the code to be run completed
2183 2209 successfully:
2184 2210
2185 2211 - 0: successful execution.
2186 2212 - 1: an error occurred.
2187 2213 """
2188 2214
2189 2215 # Set our own excepthook in case the user code tries to call it
2190 2216 # directly, so that the IPython crash handler doesn't get triggered
2191 2217 old_excepthook,sys.excepthook = sys.excepthook, self.excepthook
2192 2218
2193 2219 # we save the original sys.excepthook in the instance, in case config
2194 2220 # code (such as magics) needs access to it.
2195 2221 self.sys_excepthook = old_excepthook
2196 2222 outflag = 1 # happens in more places, so it's easier as default
2197 2223 try:
2198 2224 try:
2199 2225 self.hooks.pre_runcode_hook()
2200 2226 exec code_obj in self.user_global_ns, self.user_ns
2201 2227 finally:
2202 2228 # Reset our crash handler in place
2203 2229 sys.excepthook = old_excepthook
2204 2230 except SystemExit:
2205 2231 self.resetbuffer()
2206 2232 self.showtraceback(exception_only=True)
2207 2233 warn("To exit: use any of 'exit', 'quit', %Exit or Ctrl-D.", level=1)
2208 2234 except self.custom_exceptions:
2209 2235 etype,value,tb = sys.exc_info()
2210 2236 self.CustomTB(etype,value,tb)
2211 2237 except:
2212 2238 self.showtraceback()
2213 2239 else:
2214 2240 outflag = 0
2215 2241 if softspace(sys.stdout, 0):
2216 2242 print
2217 2243 # Flush out code object which has been run (and source)
2218 2244 self.code_to_run = None
2219 2245 return outflag
2220 2246
2221 2247 def push_line(self, line):
2222 2248 """Push a line to the interpreter.
2223 2249
2224 2250 The line should not have a trailing newline; it may have
2225 2251 internal newlines. The line is appended to a buffer and the
2226 2252 interpreter's runsource() method is called with the
2227 2253 concatenated contents of the buffer as source. If this
2228 2254 indicates that the command was executed or invalid, the buffer
2229 2255 is reset; otherwise, the command is incomplete, and the buffer
2230 2256 is left as it was after the line was appended. The return
2231 2257 value is 1 if more input is required, 0 if the line was dealt
2232 2258 with in some way (this is the same as runsource()).
2233 2259 """
2234 2260
2235 2261 # autoindent management should be done here, and not in the
2236 2262 # interactive loop, since that one is only seen by keyboard input. We
2237 2263 # need this done correctly even for code run via runlines (which uses
2238 2264 # push).
2239 2265
2240 2266 #print 'push line: <%s>' % line # dbg
2241 2267 for subline in line.splitlines():
2242 2268 self._autoindent_update(subline)
2243 2269 self.buffer.append(line)
2244 2270 more = self.runsource('\n'.join(self.buffer), self.filename)
2245 2271 if not more:
2246 2272 self.resetbuffer()
2247 2273 return more
2248 2274
2249 2275 def _autoindent_update(self,line):
2250 2276 """Keep track of the indent level."""
2251 2277
2252 2278 #debugx('line')
2253 2279 #debugx('self.indent_current_nsp')
2254 2280 if self.autoindent:
2255 2281 if line:
2256 2282 inisp = num_ini_spaces(line)
2257 2283 if inisp < self.indent_current_nsp:
2258 2284 self.indent_current_nsp = inisp
2259 2285
2260 2286 if line[-1] == ':':
2261 2287 self.indent_current_nsp += 4
2262 2288 elif dedent_re.match(line):
2263 2289 self.indent_current_nsp -= 4
2264 2290 else:
2265 2291 self.indent_current_nsp = 0
2266 2292
2267 2293 def resetbuffer(self):
2268 2294 """Reset the input buffer."""
2269 2295 self.buffer[:] = []
2270 2296
2271 2297 def raw_input(self,prompt='',continue_prompt=False):
2272 2298 """Write a prompt and read a line.
2273 2299
2274 2300 The returned line does not include the trailing newline.
2275 2301 When the user enters the EOF key sequence, EOFError is raised.
2276 2302
2277 2303 Optional inputs:
2278 2304
2279 2305 - prompt(''): a string to be printed to prompt the user.
2280 2306
2281 2307 - continue_prompt(False): whether this line is the first one or a
2282 2308 continuation in a sequence of inputs.
2283 2309 """
2284 2310 # growl.notify("raw_input: ", "prompt = %r\ncontinue_prompt = %s" % (prompt, continue_prompt))
2285 2311
2286 2312 # Code run by the user may have modified the readline completer state.
2287 2313 # We must ensure that our completer is back in place.
2288 2314
2289 2315 if self.has_readline:
2290 2316 self.set_completer()
2291 2317
2292 2318 try:
2293 2319 line = raw_input_original(prompt).decode(self.stdin_encoding)
2294 2320 except ValueError:
2295 2321 warn("\n********\nYou or a %run:ed script called sys.stdin.close()"
2296 2322 " or sys.stdout.close()!\nExiting IPython!")
2297 2323 self.ask_exit()
2298 2324 return ""
2299 2325
2300 2326 # Try to be reasonably smart about not re-indenting pasted input more
2301 2327 # than necessary. We do this by trimming out the auto-indent initial
2302 2328 # spaces, if the user's actual input started itself with whitespace.
2303 2329 #debugx('self.buffer[-1]')
2304 2330
2305 2331 if self.autoindent:
2306 2332 if num_ini_spaces(line) > self.indent_current_nsp:
2307 2333 line = line[self.indent_current_nsp:]
2308 2334 self.indent_current_nsp = 0
2309 2335
2310 2336 # store the unfiltered input before the user has any chance to modify
2311 2337 # it.
2312 2338 if line.strip():
2313 2339 if continue_prompt:
2314 2340 self.input_hist_raw[-1] += '%s\n' % line
2315 2341 if self.has_readline and self.readline_use:
2316 2342 try:
2317 2343 histlen = self.readline.get_current_history_length()
2318 2344 if histlen > 1:
2319 2345 newhist = self.input_hist_raw[-1].rstrip()
2320 2346 self.readline.remove_history_item(histlen-1)
2321 2347 self.readline.replace_history_item(histlen-2,
2322 2348 newhist.encode(self.stdin_encoding))
2323 2349 except AttributeError:
2324 2350 pass # re{move,place}_history_item are new in 2.4.
2325 2351 else:
2326 2352 self.input_hist_raw.append('%s\n' % line)
2327 2353 # only entries starting at first column go to shadow history
2328 2354 if line.lstrip() == line:
2329 2355 self.shadowhist.add(line.strip())
2330 2356 elif not continue_prompt:
2331 2357 self.input_hist_raw.append('\n')
2332 2358 try:
2333 2359 lineout = self.prefilter_manager.prefilter_lines(line,continue_prompt)
2334 2360 except:
2335 2361 # blanket except, in case a user-defined prefilter crashes, so it
2336 2362 # can't take all of ipython with it.
2337 2363 self.showtraceback()
2338 2364 return ''
2339 2365 else:
2340 2366 return lineout
2341 2367
2342 2368 #-------------------------------------------------------------------------
2343 # Working with components
2344 #-------------------------------------------------------------------------
2345
2346 def get_component(self, name=None, klass=None):
2347 """Fetch a component by name and klass in my tree."""
2348 c = Component.get_instances(root=self, name=name, klass=klass)
2349 if len(c) == 0:
2350 return None
2351 if len(c) == 1:
2352 return c[0]
2353 else:
2354 return c
2355
2356 #-------------------------------------------------------------------------
2357 # IPython extensions
2358 #-------------------------------------------------------------------------
2359
2360 def load_extension(self, module_str):
2361 """Load an IPython extension by its module name.
2362
2363 An IPython extension is an importable Python module that has
2364 a function with the signature::
2365
2366 def load_ipython_extension(ipython):
2367 # Do things with ipython
2368
2369 This function is called after your extension is imported and the
2370 currently active :class:`InteractiveShell` instance is passed as
2371 the only argument. You can do anything you want with IPython at
2372 that point, including defining new magic and aliases, adding new
2373 components, etc.
2374
2375 The :func:`load_ipython_extension` will be called again is you
2376 load or reload the extension again. It is up to the extension
2377 author to add code to manage that.
2378
2379 You can put your extension modules anywhere you want, as long as
2380 they can be imported by Python's standard import mechanism. However,
2381 to make it easy to write extensions, you can also put your extensions
2382 in ``os.path.join(self.ipython_dir, 'extensions')``. This directory
2383 is added to ``sys.path`` automatically.
2384
2385 If :func:`load_ipython_extension` returns anything, this function
2386 will return that object.
2387 """
2388 from IPython.utils.syspathcontext import prepended_to_syspath
2389
2390 if module_str not in sys.modules:
2391 with prepended_to_syspath(self.ipython_extension_dir):
2392 __import__(module_str)
2393 mod = sys.modules[module_str]
2394 return self._call_load_ipython_extension(mod)
2395
2396 def unload_extension(self, module_str):
2397 """Unload an IPython extension by its module name.
2398
2399 This function looks up the extension's name in ``sys.modules`` and
2400 simply calls ``mod.unload_ipython_extension(self)``.
2401 """
2402 if module_str in sys.modules:
2403 mod = sys.modules[module_str]
2404 self._call_unload_ipython_extension(mod)
2405
2406 def reload_extension(self, module_str):
2407 """Reload an IPython extension by calling reload.
2408
2409 If the module has not been loaded before,
2410 :meth:`InteractiveShell.load_extension` is called. Otherwise
2411 :func:`reload` is called and then the :func:`load_ipython_extension`
2412 function of the module, if it exists is called.
2413 """
2414 from IPython.utils.syspathcontext import prepended_to_syspath
2415
2416 with prepended_to_syspath(self.ipython_extension_dir):
2417 if module_str in sys.modules:
2418 mod = sys.modules[module_str]
2419 reload(mod)
2420 self._call_load_ipython_extension(mod)
2421 else:
2422 self.load_extension(module_str)
2423
2424 def _call_load_ipython_extension(self, mod):
2425 if hasattr(mod, 'load_ipython_extension'):
2426 return mod.load_ipython_extension(self)
2427
2428 def _call_unload_ipython_extension(self, mod):
2429 if hasattr(mod, 'unload_ipython_extension'):
2430 return mod.unload_ipython_extension(self)
2431
2432 #-------------------------------------------------------------------------
2433 2369 # Things related to the prefilter
2434 2370 #-------------------------------------------------------------------------
2435 2371
2436 2372 def init_prefilter(self):
2437 self.prefilter_manager = PrefilterManager(self, config=self.config)
2373 self.prefilter_manager = PrefilterManager(shell=self, config=self.config)
2438 2374 # Ultimately this will be refactored in the new interpreter code, but
2439 2375 # for now, we should expose the main prefilter method (there's legacy
2440 2376 # code out there that may rely on this).
2441 2377 self.prefilter = self.prefilter_manager.prefilter_lines
2442 2378
2443 2379 #-------------------------------------------------------------------------
2444 2380 # Utilities
2445 2381 #-------------------------------------------------------------------------
2446 2382
2447 2383 def getoutput(self, cmd):
2448 2384 return getoutput(self.var_expand(cmd,depth=2),
2449 2385 header=self.system_header,
2450 2386 verbose=self.system_verbose)
2451 2387
2452 2388 def getoutputerror(self, cmd):
2453 2389 return getoutputerror(self.var_expand(cmd,depth=2),
2454 2390 header=self.system_header,
2455 2391 verbose=self.system_verbose)
2456 2392
2457 2393 def var_expand(self,cmd,depth=0):
2458 2394 """Expand python variables in a string.
2459 2395
2460 2396 The depth argument indicates how many frames above the caller should
2461 2397 be walked to look for the local namespace where to expand variables.
2462 2398
2463 2399 The global namespace for expansion is always the user's interactive
2464 2400 namespace.
2465 2401 """
2466 2402
2467 2403 return str(ItplNS(cmd,
2468 2404 self.user_ns, # globals
2469 2405 # Skip our own frame in searching for locals:
2470 2406 sys._getframe(depth+1).f_locals # locals
2471 2407 ))
2472 2408
2473 2409 def mktempfile(self,data=None):
2474 2410 """Make a new tempfile and return its filename.
2475 2411
2476 2412 This makes a call to tempfile.mktemp, but it registers the created
2477 2413 filename internally so ipython cleans it up at exit time.
2478 2414
2479 2415 Optional inputs:
2480 2416
2481 2417 - data(None): if data is given, it gets written out to the temp file
2482 2418 immediately, and the file is closed again."""
2483 2419
2484 2420 filename = tempfile.mktemp('.py','ipython_edit_')
2485 2421 self.tempfiles.append(filename)
2486 2422
2487 2423 if data:
2488 2424 tmp_file = open(filename,'w')
2489 2425 tmp_file.write(data)
2490 2426 tmp_file.close()
2491 2427 return filename
2492 2428
2493 2429 def write(self,data):
2494 2430 """Write a string to the default output"""
2495 2431 Term.cout.write(data)
2496 2432
2497 2433 def write_err(self,data):
2498 2434 """Write a string to the default error output"""
2499 2435 Term.cerr.write(data)
2500 2436
2501 2437 def ask_yes_no(self,prompt,default=True):
2502 2438 if self.quiet:
2503 2439 return True
2504 2440 return ask_yes_no(prompt,default)
2505 2441
2506 2442 #-------------------------------------------------------------------------
2507 2443 # Things related to GUI support and pylab
2508 2444 #-------------------------------------------------------------------------
2509 2445
2510 2446 def enable_pylab(self, gui=None):
2511 2447 """Activate pylab support at runtime.
2512 2448
2513 2449 This turns on support for matplotlib, preloads into the interactive
2514 2450 namespace all of numpy and pylab, and configures IPython to correcdtly
2515 2451 interact with the GUI event loop. The GUI backend to be used can be
2516 2452 optionally selected with the optional :param:`gui` argument.
2517 2453
2518 2454 Parameters
2519 2455 ----------
2520 2456 gui : optional, string
2521 2457
2522 2458 If given, dictates the choice of matplotlib GUI backend to use
2523 2459 (should be one of IPython's supported backends, 'tk', 'qt', 'wx' or
2524 2460 'gtk'), otherwise we use the default chosen by matplotlib (as
2525 2461 dictated by the matplotlib build-time options plus the user's
2526 2462 matplotlibrc configuration file).
2527 2463 """
2528 2464 # We want to prevent the loading of pylab to pollute the user's
2529 2465 # namespace as shown by the %who* magics, so we execute the activation
2530 2466 # code in an empty namespace, and we update *both* user_ns and
2531 2467 # user_ns_hidden with this information.
2532 2468 ns = {}
2533 2469 gui = pylab_activate(ns, gui)
2534 2470 self.user_ns.update(ns)
2535 2471 self.user_ns_hidden.update(ns)
2536 2472 # Now we must activate the gui pylab wants to use, and fix %run to take
2537 2473 # plot updates into account
2538 2474 enable_gui(gui)
2539 2475 self.magic_run = self._pylab_magic_run
2540 2476
2541 2477 #-------------------------------------------------------------------------
2542 2478 # Things related to IPython exiting
2543 2479 #-------------------------------------------------------------------------
2544 2480
2545 2481 def ask_exit(self):
2546 2482 """ Ask the shell to exit. Can be overiden and used as a callback. """
2547 2483 self.exit_now = True
2548 2484
2549 2485 def exit(self):
2550 2486 """Handle interactive exit.
2551 2487
2552 2488 This method calls the ask_exit callback."""
2553 2489 if self.confirm_exit:
2554 2490 if self.ask_yes_no('Do you really want to exit ([y]/n)?','y'):
2555 2491 self.ask_exit()
2556 2492 else:
2557 2493 self.ask_exit()
2558 2494
2559 2495 def atexit_operations(self):
2560 2496 """This will be executed at the time of exit.
2561 2497
2562 2498 Saving of persistent data should be performed here.
2563 2499 """
2564 2500 self.savehist()
2565 2501
2566 2502 # Cleanup all tempfiles left around
2567 2503 for tfile in self.tempfiles:
2568 2504 try:
2569 2505 os.unlink(tfile)
2570 2506 except OSError:
2571 2507 pass
2572 2508
2573 2509 # Clear all user namespaces to release all references cleanly.
2574 2510 self.reset()
2575 2511
2576 2512 # Run user hooks
2577 2513 self.hooks.shutdown_hook()
2578 2514
2579 2515 def cleanup(self):
2580 2516 self.restore_sys_module_state()
2581 2517
2582 2518
2519 class InteractiveShellABC(object):
2520 """An abstract base class for InteractiveShell."""
2521 __metaclass__ = abc.ABCMeta
2522
2523 InteractiveShellABC.register(InteractiveShell)
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
@@ -1,1050 +1,1022 b''
1 1 #!/usr/bin/env python
2 2 # encoding: utf-8
3 3 """
4 4 Prefiltering components.
5 5
6 6 Prefilters transform user input before it is exec'd by Python. These
7 7 transforms are used to implement additional syntax such as !ls and %magic.
8 8
9 9 Authors:
10 10
11 11 * Brian Granger
12 12 * Fernando Perez
13 13 * Dan Milstein
14 14 * Ville Vainio
15 15 """
16 16
17 17 #-----------------------------------------------------------------------------
18 18 # Copyright (C) 2008-2009 The IPython Development Team
19 19 #
20 20 # Distributed under the terms of the BSD License. The full license is in
21 21 # the file COPYING, distributed as part of this software.
22 22 #-----------------------------------------------------------------------------
23 23
24 24 #-----------------------------------------------------------------------------
25 25 # Imports
26 26 #-----------------------------------------------------------------------------
27 27
28 28 import __builtin__
29 29 import codeop
30 30 import re
31 31
32 32 from IPython.core.alias import AliasManager
33 33 from IPython.core.autocall import IPyAutocall
34 from IPython.core.component import Component
34 from IPython.config.configurable import Configurable
35 35 from IPython.core.splitinput import split_user_input
36 36 from IPython.core.page import page
37 37
38 from IPython.utils.traitlets import List, Int, Any, Str, CBool, Bool
38 from IPython.utils.traitlets import List, Int, Any, Str, CBool, Bool, Instance
39 39 from IPython.utils.io import Term
40 40 from IPython.utils.text import make_quoted_expr
41 41 from IPython.utils.autoattr import auto_attr
42 42
43 43 #-----------------------------------------------------------------------------
44 44 # Global utilities, errors and constants
45 45 #-----------------------------------------------------------------------------
46 46
47 47 # Warning, these cannot be changed unless various regular expressions
48 48 # are updated in a number of places. Not great, but at least we told you.
49 49 ESC_SHELL = '!'
50 50 ESC_SH_CAP = '!!'
51 51 ESC_HELP = '?'
52 52 ESC_MAGIC = '%'
53 53 ESC_QUOTE = ','
54 54 ESC_QUOTE2 = ';'
55 55 ESC_PAREN = '/'
56 56
57 57
58 58 class PrefilterError(Exception):
59 59 pass
60 60
61 61
62 62 # RegExp to identify potential function names
63 63 re_fun_name = re.compile(r'[a-zA-Z_]([a-zA-Z0-9_.]*) *$')
64 64
65 65 # RegExp to exclude strings with this start from autocalling. In
66 66 # particular, all binary operators should be excluded, so that if foo is
67 67 # callable, foo OP bar doesn't become foo(OP bar), which is invalid. The
68 68 # characters '!=()' don't need to be checked for, as the checkPythonChars
69 69 # routine explicitely does so, to catch direct calls and rebindings of
70 70 # existing names.
71 71
72 72 # Warning: the '-' HAS TO BE AT THE END of the first group, otherwise
73 73 # it affects the rest of the group in square brackets.
74 74 re_exclude_auto = re.compile(r'^[,&^\|\*/\+-]'
75 75 r'|^is |^not |^in |^and |^or ')
76 76
77 77 # try to catch also methods for stuff in lists/tuples/dicts: off
78 78 # (experimental). For this to work, the line_split regexp would need
79 79 # to be modified so it wouldn't break things at '['. That line is
80 80 # nasty enough that I shouldn't change it until I can test it _well_.
81 81 #self.re_fun_name = re.compile (r'[a-zA-Z_]([a-zA-Z0-9_.\[\]]*) ?$')
82 82
83 83
84 84 # Handler Check Utilities
85 85 def is_shadowed(identifier, ip):
86 86 """Is the given identifier defined in one of the namespaces which shadow
87 87 the alias and magic namespaces? Note that an identifier is different
88 88 than ifun, because it can not contain a '.' character."""
89 89 # This is much safer than calling ofind, which can change state
90 90 return (identifier in ip.user_ns \
91 91 or identifier in ip.internal_ns \
92 92 or identifier in ip.ns_table['builtin'])
93 93
94 94
95 95 #-----------------------------------------------------------------------------
96 96 # The LineInfo class used throughout
97 97 #-----------------------------------------------------------------------------
98 98
99 99
100 100 class LineInfo(object):
101 101 """A single line of input and associated info.
102 102
103 103 Includes the following as properties:
104 104
105 105 line
106 106 The original, raw line
107 107
108 108 continue_prompt
109 109 Is this line a continuation in a sequence of multiline input?
110 110
111 111 pre
112 112 The initial esc character or whitespace.
113 113
114 114 pre_char
115 115 The escape character(s) in pre or the empty string if there isn't one.
116 116 Note that '!!' is a possible value for pre_char. Otherwise it will
117 117 always be a single character.
118 118
119 119 pre_whitespace
120 120 The leading whitespace from pre if it exists. If there is a pre_char,
121 121 this is just ''.
122 122
123 123 ifun
124 124 The 'function part', which is basically the maximal initial sequence
125 125 of valid python identifiers and the '.' character. This is what is
126 126 checked for alias and magic transformations, used for auto-calling,
127 127 etc.
128 128
129 129 the_rest
130 130 Everything else on the line.
131 131 """
132 132 def __init__(self, line, continue_prompt):
133 133 self.line = line
134 134 self.continue_prompt = continue_prompt
135 135 self.pre, self.ifun, self.the_rest = split_user_input(line)
136 136
137 137 self.pre_char = self.pre.strip()
138 138 if self.pre_char:
139 139 self.pre_whitespace = '' # No whitespace allowd before esc chars
140 140 else:
141 141 self.pre_whitespace = self.pre
142 142
143 143 self._oinfo = None
144 144
145 145 def ofind(self, ip):
146 146 """Do a full, attribute-walking lookup of the ifun in the various
147 147 namespaces for the given IPython InteractiveShell instance.
148 148
149 149 Return a dict with keys: found,obj,ospace,ismagic
150 150
151 151 Note: can cause state changes because of calling getattr, but should
152 152 only be run if autocall is on and if the line hasn't matched any
153 153 other, less dangerous handlers.
154 154
155 155 Does cache the results of the call, so can be called multiple times
156 156 without worrying about *further* damaging state.
157 157 """
158 158 if not self._oinfo:
159 159 # ip.shell._ofind is actually on the Magic class!
160 160 self._oinfo = ip.shell._ofind(self.ifun)
161 161 return self._oinfo
162 162
163 163 def __str__(self):
164 164 return "Lineinfo [%s|%s|%s]" %(self.pre, self.ifun, self.the_rest)
165 165
166 166
167 167 #-----------------------------------------------------------------------------
168 168 # Main Prefilter manager
169 169 #-----------------------------------------------------------------------------
170 170
171 171
172 class PrefilterManager(Component):
172 class PrefilterManager(Configurable):
173 173 """Main prefilter component.
174 174
175 175 The IPython prefilter is run on all user input before it is run. The
176 176 prefilter consumes lines of input and produces transformed lines of
177 177 input.
178 178
179 179 The iplementation consists of two phases:
180 180
181 181 1. Transformers
182 182 2. Checkers and handlers
183 183
184 184 Over time, we plan on deprecating the checkers and handlers and doing
185 185 everything in the transformers.
186 186
187 187 The transformers are instances of :class:`PrefilterTransformer` and have
188 188 a single method :meth:`transform` that takes a line and returns a
189 189 transformed line. The transformation can be accomplished using any
190 190 tool, but our current ones use regular expressions for speed. We also
191 191 ship :mod:`pyparsing` in :mod:`IPython.external` for use in transformers.
192 192
193 193 After all the transformers have been run, the line is fed to the checkers,
194 194 which are instances of :class:`PrefilterChecker`. The line is passed to
195 195 the :meth:`check` method, which either returns `None` or a
196 196 :class:`PrefilterHandler` instance. If `None` is returned, the other
197 197 checkers are tried. If an :class:`PrefilterHandler` instance is returned,
198 198 the line is passed to the :meth:`handle` method of the returned
199 199 handler and no further checkers are tried.
200 200
201 201 Both transformers and checkers have a `priority` attribute, that determines
202 202 the order in which they are called. Smaller priorities are tried first.
203 203
204 204 Both transformers and checkers also have `enabled` attribute, which is
205 205 a boolean that determines if the instance is used.
206 206
207 207 Users or developers can change the priority or enabled attribute of
208 208 transformers or checkers, but they must call the :meth:`sort_checkers`
209 209 or :meth:`sort_transformers` method after changing the priority.
210 210 """
211 211
212 212 multi_line_specials = CBool(True, config=True)
213 shell = Instance('IPython.core.iplib.InteractiveShellABC')
213 214
214 def __init__(self, parent, config=None):
215 super(PrefilterManager, self).__init__(parent, config=config)
215 def __init__(self, shell=None, config=None):
216 super(PrefilterManager, self).__init__(shell=shell, config=config)
217 self.shell = shell
216 218 self.init_transformers()
217 219 self.init_handlers()
218 220 self.init_checkers()
219 221
220 @auto_attr
221 def shell(self):
222 return Component.get_instances(
223 root=self.root,
224 klass='IPython.core.iplib.InteractiveShell')[0]
225
226 222 #-------------------------------------------------------------------------
227 223 # API for managing transformers
228 224 #-------------------------------------------------------------------------
229 225
230 226 def init_transformers(self):
231 227 """Create the default transformers."""
232 228 self._transformers = []
233 229 for transformer_cls in _default_transformers:
234 transformer_cls(self, config=self.config)
230 transformer_cls(
231 shell=self.shell, prefilter_manager=self, config=self.config
232 )
235 233
236 234 def sort_transformers(self):
237 235 """Sort the transformers by priority.
238 236
239 237 This must be called after the priority of a transformer is changed.
240 238 The :meth:`register_transformer` method calls this automatically.
241 239 """
242 240 self._transformers.sort(cmp=lambda x,y: x.priority-y.priority)
243 241
244 242 @property
245 243 def transformers(self):
246 244 """Return a list of checkers, sorted by priority."""
247 245 return self._transformers
248 246
249 247 def register_transformer(self, transformer):
250 248 """Register a transformer instance."""
251 249 if transformer not in self._transformers:
252 250 self._transformers.append(transformer)
253 251 self.sort_transformers()
254 252
255 253 def unregister_transformer(self, transformer):
256 254 """Unregister a transformer instance."""
257 255 if transformer in self._transformers:
258 256 self._transformers.remove(transformer)
259 257
260 258 #-------------------------------------------------------------------------
261 259 # API for managing checkers
262 260 #-------------------------------------------------------------------------
263 261
264 262 def init_checkers(self):
265 263 """Create the default checkers."""
266 264 self._checkers = []
267 265 for checker in _default_checkers:
268 checker(self, config=self.config)
266 checker(
267 shell=self.shell, prefilter_manager=self, config=self.config
268 )
269 269
270 270 def sort_checkers(self):
271 271 """Sort the checkers by priority.
272 272
273 273 This must be called after the priority of a checker is changed.
274 274 The :meth:`register_checker` method calls this automatically.
275 275 """
276 276 self._checkers.sort(cmp=lambda x,y: x.priority-y.priority)
277 277
278 278 @property
279 279 def checkers(self):
280 280 """Return a list of checkers, sorted by priority."""
281 281 return self._checkers
282 282
283 283 def register_checker(self, checker):
284 284 """Register a checker instance."""
285 285 if checker not in self._checkers:
286 286 self._checkers.append(checker)
287 287 self.sort_checkers()
288 288
289 289 def unregister_checker(self, checker):
290 290 """Unregister a checker instance."""
291 291 if checker in self._checkers:
292 292 self._checkers.remove(checker)
293 293
294 294 #-------------------------------------------------------------------------
295 295 # API for managing checkers
296 296 #-------------------------------------------------------------------------
297 297
298 298 def init_handlers(self):
299 299 """Create the default handlers."""
300 300 self._handlers = {}
301 301 self._esc_handlers = {}
302 302 for handler in _default_handlers:
303 handler(self, config=self.config)
303 handler(
304 shell=self.shell, prefilter_manager=self, config=self.config
305 )
304 306
305 307 @property
306 308 def handlers(self):
307 309 """Return a dict of all the handlers."""
308 310 return self._handlers
309 311
310 312 def register_handler(self, name, handler, esc_strings):
311 313 """Register a handler instance by name with esc_strings."""
312 314 self._handlers[name] = handler
313 315 for esc_str in esc_strings:
314 316 self._esc_handlers[esc_str] = handler
315 317
316 318 def unregister_handler(self, name, handler, esc_strings):
317 319 """Unregister a handler instance by name with esc_strings."""
318 320 try:
319 321 del self._handlers[name]
320 322 except KeyError:
321 323 pass
322 324 for esc_str in esc_strings:
323 325 h = self._esc_handlers.get(esc_str)
324 326 if h is handler:
325 327 del self._esc_handlers[esc_str]
326 328
327 329 def get_handler_by_name(self, name):
328 330 """Get a handler by its name."""
329 331 return self._handlers.get(name)
330 332
331 333 def get_handler_by_esc(self, esc_str):
332 334 """Get a handler by its escape string."""
333 335 return self._esc_handlers.get(esc_str)
334 336
335 337 #-------------------------------------------------------------------------
336 338 # Main prefiltering API
337 339 #-------------------------------------------------------------------------
338 340
339 341 def prefilter_line_info(self, line_info):
340 342 """Prefilter a line that has been converted to a LineInfo object.
341 343
342 344 This implements the checker/handler part of the prefilter pipe.
343 345 """
344 346 # print "prefilter_line_info: ", line_info
345 347 handler = self.find_handler(line_info)
346 348 return handler.handle(line_info)
347 349
348 350 def find_handler(self, line_info):
349 351 """Find a handler for the line_info by trying checkers."""
350 352 for checker in self.checkers:
351 353 if checker.enabled:
352 354 handler = checker.check(line_info)
353 355 if handler:
354 356 return handler
355 357 return self.get_handler_by_name('normal')
356 358
357 359 def transform_line(self, line, continue_prompt):
358 360 """Calls the enabled transformers in order of increasing priority."""
359 361 for transformer in self.transformers:
360 362 if transformer.enabled:
361 363 line = transformer.transform(line, continue_prompt)
362 364 return line
363 365
364 366 def prefilter_line(self, line, continue_prompt=False):
365 367 """Prefilter a single input line as text.
366 368
367 369 This method prefilters a single line of text by calling the
368 370 transformers and then the checkers/handlers.
369 371 """
370 372
371 373 # print "prefilter_line: ", line, continue_prompt
372 374 # All handlers *must* return a value, even if it's blank ('').
373 375
374 376 # Lines are NOT logged here. Handlers should process the line as
375 377 # needed, update the cache AND log it (so that the input cache array
376 378 # stays synced).
377 379
378 380 # save the line away in case we crash, so the post-mortem handler can
379 381 # record it
380 382 self.shell._last_input_line = line
381 383
382 384 if not line:
383 385 # Return immediately on purely empty lines, so that if the user
384 386 # previously typed some whitespace that started a continuation
385 387 # prompt, he can break out of that loop with just an empty line.
386 388 # This is how the default python prompt works.
387 389
388 390 # Only return if the accumulated input buffer was just whitespace!
389 391 if ''.join(self.shell.buffer).isspace():
390 392 self.shell.buffer[:] = []
391 393 return ''
392 394
393 395 # At this point, we invoke our transformers.
394 396 if not continue_prompt or (continue_prompt and self.multi_line_specials):
395 397 line = self.transform_line(line, continue_prompt)
396 398
397 399 # Now we compute line_info for the checkers and handlers
398 400 line_info = LineInfo(line, continue_prompt)
399 401
400 402 # the input history needs to track even empty lines
401 403 stripped = line.strip()
402 404
403 405 normal_handler = self.get_handler_by_name('normal')
404 406 if not stripped:
405 407 if not continue_prompt:
406 408 self.shell.outputcache.prompt_count -= 1
407 409
408 410 return normal_handler.handle(line_info)
409 411
410 412 # special handlers are only allowed for single line statements
411 413 if continue_prompt and not self.multi_line_specials:
412 414 return normal_handler.handle(line_info)
413 415
414 416 prefiltered = self.prefilter_line_info(line_info)
415 417 # print "prefiltered line: %r" % prefiltered
416 418 return prefiltered
417 419
418 420 def prefilter_lines(self, lines, continue_prompt=False):
419 421 """Prefilter multiple input lines of text.
420 422
421 423 This is the main entry point for prefiltering multiple lines of
422 424 input. This simply calls :meth:`prefilter_line` for each line of
423 425 input.
424 426
425 427 This covers cases where there are multiple lines in the user entry,
426 428 which is the case when the user goes back to a multiline history
427 429 entry and presses enter.
428 430 """
429 431 llines = lines.rstrip('\n').split('\n')
430 432 # We can get multiple lines in one shot, where multiline input 'blends'
431 433 # into one line, in cases like recalling from the readline history
432 434 # buffer. We need to make sure that in such cases, we correctly
433 435 # communicate downstream which line is first and which are continuation
434 436 # ones.
435 437 if len(llines) > 1:
436 438 out = '\n'.join([self.prefilter_line(line, lnum>0)
437 439 for lnum, line in enumerate(llines) ])
438 440 else:
439 441 out = self.prefilter_line(llines[0], continue_prompt)
440 442
441 443 return out
442 444
443 445 #-----------------------------------------------------------------------------
444 446 # Prefilter transformers
445 447 #-----------------------------------------------------------------------------
446 448
447 449
448 class PrefilterTransformer(Component):
450 class PrefilterTransformer(Configurable):
449 451 """Transform a line of user input."""
450 452
451 453 priority = Int(100, config=True)
452 shell = Any
453 prefilter_manager = Any
454 # Transformers don't currently use shell or prefilter_manager, but as we
455 # move away from checkers and handlers, they will need them.
456 shell = Instance('IPython.core.iplib.InteractiveShellABC')
457 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager')
454 458 enabled = Bool(True, config=True)
455 459
456 def __init__(self, parent, config=None):
457 super(PrefilterTransformer, self).__init__(parent, config=config)
460 def __init__(self, shell=None, prefilter_manager=None, config=None):
461 super(PrefilterTransformer, self).__init__(
462 shell=shell, prefilter_manager=prefilter_manager, config=config
463 )
458 464 self.prefilter_manager.register_transformer(self)
459 465
460 @auto_attr
461 def shell(self):
462 return Component.get_instances(
463 root=self.root,
464 klass='IPython.core.iplib.InteractiveShell')[0]
465
466 @auto_attr
467 def prefilter_manager(self):
468 return PrefilterManager.get_instances(root=self.root)[0]
469
470 466 def transform(self, line, continue_prompt):
471 467 """Transform a line, returning the new one."""
472 468 return None
473 469
474 470 def __repr__(self):
475 471 return "<%s(priority=%r, enabled=%r)>" % (
476 472 self.__class__.__name__, self.priority, self.enabled)
477 473
478 474
479 475 _assign_system_re = re.compile(r'(?P<lhs>(\s*)([\w\.]+)((\s*,\s*[\w\.]+)*))'
480 476 r'\s*=\s*!(?P<cmd>.*)')
481 477
482 478
483 479 class AssignSystemTransformer(PrefilterTransformer):
484 480 """Handle the `files = !ls` syntax."""
485 481
486 482 priority = Int(100, config=True)
487 483
488 484 def transform(self, line, continue_prompt):
489 485 m = _assign_system_re.match(line)
490 486 if m is not None:
491 487 cmd = m.group('cmd')
492 488 lhs = m.group('lhs')
493 489 expr = make_quoted_expr("sc -l =%s" % cmd)
494 490 new_line = '%s = get_ipython().magic(%s)' % (lhs, expr)
495 491 return new_line
496 492 return line
497 493
498 494
499 495 _assign_magic_re = re.compile(r'(?P<lhs>(\s*)([\w\.]+)((\s*,\s*[\w\.]+)*))'
500 496 r'\s*=\s*%(?P<cmd>.*)')
501 497
502 498 class AssignMagicTransformer(PrefilterTransformer):
503 499 """Handle the `a = %who` syntax."""
504 500
505 501 priority = Int(200, config=True)
506 502
507 503 def transform(self, line, continue_prompt):
508 504 m = _assign_magic_re.match(line)
509 505 if m is not None:
510 506 cmd = m.group('cmd')
511 507 lhs = m.group('lhs')
512 508 expr = make_quoted_expr(cmd)
513 509 new_line = '%s = get_ipython().magic(%s)' % (lhs, expr)
514 510 return new_line
515 511 return line
516 512
517 513
518 514 _classic_prompt_re = re.compile(r'(^[ \t]*>>> |^[ \t]*\.\.\. )')
519 515
520 516 class PyPromptTransformer(PrefilterTransformer):
521 517 """Handle inputs that start with '>>> ' syntax."""
522 518
523 519 priority = Int(50, config=True)
524 520
525 521 def transform(self, line, continue_prompt):
526 522
527 523 if not line or line.isspace() or line.strip() == '...':
528 524 # This allows us to recognize multiple input prompts separated by
529 525 # blank lines and pasted in a single chunk, very common when
530 526 # pasting doctests or long tutorial passages.
531 527 return ''
532 528 m = _classic_prompt_re.match(line)
533 529 if m:
534 530 return line[len(m.group(0)):]
535 531 else:
536 532 return line
537 533
538 534
539 535 _ipy_prompt_re = re.compile(r'(^[ \t]*In \[\d+\]: |^[ \t]*\ \ \ \.\.\.+: )')
540 536
541 537 class IPyPromptTransformer(PrefilterTransformer):
542 538 """Handle inputs that start classic IPython prompt syntax."""
543 539
544 540 priority = Int(50, config=True)
545 541
546 542 def transform(self, line, continue_prompt):
547 543
548 544 if not line or line.isspace() or line.strip() == '...':
549 545 # This allows us to recognize multiple input prompts separated by
550 546 # blank lines and pasted in a single chunk, very common when
551 547 # pasting doctests or long tutorial passages.
552 548 return ''
553 549 m = _ipy_prompt_re.match(line)
554 550 if m:
555 551 return line[len(m.group(0)):]
556 552 else:
557 553 return line
558 554
559 555 #-----------------------------------------------------------------------------
560 556 # Prefilter checkers
561 557 #-----------------------------------------------------------------------------
562 558
563 559
564 class PrefilterChecker(Component):
560 class PrefilterChecker(Configurable):
565 561 """Inspect an input line and return a handler for that line."""
566 562
567 563 priority = Int(100, config=True)
568 shell = Any
569 prefilter_manager = Any
564 shell = Instance('IPython.core.iplib.InteractiveShellABC')
565 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager')
570 566 enabled = Bool(True, config=True)
571 567
572 def __init__(self, parent, config=None):
573 super(PrefilterChecker, self).__init__(parent, config=config)
568 def __init__(self, shell=None, prefilter_manager=None, config=None):
569 super(PrefilterChecker, self).__init__(
570 shell=shell, prefilter_manager=prefilter_manager, config=config
571 )
574 572 self.prefilter_manager.register_checker(self)
575 573
576 @auto_attr
577 def shell(self):
578 return Component.get_instances(
579 root=self.root,
580 klass='IPython.core.iplib.InteractiveShell')[0]
581
582 @auto_attr
583 def prefilter_manager(self):
584 return PrefilterManager.get_instances(root=self.root)[0]
585
586 574 def check(self, line_info):
587 575 """Inspect line_info and return a handler instance or None."""
588 576 return None
589 577
590 578 def __repr__(self):
591 579 return "<%s(priority=%r, enabled=%r)>" % (
592 580 self.__class__.__name__, self.priority, self.enabled)
593 581
594 582
595 583 class EmacsChecker(PrefilterChecker):
596 584
597 585 priority = Int(100, config=True)
598 586 enabled = Bool(False, config=True)
599 587
600 588 def check(self, line_info):
601 589 "Emacs ipython-mode tags certain input lines."
602 590 if line_info.line.endswith('# PYTHON-MODE'):
603 591 return self.prefilter_manager.get_handler_by_name('emacs')
604 592 else:
605 593 return None
606 594
607 595
608 596 class ShellEscapeChecker(PrefilterChecker):
609 597
610 598 priority = Int(200, config=True)
611 599
612 600 def check(self, line_info):
613 601 if line_info.line.lstrip().startswith(ESC_SHELL):
614 602 return self.prefilter_manager.get_handler_by_name('shell')
615 603
616 604
617 605 class IPyAutocallChecker(PrefilterChecker):
618 606
619 607 priority = Int(300, config=True)
620 608
621 609 def check(self, line_info):
622 610 "Instances of IPyAutocall in user_ns get autocalled immediately"
623 611 obj = self.shell.user_ns.get(line_info.ifun, None)
624 612 if isinstance(obj, IPyAutocall):
625 613 obj.set_ip(self.shell)
626 614 return self.prefilter_manager.get_handler_by_name('auto')
627 615 else:
628 616 return None
629 617
630 618
631 619 class MultiLineMagicChecker(PrefilterChecker):
632 620
633 621 priority = Int(400, config=True)
634 622
635 623 def check(self, line_info):
636 624 "Allow ! and !! in multi-line statements if multi_line_specials is on"
637 625 # Note that this one of the only places we check the first character of
638 626 # ifun and *not* the pre_char. Also note that the below test matches
639 627 # both ! and !!.
640 628 if line_info.continue_prompt \
641 629 and self.prefilter_manager.multi_line_specials:
642 630 if line_info.ifun.startswith(ESC_MAGIC):
643 631 return self.prefilter_manager.get_handler_by_name('magic')
644 632 else:
645 633 return None
646 634
647 635
648 636 class EscCharsChecker(PrefilterChecker):
649 637
650 638 priority = Int(500, config=True)
651 639
652 640 def check(self, line_info):
653 641 """Check for escape character and return either a handler to handle it,
654 642 or None if there is no escape char."""
655 643 if line_info.line[-1] == ESC_HELP \
656 644 and line_info.pre_char != ESC_SHELL \
657 645 and line_info.pre_char != ESC_SH_CAP:
658 646 # the ? can be at the end, but *not* for either kind of shell escape,
659 647 # because a ? can be a vaild final char in a shell cmd
660 648 return self.prefilter_manager.get_handler_by_name('help')
661 649 else:
662 650 # This returns None like it should if no handler exists
663 651 return self.prefilter_manager.get_handler_by_esc(line_info.pre_char)
664 652
665 653
666 654 class AssignmentChecker(PrefilterChecker):
667 655
668 656 priority = Int(600, config=True)
669 657
670 658 def check(self, line_info):
671 659 """Check to see if user is assigning to a var for the first time, in
672 660 which case we want to avoid any sort of automagic / autocall games.
673 661
674 662 This allows users to assign to either alias or magic names true python
675 663 variables (the magic/alias systems always take second seat to true
676 664 python code). E.g. ls='hi', or ls,that=1,2"""
677 665 if line_info.the_rest:
678 666 if line_info.the_rest[0] in '=,':
679 667 return self.prefilter_manager.get_handler_by_name('normal')
680 668 else:
681 669 return None
682 670
683 671
684 672 class AutoMagicChecker(PrefilterChecker):
685 673
686 674 priority = Int(700, config=True)
687 675
688 676 def check(self, line_info):
689 677 """If the ifun is magic, and automagic is on, run it. Note: normal,
690 678 non-auto magic would already have been triggered via '%' in
691 679 check_esc_chars. This just checks for automagic. Also, before
692 680 triggering the magic handler, make sure that there is nothing in the
693 681 user namespace which could shadow it."""
694 682 if not self.shell.automagic or not hasattr(self.shell,'magic_'+line_info.ifun):
695 683 return None
696 684
697 685 # We have a likely magic method. Make sure we should actually call it.
698 686 if line_info.continue_prompt and not self.prefilter_manager.multi_line_specials:
699 687 return None
700 688
701 689 head = line_info.ifun.split('.',1)[0]
702 690 if is_shadowed(head, self.shell):
703 691 return None
704 692
705 693 return self.prefilter_manager.get_handler_by_name('magic')
706 694
707 695
708 696 class AliasChecker(PrefilterChecker):
709 697
710 698 priority = Int(800, config=True)
711 699
712 @auto_attr
713 def alias_manager(self):
714 return AliasManager.get_instances(root=self.root)[0]
715
716 700 def check(self, line_info):
717 701 "Check if the initital identifier on the line is an alias."
718 702 # Note: aliases can not contain '.'
719 703 head = line_info.ifun.split('.',1)[0]
720 if line_info.ifun not in self.alias_manager \
721 or head not in self.alias_manager \
704 if line_info.ifun not in self.shell.alias_manager \
705 or head not in self.shell.alias_manager \
722 706 or is_shadowed(head, self.shell):
723 707 return None
724 708
725 709 return self.prefilter_manager.get_handler_by_name('alias')
726 710
727 711
728 712 class PythonOpsChecker(PrefilterChecker):
729 713
730 714 priority = Int(900, config=True)
731 715
732 716 def check(self, line_info):
733 717 """If the 'rest' of the line begins with a function call or pretty much
734 718 any python operator, we should simply execute the line (regardless of
735 719 whether or not there's a possible autocall expansion). This avoids
736 720 spurious (and very confusing) geattr() accesses."""
737 721 if line_info.the_rest and line_info.the_rest[0] in '!=()<>,+*/%^&|':
738 722 return self.prefilter_manager.get_handler_by_name('normal')
739 723 else:
740 724 return None
741 725
742 726
743 727 class AutocallChecker(PrefilterChecker):
744 728
745 729 priority = Int(1000, config=True)
746 730
747 731 def check(self, line_info):
748 732 "Check if the initial word/function is callable and autocall is on."
749 733 if not self.shell.autocall:
750 734 return None
751 735
752 736 oinfo = line_info.ofind(self.shell) # This can mutate state via getattr
753 737 if not oinfo['found']:
754 738 return None
755 739
756 740 if callable(oinfo['obj']) \
757 741 and (not re_exclude_auto.match(line_info.the_rest)) \
758 742 and re_fun_name.match(line_info.ifun):
759 743 return self.prefilter_manager.get_handler_by_name('auto')
760 744 else:
761 745 return None
762 746
763 747
764 748 #-----------------------------------------------------------------------------
765 749 # Prefilter handlers
766 750 #-----------------------------------------------------------------------------
767 751
768 752
769 class PrefilterHandler(Component):
753 class PrefilterHandler(Configurable):
770 754
771 755 handler_name = Str('normal')
772 756 esc_strings = List([])
773 shell = Any
774 prefilter_manager = Any
757 shell = Instance('IPython.core.iplib.InteractiveShellABC')
758 prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager')
775 759
776 def __init__(self, parent, config=None):
777 super(PrefilterHandler, self).__init__(parent, config=config)
760 def __init__(self, shell=None, prefilter_manager=None, config=None):
761 super(PrefilterHandler, self).__init__(
762 shell=shell, prefilter_manager=prefilter_manager, config=config
763 )
778 764 self.prefilter_manager.register_handler(
779 765 self.handler_name,
780 766 self,
781 767 self.esc_strings
782 768 )
783 769
784 @auto_attr
785 def shell(self):
786 return Component.get_instances(
787 root=self.root,
788 klass='IPython.core.iplib.InteractiveShell')[0]
789
790 @auto_attr
791 def prefilter_manager(self):
792 return PrefilterManager.get_instances(root=self.root)[0]
793
794 770 def handle(self, line_info):
795 771 # print "normal: ", line_info
796 772 """Handle normal input lines. Use as a template for handlers."""
797 773
798 774 # With autoindent on, we need some way to exit the input loop, and I
799 775 # don't want to force the user to have to backspace all the way to
800 776 # clear the line. The rule will be in this case, that either two
801 777 # lines of pure whitespace in a row, or a line of pure whitespace but
802 778 # of a size different to the indent level, will exit the input loop.
803 779 line = line_info.line
804 780 continue_prompt = line_info.continue_prompt
805 781
806 782 if (continue_prompt and
807 783 self.shell.autoindent and
808 784 line.isspace() and
809 785
810 786 (0 < abs(len(line) - self.shell.indent_current_nsp) <= 2
811 787 or
812 788 not self.shell.buffer
813 789 or
814 790 (self.shell.buffer[-1]).isspace()
815 791 )
816 792 ):
817 793 line = ''
818 794
819 795 self.shell.log(line, line, continue_prompt)
820 796 return line
821 797
822 798 def __str__(self):
823 799 return "<%s(name=%s)>" % (self.__class__.__name__, self.handler_name)
824 800
825 801
826 802 class AliasHandler(PrefilterHandler):
827 803
828 804 handler_name = Str('alias')
829 805
830 @auto_attr
831 def alias_manager(self):
832 return AliasManager.get_instances(root=self.root)[0]
833
834 806 def handle(self, line_info):
835 807 """Handle alias input lines. """
836 transformed = self.alias_manager.expand_aliases(line_info.ifun,line_info.the_rest)
808 transformed = self.shell.alias_manager.expand_aliases(line_info.ifun,line_info.the_rest)
837 809 # pre is needed, because it carries the leading whitespace. Otherwise
838 810 # aliases won't work in indented sections.
839 811 line_out = '%sget_ipython().system(%s)' % (line_info.pre_whitespace,
840 812 make_quoted_expr(transformed))
841 813
842 814 self.shell.log(line_info.line, line_out, line_info.continue_prompt)
843 815 return line_out
844 816
845 817
846 818 class ShellEscapeHandler(PrefilterHandler):
847 819
848 820 handler_name = Str('shell')
849 821 esc_strings = List([ESC_SHELL, ESC_SH_CAP])
850 822
851 823 def handle(self, line_info):
852 824 """Execute the line in a shell, empty return value"""
853 825 magic_handler = self.prefilter_manager.get_handler_by_name('magic')
854 826
855 827 line = line_info.line
856 828 if line.lstrip().startswith(ESC_SH_CAP):
857 829 # rewrite LineInfo's line, ifun and the_rest to properly hold the
858 830 # call to %sx and the actual command to be executed, so
859 831 # handle_magic can work correctly. Note that this works even if
860 832 # the line is indented, so it handles multi_line_specials
861 833 # properly.
862 834 new_rest = line.lstrip()[2:]
863 835 line_info.line = '%ssx %s' % (ESC_MAGIC, new_rest)
864 836 line_info.ifun = 'sx'
865 837 line_info.the_rest = new_rest
866 838 return magic_handler.handle(line_info)
867 839 else:
868 840 cmd = line.lstrip().lstrip(ESC_SHELL)
869 841 line_out = '%sget_ipython().system(%s)' % (line_info.pre_whitespace,
870 842 make_quoted_expr(cmd))
871 843 # update cache/log and return
872 844 self.shell.log(line, line_out, line_info.continue_prompt)
873 845 return line_out
874 846
875 847
876 848 class MagicHandler(PrefilterHandler):
877 849
878 850 handler_name = Str('magic')
879 851 esc_strings = List([ESC_MAGIC])
880 852
881 853 def handle(self, line_info):
882 854 """Execute magic functions."""
883 855 ifun = line_info.ifun
884 856 the_rest = line_info.the_rest
885 857 cmd = '%sget_ipython().magic(%s)' % (line_info.pre_whitespace,
886 858 make_quoted_expr(ifun + " " + the_rest))
887 859 self.shell.log(line_info.line, cmd, line_info.continue_prompt)
888 860 return cmd
889 861
890 862
891 863 class AutoHandler(PrefilterHandler):
892 864
893 865 handler_name = Str('auto')
894 866 esc_strings = List([ESC_PAREN, ESC_QUOTE, ESC_QUOTE2])
895 867
896 868 def handle(self, line_info):
897 """Hande lines which can be auto-executed, quoting if requested."""
869 """Handle lines which can be auto-executed, quoting if requested."""
898 870 line = line_info.line
899 871 ifun = line_info.ifun
900 872 the_rest = line_info.the_rest
901 873 pre = line_info.pre
902 874 continue_prompt = line_info.continue_prompt
903 875 obj = line_info.ofind(self)['obj']
904 876 #print 'pre <%s> ifun <%s> rest <%s>' % (pre,ifun,the_rest) # dbg
905 877
906 878 # This should only be active for single-line input!
907 879 if continue_prompt:
908 880 self.shell.log(line,line,continue_prompt)
909 881 return line
910 882
911 883 force_auto = isinstance(obj, IPyAutocall)
912 884 auto_rewrite = True
913 885
914 886 if pre == ESC_QUOTE:
915 887 # Auto-quote splitting on whitespace
916 888 newcmd = '%s("%s")' % (ifun,'", "'.join(the_rest.split()) )
917 889 elif pre == ESC_QUOTE2:
918 890 # Auto-quote whole string
919 891 newcmd = '%s("%s")' % (ifun,the_rest)
920 892 elif pre == ESC_PAREN:
921 893 newcmd = '%s(%s)' % (ifun,",".join(the_rest.split()))
922 894 else:
923 895 # Auto-paren.
924 896 # We only apply it to argument-less calls if the autocall
925 897 # parameter is set to 2. We only need to check that autocall is <
926 898 # 2, since this function isn't called unless it's at least 1.
927 899 if not the_rest and (self.shell.autocall < 2) and not force_auto:
928 900 newcmd = '%s %s' % (ifun,the_rest)
929 901 auto_rewrite = False
930 902 else:
931 903 if not force_auto and the_rest.startswith('['):
932 904 if hasattr(obj,'__getitem__'):
933 905 # Don't autocall in this case: item access for an object
934 906 # which is BOTH callable and implements __getitem__.
935 907 newcmd = '%s %s' % (ifun,the_rest)
936 908 auto_rewrite = False
937 909 else:
938 910 # if the object doesn't support [] access, go ahead and
939 911 # autocall
940 912 newcmd = '%s(%s)' % (ifun.rstrip(),the_rest)
941 913 elif the_rest.endswith(';'):
942 914 newcmd = '%s(%s);' % (ifun.rstrip(),the_rest[:-1])
943 915 else:
944 916 newcmd = '%s(%s)' % (ifun.rstrip(), the_rest)
945 917
946 918 if auto_rewrite:
947 919 rw = self.shell.outputcache.prompt1.auto_rewrite() + newcmd
948 920
949 921 try:
950 922 # plain ascii works better w/ pyreadline, on some machines, so
951 923 # we use it and only print uncolored rewrite if we have unicode
952 924 rw = str(rw)
953 925 print >>Term.cout, rw
954 926 except UnicodeEncodeError:
955 927 print "-------------->" + newcmd
956 928
957 929 # log what is now valid Python, not the actual user input (without the
958 930 # final newline)
959 931 self.shell.log(line,newcmd,continue_prompt)
960 932 return newcmd
961 933
962 934
963 935 class HelpHandler(PrefilterHandler):
964 936
965 937 handler_name = Str('help')
966 938 esc_strings = List([ESC_HELP])
967 939
968 940 def handle(self, line_info):
969 941 """Try to get some help for the object.
970 942
971 943 obj? or ?obj -> basic information.
972 944 obj?? or ??obj -> more details.
973 945 """
974 946 normal_handler = self.prefilter_manager.get_handler_by_name('normal')
975 947 line = line_info.line
976 948 # We need to make sure that we don't process lines which would be
977 949 # otherwise valid python, such as "x=1 # what?"
978 950 try:
979 951 codeop.compile_command(line)
980 952 except SyntaxError:
981 953 # We should only handle as help stuff which is NOT valid syntax
982 954 if line[0]==ESC_HELP:
983 955 line = line[1:]
984 956 elif line[-1]==ESC_HELP:
985 957 line = line[:-1]
986 958 self.shell.log(line, '#?'+line, line_info.continue_prompt)
987 959 if line:
988 960 #print 'line:<%r>' % line # dbg
989 961 self.shell.magic_pinfo(line)
990 962 else:
991 963 page(self.shell.usage, screen_lines=self.shell.usable_screen_length)
992 964 return '' # Empty string is needed here!
993 965 except:
994 966 raise
995 967 # Pass any other exceptions through to the normal handler
996 968 return normal_handler.handle(line_info)
997 969 else:
998 970 # If the code compiles ok, we should handle it normally
999 971 return normal_handler.handle(line_info)
1000 972
1001 973
1002 974 class EmacsHandler(PrefilterHandler):
1003 975
1004 976 handler_name = Str('emacs')
1005 977 esc_strings = List([])
1006 978
1007 979 def handle(self, line_info):
1008 980 """Handle input lines marked by python-mode."""
1009 981
1010 982 # Currently, nothing is done. Later more functionality can be added
1011 983 # here if needed.
1012 984
1013 985 # The input cache shouldn't be updated
1014 986 return line_info.line
1015 987
1016 988
1017 989 #-----------------------------------------------------------------------------
1018 990 # Defaults
1019 991 #-----------------------------------------------------------------------------
1020 992
1021 993
1022 994 _default_transformers = [
1023 995 AssignSystemTransformer,
1024 996 AssignMagicTransformer,
1025 997 PyPromptTransformer,
1026 998 IPyPromptTransformer,
1027 999 ]
1028 1000
1029 1001 _default_checkers = [
1030 1002 EmacsChecker,
1031 1003 ShellEscapeChecker,
1032 1004 IPyAutocallChecker,
1033 1005 MultiLineMagicChecker,
1034 1006 EscCharsChecker,
1035 1007 AssignmentChecker,
1036 1008 AutoMagicChecker,
1037 1009 AliasChecker,
1038 1010 PythonOpsChecker,
1039 1011 AutocallChecker
1040 1012 ]
1041 1013
1042 1014 _default_handlers = [
1043 1015 PrefilterHandler,
1044 1016 AliasHandler,
1045 1017 ShellEscapeHandler,
1046 1018 MagicHandler,
1047 1019 AutoHandler,
1048 1020 HelpHandler,
1049 1021 EmacsHandler
1050 1022 ]
@@ -1,41 +1,47 b''
1 1 """Minimal script to reproduce our nasty reference counting bug.
2 2
3 3 The problem is related to https://bugs.launchpad.net/ipython/+bug/269966
4 4
5 5 The original fix for that appeared to work, but John D. Hunter found a
6 6 matplotlib example which, when run twice in a row, would break. The problem
7 7 were references held by open figures to internals of Tkinter.
8 8
9 9 This code reproduces the problem that John saw, without matplotlib.
10 10
11 11 This script is meant to be called by other parts of the test suite that call it
12 12 via %run as if it were executed interactively by the user. As of 2009-04-13,
13 13 test_magic.py calls it.
14 14 """
15 15
16 16 #-----------------------------------------------------------------------------
17 17 # Module imports
18 18 #-----------------------------------------------------------------------------
19 19 import sys
20 20
21 21 from IPython.core import ipapi
22 22
23 23 #-----------------------------------------------------------------------------
24 24 # Globals
25 25 #-----------------------------------------------------------------------------
26 ip = ipapi.get()
27 26
28 if not '_refbug_cache' in ip.user_ns:
29 ip.user_ns['_refbug_cache'] = []
27 # This needs to be here because nose and other test runners will import
28 # this module. Importing this module has potential side effects that we
29 # want to prevent.
30 if __name__ == '__main__':
30 31
32 ip = ipapi.get()
31 33
32 aglobal = 'Hello'
33 def f():
34 return aglobal
34 if not '_refbug_cache' in ip.user_ns:
35 ip.user_ns['_refbug_cache'] = []
35 36
36 cache = ip.user_ns['_refbug_cache']
37 cache.append(f)
38 37
39 def call_f():
40 for func in cache:
41 print 'lowercased:',func().lower()
38 aglobal = 'Hello'
39 def f():
40 return aglobal
41
42 cache = ip.user_ns['_refbug_cache']
43 cache.append(f)
44
45 def call_f():
46 for func in cache:
47 print 'lowercased:',func().lower()
@@ -1,13 +1,2 b''
1 1 # -*- coding: utf-8 -*-
2 """This directory is meant for special-purpose extensions to IPython.
3
4 This can include things which alter the syntax processing stage (see
5 PhysicalQ_Input for an example of how to do this).
6
7 Any file located here can be called with an 'execfile =' option as
8
9 execfile = extensions/filename.py
10
11 since the IPython directory itself is already part of the search path for
12 files listed as 'execfile ='.
13 """
2 """This directory is meant for IPython extensions."""
@@ -1,209 +1,201 b''
1 1 #!/usr/bin/env python
2 2 # encoding: utf-8
3 3
4 4 """Magic command interface for interactive parallel work."""
5 5
6 6 #-----------------------------------------------------------------------------
7 7 # Copyright (C) 2008-2009 The IPython Development Team
8 8 #
9 9 # Distributed under the terms of the BSD License. The full license is in
10 10 # the file COPYING, distributed as part of this software.
11 11 #-----------------------------------------------------------------------------
12 12
13 13 #-----------------------------------------------------------------------------
14 14 # Imports
15 15 #-----------------------------------------------------------------------------
16 16
17 17 import new
18 18
19 from IPython.core.component import Component
20 from IPython.utils.traitlets import Bool, Any
19 from IPython.core.plugin import Plugin
20 from IPython.utils.traitlets import Bool, Any, Instance
21 21 from IPython.utils.autoattr import auto_attr
22 22 from IPython.testing import decorators as testdec
23 23
24 24 #-----------------------------------------------------------------------------
25 25 # Definitions of magic functions for use with IPython
26 26 #-----------------------------------------------------------------------------
27 27
28 28
29 29 NO_ACTIVE_MULTIENGINE_CLIENT = """
30 30 Use activate() on a MultiEngineClient object to activate it for magics.
31 31 """
32 32
33 33
34 class ParalleMagicComponent(Component):
34 class ParalleMagic(Plugin):
35 35 """A component to manage the %result, %px and %autopx magics."""
36 36
37 37 active_multiengine_client = Any()
38 38 verbose = Bool(False, config=True)
39 shell = Instance('IPython.core.iplib.InteractiveShellABC')
39 40
40 def __init__(self, parent, name=None, config=None):
41 super(ParalleMagicComponent, self).__init__(parent, name=name, config=config)
41 def __init__(self, shell=None, config=None):
42 super(ParalleMagic, self).__init__(shell=shell, config=config)
42 43 self._define_magics()
43 44 # A flag showing if autopx is activated or not
44 45 self.autopx = False
45 46
46 # Access other components like this rather than by a regular attribute.
47 # This won't lookup the InteractiveShell object until it is used and
48 # then it is cached. This is both efficient and couples this class
49 # more loosely to InteractiveShell.
50 @auto_attr
51 def shell(self):
52 return Component.get_instances(
53 root=self.root,
54 klass='IPython.core.iplib.InteractiveShell')[0]
55
56 47 def _define_magics(self):
57 48 """Define the magic functions."""
58 49 self.shell.define_magic('result', self.magic_result)
59 50 self.shell.define_magic('px', self.magic_px)
60 51 self.shell.define_magic('autopx', self.magic_autopx)
61 52
62 53 @testdec.skip_doctest
63 54 def magic_result(self, ipself, parameter_s=''):
64 55 """Print the result of command i on all engines..
65 56
66 57 To use this a :class:`MultiEngineClient` instance must be created
67 58 and then activated by calling its :meth:`activate` method.
68 59
69 60 Then you can do the following::
70 61
71 62 In [23]: %result
72 63 Out[23]:
73 64 <Results List>
74 65 [0] In [6]: a = 10
75 66 [1] In [6]: a = 10
76 67
77 68 In [22]: %result 6
78 69 Out[22]:
79 70 <Results List>
80 71 [0] In [6]: a = 10
81 72 [1] In [6]: a = 10
82 73 """
83 74 if self.active_multiengine_client is None:
84 75 print NO_ACTIVE_MULTIENGINE_CLIENT
85 76 return
86 77
87 78 try:
88 79 index = int(parameter_s)
89 80 except:
90 81 index = None
91 82 result = self.active_multiengine_client.get_result(index)
92 83 return result
93 84
94 85 @testdec.skip_doctest
95 86 def magic_px(self, ipself, parameter_s=''):
96 87 """Executes the given python command in parallel.
97 88
98 89 To use this a :class:`MultiEngineClient` instance must be created
99 90 and then activated by calling its :meth:`activate` method.
100 91
101 92 Then you can do the following::
102 93
103 94 In [24]: %px a = 5
104 95 Parallel execution on engines: all
105 96 Out[24]:
106 97 <Results List>
107 98 [0] In [7]: a = 5
108 99 [1] In [7]: a = 5
109 100 """
110 101
111 102 if self.active_multiengine_client is None:
112 103 print NO_ACTIVE_MULTIENGINE_CLIENT
113 104 return
114 105 print "Parallel execution on engines: %s" % self.active_multiengine_client.targets
115 106 result = self.active_multiengine_client.execute(parameter_s)
116 107 return result
117 108
118 109 @testdec.skip_doctest
119 110 def magic_autopx(self, ipself, parameter_s=''):
120 111 """Toggles auto parallel mode.
121 112
122 113 To use this a :class:`MultiEngineClient` instance must be created
123 114 and then activated by calling its :meth:`activate` method. Once this
124 115 is called, all commands typed at the command line are send to
125 116 the engines to be executed in parallel. To control which engine
126 117 are used, set the ``targets`` attributed of the multiengine client
127 118 before entering ``%autopx`` mode.
128 119
129 120 Then you can do the following::
130 121
131 122 In [25]: %autopx
132 123 %autopx to enabled
133 124
134 125 In [26]: a = 10
135 126 <Results List>
136 127 [0] In [8]: a = 10
137 128 [1] In [8]: a = 10
138 129
139 130
140 131 In [27]: %autopx
141 132 %autopx disabled
142 133 """
143 134 if self.autopx:
144 135 self._disable_autopx()
145 136 else:
146 137 self._enable_autopx()
147 138
148 139 def _enable_autopx(self):
149 140 """Enable %autopx mode by saving the original runsource and installing
150 141 pxrunsource.
151 142 """
152 143 if self.active_multiengine_client is None:
153 144 print NO_ACTIVE_MULTIENGINE_CLIENT
154 145 return
155 146
156 147 self._original_runsource = self.shell.runsource
157 148 self.shell.runsource = new.instancemethod(
158 149 self.pxrunsource, self.shell, self.shell.__class__
159 150 )
160 151 self.autopx = True
161 152 print "%autopx enabled"
162 153
163 154 def _disable_autopx(self):
164 155 """Disable %autopx by restoring the original InteractiveShell.runsource."""
165 156 if self.autopx:
166 157 self.shell.runsource = self._original_runsource
167 158 self.autopx = False
168 159 print "%autopx disabled"
169 160
170 161 def pxrunsource(self, ipself, source, filename="<input>", symbol="single"):
171 162 """A parallel replacement for InteractiveShell.runsource."""
172 163
173 164 try:
174 165 code = ipself.compile(source, filename, symbol)
175 166 except (OverflowError, SyntaxError, ValueError):
176 167 # Case 1
177 168 ipself.showsyntaxerror(filename)
178 169 return None
179 170
180 171 if code is None:
181 172 # Case 2
182 173 return True
183 174
184 175 # Case 3
185 176 # Because autopx is enabled, we now call executeAll or disable autopx if
186 177 # %autopx or autopx has been called
187 178 if 'get_ipython().magic("%autopx' in source or 'get_ipython().magic("autopx' in source:
188 179 self._disable_autopx()
189 180 return False
190 181 else:
191 182 try:
192 183 result = self.active_multiengine_client.execute(source)
193 184 except:
194 185 ipself.showtraceback()
195 186 else:
196 187 print result.__repr__()
197 188 return False
198 189
199 190
200 191 _loaded = False
201 192
202 193
203 194 def load_ipython_extension(ip):
204 195 """Load the extension in IPython."""
205 196 global _loaded
206 197 if not _loaded:
207 prd = ParalleMagicComponent(ip, name='parallel_magic')
198 plugin = ParalleMagic(shell=ip, config=ip.config)
199 ip.plugin_manager.register_plugin('parallel_magic', plugin)
208 200 _loaded = True
209 201
@@ -1,166 +1,157 b''
1 1 """Use pretty.py for configurable pretty-printing.
2 2
3 3 To enable this extension in your configuration
4 4 file, add the following to :file:`ipython_config.py`::
5 5
6 6 c.Global.extensions = ['IPython.extensions.pretty']
7 7 def dict_pprinter(obj, p, cycle):
8 8 return p.text("<dict>")
9 9 c.PrettyResultDisplay.verbose = True
10 10 c.PrettyResultDisplay.defaults_for_type = [
11 11 (dict, dict_pprinter)
12 12 ]
13 13 c.PrettyResultDisplay.defaults_for_type_by_name = [
14 14 ('numpy', 'dtype', 'IPython.extensions.pretty.dtype_pprinter')
15 15 ]
16 16
17 17 This extension can also be loaded by using the ``%load_ext`` magic::
18 18
19 19 %load_ext IPython.extensions.pretty
20 20
21 21 If this extension is enabled, you can always add additional pretty printers
22 22 by doing::
23 23
24 24 ip = get_ipython()
25 25 prd = ip.get_component('pretty_result_display')
26 26 import numpy
27 27 from IPython.extensions.pretty import dtype_pprinter
28 28 prd.for_type(numpy.dtype, dtype_pprinter)
29 29
30 30 # If you don't want to have numpy imported until it needs to be:
31 31 prd.for_type_by_name('numpy', 'dtype', dtype_pprinter)
32 32 """
33 33
34 34 #-----------------------------------------------------------------------------
35 35 # Imports
36 36 #-----------------------------------------------------------------------------
37 37
38 38 from IPython.core.error import TryNext
39 39 from IPython.external import pretty
40 from IPython.core.component import Component
41 from IPython.utils.traitlets import Bool, List
40 from IPython.core.plugin import Plugin
41 from IPython.utils.traitlets import Bool, List, Instance
42 42 from IPython.utils.io import Term
43 43 from IPython.utils.autoattr import auto_attr
44 44 from IPython.utils.importstring import import_item
45 45
46 46 #-----------------------------------------------------------------------------
47 47 # Code
48 48 #-----------------------------------------------------------------------------
49 49
50 50
51 51 _loaded = False
52 52
53 53
54 class PrettyResultDisplay(Component):
54 class PrettyResultDisplay(Plugin):
55 55 """A component for pretty printing on steroids."""
56 56
57 57 verbose = Bool(False, config=True)
58 shell = Instance('IPython.core.iplib.InteractiveShellABC')
58 59
59 60 # A list of (type, func_name), like
60 61 # [(dict, 'my_dict_printer')]
61 62 # The final argument can also be a callable
62 63 defaults_for_type = List(default_value=[], config=True)
63 64
64 65 # A list of (module_name, type_name, func_name), like
65 66 # [('numpy', 'dtype', 'IPython.extensions.pretty.dtype_pprinter')]
66 67 # The final argument can also be a callable
67 68 defaults_for_type_by_name = List(default_value=[], config=True)
68 69
69 def __init__(self, parent, name=None, config=None):
70 super(PrettyResultDisplay, self).__init__(parent, name=name, config=config)
70 def __init__(self, shell=None, config=None):
71 super(PrettyResultDisplay, self).__init__(shell=shell, config=config)
71 72 self._setup_defaults()
72 73
73 74 def _setup_defaults(self):
74 75 """Initialize the default pretty printers."""
75 76 for typ, func_name in self.defaults_for_type:
76 77 func = self._resolve_func_name(func_name)
77 78 self.for_type(typ, func)
78 79 for type_module, type_name, func_name in self.defaults_for_type_by_name:
79 80 func = self._resolve_func_name(func_name)
80 81 self.for_type_by_name(type_module, type_name, func)
81 82
82 83 def _resolve_func_name(self, func_name):
83 84 if callable(func_name):
84 85 return func_name
85 86 elif isinstance(func_name, basestring):
86 87 return import_item(func_name)
87 88 else:
88 89 raise TypeError('func_name must be a str or callable, got: %r' % func_name)
89 90
90 # Access other components like this rather than by a regular attribute.
91 # This won't lookup the InteractiveShell object until it is used and
92 # then it is cached. This is both efficient and couples this class
93 # more loosely to InteractiveShell.
94 @auto_attr
95 def shell(self):
96 return Component.get_instances(
97 root=self.root,
98 klass='IPython.core.iplib.InteractiveShell')[0]
99
100 91 def __call__(self, otherself, arg):
101 92 """Uber-pretty-printing display hook.
102 93
103 94 Called for displaying the result to the user.
104 95 """
105 96
106 97 if self.shell.pprint:
107 98 out = pretty.pretty(arg, verbose=self.verbose)
108 99 if '\n' in out:
109 100 # So that multi-line strings line up with the left column of
110 101 # the screen, instead of having the output prompt mess up
111 102 # their first line.
112 103 Term.cout.write('\n')
113 104 print >>Term.cout, out
114 105 else:
115 106 raise TryNext
116 107
117 108 def for_type(self, typ, func):
118 109 """Add a pretty printer for a type."""
119 110 return pretty.for_type(typ, func)
120 111
121 112 def for_type_by_name(self, type_module, type_name, func):
122 113 """Add a pretty printer for a type by its name and module name."""
123 114 return pretty.for_type_by_name(type_module, type_name, func)
124 115
125 116
126 117 #-----------------------------------------------------------------------------
127 118 # Initialization code for the extension
128 119 #-----------------------------------------------------------------------------
129 120
130 121
131 122 def load_ipython_extension(ip):
132 123 """Load the extension in IPython as a hook."""
133 124 global _loaded
134 125 if not _loaded:
135 prd = PrettyResultDisplay(ip, name='pretty_result_display')
136 ip.set_hook('result_display', prd, priority=99)
126 plugin = PrettyResultDisplay(shell=ip, config=ip.config)
127 ip.set_hook('result_display', plugin, priority=99)
137 128 _loaded = True
138 return prd
129 ip.plugin_manager.register_plugin('pretty_result_display', plugin)
139 130
140 131 def unload_ipython_extension(ip):
141 132 """Unload the extension."""
142 133 # The hook system does not have a way to remove a hook so this is a pass
143 134 pass
144 135
145 136
146 137 #-----------------------------------------------------------------------------
147 138 # Example pretty printers
148 139 #-----------------------------------------------------------------------------
149 140
150 141
151 142 def dtype_pprinter(obj, p, cycle):
152 143 """ A pretty-printer for numpy dtype objects.
153 144 """
154 145 if cycle:
155 146 return p.text('dtype(...)')
156 147 if hasattr(obj, 'fields'):
157 148 if obj.fields is None:
158 149 p.text(repr(obj))
159 150 else:
160 151 p.begin_group(7, 'dtype([')
161 152 for i, field in enumerate(obj.descr):
162 153 if i > 0:
163 154 p.text(',')
164 155 p.breakable()
165 156 p.pretty(field)
166 157 p.end_group(7, '])')
@@ -1,101 +1,100 b''
1 1 #!/usr/bin/env python
2 2 # encoding: utf-8
3 3 """
4 4 Simple tests for :mod:`IPython.extensions.pretty`.
5 5 """
6 6
7 7 #-----------------------------------------------------------------------------
8 8 # Copyright (C) 2008-2009 The IPython Development Team
9 9 #
10 10 # Distributed under the terms of the BSD License. The full license is in
11 11 # the file COPYING, distributed as part of this software.
12 12 #-----------------------------------------------------------------------------
13 13
14 14 #-----------------------------------------------------------------------------
15 15 # Imports
16 16 #-----------------------------------------------------------------------------
17 17
18 18 from unittest import TestCase
19 19
20 from IPython.core.component import Component, masquerade_as
21 from IPython.core.iplib import InteractiveShell
20 from IPython.config.configurable import Configurable
21 from IPython.core.iplib import InteractiveShellABC
22 22 from IPython.extensions import pretty as pretty_ext
23 23 from IPython.external import pretty
24 24 from IPython.testing import decorators as dec
25 25 from IPython.testing import tools as tt
26 26 from IPython.utils.traitlets import Bool
27 27
28 28 #-----------------------------------------------------------------------------
29 29 # Tests
30 30 #-----------------------------------------------------------------------------
31 31
32 class InteractiveShellStub(Component):
32 class InteractiveShellStub(Configurable):
33 33 pprint = Bool(True)
34 34
35 InteractiveShellABC.register(InteractiveShellStub)
36
35 37 class A(object):
36 38 pass
37 39
38 40 def a_pprinter(o, p, c):
39 41 return p.text("<A>")
40 42
41 43 class TestPrettyResultDisplay(TestCase):
42 44
43 45 def setUp(self):
44 self.ip = InteractiveShellStub(None)
45 # This allows our stub to be retrieved instead of the real
46 # InteractiveShell
47 masquerade_as(self.ip, InteractiveShell)
48 self.prd = pretty_ext.PrettyResultDisplay(self.ip,
49 name='pretty_result_display')
46 self.ip = InteractiveShellStub()
47 self.prd = pretty_ext.PrettyResultDisplay(shell=self.ip, config=None)
50 48
51 49 def test_for_type(self):
52 50 self.prd.for_type(A, a_pprinter)
53 51 a = A()
54 52 result = pretty.pretty(a)
55 53 self.assertEquals(result, "<A>")
56 54
57 55 ipy_src = """
58 56 class A(object):
59 57 def __repr__(self):
60 58 return 'A()'
61 59
62 60 class B(object):
63 61 def __repr__(self):
64 62 return 'B()'
65 63
66 64 a = A()
67 65 b = B()
68 66
69 67 def a_pretty_printer(obj, p, cycle):
70 68 p.text('<A>')
71 69
72 70 def b_pretty_printer(obj, p, cycle):
73 71 p.text('<B>')
74 72
75 73
76 74 a
77 75 b
78 76
79 77 ip = get_ipython()
80 prd = ip.load_extension('pretty')
78 ip.extension_manager.load_extension('pretty')
79 prd = ip.plugin_manager.get_plugin('pretty_result_display')
81 80 prd.for_type(A, a_pretty_printer)
82 81 prd.for_type_by_name(B.__module__, B.__name__, b_pretty_printer)
83 82
84 83 a
85 84 b
86 85 """
87 86 ipy_out = """
88 87 A()
89 88 B()
90 89 <A>
91 90 <B>
92 91 """
93 92
94 93 class TestPrettyInteractively(tt.TempFileMixin):
95 94
96 95 # XXX Unfortunately, ipexec_validate fails under win32. If someone helps
97 96 # us write a win32-compatible version, we can reactivate this test.
98 97 @dec.skip_win32
99 98 def test_printers(self):
100 99 self.mktmp(ipy_src, '.ipy')
101 100 tt.ipexec_validate(self.fname, ipy_out)
@@ -1,539 +1,538 b''
1 1 #!/usr/bin/env python
2 2 # encoding: utf-8
3 3 """
4 4 The IPython cluster directory
5 5 """
6 6
7 7 #-----------------------------------------------------------------------------
8 8 # Copyright (C) 2008-2009 The IPython Development Team
9 9 #
10 10 # Distributed under the terms of the BSD License. The full license is in
11 11 # the file COPYING, distributed as part of this software.
12 12 #-----------------------------------------------------------------------------
13 13
14 14 #-----------------------------------------------------------------------------
15 15 # Imports
16 16 #-----------------------------------------------------------------------------
17 17
18 18 from __future__ import with_statement
19 19
20 20 import os
21 21 import shutil
22 22 import sys
23 23 import warnings
24 24
25 25 from twisted.python import log
26 26
27 27 from IPython.config.loader import PyFileConfigLoader
28 28 from IPython.core.application import Application, BaseAppConfigLoader
29 from IPython.core.component import Component
29 from IPython.config.configurable import Configurable
30 30 from IPython.core.crashhandler import CrashHandler
31 31 from IPython.core import release
32 32 from IPython.utils.path import (
33 33 get_ipython_package_dir,
34 34 expand_path
35 35 )
36 36 from IPython.utils.traitlets import Unicode
37 37
38 38 #-----------------------------------------------------------------------------
39 39 # Warnings control
40 40 #-----------------------------------------------------------------------------
41 41 # Twisted generates annoying warnings with Python 2.6, as will do other code
42 42 # that imports 'sets' as of today
43 43 warnings.filterwarnings('ignore', 'the sets module is deprecated',
44 44 DeprecationWarning )
45 45
46 46 # This one also comes from Twisted
47 47 warnings.filterwarnings('ignore', 'the sha module is deprecated',
48 48 DeprecationWarning)
49 49
50 50 #-----------------------------------------------------------------------------
51 51 # Module errors
52 52 #-----------------------------------------------------------------------------
53 53
54 54 class ClusterDirError(Exception):
55 55 pass
56 56
57 57
58 58 class PIDFileError(Exception):
59 59 pass
60 60
61 61
62 62 #-----------------------------------------------------------------------------
63 63 # Class for managing cluster directories
64 64 #-----------------------------------------------------------------------------
65 65
66 class ClusterDir(Component):
66 class ClusterDir(Configurable):
67 67 """An object to manage the cluster directory and its resources.
68 68
69 69 The cluster directory is used by :command:`ipcontroller`,
70 70 :command:`ipcontroller` and :command:`ipcontroller` to manage the
71 71 configuration, logging and security of these applications.
72 72
73 73 This object knows how to find, create and manage these directories. This
74 74 should be used by any code that want's to handle cluster directories.
75 75 """
76 76
77 77 security_dir_name = Unicode('security')
78 78 log_dir_name = Unicode('log')
79 79 pid_dir_name = Unicode('pid')
80 80 security_dir = Unicode(u'')
81 81 log_dir = Unicode(u'')
82 82 pid_dir = Unicode(u'')
83 83 location = Unicode(u'')
84 84
85 def __init__(self, location):
86 super(ClusterDir, self).__init__(None)
87 self.location = location
85 def __init__(self, location=u''):
86 super(ClusterDir, self).__init__(location=location)
88 87
89 88 def _location_changed(self, name, old, new):
90 89 if not os.path.isdir(new):
91 90 os.makedirs(new)
92 91 self.security_dir = os.path.join(new, self.security_dir_name)
93 92 self.log_dir = os.path.join(new, self.log_dir_name)
94 93 self.pid_dir = os.path.join(new, self.pid_dir_name)
95 94 self.check_dirs()
96 95
97 96 def _log_dir_changed(self, name, old, new):
98 97 self.check_log_dir()
99 98
100 99 def check_log_dir(self):
101 100 if not os.path.isdir(self.log_dir):
102 101 os.mkdir(self.log_dir)
103 102
104 103 def _security_dir_changed(self, name, old, new):
105 104 self.check_security_dir()
106 105
107 106 def check_security_dir(self):
108 107 if not os.path.isdir(self.security_dir):
109 108 os.mkdir(self.security_dir, 0700)
110 109 os.chmod(self.security_dir, 0700)
111 110
112 111 def _pid_dir_changed(self, name, old, new):
113 112 self.check_pid_dir()
114 113
115 114 def check_pid_dir(self):
116 115 if not os.path.isdir(self.pid_dir):
117 116 os.mkdir(self.pid_dir, 0700)
118 117 os.chmod(self.pid_dir, 0700)
119 118
120 119 def check_dirs(self):
121 120 self.check_security_dir()
122 121 self.check_log_dir()
123 122 self.check_pid_dir()
124 123
125 124 def load_config_file(self, filename):
126 125 """Load a config file from the top level of the cluster dir.
127 126
128 127 Parameters
129 128 ----------
130 129 filename : unicode or str
131 130 The filename only of the config file that must be located in
132 131 the top-level of the cluster directory.
133 132 """
134 133 loader = PyFileConfigLoader(filename, self.location)
135 134 return loader.load_config()
136 135
137 136 def copy_config_file(self, config_file, path=None, overwrite=False):
138 137 """Copy a default config file into the active cluster directory.
139 138
140 139 Default configuration files are kept in :mod:`IPython.config.default`.
141 140 This function moves these from that location to the working cluster
142 141 directory.
143 142 """
144 143 if path is None:
145 144 import IPython.config.default
146 145 path = IPython.config.default.__file__.split(os.path.sep)[:-1]
147 146 path = os.path.sep.join(path)
148 147 src = os.path.join(path, config_file)
149 148 dst = os.path.join(self.location, config_file)
150 149 if not os.path.isfile(dst) or overwrite:
151 150 shutil.copy(src, dst)
152 151
153 152 def copy_all_config_files(self, path=None, overwrite=False):
154 153 """Copy all config files into the active cluster directory."""
155 154 for f in [u'ipcontroller_config.py', u'ipengine_config.py',
156 155 u'ipcluster_config.py']:
157 156 self.copy_config_file(f, path=path, overwrite=overwrite)
158 157
159 158 @classmethod
160 159 def create_cluster_dir(csl, cluster_dir):
161 160 """Create a new cluster directory given a full path.
162 161
163 162 Parameters
164 163 ----------
165 164 cluster_dir : str
166 165 The full path to the cluster directory. If it does exist, it will
167 166 be used. If not, it will be created.
168 167 """
169 return ClusterDir(cluster_dir)
168 return ClusterDir(location=cluster_dir)
170 169
171 170 @classmethod
172 171 def create_cluster_dir_by_profile(cls, path, profile=u'default'):
173 172 """Create a cluster dir by profile name and path.
174 173
175 174 Parameters
176 175 ----------
177 176 path : str
178 177 The path (directory) to put the cluster directory in.
179 178 profile : str
180 179 The name of the profile. The name of the cluster directory will
181 180 be "cluster_<profile>".
182 181 """
183 182 if not os.path.isdir(path):
184 183 raise ClusterDirError('Directory not found: %s' % path)
185 184 cluster_dir = os.path.join(path, u'cluster_' + profile)
186 return ClusterDir(cluster_dir)
185 return ClusterDir(location=cluster_dir)
187 186
188 187 @classmethod
189 188 def find_cluster_dir_by_profile(cls, ipython_dir, profile=u'default'):
190 189 """Find an existing cluster dir by profile name, return its ClusterDir.
191 190
192 191 This searches through a sequence of paths for a cluster dir. If it
193 192 is not found, a :class:`ClusterDirError` exception will be raised.
194 193
195 194 The search path algorithm is:
196 195 1. ``os.getcwd()``
197 196 2. ``ipython_dir``
198 197 3. The directories found in the ":" separated
199 198 :env:`IPCLUSTER_DIR_PATH` environment variable.
200 199
201 200 Parameters
202 201 ----------
203 202 ipython_dir : unicode or str
204 203 The IPython directory to use.
205 204 profile : unicode or str
206 205 The name of the profile. The name of the cluster directory
207 206 will be "cluster_<profile>".
208 207 """
209 208 dirname = u'cluster_' + profile
210 209 cluster_dir_paths = os.environ.get('IPCLUSTER_DIR_PATH','')
211 210 if cluster_dir_paths:
212 211 cluster_dir_paths = cluster_dir_paths.split(':')
213 212 else:
214 213 cluster_dir_paths = []
215 214 paths = [os.getcwd(), ipython_dir] + cluster_dir_paths
216 215 for p in paths:
217 216 cluster_dir = os.path.join(p, dirname)
218 217 if os.path.isdir(cluster_dir):
219 return ClusterDir(cluster_dir)
218 return ClusterDir(location=cluster_dir)
220 219 else:
221 220 raise ClusterDirError('Cluster directory not found in paths: %s' % dirname)
222 221
223 222 @classmethod
224 223 def find_cluster_dir(cls, cluster_dir):
225 224 """Find/create a cluster dir and return its ClusterDir.
226 225
227 226 This will create the cluster directory if it doesn't exist.
228 227
229 228 Parameters
230 229 ----------
231 230 cluster_dir : unicode or str
232 231 The path of the cluster directory. This is expanded using
233 232 :func:`IPython.utils.genutils.expand_path`.
234 233 """
235 234 cluster_dir = expand_path(cluster_dir)
236 235 if not os.path.isdir(cluster_dir):
237 236 raise ClusterDirError('Cluster directory not found: %s' % cluster_dir)
238 return ClusterDir(cluster_dir)
237 return ClusterDir(location=cluster_dir)
239 238
240 239
241 240 #-----------------------------------------------------------------------------
242 241 # Command line options
243 242 #-----------------------------------------------------------------------------
244 243
245 244 class ClusterDirConfigLoader(BaseAppConfigLoader):
246 245
247 246 def _add_cluster_profile(self, parser):
248 247 paa = parser.add_argument
249 248 paa('-p', '--profile',
250 249 dest='Global.profile',type=unicode,
251 250 help=
252 251 """The string name of the profile to be used. This determines the name
253 252 of the cluster dir as: cluster_<profile>. The default profile is named
254 253 'default'. The cluster directory is resolve this way if the
255 254 --cluster-dir option is not used.""",
256 255 metavar='Global.profile')
257 256
258 257 def _add_cluster_dir(self, parser):
259 258 paa = parser.add_argument
260 259 paa('--cluster-dir',
261 260 dest='Global.cluster_dir',type=unicode,
262 261 help="""Set the cluster dir. This overrides the logic used by the
263 262 --profile option.""",
264 263 metavar='Global.cluster_dir')
265 264
266 265 def _add_work_dir(self, parser):
267 266 paa = parser.add_argument
268 267 paa('--work-dir',
269 268 dest='Global.work_dir',type=unicode,
270 269 help='Set the working dir for the process.',
271 270 metavar='Global.work_dir')
272 271
273 272 def _add_clean_logs(self, parser):
274 273 paa = parser.add_argument
275 274 paa('--clean-logs',
276 275 dest='Global.clean_logs', action='store_true',
277 276 help='Delete old log flies before starting.')
278 277
279 278 def _add_no_clean_logs(self, parser):
280 279 paa = parser.add_argument
281 280 paa('--no-clean-logs',
282 281 dest='Global.clean_logs', action='store_false',
283 282 help="Don't Delete old log flies before starting.")
284 283
285 284 def _add_arguments(self):
286 285 super(ClusterDirConfigLoader, self)._add_arguments()
287 286 self._add_cluster_profile(self.parser)
288 287 self._add_cluster_dir(self.parser)
289 288 self._add_work_dir(self.parser)
290 289 self._add_clean_logs(self.parser)
291 290 self._add_no_clean_logs(self.parser)
292 291
293 292
294 293 #-----------------------------------------------------------------------------
295 294 # Crash handler for this application
296 295 #-----------------------------------------------------------------------------
297 296
298 297
299 298 _message_template = """\
300 299 Oops, $self.app_name crashed. We do our best to make it stable, but...
301 300
302 301 A crash report was automatically generated with the following information:
303 302 - A verbatim copy of the crash traceback.
304 303 - Data on your current $self.app_name configuration.
305 304
306 305 It was left in the file named:
307 306 \t'$self.crash_report_fname'
308 307 If you can email this file to the developers, the information in it will help
309 308 them in understanding and correcting the problem.
310 309
311 310 You can mail it to: $self.contact_name at $self.contact_email
312 311 with the subject '$self.app_name Crash Report'.
313 312
314 313 If you want to do it now, the following command will work (under Unix):
315 314 mail -s '$self.app_name Crash Report' $self.contact_email < $self.crash_report_fname
316 315
317 316 To ensure accurate tracking of this issue, please file a report about it at:
318 317 $self.bug_tracker
319 318 """
320 319
321 320 class ClusterDirCrashHandler(CrashHandler):
322 321 """sys.excepthook for IPython itself, leaves a detailed report on disk."""
323 322
324 323 message_template = _message_template
325 324
326 325 def __init__(self, app):
327 326 contact_name = release.authors['Brian'][0]
328 327 contact_email = release.authors['Brian'][1]
329 328 bug_tracker = 'https://bugs.launchpad.net/ipython/+filebug'
330 329 super(ClusterDirCrashHandler,self).__init__(
331 330 app, contact_name, contact_email, bug_tracker
332 331 )
333 332
334 333
335 334 #-----------------------------------------------------------------------------
336 335 # Main application
337 336 #-----------------------------------------------------------------------------
338 337
339 338 class ApplicationWithClusterDir(Application):
340 339 """An application that puts everything into a cluster directory.
341 340
342 341 Instead of looking for things in the ipython_dir, this type of application
343 342 will use its own private directory called the "cluster directory"
344 343 for things like config files, log files, etc.
345 344
346 345 The cluster directory is resolved as follows:
347 346
348 347 * If the ``--cluster-dir`` option is given, it is used.
349 348 * If ``--cluster-dir`` is not given, the application directory is
350 349 resolve using the profile name as ``cluster_<profile>``. The search
351 350 path for this directory is then i) cwd if it is found there
352 351 and ii) in ipython_dir otherwise.
353 352
354 353 The config file for the application is to be put in the cluster
355 354 dir and named the value of the ``config_file_name`` class attribute.
356 355 """
357 356
358 357 command_line_loader = ClusterDirConfigLoader
359 358 crash_handler_class = ClusterDirCrashHandler
360 359 auto_create_cluster_dir = True
361 360
362 361 def create_default_config(self):
363 362 super(ApplicationWithClusterDir, self).create_default_config()
364 363 self.default_config.Global.profile = u'default'
365 364 self.default_config.Global.cluster_dir = u''
366 365 self.default_config.Global.work_dir = os.getcwd()
367 366 self.default_config.Global.log_to_file = False
368 367 self.default_config.Global.clean_logs = False
369 368
370 369 def find_resources(self):
371 370 """This resolves the cluster directory.
372 371
373 372 This tries to find the cluster directory and if successful, it will
374 373 have done:
375 374 * Sets ``self.cluster_dir_obj`` to the :class:`ClusterDir` object for
376 375 the application.
377 376 * Sets ``self.cluster_dir`` attribute of the application and config
378 377 objects.
379 378
380 379 The algorithm used for this is as follows:
381 380 1. Try ``Global.cluster_dir``.
382 381 2. Try using ``Global.profile``.
383 382 3. If both of these fail and ``self.auto_create_cluster_dir`` is
384 383 ``True``, then create the new cluster dir in the IPython directory.
385 384 4. If all fails, then raise :class:`ClusterDirError`.
386 385 """
387 386
388 387 try:
389 388 cluster_dir = self.command_line_config.Global.cluster_dir
390 389 except AttributeError:
391 390 cluster_dir = self.default_config.Global.cluster_dir
392 391 cluster_dir = expand_path(cluster_dir)
393 392 try:
394 393 self.cluster_dir_obj = ClusterDir.find_cluster_dir(cluster_dir)
395 394 except ClusterDirError:
396 395 pass
397 396 else:
398 397 self.log.info('Using existing cluster dir: %s' % \
399 398 self.cluster_dir_obj.location
400 399 )
401 400 self.finish_cluster_dir()
402 401 return
403 402
404 403 try:
405 404 self.profile = self.command_line_config.Global.profile
406 405 except AttributeError:
407 406 self.profile = self.default_config.Global.profile
408 407 try:
409 408 self.cluster_dir_obj = ClusterDir.find_cluster_dir_by_profile(
410 409 self.ipython_dir, self.profile)
411 410 except ClusterDirError:
412 411 pass
413 412 else:
414 413 self.log.info('Using existing cluster dir: %s' % \
415 414 self.cluster_dir_obj.location
416 415 )
417 416 self.finish_cluster_dir()
418 417 return
419 418
420 419 if self.auto_create_cluster_dir:
421 420 self.cluster_dir_obj = ClusterDir.create_cluster_dir_by_profile(
422 421 self.ipython_dir, self.profile
423 422 )
424 423 self.log.info('Creating new cluster dir: %s' % \
425 424 self.cluster_dir_obj.location
426 425 )
427 426 self.finish_cluster_dir()
428 427 else:
429 428 raise ClusterDirError('Could not find a valid cluster directory.')
430 429
431 430 def finish_cluster_dir(self):
432 431 # Set the cluster directory
433 432 self.cluster_dir = self.cluster_dir_obj.location
434 433
435 434 # These have to be set because they could be different from the one
436 435 # that we just computed. Because command line has the highest
437 436 # priority, this will always end up in the master_config.
438 437 self.default_config.Global.cluster_dir = self.cluster_dir
439 438 self.command_line_config.Global.cluster_dir = self.cluster_dir
440 439
441 440 def find_config_file_name(self):
442 441 """Find the config file name for this application."""
443 442 # For this type of Application it should be set as a class attribute.
444 443 if not hasattr(self, 'default_config_file_name'):
445 444 self.log.critical("No config filename found")
446 445 else:
447 446 self.config_file_name = self.default_config_file_name
448 447
449 448 def find_config_file_paths(self):
450 449 # Set the search path to to the cluster directory. We should NOT
451 450 # include IPython.config.default here as the default config files
452 451 # are ALWAYS automatically moved to the cluster directory.
453 452 conf_dir = os.path.join(get_ipython_package_dir(), 'config', 'default')
454 453 self.config_file_paths = (self.cluster_dir,)
455 454
456 455 def pre_construct(self):
457 456 # The log and security dirs were set earlier, but here we put them
458 457 # into the config and log them.
459 458 config = self.master_config
460 459 sdir = self.cluster_dir_obj.security_dir
461 460 self.security_dir = config.Global.security_dir = sdir
462 461 ldir = self.cluster_dir_obj.log_dir
463 462 self.log_dir = config.Global.log_dir = ldir
464 463 pdir = self.cluster_dir_obj.pid_dir
465 464 self.pid_dir = config.Global.pid_dir = pdir
466 465 self.log.info("Cluster directory set to: %s" % self.cluster_dir)
467 466 config.Global.work_dir = unicode(expand_path(config.Global.work_dir))
468 467 # Change to the working directory. We do this just before construct
469 468 # is called so all the components there have the right working dir.
470 469 self.to_work_dir()
471 470
472 471 def to_work_dir(self):
473 472 wd = self.master_config.Global.work_dir
474 473 if unicode(wd) != unicode(os.getcwd()):
475 474 os.chdir(wd)
476 475 self.log.info("Changing to working dir: %s" % wd)
477 476
478 477 def start_logging(self):
479 478 # Remove old log files
480 479 if self.master_config.Global.clean_logs:
481 480 log_dir = self.master_config.Global.log_dir
482 481 for f in os.listdir(log_dir):
483 482 if f.startswith(self.name + u'-') and f.endswith('.log'):
484 483 os.remove(os.path.join(log_dir, f))
485 484 # Start logging to the new log file
486 485 if self.master_config.Global.log_to_file:
487 486 log_filename = self.name + u'-' + str(os.getpid()) + u'.log'
488 487 logfile = os.path.join(self.log_dir, log_filename)
489 488 open_log_file = open(logfile, 'w')
490 489 else:
491 490 open_log_file = sys.stdout
492 491 log.startLogging(open_log_file)
493 492
494 493 def write_pid_file(self, overwrite=False):
495 494 """Create a .pid file in the pid_dir with my pid.
496 495
497 496 This must be called after pre_construct, which sets `self.pid_dir`.
498 497 This raises :exc:`PIDFileError` if the pid file exists already.
499 498 """
500 499 pid_file = os.path.join(self.pid_dir, self.name + u'.pid')
501 500 if os.path.isfile(pid_file):
502 501 pid = self.get_pid_from_file()
503 502 if not overwrite:
504 503 raise PIDFileError(
505 504 'The pid file [%s] already exists. \nThis could mean that this '
506 505 'server is already running with [pid=%s].' % (pid_file, pid)
507 506 )
508 507 with open(pid_file, 'w') as f:
509 508 self.log.info("Creating pid file: %s" % pid_file)
510 509 f.write(repr(os.getpid())+'\n')
511 510
512 511 def remove_pid_file(self):
513 512 """Remove the pid file.
514 513
515 514 This should be called at shutdown by registering a callback with
516 515 :func:`reactor.addSystemEventTrigger`. This needs to return
517 516 ``None``.
518 517 """
519 518 pid_file = os.path.join(self.pid_dir, self.name + u'.pid')
520 519 if os.path.isfile(pid_file):
521 520 try:
522 521 self.log.info("Removing pid file: %s" % pid_file)
523 522 os.remove(pid_file)
524 523 except:
525 524 self.log.warn("Error removing the pid file: %s" % pid_file)
526 525
527 526 def get_pid_from_file(self):
528 527 """Get the pid from the pid file.
529 528
530 529 If the pid file doesn't exist a :exc:`PIDFileError` is raised.
531 530 """
532 531 pid_file = os.path.join(self.pid_dir, self.name + u'.pid')
533 532 if os.path.isfile(pid_file):
534 533 with open(pid_file, 'r') as f:
535 534 pid = int(f.read().strip())
536 535 return pid
537 536 else:
538 537 raise PIDFileError('pid file not found: %s' % pid_file)
539 538
@@ -1,79 +1,79 b''
1 1 #!/usr/bin/env python
2 2 # encoding: utf-8
3 3 """
4 4 A class for creating a Twisted service that is configured using IPython's
5 5 configuration system.
6 6 """
7 7
8 8 #-----------------------------------------------------------------------------
9 9 # Copyright (C) 2008-2009 The IPython Development Team
10 10 #
11 11 # Distributed under the terms of the BSD License. The full license is in
12 12 # the file COPYING, distributed as part of this software.
13 13 #-----------------------------------------------------------------------------
14 14
15 15 #-----------------------------------------------------------------------------
16 16 # Imports
17 17 #-----------------------------------------------------------------------------
18 18
19 19 import zope.interface as zi
20 20
21 from IPython.core.component import Component
21 from IPython.config.configurable import Configurable
22 22
23 23 #-----------------------------------------------------------------------------
24 24 # Code
25 25 #-----------------------------------------------------------------------------
26 26
27 27
28 28 class IConfiguredObjectFactory(zi.Interface):
29 29 """I am a component that creates a configured object.
30 30
31 31 This class is useful if you want to configure a class that is not a
32 subclass of :class:`IPython.core.component.Component`.
32 subclass of :class:`IPython.config.configurable.Configurable`.
33 33 """
34 34
35 35 def __init__(config):
36 36 """Get ready to configure the object using config."""
37 37
38 38 def create():
39 39 """Return an instance of the configured object."""
40 40
41 41
42 class ConfiguredObjectFactory(Component):
42 class ConfiguredObjectFactory(Configurable):
43 43
44 44 zi.implements(IConfiguredObjectFactory)
45 45
46 def __init__(self, config):
47 super(ConfiguredObjectFactory, self).__init__(None, config=config)
46 def __init__(self, config=None):
47 super(ConfiguredObjectFactory, self).__init__(config=config)
48 48
49 49 def create(self):
50 50 raise NotImplementedError('create must be implemented in a subclass')
51 51
52 52
53 53 class IAdaptedConfiguredObjectFactory(zi.Interface):
54 54 """I am a component that adapts and configures an object.
55 55
56 56 This class is useful if you have the adapt an instance and configure it.
57 57 """
58 58
59 def __init__(config, adaptee=None):
59 def __init__(config=None, adaptee=None):
60 60 """Get ready to adapt adaptee and then configure it using config."""
61 61
62 62 def create():
63 63 """Return an instance of the adapted and configured object."""
64 64
65 65
66 class AdaptedConfiguredObjectFactory(Component):
66 class AdaptedConfiguredObjectFactory(Configurable):
67 67
68 68 # zi.implements(IAdaptedConfiguredObjectFactory)
69 69
70 def __init__(self, config, adaptee):
70 def __init__(self, config=None, adaptee=None):
71 71 # print
72 72 # print "config pre:", config
73 super(AdaptedConfiguredObjectFactory, self).__init__(None, config=config)
73 super(AdaptedConfiguredObjectFactory, self).__init__(config=config)
74 74 # print
75 75 # print "config post:", config
76 76 self.adaptee = adaptee
77 77
78 78 def create(self):
79 raise NotImplementedError('create must be implemented in a subclass') No newline at end of file
79 raise NotImplementedError('create must be implemented in a subclass')
@@ -1,296 +1,296 b''
1 1 #!/usr/bin/env python
2 2 # encoding: utf-8
3 3 """
4 4 Foolscap related utilities.
5 5 """
6 6
7 7 #-----------------------------------------------------------------------------
8 8 # Copyright (C) 2008-2009 The IPython Development Team
9 9 #
10 10 # Distributed under the terms of the BSD License. The full license is in
11 11 # the file COPYING, distributed as part of this software.
12 12 #-----------------------------------------------------------------------------
13 13
14 14 #-----------------------------------------------------------------------------
15 15 # Imports
16 16 #-----------------------------------------------------------------------------
17 17
18 18 from __future__ import with_statement
19 19
20 20 import os
21 21 import tempfile
22 22
23 23 from twisted.internet import reactor, defer
24 24 from twisted.python import log
25 25
26 26 import foolscap
27 27 try:
28 28 from foolscap.api import Tub, UnauthenticatedTub
29 29 except ImportError:
30 30 from foolscap import Tub, UnauthenticatedTub
31 31
32 32 from IPython.config.loader import Config
33 33 from IPython.kernel.configobjfactory import AdaptedConfiguredObjectFactory
34 34 from IPython.kernel.error import SecurityError
35 35
36 36 from IPython.utils.importstring import import_item
37 37 from IPython.utils.path import expand_path
38 38 from IPython.utils.traitlets import Int, Str, Bool, Instance
39 39
40 40 #-----------------------------------------------------------------------------
41 41 # Code
42 42 #-----------------------------------------------------------------------------
43 43
44 44
45 45 # We do this so if a user doesn't have OpenSSL installed, it will try to use
46 46 # an UnauthenticatedTub. But, they will still run into problems if they
47 47 # try to use encrypted furls.
48 48 try:
49 49 import OpenSSL
50 50 except:
51 51 Tub = UnauthenticatedTub
52 52 have_crypto = False
53 53 else:
54 54 have_crypto = True
55 55
56 56
57 57 class FURLError(Exception):
58 58 pass
59 59
60 60
61 61 def check_furl_file_security(furl_file, secure):
62 62 """Remove the old furl_file if changing security modes."""
63 63 furl_file = expand_path(furl_file)
64 64 if os.path.isfile(furl_file):
65 65 with open(furl_file, 'r') as f:
66 66 oldfurl = f.read().strip()
67 67 if (oldfurl.startswith('pb://') and not secure) or (oldfurl.startswith('pbu://') and secure):
68 68 os.remove(furl_file)
69 69
70 70
71 71 def is_secure(furl):
72 72 """Is the given FURL secure or not."""
73 73 if is_valid_furl(furl):
74 74 if furl.startswith("pb://"):
75 75 return True
76 76 elif furl.startswith("pbu://"):
77 77 return False
78 78 else:
79 79 raise FURLError("invalid FURL: %s" % furl)
80 80
81 81
82 82 def is_valid_furl(furl):
83 83 """Is the str a valid FURL or not."""
84 84 if isinstance(furl, str):
85 85 if furl.startswith("pb://") or furl.startswith("pbu://"):
86 86 return True
87 87 else:
88 88 return False
89 89 else:
90 90 return False
91 91
92 92
93 93 def is_valid_furl_file(furl_or_file):
94 94 """See if furl_or_file exists and contains a valid FURL.
95 95
96 96 This doesn't try to read the contents because often we have to validate
97 97 FURL files that are created, but don't yet have a FURL written to them.
98 98 """
99 99 if isinstance(furl_or_file, (str, unicode)):
100 100 path, furl_filename = os.path.split(furl_or_file)
101 101 if os.path.isdir(path) and furl_filename.endswith('.furl'):
102 102 return True
103 103 return False
104 104
105 105
106 106 def find_furl(furl_or_file):
107 107 """Find, validate and return a FURL in a string or file.
108 108
109 109 This calls :func:`IPython.utils.path.expand_path` on the argument to
110 110 properly handle ``~`` and ``$`` variables in the path.
111 111 """
112 112 if is_valid_furl(furl_or_file):
113 113 return furl_or_file
114 114 furl_or_file = expand_path(furl_or_file)
115 115 if is_valid_furl_file(furl_or_file):
116 116 with open(furl_or_file, 'r') as f:
117 117 furl = f.read().strip()
118 118 if is_valid_furl(furl):
119 119 return furl
120 120 raise FURLError("Not a valid FURL or FURL file: %r" % furl_or_file)
121 121
122 122
123 123 def is_valid_furl_or_file(furl_or_file):
124 124 """Validate a FURL or a FURL file.
125 125
126 126 If ``furl_or_file`` looks like a file, we simply make sure its directory
127 127 exists and that it has a ``.furl`` file extension. We don't try to see
128 128 if the FURL file exists or to read its contents. This is useful for
129 129 cases where auto re-connection is being used.
130 130 """
131 131 if is_valid_furl(furl_or_file) or is_valid_furl_file(furl_or_file):
132 132 return True
133 133 else:
134 134 return False
135 135
136 136
137 137 def validate_furl_or_file(furl_or_file):
138 138 """Like :func:`is_valid_furl_or_file`, but raises an error."""
139 139 if not is_valid_furl_or_file(furl_or_file):
140 140 raise FURLError('Not a valid FURL or FURL file: %r' % furl_or_file)
141 141
142 142
143 143 def get_temp_furlfile(filename):
144 144 """Return a temporary FURL file."""
145 145 return tempfile.mktemp(dir=os.path.dirname(filename),
146 146 prefix=os.path.basename(filename))
147 147
148 148
149 149 def make_tub(ip, port, secure, cert_file):
150 150 """Create a listening tub given an ip, port, and cert_file location.
151 151
152 152 Parameters
153 153 ----------
154 154 ip : str
155 155 The ip address or hostname that the tub should listen on.
156 156 Empty means all interfaces.
157 157 port : int
158 158 The port that the tub should listen on. A value of 0 means
159 159 pick a random port
160 160 secure: bool
161 161 Will the connection be secure (in the Foolscap sense).
162 162 cert_file: str
163 163 A filename of a file to be used for theSSL certificate.
164 164
165 165 Returns
166 166 -------
167 167 A tub, listener tuple.
168 168 """
169 169 if secure:
170 170 if have_crypto:
171 171 tub = Tub(certFile=cert_file)
172 172 else:
173 173 raise SecurityError("OpenSSL/pyOpenSSL is not available, so we "
174 174 "can't run in secure mode. Try running without "
175 175 "security using 'ipcontroller -xy'.")
176 176 else:
177 177 tub = UnauthenticatedTub()
178 178
179 179 # Set the strport based on the ip and port and start listening
180 180 if ip == '':
181 181 strport = "tcp:%i" % port
182 182 else:
183 183 strport = "tcp:%i:interface=%s" % (port, ip)
184 184 log.msg("Starting listener with [secure=%r] on: %s" % (secure, strport))
185 185 listener = tub.listenOn(strport)
186 186
187 187 return tub, listener
188 188
189 189
190 190 class FCServiceFactory(AdaptedConfiguredObjectFactory):
191 191 """This class creates a tub with various services running in it.
192 192
193 193 The basic idea is that :meth:`create` returns a running :class:`Tub`
194 instance that has a number of Foolscap references registered in it.
195 This class is a subclass of :class:`IPython.core.component.Component`
196 so the IPython configuration and component system are used.
194 instance that has a number of Foolscap references registered in it. This
195 class is a subclass of :class:`IPython.config.configurable.Configurable`
196 so the IPython configuration system is used.
197 197
198 198 Attributes
199 199 ----------
200 200 interfaces : Config
201 201 A Config instance whose values are sub-Config objects having two
202 202 keys: furl_file and interface_chain.
203 203
204 204 The other attributes are the standard ones for Foolscap.
205 205 """
206 206
207 207 ip = Str('', config=True)
208 208 port = Int(0, config=True)
209 209 secure = Bool(True, config=True)
210 210 cert_file = Str('', config=True)
211 211 location = Str('', config=True)
212 212 reuse_furls = Bool(False, config=True)
213 213 interfaces = Instance(klass=Config, kw={}, allow_none=False, config=True)
214 214
215 215 def __init__(self, config, adaptee):
216 216 super(FCServiceFactory, self).__init__(config, adaptee)
217 217 self._check_reuse_furls()
218 218
219 219 def _ip_changed(self, name, old, new):
220 220 if new == 'localhost' or new == '127.0.0.1':
221 221 self.location = '127.0.0.1'
222 222
223 223 def _check_reuse_furls(self):
224 224 furl_files = [i.furl_file for i in self.interfaces.values()]
225 225 for ff in furl_files:
226 226 fullfile = self._get_security_file(ff)
227 227 if self.reuse_furls:
228 228 if self.port==0:
229 229 raise FURLError("You are trying to reuse the FURL file "
230 230 "for this connection, but the port for this connection "
231 231 "is set to 0 (autoselect). To reuse the FURL file "
232 232 "you need to specify specific port to listen on."
233 233 )
234 234 else:
235 235 log.msg("Reusing FURL file: %s" % fullfile)
236 236 else:
237 237 if os.path.isfile(fullfile):
238 238 log.msg("Removing old FURL file: %s" % fullfile)
239 239 os.remove(fullfile)
240 240
241 241 def _get_security_file(self, filename):
242 242 return os.path.join(self.config.Global.security_dir, filename)
243 243
244 244 def create(self):
245 245 """Create and return the Foolscap tub with everything running."""
246 246
247 247 self.tub, self.listener = make_tub(
248 248 self.ip, self.port, self.secure,
249 249 self._get_security_file(self.cert_file)
250 250 )
251 251 # log.msg("Interfaces to register [%r]: %r" % \
252 252 # (self.__class__, self.interfaces))
253 253 if not self.secure:
254 254 log.msg("WARNING: running with no security: %s" % \
255 255 self.__class__.__name__)
256 256 reactor.callWhenRunning(self.set_location_and_register)
257 257 return self.tub
258 258
259 259 def set_location_and_register(self):
260 260 """Set the location for the tub and return a deferred."""
261 261
262 262 if self.location == '':
263 263 d = self.tub.setLocationAutomatically()
264 264 else:
265 265 d = defer.maybeDeferred(self.tub.setLocation,
266 266 "%s:%i" % (self.location, self.listener.getPortnum()))
267 267 self.adapt_to_interfaces(d)
268 268
269 269 def adapt_to_interfaces(self, d):
270 270 """Run through the interfaces, adapt and register."""
271 271
272 272 for ifname, ifconfig in self.interfaces.iteritems():
273 273 ff = self._get_security_file(ifconfig.furl_file)
274 274 log.msg("Adapting [%s] to interface: %s" % \
275 275 (self.adaptee.__class__.__name__, ifname))
276 276 log.msg("Saving FURL for interface [%s] to file: %s" % (ifname, ff))
277 277 check_furl_file_security(ff, self.secure)
278 278 adaptee = self.adaptee
279 279 for i in ifconfig.interface_chain:
280 280 adaptee = import_item(i)(adaptee)
281 281 d.addCallback(self.register, adaptee, furl_file=ff)
282 282
283 283 def register(self, empty, ref, furl_file):
284 284 """Register the reference with the FURL file.
285 285
286 286 The FURL file is created and then moved to make sure that when the
287 287 file appears, the buffer has been flushed and the file closed. This
288 288 is not done if we are re-using FURLS however.
289 289 """
290 290 if self.reuse_furls:
291 291 self.tub.registerReference(ref, furlFile=furl_file)
292 292 else:
293 293 temp_furl_file = get_temp_furlfile(furl_file)
294 294 self.tub.registerReference(ref, furlFile=temp_furl_file)
295 295 os.rename(temp_furl_file, furl_file)
296 296
@@ -1,835 +1,834 b''
1 1 #!/usr/bin/env python
2 2 # encoding: utf-8
3 3 """
4 4 Facilities for launching IPython processes asynchronously.
5 5 """
6 6
7 7 #-----------------------------------------------------------------------------
8 8 # Copyright (C) 2008-2009 The IPython Development Team
9 9 #
10 10 # Distributed under the terms of the BSD License. The full license is in
11 11 # the file COPYING, distributed as part of this software.
12 12 #-----------------------------------------------------------------------------
13 13
14 14 #-----------------------------------------------------------------------------
15 15 # Imports
16 16 #-----------------------------------------------------------------------------
17 17
18 18 import os
19 19 import re
20 20 import sys
21 21
22 from IPython.core.component import Component
22 from IPython.config.configurable import Configurable
23 23 from IPython.external import Itpl
24 24 from IPython.utils.traitlets import Str, Int, List, Unicode
25 25 from IPython.utils.path import get_ipython_module_path
26 26 from IPython.utils.process import find_cmd, pycmd2argv, FindCmdError
27 27 from IPython.kernel.twistedutil import (
28 28 gatherBoth,
29 29 make_deferred,
30 30 sleep_deferred
31 31 )
32 32 from IPython.kernel.winhpcjob import (
33 33 IPControllerTask, IPEngineTask,
34 34 IPControllerJob, IPEngineSetJob
35 35 )
36 36
37 37 from twisted.internet import reactor, defer
38 38 from twisted.internet.defer import inlineCallbacks
39 39 from twisted.internet.protocol import ProcessProtocol
40 40 from twisted.internet.utils import getProcessOutput
41 41 from twisted.internet.error import ProcessDone, ProcessTerminated
42 42 from twisted.python import log
43 43 from twisted.python.failure import Failure
44 44
45 45
46 46 #-----------------------------------------------------------------------------
47 47 # Paths to the kernel apps
48 48 #-----------------------------------------------------------------------------
49 49
50 50
51 51 ipcluster_cmd_argv = pycmd2argv(get_ipython_module_path(
52 52 'IPython.kernel.ipclusterapp'
53 53 ))
54 54
55 55 ipengine_cmd_argv = pycmd2argv(get_ipython_module_path(
56 56 'IPython.kernel.ipengineapp'
57 57 ))
58 58
59 59 ipcontroller_cmd_argv = pycmd2argv(get_ipython_module_path(
60 60 'IPython.kernel.ipcontrollerapp'
61 61 ))
62 62
63 63 #-----------------------------------------------------------------------------
64 64 # Base launchers and errors
65 65 #-----------------------------------------------------------------------------
66 66
67 67
68 68 class LauncherError(Exception):
69 69 pass
70 70
71 71
72 72 class ProcessStateError(LauncherError):
73 73 pass
74 74
75 75
76 76 class UnknownStatus(LauncherError):
77 77 pass
78 78
79 79
80 class BaseLauncher(Component):
80 class BaseLauncher(Configurable):
81 81 """An asbtraction for starting, stopping and signaling a process."""
82 82
83 83 # In all of the launchers, the work_dir is where child processes will be
84 84 # run. This will usually be the cluster_dir, but may not be. any work_dir
85 85 # passed into the __init__ method will override the config value.
86 86 # This should not be used to set the work_dir for the actual engine
87 87 # and controller. Instead, use their own config files or the
88 88 # controller_args, engine_args attributes of the launchers to add
89 89 # the --work-dir option.
90 90 work_dir = Unicode(u'')
91 91
92 def __init__(self, work_dir, parent=None, name=None, config=None):
93 super(BaseLauncher, self).__init__(parent, name, config)
94 self.work_dir = work_dir
92 def __init__(self, work_dir=u'', config=None):
93 super(BaseLauncher, self).__init__(work_dir=work_dir, config=config)
95 94 self.state = 'before' # can be before, running, after
96 95 self.stop_deferreds = []
97 96 self.start_data = None
98 97 self.stop_data = None
99 98
100 99 @property
101 100 def args(self):
102 101 """A list of cmd and args that will be used to start the process.
103 102
104 103 This is what is passed to :func:`spawnProcess` and the first element
105 104 will be the process name.
106 105 """
107 106 return self.find_args()
108 107
109 108 def find_args(self):
110 109 """The ``.args`` property calls this to find the args list.
111 110
112 111 Subcommand should implement this to construct the cmd and args.
113 112 """
114 113 raise NotImplementedError('find_args must be implemented in a subclass')
115 114
116 115 @property
117 116 def arg_str(self):
118 117 """The string form of the program arguments."""
119 118 return ' '.join(self.args)
120 119
121 120 @property
122 121 def running(self):
123 122 """Am I running."""
124 123 if self.state == 'running':
125 124 return True
126 125 else:
127 126 return False
128 127
129 128 def start(self):
130 129 """Start the process.
131 130
132 131 This must return a deferred that fires with information about the
133 132 process starting (like a pid, job id, etc.).
134 133 """
135 134 return defer.fail(
136 135 Failure(NotImplementedError(
137 136 'start must be implemented in a subclass')
138 137 )
139 138 )
140 139
141 140 def stop(self):
142 141 """Stop the process and notify observers of stopping.
143 142
144 143 This must return a deferred that fires with information about the
145 144 processing stopping, like errors that occur while the process is
146 145 attempting to be shut down. This deferred won't fire when the process
147 146 actually stops. To observe the actual process stopping, see
148 147 :func:`observe_stop`.
149 148 """
150 149 return defer.fail(
151 150 Failure(NotImplementedError(
152 151 'stop must be implemented in a subclass')
153 152 )
154 153 )
155 154
156 155 def observe_stop(self):
157 156 """Get a deferred that will fire when the process stops.
158 157
159 158 The deferred will fire with data that contains information about
160 159 the exit status of the process.
161 160 """
162 161 if self.state=='after':
163 162 return defer.succeed(self.stop_data)
164 163 else:
165 164 d = defer.Deferred()
166 165 self.stop_deferreds.append(d)
167 166 return d
168 167
169 168 def notify_start(self, data):
170 169 """Call this to trigger startup actions.
171 170
172 171 This logs the process startup and sets the state to 'running'. It is
173 172 a pass-through so it can be used as a callback.
174 173 """
175 174
176 175 log.msg('Process %r started: %r' % (self.args[0], data))
177 176 self.start_data = data
178 177 self.state = 'running'
179 178 return data
180 179
181 180 def notify_stop(self, data):
182 181 """Call this to trigger process stop actions.
183 182
184 183 This logs the process stopping and sets the state to 'after'. Call
185 184 this to trigger all the deferreds from :func:`observe_stop`."""
186 185
187 186 log.msg('Process %r stopped: %r' % (self.args[0], data))
188 187 self.stop_data = data
189 188 self.state = 'after'
190 189 for i in range(len(self.stop_deferreds)):
191 190 d = self.stop_deferreds.pop()
192 191 d.callback(data)
193 192 return data
194 193
195 194 def signal(self, sig):
196 195 """Signal the process.
197 196
198 197 Return a semi-meaningless deferred after signaling the process.
199 198
200 199 Parameters
201 200 ----------
202 201 sig : str or int
203 202 'KILL', 'INT', etc., or any signal number
204 203 """
205 204 return defer.fail(
206 205 Failure(NotImplementedError(
207 206 'signal must be implemented in a subclass')
208 207 )
209 208 )
210 209
211 210
212 211 #-----------------------------------------------------------------------------
213 212 # Local process launchers
214 213 #-----------------------------------------------------------------------------
215 214
216 215
217 216 class LocalProcessLauncherProtocol(ProcessProtocol):
218 217 """A ProcessProtocol to go with the LocalProcessLauncher."""
219 218
220 219 def __init__(self, process_launcher):
221 220 self.process_launcher = process_launcher
222 221 self.pid = None
223 222
224 223 def connectionMade(self):
225 224 self.pid = self.transport.pid
226 225 self.process_launcher.notify_start(self.transport.pid)
227 226
228 227 def processEnded(self, status):
229 228 value = status.value
230 229 if isinstance(value, ProcessDone):
231 230 self.process_launcher.notify_stop(
232 231 {'exit_code':0,
233 232 'signal':None,
234 233 'status':None,
235 234 'pid':self.pid
236 235 }
237 236 )
238 237 elif isinstance(value, ProcessTerminated):
239 238 self.process_launcher.notify_stop(
240 239 {'exit_code':value.exitCode,
241 240 'signal':value.signal,
242 241 'status':value.status,
243 242 'pid':self.pid
244 243 }
245 244 )
246 245 else:
247 246 raise UnknownStatus("Unknown exit status, this is probably a "
248 247 "bug in Twisted")
249 248
250 249 def outReceived(self, data):
251 250 log.msg(data)
252 251
253 252 def errReceived(self, data):
254 253 log.err(data)
255 254
256 255
257 256 class LocalProcessLauncher(BaseLauncher):
258 257 """Start and stop an external process in an asynchronous manner.
259 258
260 259 This will launch the external process with a working directory of
261 260 ``self.work_dir``.
262 261 """
263 262
264 263 # This is used to to construct self.args, which is passed to
265 264 # spawnProcess.
266 265 cmd_and_args = List([])
267 266
268 def __init__(self, work_dir, parent=None, name=None, config=None):
267 def __init__(self, work_dir=u'', config=None):
269 268 super(LocalProcessLauncher, self).__init__(
270 work_dir, parent, name, config
269 work_dir=work_dir, config=config
271 270 )
272 271 self.process_protocol = None
273 272 self.start_deferred = None
274 273
275 274 def find_args(self):
276 275 return self.cmd_and_args
277 276
278 277 def start(self):
279 278 if self.state == 'before':
280 279 self.process_protocol = LocalProcessLauncherProtocol(self)
281 280 self.start_deferred = defer.Deferred()
282 281 self.process_transport = reactor.spawnProcess(
283 282 self.process_protocol,
284 283 str(self.args[0]), # twisted expects these to be str, not unicode
285 284 [str(a) for a in self.args], # str expected, not unicode
286 285 env=os.environ,
287 286 path=self.work_dir # start in the work_dir
288 287 )
289 288 return self.start_deferred
290 289 else:
291 290 s = 'The process was already started and has state: %r' % self.state
292 291 return defer.fail(ProcessStateError(s))
293 292
294 293 def notify_start(self, data):
295 294 super(LocalProcessLauncher, self).notify_start(data)
296 295 self.start_deferred.callback(data)
297 296
298 297 def stop(self):
299 298 return self.interrupt_then_kill()
300 299
301 300 @make_deferred
302 301 def signal(self, sig):
303 302 if self.state == 'running':
304 303 self.process_transport.signalProcess(sig)
305 304
306 305 @inlineCallbacks
307 306 def interrupt_then_kill(self, delay=2.0):
308 307 """Send INT, wait a delay and then send KILL."""
309 308 yield self.signal('INT')
310 309 yield sleep_deferred(delay)
311 310 yield self.signal('KILL')
312 311
313 312
314 313 class LocalControllerLauncher(LocalProcessLauncher):
315 314 """Launch a controller as a regular external process."""
316 315
317 316 controller_cmd = List(ipcontroller_cmd_argv, config=True)
318 317 # Command line arguments to ipcontroller.
319 318 controller_args = List(['--log-to-file','--log-level', '40'], config=True)
320 319
321 320 def find_args(self):
322 321 return self.controller_cmd + self.controller_args
323 322
324 323 def start(self, cluster_dir):
325 324 """Start the controller by cluster_dir."""
326 325 self.controller_args.extend(['--cluster-dir', cluster_dir])
327 326 self.cluster_dir = unicode(cluster_dir)
328 327 log.msg("Starting LocalControllerLauncher: %r" % self.args)
329 328 return super(LocalControllerLauncher, self).start()
330 329
331 330
332 331 class LocalEngineLauncher(LocalProcessLauncher):
333 332 """Launch a single engine as a regular externall process."""
334 333
335 334 engine_cmd = List(ipengine_cmd_argv, config=True)
336 335 # Command line arguments for ipengine.
337 336 engine_args = List(
338 337 ['--log-to-file','--log-level', '40'], config=True
339 338 )
340 339
341 340 def find_args(self):
342 341 return self.engine_cmd + self.engine_args
343 342
344 343 def start(self, cluster_dir):
345 344 """Start the engine by cluster_dir."""
346 345 self.engine_args.extend(['--cluster-dir', cluster_dir])
347 346 self.cluster_dir = unicode(cluster_dir)
348 347 return super(LocalEngineLauncher, self).start()
349 348
350 349
351 350 class LocalEngineSetLauncher(BaseLauncher):
352 351 """Launch a set of engines as regular external processes."""
353 352
354 353 # Command line arguments for ipengine.
355 354 engine_args = List(
356 355 ['--log-to-file','--log-level', '40'], config=True
357 356 )
358 357
359 def __init__(self, work_dir, parent=None, name=None, config=None):
358 def __init__(self, work_dir=u'', config=None):
360 359 super(LocalEngineSetLauncher, self).__init__(
361 work_dir, parent, name, config
360 work_dir=work_dir, config=config
362 361 )
363 362 self.launchers = []
364 363
365 364 def start(self, n, cluster_dir):
366 365 """Start n engines by profile or cluster_dir."""
367 366 self.cluster_dir = unicode(cluster_dir)
368 367 dlist = []
369 368 for i in range(n):
370 el = LocalEngineLauncher(self.work_dir, self)
369 el = LocalEngineLauncher(work_dir=self.work_dir, config=self.config)
371 370 # Copy the engine args over to each engine launcher.
372 371 import copy
373 372 el.engine_args = copy.deepcopy(self.engine_args)
374 373 d = el.start(cluster_dir)
375 374 if i==0:
376 375 log.msg("Starting LocalEngineSetLauncher: %r" % el.args)
377 376 self.launchers.append(el)
378 377 dlist.append(d)
379 378 # The consumeErrors here could be dangerous
380 379 dfinal = gatherBoth(dlist, consumeErrors=True)
381 380 dfinal.addCallback(self.notify_start)
382 381 return dfinal
383 382
384 383 def find_args(self):
385 384 return ['engine set']
386 385
387 386 def signal(self, sig):
388 387 dlist = []
389 388 for el in self.launchers:
390 389 d = el.signal(sig)
391 390 dlist.append(d)
392 391 dfinal = gatherBoth(dlist, consumeErrors=True)
393 392 return dfinal
394 393
395 394 def interrupt_then_kill(self, delay=1.0):
396 395 dlist = []
397 396 for el in self.launchers:
398 397 d = el.interrupt_then_kill(delay)
399 398 dlist.append(d)
400 399 dfinal = gatherBoth(dlist, consumeErrors=True)
401 400 return dfinal
402 401
403 402 def stop(self):
404 403 return self.interrupt_then_kill()
405 404
406 405 def observe_stop(self):
407 406 dlist = [el.observe_stop() for el in self.launchers]
408 407 dfinal = gatherBoth(dlist, consumeErrors=False)
409 408 dfinal.addCallback(self.notify_stop)
410 409 return dfinal
411 410
412 411
413 412 #-----------------------------------------------------------------------------
414 413 # MPIExec launchers
415 414 #-----------------------------------------------------------------------------
416 415
417 416
418 417 class MPIExecLauncher(LocalProcessLauncher):
419 418 """Launch an external process using mpiexec."""
420 419
421 420 # The mpiexec command to use in starting the process.
422 421 mpi_cmd = List(['mpiexec'], config=True)
423 422 # The command line arguments to pass to mpiexec.
424 423 mpi_args = List([], config=True)
425 424 # The program to start using mpiexec.
426 425 program = List(['date'], config=True)
427 426 # The command line argument to the program.
428 427 program_args = List([], config=True)
429 428 # The number of instances of the program to start.
430 429 n = Int(1, config=True)
431 430
432 431 def find_args(self):
433 432 """Build self.args using all the fields."""
434 433 return self.mpi_cmd + ['-n', self.n] + self.mpi_args + \
435 434 self.program + self.program_args
436 435
437 436 def start(self, n):
438 437 """Start n instances of the program using mpiexec."""
439 438 self.n = n
440 439 return super(MPIExecLauncher, self).start()
441 440
442 441
443 442 class MPIExecControllerLauncher(MPIExecLauncher):
444 443 """Launch a controller using mpiexec."""
445 444
446 445 controller_cmd = List(ipcontroller_cmd_argv, config=True)
447 446 # Command line arguments to ipcontroller.
448 447 controller_args = List(['--log-to-file','--log-level', '40'], config=True)
449 448 n = Int(1, config=False)
450 449
451 450 def start(self, cluster_dir):
452 451 """Start the controller by cluster_dir."""
453 452 self.controller_args.extend(['--cluster-dir', cluster_dir])
454 453 self.cluster_dir = unicode(cluster_dir)
455 454 log.msg("Starting MPIExecControllerLauncher: %r" % self.args)
456 455 return super(MPIExecControllerLauncher, self).start(1)
457 456
458 457 def find_args(self):
459 458 return self.mpi_cmd + ['-n', self.n] + self.mpi_args + \
460 459 self.controller_cmd + self.controller_args
461 460
462 461
463 462 class MPIExecEngineSetLauncher(MPIExecLauncher):
464 463
465 464 engine_cmd = List(ipengine_cmd_argv, config=True)
466 465 # Command line arguments for ipengine.
467 466 engine_args = List(
468 467 ['--log-to-file','--log-level', '40'], config=True
469 468 )
470 469 n = Int(1, config=True)
471 470
472 471 def start(self, n, cluster_dir):
473 472 """Start n engines by profile or cluster_dir."""
474 473 self.engine_args.extend(['--cluster-dir', cluster_dir])
475 474 self.cluster_dir = unicode(cluster_dir)
476 475 self.n = n
477 476 log.msg('Starting MPIExecEngineSetLauncher: %r' % self.args)
478 477 return super(MPIExecEngineSetLauncher, self).start(n)
479 478
480 479 def find_args(self):
481 480 return self.mpi_cmd + ['-n', self.n] + self.mpi_args + \
482 481 self.engine_cmd + self.engine_args
483 482
484 483
485 484 #-----------------------------------------------------------------------------
486 485 # SSH launchers
487 486 #-----------------------------------------------------------------------------
488 487
489 488 # TODO: Get SSH Launcher working again.
490 489
491 490 class SSHLauncher(BaseLauncher):
492 491 """A minimal launcher for ssh.
493 492
494 493 To be useful this will probably have to be extended to use the ``sshx``
495 494 idea for environment variables. There could be other things this needs
496 495 as well.
497 496 """
498 497
499 498 ssh_cmd = List(['ssh'], config=True)
500 499 ssh_args = List([], config=True)
501 500 program = List(['date'], config=True)
502 501 program_args = List([], config=True)
503 502 hostname = Str('', config=True)
504 503 user = Str('', config=True)
505 504 location = Str('')
506 505
507 506 def _hostname_changed(self, name, old, new):
508 507 self.location = '%s@%s' % (self.user, new)
509 508
510 509 def _user_changed(self, name, old, new):
511 510 self.location = '%s@%s' % (new, self.hostname)
512 511
513 512 def find_args(self):
514 513 return self.ssh_cmd + self.ssh_args + [self.location] + \
515 514 self.program + self.program_args
516 515
517 516 def start(self, n, hostname=None, user=None):
518 517 if hostname is not None:
519 518 self.hostname = hostname
520 519 if user is not None:
521 520 self.user = user
522 521 return super(SSHLauncher, self).start()
523 522
524 523
525 524 class SSHControllerLauncher(SSHLauncher):
526 525 pass
527 526
528 527
529 528 class SSHEngineSetLauncher(BaseLauncher):
530 529 pass
531 530
532 531
533 532 #-----------------------------------------------------------------------------
534 533 # Windows HPC Server 2008 scheduler launchers
535 534 #-----------------------------------------------------------------------------
536 535
537 536
538 537 # This is only used on Windows.
539 538 def find_job_cmd():
540 539 if os.name=='nt':
541 540 try:
542 541 return find_cmd('job')
543 542 except FindCmdError:
544 543 return 'job'
545 544 else:
546 545 return 'job'
547 546
548 547
549 548 class WindowsHPCLauncher(BaseLauncher):
550 549
551 550 # A regular expression used to get the job id from the output of the
552 551 # submit_command.
553 552 job_id_regexp = Str(r'\d+', config=True)
554 553 # The filename of the instantiated job script.
555 554 job_file_name = Unicode(u'ipython_job.xml', config=True)
556 555 # The full path to the instantiated job script. This gets made dynamically
557 556 # by combining the work_dir with the job_file_name.
558 557 job_file = Unicode(u'')
559 558 # The hostname of the scheduler to submit the job to
560 559 scheduler = Str('', config=True)
561 560 job_cmd = Str(find_job_cmd(), config=True)
562 561
563 def __init__(self, work_dir, parent=None, name=None, config=None):
562 def __init__(self, work_dir=u'', config=None):
564 563 super(WindowsHPCLauncher, self).__init__(
565 work_dir, parent, name, config
564 work_dir=work_dir, config=config
566 565 )
567 566
568 567 @property
569 568 def job_file(self):
570 569 return os.path.join(self.work_dir, self.job_file_name)
571 570
572 571 def write_job_file(self, n):
573 572 raise NotImplementedError("Implement write_job_file in a subclass.")
574 573
575 574 def find_args(self):
576 575 return ['job.exe']
577 576
578 577 def parse_job_id(self, output):
579 578 """Take the output of the submit command and return the job id."""
580 579 m = re.search(self.job_id_regexp, output)
581 580 if m is not None:
582 581 job_id = m.group()
583 582 else:
584 583 raise LauncherError("Job id couldn't be determined: %s" % output)
585 584 self.job_id = job_id
586 585 log.msg('Job started with job id: %r' % job_id)
587 586 return job_id
588 587
589 588 @inlineCallbacks
590 589 def start(self, n):
591 590 """Start n copies of the process using the Win HPC job scheduler."""
592 591 self.write_job_file(n)
593 592 args = [
594 593 'submit',
595 594 '/jobfile:%s' % self.job_file,
596 595 '/scheduler:%s' % self.scheduler
597 596 ]
598 597 log.msg("Starting Win HPC Job: %s" % (self.job_cmd + ' ' + ' '.join(args),))
599 598 # Twisted will raise DeprecationWarnings if we try to pass unicode to this
600 599 output = yield getProcessOutput(str(self.job_cmd),
601 600 [str(a) for a in args],
602 601 env=dict((str(k),str(v)) for k,v in os.environ.items()),
603 602 path=self.work_dir
604 603 )
605 604 job_id = self.parse_job_id(output)
606 605 self.notify_start(job_id)
607 606 defer.returnValue(job_id)
608 607
609 608 @inlineCallbacks
610 609 def stop(self):
611 610 args = [
612 611 'cancel',
613 612 self.job_id,
614 613 '/scheduler:%s' % self.scheduler
615 614 ]
616 615 log.msg("Stopping Win HPC Job: %s" % (self.job_cmd + ' ' + ' '.join(args),))
617 616 try:
618 617 # Twisted will raise DeprecationWarnings if we try to pass unicode to this
619 618 output = yield getProcessOutput(str(self.job_cmd),
620 619 [str(a) for a in args],
621 620 env=dict((str(k),str(v)) for k,v in os.environ.items()),
622 621 path=self.work_dir
623 622 )
624 623 except:
625 624 output = 'The job already appears to be stoppped: %r' % self.job_id
626 625 self.notify_stop(output) # Pass the output of the kill cmd
627 626 defer.returnValue(output)
628 627
629 628
630 629 class WindowsHPCControllerLauncher(WindowsHPCLauncher):
631 630
632 631 job_file_name = Unicode(u'ipcontroller_job.xml', config=True)
633 632 extra_args = List([], config=False)
634 633
635 634 def write_job_file(self, n):
636 job = IPControllerJob(self)
635 job = IPControllerJob(config=self.config)
637 636
638 t = IPControllerTask(self)
637 t = IPControllerTask(config=self.config)
639 638 # The tasks work directory is *not* the actual work directory of
640 639 # the controller. It is used as the base path for the stdout/stderr
641 640 # files that the scheduler redirects to.
642 641 t.work_directory = self.cluster_dir
643 642 # Add the --cluster-dir and from self.start().
644 643 t.controller_args.extend(self.extra_args)
645 644 job.add_task(t)
646 645
647 646 log.msg("Writing job description file: %s" % self.job_file)
648 647 job.write(self.job_file)
649 648
650 649 @property
651 650 def job_file(self):
652 651 return os.path.join(self.cluster_dir, self.job_file_name)
653 652
654 653 def start(self, cluster_dir):
655 654 """Start the controller by cluster_dir."""
656 655 self.extra_args = ['--cluster-dir', cluster_dir]
657 656 self.cluster_dir = unicode(cluster_dir)
658 657 return super(WindowsHPCControllerLauncher, self).start(1)
659 658
660 659
661 660 class WindowsHPCEngineSetLauncher(WindowsHPCLauncher):
662 661
663 662 job_file_name = Unicode(u'ipengineset_job.xml', config=True)
664 663 extra_args = List([], config=False)
665 664
666 665 def write_job_file(self, n):
667 job = IPEngineSetJob(self)
666 job = IPEngineSetJob(config=self.config)
668 667
669 668 for i in range(n):
670 t = IPEngineTask(self)
669 t = IPEngineTask(config=self.config)
671 670 # The tasks work directory is *not* the actual work directory of
672 671 # the engine. It is used as the base path for the stdout/stderr
673 672 # files that the scheduler redirects to.
674 673 t.work_directory = self.cluster_dir
675 674 # Add the --cluster-dir and from self.start().
676 675 t.engine_args.extend(self.extra_args)
677 676 job.add_task(t)
678 677
679 678 log.msg("Writing job description file: %s" % self.job_file)
680 679 job.write(self.job_file)
681 680
682 681 @property
683 682 def job_file(self):
684 683 return os.path.join(self.cluster_dir, self.job_file_name)
685 684
686 685 def start(self, n, cluster_dir):
687 686 """Start the controller by cluster_dir."""
688 687 self.extra_args = ['--cluster-dir', cluster_dir]
689 688 self.cluster_dir = unicode(cluster_dir)
690 689 return super(WindowsHPCEngineSetLauncher, self).start(n)
691 690
692 691
693 692 #-----------------------------------------------------------------------------
694 693 # Batch (PBS) system launchers
695 694 #-----------------------------------------------------------------------------
696 695
697 696 # TODO: Get PBS launcher working again.
698 697
699 698 class BatchSystemLauncher(BaseLauncher):
700 699 """Launch an external process using a batch system.
701 700
702 701 This class is designed to work with UNIX batch systems like PBS, LSF,
703 702 GridEngine, etc. The overall model is that there are different commands
704 703 like qsub, qdel, etc. that handle the starting and stopping of the process.
705 704
706 705 This class also has the notion of a batch script. The ``batch_template``
707 706 attribute can be set to a string that is a template for the batch script.
708 707 This template is instantiated using Itpl. Thus the template can use
709 708 ${n} fot the number of instances. Subclasses can add additional variables
710 709 to the template dict.
711 710 """
712 711
713 712 # Subclasses must fill these in. See PBSEngineSet
714 713 # The name of the command line program used to submit jobs.
715 714 submit_command = Str('', config=True)
716 715 # The name of the command line program used to delete jobs.
717 716 delete_command = Str('', config=True)
718 717 # A regular expression used to get the job id from the output of the
719 718 # submit_command.
720 719 job_id_regexp = Str('', config=True)
721 720 # The string that is the batch script template itself.
722 721 batch_template = Str('', config=True)
723 722 # The filename of the instantiated batch script.
724 723 batch_file_name = Unicode(u'batch_script', config=True)
725 724 # The full path to the instantiated batch script.
726 725 batch_file = Unicode(u'')
727 726
728 def __init__(self, work_dir, parent=None, name=None, config=None):
727 def __init__(self, work_dir=u'', config=None):
729 728 super(BatchSystemLauncher, self).__init__(
730 work_dir, parent, name, config
729 work_dir=work_dir, config=config
731 730 )
732 731 self.batch_file = os.path.join(self.work_dir, self.batch_file_name)
733 732 self.context = {}
734 733
735 734 def parse_job_id(self, output):
736 735 """Take the output of the submit command and return the job id."""
737 736 m = re.match(self.job_id_regexp, output)
738 737 if m is not None:
739 738 job_id = m.group()
740 739 else:
741 740 raise LauncherError("Job id couldn't be determined: %s" % output)
742 741 self.job_id = job_id
743 742 log.msg('Job started with job id: %r' % job_id)
744 743 return job_id
745 744
746 745 def write_batch_script(self, n):
747 746 """Instantiate and write the batch script to the work_dir."""
748 747 self.context['n'] = n
749 748 script_as_string = Itpl.itplns(self.batch_template, self.context)
750 749 log.msg('Writing instantiated batch script: %s' % self.batch_file)
751 750 f = open(self.batch_file, 'w')
752 751 f.write(script_as_string)
753 752 f.close()
754 753
755 754 @inlineCallbacks
756 755 def start(self, n):
757 756 """Start n copies of the process using a batch system."""
758 757 self.write_batch_script(n)
759 758 output = yield getProcessOutput(self.submit_command,
760 759 [self.batch_file], env=os.environ)
761 760 job_id = self.parse_job_id(output)
762 761 self.notify_start(job_id)
763 762 defer.returnValue(job_id)
764 763
765 764 @inlineCallbacks
766 765 def stop(self):
767 766 output = yield getProcessOutput(self.delete_command,
768 767 [self.job_id], env=os.environ
769 768 )
770 769 self.notify_stop(output) # Pass the output of the kill cmd
771 770 defer.returnValue(output)
772 771
773 772
774 773 class PBSLauncher(BatchSystemLauncher):
775 774 """A BatchSystemLauncher subclass for PBS."""
776 775
777 776 submit_command = Str('qsub', config=True)
778 777 delete_command = Str('qdel', config=True)
779 778 job_id_regexp = Str(r'\d+', config=True)
780 779 batch_template = Str('', config=True)
781 780 batch_file_name = Unicode(u'pbs_batch_script', config=True)
782 781 batch_file = Unicode(u'')
783 782
784 783
785 784 class PBSControllerLauncher(PBSLauncher):
786 785 """Launch a controller using PBS."""
787 786
788 787 batch_file_name = Unicode(u'pbs_batch_script_controller', config=True)
789 788
790 789 def start(self, cluster_dir):
791 790 """Start the controller by profile or cluster_dir."""
792 791 # Here we save profile and cluster_dir in the context so they
793 792 # can be used in the batch script template as ${profile} and
794 793 # ${cluster_dir}
795 794 self.context['cluster_dir'] = cluster_dir
796 795 self.cluster_dir = unicode(cluster_dir)
797 796 log.msg("Starting PBSControllerLauncher: %r" % self.args)
798 797 return super(PBSControllerLauncher, self).start(1)
799 798
800 799
801 800 class PBSEngineSetLauncher(PBSLauncher):
802 801
803 802 batch_file_name = Unicode(u'pbs_batch_script_engines', config=True)
804 803
805 804 def start(self, n, cluster_dir):
806 805 """Start n engines by profile or cluster_dir."""
807 806 self.program_args.extend(['--cluster-dir', cluster_dir])
808 807 self.cluster_dir = unicode(cluster_dir)
809 808 log.msg('Starting PBSEngineSetLauncher: %r' % self.args)
810 809 return super(PBSEngineSetLauncher, self).start(n)
811 810
812 811
813 812 #-----------------------------------------------------------------------------
814 813 # A launcher for ipcluster itself!
815 814 #-----------------------------------------------------------------------------
816 815
817 816
818 817 class IPClusterLauncher(LocalProcessLauncher):
819 818 """Launch the ipcluster program in an external process."""
820 819
821 820 ipcluster_cmd = List(ipcluster_cmd_argv, config=True)
822 821 # Command line arguments to pass to ipcluster.
823 822 ipcluster_args = List(
824 823 ['--clean-logs', '--log-to-file', '--log-level', '40'], config=True)
825 824 ipcluster_subcommand = Str('start')
826 825 ipcluster_n = Int(2)
827 826
828 827 def find_args(self):
829 828 return self.ipcluster_cmd + [self.ipcluster_subcommand] + \
830 829 ['-n', repr(self.ipcluster_n)] + self.ipcluster_args
831 830
832 831 def start(self):
833 832 log.msg("Starting ipcluster: %r" % self.args)
834 833 return super(IPClusterLauncher, self).start()
835 834
@@ -1,316 +1,316 b''
1 1 #!/usr/bin/env python
2 2 # encoding: utf-8
3 3 """
4 4 Job and task components for writing .xml files that the Windows HPC Server
5 5 2008 can use to start jobs.
6 6 """
7 7
8 8 #-----------------------------------------------------------------------------
9 9 # Copyright (C) 2008-2009 The IPython Development Team
10 10 #
11 11 # Distributed under the terms of the BSD License. The full license is in
12 12 # the file COPYING, distributed as part of this software.
13 13 #-----------------------------------------------------------------------------
14 14
15 15 #-----------------------------------------------------------------------------
16 16 # Imports
17 17 #-----------------------------------------------------------------------------
18 18
19 19 from __future__ import with_statement
20 20
21 21 import os
22 22 import re
23 23 import uuid
24 24
25 25 from xml.etree import ElementTree as ET
26 26
27 from IPython.core.component import Component
27 from IPython.config.configurable import Configurable
28 28 from IPython.utils.traitlets import (
29 29 Str, Int, List, Instance,
30 30 Enum, Bool, CStr
31 31 )
32 32
33 33 #-----------------------------------------------------------------------------
34 # Job and Task Component
34 # Job and Task classes
35 35 #-----------------------------------------------------------------------------
36 36
37 37
38 38 def as_str(value):
39 39 if isinstance(value, str):
40 40 return value
41 41 elif isinstance(value, bool):
42 42 if value:
43 43 return 'true'
44 44 else:
45 45 return 'false'
46 46 elif isinstance(value, (int, float)):
47 47 return repr(value)
48 48 else:
49 49 return value
50 50
51 51
52 52 def indent(elem, level=0):
53 53 i = "\n" + level*" "
54 54 if len(elem):
55 55 if not elem.text or not elem.text.strip():
56 56 elem.text = i + " "
57 57 if not elem.tail or not elem.tail.strip():
58 58 elem.tail = i
59 59 for elem in elem:
60 60 indent(elem, level+1)
61 61 if not elem.tail or not elem.tail.strip():
62 62 elem.tail = i
63 63 else:
64 64 if level and (not elem.tail or not elem.tail.strip()):
65 65 elem.tail = i
66 66
67 67
68 68 def find_username():
69 69 domain = os.environ.get('USERDOMAIN')
70 70 username = os.environ.get('USERNAME','')
71 71 if domain is None:
72 72 return username
73 73 else:
74 74 return '%s\\%s' % (domain, username)
75 75
76 76
77 class WinHPCJob(Component):
77 class WinHPCJob(Configurable):
78 78
79 79 job_id = Str('')
80 80 job_name = Str('MyJob', config=True)
81 81 min_cores = Int(1, config=True)
82 82 max_cores = Int(1, config=True)
83 83 min_sockets = Int(1, config=True)
84 84 max_sockets = Int(1, config=True)
85 85 min_nodes = Int(1, config=True)
86 86 max_nodes = Int(1, config=True)
87 87 unit_type = Str("Core", config=True)
88 88 auto_calculate_min = Bool(True, config=True)
89 89 auto_calculate_max = Bool(True, config=True)
90 90 run_until_canceled = Bool(False, config=True)
91 91 is_exclusive = Bool(False, config=True)
92 92 username = Str(find_username(), config=True)
93 93 job_type = Str('Batch', config=True)
94 94 priority = Enum(('Lowest','BelowNormal','Normal','AboveNormal','Highest'),
95 95 default_value='Highest', config=True)
96 96 requested_nodes = Str('', config=True)
97 97 project = Str('IPython', config=True)
98 98 xmlns = Str('http://schemas.microsoft.com/HPCS2008/scheduler/')
99 99 version = Str("2.000")
100 100 tasks = List([])
101 101
102 102 @property
103 103 def owner(self):
104 104 return self.username
105 105
106 106 def _write_attr(self, root, attr, key):
107 107 s = as_str(getattr(self, attr, ''))
108 108 if s:
109 109 root.set(key, s)
110 110
111 111 def as_element(self):
112 112 # We have to add _A_ type things to get the right order than
113 113 # the MSFT XML parser expects.
114 114 root = ET.Element('Job')
115 115 self._write_attr(root, 'version', '_A_Version')
116 116 self._write_attr(root, 'job_name', '_B_Name')
117 117 self._write_attr(root, 'unit_type', '_C_UnitType')
118 118 self._write_attr(root, 'min_cores', '_D_MinCores')
119 119 self._write_attr(root, 'max_cores', '_E_MaxCores')
120 120 self._write_attr(root, 'min_sockets', '_F_MinSockets')
121 121 self._write_attr(root, 'max_sockets', '_G_MaxSockets')
122 122 self._write_attr(root, 'min_nodes', '_H_MinNodes')
123 123 self._write_attr(root, 'max_nodes', '_I_MaxNodes')
124 124 self._write_attr(root, 'run_until_canceled', '_J_RunUntilCanceled')
125 125 self._write_attr(root, 'is_exclusive', '_K_IsExclusive')
126 126 self._write_attr(root, 'username', '_L_UserName')
127 127 self._write_attr(root, 'job_type', '_M_JobType')
128 128 self._write_attr(root, 'priority', '_N_Priority')
129 129 self._write_attr(root, 'requested_nodes', '_O_RequestedNodes')
130 130 self._write_attr(root, 'auto_calculate_max', '_P_AutoCalculateMax')
131 131 self._write_attr(root, 'auto_calculate_min', '_Q_AutoCalculateMin')
132 132 self._write_attr(root, 'project', '_R_Project')
133 133 self._write_attr(root, 'owner', '_S_Owner')
134 134 self._write_attr(root, 'xmlns', '_T_xmlns')
135 135 dependencies = ET.SubElement(root, "Dependencies")
136 136 etasks = ET.SubElement(root, "Tasks")
137 137 for t in self.tasks:
138 138 etasks.append(t.as_element())
139 139 return root
140 140
141 141 def tostring(self):
142 142 """Return the string representation of the job description XML."""
143 143 root = self.as_element()
144 144 indent(root)
145 145 txt = ET.tostring(root, encoding="utf-8")
146 146 # Now remove the tokens used to order the attributes.
147 147 txt = re.sub(r'_[A-Z]_','',txt)
148 148 txt = '<?xml version="1.0" encoding="utf-8"?>\n' + txt
149 149 return txt
150 150
151 151 def write(self, filename):
152 152 """Write the XML job description to a file."""
153 153 txt = self.tostring()
154 154 with open(filename, 'w') as f:
155 155 f.write(txt)
156 156
157 157 def add_task(self, task):
158 158 """Add a task to the job.
159 159
160 160 Parameters
161 161 ----------
162 162 task : :class:`WinHPCTask`
163 163 The task object to add.
164 164 """
165 165 self.tasks.append(task)
166 166
167 167
168 class WinHPCTask(Component):
168 class WinHPCTask(Configurable):
169 169
170 170 task_id = Str('')
171 171 task_name = Str('')
172 172 version = Str("2.000")
173 173 min_cores = Int(1, config=True)
174 174 max_cores = Int(1, config=True)
175 175 min_sockets = Int(1, config=True)
176 176 max_sockets = Int(1, config=True)
177 177 min_nodes = Int(1, config=True)
178 178 max_nodes = Int(1, config=True)
179 179 unit_type = Str("Core", config=True)
180 180 command_line = CStr('', config=True)
181 181 work_directory = CStr('', config=True)
182 182 is_rerunnaable = Bool(True, config=True)
183 183 std_out_file_path = CStr('', config=True)
184 184 std_err_file_path = CStr('', config=True)
185 185 is_parametric = Bool(False, config=True)
186 186 environment_variables = Instance(dict, args=(), config=True)
187 187
188 188 def _write_attr(self, root, attr, key):
189 189 s = as_str(getattr(self, attr, ''))
190 190 if s:
191 191 root.set(key, s)
192 192
193 193 def as_element(self):
194 194 root = ET.Element('Task')
195 195 self._write_attr(root, 'version', '_A_Version')
196 196 self._write_attr(root, 'task_name', '_B_Name')
197 197 self._write_attr(root, 'min_cores', '_C_MinCores')
198 198 self._write_attr(root, 'max_cores', '_D_MaxCores')
199 199 self._write_attr(root, 'min_sockets', '_E_MinSockets')
200 200 self._write_attr(root, 'max_sockets', '_F_MaxSockets')
201 201 self._write_attr(root, 'min_nodes', '_G_MinNodes')
202 202 self._write_attr(root, 'max_nodes', '_H_MaxNodes')
203 203 self._write_attr(root, 'command_line', '_I_CommandLine')
204 204 self._write_attr(root, 'work_directory', '_J_WorkDirectory')
205 205 self._write_attr(root, 'is_rerunnaable', '_K_IsRerunnable')
206 206 self._write_attr(root, 'std_out_file_path', '_L_StdOutFilePath')
207 207 self._write_attr(root, 'std_err_file_path', '_M_StdErrFilePath')
208 208 self._write_attr(root, 'is_parametric', '_N_IsParametric')
209 209 self._write_attr(root, 'unit_type', '_O_UnitType')
210 210 root.append(self.get_env_vars())
211 211 return root
212 212
213 213 def get_env_vars(self):
214 214 env_vars = ET.Element('EnvironmentVariables')
215 215 for k, v in self.environment_variables.items():
216 216 variable = ET.SubElement(env_vars, "Variable")
217 217 name = ET.SubElement(variable, "Name")
218 218 name.text = k
219 219 value = ET.SubElement(variable, "Value")
220 220 value.text = v
221 221 return env_vars
222 222
223 223
224 224
225 225 # By declaring these, we can configure the controller and engine separately!
226 226
227 227 class IPControllerJob(WinHPCJob):
228 228 job_name = Str('IPController', config=False)
229 229 is_exclusive = Bool(False, config=True)
230 230 username = Str(find_username(), config=True)
231 231 priority = Enum(('Lowest','BelowNormal','Normal','AboveNormal','Highest'),
232 232 default_value='Highest', config=True)
233 233 requested_nodes = Str('', config=True)
234 234 project = Str('IPython', config=True)
235 235
236 236
237 237 class IPEngineSetJob(WinHPCJob):
238 238 job_name = Str('IPEngineSet', config=False)
239 239 is_exclusive = Bool(False, config=True)
240 240 username = Str(find_username(), config=True)
241 241 priority = Enum(('Lowest','BelowNormal','Normal','AboveNormal','Highest'),
242 242 default_value='Highest', config=True)
243 243 requested_nodes = Str('', config=True)
244 244 project = Str('IPython', config=True)
245 245
246 246
247 247 class IPControllerTask(WinHPCTask):
248 248
249 249 task_name = Str('IPController', config=True)
250 250 controller_cmd = List(['ipcontroller.exe'], config=True)
251 251 controller_args = List(['--log-to-file', '--log-level', '40'], config=True)
252 252 # I don't want these to be configurable
253 253 std_out_file_path = CStr('', config=False)
254 254 std_err_file_path = CStr('', config=False)
255 255 min_cores = Int(1, config=False)
256 256 max_cores = Int(1, config=False)
257 257 min_sockets = Int(1, config=False)
258 258 max_sockets = Int(1, config=False)
259 259 min_nodes = Int(1, config=False)
260 260 max_nodes = Int(1, config=False)
261 261 unit_type = Str("Core", config=False)
262 262 work_directory = CStr('', config=False)
263 263
264 def __init__(self, parent, name=None, config=None):
265 super(IPControllerTask, self).__init__(parent, name, config)
264 def __init__(self, config=None):
265 super(IPControllerTask, self).__init__(config=config)
266 266 the_uuid = uuid.uuid1()
267 267 self.std_out_file_path = os.path.join('log','ipcontroller-%s.out' % the_uuid)
268 268 self.std_err_file_path = os.path.join('log','ipcontroller-%s.err' % the_uuid)
269 269
270 270 @property
271 271 def command_line(self):
272 272 return ' '.join(self.controller_cmd + self.controller_args)
273 273
274 274
275 275 class IPEngineTask(WinHPCTask):
276 276
277 277 task_name = Str('IPEngine', config=True)
278 278 engine_cmd = List(['ipengine.exe'], config=True)
279 279 engine_args = List(['--log-to-file', '--log-level', '40'], config=True)
280 280 # I don't want these to be configurable
281 281 std_out_file_path = CStr('', config=False)
282 282 std_err_file_path = CStr('', config=False)
283 283 min_cores = Int(1, config=False)
284 284 max_cores = Int(1, config=False)
285 285 min_sockets = Int(1, config=False)
286 286 max_sockets = Int(1, config=False)
287 287 min_nodes = Int(1, config=False)
288 288 max_nodes = Int(1, config=False)
289 289 unit_type = Str("Core", config=False)
290 290 work_directory = CStr('', config=False)
291 291
292 def __init__(self, parent, name=None, config=None):
293 super(IPEngineTask,self).__init__(parent, name, config)
292 def __init__(self, config=None):
293 super(IPEngineTask,self).__init__(config=config)
294 294 the_uuid = uuid.uuid1()
295 295 self.std_out_file_path = os.path.join('log','ipengine-%s.out' % the_uuid)
296 296 self.std_err_file_path = os.path.join('log','ipengine-%s.err' % the_uuid)
297 297
298 298 @property
299 299 def command_line(self):
300 300 return ' '.join(self.engine_cmd + self.engine_args)
301 301
302 302
303 303 # j = WinHPCJob(None)
304 304 # j.job_name = 'IPCluster'
305 305 # j.username = 'GNET\\bgranger'
306 306 # j.requested_nodes = 'GREEN'
307 307 #
308 308 # t = WinHPCTask(None)
309 309 # t.task_name = 'Controller'
310 310 # t.command_line = r"\\blue\domainusers$\bgranger\Python\Python25\Scripts\ipcontroller.exe --log-to-file -p default --log-level 10"
311 311 # t.work_directory = r"\\blue\domainusers$\bgranger\.ipython\cluster_default"
312 312 # t.std_out_file_path = 'controller-out.txt'
313 313 # t.std_err_file_path = 'controller-err.txt'
314 314 # t.environment_variables['PYTHONPATH'] = r"\\blue\domainusers$\bgranger\Python\Python25\Lib\site-packages"
315 315 # j.add_task(t)
316 316
@@ -1,174 +1,174 b''
1 1 """Global IPython app to support test running.
2 2
3 3 We must start our own ipython object and heavily muck with it so that all the
4 4 modifications IPython makes to system behavior don't send the doctest machinery
5 5 into a fit. This code should be considered a gross hack, but it gets the job
6 6 done.
7 7 """
8 8
9 9 from __future__ import absolute_import
10 10
11 11 #-----------------------------------------------------------------------------
12 12 # Copyright (C) 2009 The IPython Development Team
13 13 #
14 14 # Distributed under the terms of the BSD License. The full license is in
15 15 # the file COPYING, distributed as part of this software.
16 16 #-----------------------------------------------------------------------------
17 17
18 18 #-----------------------------------------------------------------------------
19 19 # Imports
20 20 #-----------------------------------------------------------------------------
21 21
22 22 import __builtin__
23 23 import commands
24 24 import os
25 25 import sys
26 26
27 27 from . import tools
28 28
29 29 #-----------------------------------------------------------------------------
30 30 # Functions
31 31 #-----------------------------------------------------------------------------
32 32
33 33 # Hack to modify the %run command so we can sync the user's namespace with the
34 34 # test globals. Once we move over to a clean magic system, this will be done
35 35 # with much less ugliness.
36 36
37 37 class py_file_finder(object):
38 38 def __init__(self,test_filename):
39 39 self.test_filename = test_filename
40 40
41 41 def __call__(self,name):
42 42 from IPython.utils.path import get_py_filename
43 43 try:
44 44 return get_py_filename(name)
45 45 except IOError:
46 46 test_dir = os.path.dirname(self.test_filename)
47 47 new_path = os.path.join(test_dir,name)
48 48 return get_py_filename(new_path)
49 49
50 50
51 51 def _run_ns_sync(self,arg_s,runner=None):
52 52 """Modified version of %run that syncs testing namespaces.
53 53
54 54 This is strictly needed for running doctests that call %run.
55 55 """
56 56 #print >> sys.stderr, 'in run_ns_sync', arg_s # dbg
57 57
58 58 _ip = get_ipython()
59 59 finder = py_file_finder(arg_s)
60 60 out = _ip.magic_run_ori(arg_s,runner,finder)
61 61 return out
62 62
63 63
64 64 class ipnsdict(dict):
65 65 """A special subclass of dict for use as an IPython namespace in doctests.
66 66
67 67 This subclass adds a simple checkpointing capability so that when testing
68 68 machinery clears it (we use it as the test execution context), it doesn't
69 69 get completely destroyed.
70 70 """
71 71
72 72 def __init__(self,*a):
73 73 dict.__init__(self,*a)
74 74 self._savedict = {}
75 75
76 76 def clear(self):
77 77 dict.clear(self)
78 78 self.update(self._savedict)
79 79
80 80 def _checkpoint(self):
81 81 self._savedict.clear()
82 82 self._savedict.update(self)
83 83
84 84 def update(self,other):
85 85 self._checkpoint()
86 86 dict.update(self,other)
87 87
88 88 # If '_' is in the namespace, python won't set it when executing code,
89 89 # and we have examples that test it. So we ensure that the namespace
90 90 # is always 'clean' of it before it's used for test code execution.
91 91 self.pop('_',None)
92 92
93 93 # The builtins namespace must *always* be the real __builtin__ module,
94 94 # else weird stuff happens. The main ipython code does have provisions
95 95 # to ensure this after %run, but since in this class we do some
96 96 # aggressive low-level cleaning of the execution namespace, we need to
97 97 # correct for that ourselves, to ensure consitency with the 'real'
98 98 # ipython.
99 99 self['__builtins__'] = __builtin__
100 100
101 101
102 102 def get_ipython():
103 103 # This will get replaced by the real thing once we start IPython below
104 104 return start_ipython()
105 105
106 106
107 107 def start_ipython():
108 108 """Start a global IPython shell, which we need for IPython-specific syntax.
109 109 """
110 110 global get_ipython
111 111
112 112 # This function should only ever run once!
113 113 if hasattr(start_ipython, 'already_called'):
114 114 return
115 115 start_ipython.already_called = True
116 116
117 117 # Ok, first time we're called, go ahead
118 118 from IPython.core import iplib
119 119
120 120 def xsys(cmd):
121 121 """Execute a command and print its output.
122 122
123 123 This is just a convenience function to replace the IPython system call
124 124 with one that is more doctest-friendly.
125 125 """
126 126 cmd = _ip.var_expand(cmd,depth=1)
127 127 sys.stdout.write(commands.getoutput(cmd))
128 128 sys.stdout.flush()
129 129
130 130 # Store certain global objects that IPython modifies
131 131 _displayhook = sys.displayhook
132 132 _excepthook = sys.excepthook
133 133 _main = sys.modules.get('__main__')
134 134
135 135 # Create custom argv and namespaces for our IPython to be test-friendly
136 136 config = tools.default_config()
137 137
138 138 # Create and initialize our test-friendly IPython instance.
139 shell = iplib.InteractiveShell(
140 parent=None, config=config,
139 shell = iplib.InteractiveShell.instance(
140 config=config,
141 141 user_ns=ipnsdict(), user_global_ns={}
142 142 )
143 143
144 144 # A few more tweaks needed for playing nicely with doctests...
145 145
146 146 # These traps are normally only active for interactive use, set them
147 147 # permanently since we'll be mocking interactive sessions.
148 148 shell.builtin_trap.set()
149 149
150 150 # Set error printing to stdout so nose can doctest exceptions
151 151 shell.InteractiveTB.out_stream = 'stdout'
152 152
153 153 # Modify the IPython system call with one that uses getoutput, so that we
154 154 # can capture subcommands and print them to Python's stdout, otherwise the
155 155 # doctest machinery would miss them.
156 156 shell.system = xsys
157 157
158 158 # IPython is ready, now clean up some global state...
159 159
160 160 # Deactivate the various python system hooks added by ipython for
161 161 # interactive convenience so we don't confuse the doctest system
162 162 sys.modules['__main__'] = _main
163 163 sys.displayhook = _displayhook
164 164 sys.excepthook = _excepthook
165 165
166 166 # So that ipython magics and aliases can be doctested (they work by making
167 167 # a call into a global _ip object). Also make the top-level get_ipython
168 168 # now return this without recursively calling here again.
169 169 _ip = shell
170 170 get_ipython = _ip.get_ipython
171 171 __builtin__._ip = _ip
172 172 __builtin__.get_ipython = get_ipython
173 173
174 174 return _ip
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: file was removed
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