##// END OF EJS Templates
First prototype of component, traitlets and a config loader.
Brian Granger -
Show More
@@ -0,0 +1,186 b''
1 #!/usr/bin/env python
2 # encoding: utf-8
3 """A factory for creating configuration objects.
4 """
5
6 #-----------------------------------------------------------------------------
7 # Copyright (C) 2008-2009 The IPython Development Team
8 #
9 # Distributed under the terms of the BSD License. The full license is in
10 # the file COPYING, distributed as part of this software.
11 #-----------------------------------------------------------------------------
12
13 #-----------------------------------------------------------------------------
14 # Imports
15 #-----------------------------------------------------------------------------
16
17 import os
18
19 from IPython.utils.ipstruct import Struct
20
21 #-----------------------------------------------------------------------------
22 # Code
23 #-----------------------------------------------------------------------------
24
25
26 class ConfigLoaderError(Exception):
27 pass
28
29
30 class ConfigLoader(object):
31 """A object for loading configurations from just about anywhere.
32
33 The resulting configuration is packaged as a :class:`Struct`.
34 """
35
36 def __init__(self):
37 """A base class for config loaders.
38
39 Examples
40 --------
41
42 >>> cl = ConfigLoader()
43 >>> config = cl.load_config()
44 >>> config
45 {}
46 """
47 self.clear()
48
49 def clear(self):
50 self.config = Struct()
51
52 def load_config(self):
53 """Load a config from somewhere, return a Struct.
54
55 Usually, this will cause self.config to be set and then returned.
56 """
57 return self.config
58
59
60 class FileConfigLoader(ConfigLoader):
61 """A config loader for pure python files.
62
63 This calls execfile on a plain python file and looks for attributes
64 that are all caps. These attribute are added to the config Struct.
65 """
66
67 def __init__(self, filename, path='.'):
68 """Build a config loader for a filename and path.
69
70 Parameters
71 ----------
72 filename : str
73 The file name of the config file.
74 path : str, list, tuple
75 The path to search for the config file on, or a sequence of
76 paths to try in order
77
78 Examples
79 --------
80
81
82 """
83 self.filename = filename
84 self.path = path
85 self.full_filename = ''
86 self.data = None
87 ConfigLoader.__init__(self)
88
89 def find_file(self):
90 """Implement file finding logic here."""
91 self.full_filename = self.filename
92
93 def read_file_as_dict(self):
94 if not os.path.isfile(self.full_filename):
95 raise IOError("config file does not exist: %r" % self.fullfilename)
96 self.data = {}
97 execfile(self.full_filename, self.data)
98
99 def convert_to_struct(self):
100 if self.data is None:
101 ConfigLoaderError('self.data does not exist')
102 for k, v in self.data.iteritems():
103 if k == k.upper():
104 self.config[k] = v
105
106 def load_config(self):
107 self.find_file()
108 self.read_file_as_dict()
109 self.convert_to_struct()
110 return self.config
111
112 class PyConfigLoader(object):
113 pass
114
115
116 class DefaultFileConfigLoader(object):
117
118 def __init__(self, filename, install_location):
119 pass
120
121 def load_config(self):
122 pass
123
124 def install(self, force=False):
125 pass
126
127
128 class CommandLineConfigLoader(ConfigLoader):
129
130 def __init__(self):
131 self.parser = None
132 self.parsed_data = None
133 self.clear()
134
135
136 def clear(self):
137 self.config = Struct()
138
139 def load_config(self, args=None):
140 self.create_parser()
141 self.parse_args(args)
142 self.convert_to_struct()
143 return self.config
144
145 def create_parser(self):
146 """Create self.parser"""
147
148 def parse_args(self, args=None):
149 """self.parser->self.parsed_data"""
150 if self.parser is None:
151 raise ConfigLoaderError('self.parser does not exist')
152 if args is None:
153 self.parsed_data = parser.parse_args()
154 else:
155 self.parse_data = parser.parse_args(args)
156
157 def convert_to_struct(self):
158 """self.parsed_data->self.config"""
159 if self.parsed_data is None:
160 raise ConfigLoaderError('self.parsed_data does not exist')
161 self.config = Struct(vars(self.parsed_data))
162
163
164 class ArgParseConfigLoader(CommandLineConfigLoader):
165
166 # arguments = [(('-f','--file'),dict(type=str,dest='file'))]
167 arguments = []
168
169 def __init__(self, *args, **kw):
170 """Create a config loader for use with argparse.
171
172 The args and kwargs arguments here are passed onto the constructor
173 of :class:`argparse.ArgumentParser`.
174 """
175 self.args = args
176 self.kw = kw
177 CommandLineConfigLoader.__init__(self)
178
179 def create_parser(self):
180 self.parser = argparse.ArgumentParser(*self.args, **self.kw)
181 self.add_arguments()
182
183 def add_arguments(self):
184 for argument in self.arguments:
185 self.parser.add_argument(*argument[0],**argument[1])
186
@@ -0,0 +1,184 b''
1 #!/usr/bin/env python
2 # encoding: utf-8
3 """
4 A lightweight component system for IPython.
5
6 Authors:
7
8 * Brian Granger
9 * Fernando Perez
10 """
11
12 #-----------------------------------------------------------------------------
13 # Copyright (C) 2008-2009 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
24 from weakref import WeakValueDictionary
25
26 from IPython.utils.traitlets import (
27 HasTraitlets, TraitletError, MetaHasTraitlets,
28 Int, Float, Str, Bool, Unicode
29 )
30
31
32 #-----------------------------------------------------------------------------
33 # Helper classes for Components
34 #-----------------------------------------------------------------------------
35
36
37 class Config(object):
38 pass
39
40
41 class MetaComponentTracker(type):
42 """A metaclass that tracks instances of Components and its subclasses."""
43
44 def __init__(cls, name, bases, d):
45 super(MetaComponentTracker, cls).__init__(name, bases, d)
46 cls.__instance_refs = WeakValueDictionary()
47 cls.__numcreated = 0
48
49 def __call__(cls, *args, **kw):
50 """Called when class is called (instantiated)!!!
51
52 Then a Component or subclass is instantiated, this is called and
53 the instance is saved in a WeakValueDictionary for tracking.
54 """
55
56 instance = super(MetaComponentTracker, cls).__call__(*args, **kw)
57 for c in cls.__mro__:
58 if issubclass(cls, c) and issubclass(c, Component):
59 c.__numcreated += 1
60 c.__instance_refs[c.__numcreated] = instance
61 return instance
62
63 def get_instances(cls):
64 """Get all instances of cls and its subclasses."""
65 return cls.__instance_refs.values()
66
67 def get_instances_by_name(cls, name):
68 """Get all instances of cls and its subclasses by name."""
69 return [i for i in cls.get_instances() if i.name == name]
70
71 def get_instances_by_subclass(cls, thisclass):
72 """Get all instances of cls that are instances of thisclass.
73
74 This includes all instances of subclasses of thisclass.
75 """
76 return [i for i in cls.get_instances() if isinstance(i, thisclass)]
77
78 def get_instances_by_class(cls, thisclass):
79 """Get all instances of cls that are instances of thisclass.
80
81 This exclused instances of thisclass subclasses.
82 """
83
84 return [i for i in cls.get_instances() if type(i) is thisclass]
85
86 def get_instances_by_condition(cls, call):
87 """Get all instances of cls, i such that call(i)==True."""
88 return [i for i in cls.get_instances() if call(i)]
89
90
91 class ComponentNameGenerator(object):
92 """A Singleton to generate unique component names."""
93
94 def __init__(self, prefix):
95 self.prefix = prefix
96 self.i = 0
97
98 def __call__(self):
99 count = self.i
100 self.i += 1
101 return "%s%s" % (self.prefix, count)
102
103
104 ComponentNameGenerator = ComponentNameGenerator('ipython.component')
105
106
107 class MetaComponent(MetaHasTraitlets, MetaComponentTracker):
108 pass
109
110
111 #-----------------------------------------------------------------------------
112 # Component implementation
113 #-----------------------------------------------------------------------------
114
115
116 class Component(HasTraitlets):
117
118 __metaclass__ = MetaComponent
119
120 config = Config()
121
122 def __init__(self, parent, name=None, config=None):
123 """Create a component given a parent.
124
125 Parameters
126 ----------
127 parent : Component subclass
128 The parent in the component graph. The parent is used
129 to get the root of the component graph.
130 name : str
131 The unique name of the component. If empty, then a unique
132 one will be autogenerated.
133 config : Config
134 If this is empty, self.config = root.config, otherwise
135 self.config = config and root.config is ignored. This argument
136 should be used to pass the config to the root. Otherwise, it
137 can be used to *override* the inheritance of root.config. If a
138 caller wants to modify root.config (not override), the caller
139 should make a copy and change attributes and then pass the copy
140 to this argument. We might think about changing this behavior.
141 """
142 super(Component, self).__init__()
143 if name is None:
144 self._name = ComponentNameGenerator()
145 else:
146 self._name = name
147 self.parent = parent # this uses the property and handles None
148 if config is not None:
149 self.config = config
150 else:
151 if self.parent is not None:
152 self.config = self.parent.config
153
154 #-------------------------------------------------------------------------
155 # Properties
156 #-------------------------------------------------------------------------
157
158 def _set_name(self, name):
159 # This should use the ComponentNameGenerator to test for uniqueness
160 self._name = name
161
162 def _get_name(self):
163 return self._name
164
165 name = property(_get_name, _set_name)
166
167 def _set_parent(self, parent):
168 if parent is None:
169 self._parent = None
170 self._root = self
171 else:
172 assert isinstance(parent, Component), 'parent must be a component'
173 self._parent = parent
174 self._root = parent.root
175
176 def _get_parent(self):
177 return self._parent
178
179 parent = property(_get_parent, _set_parent)
180
181 @property
182 def root(self):
183 return self._root
184
@@ -0,0 +1,324 b''
1 #!/usr/bin/env python
2 # encoding: utf-8
3 """
4 A lightweight Traits like module.
5
6 Authors:
7
8 * Brian Granger
9 * Enthought, Inc. Some of the code in this file comes from enthought.traits
10 and is licensed under the BSD license. Also, many of the ideas also come
11 from enthought.traits even though our implementation is very different.
12 """
13
14 #-----------------------------------------------------------------------------
15 # Copyright (C) 2008-2009 The IPython Development Team
16 #
17 # Distributed under the terms of the BSD License. The full license is in
18 # the file COPYING, distributed as part of this software.
19 #-----------------------------------------------------------------------------
20
21 #-----------------------------------------------------------------------------
22 # Imports
23 #-----------------------------------------------------------------------------
24
25 import inspect
26 import types
27 from types import InstanceType
28
29 #-----------------------------------------------------------------------------
30 # Basic classes
31 #-----------------------------------------------------------------------------
32
33
34 class NoDefaultSpecified ( object ): pass
35 NoDefaultSpecified = NoDefaultSpecified()
36
37
38 class Undefined ( object ): pass
39 Undefined = Undefined()
40
41
42 class TraitletError(Exception):
43 pass
44
45
46 #-----------------------------------------------------------------------------
47 # Utilities
48 #-----------------------------------------------------------------------------
49
50
51 def class_of ( object ):
52 """ Returns a string containing the class name of an object with the
53 correct indefinite article ('a' or 'an') preceding it (e.g., 'an Image',
54 'a PlotValue').
55 """
56 if isinstance( object, basestring ):
57 return add_article( object )
58
59 return add_article( object.__class__.__name__ )
60
61
62 def add_article ( name ):
63 """ Returns a string containing the correct indefinite article ('a' or 'an')
64 prefixed to the specified string.
65 """
66 if name[:1].lower() in 'aeiou':
67 return 'an ' + name
68
69 return 'a ' + name
70
71
72 def repr_type(obj):
73 """ Return a string representation of a value and its type for readable
74 error messages.
75 """
76 the_type = type(obj)
77 if the_type is InstanceType:
78 # Old-style class.
79 the_type = obj.__class__
80 msg = '%r %r' % (obj, the_type)
81 return msg
82
83
84 def parse_notifier_name(name):
85 if isinstance(name, str):
86 return [name]
87 elif name is None:
88 return ['anytraitlet']
89 elif isinstance(name, (list, tuple)):
90 for n in name:
91 assert isinstance(n, str), "names must be strings"
92 return name
93
94
95 #-----------------------------------------------------------------------------
96 # Base TraitletType for all traitlets
97 #-----------------------------------------------------------------------------
98
99
100 class TraitletType(object):
101
102 metadata = {}
103 default_value = None
104 info_text = 'any value'
105
106 # def __init__(self, name, default_value=NoDefaultSpecified, **metadata):
107 # self.name = name
108 def __init__(self, default_value=NoDefaultSpecified, **metadata):
109 if default_value is not NoDefaultSpecified:
110 self.default_value = default_value
111 self.metadata.update(metadata)
112
113 def __get__(self, inst, cls=None):
114 if inst is None:
115 return self
116 else:
117 return inst._traitlet_values.get(self.name, self.default_value)
118
119 def __set__(self, inst, value):
120 new_value = self._validate(inst, value)
121 old_value = self.__get__(inst)
122 if old_value != new_value:
123 inst._traitlet_values[self.name] = new_value
124 inst._notify(self.name, old_value, value)
125
126 def _validate(self, inst, value):
127 if hasattr(self, 'validate'):
128 return self.validate(inst, value)
129 elif hasattr(self, 'is_valid_for'):
130 valid = self.is_valid_for(value)
131 if valid:
132 return value
133 else:
134 raise TraitletError('invalid value for type: %r' % value)
135 elif hasattr(self, 'value_for'):
136 return self.value_for(value)
137 else:
138 return value
139
140 def info(self):
141 return self.info_text
142
143 def error(self, obj, value):
144 if obj is not None:
145 e = "The '%s' traitlet of %s instance must be %s, but a value of %s was specified." \
146 % (self.name, class_of(obj),
147 self.info(), repr_type(value))
148 else:
149 e = "The '%s' traitlet must be %s, but a value of %r was specified." \
150 % (self.name, self.info(), repr_type(value))
151 raise TraitletError(e)
152
153
154 #-----------------------------------------------------------------------------
155 # The HasTraitlets implementation
156 #-----------------------------------------------------------------------------
157
158
159 class MetaHasTraitlets(type):
160 """A metaclass for HasTraitlets.
161
162 This metaclass makes sure that any TraitletType class attributes are
163 instantiated and sets their name attribute.
164 """
165
166 def __new__(mcls, name, bases, classdict):
167 for k,v in classdict.iteritems():
168 if isinstance(v, TraitletType):
169 v.name = k
170 elif inspect.isclass(v):
171 if issubclass(v, TraitletType):
172 vinst = v()
173 vinst.name = k
174 classdict[k] = vinst
175 return super(MetaHasTraitlets, mcls).__new__(mcls, name, bases, classdict)
176
177
178 class HasTraitlets(object):
179
180 __metaclass__ = MetaHasTraitlets
181
182 def __init__(self):
183 self._traitlet_values = {}
184 self._notifiers = {}
185
186 def _notify(self, name, old_value, new_value):
187 callables = self._notifiers.get(name,[])
188 more_callables = self._notifiers.get('anytraitlet',[])
189 callables.extend(more_callables)
190 for c in callables:
191 # Traits catches and logs errors here. I allow them to raise
192 c(name, old_value, new_value)
193
194 def _add_notifiers(self, handler, name):
195 if not self._notifiers.has_key(name):
196 nlist = []
197 self._notifiers[name] = nlist
198 else:
199 nlist = self._notifiers[name]
200 if handler not in nlist:
201 nlist.append(handler)
202
203 def _remove_notifiers(self, handler, name):
204 if self._notifiers.has_key(name):
205 nlist = self._notifiers[name]
206 try:
207 index = nlist.index(handler)
208 except ValueError:
209 pass
210 else:
211 del nlist[index]
212
213 def on_traitlet_change(self, handler, name=None, remove=False):
214 if remove:
215 names = parse_notifier_name(name)
216 for n in names:
217 self._remove_notifiers(handler, n)
218 else:
219 names = parse_notifier_name(name)
220 for n in names:
221 self._add_notifiers(handler, n)
222
223
224 #-----------------------------------------------------------------------------
225 # Actual TraitletTypes implementations/subclasses
226 #-----------------------------------------------------------------------------
227
228
229 class Any(TraitletType):
230 default_value = None
231 info_text = 'any value'
232
233
234 class Int(TraitletType):
235
236 evaluate = int
237 default_value = 0
238 info_text = 'an integer'
239
240 def validate(self, obj, value):
241 if isinstance(value, int):
242 return value
243 self.error(obj, value)
244
245
246 class Long(TraitletType):
247
248 evaluate = long
249 default_value = 0L
250 info_text = 'a long'
251
252 def validate(self, obj, value):
253 if isinstance(value, long):
254 return value
255 if isinstance(value, int):
256 return long(value)
257 self.error(obj, value)
258
259
260 class Float(TraitletType):
261
262 evaluate = float
263 default_value = 0.0
264 info_text = 'a float'
265
266 def validate(self, obj, value):
267 if isinstance(value, float):
268 return value
269 if isinstance(value, int):
270 return float(value)
271 self.error(obj, value)
272
273
274 class Complex(TraitletType):
275
276 evaluate = complex
277 default_value = 0.0 + 0.0j
278 info_text = 'a complex number'
279
280 def validate(self, obj, value):
281 if isinstance(value, complex):
282 return value
283 if isinstance(value, (float, int)):
284 return complex(value)
285 self.error(obj, value)
286
287
288 class Str(TraitletType):
289
290 evaluate = lambda x: x
291 default_value = ''
292 info_text = 'a string'
293
294 def validate(self, obj, value):
295 if isinstance(value, str):
296 return value
297 self.error(obj, value)
298
299
300 class Unicode(TraitletType):
301
302 evaluate = unicode
303 default_value = u''
304 info_text = 'a unicode string'
305
306 def validate(self, obj, value):
307 if isinstance(value, unicode):
308 return value
309 if isinstance(value, str):
310 return unicode(value)
311 self.error(obj, value)
312
313
314 class Bool(TraitletType):
315
316 evaluate = bool
317 default_value = False
318 info_text = 'a boolean'
319
320 def validate(self, obj, value):
321 if isinstance(value, bool):
322 return value
323 self.error(obj, value)
324
@@ -1,273 +1,274 b''
1 # -*- coding: utf-8 -*-
1 #!/usr/bin/env python
2 # encoding: utf-8
2 """IPython Shell classes.
3 """IPython Shell classes.
3
4
4 Originally, this module was horribly complicated because of the need to
5 Originally, this module was horribly complicated because of the need to
5 use threads to integrate with GUI toolkit event loops. Now, we are using
6 use threads to integrate with GUI toolkit event loops. Now, we are using
6 the :mod:`IPython.lib.inputhook`, which is based on PyOS_InputHook. This
7 the :mod:`IPython.lib.inputhook`, which is based on PyOS_InputHook. This
7 dramatically simplifies this logic and allow 3rd party packages (such as
8 dramatically simplifies this logic and allow 3rd party packages (such as
8 matplotlib) to handle these things by themselves.
9 matplotlib) to handle these things by themselves.
9
10
10 This new approach also allows projects like matplotlib to work interactively
11 This new approach also allows projects like matplotlib to work interactively
11 in the standard python shell.
12 in the standard python shell.
12 """
13 """
13
14
14 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
15 # Copyright (C) 2008-2009 The IPython Development Team
16 # Copyright (C) 2008-2009 The IPython Development Team
16 #
17 #
17 # Distributed under the terms of the BSD License. The full license is in
18 # Distributed under the terms of the BSD License. The full license is in
18 # the file COPYING, distributed as part of this software.
19 # the file COPYING, distributed as part of this software.
19 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
20
21
21 #-----------------------------------------------------------------------------
22 #-----------------------------------------------------------------------------
22 # Imports
23 # Imports
23 #-----------------------------------------------------------------------------
24 #-----------------------------------------------------------------------------
24
25
25 import sys
26 import sys
26
27
27 from IPython.core import ultratb
28 from IPython.core import ultratb
28 from IPython.core import ipapi
29 from IPython.core import ipapi
29 from IPython.utils.genutils import ask_yes_no
30 from IPython.utils.genutils import ask_yes_no
30 from IPython.core.iplib import InteractiveShell
31 from IPython.core.iplib import InteractiveShell
31 from IPython.core.ipmaker import make_IPython
32 from IPython.core.ipmaker import make_IPython
32
33
33 #-----------------------------------------------------------------------------
34 #-----------------------------------------------------------------------------
34 # Code
35 # Code
35 #-----------------------------------------------------------------------------
36 #-----------------------------------------------------------------------------
36
37
37
38
38 class IPShell:
39 class IPShell:
39 """Create an IPython instance.
40 """Create an IPython instance.
40
41
41 This calls the factory :func:`make_IPython`, which creates a configured
42 This calls the factory :func:`make_IPython`, which creates a configured
42 :class:`InteractiveShell` object, and presents the result as a simple
43 :class:`InteractiveShell` object, and presents the result as a simple
43 class with a :meth:`mainloop` method.
44 class with a :meth:`mainloop` method.
44 """
45 """
45
46
46 def __init__(self, argv=None, user_ns=None, user_global_ns=None,
47 def __init__(self, argv=None, user_ns=None, user_global_ns=None,
47 debug=1, shell_class=InteractiveShell):
48 debug=1, shell_class=InteractiveShell):
48 self.IP = make_IPython(argv, user_ns=user_ns,
49 self.IP = make_IPython(argv, user_ns=user_ns,
49 user_global_ns=user_global_ns,
50 user_global_ns=user_global_ns,
50 debug=debug, shell_class=shell_class)
51 debug=debug, shell_class=shell_class)
51
52
52 def mainloop(self,sys_exit=0,banner=None):
53 def mainloop(self,sys_exit=0,banner=None):
53 self.IP.mainloop(banner)
54 self.IP.mainloop(banner)
54 if sys_exit:
55 if sys_exit:
55 sys.exit()
56 sys.exit()
56
57
57
58
58 # This is an additional magic that is exposed in embedded shells.
59 # This is an additional magic that is exposed in embedded shells.
59 def kill_embedded(self,parameter_s=''):
60 def kill_embedded(self,parameter_s=''):
60 """%kill_embedded : deactivate for good the current embedded IPython.
61 """%kill_embedded : deactivate for good the current embedded IPython.
61
62
62 This function (after asking for confirmation) sets an internal flag so that
63 This function (after asking for confirmation) sets an internal flag so that
63 an embedded IPython will never activate again. This is useful to
64 an embedded IPython will never activate again. This is useful to
64 permanently disable a shell that is being called inside a loop: once you've
65 permanently disable a shell that is being called inside a loop: once you've
65 figured out what you needed from it, you may then kill it and the program
66 figured out what you needed from it, you may then kill it and the program
66 will then continue to run without the interactive shell interfering again.
67 will then continue to run without the interactive shell interfering again.
67 """
68 """
68
69
69 kill = ask_yes_no("Are you sure you want to kill this embedded instance "
70 kill = ask_yes_no("Are you sure you want to kill this embedded instance "
70 "(y/n)? [y/N] ",'n')
71 "(y/n)? [y/N] ",'n')
71 if kill:
72 if kill:
72 self.shell.embedded_active = False
73 self.shell.embedded_active = False
73 print "This embedded IPython will not reactivate anymore once you exit."
74 print "This embedded IPython will not reactivate anymore once you exit."
74
75
75
76
76 class IPShellEmbed:
77 class IPShellEmbed:
77 """Allow embedding an IPython shell into a running program.
78 """Allow embedding an IPython shell into a running program.
78
79
79 Instances of this class are callable, with the __call__ method being an
80 Instances of this class are callable, with the __call__ method being an
80 alias to the embed() method of an InteractiveShell instance.
81 alias to the embed() method of an InteractiveShell instance.
81
82
82 Usage (see also the example-embed.py file for a running example)::
83 Usage (see also the example-embed.py file for a running example)::
83
84
84 ipshell = IPShellEmbed([argv,banner,exit_msg,rc_override])
85 ipshell = IPShellEmbed([argv,banner,exit_msg,rc_override])
85
86
86 * argv: list containing valid command-line options for IPython, as they
87 * argv: list containing valid command-line options for IPython, as they
87 would appear in sys.argv[1:].
88 would appear in sys.argv[1:].
88
89
89 For example, the following command-line options::
90 For example, the following command-line options::
90
91
91 $ ipython -prompt_in1 'Input <\\#>' -colors LightBG
92 $ ipython -prompt_in1 'Input <\\#>' -colors LightBG
92
93
93 would be passed in the argv list as::
94 would be passed in the argv list as::
94
95
95 ['-prompt_in1','Input <\\#>','-colors','LightBG']
96 ['-prompt_in1','Input <\\#>','-colors','LightBG']
96
97
97 * banner: string which gets printed every time the interpreter starts.
98 * banner: string which gets printed every time the interpreter starts.
98
99
99 * exit_msg: string which gets printed every time the interpreter exits.
100 * exit_msg: string which gets printed every time the interpreter exits.
100
101
101 * rc_override: a dict or Struct of configuration options such as those
102 * rc_override: a dict or Struct of configuration options such as those
102 used by IPython. These options are read from your ~/.ipython/ipythonrc
103 used by IPython. These options are read from your ~/.ipython/ipythonrc
103 file when the Shell object is created. Passing an explicit rc_override
104 file when the Shell object is created. Passing an explicit rc_override
104 dict with any options you want allows you to override those values at
105 dict with any options you want allows you to override those values at
105 creation time without having to modify the file. This way you can create
106 creation time without having to modify the file. This way you can create
106 embeddable instances configured in any way you want without editing any
107 embeddable instances configured in any way you want without editing any
107 global files (thus keeping your interactive IPython configuration
108 global files (thus keeping your interactive IPython configuration
108 unchanged).
109 unchanged).
109
110
110 Then the ipshell instance can be called anywhere inside your code::
111 Then the ipshell instance can be called anywhere inside your code::
111
112
112 ipshell(header='') -> Opens up an IPython shell.
113 ipshell(header='') -> Opens up an IPython shell.
113
114
114 * header: string printed by the IPython shell upon startup. This can let
115 * header: string printed by the IPython shell upon startup. This can let
115 you know where in your code you are when dropping into the shell. Note
116 you know where in your code you are when dropping into the shell. Note
116 that 'banner' gets prepended to all calls, so header is used for
117 that 'banner' gets prepended to all calls, so header is used for
117 location-specific information.
118 location-specific information.
118
119
119 For more details, see the __call__ method below.
120 For more details, see the __call__ method below.
120
121
121 When the IPython shell is exited with Ctrl-D, normal program execution
122 When the IPython shell is exited with Ctrl-D, normal program execution
122 resumes.
123 resumes.
123
124
124 This functionality was inspired by a posting on comp.lang.python by cmkl
125 This functionality was inspired by a posting on comp.lang.python by cmkl
125 <cmkleffner@gmx.de> on Dec. 06/01 concerning similar uses of pyrepl, and
126 <cmkleffner@gmx.de> on Dec. 06/01 concerning similar uses of pyrepl, and
126 by the IDL stop/continue commands.
127 by the IDL stop/continue commands.
127 """
128 """
128
129
129 def __init__(self, argv=None, banner='', exit_msg=None,
130 def __init__(self, argv=None, banner='', exit_msg=None,
130 rc_override=None, user_ns=None):
131 rc_override=None, user_ns=None):
131 """Note that argv here is a string, NOT a list."""
132 """Note that argv here is a string, NOT a list."""
132
133
133 self.set_banner(banner)
134 self.set_banner(banner)
134 self.set_exit_msg(exit_msg)
135 self.set_exit_msg(exit_msg)
135 self.set_dummy_mode(0)
136 self.set_dummy_mode(0)
136
137
137 # sys.displayhook is a global, we need to save the user's original
138 # sys.displayhook is a global, we need to save the user's original
138 # Don't rely on __displayhook__, as the user may have changed that.
139 # Don't rely on __displayhook__, as the user may have changed that.
139 self.sys_displayhook_ori = sys.displayhook
140 self.sys_displayhook_ori = sys.displayhook
140
141
141 # save readline completer status
142 # save readline completer status
142 try:
143 try:
143 #print 'Save completer',sys.ipcompleter # dbg
144 #print 'Save completer',sys.ipcompleter # dbg
144 self.sys_ipcompleter_ori = sys.ipcompleter
145 self.sys_ipcompleter_ori = sys.ipcompleter
145 except:
146 except:
146 pass # not nested with IPython
147 pass # not nested with IPython
147
148
148 self.IP = make_IPython(argv,rc_override=rc_override,
149 self.IP = make_IPython(argv,rc_override=rc_override,
149 embedded=True,
150 embedded=True,
150 user_ns=user_ns)
151 user_ns=user_ns)
151
152
152 ip = ipapi.IPApi(self.IP)
153 ip = ipapi.IPApi(self.IP)
153 ip.expose_magic("kill_embedded",kill_embedded)
154 ip.expose_magic("kill_embedded",kill_embedded)
154
155
155 # copy our own displayhook also
156 # copy our own displayhook also
156 self.sys_displayhook_embed = sys.displayhook
157 self.sys_displayhook_embed = sys.displayhook
157 # and leave the system's display hook clean
158 # and leave the system's display hook clean
158 sys.displayhook = self.sys_displayhook_ori
159 sys.displayhook = self.sys_displayhook_ori
159 # don't use the ipython crash handler so that user exceptions aren't
160 # don't use the ipython crash handler so that user exceptions aren't
160 # trapped
161 # trapped
161 sys.excepthook = ultratb.FormattedTB(color_scheme = self.IP.rc.colors,
162 sys.excepthook = ultratb.FormattedTB(color_scheme = self.IP.rc.colors,
162 mode = self.IP.rc.xmode,
163 mode = self.IP.rc.xmode,
163 call_pdb = self.IP.rc.pdb)
164 call_pdb = self.IP.rc.pdb)
164 self.restore_system_completer()
165 self.restore_system_completer()
165
166
166 def restore_system_completer(self):
167 def restore_system_completer(self):
167 """Restores the readline completer which was in place.
168 """Restores the readline completer which was in place.
168
169
169 This allows embedded IPython within IPython not to disrupt the
170 This allows embedded IPython within IPython not to disrupt the
170 parent's completion.
171 parent's completion.
171 """
172 """
172
173
173 try:
174 try:
174 self.IP.readline.set_completer(self.sys_ipcompleter_ori)
175 self.IP.readline.set_completer(self.sys_ipcompleter_ori)
175 sys.ipcompleter = self.sys_ipcompleter_ori
176 sys.ipcompleter = self.sys_ipcompleter_ori
176 except:
177 except:
177 pass
178 pass
178
179
179 def __call__(self, header='', local_ns=None, global_ns=None, dummy=None):
180 def __call__(self, header='', local_ns=None, global_ns=None, dummy=None):
180 """Activate the interactive interpreter.
181 """Activate the interactive interpreter.
181
182
182 __call__(self,header='',local_ns=None,global_ns,dummy=None) -> Start
183 __call__(self,header='',local_ns=None,global_ns,dummy=None) -> Start
183 the interpreter shell with the given local and global namespaces, and
184 the interpreter shell with the given local and global namespaces, and
184 optionally print a header string at startup.
185 optionally print a header string at startup.
185
186
186 The shell can be globally activated/deactivated using the
187 The shell can be globally activated/deactivated using the
187 set/get_dummy_mode methods. This allows you to turn off a shell used
188 set/get_dummy_mode methods. This allows you to turn off a shell used
188 for debugging globally.
189 for debugging globally.
189
190
190 However, *each* time you call the shell you can override the current
191 However, *each* time you call the shell you can override the current
191 state of dummy_mode with the optional keyword parameter 'dummy'. For
192 state of dummy_mode with the optional keyword parameter 'dummy'. For
192 example, if you set dummy mode on with IPShell.set_dummy_mode(1), you
193 example, if you set dummy mode on with IPShell.set_dummy_mode(1), you
193 can still have a specific call work by making it as IPShell(dummy=0).
194 can still have a specific call work by making it as IPShell(dummy=0).
194
195
195 The optional keyword parameter dummy controls whether the call
196 The optional keyword parameter dummy controls whether the call
196 actually does anything.
197 actually does anything.
197 """
198 """
198
199
199 # If the user has turned it off, go away
200 # If the user has turned it off, go away
200 if not self.IP.embedded_active:
201 if not self.IP.embedded_active:
201 return
202 return
202
203
203 # Normal exits from interactive mode set this flag, so the shell can't
204 # Normal exits from interactive mode set this flag, so the shell can't
204 # re-enter (it checks this variable at the start of interactive mode).
205 # re-enter (it checks this variable at the start of interactive mode).
205 self.IP.exit_now = False
206 self.IP.exit_now = False
206
207
207 # Allow the dummy parameter to override the global __dummy_mode
208 # Allow the dummy parameter to override the global __dummy_mode
208 if dummy or (dummy != 0 and self.__dummy_mode):
209 if dummy or (dummy != 0 and self.__dummy_mode):
209 return
210 return
210
211
211 # Set global subsystems (display,completions) to our values
212 # Set global subsystems (display,completions) to our values
212 sys.displayhook = self.sys_displayhook_embed
213 sys.displayhook = self.sys_displayhook_embed
213 if self.IP.has_readline:
214 if self.IP.has_readline:
214 self.IP.set_completer()
215 self.IP.set_completer()
215
216
216 if self.banner and header:
217 if self.banner and header:
217 format = '%s\n%s\n'
218 format = '%s\n%s\n'
218 else:
219 else:
219 format = '%s%s\n'
220 format = '%s%s\n'
220 banner = format % (self.banner,header)
221 banner = format % (self.banner,header)
221
222
222 # Call the embedding code with a stack depth of 1 so it can skip over
223 # Call the embedding code with a stack depth of 1 so it can skip over
223 # our call and get the original caller's namespaces.
224 # our call and get the original caller's namespaces.
224 self.IP.embed_mainloop(banner,local_ns,global_ns,stack_depth=1)
225 self.IP.embed_mainloop(banner,local_ns,global_ns,stack_depth=1)
225
226
226 if self.exit_msg:
227 if self.exit_msg:
227 print self.exit_msg
228 print self.exit_msg
228
229
229 # Restore global systems (display, completion)
230 # Restore global systems (display, completion)
230 sys.displayhook = self.sys_displayhook_ori
231 sys.displayhook = self.sys_displayhook_ori
231 self.restore_system_completer()
232 self.restore_system_completer()
232
233
233 def set_dummy_mode(self, dummy):
234 def set_dummy_mode(self, dummy):
234 """Sets the embeddable shell's dummy mode parameter.
235 """Sets the embeddable shell's dummy mode parameter.
235
236
236 set_dummy_mode(dummy): dummy = 0 or 1.
237 set_dummy_mode(dummy): dummy = 0 or 1.
237
238
238 This parameter is persistent and makes calls to the embeddable shell
239 This parameter is persistent and makes calls to the embeddable shell
239 silently return without performing any action. This allows you to
240 silently return without performing any action. This allows you to
240 globally activate or deactivate a shell you're using with a single call.
241 globally activate or deactivate a shell you're using with a single call.
241
242
242 If you need to manually"""
243 If you need to manually"""
243
244
244 if dummy not in [0,1,False,True]:
245 if dummy not in [0,1,False,True]:
245 raise ValueError,'dummy parameter must be boolean'
246 raise ValueError,'dummy parameter must be boolean'
246 self.__dummy_mode = dummy
247 self.__dummy_mode = dummy
247
248
248 def get_dummy_mode(self):
249 def get_dummy_mode(self):
249 """Return the current value of the dummy mode parameter.
250 """Return the current value of the dummy mode parameter.
250 """
251 """
251 return self.__dummy_mode
252 return self.__dummy_mode
252
253
253 def set_banner(self, banner):
254 def set_banner(self, banner):
254 """Sets the global banner.
255 """Sets the global banner.
255
256
256 This banner gets prepended to every header printed when the shell
257 This banner gets prepended to every header printed when the shell
257 instance is called."""
258 instance is called."""
258
259
259 self.banner = banner
260 self.banner = banner
260
261
261 def set_exit_msg(self, exit_msg):
262 def set_exit_msg(self, exit_msg):
262 """Sets the global exit_msg.
263 """Sets the global exit_msg.
263
264
264 This exit message gets printed upon exiting every time the embedded
265 This exit message gets printed upon exiting every time the embedded
265 shell is called. It is None by default. """
266 shell is called. It is None by default. """
266
267
267 self.exit_msg = exit_msg
268 self.exit_msg = exit_msg
268
269
269 # This is the one which should be called by external code.
270 # This is the one which should be called by external code.
270 def start(user_ns = None):
271 def start(user_ns = None):
271 """Return a running shell instance of :class:`IPShell`."""
272 """Return a running shell instance of :class:`IPShell`."""
272 return IPShell(user_ns = user_ns)
273 return IPShell(user_ns = user_ns)
273
274
General Comments 0
You need to be logged in to leave comments. Login now