##// END OF EJS Templates
Final changes traitlet -> trait for review
Dav Clark -
Show More
@@ -1,325 +1,325 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # encoding: utf-8
2 # encoding: utf-8
3 """
3 """
4 A lightweight component system for IPython.
4 A lightweight component system for IPython.
5
5
6 Authors:
6 Authors:
7
7
8 * Brian Granger
8 * Brian Granger
9 * Fernando Perez
9 * Fernando Perez
10 """
10 """
11
11
12 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
13 # Copyright (C) 2008-2009 The IPython Development Team
13 # Copyright (C) 2008-2009 The IPython Development Team
14 #
14 #
15 # Distributed under the terms of the BSD License. The full license is in
15 # Distributed under the terms of the BSD License. The full license is in
16 # the file COPYING, distributed as part of this software.
16 # the file COPYING, distributed as part of this software.
17 #-----------------------------------------------------------------------------
17 #-----------------------------------------------------------------------------
18
18
19 #-----------------------------------------------------------------------------
19 #-----------------------------------------------------------------------------
20 # Imports
20 # Imports
21 #-----------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
22
22
23 from copy import deepcopy
23 from copy import deepcopy
24 import datetime
24 import datetime
25 from weakref import WeakValueDictionary
25 from weakref import WeakValueDictionary
26
26
27 from IPython.utils.importstring import import_item
27 from IPython.utils.importstring import import_item
28 from IPython.config.loader import Config
28 from IPython.config.loader import Config
29 from IPython.utils.traitlets import (
29 from IPython.utils.traitlets import (
30 HasTraits, TraitletError, MetaHasTraits, Instance, This
30 HasTraits, TraitError, MetaHasTraits, Instance, This
31 )
31 )
32
32
33
33
34 #-----------------------------------------------------------------------------
34 #-----------------------------------------------------------------------------
35 # Helper classes for Components
35 # Helper classes for Components
36 #-----------------------------------------------------------------------------
36 #-----------------------------------------------------------------------------
37
37
38
38
39 class ComponentError(Exception):
39 class ComponentError(Exception):
40 pass
40 pass
41
41
42 class MetaComponentTracker(type):
42 class MetaComponentTracker(type):
43 """A metaclass that tracks instances of Components and its subclasses."""
43 """A metaclass that tracks instances of Components and its subclasses."""
44
44
45 def __init__(cls, name, bases, d):
45 def __init__(cls, name, bases, d):
46 super(MetaComponentTracker, cls).__init__(name, bases, d)
46 super(MetaComponentTracker, cls).__init__(name, bases, d)
47 cls.__instance_refs = WeakValueDictionary()
47 cls.__instance_refs = WeakValueDictionary()
48 cls.__numcreated = 0
48 cls.__numcreated = 0
49
49
50 def __call__(cls, *args, **kw):
50 def __call__(cls, *args, **kw):
51 """Called when a class is called (instantiated)!!!
51 """Called when a class is called (instantiated)!!!
52
52
53 When a Component or subclass is instantiated, this is called and
53 When a Component or subclass is instantiated, this is called and
54 the instance is saved in a WeakValueDictionary for tracking.
54 the instance is saved in a WeakValueDictionary for tracking.
55 """
55 """
56 instance = cls.__new__(cls, *args, **kw)
56 instance = cls.__new__(cls, *args, **kw)
57
57
58 # Register the instance before __init__ is called so get_instances
58 # Register the instance before __init__ is called so get_instances
59 # works inside __init__ methods!
59 # works inside __init__ methods!
60 indices = cls.register_instance(instance)
60 indices = cls.register_instance(instance)
61
61
62 # This is in a try/except because of the __init__ method fails, the
62 # This is in a try/except because of the __init__ method fails, the
63 # instance is discarded and shouldn't be tracked.
63 # instance is discarded and shouldn't be tracked.
64 try:
64 try:
65 if isinstance(instance, cls):
65 if isinstance(instance, cls):
66 cls.__init__(instance, *args, **kw)
66 cls.__init__(instance, *args, **kw)
67 except:
67 except:
68 # Unregister the instance because __init__ failed!
68 # Unregister the instance because __init__ failed!
69 cls.unregister_instances(indices)
69 cls.unregister_instances(indices)
70 raise
70 raise
71 else:
71 else:
72 return instance
72 return instance
73
73
74 def register_instance(cls, instance):
74 def register_instance(cls, instance):
75 """Register instance with cls and its subclasses."""
75 """Register instance with cls and its subclasses."""
76 # indices is a list of the keys used to register the instance
76 # indices is a list of the keys used to register the instance
77 # with. This list is needed if the instance needs to be unregistered.
77 # with. This list is needed if the instance needs to be unregistered.
78 indices = []
78 indices = []
79 for c in cls.__mro__:
79 for c in cls.__mro__:
80 if issubclass(cls, c) and issubclass(c, Component):
80 if issubclass(cls, c) and issubclass(c, Component):
81 c.__numcreated += 1
81 c.__numcreated += 1
82 indices.append(c.__numcreated)
82 indices.append(c.__numcreated)
83 c.__instance_refs[c.__numcreated] = instance
83 c.__instance_refs[c.__numcreated] = instance
84 else:
84 else:
85 break
85 break
86 return indices
86 return indices
87
87
88 def unregister_instances(cls, indices):
88 def unregister_instances(cls, indices):
89 """Unregister instance with cls and its subclasses."""
89 """Unregister instance with cls and its subclasses."""
90 for c, index in zip(cls.__mro__, indices):
90 for c, index in zip(cls.__mro__, indices):
91 try:
91 try:
92 del c.__instance_refs[index]
92 del c.__instance_refs[index]
93 except KeyError:
93 except KeyError:
94 pass
94 pass
95
95
96 def clear_instances(cls):
96 def clear_instances(cls):
97 """Clear all instances tracked by cls."""
97 """Clear all instances tracked by cls."""
98 cls.__instance_refs.clear()
98 cls.__instance_refs.clear()
99 cls.__numcreated = 0
99 cls.__numcreated = 0
100
100
101 def get_instances(cls, name=None, root=None, klass=None):
101 def get_instances(cls, name=None, root=None, klass=None):
102 """Get all instances of cls and its subclasses.
102 """Get all instances of cls and its subclasses.
103
103
104 Parameters
104 Parameters
105 ----------
105 ----------
106 name : str
106 name : str
107 Limit to components with this name.
107 Limit to components with this name.
108 root : Component or subclass
108 root : Component or subclass
109 Limit to components having this root.
109 Limit to components having this root.
110 klass : class or str
110 klass : class or str
111 Limits to instances of the class or its subclasses. If a str
111 Limits to instances of the class or its subclasses. If a str
112 is given ut must be in the form 'foo.bar.MyClass'. The str
112 is given ut must be in the form 'foo.bar.MyClass'. The str
113 form of this argument is useful for forward declarations.
113 form of this argument is useful for forward declarations.
114 """
114 """
115 if klass is not None:
115 if klass is not None:
116 if isinstance(klass, basestring):
116 if isinstance(klass, basestring):
117 klass = import_item(klass)
117 klass = import_item(klass)
118 # Limit search to instances of klass for performance
118 # Limit search to instances of klass for performance
119 if issubclass(klass, Component):
119 if issubclass(klass, Component):
120 return klass.get_instances(name=name, root=root)
120 return klass.get_instances(name=name, root=root)
121 instances = cls.__instance_refs.values()
121 instances = cls.__instance_refs.values()
122 if name is not None:
122 if name is not None:
123 instances = [i for i in instances if i.name == name]
123 instances = [i for i in instances if i.name == name]
124 if klass is not None:
124 if klass is not None:
125 instances = [i for i in instances if isinstance(i, klass)]
125 instances = [i for i in instances if isinstance(i, klass)]
126 if root is not None:
126 if root is not None:
127 instances = [i for i in instances if i.root == root]
127 instances = [i for i in instances if i.root == root]
128 return instances
128 return instances
129
129
130 def get_instances_by_condition(cls, call, name=None, root=None,
130 def get_instances_by_condition(cls, call, name=None, root=None,
131 klass=None):
131 klass=None):
132 """Get all instances of cls, i such that call(i)==True.
132 """Get all instances of cls, i such that call(i)==True.
133
133
134 This also takes the ``name`` and ``root`` and ``classname``
134 This also takes the ``name`` and ``root`` and ``classname``
135 arguments of :meth:`get_instance`
135 arguments of :meth:`get_instance`
136 """
136 """
137 return [i for i in cls.get_instances(name, root, klass) if call(i)]
137 return [i for i in cls.get_instances(name, root, klass) if call(i)]
138
138
139
139
140 def masquerade_as(instance, cls):
140 def masquerade_as(instance, cls):
141 """Let instance masquerade as an instance of cls.
141 """Let instance masquerade as an instance of cls.
142
142
143 Sometimes, such as in testing code, it is useful to let a class
143 Sometimes, such as in testing code, it is useful to let a class
144 masquerade as another. Python, being duck typed, allows this by
144 masquerade as another. Python, being duck typed, allows this by
145 default. But, instances of components are tracked by their class type.
145 default. But, instances of components are tracked by their class type.
146
146
147 After calling this, ``cls.get_instances()`` will return ``instance``. This
147 After calling this, ``cls.get_instances()`` will return ``instance``. This
148 does not, however, cause ``isinstance(instance, cls)`` to return ``True``.
148 does not, however, cause ``isinstance(instance, cls)`` to return ``True``.
149
149
150 Parameters
150 Parameters
151 ----------
151 ----------
152 instance : an instance of a Component or Component subclass
152 instance : an instance of a Component or Component subclass
153 The instance that will pretend to be a cls.
153 The instance that will pretend to be a cls.
154 cls : subclass of Component
154 cls : subclass of Component
155 The Component subclass that instance will pretend to be.
155 The Component subclass that instance will pretend to be.
156 """
156 """
157 cls.register_instance(instance)
157 cls.register_instance(instance)
158
158
159
159
160 class ComponentNameGenerator(object):
160 class ComponentNameGenerator(object):
161 """A Singleton to generate unique component names."""
161 """A Singleton to generate unique component names."""
162
162
163 def __init__(self, prefix):
163 def __init__(self, prefix):
164 self.prefix = prefix
164 self.prefix = prefix
165 self.i = 0
165 self.i = 0
166
166
167 def __call__(self):
167 def __call__(self):
168 count = self.i
168 count = self.i
169 self.i += 1
169 self.i += 1
170 return "%s%s" % (self.prefix, count)
170 return "%s%s" % (self.prefix, count)
171
171
172
172
173 ComponentNameGenerator = ComponentNameGenerator('ipython.component')
173 ComponentNameGenerator = ComponentNameGenerator('ipython.component')
174
174
175
175
176 class MetaComponent(MetaHasTraits, MetaComponentTracker):
176 class MetaComponent(MetaHasTraits, MetaComponentTracker):
177 pass
177 pass
178
178
179
179
180 #-----------------------------------------------------------------------------
180 #-----------------------------------------------------------------------------
181 # Component implementation
181 # Component implementation
182 #-----------------------------------------------------------------------------
182 #-----------------------------------------------------------------------------
183
183
184
184
185 class Component(HasTraits):
185 class Component(HasTraits):
186
186
187 __metaclass__ = MetaComponent
187 __metaclass__ = MetaComponent
188
188
189 # Traitlets are fun!
189 # Traits are fun!
190 config = Instance(Config,(),{})
190 config = Instance(Config,(),{})
191 parent = This()
191 parent = This()
192 root = This()
192 root = This()
193 created = None
193 created = None
194
194
195 def __init__(self, parent, name=None, config=None):
195 def __init__(self, parent, name=None, config=None):
196 """Create a component given a parent and possibly and name and config.
196 """Create a component given a parent and possibly and name and config.
197
197
198 Parameters
198 Parameters
199 ----------
199 ----------
200 parent : Component subclass
200 parent : Component subclass
201 The parent in the component graph. The parent is used
201 The parent in the component graph. The parent is used
202 to get the root of the component graph.
202 to get the root of the component graph.
203 name : str
203 name : str
204 The unique name of the component. If empty, then a unique
204 The unique name of the component. If empty, then a unique
205 one will be autogenerated.
205 one will be autogenerated.
206 config : Config
206 config : Config
207 If this is empty, self.config = parent.config, otherwise
207 If this is empty, self.config = parent.config, otherwise
208 self.config = config and root.config is ignored. This argument
208 self.config = config and root.config is ignored. This argument
209 should only be used to *override* the automatic inheritance of
209 should only be used to *override* the automatic inheritance of
210 parent.config. If a caller wants to modify parent.config
210 parent.config. If a caller wants to modify parent.config
211 (not override), the caller should make a copy and change
211 (not override), the caller should make a copy and change
212 attributes and then pass the copy to this argument.
212 attributes and then pass the copy to this argument.
213
213
214 Notes
214 Notes
215 -----
215 -----
216 Subclasses of Component must call the :meth:`__init__` method of
216 Subclasses of Component must call the :meth:`__init__` method of
217 :class:`Component` *before* doing anything else and using
217 :class:`Component` *before* doing anything else and using
218 :func:`super`::
218 :func:`super`::
219
219
220 class MyComponent(Component):
220 class MyComponent(Component):
221 def __init__(self, parent, name=None, config=None):
221 def __init__(self, parent, name=None, config=None):
222 super(MyComponent, self).__init__(parent, name, config)
222 super(MyComponent, self).__init__(parent, name, config)
223 # Then any other code you need to finish initialization.
223 # Then any other code you need to finish initialization.
224
224
225 This ensures that the :attr:`parent`, :attr:`name` and :attr:`config`
225 This ensures that the :attr:`parent`, :attr:`name` and :attr:`config`
226 attributes are handled properly.
226 attributes are handled properly.
227 """
227 """
228 super(Component, self).__init__()
228 super(Component, self).__init__()
229 self._children = []
229 self._children = []
230 if name is None:
230 if name is None:
231 self.name = ComponentNameGenerator()
231 self.name = ComponentNameGenerator()
232 else:
232 else:
233 self.name = name
233 self.name = name
234 self.root = self # This is the default, it is set when parent is set
234 self.root = self # This is the default, it is set when parent is set
235 self.parent = parent
235 self.parent = parent
236 if config is not None:
236 if config is not None:
237 self.config = config
237 self.config = config
238 # We used to deepcopy, but for now we are trying to just save
238 # We used to deepcopy, but for now we are trying to just save
239 # by reference. This *could* have side effects as all components
239 # by reference. This *could* have side effects as all components
240 # will share config.
240 # will share config.
241 # self.config = deepcopy(config)
241 # self.config = deepcopy(config)
242 else:
242 else:
243 if self.parent is not None:
243 if self.parent is not None:
244 self.config = self.parent.config
244 self.config = self.parent.config
245 # We used to deepcopy, but for now we are trying to just save
245 # We used to deepcopy, but for now we are trying to just save
246 # by reference. This *could* have side effects as all components
246 # by reference. This *could* have side effects as all components
247 # will share config.
247 # will share config.
248 # self.config = deepcopy(self.parent.config)
248 # self.config = deepcopy(self.parent.config)
249
249
250 self.created = datetime.datetime.now()
250 self.created = datetime.datetime.now()
251
251
252 #-------------------------------------------------------------------------
252 #-------------------------------------------------------------------------
253 # Static traitlet notifiations
253 # Static trait notifiations
254 #-------------------------------------------------------------------------
254 #-------------------------------------------------------------------------
255
255
256 def _parent_changed(self, name, old, new):
256 def _parent_changed(self, name, old, new):
257 if old is not None:
257 if old is not None:
258 old._remove_child(self)
258 old._remove_child(self)
259 if new is not None:
259 if new is not None:
260 new._add_child(self)
260 new._add_child(self)
261
261
262 if new is None:
262 if new is None:
263 self.root = self
263 self.root = self
264 else:
264 else:
265 self.root = new.root
265 self.root = new.root
266
266
267 def _root_changed(self, name, old, new):
267 def _root_changed(self, name, old, new):
268 if self.parent is None:
268 if self.parent is None:
269 if not (new is self):
269 if not (new is self):
270 raise ComponentError("Root not self, but parent is None.")
270 raise ComponentError("Root not self, but parent is None.")
271 else:
271 else:
272 if not self.parent.root is new:
272 if not self.parent.root is new:
273 raise ComponentError("Error in setting the root attribute: "
273 raise ComponentError("Error in setting the root attribute: "
274 "root != parent.root")
274 "root != parent.root")
275
275
276 def _config_changed(self, name, old, new):
276 def _config_changed(self, name, old, new):
277 """Update all the class traits having ``config=True`` as metadata.
277 """Update all the class traits having ``config=True`` as metadata.
278
278
279 For any class traitlet with a ``config`` metadata attribute that is
279 For any class trait with a ``config`` metadata attribute that is
280 ``True``, we update the traitlet with the value of the corresponding
280 ``True``, we update the trait with the value of the corresponding
281 config entry.
281 config entry.
282 """
282 """
283 # Get all traitlets with a config metadata entry that is True
283 # Get all traits with a config metadata entry that is True
284 traitlets = self.traits(config=True)
284 traits = self.traits(config=True)
285
285
286 # We auto-load config section for this class as well as any parent
286 # We auto-load config section for this class as well as any parent
287 # classes that are Component subclasses. This starts with Component
287 # classes that are Component subclasses. This starts with Component
288 # and works down the mro loading the config for each section.
288 # and works down the mro loading the config for each section.
289 section_names = [cls.__name__ for cls in \
289 section_names = [cls.__name__ for cls in \
290 reversed(self.__class__.__mro__) if
290 reversed(self.__class__.__mro__) if
291 issubclass(cls, Component) and issubclass(self.__class__, cls)]
291 issubclass(cls, Component) and issubclass(self.__class__, cls)]
292
292
293 for sname in section_names:
293 for sname in section_names:
294 # Don't do a blind getattr as that would cause the config to
294 # Don't do a blind getattr as that would cause the config to
295 # dynamically create the section with name self.__class__.__name__.
295 # dynamically create the section with name self.__class__.__name__.
296 if new._has_section(sname):
296 if new._has_section(sname):
297 my_config = new[sname]
297 my_config = new[sname]
298 for k, v in traitlets.items():
298 for k, v in traits.items():
299 try:
299 try:
300 config_value = my_config[k]
300 config_value = my_config[k]
301 except KeyError:
301 except KeyError:
302 pass
302 pass
303 else:
303 else:
304 # print "Setting %s.%s from %s.%s=%r" % \
304 # print "Setting %s.%s from %s.%s=%r" % \
305 # (self.__class__.__name__,k,sname,k,config_value)
305 # (self.__class__.__name__,k,sname,k,config_value)
306 setattr(self, k, config_value)
306 setattr(self, k, config_value)
307
307
308 @property
308 @property
309 def children(self):
309 def children(self):
310 """A list of all my child components."""
310 """A list of all my child components."""
311 return self._children
311 return self._children
312
312
313 def _remove_child(self, child):
313 def _remove_child(self, child):
314 """A private method for removing children components."""
314 """A private method for removing children components."""
315 if child in self._children:
315 if child in self._children:
316 index = self._children.index(child)
316 index = self._children.index(child)
317 del self._children[index]
317 del self._children[index]
318
318
319 def _add_child(self, child):
319 def _add_child(self, child):
320 """A private method for adding children components."""
320 """A private method for adding children components."""
321 if child not in self._children:
321 if child not in self._children:
322 self._children.append(child)
322 self._children.append(child)
323
323
324 def __repr__(self):
324 def __repr__(self):
325 return "<%s('%s')>" % (self.__class__.__name__, self.name)
325 return "<%s('%s')>" % (self.__class__.__name__, self.name)
@@ -1,2470 +1,2470 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 Main IPython Component
3 Main IPython Component
4 """
4 """
5
5
6 #-----------------------------------------------------------------------------
6 #-----------------------------------------------------------------------------
7 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de>
7 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de>
8 # Copyright (C) 2001-2007 Fernando Perez. <fperez@colorado.edu>
8 # Copyright (C) 2001-2007 Fernando Perez. <fperez@colorado.edu>
9 # Copyright (C) 2008-2009 The IPython Development Team
9 # Copyright (C) 2008-2009 The IPython Development Team
10 #
10 #
11 # Distributed under the terms of the BSD License. The full license is in
11 # Distributed under the terms of the BSD License. The full license is in
12 # the file COPYING, distributed as part of this software.
12 # the file COPYING, distributed as part of this software.
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14
14
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16 # Imports
16 # Imports
17 #-----------------------------------------------------------------------------
17 #-----------------------------------------------------------------------------
18
18
19 from __future__ import with_statement
19 from __future__ import with_statement
20
20
21 import __builtin__
21 import __builtin__
22 import StringIO
22 import StringIO
23 import bdb
23 import bdb
24 import codeop
24 import codeop
25 import exceptions
25 import exceptions
26 import new
26 import new
27 import os
27 import os
28 import re
28 import re
29 import string
29 import string
30 import sys
30 import sys
31 import tempfile
31 import tempfile
32 from contextlib import nested
32 from contextlib import nested
33
33
34 from IPython.core import ultratb
34 from IPython.core import ultratb
35 from IPython.core import debugger, oinspect
35 from IPython.core import debugger, oinspect
36 from IPython.core import shadowns
36 from IPython.core import shadowns
37 from IPython.core import history as ipcorehist
37 from IPython.core import history as ipcorehist
38 from IPython.core import prefilter
38 from IPython.core import prefilter
39 from IPython.core.alias import AliasManager
39 from IPython.core.alias import AliasManager
40 from IPython.core.builtin_trap import BuiltinTrap
40 from IPython.core.builtin_trap import BuiltinTrap
41 from IPython.core.display_trap import DisplayTrap
41 from IPython.core.display_trap import DisplayTrap
42 from IPython.core.fakemodule import FakeModule, init_fakemod_dict
42 from IPython.core.fakemodule import FakeModule, init_fakemod_dict
43 from IPython.core.logger import Logger
43 from IPython.core.logger import Logger
44 from IPython.core.magic import Magic
44 from IPython.core.magic import Magic
45 from IPython.core.prompts import CachedOutput
45 from IPython.core.prompts import CachedOutput
46 from IPython.core.prefilter import PrefilterManager
46 from IPython.core.prefilter import PrefilterManager
47 from IPython.core.component import Component
47 from IPython.core.component import Component
48 from IPython.core.usage import interactive_usage, default_banner
48 from IPython.core.usage import interactive_usage, default_banner
49 from IPython.core.error import TryNext, UsageError
49 from IPython.core.error import TryNext, UsageError
50
50
51 from IPython.utils import pickleshare
51 from IPython.utils import pickleshare
52 from IPython.external.Itpl import ItplNS
52 from IPython.external.Itpl import ItplNS
53 from IPython.lib.backgroundjobs import BackgroundJobManager
53 from IPython.lib.backgroundjobs import BackgroundJobManager
54 from IPython.utils.ipstruct import Struct
54 from IPython.utils.ipstruct import Struct
55 from IPython.utils import PyColorize
55 from IPython.utils import PyColorize
56 from IPython.utils.genutils import *
56 from IPython.utils.genutils import *
57 from IPython.utils.genutils import get_ipython_dir
57 from IPython.utils.genutils import get_ipython_dir
58 from IPython.utils.platutils import toggle_set_term_title, set_term_title
58 from IPython.utils.platutils import toggle_set_term_title, set_term_title
59 from IPython.utils.strdispatch import StrDispatch
59 from IPython.utils.strdispatch import StrDispatch
60 from IPython.utils.syspathcontext import prepended_to_syspath
60 from IPython.utils.syspathcontext import prepended_to_syspath
61
61
62 # from IPython.utils import growl
62 # from IPython.utils import growl
63 # growl.start("IPython")
63 # growl.start("IPython")
64
64
65 from IPython.utils.traitlets import (
65 from IPython.utils.traitlets import (
66 Int, Str, CBool, CaselessStrEnum, Enum, List, Unicode
66 Int, Str, CBool, CaselessStrEnum, Enum, List, Unicode
67 )
67 )
68
68
69 #-----------------------------------------------------------------------------
69 #-----------------------------------------------------------------------------
70 # Globals
70 # Globals
71 #-----------------------------------------------------------------------------
71 #-----------------------------------------------------------------------------
72
72
73
73
74 # store the builtin raw_input globally, and use this always, in case user code
74 # store the builtin raw_input globally, and use this always, in case user code
75 # overwrites it (like wx.py.PyShell does)
75 # overwrites it (like wx.py.PyShell does)
76 raw_input_original = raw_input
76 raw_input_original = raw_input
77
77
78 # compiled regexps for autoindent management
78 # compiled regexps for autoindent management
79 dedent_re = re.compile(r'^\s+raise|^\s+return|^\s+pass')
79 dedent_re = re.compile(r'^\s+raise|^\s+return|^\s+pass')
80
80
81
81
82 #-----------------------------------------------------------------------------
82 #-----------------------------------------------------------------------------
83 # Utilities
83 # Utilities
84 #-----------------------------------------------------------------------------
84 #-----------------------------------------------------------------------------
85
85
86
86
87 ini_spaces_re = re.compile(r'^(\s+)')
87 ini_spaces_re = re.compile(r'^(\s+)')
88
88
89
89
90 def num_ini_spaces(strng):
90 def num_ini_spaces(strng):
91 """Return the number of initial spaces in a string"""
91 """Return the number of initial spaces in a string"""
92
92
93 ini_spaces = ini_spaces_re.match(strng)
93 ini_spaces = ini_spaces_re.match(strng)
94 if ini_spaces:
94 if ini_spaces:
95 return ini_spaces.end()
95 return ini_spaces.end()
96 else:
96 else:
97 return 0
97 return 0
98
98
99
99
100 def softspace(file, newvalue):
100 def softspace(file, newvalue):
101 """Copied from code.py, to remove the dependency"""
101 """Copied from code.py, to remove the dependency"""
102
102
103 oldvalue = 0
103 oldvalue = 0
104 try:
104 try:
105 oldvalue = file.softspace
105 oldvalue = file.softspace
106 except AttributeError:
106 except AttributeError:
107 pass
107 pass
108 try:
108 try:
109 file.softspace = newvalue
109 file.softspace = newvalue
110 except (AttributeError, TypeError):
110 except (AttributeError, TypeError):
111 # "attribute-less object" or "read-only attributes"
111 # "attribute-less object" or "read-only attributes"
112 pass
112 pass
113 return oldvalue
113 return oldvalue
114
114
115
115
116 class SpaceInInput(exceptions.Exception): pass
116 class SpaceInInput(exceptions.Exception): pass
117
117
118 class Bunch: pass
118 class Bunch: pass
119
119
120 class InputList(list):
120 class InputList(list):
121 """Class to store user input.
121 """Class to store user input.
122
122
123 It's basically a list, but slices return a string instead of a list, thus
123 It's basically a list, but slices return a string instead of a list, thus
124 allowing things like (assuming 'In' is an instance):
124 allowing things like (assuming 'In' is an instance):
125
125
126 exec In[4:7]
126 exec In[4:7]
127
127
128 or
128 or
129
129
130 exec In[5:9] + In[14] + In[21:25]"""
130 exec In[5:9] + In[14] + In[21:25]"""
131
131
132 def __getslice__(self,i,j):
132 def __getslice__(self,i,j):
133 return ''.join(list.__getslice__(self,i,j))
133 return ''.join(list.__getslice__(self,i,j))
134
134
135
135
136 class SyntaxTB(ultratb.ListTB):
136 class SyntaxTB(ultratb.ListTB):
137 """Extension which holds some state: the last exception value"""
137 """Extension which holds some state: the last exception value"""
138
138
139 def __init__(self,color_scheme = 'NoColor'):
139 def __init__(self,color_scheme = 'NoColor'):
140 ultratb.ListTB.__init__(self,color_scheme)
140 ultratb.ListTB.__init__(self,color_scheme)
141 self.last_syntax_error = None
141 self.last_syntax_error = None
142
142
143 def __call__(self, etype, value, elist):
143 def __call__(self, etype, value, elist):
144 self.last_syntax_error = value
144 self.last_syntax_error = value
145 ultratb.ListTB.__call__(self,etype,value,elist)
145 ultratb.ListTB.__call__(self,etype,value,elist)
146
146
147 def clear_err_state(self):
147 def clear_err_state(self):
148 """Return the current error state and clear it"""
148 """Return the current error state and clear it"""
149 e = self.last_syntax_error
149 e = self.last_syntax_error
150 self.last_syntax_error = None
150 self.last_syntax_error = None
151 return e
151 return e
152
152
153
153
154 def get_default_editor():
154 def get_default_editor():
155 try:
155 try:
156 ed = os.environ['EDITOR']
156 ed = os.environ['EDITOR']
157 except KeyError:
157 except KeyError:
158 if os.name == 'posix':
158 if os.name == 'posix':
159 ed = 'vi' # the only one guaranteed to be there!
159 ed = 'vi' # the only one guaranteed to be there!
160 else:
160 else:
161 ed = 'notepad' # same in Windows!
161 ed = 'notepad' # same in Windows!
162 return ed
162 return ed
163
163
164
164
165 class SeparateStr(Str):
165 class SeparateStr(Str):
166 """A Str subclass to validate separate_in, separate_out, etc.
166 """A Str subclass to validate separate_in, separate_out, etc.
167
167
168 This is a Str based traitlet that converts '0'->'' and '\\n'->'\n'.
168 This is a Str based trait that converts '0'->'' and '\\n'->'\n'.
169 """
169 """
170
170
171 def validate(self, obj, value):
171 def validate(self, obj, value):
172 if value == '0': value = ''
172 if value == '0': value = ''
173 value = value.replace('\\n','\n')
173 value = value.replace('\\n','\n')
174 return super(SeparateStr, self).validate(obj, value)
174 return super(SeparateStr, self).validate(obj, value)
175
175
176
176
177 #-----------------------------------------------------------------------------
177 #-----------------------------------------------------------------------------
178 # Main IPython class
178 # Main IPython class
179 #-----------------------------------------------------------------------------
179 #-----------------------------------------------------------------------------
180
180
181
181
182 class InteractiveShell(Component, Magic):
182 class InteractiveShell(Component, Magic):
183 """An enhanced, interactive shell for Python."""
183 """An enhanced, interactive shell for Python."""
184
184
185 autocall = Enum((0,1,2), config=True)
185 autocall = Enum((0,1,2), config=True)
186 autoedit_syntax = CBool(False, config=True)
186 autoedit_syntax = CBool(False, config=True)
187 autoindent = CBool(True, config=True)
187 autoindent = CBool(True, config=True)
188 automagic = CBool(True, config=True)
188 automagic = CBool(True, config=True)
189 banner = Str('')
189 banner = Str('')
190 banner1 = Str(default_banner, config=True)
190 banner1 = Str(default_banner, config=True)
191 banner2 = Str('', config=True)
191 banner2 = Str('', config=True)
192 cache_size = Int(1000, config=True)
192 cache_size = Int(1000, config=True)
193 color_info = CBool(True, config=True)
193 color_info = CBool(True, config=True)
194 colors = CaselessStrEnum(('NoColor','LightBG','Linux'),
194 colors = CaselessStrEnum(('NoColor','LightBG','Linux'),
195 default_value='LightBG', config=True)
195 default_value='LightBG', config=True)
196 confirm_exit = CBool(True, config=True)
196 confirm_exit = CBool(True, config=True)
197 debug = CBool(False, config=True)
197 debug = CBool(False, config=True)
198 deep_reload = CBool(False, config=True)
198 deep_reload = CBool(False, config=True)
199 # This display_banner only controls whether or not self.show_banner()
199 # This display_banner only controls whether or not self.show_banner()
200 # is called when mainloop/interact are called. The default is False
200 # is called when mainloop/interact are called. The default is False
201 # because for the terminal based application, the banner behavior
201 # because for the terminal based application, the banner behavior
202 # is controlled by Global.display_banner, which IPythonApp looks at
202 # is controlled by Global.display_banner, which IPythonApp looks at
203 # to determine if *it* should call show_banner() by hand or not.
203 # to determine if *it* should call show_banner() by hand or not.
204 display_banner = CBool(False) # This isn't configurable!
204 display_banner = CBool(False) # This isn't configurable!
205 embedded = CBool(False)
205 embedded = CBool(False)
206 embedded_active = CBool(False)
206 embedded_active = CBool(False)
207 editor = Str(get_default_editor(), config=True)
207 editor = Str(get_default_editor(), config=True)
208 filename = Str("<ipython console>")
208 filename = Str("<ipython console>")
209 ipythondir= Unicode('', config=True) # Set to get_ipython_dir() in __init__
209 ipythondir= Unicode('', config=True) # Set to get_ipython_dir() in __init__
210 logstart = CBool(False, config=True)
210 logstart = CBool(False, config=True)
211 logfile = Str('', config=True)
211 logfile = Str('', config=True)
212 logappend = Str('', config=True)
212 logappend = Str('', config=True)
213 object_info_string_level = Enum((0,1,2), default_value=0,
213 object_info_string_level = Enum((0,1,2), default_value=0,
214 config=True)
214 config=True)
215 pager = Str('less', config=True)
215 pager = Str('less', config=True)
216 pdb = CBool(False, config=True)
216 pdb = CBool(False, config=True)
217 pprint = CBool(True, config=True)
217 pprint = CBool(True, config=True)
218 profile = Str('', config=True)
218 profile = Str('', config=True)
219 prompt_in1 = Str('In [\\#]: ', config=True)
219 prompt_in1 = Str('In [\\#]: ', config=True)
220 prompt_in2 = Str(' .\\D.: ', config=True)
220 prompt_in2 = Str(' .\\D.: ', config=True)
221 prompt_out = Str('Out[\\#]: ', config=True)
221 prompt_out = Str('Out[\\#]: ', config=True)
222 prompts_pad_left = CBool(True, config=True)
222 prompts_pad_left = CBool(True, config=True)
223 quiet = CBool(False, config=True)
223 quiet = CBool(False, config=True)
224
224
225 readline_use = CBool(True, config=True)
225 readline_use = CBool(True, config=True)
226 readline_merge_completions = CBool(True, config=True)
226 readline_merge_completions = CBool(True, config=True)
227 readline_omit__names = Enum((0,1,2), default_value=0, config=True)
227 readline_omit__names = Enum((0,1,2), default_value=0, config=True)
228 readline_remove_delims = Str('-/~', config=True)
228 readline_remove_delims = Str('-/~', config=True)
229 readline_parse_and_bind = List([
229 readline_parse_and_bind = List([
230 'tab: complete',
230 'tab: complete',
231 '"\C-l": possible-completions',
231 '"\C-l": possible-completions',
232 'set show-all-if-ambiguous on',
232 'set show-all-if-ambiguous on',
233 '"\C-o": tab-insert',
233 '"\C-o": tab-insert',
234 '"\M-i": " "',
234 '"\M-i": " "',
235 '"\M-o": "\d\d\d\d"',
235 '"\M-o": "\d\d\d\d"',
236 '"\M-I": "\d\d\d\d"',
236 '"\M-I": "\d\d\d\d"',
237 '"\C-r": reverse-search-history',
237 '"\C-r": reverse-search-history',
238 '"\C-s": forward-search-history',
238 '"\C-s": forward-search-history',
239 '"\C-p": history-search-backward',
239 '"\C-p": history-search-backward',
240 '"\C-n": history-search-forward',
240 '"\C-n": history-search-forward',
241 '"\e[A": history-search-backward',
241 '"\e[A": history-search-backward',
242 '"\e[B": history-search-forward',
242 '"\e[B": history-search-forward',
243 '"\C-k": kill-line',
243 '"\C-k": kill-line',
244 '"\C-u": unix-line-discard',
244 '"\C-u": unix-line-discard',
245 ], allow_none=False, config=True)
245 ], allow_none=False, config=True)
246
246
247 screen_length = Int(0, config=True)
247 screen_length = Int(0, config=True)
248
248
249 # Use custom TraitletTypes that convert '0'->'' and '\\n'->'\n'
249 # Use custom TraitTypes that convert '0'->'' and '\\n'->'\n'
250 separate_in = SeparateStr('\n', config=True)
250 separate_in = SeparateStr('\n', config=True)
251 separate_out = SeparateStr('', config=True)
251 separate_out = SeparateStr('', config=True)
252 separate_out2 = SeparateStr('', config=True)
252 separate_out2 = SeparateStr('', config=True)
253
253
254 system_header = Str('IPython system call: ', config=True)
254 system_header = Str('IPython system call: ', config=True)
255 system_verbose = CBool(False, config=True)
255 system_verbose = CBool(False, config=True)
256 term_title = CBool(False, config=True)
256 term_title = CBool(False, config=True)
257 wildcards_case_sensitive = CBool(True, config=True)
257 wildcards_case_sensitive = CBool(True, config=True)
258 xmode = CaselessStrEnum(('Context','Plain', 'Verbose'),
258 xmode = CaselessStrEnum(('Context','Plain', 'Verbose'),
259 default_value='Context', config=True)
259 default_value='Context', config=True)
260
260
261 autoexec = List(allow_none=False)
261 autoexec = List(allow_none=False)
262
262
263 # class attribute to indicate whether the class supports threads or not.
263 # class attribute to indicate whether the class supports threads or not.
264 # Subclasses with thread support should override this as needed.
264 # Subclasses with thread support should override this as needed.
265 isthreaded = False
265 isthreaded = False
266
266
267 def __init__(self, parent=None, config=None, ipythondir=None, usage=None,
267 def __init__(self, parent=None, config=None, ipythondir=None, usage=None,
268 user_ns=None, user_global_ns=None,
268 user_ns=None, user_global_ns=None,
269 banner1=None, banner2=None, display_banner=None,
269 banner1=None, banner2=None, display_banner=None,
270 custom_exceptions=((),None)):
270 custom_exceptions=((),None)):
271
271
272 # This is where traitlets with a config_key argument are updated
272 # This is where traits with a config_key argument are updated
273 # from the values on config.
273 # from the values on config.
274 super(InteractiveShell, self).__init__(parent, config=config)
274 super(InteractiveShell, self).__init__(parent, config=config)
275
275
276 # These are relatively independent and stateless
276 # These are relatively independent and stateless
277 self.init_ipythondir(ipythondir)
277 self.init_ipythondir(ipythondir)
278 self.init_instance_attrs()
278 self.init_instance_attrs()
279 self.init_term_title()
279 self.init_term_title()
280 self.init_usage(usage)
280 self.init_usage(usage)
281 self.init_banner(banner1, banner2, display_banner)
281 self.init_banner(banner1, banner2, display_banner)
282
282
283 # Create namespaces (user_ns, user_global_ns, etc.)
283 # Create namespaces (user_ns, user_global_ns, etc.)
284 self.init_create_namespaces(user_ns, user_global_ns)
284 self.init_create_namespaces(user_ns, user_global_ns)
285 # This has to be done after init_create_namespaces because it uses
285 # This has to be done after init_create_namespaces because it uses
286 # something in self.user_ns, but before init_sys_modules, which
286 # something in self.user_ns, but before init_sys_modules, which
287 # is the first thing to modify sys.
287 # is the first thing to modify sys.
288 self.save_sys_module_state()
288 self.save_sys_module_state()
289 self.init_sys_modules()
289 self.init_sys_modules()
290
290
291 self.init_history()
291 self.init_history()
292 self.init_encoding()
292 self.init_encoding()
293 self.init_prefilter()
293 self.init_prefilter()
294
294
295 Magic.__init__(self, self)
295 Magic.__init__(self, self)
296
296
297 self.init_syntax_highlighting()
297 self.init_syntax_highlighting()
298 self.init_hooks()
298 self.init_hooks()
299 self.init_pushd_popd_magic()
299 self.init_pushd_popd_magic()
300 self.init_traceback_handlers(custom_exceptions)
300 self.init_traceback_handlers(custom_exceptions)
301 self.init_user_ns()
301 self.init_user_ns()
302 self.init_logger()
302 self.init_logger()
303 self.init_alias()
303 self.init_alias()
304 self.init_builtins()
304 self.init_builtins()
305
305
306 # pre_config_initialization
306 # pre_config_initialization
307 self.init_shadow_hist()
307 self.init_shadow_hist()
308
308
309 # The next section should contain averything that was in ipmaker.
309 # The next section should contain averything that was in ipmaker.
310 self.init_logstart()
310 self.init_logstart()
311
311
312 # The following was in post_config_initialization
312 # The following was in post_config_initialization
313 self.init_inspector()
313 self.init_inspector()
314 self.init_readline()
314 self.init_readline()
315 self.init_prompts()
315 self.init_prompts()
316 self.init_displayhook()
316 self.init_displayhook()
317 self.init_reload_doctest()
317 self.init_reload_doctest()
318 self.init_magics()
318 self.init_magics()
319 self.init_pdb()
319 self.init_pdb()
320 self.hooks.late_startup_hook()
320 self.hooks.late_startup_hook()
321
321
322 def get_ipython(self):
322 def get_ipython(self):
323 return self
323 return self
324
324
325 #-------------------------------------------------------------------------
325 #-------------------------------------------------------------------------
326 # Traitlet changed handlers
326 # Trait changed handlers
327 #-------------------------------------------------------------------------
327 #-------------------------------------------------------------------------
328
328
329 def _banner1_changed(self):
329 def _banner1_changed(self):
330 self.compute_banner()
330 self.compute_banner()
331
331
332 def _banner2_changed(self):
332 def _banner2_changed(self):
333 self.compute_banner()
333 self.compute_banner()
334
334
335 def _ipythondir_changed(self, name, new):
335 def _ipythondir_changed(self, name, new):
336 if not os.path.isdir(new):
336 if not os.path.isdir(new):
337 os.makedirs(new, mode = 0777)
337 os.makedirs(new, mode = 0777)
338 if not os.path.isdir(self.ipython_extension_dir):
338 if not os.path.isdir(self.ipython_extension_dir):
339 os.makedirs(self.ipython_extension_dir, mode = 0777)
339 os.makedirs(self.ipython_extension_dir, mode = 0777)
340
340
341 @property
341 @property
342 def ipython_extension_dir(self):
342 def ipython_extension_dir(self):
343 return os.path.join(self.ipythondir, 'extensions')
343 return os.path.join(self.ipythondir, 'extensions')
344
344
345 @property
345 @property
346 def usable_screen_length(self):
346 def usable_screen_length(self):
347 if self.screen_length == 0:
347 if self.screen_length == 0:
348 return 0
348 return 0
349 else:
349 else:
350 num_lines_bot = self.separate_in.count('\n')+1
350 num_lines_bot = self.separate_in.count('\n')+1
351 return self.screen_length - num_lines_bot
351 return self.screen_length - num_lines_bot
352
352
353 def _term_title_changed(self, name, new_value):
353 def _term_title_changed(self, name, new_value):
354 self.init_term_title()
354 self.init_term_title()
355
355
356 def set_autoindent(self,value=None):
356 def set_autoindent(self,value=None):
357 """Set the autoindent flag, checking for readline support.
357 """Set the autoindent flag, checking for readline support.
358
358
359 If called with no arguments, it acts as a toggle."""
359 If called with no arguments, it acts as a toggle."""
360
360
361 if not self.has_readline:
361 if not self.has_readline:
362 if os.name == 'posix':
362 if os.name == 'posix':
363 warn("The auto-indent feature requires the readline library")
363 warn("The auto-indent feature requires the readline library")
364 self.autoindent = 0
364 self.autoindent = 0
365 return
365 return
366 if value is None:
366 if value is None:
367 self.autoindent = not self.autoindent
367 self.autoindent = not self.autoindent
368 else:
368 else:
369 self.autoindent = value
369 self.autoindent = value
370
370
371 #-------------------------------------------------------------------------
371 #-------------------------------------------------------------------------
372 # init_* methods called by __init__
372 # init_* methods called by __init__
373 #-------------------------------------------------------------------------
373 #-------------------------------------------------------------------------
374
374
375 def init_ipythondir(self, ipythondir):
375 def init_ipythondir(self, ipythondir):
376 if ipythondir is not None:
376 if ipythondir is not None:
377 self.ipythondir = ipythondir
377 self.ipythondir = ipythondir
378 self.config.Global.ipythondir = self.ipythondir
378 self.config.Global.ipythondir = self.ipythondir
379 return
379 return
380
380
381 if hasattr(self.config.Global, 'ipythondir'):
381 if hasattr(self.config.Global, 'ipythondir'):
382 self.ipythondir = self.config.Global.ipythondir
382 self.ipythondir = self.config.Global.ipythondir
383 else:
383 else:
384 self.ipythondir = get_ipython_dir()
384 self.ipythondir = get_ipython_dir()
385
385
386 # All children can just read this
386 # All children can just read this
387 self.config.Global.ipythondir = self.ipythondir
387 self.config.Global.ipythondir = self.ipythondir
388
388
389 def init_instance_attrs(self):
389 def init_instance_attrs(self):
390 self.jobs = BackgroundJobManager()
390 self.jobs = BackgroundJobManager()
391 self.more = False
391 self.more = False
392
392
393 # command compiler
393 # command compiler
394 self.compile = codeop.CommandCompiler()
394 self.compile = codeop.CommandCompiler()
395
395
396 # User input buffer
396 # User input buffer
397 self.buffer = []
397 self.buffer = []
398
398
399 # Make an empty namespace, which extension writers can rely on both
399 # Make an empty namespace, which extension writers can rely on both
400 # existing and NEVER being used by ipython itself. This gives them a
400 # existing and NEVER being used by ipython itself. This gives them a
401 # convenient location for storing additional information and state
401 # convenient location for storing additional information and state
402 # their extensions may require, without fear of collisions with other
402 # their extensions may require, without fear of collisions with other
403 # ipython names that may develop later.
403 # ipython names that may develop later.
404 self.meta = Struct()
404 self.meta = Struct()
405
405
406 # Object variable to store code object waiting execution. This is
406 # Object variable to store code object waiting execution. This is
407 # used mainly by the multithreaded shells, but it can come in handy in
407 # used mainly by the multithreaded shells, but it can come in handy in
408 # other situations. No need to use a Queue here, since it's a single
408 # other situations. No need to use a Queue here, since it's a single
409 # item which gets cleared once run.
409 # item which gets cleared once run.
410 self.code_to_run = None
410 self.code_to_run = None
411
411
412 # Flag to mark unconditional exit
412 # Flag to mark unconditional exit
413 self.exit_now = False
413 self.exit_now = False
414
414
415 # Temporary files used for various purposes. Deleted at exit.
415 # Temporary files used for various purposes. Deleted at exit.
416 self.tempfiles = []
416 self.tempfiles = []
417
417
418 # Keep track of readline usage (later set by init_readline)
418 # Keep track of readline usage (later set by init_readline)
419 self.has_readline = False
419 self.has_readline = False
420
420
421 # keep track of where we started running (mainly for crash post-mortem)
421 # keep track of where we started running (mainly for crash post-mortem)
422 # This is not being used anywhere currently.
422 # This is not being used anywhere currently.
423 self.starting_dir = os.getcwd()
423 self.starting_dir = os.getcwd()
424
424
425 # Indentation management
425 # Indentation management
426 self.indent_current_nsp = 0
426 self.indent_current_nsp = 0
427
427
428 def init_term_title(self):
428 def init_term_title(self):
429 # Enable or disable the terminal title.
429 # Enable or disable the terminal title.
430 if self.term_title:
430 if self.term_title:
431 toggle_set_term_title(True)
431 toggle_set_term_title(True)
432 set_term_title('IPython: ' + abbrev_cwd())
432 set_term_title('IPython: ' + abbrev_cwd())
433 else:
433 else:
434 toggle_set_term_title(False)
434 toggle_set_term_title(False)
435
435
436 def init_usage(self, usage=None):
436 def init_usage(self, usage=None):
437 if usage is None:
437 if usage is None:
438 self.usage = interactive_usage
438 self.usage = interactive_usage
439 else:
439 else:
440 self.usage = usage
440 self.usage = usage
441
441
442 def init_encoding(self):
442 def init_encoding(self):
443 # Get system encoding at startup time. Certain terminals (like Emacs
443 # Get system encoding at startup time. Certain terminals (like Emacs
444 # under Win32 have it set to None, and we need to have a known valid
444 # under Win32 have it set to None, and we need to have a known valid
445 # encoding to use in the raw_input() method
445 # encoding to use in the raw_input() method
446 try:
446 try:
447 self.stdin_encoding = sys.stdin.encoding or 'ascii'
447 self.stdin_encoding = sys.stdin.encoding or 'ascii'
448 except AttributeError:
448 except AttributeError:
449 self.stdin_encoding = 'ascii'
449 self.stdin_encoding = 'ascii'
450
450
451 def init_syntax_highlighting(self):
451 def init_syntax_highlighting(self):
452 # Python source parser/formatter for syntax highlighting
452 # Python source parser/formatter for syntax highlighting
453 pyformat = PyColorize.Parser().format
453 pyformat = PyColorize.Parser().format
454 self.pycolorize = lambda src: pyformat(src,'str',self.colors)
454 self.pycolorize = lambda src: pyformat(src,'str',self.colors)
455
455
456 def init_pushd_popd_magic(self):
456 def init_pushd_popd_magic(self):
457 # for pushd/popd management
457 # for pushd/popd management
458 try:
458 try:
459 self.home_dir = get_home_dir()
459 self.home_dir = get_home_dir()
460 except HomeDirError, msg:
460 except HomeDirError, msg:
461 fatal(msg)
461 fatal(msg)
462
462
463 self.dir_stack = []
463 self.dir_stack = []
464
464
465 def init_logger(self):
465 def init_logger(self):
466 self.logger = Logger(self, logfname='ipython_log.py', logmode='rotate')
466 self.logger = Logger(self, logfname='ipython_log.py', logmode='rotate')
467 # local shortcut, this is used a LOT
467 # local shortcut, this is used a LOT
468 self.log = self.logger.log
468 self.log = self.logger.log
469
469
470 def init_logstart(self):
470 def init_logstart(self):
471 if self.logappend:
471 if self.logappend:
472 self.magic_logstart(self.logappend + ' append')
472 self.magic_logstart(self.logappend + ' append')
473 elif self.logfile:
473 elif self.logfile:
474 self.magic_logstart(self.logfile)
474 self.magic_logstart(self.logfile)
475 elif self.logstart:
475 elif self.logstart:
476 self.magic_logstart()
476 self.magic_logstart()
477
477
478 def init_builtins(self):
478 def init_builtins(self):
479 self.builtin_trap = BuiltinTrap(self)
479 self.builtin_trap = BuiltinTrap(self)
480
480
481 def init_inspector(self):
481 def init_inspector(self):
482 # Object inspector
482 # Object inspector
483 self.inspector = oinspect.Inspector(oinspect.InspectColors,
483 self.inspector = oinspect.Inspector(oinspect.InspectColors,
484 PyColorize.ANSICodeColors,
484 PyColorize.ANSICodeColors,
485 'NoColor',
485 'NoColor',
486 self.object_info_string_level)
486 self.object_info_string_level)
487
487
488 def init_prompts(self):
488 def init_prompts(self):
489 # Initialize cache, set in/out prompts and printing system
489 # Initialize cache, set in/out prompts and printing system
490 self.outputcache = CachedOutput(self,
490 self.outputcache = CachedOutput(self,
491 self.cache_size,
491 self.cache_size,
492 self.pprint,
492 self.pprint,
493 input_sep = self.separate_in,
493 input_sep = self.separate_in,
494 output_sep = self.separate_out,
494 output_sep = self.separate_out,
495 output_sep2 = self.separate_out2,
495 output_sep2 = self.separate_out2,
496 ps1 = self.prompt_in1,
496 ps1 = self.prompt_in1,
497 ps2 = self.prompt_in2,
497 ps2 = self.prompt_in2,
498 ps_out = self.prompt_out,
498 ps_out = self.prompt_out,
499 pad_left = self.prompts_pad_left)
499 pad_left = self.prompts_pad_left)
500
500
501 # user may have over-ridden the default print hook:
501 # user may have over-ridden the default print hook:
502 try:
502 try:
503 self.outputcache.__class__.display = self.hooks.display
503 self.outputcache.__class__.display = self.hooks.display
504 except AttributeError:
504 except AttributeError:
505 pass
505 pass
506
506
507 def init_displayhook(self):
507 def init_displayhook(self):
508 self.display_trap = DisplayTrap(self, self.outputcache)
508 self.display_trap = DisplayTrap(self, self.outputcache)
509
509
510 def init_reload_doctest(self):
510 def init_reload_doctest(self):
511 # Do a proper resetting of doctest, including the necessary displayhook
511 # Do a proper resetting of doctest, including the necessary displayhook
512 # monkeypatching
512 # monkeypatching
513 try:
513 try:
514 doctest_reload()
514 doctest_reload()
515 except ImportError:
515 except ImportError:
516 warn("doctest module does not exist.")
516 warn("doctest module does not exist.")
517
517
518 #-------------------------------------------------------------------------
518 #-------------------------------------------------------------------------
519 # Things related to the banner
519 # Things related to the banner
520 #-------------------------------------------------------------------------
520 #-------------------------------------------------------------------------
521
521
522 def init_banner(self, banner1, banner2, display_banner):
522 def init_banner(self, banner1, banner2, display_banner):
523 if banner1 is not None:
523 if banner1 is not None:
524 self.banner1 = banner1
524 self.banner1 = banner1
525 if banner2 is not None:
525 if banner2 is not None:
526 self.banner2 = banner2
526 self.banner2 = banner2
527 if display_banner is not None:
527 if display_banner is not None:
528 self.display_banner = display_banner
528 self.display_banner = display_banner
529 self.compute_banner()
529 self.compute_banner()
530
530
531 def show_banner(self, banner=None):
531 def show_banner(self, banner=None):
532 if banner is None:
532 if banner is None:
533 banner = self.banner
533 banner = self.banner
534 self.write(banner)
534 self.write(banner)
535
535
536 def compute_banner(self):
536 def compute_banner(self):
537 self.banner = self.banner1 + '\n'
537 self.banner = self.banner1 + '\n'
538 if self.profile:
538 if self.profile:
539 self.banner += '\nIPython profile: %s\n' % self.profile
539 self.banner += '\nIPython profile: %s\n' % self.profile
540 if self.banner2:
540 if self.banner2:
541 self.banner += '\n' + self.banner2 + '\n'
541 self.banner += '\n' + self.banner2 + '\n'
542
542
543 #-------------------------------------------------------------------------
543 #-------------------------------------------------------------------------
544 # Things related to injections into the sys module
544 # Things related to injections into the sys module
545 #-------------------------------------------------------------------------
545 #-------------------------------------------------------------------------
546
546
547 def save_sys_module_state(self):
547 def save_sys_module_state(self):
548 """Save the state of hooks in the sys module.
548 """Save the state of hooks in the sys module.
549
549
550 This has to be called after self.user_ns is created.
550 This has to be called after self.user_ns is created.
551 """
551 """
552 self._orig_sys_module_state = {}
552 self._orig_sys_module_state = {}
553 self._orig_sys_module_state['stdin'] = sys.stdin
553 self._orig_sys_module_state['stdin'] = sys.stdin
554 self._orig_sys_module_state['stdout'] = sys.stdout
554 self._orig_sys_module_state['stdout'] = sys.stdout
555 self._orig_sys_module_state['stderr'] = sys.stderr
555 self._orig_sys_module_state['stderr'] = sys.stderr
556 self._orig_sys_module_state['excepthook'] = sys.excepthook
556 self._orig_sys_module_state['excepthook'] = sys.excepthook
557 try:
557 try:
558 self._orig_sys_modules_main_name = self.user_ns['__name__']
558 self._orig_sys_modules_main_name = self.user_ns['__name__']
559 except KeyError:
559 except KeyError:
560 pass
560 pass
561
561
562 def restore_sys_module_state(self):
562 def restore_sys_module_state(self):
563 """Restore the state of the sys module."""
563 """Restore the state of the sys module."""
564 try:
564 try:
565 for k, v in self._orig_sys_module_state.items():
565 for k, v in self._orig_sys_module_state.items():
566 setattr(sys, k, v)
566 setattr(sys, k, v)
567 except AttributeError:
567 except AttributeError:
568 pass
568 pass
569 try:
569 try:
570 delattr(sys, 'ipcompleter')
570 delattr(sys, 'ipcompleter')
571 except AttributeError:
571 except AttributeError:
572 pass
572 pass
573 # Reset what what done in self.init_sys_modules
573 # Reset what what done in self.init_sys_modules
574 try:
574 try:
575 sys.modules[self.user_ns['__name__']] = self._orig_sys_modules_main_name
575 sys.modules[self.user_ns['__name__']] = self._orig_sys_modules_main_name
576 except (AttributeError, KeyError):
576 except (AttributeError, KeyError):
577 pass
577 pass
578
578
579 #-------------------------------------------------------------------------
579 #-------------------------------------------------------------------------
580 # Things related to hooks
580 # Things related to hooks
581 #-------------------------------------------------------------------------
581 #-------------------------------------------------------------------------
582
582
583 def init_hooks(self):
583 def init_hooks(self):
584 # hooks holds pointers used for user-side customizations
584 # hooks holds pointers used for user-side customizations
585 self.hooks = Struct()
585 self.hooks = Struct()
586
586
587 self.strdispatchers = {}
587 self.strdispatchers = {}
588
588
589 # Set all default hooks, defined in the IPython.hooks module.
589 # Set all default hooks, defined in the IPython.hooks module.
590 import IPython.core.hooks
590 import IPython.core.hooks
591 hooks = IPython.core.hooks
591 hooks = IPython.core.hooks
592 for hook_name in hooks.__all__:
592 for hook_name in hooks.__all__:
593 # default hooks have priority 100, i.e. low; user hooks should have
593 # default hooks have priority 100, i.e. low; user hooks should have
594 # 0-100 priority
594 # 0-100 priority
595 self.set_hook(hook_name,getattr(hooks,hook_name), 100)
595 self.set_hook(hook_name,getattr(hooks,hook_name), 100)
596
596
597 def set_hook(self,name,hook, priority = 50, str_key = None, re_key = None):
597 def set_hook(self,name,hook, priority = 50, str_key = None, re_key = None):
598 """set_hook(name,hook) -> sets an internal IPython hook.
598 """set_hook(name,hook) -> sets an internal IPython hook.
599
599
600 IPython exposes some of its internal API as user-modifiable hooks. By
600 IPython exposes some of its internal API as user-modifiable hooks. By
601 adding your function to one of these hooks, you can modify IPython's
601 adding your function to one of these hooks, you can modify IPython's
602 behavior to call at runtime your own routines."""
602 behavior to call at runtime your own routines."""
603
603
604 # At some point in the future, this should validate the hook before it
604 # At some point in the future, this should validate the hook before it
605 # accepts it. Probably at least check that the hook takes the number
605 # accepts it. Probably at least check that the hook takes the number
606 # of args it's supposed to.
606 # of args it's supposed to.
607
607
608 f = new.instancemethod(hook,self,self.__class__)
608 f = new.instancemethod(hook,self,self.__class__)
609
609
610 # check if the hook is for strdispatcher first
610 # check if the hook is for strdispatcher first
611 if str_key is not None:
611 if str_key is not None:
612 sdp = self.strdispatchers.get(name, StrDispatch())
612 sdp = self.strdispatchers.get(name, StrDispatch())
613 sdp.add_s(str_key, f, priority )
613 sdp.add_s(str_key, f, priority )
614 self.strdispatchers[name] = sdp
614 self.strdispatchers[name] = sdp
615 return
615 return
616 if re_key is not None:
616 if re_key is not None:
617 sdp = self.strdispatchers.get(name, StrDispatch())
617 sdp = self.strdispatchers.get(name, StrDispatch())
618 sdp.add_re(re.compile(re_key), f, priority )
618 sdp.add_re(re.compile(re_key), f, priority )
619 self.strdispatchers[name] = sdp
619 self.strdispatchers[name] = sdp
620 return
620 return
621
621
622 dp = getattr(self.hooks, name, None)
622 dp = getattr(self.hooks, name, None)
623 if name not in IPython.core.hooks.__all__:
623 if name not in IPython.core.hooks.__all__:
624 print "Warning! Hook '%s' is not one of %s" % (name, IPython.core.hooks.__all__ )
624 print "Warning! Hook '%s' is not one of %s" % (name, IPython.core.hooks.__all__ )
625 if not dp:
625 if not dp:
626 dp = IPython.core.hooks.CommandChainDispatcher()
626 dp = IPython.core.hooks.CommandChainDispatcher()
627
627
628 try:
628 try:
629 dp.add(f,priority)
629 dp.add(f,priority)
630 except AttributeError:
630 except AttributeError:
631 # it was not commandchain, plain old func - replace
631 # it was not commandchain, plain old func - replace
632 dp = f
632 dp = f
633
633
634 setattr(self.hooks,name, dp)
634 setattr(self.hooks,name, dp)
635
635
636 #-------------------------------------------------------------------------
636 #-------------------------------------------------------------------------
637 # Things related to the "main" module
637 # Things related to the "main" module
638 #-------------------------------------------------------------------------
638 #-------------------------------------------------------------------------
639
639
640 def new_main_mod(self,ns=None):
640 def new_main_mod(self,ns=None):
641 """Return a new 'main' module object for user code execution.
641 """Return a new 'main' module object for user code execution.
642 """
642 """
643 main_mod = self._user_main_module
643 main_mod = self._user_main_module
644 init_fakemod_dict(main_mod,ns)
644 init_fakemod_dict(main_mod,ns)
645 return main_mod
645 return main_mod
646
646
647 def cache_main_mod(self,ns,fname):
647 def cache_main_mod(self,ns,fname):
648 """Cache a main module's namespace.
648 """Cache a main module's namespace.
649
649
650 When scripts are executed via %run, we must keep a reference to the
650 When scripts are executed via %run, we must keep a reference to the
651 namespace of their __main__ module (a FakeModule instance) around so
651 namespace of their __main__ module (a FakeModule instance) around so
652 that Python doesn't clear it, rendering objects defined therein
652 that Python doesn't clear it, rendering objects defined therein
653 useless.
653 useless.
654
654
655 This method keeps said reference in a private dict, keyed by the
655 This method keeps said reference in a private dict, keyed by the
656 absolute path of the module object (which corresponds to the script
656 absolute path of the module object (which corresponds to the script
657 path). This way, for multiple executions of the same script we only
657 path). This way, for multiple executions of the same script we only
658 keep one copy of the namespace (the last one), thus preventing memory
658 keep one copy of the namespace (the last one), thus preventing memory
659 leaks from old references while allowing the objects from the last
659 leaks from old references while allowing the objects from the last
660 execution to be accessible.
660 execution to be accessible.
661
661
662 Note: we can not allow the actual FakeModule instances to be deleted,
662 Note: we can not allow the actual FakeModule instances to be deleted,
663 because of how Python tears down modules (it hard-sets all their
663 because of how Python tears down modules (it hard-sets all their
664 references to None without regard for reference counts). This method
664 references to None without regard for reference counts). This method
665 must therefore make a *copy* of the given namespace, to allow the
665 must therefore make a *copy* of the given namespace, to allow the
666 original module's __dict__ to be cleared and reused.
666 original module's __dict__ to be cleared and reused.
667
667
668
668
669 Parameters
669 Parameters
670 ----------
670 ----------
671 ns : a namespace (a dict, typically)
671 ns : a namespace (a dict, typically)
672
672
673 fname : str
673 fname : str
674 Filename associated with the namespace.
674 Filename associated with the namespace.
675
675
676 Examples
676 Examples
677 --------
677 --------
678
678
679 In [10]: import IPython
679 In [10]: import IPython
680
680
681 In [11]: _ip.cache_main_mod(IPython.__dict__,IPython.__file__)
681 In [11]: _ip.cache_main_mod(IPython.__dict__,IPython.__file__)
682
682
683 In [12]: IPython.__file__ in _ip._main_ns_cache
683 In [12]: IPython.__file__ in _ip._main_ns_cache
684 Out[12]: True
684 Out[12]: True
685 """
685 """
686 self._main_ns_cache[os.path.abspath(fname)] = ns.copy()
686 self._main_ns_cache[os.path.abspath(fname)] = ns.copy()
687
687
688 def clear_main_mod_cache(self):
688 def clear_main_mod_cache(self):
689 """Clear the cache of main modules.
689 """Clear the cache of main modules.
690
690
691 Mainly for use by utilities like %reset.
691 Mainly for use by utilities like %reset.
692
692
693 Examples
693 Examples
694 --------
694 --------
695
695
696 In [15]: import IPython
696 In [15]: import IPython
697
697
698 In [16]: _ip.cache_main_mod(IPython.__dict__,IPython.__file__)
698 In [16]: _ip.cache_main_mod(IPython.__dict__,IPython.__file__)
699
699
700 In [17]: len(_ip._main_ns_cache) > 0
700 In [17]: len(_ip._main_ns_cache) > 0
701 Out[17]: True
701 Out[17]: True
702
702
703 In [18]: _ip.clear_main_mod_cache()
703 In [18]: _ip.clear_main_mod_cache()
704
704
705 In [19]: len(_ip._main_ns_cache) == 0
705 In [19]: len(_ip._main_ns_cache) == 0
706 Out[19]: True
706 Out[19]: True
707 """
707 """
708 self._main_ns_cache.clear()
708 self._main_ns_cache.clear()
709
709
710 #-------------------------------------------------------------------------
710 #-------------------------------------------------------------------------
711 # Things related to debugging
711 # Things related to debugging
712 #-------------------------------------------------------------------------
712 #-------------------------------------------------------------------------
713
713
714 def init_pdb(self):
714 def init_pdb(self):
715 # Set calling of pdb on exceptions
715 # Set calling of pdb on exceptions
716 # self.call_pdb is a property
716 # self.call_pdb is a property
717 self.call_pdb = self.pdb
717 self.call_pdb = self.pdb
718
718
719 def _get_call_pdb(self):
719 def _get_call_pdb(self):
720 return self._call_pdb
720 return self._call_pdb
721
721
722 def _set_call_pdb(self,val):
722 def _set_call_pdb(self,val):
723
723
724 if val not in (0,1,False,True):
724 if val not in (0,1,False,True):
725 raise ValueError,'new call_pdb value must be boolean'
725 raise ValueError,'new call_pdb value must be boolean'
726
726
727 # store value in instance
727 # store value in instance
728 self._call_pdb = val
728 self._call_pdb = val
729
729
730 # notify the actual exception handlers
730 # notify the actual exception handlers
731 self.InteractiveTB.call_pdb = val
731 self.InteractiveTB.call_pdb = val
732 if self.isthreaded:
732 if self.isthreaded:
733 try:
733 try:
734 self.sys_excepthook.call_pdb = val
734 self.sys_excepthook.call_pdb = val
735 except:
735 except:
736 warn('Failed to activate pdb for threaded exception handler')
736 warn('Failed to activate pdb for threaded exception handler')
737
737
738 call_pdb = property(_get_call_pdb,_set_call_pdb,None,
738 call_pdb = property(_get_call_pdb,_set_call_pdb,None,
739 'Control auto-activation of pdb at exceptions')
739 'Control auto-activation of pdb at exceptions')
740
740
741 def debugger(self,force=False):
741 def debugger(self,force=False):
742 """Call the pydb/pdb debugger.
742 """Call the pydb/pdb debugger.
743
743
744 Keywords:
744 Keywords:
745
745
746 - force(False): by default, this routine checks the instance call_pdb
746 - force(False): by default, this routine checks the instance call_pdb
747 flag and does not actually invoke the debugger if the flag is false.
747 flag and does not actually invoke the debugger if the flag is false.
748 The 'force' option forces the debugger to activate even if the flag
748 The 'force' option forces the debugger to activate even if the flag
749 is false.
749 is false.
750 """
750 """
751
751
752 if not (force or self.call_pdb):
752 if not (force or self.call_pdb):
753 return
753 return
754
754
755 if not hasattr(sys,'last_traceback'):
755 if not hasattr(sys,'last_traceback'):
756 error('No traceback has been produced, nothing to debug.')
756 error('No traceback has been produced, nothing to debug.')
757 return
757 return
758
758
759 # use pydb if available
759 # use pydb if available
760 if debugger.has_pydb:
760 if debugger.has_pydb:
761 from pydb import pm
761 from pydb import pm
762 else:
762 else:
763 # fallback to our internal debugger
763 # fallback to our internal debugger
764 pm = lambda : self.InteractiveTB.debugger(force=True)
764 pm = lambda : self.InteractiveTB.debugger(force=True)
765 self.history_saving_wrapper(pm)()
765 self.history_saving_wrapper(pm)()
766
766
767 #-------------------------------------------------------------------------
767 #-------------------------------------------------------------------------
768 # Things related to IPython's various namespaces
768 # Things related to IPython's various namespaces
769 #-------------------------------------------------------------------------
769 #-------------------------------------------------------------------------
770
770
771 def init_create_namespaces(self, user_ns=None, user_global_ns=None):
771 def init_create_namespaces(self, user_ns=None, user_global_ns=None):
772 # Create the namespace where the user will operate. user_ns is
772 # Create the namespace where the user will operate. user_ns is
773 # normally the only one used, and it is passed to the exec calls as
773 # normally the only one used, and it is passed to the exec calls as
774 # the locals argument. But we do carry a user_global_ns namespace
774 # the locals argument. But we do carry a user_global_ns namespace
775 # given as the exec 'globals' argument, This is useful in embedding
775 # given as the exec 'globals' argument, This is useful in embedding
776 # situations where the ipython shell opens in a context where the
776 # situations where the ipython shell opens in a context where the
777 # distinction between locals and globals is meaningful. For
777 # distinction between locals and globals is meaningful. For
778 # non-embedded contexts, it is just the same object as the user_ns dict.
778 # non-embedded contexts, it is just the same object as the user_ns dict.
779
779
780 # FIXME. For some strange reason, __builtins__ is showing up at user
780 # FIXME. For some strange reason, __builtins__ is showing up at user
781 # level as a dict instead of a module. This is a manual fix, but I
781 # level as a dict instead of a module. This is a manual fix, but I
782 # should really track down where the problem is coming from. Alex
782 # should really track down where the problem is coming from. Alex
783 # Schmolck reported this problem first.
783 # Schmolck reported this problem first.
784
784
785 # A useful post by Alex Martelli on this topic:
785 # A useful post by Alex Martelli on this topic:
786 # Re: inconsistent value from __builtins__
786 # Re: inconsistent value from __builtins__
787 # Von: Alex Martelli <aleaxit@yahoo.com>
787 # Von: Alex Martelli <aleaxit@yahoo.com>
788 # Datum: Freitag 01 Oktober 2004 04:45:34 nachmittags/abends
788 # Datum: Freitag 01 Oktober 2004 04:45:34 nachmittags/abends
789 # Gruppen: comp.lang.python
789 # Gruppen: comp.lang.python
790
790
791 # Michael Hohn <hohn@hooknose.lbl.gov> wrote:
791 # Michael Hohn <hohn@hooknose.lbl.gov> wrote:
792 # > >>> print type(builtin_check.get_global_binding('__builtins__'))
792 # > >>> print type(builtin_check.get_global_binding('__builtins__'))
793 # > <type 'dict'>
793 # > <type 'dict'>
794 # > >>> print type(__builtins__)
794 # > >>> print type(__builtins__)
795 # > <type 'module'>
795 # > <type 'module'>
796 # > Is this difference in return value intentional?
796 # > Is this difference in return value intentional?
797
797
798 # Well, it's documented that '__builtins__' can be either a dictionary
798 # Well, it's documented that '__builtins__' can be either a dictionary
799 # or a module, and it's been that way for a long time. Whether it's
799 # or a module, and it's been that way for a long time. Whether it's
800 # intentional (or sensible), I don't know. In any case, the idea is
800 # intentional (or sensible), I don't know. In any case, the idea is
801 # that if you need to access the built-in namespace directly, you
801 # that if you need to access the built-in namespace directly, you
802 # should start with "import __builtin__" (note, no 's') which will
802 # should start with "import __builtin__" (note, no 's') which will
803 # definitely give you a module. Yeah, it's somewhat confusing:-(.
803 # definitely give you a module. Yeah, it's somewhat confusing:-(.
804
804
805 # These routines return properly built dicts as needed by the rest of
805 # These routines return properly built dicts as needed by the rest of
806 # the code, and can also be used by extension writers to generate
806 # the code, and can also be used by extension writers to generate
807 # properly initialized namespaces.
807 # properly initialized namespaces.
808 user_ns, user_global_ns = self.make_user_namespaces(user_ns,
808 user_ns, user_global_ns = self.make_user_namespaces(user_ns,
809 user_global_ns)
809 user_global_ns)
810
810
811 # Assign namespaces
811 # Assign namespaces
812 # This is the namespace where all normal user variables live
812 # This is the namespace where all normal user variables live
813 self.user_ns = user_ns
813 self.user_ns = user_ns
814 self.user_global_ns = user_global_ns
814 self.user_global_ns = user_global_ns
815
815
816 # An auxiliary namespace that checks what parts of the user_ns were
816 # An auxiliary namespace that checks what parts of the user_ns were
817 # loaded at startup, so we can list later only variables defined in
817 # loaded at startup, so we can list later only variables defined in
818 # actual interactive use. Since it is always a subset of user_ns, it
818 # actual interactive use. Since it is always a subset of user_ns, it
819 # doesn't need to be seaparately tracked in the ns_table
819 # doesn't need to be seaparately tracked in the ns_table
820 self.user_config_ns = {}
820 self.user_config_ns = {}
821
821
822 # A namespace to keep track of internal data structures to prevent
822 # A namespace to keep track of internal data structures to prevent
823 # them from cluttering user-visible stuff. Will be updated later
823 # them from cluttering user-visible stuff. Will be updated later
824 self.internal_ns = {}
824 self.internal_ns = {}
825
825
826 # Now that FakeModule produces a real module, we've run into a nasty
826 # Now that FakeModule produces a real module, we've run into a nasty
827 # problem: after script execution (via %run), the module where the user
827 # problem: after script execution (via %run), the module where the user
828 # code ran is deleted. Now that this object is a true module (needed
828 # code ran is deleted. Now that this object is a true module (needed
829 # so docetst and other tools work correctly), the Python module
829 # so docetst and other tools work correctly), the Python module
830 # teardown mechanism runs over it, and sets to None every variable
830 # teardown mechanism runs over it, and sets to None every variable
831 # present in that module. Top-level references to objects from the
831 # present in that module. Top-level references to objects from the
832 # script survive, because the user_ns is updated with them. However,
832 # script survive, because the user_ns is updated with them. However,
833 # calling functions defined in the script that use other things from
833 # calling functions defined in the script that use other things from
834 # the script will fail, because the function's closure had references
834 # the script will fail, because the function's closure had references
835 # to the original objects, which are now all None. So we must protect
835 # to the original objects, which are now all None. So we must protect
836 # these modules from deletion by keeping a cache.
836 # these modules from deletion by keeping a cache.
837 #
837 #
838 # To avoid keeping stale modules around (we only need the one from the
838 # To avoid keeping stale modules around (we only need the one from the
839 # last run), we use a dict keyed with the full path to the script, so
839 # last run), we use a dict keyed with the full path to the script, so
840 # only the last version of the module is held in the cache. Note,
840 # only the last version of the module is held in the cache. Note,
841 # however, that we must cache the module *namespace contents* (their
841 # however, that we must cache the module *namespace contents* (their
842 # __dict__). Because if we try to cache the actual modules, old ones
842 # __dict__). Because if we try to cache the actual modules, old ones
843 # (uncached) could be destroyed while still holding references (such as
843 # (uncached) could be destroyed while still holding references (such as
844 # those held by GUI objects that tend to be long-lived)>
844 # those held by GUI objects that tend to be long-lived)>
845 #
845 #
846 # The %reset command will flush this cache. See the cache_main_mod()
846 # The %reset command will flush this cache. See the cache_main_mod()
847 # and clear_main_mod_cache() methods for details on use.
847 # and clear_main_mod_cache() methods for details on use.
848
848
849 # This is the cache used for 'main' namespaces
849 # This is the cache used for 'main' namespaces
850 self._main_ns_cache = {}
850 self._main_ns_cache = {}
851 # And this is the single instance of FakeModule whose __dict__ we keep
851 # And this is the single instance of FakeModule whose __dict__ we keep
852 # copying and clearing for reuse on each %run
852 # copying and clearing for reuse on each %run
853 self._user_main_module = FakeModule()
853 self._user_main_module = FakeModule()
854
854
855 # A table holding all the namespaces IPython deals with, so that
855 # A table holding all the namespaces IPython deals with, so that
856 # introspection facilities can search easily.
856 # introspection facilities can search easily.
857 self.ns_table = {'user':user_ns,
857 self.ns_table = {'user':user_ns,
858 'user_global':user_global_ns,
858 'user_global':user_global_ns,
859 'internal':self.internal_ns,
859 'internal':self.internal_ns,
860 'builtin':__builtin__.__dict__
860 'builtin':__builtin__.__dict__
861 }
861 }
862
862
863 # Similarly, track all namespaces where references can be held and that
863 # Similarly, track all namespaces where references can be held and that
864 # we can safely clear (so it can NOT include builtin). This one can be
864 # we can safely clear (so it can NOT include builtin). This one can be
865 # a simple list.
865 # a simple list.
866 self.ns_refs_table = [ user_ns, user_global_ns, self.user_config_ns,
866 self.ns_refs_table = [ user_ns, user_global_ns, self.user_config_ns,
867 self.internal_ns, self._main_ns_cache ]
867 self.internal_ns, self._main_ns_cache ]
868
868
869 def init_sys_modules(self):
869 def init_sys_modules(self):
870 # We need to insert into sys.modules something that looks like a
870 # We need to insert into sys.modules something that looks like a
871 # module but which accesses the IPython namespace, for shelve and
871 # module but which accesses the IPython namespace, for shelve and
872 # pickle to work interactively. Normally they rely on getting
872 # pickle to work interactively. Normally they rely on getting
873 # everything out of __main__, but for embedding purposes each IPython
873 # everything out of __main__, but for embedding purposes each IPython
874 # instance has its own private namespace, so we can't go shoving
874 # instance has its own private namespace, so we can't go shoving
875 # everything into __main__.
875 # everything into __main__.
876
876
877 # note, however, that we should only do this for non-embedded
877 # note, however, that we should only do this for non-embedded
878 # ipythons, which really mimic the __main__.__dict__ with their own
878 # ipythons, which really mimic the __main__.__dict__ with their own
879 # namespace. Embedded instances, on the other hand, should not do
879 # namespace. Embedded instances, on the other hand, should not do
880 # this because they need to manage the user local/global namespaces
880 # this because they need to manage the user local/global namespaces
881 # only, but they live within a 'normal' __main__ (meaning, they
881 # only, but they live within a 'normal' __main__ (meaning, they
882 # shouldn't overtake the execution environment of the script they're
882 # shouldn't overtake the execution environment of the script they're
883 # embedded in).
883 # embedded in).
884
884
885 # This is overridden in the InteractiveShellEmbed subclass to a no-op.
885 # This is overridden in the InteractiveShellEmbed subclass to a no-op.
886
886
887 try:
887 try:
888 main_name = self.user_ns['__name__']
888 main_name = self.user_ns['__name__']
889 except KeyError:
889 except KeyError:
890 raise KeyError('user_ns dictionary MUST have a "__name__" key')
890 raise KeyError('user_ns dictionary MUST have a "__name__" key')
891 else:
891 else:
892 sys.modules[main_name] = FakeModule(self.user_ns)
892 sys.modules[main_name] = FakeModule(self.user_ns)
893
893
894 def make_user_namespaces(self, user_ns=None, user_global_ns=None):
894 def make_user_namespaces(self, user_ns=None, user_global_ns=None):
895 """Return a valid local and global user interactive namespaces.
895 """Return a valid local and global user interactive namespaces.
896
896
897 This builds a dict with the minimal information needed to operate as a
897 This builds a dict with the minimal information needed to operate as a
898 valid IPython user namespace, which you can pass to the various
898 valid IPython user namespace, which you can pass to the various
899 embedding classes in ipython. The default implementation returns the
899 embedding classes in ipython. The default implementation returns the
900 same dict for both the locals and the globals to allow functions to
900 same dict for both the locals and the globals to allow functions to
901 refer to variables in the namespace. Customized implementations can
901 refer to variables in the namespace. Customized implementations can
902 return different dicts. The locals dictionary can actually be anything
902 return different dicts. The locals dictionary can actually be anything
903 following the basic mapping protocol of a dict, but the globals dict
903 following the basic mapping protocol of a dict, but the globals dict
904 must be a true dict, not even a subclass. It is recommended that any
904 must be a true dict, not even a subclass. It is recommended that any
905 custom object for the locals namespace synchronize with the globals
905 custom object for the locals namespace synchronize with the globals
906 dict somehow.
906 dict somehow.
907
907
908 Raises TypeError if the provided globals namespace is not a true dict.
908 Raises TypeError if the provided globals namespace is not a true dict.
909
909
910 :Parameters:
910 :Parameters:
911 user_ns : dict-like, optional
911 user_ns : dict-like, optional
912 The current user namespace. The items in this namespace should
912 The current user namespace. The items in this namespace should
913 be included in the output. If None, an appropriate blank
913 be included in the output. If None, an appropriate blank
914 namespace should be created.
914 namespace should be created.
915 user_global_ns : dict, optional
915 user_global_ns : dict, optional
916 The current user global namespace. The items in this namespace
916 The current user global namespace. The items in this namespace
917 should be included in the output. If None, an appropriate
917 should be included in the output. If None, an appropriate
918 blank namespace should be created.
918 blank namespace should be created.
919
919
920 :Returns:
920 :Returns:
921 A tuple pair of dictionary-like object to be used as the local namespace
921 A tuple pair of dictionary-like object to be used as the local namespace
922 of the interpreter and a dict to be used as the global namespace.
922 of the interpreter and a dict to be used as the global namespace.
923 """
923 """
924
924
925 if user_ns is None:
925 if user_ns is None:
926 # Set __name__ to __main__ to better match the behavior of the
926 # Set __name__ to __main__ to better match the behavior of the
927 # normal interpreter.
927 # normal interpreter.
928 user_ns = {'__name__' :'__main__',
928 user_ns = {'__name__' :'__main__',
929 '__builtins__' : __builtin__,
929 '__builtins__' : __builtin__,
930 }
930 }
931 else:
931 else:
932 user_ns.setdefault('__name__','__main__')
932 user_ns.setdefault('__name__','__main__')
933 user_ns.setdefault('__builtins__',__builtin__)
933 user_ns.setdefault('__builtins__',__builtin__)
934
934
935 if user_global_ns is None:
935 if user_global_ns is None:
936 user_global_ns = user_ns
936 user_global_ns = user_ns
937 if type(user_global_ns) is not dict:
937 if type(user_global_ns) is not dict:
938 raise TypeError("user_global_ns must be a true dict; got %r"
938 raise TypeError("user_global_ns must be a true dict; got %r"
939 % type(user_global_ns))
939 % type(user_global_ns))
940
940
941 return user_ns, user_global_ns
941 return user_ns, user_global_ns
942
942
943 def init_user_ns(self):
943 def init_user_ns(self):
944 """Initialize all user-visible namespaces to their minimum defaults.
944 """Initialize all user-visible namespaces to their minimum defaults.
945
945
946 Certain history lists are also initialized here, as they effectively
946 Certain history lists are also initialized here, as they effectively
947 act as user namespaces.
947 act as user namespaces.
948
948
949 Notes
949 Notes
950 -----
950 -----
951 All data structures here are only filled in, they are NOT reset by this
951 All data structures here are only filled in, they are NOT reset by this
952 method. If they were not empty before, data will simply be added to
952 method. If they were not empty before, data will simply be added to
953 therm.
953 therm.
954 """
954 """
955 # Store myself as the public api!!!
955 # Store myself as the public api!!!
956 self.user_ns['get_ipython'] = self.get_ipython
956 self.user_ns['get_ipython'] = self.get_ipython
957
957
958 # make global variables for user access to the histories
958 # make global variables for user access to the histories
959 self.user_ns['_ih'] = self.input_hist
959 self.user_ns['_ih'] = self.input_hist
960 self.user_ns['_oh'] = self.output_hist
960 self.user_ns['_oh'] = self.output_hist
961 self.user_ns['_dh'] = self.dir_hist
961 self.user_ns['_dh'] = self.dir_hist
962
962
963 # user aliases to input and output histories
963 # user aliases to input and output histories
964 self.user_ns['In'] = self.input_hist
964 self.user_ns['In'] = self.input_hist
965 self.user_ns['Out'] = self.output_hist
965 self.user_ns['Out'] = self.output_hist
966
966
967 self.user_ns['_sh'] = shadowns
967 self.user_ns['_sh'] = shadowns
968
968
969 # Put 'help' in the user namespace
969 # Put 'help' in the user namespace
970 try:
970 try:
971 from site import _Helper
971 from site import _Helper
972 self.user_ns['help'] = _Helper()
972 self.user_ns['help'] = _Helper()
973 except ImportError:
973 except ImportError:
974 warn('help() not available - check site.py')
974 warn('help() not available - check site.py')
975
975
976 def reset(self):
976 def reset(self):
977 """Clear all internal namespaces.
977 """Clear all internal namespaces.
978
978
979 Note that this is much more aggressive than %reset, since it clears
979 Note that this is much more aggressive than %reset, since it clears
980 fully all namespaces, as well as all input/output lists.
980 fully all namespaces, as well as all input/output lists.
981 """
981 """
982 for ns in self.ns_refs_table:
982 for ns in self.ns_refs_table:
983 ns.clear()
983 ns.clear()
984
984
985 self.alias_manager.clear_aliases()
985 self.alias_manager.clear_aliases()
986
986
987 # Clear input and output histories
987 # Clear input and output histories
988 self.input_hist[:] = []
988 self.input_hist[:] = []
989 self.input_hist_raw[:] = []
989 self.input_hist_raw[:] = []
990 self.output_hist.clear()
990 self.output_hist.clear()
991
991
992 # Restore the user namespaces to minimal usability
992 # Restore the user namespaces to minimal usability
993 self.init_user_ns()
993 self.init_user_ns()
994
994
995 # Restore the default and user aliases
995 # Restore the default and user aliases
996 self.alias_manager.init_aliases()
996 self.alias_manager.init_aliases()
997
997
998 def push(self, variables, interactive=True):
998 def push(self, variables, interactive=True):
999 """Inject a group of variables into the IPython user namespace.
999 """Inject a group of variables into the IPython user namespace.
1000
1000
1001 Parameters
1001 Parameters
1002 ----------
1002 ----------
1003 variables : dict, str or list/tuple of str
1003 variables : dict, str or list/tuple of str
1004 The variables to inject into the user's namespace. If a dict,
1004 The variables to inject into the user's namespace. If a dict,
1005 a simple update is done. If a str, the string is assumed to
1005 a simple update is done. If a str, the string is assumed to
1006 have variable names separated by spaces. A list/tuple of str
1006 have variable names separated by spaces. A list/tuple of str
1007 can also be used to give the variable names. If just the variable
1007 can also be used to give the variable names. If just the variable
1008 names are give (list/tuple/str) then the variable values looked
1008 names are give (list/tuple/str) then the variable values looked
1009 up in the callers frame.
1009 up in the callers frame.
1010 interactive : bool
1010 interactive : bool
1011 If True (default), the variables will be listed with the ``who``
1011 If True (default), the variables will be listed with the ``who``
1012 magic.
1012 magic.
1013 """
1013 """
1014 vdict = None
1014 vdict = None
1015
1015
1016 # We need a dict of name/value pairs to do namespace updates.
1016 # We need a dict of name/value pairs to do namespace updates.
1017 if isinstance(variables, dict):
1017 if isinstance(variables, dict):
1018 vdict = variables
1018 vdict = variables
1019 elif isinstance(variables, (basestring, list, tuple)):
1019 elif isinstance(variables, (basestring, list, tuple)):
1020 if isinstance(variables, basestring):
1020 if isinstance(variables, basestring):
1021 vlist = variables.split()
1021 vlist = variables.split()
1022 else:
1022 else:
1023 vlist = variables
1023 vlist = variables
1024 vdict = {}
1024 vdict = {}
1025 cf = sys._getframe(1)
1025 cf = sys._getframe(1)
1026 for name in vlist:
1026 for name in vlist:
1027 try:
1027 try:
1028 vdict[name] = eval(name, cf.f_globals, cf.f_locals)
1028 vdict[name] = eval(name, cf.f_globals, cf.f_locals)
1029 except:
1029 except:
1030 print ('Could not get variable %s from %s' %
1030 print ('Could not get variable %s from %s' %
1031 (name,cf.f_code.co_name))
1031 (name,cf.f_code.co_name))
1032 else:
1032 else:
1033 raise ValueError('variables must be a dict/str/list/tuple')
1033 raise ValueError('variables must be a dict/str/list/tuple')
1034
1034
1035 # Propagate variables to user namespace
1035 # Propagate variables to user namespace
1036 self.user_ns.update(vdict)
1036 self.user_ns.update(vdict)
1037
1037
1038 # And configure interactive visibility
1038 # And configure interactive visibility
1039 config_ns = self.user_config_ns
1039 config_ns = self.user_config_ns
1040 if interactive:
1040 if interactive:
1041 for name, val in vdict.iteritems():
1041 for name, val in vdict.iteritems():
1042 config_ns.pop(name, None)
1042 config_ns.pop(name, None)
1043 else:
1043 else:
1044 for name,val in vdict.iteritems():
1044 for name,val in vdict.iteritems():
1045 config_ns[name] = val
1045 config_ns[name] = val
1046
1046
1047 #-------------------------------------------------------------------------
1047 #-------------------------------------------------------------------------
1048 # Things related to history management
1048 # Things related to history management
1049 #-------------------------------------------------------------------------
1049 #-------------------------------------------------------------------------
1050
1050
1051 def init_history(self):
1051 def init_history(self):
1052 # List of input with multi-line handling.
1052 # List of input with multi-line handling.
1053 self.input_hist = InputList()
1053 self.input_hist = InputList()
1054 # This one will hold the 'raw' input history, without any
1054 # This one will hold the 'raw' input history, without any
1055 # pre-processing. This will allow users to retrieve the input just as
1055 # pre-processing. This will allow users to retrieve the input just as
1056 # it was exactly typed in by the user, with %hist -r.
1056 # it was exactly typed in by the user, with %hist -r.
1057 self.input_hist_raw = InputList()
1057 self.input_hist_raw = InputList()
1058
1058
1059 # list of visited directories
1059 # list of visited directories
1060 try:
1060 try:
1061 self.dir_hist = [os.getcwd()]
1061 self.dir_hist = [os.getcwd()]
1062 except OSError:
1062 except OSError:
1063 self.dir_hist = []
1063 self.dir_hist = []
1064
1064
1065 # dict of output history
1065 # dict of output history
1066 self.output_hist = {}
1066 self.output_hist = {}
1067
1067
1068 # Now the history file
1068 # Now the history file
1069 if self.profile:
1069 if self.profile:
1070 histfname = 'history-%s' % self.profile
1070 histfname = 'history-%s' % self.profile
1071 else:
1071 else:
1072 histfname = 'history'
1072 histfname = 'history'
1073 self.histfile = os.path.join(self.ipythondir, histfname)
1073 self.histfile = os.path.join(self.ipythondir, histfname)
1074
1074
1075 # Fill the history zero entry, user counter starts at 1
1075 # Fill the history zero entry, user counter starts at 1
1076 self.input_hist.append('\n')
1076 self.input_hist.append('\n')
1077 self.input_hist_raw.append('\n')
1077 self.input_hist_raw.append('\n')
1078
1078
1079 def init_shadow_hist(self):
1079 def init_shadow_hist(self):
1080 try:
1080 try:
1081 self.db = pickleshare.PickleShareDB(self.ipythondir + "/db")
1081 self.db = pickleshare.PickleShareDB(self.ipythondir + "/db")
1082 except exceptions.UnicodeDecodeError:
1082 except exceptions.UnicodeDecodeError:
1083 print "Your ipythondir can't be decoded to unicode!"
1083 print "Your ipythondir can't be decoded to unicode!"
1084 print "Please set HOME environment variable to something that"
1084 print "Please set HOME environment variable to something that"
1085 print r"only has ASCII characters, e.g. c:\home"
1085 print r"only has ASCII characters, e.g. c:\home"
1086 print "Now it is", self.ipythondir
1086 print "Now it is", self.ipythondir
1087 sys.exit()
1087 sys.exit()
1088 self.shadowhist = ipcorehist.ShadowHist(self.db)
1088 self.shadowhist = ipcorehist.ShadowHist(self.db)
1089
1089
1090 def savehist(self):
1090 def savehist(self):
1091 """Save input history to a file (via readline library)."""
1091 """Save input history to a file (via readline library)."""
1092
1092
1093 if not self.has_readline:
1093 if not self.has_readline:
1094 return
1094 return
1095
1095
1096 try:
1096 try:
1097 self.readline.write_history_file(self.histfile)
1097 self.readline.write_history_file(self.histfile)
1098 except:
1098 except:
1099 print 'Unable to save IPython command history to file: ' + \
1099 print 'Unable to save IPython command history to file: ' + \
1100 `self.histfile`
1100 `self.histfile`
1101
1101
1102 def reloadhist(self):
1102 def reloadhist(self):
1103 """Reload the input history from disk file."""
1103 """Reload the input history from disk file."""
1104
1104
1105 if self.has_readline:
1105 if self.has_readline:
1106 try:
1106 try:
1107 self.readline.clear_history()
1107 self.readline.clear_history()
1108 self.readline.read_history_file(self.shell.histfile)
1108 self.readline.read_history_file(self.shell.histfile)
1109 except AttributeError:
1109 except AttributeError:
1110 pass
1110 pass
1111
1111
1112 def history_saving_wrapper(self, func):
1112 def history_saving_wrapper(self, func):
1113 """ Wrap func for readline history saving
1113 """ Wrap func for readline history saving
1114
1114
1115 Convert func into callable that saves & restores
1115 Convert func into callable that saves & restores
1116 history around the call """
1116 history around the call """
1117
1117
1118 if not self.has_readline:
1118 if not self.has_readline:
1119 return func
1119 return func
1120
1120
1121 def wrapper():
1121 def wrapper():
1122 self.savehist()
1122 self.savehist()
1123 try:
1123 try:
1124 func()
1124 func()
1125 finally:
1125 finally:
1126 readline.read_history_file(self.histfile)
1126 readline.read_history_file(self.histfile)
1127 return wrapper
1127 return wrapper
1128
1128
1129 #-------------------------------------------------------------------------
1129 #-------------------------------------------------------------------------
1130 # Things related to exception handling and tracebacks (not debugging)
1130 # Things related to exception handling and tracebacks (not debugging)
1131 #-------------------------------------------------------------------------
1131 #-------------------------------------------------------------------------
1132
1132
1133 def init_traceback_handlers(self, custom_exceptions):
1133 def init_traceback_handlers(self, custom_exceptions):
1134 # Syntax error handler.
1134 # Syntax error handler.
1135 self.SyntaxTB = SyntaxTB(color_scheme='NoColor')
1135 self.SyntaxTB = SyntaxTB(color_scheme='NoColor')
1136
1136
1137 # The interactive one is initialized with an offset, meaning we always
1137 # The interactive one is initialized with an offset, meaning we always
1138 # want to remove the topmost item in the traceback, which is our own
1138 # want to remove the topmost item in the traceback, which is our own
1139 # internal code. Valid modes: ['Plain','Context','Verbose']
1139 # internal code. Valid modes: ['Plain','Context','Verbose']
1140 self.InteractiveTB = ultratb.AutoFormattedTB(mode = 'Plain',
1140 self.InteractiveTB = ultratb.AutoFormattedTB(mode = 'Plain',
1141 color_scheme='NoColor',
1141 color_scheme='NoColor',
1142 tb_offset = 1)
1142 tb_offset = 1)
1143
1143
1144 # IPython itself shouldn't crash. This will produce a detailed
1144 # IPython itself shouldn't crash. This will produce a detailed
1145 # post-mortem if it does. But we only install the crash handler for
1145 # post-mortem if it does. But we only install the crash handler for
1146 # non-threaded shells, the threaded ones use a normal verbose reporter
1146 # non-threaded shells, the threaded ones use a normal verbose reporter
1147 # and lose the crash handler. This is because exceptions in the main
1147 # and lose the crash handler. This is because exceptions in the main
1148 # thread (such as in GUI code) propagate directly to sys.excepthook,
1148 # thread (such as in GUI code) propagate directly to sys.excepthook,
1149 # and there's no point in printing crash dumps for every user exception.
1149 # and there's no point in printing crash dumps for every user exception.
1150 if self.isthreaded:
1150 if self.isthreaded:
1151 ipCrashHandler = ultratb.FormattedTB()
1151 ipCrashHandler = ultratb.FormattedTB()
1152 else:
1152 else:
1153 from IPython.core import crashhandler
1153 from IPython.core import crashhandler
1154 ipCrashHandler = crashhandler.IPythonCrashHandler(self)
1154 ipCrashHandler = crashhandler.IPythonCrashHandler(self)
1155 self.set_crash_handler(ipCrashHandler)
1155 self.set_crash_handler(ipCrashHandler)
1156
1156
1157 # and add any custom exception handlers the user may have specified
1157 # and add any custom exception handlers the user may have specified
1158 self.set_custom_exc(*custom_exceptions)
1158 self.set_custom_exc(*custom_exceptions)
1159
1159
1160 def set_crash_handler(self, crashHandler):
1160 def set_crash_handler(self, crashHandler):
1161 """Set the IPython crash handler.
1161 """Set the IPython crash handler.
1162
1162
1163 This must be a callable with a signature suitable for use as
1163 This must be a callable with a signature suitable for use as
1164 sys.excepthook."""
1164 sys.excepthook."""
1165
1165
1166 # Install the given crash handler as the Python exception hook
1166 # Install the given crash handler as the Python exception hook
1167 sys.excepthook = crashHandler
1167 sys.excepthook = crashHandler
1168
1168
1169 # The instance will store a pointer to this, so that runtime code
1169 # The instance will store a pointer to this, so that runtime code
1170 # (such as magics) can access it. This is because during the
1170 # (such as magics) can access it. This is because during the
1171 # read-eval loop, it gets temporarily overwritten (to deal with GUI
1171 # read-eval loop, it gets temporarily overwritten (to deal with GUI
1172 # frameworks).
1172 # frameworks).
1173 self.sys_excepthook = sys.excepthook
1173 self.sys_excepthook = sys.excepthook
1174
1174
1175 def set_custom_exc(self,exc_tuple,handler):
1175 def set_custom_exc(self,exc_tuple,handler):
1176 """set_custom_exc(exc_tuple,handler)
1176 """set_custom_exc(exc_tuple,handler)
1177
1177
1178 Set a custom exception handler, which will be called if any of the
1178 Set a custom exception handler, which will be called if any of the
1179 exceptions in exc_tuple occur in the mainloop (specifically, in the
1179 exceptions in exc_tuple occur in the mainloop (specifically, in the
1180 runcode() method.
1180 runcode() method.
1181
1181
1182 Inputs:
1182 Inputs:
1183
1183
1184 - exc_tuple: a *tuple* of valid exceptions to call the defined
1184 - exc_tuple: a *tuple* of valid exceptions to call the defined
1185 handler for. It is very important that you use a tuple, and NOT A
1185 handler for. It is very important that you use a tuple, and NOT A
1186 LIST here, because of the way Python's except statement works. If
1186 LIST here, because of the way Python's except statement works. If
1187 you only want to trap a single exception, use a singleton tuple:
1187 you only want to trap a single exception, use a singleton tuple:
1188
1188
1189 exc_tuple == (MyCustomException,)
1189 exc_tuple == (MyCustomException,)
1190
1190
1191 - handler: this must be defined as a function with the following
1191 - handler: this must be defined as a function with the following
1192 basic interface: def my_handler(self,etype,value,tb).
1192 basic interface: def my_handler(self,etype,value,tb).
1193
1193
1194 This will be made into an instance method (via new.instancemethod)
1194 This will be made into an instance method (via new.instancemethod)
1195 of IPython itself, and it will be called if any of the exceptions
1195 of IPython itself, and it will be called if any of the exceptions
1196 listed in the exc_tuple are caught. If the handler is None, an
1196 listed in the exc_tuple are caught. If the handler is None, an
1197 internal basic one is used, which just prints basic info.
1197 internal basic one is used, which just prints basic info.
1198
1198
1199 WARNING: by putting in your own exception handler into IPython's main
1199 WARNING: by putting in your own exception handler into IPython's main
1200 execution loop, you run a very good chance of nasty crashes. This
1200 execution loop, you run a very good chance of nasty crashes. This
1201 facility should only be used if you really know what you are doing."""
1201 facility should only be used if you really know what you are doing."""
1202
1202
1203 assert type(exc_tuple)==type(()) , \
1203 assert type(exc_tuple)==type(()) , \
1204 "The custom exceptions must be given AS A TUPLE."
1204 "The custom exceptions must be given AS A TUPLE."
1205
1205
1206 def dummy_handler(self,etype,value,tb):
1206 def dummy_handler(self,etype,value,tb):
1207 print '*** Simple custom exception handler ***'
1207 print '*** Simple custom exception handler ***'
1208 print 'Exception type :',etype
1208 print 'Exception type :',etype
1209 print 'Exception value:',value
1209 print 'Exception value:',value
1210 print 'Traceback :',tb
1210 print 'Traceback :',tb
1211 print 'Source code :','\n'.join(self.buffer)
1211 print 'Source code :','\n'.join(self.buffer)
1212
1212
1213 if handler is None: handler = dummy_handler
1213 if handler is None: handler = dummy_handler
1214
1214
1215 self.CustomTB = new.instancemethod(handler,self,self.__class__)
1215 self.CustomTB = new.instancemethod(handler,self,self.__class__)
1216 self.custom_exceptions = exc_tuple
1216 self.custom_exceptions = exc_tuple
1217
1217
1218 def excepthook(self, etype, value, tb):
1218 def excepthook(self, etype, value, tb):
1219 """One more defense for GUI apps that call sys.excepthook.
1219 """One more defense for GUI apps that call sys.excepthook.
1220
1220
1221 GUI frameworks like wxPython trap exceptions and call
1221 GUI frameworks like wxPython trap exceptions and call
1222 sys.excepthook themselves. I guess this is a feature that
1222 sys.excepthook themselves. I guess this is a feature that
1223 enables them to keep running after exceptions that would
1223 enables them to keep running after exceptions that would
1224 otherwise kill their mainloop. This is a bother for IPython
1224 otherwise kill their mainloop. This is a bother for IPython
1225 which excepts to catch all of the program exceptions with a try:
1225 which excepts to catch all of the program exceptions with a try:
1226 except: statement.
1226 except: statement.
1227
1227
1228 Normally, IPython sets sys.excepthook to a CrashHandler instance, so if
1228 Normally, IPython sets sys.excepthook to a CrashHandler instance, so if
1229 any app directly invokes sys.excepthook, it will look to the user like
1229 any app directly invokes sys.excepthook, it will look to the user like
1230 IPython crashed. In order to work around this, we can disable the
1230 IPython crashed. In order to work around this, we can disable the
1231 CrashHandler and replace it with this excepthook instead, which prints a
1231 CrashHandler and replace it with this excepthook instead, which prints a
1232 regular traceback using our InteractiveTB. In this fashion, apps which
1232 regular traceback using our InteractiveTB. In this fashion, apps which
1233 call sys.excepthook will generate a regular-looking exception from
1233 call sys.excepthook will generate a regular-looking exception from
1234 IPython, and the CrashHandler will only be triggered by real IPython
1234 IPython, and the CrashHandler will only be triggered by real IPython
1235 crashes.
1235 crashes.
1236
1236
1237 This hook should be used sparingly, only in places which are not likely
1237 This hook should be used sparingly, only in places which are not likely
1238 to be true IPython errors.
1238 to be true IPython errors.
1239 """
1239 """
1240 self.showtraceback((etype,value,tb),tb_offset=0)
1240 self.showtraceback((etype,value,tb),tb_offset=0)
1241
1241
1242 def showtraceback(self,exc_tuple = None,filename=None,tb_offset=None):
1242 def showtraceback(self,exc_tuple = None,filename=None,tb_offset=None):
1243 """Display the exception that just occurred.
1243 """Display the exception that just occurred.
1244
1244
1245 If nothing is known about the exception, this is the method which
1245 If nothing is known about the exception, this is the method which
1246 should be used throughout the code for presenting user tracebacks,
1246 should be used throughout the code for presenting user tracebacks,
1247 rather than directly invoking the InteractiveTB object.
1247 rather than directly invoking the InteractiveTB object.
1248
1248
1249 A specific showsyntaxerror() also exists, but this method can take
1249 A specific showsyntaxerror() also exists, but this method can take
1250 care of calling it if needed, so unless you are explicitly catching a
1250 care of calling it if needed, so unless you are explicitly catching a
1251 SyntaxError exception, don't try to analyze the stack manually and
1251 SyntaxError exception, don't try to analyze the stack manually and
1252 simply call this method."""
1252 simply call this method."""
1253
1253
1254
1254
1255 # Though this won't be called by syntax errors in the input line,
1255 # Though this won't be called by syntax errors in the input line,
1256 # there may be SyntaxError cases whith imported code.
1256 # there may be SyntaxError cases whith imported code.
1257
1257
1258 try:
1258 try:
1259 if exc_tuple is None:
1259 if exc_tuple is None:
1260 etype, value, tb = sys.exc_info()
1260 etype, value, tb = sys.exc_info()
1261 else:
1261 else:
1262 etype, value, tb = exc_tuple
1262 etype, value, tb = exc_tuple
1263
1263
1264 if etype is SyntaxError:
1264 if etype is SyntaxError:
1265 self.showsyntaxerror(filename)
1265 self.showsyntaxerror(filename)
1266 elif etype is UsageError:
1266 elif etype is UsageError:
1267 print "UsageError:", value
1267 print "UsageError:", value
1268 else:
1268 else:
1269 # WARNING: these variables are somewhat deprecated and not
1269 # WARNING: these variables are somewhat deprecated and not
1270 # necessarily safe to use in a threaded environment, but tools
1270 # necessarily safe to use in a threaded environment, but tools
1271 # like pdb depend on their existence, so let's set them. If we
1271 # like pdb depend on their existence, so let's set them. If we
1272 # find problems in the field, we'll need to revisit their use.
1272 # find problems in the field, we'll need to revisit their use.
1273 sys.last_type = etype
1273 sys.last_type = etype
1274 sys.last_value = value
1274 sys.last_value = value
1275 sys.last_traceback = tb
1275 sys.last_traceback = tb
1276
1276
1277 if etype in self.custom_exceptions:
1277 if etype in self.custom_exceptions:
1278 self.CustomTB(etype,value,tb)
1278 self.CustomTB(etype,value,tb)
1279 else:
1279 else:
1280 self.InteractiveTB(etype,value,tb,tb_offset=tb_offset)
1280 self.InteractiveTB(etype,value,tb,tb_offset=tb_offset)
1281 if self.InteractiveTB.call_pdb and self.has_readline:
1281 if self.InteractiveTB.call_pdb and self.has_readline:
1282 # pdb mucks up readline, fix it back
1282 # pdb mucks up readline, fix it back
1283 self.set_completer()
1283 self.set_completer()
1284 except KeyboardInterrupt:
1284 except KeyboardInterrupt:
1285 self.write("\nKeyboardInterrupt\n")
1285 self.write("\nKeyboardInterrupt\n")
1286
1286
1287 def showsyntaxerror(self, filename=None):
1287 def showsyntaxerror(self, filename=None):
1288 """Display the syntax error that just occurred.
1288 """Display the syntax error that just occurred.
1289
1289
1290 This doesn't display a stack trace because there isn't one.
1290 This doesn't display a stack trace because there isn't one.
1291
1291
1292 If a filename is given, it is stuffed in the exception instead
1292 If a filename is given, it is stuffed in the exception instead
1293 of what was there before (because Python's parser always uses
1293 of what was there before (because Python's parser always uses
1294 "<string>" when reading from a string).
1294 "<string>" when reading from a string).
1295 """
1295 """
1296 etype, value, last_traceback = sys.exc_info()
1296 etype, value, last_traceback = sys.exc_info()
1297
1297
1298 # See note about these variables in showtraceback() below
1298 # See note about these variables in showtraceback() below
1299 sys.last_type = etype
1299 sys.last_type = etype
1300 sys.last_value = value
1300 sys.last_value = value
1301 sys.last_traceback = last_traceback
1301 sys.last_traceback = last_traceback
1302
1302
1303 if filename and etype is SyntaxError:
1303 if filename and etype is SyntaxError:
1304 # Work hard to stuff the correct filename in the exception
1304 # Work hard to stuff the correct filename in the exception
1305 try:
1305 try:
1306 msg, (dummy_filename, lineno, offset, line) = value
1306 msg, (dummy_filename, lineno, offset, line) = value
1307 except:
1307 except:
1308 # Not the format we expect; leave it alone
1308 # Not the format we expect; leave it alone
1309 pass
1309 pass
1310 else:
1310 else:
1311 # Stuff in the right filename
1311 # Stuff in the right filename
1312 try:
1312 try:
1313 # Assume SyntaxError is a class exception
1313 # Assume SyntaxError is a class exception
1314 value = SyntaxError(msg, (filename, lineno, offset, line))
1314 value = SyntaxError(msg, (filename, lineno, offset, line))
1315 except:
1315 except:
1316 # If that failed, assume SyntaxError is a string
1316 # If that failed, assume SyntaxError is a string
1317 value = msg, (filename, lineno, offset, line)
1317 value = msg, (filename, lineno, offset, line)
1318 self.SyntaxTB(etype,value,[])
1318 self.SyntaxTB(etype,value,[])
1319
1319
1320 def edit_syntax_error(self):
1320 def edit_syntax_error(self):
1321 """The bottom half of the syntax error handler called in the main loop.
1321 """The bottom half of the syntax error handler called in the main loop.
1322
1322
1323 Loop until syntax error is fixed or user cancels.
1323 Loop until syntax error is fixed or user cancels.
1324 """
1324 """
1325
1325
1326 while self.SyntaxTB.last_syntax_error:
1326 while self.SyntaxTB.last_syntax_error:
1327 # copy and clear last_syntax_error
1327 # copy and clear last_syntax_error
1328 err = self.SyntaxTB.clear_err_state()
1328 err = self.SyntaxTB.clear_err_state()
1329 if not self._should_recompile(err):
1329 if not self._should_recompile(err):
1330 return
1330 return
1331 try:
1331 try:
1332 # may set last_syntax_error again if a SyntaxError is raised
1332 # may set last_syntax_error again if a SyntaxError is raised
1333 self.safe_execfile(err.filename,self.user_ns)
1333 self.safe_execfile(err.filename,self.user_ns)
1334 except:
1334 except:
1335 self.showtraceback()
1335 self.showtraceback()
1336 else:
1336 else:
1337 try:
1337 try:
1338 f = file(err.filename)
1338 f = file(err.filename)
1339 try:
1339 try:
1340 # This should be inside a display_trap block and I
1340 # This should be inside a display_trap block and I
1341 # think it is.
1341 # think it is.
1342 sys.displayhook(f.read())
1342 sys.displayhook(f.read())
1343 finally:
1343 finally:
1344 f.close()
1344 f.close()
1345 except:
1345 except:
1346 self.showtraceback()
1346 self.showtraceback()
1347
1347
1348 def _should_recompile(self,e):
1348 def _should_recompile(self,e):
1349 """Utility routine for edit_syntax_error"""
1349 """Utility routine for edit_syntax_error"""
1350
1350
1351 if e.filename in ('<ipython console>','<input>','<string>',
1351 if e.filename in ('<ipython console>','<input>','<string>',
1352 '<console>','<BackgroundJob compilation>',
1352 '<console>','<BackgroundJob compilation>',
1353 None):
1353 None):
1354
1354
1355 return False
1355 return False
1356 try:
1356 try:
1357 if (self.autoedit_syntax and
1357 if (self.autoedit_syntax and
1358 not self.ask_yes_no('Return to editor to correct syntax error? '
1358 not self.ask_yes_no('Return to editor to correct syntax error? '
1359 '[Y/n] ','y')):
1359 '[Y/n] ','y')):
1360 return False
1360 return False
1361 except EOFError:
1361 except EOFError:
1362 return False
1362 return False
1363
1363
1364 def int0(x):
1364 def int0(x):
1365 try:
1365 try:
1366 return int(x)
1366 return int(x)
1367 except TypeError:
1367 except TypeError:
1368 return 0
1368 return 0
1369 # always pass integer line and offset values to editor hook
1369 # always pass integer line and offset values to editor hook
1370 try:
1370 try:
1371 self.hooks.fix_error_editor(e.filename,
1371 self.hooks.fix_error_editor(e.filename,
1372 int0(e.lineno),int0(e.offset),e.msg)
1372 int0(e.lineno),int0(e.offset),e.msg)
1373 except TryNext:
1373 except TryNext:
1374 warn('Could not open editor')
1374 warn('Could not open editor')
1375 return False
1375 return False
1376 return True
1376 return True
1377
1377
1378 #-------------------------------------------------------------------------
1378 #-------------------------------------------------------------------------
1379 # Things related to tab completion
1379 # Things related to tab completion
1380 #-------------------------------------------------------------------------
1380 #-------------------------------------------------------------------------
1381
1381
1382 def complete(self, text):
1382 def complete(self, text):
1383 """Return a sorted list of all possible completions on text.
1383 """Return a sorted list of all possible completions on text.
1384
1384
1385 Inputs:
1385 Inputs:
1386
1386
1387 - text: a string of text to be completed on.
1387 - text: a string of text to be completed on.
1388
1388
1389 This is a wrapper around the completion mechanism, similar to what
1389 This is a wrapper around the completion mechanism, similar to what
1390 readline does at the command line when the TAB key is hit. By
1390 readline does at the command line when the TAB key is hit. By
1391 exposing it as a method, it can be used by other non-readline
1391 exposing it as a method, it can be used by other non-readline
1392 environments (such as GUIs) for text completion.
1392 environments (such as GUIs) for text completion.
1393
1393
1394 Simple usage example:
1394 Simple usage example:
1395
1395
1396 In [7]: x = 'hello'
1396 In [7]: x = 'hello'
1397
1397
1398 In [8]: x
1398 In [8]: x
1399 Out[8]: 'hello'
1399 Out[8]: 'hello'
1400
1400
1401 In [9]: print x
1401 In [9]: print x
1402 hello
1402 hello
1403
1403
1404 In [10]: _ip.complete('x.l')
1404 In [10]: _ip.complete('x.l')
1405 Out[10]: ['x.ljust', 'x.lower', 'x.lstrip']
1405 Out[10]: ['x.ljust', 'x.lower', 'x.lstrip']
1406 """
1406 """
1407
1407
1408 # Inject names into __builtin__ so we can complete on the added names.
1408 # Inject names into __builtin__ so we can complete on the added names.
1409 with self.builtin_trap:
1409 with self.builtin_trap:
1410 complete = self.Completer.complete
1410 complete = self.Completer.complete
1411 state = 0
1411 state = 0
1412 # use a dict so we get unique keys, since ipyhton's multiple
1412 # use a dict so we get unique keys, since ipyhton's multiple
1413 # completers can return duplicates. When we make 2.4 a requirement,
1413 # completers can return duplicates. When we make 2.4 a requirement,
1414 # start using sets instead, which are faster.
1414 # start using sets instead, which are faster.
1415 comps = {}
1415 comps = {}
1416 while True:
1416 while True:
1417 newcomp = complete(text,state,line_buffer=text)
1417 newcomp = complete(text,state,line_buffer=text)
1418 if newcomp is None:
1418 if newcomp is None:
1419 break
1419 break
1420 comps[newcomp] = 1
1420 comps[newcomp] = 1
1421 state += 1
1421 state += 1
1422 outcomps = comps.keys()
1422 outcomps = comps.keys()
1423 outcomps.sort()
1423 outcomps.sort()
1424 #print "T:",text,"OC:",outcomps # dbg
1424 #print "T:",text,"OC:",outcomps # dbg
1425 #print "vars:",self.user_ns.keys()
1425 #print "vars:",self.user_ns.keys()
1426 return outcomps
1426 return outcomps
1427
1427
1428 def set_custom_completer(self,completer,pos=0):
1428 def set_custom_completer(self,completer,pos=0):
1429 """set_custom_completer(completer,pos=0)
1429 """set_custom_completer(completer,pos=0)
1430
1430
1431 Adds a new custom completer function.
1431 Adds a new custom completer function.
1432
1432
1433 The position argument (defaults to 0) is the index in the completers
1433 The position argument (defaults to 0) is the index in the completers
1434 list where you want the completer to be inserted."""
1434 list where you want the completer to be inserted."""
1435
1435
1436 newcomp = new.instancemethod(completer,self.Completer,
1436 newcomp = new.instancemethod(completer,self.Completer,
1437 self.Completer.__class__)
1437 self.Completer.__class__)
1438 self.Completer.matchers.insert(pos,newcomp)
1438 self.Completer.matchers.insert(pos,newcomp)
1439
1439
1440 def set_completer(self):
1440 def set_completer(self):
1441 """reset readline's completer to be our own."""
1441 """reset readline's completer to be our own."""
1442 self.readline.set_completer(self.Completer.complete)
1442 self.readline.set_completer(self.Completer.complete)
1443
1443
1444 #-------------------------------------------------------------------------
1444 #-------------------------------------------------------------------------
1445 # Things related to readline
1445 # Things related to readline
1446 #-------------------------------------------------------------------------
1446 #-------------------------------------------------------------------------
1447
1447
1448 def init_readline(self):
1448 def init_readline(self):
1449 """Command history completion/saving/reloading."""
1449 """Command history completion/saving/reloading."""
1450
1450
1451 self.rl_next_input = None
1451 self.rl_next_input = None
1452 self.rl_do_indent = False
1452 self.rl_do_indent = False
1453
1453
1454 if not self.readline_use:
1454 if not self.readline_use:
1455 return
1455 return
1456
1456
1457 import IPython.utils.rlineimpl as readline
1457 import IPython.utils.rlineimpl as readline
1458
1458
1459 if not readline.have_readline:
1459 if not readline.have_readline:
1460 self.has_readline = 0
1460 self.has_readline = 0
1461 self.readline = None
1461 self.readline = None
1462 # no point in bugging windows users with this every time:
1462 # no point in bugging windows users with this every time:
1463 warn('Readline services not available on this platform.')
1463 warn('Readline services not available on this platform.')
1464 else:
1464 else:
1465 sys.modules['readline'] = readline
1465 sys.modules['readline'] = readline
1466 import atexit
1466 import atexit
1467 from IPython.core.completer import IPCompleter
1467 from IPython.core.completer import IPCompleter
1468 self.Completer = IPCompleter(self,
1468 self.Completer = IPCompleter(self,
1469 self.user_ns,
1469 self.user_ns,
1470 self.user_global_ns,
1470 self.user_global_ns,
1471 self.readline_omit__names,
1471 self.readline_omit__names,
1472 self.alias_manager.alias_table)
1472 self.alias_manager.alias_table)
1473 sdisp = self.strdispatchers.get('complete_command', StrDispatch())
1473 sdisp = self.strdispatchers.get('complete_command', StrDispatch())
1474 self.strdispatchers['complete_command'] = sdisp
1474 self.strdispatchers['complete_command'] = sdisp
1475 self.Completer.custom_completers = sdisp
1475 self.Completer.custom_completers = sdisp
1476 # Platform-specific configuration
1476 # Platform-specific configuration
1477 if os.name == 'nt':
1477 if os.name == 'nt':
1478 self.readline_startup_hook = readline.set_pre_input_hook
1478 self.readline_startup_hook = readline.set_pre_input_hook
1479 else:
1479 else:
1480 self.readline_startup_hook = readline.set_startup_hook
1480 self.readline_startup_hook = readline.set_startup_hook
1481
1481
1482 # Load user's initrc file (readline config)
1482 # Load user's initrc file (readline config)
1483 # Or if libedit is used, load editrc.
1483 # Or if libedit is used, load editrc.
1484 inputrc_name = os.environ.get('INPUTRC')
1484 inputrc_name = os.environ.get('INPUTRC')
1485 if inputrc_name is None:
1485 if inputrc_name is None:
1486 home_dir = get_home_dir()
1486 home_dir = get_home_dir()
1487 if home_dir is not None:
1487 if home_dir is not None:
1488 inputrc_name = '.inputrc'
1488 inputrc_name = '.inputrc'
1489 if readline.uses_libedit:
1489 if readline.uses_libedit:
1490 inputrc_name = '.editrc'
1490 inputrc_name = '.editrc'
1491 inputrc_name = os.path.join(home_dir, inputrc_name)
1491 inputrc_name = os.path.join(home_dir, inputrc_name)
1492 if os.path.isfile(inputrc_name):
1492 if os.path.isfile(inputrc_name):
1493 try:
1493 try:
1494 readline.read_init_file(inputrc_name)
1494 readline.read_init_file(inputrc_name)
1495 except:
1495 except:
1496 warn('Problems reading readline initialization file <%s>'
1496 warn('Problems reading readline initialization file <%s>'
1497 % inputrc_name)
1497 % inputrc_name)
1498
1498
1499 self.has_readline = 1
1499 self.has_readline = 1
1500 self.readline = readline
1500 self.readline = readline
1501 # save this in sys so embedded copies can restore it properly
1501 # save this in sys so embedded copies can restore it properly
1502 sys.ipcompleter = self.Completer.complete
1502 sys.ipcompleter = self.Completer.complete
1503 self.set_completer()
1503 self.set_completer()
1504
1504
1505 # Configure readline according to user's prefs
1505 # Configure readline according to user's prefs
1506 # This is only done if GNU readline is being used. If libedit
1506 # This is only done if GNU readline is being used. If libedit
1507 # is being used (as on Leopard) the readline config is
1507 # is being used (as on Leopard) the readline config is
1508 # not run as the syntax for libedit is different.
1508 # not run as the syntax for libedit is different.
1509 if not readline.uses_libedit:
1509 if not readline.uses_libedit:
1510 for rlcommand in self.readline_parse_and_bind:
1510 for rlcommand in self.readline_parse_and_bind:
1511 #print "loading rl:",rlcommand # dbg
1511 #print "loading rl:",rlcommand # dbg
1512 readline.parse_and_bind(rlcommand)
1512 readline.parse_and_bind(rlcommand)
1513
1513
1514 # Remove some chars from the delimiters list. If we encounter
1514 # Remove some chars from the delimiters list. If we encounter
1515 # unicode chars, discard them.
1515 # unicode chars, discard them.
1516 delims = readline.get_completer_delims().encode("ascii", "ignore")
1516 delims = readline.get_completer_delims().encode("ascii", "ignore")
1517 delims = delims.translate(string._idmap,
1517 delims = delims.translate(string._idmap,
1518 self.readline_remove_delims)
1518 self.readline_remove_delims)
1519 readline.set_completer_delims(delims)
1519 readline.set_completer_delims(delims)
1520 # otherwise we end up with a monster history after a while:
1520 # otherwise we end up with a monster history after a while:
1521 readline.set_history_length(1000)
1521 readline.set_history_length(1000)
1522 try:
1522 try:
1523 #print '*** Reading readline history' # dbg
1523 #print '*** Reading readline history' # dbg
1524 readline.read_history_file(self.histfile)
1524 readline.read_history_file(self.histfile)
1525 except IOError:
1525 except IOError:
1526 pass # It doesn't exist yet.
1526 pass # It doesn't exist yet.
1527
1527
1528 atexit.register(self.atexit_operations)
1528 atexit.register(self.atexit_operations)
1529 del atexit
1529 del atexit
1530
1530
1531 # Configure auto-indent for all platforms
1531 # Configure auto-indent for all platforms
1532 self.set_autoindent(self.autoindent)
1532 self.set_autoindent(self.autoindent)
1533
1533
1534 def set_next_input(self, s):
1534 def set_next_input(self, s):
1535 """ Sets the 'default' input string for the next command line.
1535 """ Sets the 'default' input string for the next command line.
1536
1536
1537 Requires readline.
1537 Requires readline.
1538
1538
1539 Example:
1539 Example:
1540
1540
1541 [D:\ipython]|1> _ip.set_next_input("Hello Word")
1541 [D:\ipython]|1> _ip.set_next_input("Hello Word")
1542 [D:\ipython]|2> Hello Word_ # cursor is here
1542 [D:\ipython]|2> Hello Word_ # cursor is here
1543 """
1543 """
1544
1544
1545 self.rl_next_input = s
1545 self.rl_next_input = s
1546
1546
1547 def pre_readline(self):
1547 def pre_readline(self):
1548 """readline hook to be used at the start of each line.
1548 """readline hook to be used at the start of each line.
1549
1549
1550 Currently it handles auto-indent only."""
1550 Currently it handles auto-indent only."""
1551
1551
1552 #debugx('self.indent_current_nsp','pre_readline:')
1552 #debugx('self.indent_current_nsp','pre_readline:')
1553
1553
1554 if self.rl_do_indent:
1554 if self.rl_do_indent:
1555 self.readline.insert_text(self._indent_current_str())
1555 self.readline.insert_text(self._indent_current_str())
1556 if self.rl_next_input is not None:
1556 if self.rl_next_input is not None:
1557 self.readline.insert_text(self.rl_next_input)
1557 self.readline.insert_text(self.rl_next_input)
1558 self.rl_next_input = None
1558 self.rl_next_input = None
1559
1559
1560 def _indent_current_str(self):
1560 def _indent_current_str(self):
1561 """return the current level of indentation as a string"""
1561 """return the current level of indentation as a string"""
1562 return self.indent_current_nsp * ' '
1562 return self.indent_current_nsp * ' '
1563
1563
1564 #-------------------------------------------------------------------------
1564 #-------------------------------------------------------------------------
1565 # Things related to magics
1565 # Things related to magics
1566 #-------------------------------------------------------------------------
1566 #-------------------------------------------------------------------------
1567
1567
1568 def init_magics(self):
1568 def init_magics(self):
1569 # Set user colors (don't do it in the constructor above so that it
1569 # Set user colors (don't do it in the constructor above so that it
1570 # doesn't crash if colors option is invalid)
1570 # doesn't crash if colors option is invalid)
1571 self.magic_colors(self.colors)
1571 self.magic_colors(self.colors)
1572
1572
1573 def magic(self,arg_s):
1573 def magic(self,arg_s):
1574 """Call a magic function by name.
1574 """Call a magic function by name.
1575
1575
1576 Input: a string containing the name of the magic function to call and any
1576 Input: a string containing the name of the magic function to call and any
1577 additional arguments to be passed to the magic.
1577 additional arguments to be passed to the magic.
1578
1578
1579 magic('name -opt foo bar') is equivalent to typing at the ipython
1579 magic('name -opt foo bar') is equivalent to typing at the ipython
1580 prompt:
1580 prompt:
1581
1581
1582 In[1]: %name -opt foo bar
1582 In[1]: %name -opt foo bar
1583
1583
1584 To call a magic without arguments, simply use magic('name').
1584 To call a magic without arguments, simply use magic('name').
1585
1585
1586 This provides a proper Python function to call IPython's magics in any
1586 This provides a proper Python function to call IPython's magics in any
1587 valid Python code you can type at the interpreter, including loops and
1587 valid Python code you can type at the interpreter, including loops and
1588 compound statements.
1588 compound statements.
1589 """
1589 """
1590
1590
1591 args = arg_s.split(' ',1)
1591 args = arg_s.split(' ',1)
1592 magic_name = args[0]
1592 magic_name = args[0]
1593 magic_name = magic_name.lstrip(prefilter.ESC_MAGIC)
1593 magic_name = magic_name.lstrip(prefilter.ESC_MAGIC)
1594
1594
1595 try:
1595 try:
1596 magic_args = args[1]
1596 magic_args = args[1]
1597 except IndexError:
1597 except IndexError:
1598 magic_args = ''
1598 magic_args = ''
1599 fn = getattr(self,'magic_'+magic_name,None)
1599 fn = getattr(self,'magic_'+magic_name,None)
1600 if fn is None:
1600 if fn is None:
1601 error("Magic function `%s` not found." % magic_name)
1601 error("Magic function `%s` not found." % magic_name)
1602 else:
1602 else:
1603 magic_args = self.var_expand(magic_args,1)
1603 magic_args = self.var_expand(magic_args,1)
1604 with nested(self.builtin_trap,):
1604 with nested(self.builtin_trap,):
1605 result = fn(magic_args)
1605 result = fn(magic_args)
1606 return result
1606 return result
1607
1607
1608 def define_magic(self, magicname, func):
1608 def define_magic(self, magicname, func):
1609 """Expose own function as magic function for ipython
1609 """Expose own function as magic function for ipython
1610
1610
1611 def foo_impl(self,parameter_s=''):
1611 def foo_impl(self,parameter_s=''):
1612 'My very own magic!. (Use docstrings, IPython reads them).'
1612 'My very own magic!. (Use docstrings, IPython reads them).'
1613 print 'Magic function. Passed parameter is between < >:'
1613 print 'Magic function. Passed parameter is between < >:'
1614 print '<%s>' % parameter_s
1614 print '<%s>' % parameter_s
1615 print 'The self object is:',self
1615 print 'The self object is:',self
1616
1616
1617 self.define_magic('foo',foo_impl)
1617 self.define_magic('foo',foo_impl)
1618 """
1618 """
1619
1619
1620 import new
1620 import new
1621 im = new.instancemethod(func,self, self.__class__)
1621 im = new.instancemethod(func,self, self.__class__)
1622 old = getattr(self, "magic_" + magicname, None)
1622 old = getattr(self, "magic_" + magicname, None)
1623 setattr(self, "magic_" + magicname, im)
1623 setattr(self, "magic_" + magicname, im)
1624 return old
1624 return old
1625
1625
1626 #-------------------------------------------------------------------------
1626 #-------------------------------------------------------------------------
1627 # Things related to macros
1627 # Things related to macros
1628 #-------------------------------------------------------------------------
1628 #-------------------------------------------------------------------------
1629
1629
1630 def define_macro(self, name, themacro):
1630 def define_macro(self, name, themacro):
1631 """Define a new macro
1631 """Define a new macro
1632
1632
1633 Parameters
1633 Parameters
1634 ----------
1634 ----------
1635 name : str
1635 name : str
1636 The name of the macro.
1636 The name of the macro.
1637 themacro : str or Macro
1637 themacro : str or Macro
1638 The action to do upon invoking the macro. If a string, a new
1638 The action to do upon invoking the macro. If a string, a new
1639 Macro object is created by passing the string to it.
1639 Macro object is created by passing the string to it.
1640 """
1640 """
1641
1641
1642 from IPython.core import macro
1642 from IPython.core import macro
1643
1643
1644 if isinstance(themacro, basestring):
1644 if isinstance(themacro, basestring):
1645 themacro = macro.Macro(themacro)
1645 themacro = macro.Macro(themacro)
1646 if not isinstance(themacro, macro.Macro):
1646 if not isinstance(themacro, macro.Macro):
1647 raise ValueError('A macro must be a string or a Macro instance.')
1647 raise ValueError('A macro must be a string or a Macro instance.')
1648 self.user_ns[name] = themacro
1648 self.user_ns[name] = themacro
1649
1649
1650 #-------------------------------------------------------------------------
1650 #-------------------------------------------------------------------------
1651 # Things related to the running of system commands
1651 # Things related to the running of system commands
1652 #-------------------------------------------------------------------------
1652 #-------------------------------------------------------------------------
1653
1653
1654 def system(self, cmd):
1654 def system(self, cmd):
1655 """Make a system call, using IPython."""
1655 """Make a system call, using IPython."""
1656 return self.hooks.shell_hook(self.var_expand(cmd, depth=2))
1656 return self.hooks.shell_hook(self.var_expand(cmd, depth=2))
1657
1657
1658 #-------------------------------------------------------------------------
1658 #-------------------------------------------------------------------------
1659 # Things related to aliases
1659 # Things related to aliases
1660 #-------------------------------------------------------------------------
1660 #-------------------------------------------------------------------------
1661
1661
1662 def init_alias(self):
1662 def init_alias(self):
1663 self.alias_manager = AliasManager(self, config=self.config)
1663 self.alias_manager = AliasManager(self, config=self.config)
1664 self.ns_table['alias'] = self.alias_manager.alias_table,
1664 self.ns_table['alias'] = self.alias_manager.alias_table,
1665
1665
1666 #-------------------------------------------------------------------------
1666 #-------------------------------------------------------------------------
1667 # Things related to the running of code
1667 # Things related to the running of code
1668 #-------------------------------------------------------------------------
1668 #-------------------------------------------------------------------------
1669
1669
1670 def ex(self, cmd):
1670 def ex(self, cmd):
1671 """Execute a normal python statement in user namespace."""
1671 """Execute a normal python statement in user namespace."""
1672 with nested(self.builtin_trap,):
1672 with nested(self.builtin_trap,):
1673 exec cmd in self.user_global_ns, self.user_ns
1673 exec cmd in self.user_global_ns, self.user_ns
1674
1674
1675 def ev(self, expr):
1675 def ev(self, expr):
1676 """Evaluate python expression expr in user namespace.
1676 """Evaluate python expression expr in user namespace.
1677
1677
1678 Returns the result of evaluation
1678 Returns the result of evaluation
1679 """
1679 """
1680 with nested(self.builtin_trap,):
1680 with nested(self.builtin_trap,):
1681 return eval(expr, self.user_global_ns, self.user_ns)
1681 return eval(expr, self.user_global_ns, self.user_ns)
1682
1682
1683 def mainloop(self, display_banner=None):
1683 def mainloop(self, display_banner=None):
1684 """Start the mainloop.
1684 """Start the mainloop.
1685
1685
1686 If an optional banner argument is given, it will override the
1686 If an optional banner argument is given, it will override the
1687 internally created default banner.
1687 internally created default banner.
1688 """
1688 """
1689
1689
1690 with nested(self.builtin_trap, self.display_trap):
1690 with nested(self.builtin_trap, self.display_trap):
1691
1691
1692 # if you run stuff with -c <cmd>, raw hist is not updated
1692 # if you run stuff with -c <cmd>, raw hist is not updated
1693 # ensure that it's in sync
1693 # ensure that it's in sync
1694 if len(self.input_hist) != len (self.input_hist_raw):
1694 if len(self.input_hist) != len (self.input_hist_raw):
1695 self.input_hist_raw = InputList(self.input_hist)
1695 self.input_hist_raw = InputList(self.input_hist)
1696
1696
1697 while 1:
1697 while 1:
1698 try:
1698 try:
1699 self.interact(display_banner=display_banner)
1699 self.interact(display_banner=display_banner)
1700 #self.interact_with_readline()
1700 #self.interact_with_readline()
1701 # XXX for testing of a readline-decoupled repl loop, call
1701 # XXX for testing of a readline-decoupled repl loop, call
1702 # interact_with_readline above
1702 # interact_with_readline above
1703 break
1703 break
1704 except KeyboardInterrupt:
1704 except KeyboardInterrupt:
1705 # this should not be necessary, but KeyboardInterrupt
1705 # this should not be necessary, but KeyboardInterrupt
1706 # handling seems rather unpredictable...
1706 # handling seems rather unpredictable...
1707 self.write("\nKeyboardInterrupt in interact()\n")
1707 self.write("\nKeyboardInterrupt in interact()\n")
1708
1708
1709 def interact_prompt(self):
1709 def interact_prompt(self):
1710 """ Print the prompt (in read-eval-print loop)
1710 """ Print the prompt (in read-eval-print loop)
1711
1711
1712 Provided for those who want to implement their own read-eval-print loop (e.g. GUIs), not
1712 Provided for those who want to implement their own read-eval-print loop (e.g. GUIs), not
1713 used in standard IPython flow.
1713 used in standard IPython flow.
1714 """
1714 """
1715 if self.more:
1715 if self.more:
1716 try:
1716 try:
1717 prompt = self.hooks.generate_prompt(True)
1717 prompt = self.hooks.generate_prompt(True)
1718 except:
1718 except:
1719 self.showtraceback()
1719 self.showtraceback()
1720 if self.autoindent:
1720 if self.autoindent:
1721 self.rl_do_indent = True
1721 self.rl_do_indent = True
1722
1722
1723 else:
1723 else:
1724 try:
1724 try:
1725 prompt = self.hooks.generate_prompt(False)
1725 prompt = self.hooks.generate_prompt(False)
1726 except:
1726 except:
1727 self.showtraceback()
1727 self.showtraceback()
1728 self.write(prompt)
1728 self.write(prompt)
1729
1729
1730 def interact_handle_input(self,line):
1730 def interact_handle_input(self,line):
1731 """ Handle the input line (in read-eval-print loop)
1731 """ Handle the input line (in read-eval-print loop)
1732
1732
1733 Provided for those who want to implement their own read-eval-print loop (e.g. GUIs), not
1733 Provided for those who want to implement their own read-eval-print loop (e.g. GUIs), not
1734 used in standard IPython flow.
1734 used in standard IPython flow.
1735 """
1735 """
1736 if line.lstrip() == line:
1736 if line.lstrip() == line:
1737 self.shadowhist.add(line.strip())
1737 self.shadowhist.add(line.strip())
1738 lineout = self.prefilter_manager.prefilter_lines(line,self.more)
1738 lineout = self.prefilter_manager.prefilter_lines(line,self.more)
1739
1739
1740 if line.strip():
1740 if line.strip():
1741 if self.more:
1741 if self.more:
1742 self.input_hist_raw[-1] += '%s\n' % line
1742 self.input_hist_raw[-1] += '%s\n' % line
1743 else:
1743 else:
1744 self.input_hist_raw.append('%s\n' % line)
1744 self.input_hist_raw.append('%s\n' % line)
1745
1745
1746
1746
1747 self.more = self.push_line(lineout)
1747 self.more = self.push_line(lineout)
1748 if (self.SyntaxTB.last_syntax_error and
1748 if (self.SyntaxTB.last_syntax_error and
1749 self.autoedit_syntax):
1749 self.autoedit_syntax):
1750 self.edit_syntax_error()
1750 self.edit_syntax_error()
1751
1751
1752 def interact_with_readline(self):
1752 def interact_with_readline(self):
1753 """ Demo of using interact_handle_input, interact_prompt
1753 """ Demo of using interact_handle_input, interact_prompt
1754
1754
1755 This is the main read-eval-print loop. If you need to implement your own (e.g. for GUI),
1755 This is the main read-eval-print loop. If you need to implement your own (e.g. for GUI),
1756 it should work like this.
1756 it should work like this.
1757 """
1757 """
1758 self.readline_startup_hook(self.pre_readline)
1758 self.readline_startup_hook(self.pre_readline)
1759 while not self.exit_now:
1759 while not self.exit_now:
1760 self.interact_prompt()
1760 self.interact_prompt()
1761 if self.more:
1761 if self.more:
1762 self.rl_do_indent = True
1762 self.rl_do_indent = True
1763 else:
1763 else:
1764 self.rl_do_indent = False
1764 self.rl_do_indent = False
1765 line = raw_input_original().decode(self.stdin_encoding)
1765 line = raw_input_original().decode(self.stdin_encoding)
1766 self.interact_handle_input(line)
1766 self.interact_handle_input(line)
1767
1767
1768 def interact(self, display_banner=None):
1768 def interact(self, display_banner=None):
1769 """Closely emulate the interactive Python console."""
1769 """Closely emulate the interactive Python console."""
1770
1770
1771 # batch run -> do not interact
1771 # batch run -> do not interact
1772 if self.exit_now:
1772 if self.exit_now:
1773 return
1773 return
1774
1774
1775 if display_banner is None:
1775 if display_banner is None:
1776 display_banner = self.display_banner
1776 display_banner = self.display_banner
1777 if display_banner:
1777 if display_banner:
1778 self.show_banner()
1778 self.show_banner()
1779
1779
1780 more = 0
1780 more = 0
1781
1781
1782 # Mark activity in the builtins
1782 # Mark activity in the builtins
1783 __builtin__.__dict__['__IPYTHON__active'] += 1
1783 __builtin__.__dict__['__IPYTHON__active'] += 1
1784
1784
1785 if self.has_readline:
1785 if self.has_readline:
1786 self.readline_startup_hook(self.pre_readline)
1786 self.readline_startup_hook(self.pre_readline)
1787 # exit_now is set by a call to %Exit or %Quit, through the
1787 # exit_now is set by a call to %Exit or %Quit, through the
1788 # ask_exit callback.
1788 # ask_exit callback.
1789
1789
1790 while not self.exit_now:
1790 while not self.exit_now:
1791 self.hooks.pre_prompt_hook()
1791 self.hooks.pre_prompt_hook()
1792 if more:
1792 if more:
1793 try:
1793 try:
1794 prompt = self.hooks.generate_prompt(True)
1794 prompt = self.hooks.generate_prompt(True)
1795 except:
1795 except:
1796 self.showtraceback()
1796 self.showtraceback()
1797 if self.autoindent:
1797 if self.autoindent:
1798 self.rl_do_indent = True
1798 self.rl_do_indent = True
1799
1799
1800 else:
1800 else:
1801 try:
1801 try:
1802 prompt = self.hooks.generate_prompt(False)
1802 prompt = self.hooks.generate_prompt(False)
1803 except:
1803 except:
1804 self.showtraceback()
1804 self.showtraceback()
1805 try:
1805 try:
1806 line = self.raw_input(prompt, more)
1806 line = self.raw_input(prompt, more)
1807 if self.exit_now:
1807 if self.exit_now:
1808 # quick exit on sys.std[in|out] close
1808 # quick exit on sys.std[in|out] close
1809 break
1809 break
1810 if self.autoindent:
1810 if self.autoindent:
1811 self.rl_do_indent = False
1811 self.rl_do_indent = False
1812
1812
1813 except KeyboardInterrupt:
1813 except KeyboardInterrupt:
1814 #double-guard against keyboardinterrupts during kbdint handling
1814 #double-guard against keyboardinterrupts during kbdint handling
1815 try:
1815 try:
1816 self.write('\nKeyboardInterrupt\n')
1816 self.write('\nKeyboardInterrupt\n')
1817 self.resetbuffer()
1817 self.resetbuffer()
1818 # keep cache in sync with the prompt counter:
1818 # keep cache in sync with the prompt counter:
1819 self.outputcache.prompt_count -= 1
1819 self.outputcache.prompt_count -= 1
1820
1820
1821 if self.autoindent:
1821 if self.autoindent:
1822 self.indent_current_nsp = 0
1822 self.indent_current_nsp = 0
1823 more = 0
1823 more = 0
1824 except KeyboardInterrupt:
1824 except KeyboardInterrupt:
1825 pass
1825 pass
1826 except EOFError:
1826 except EOFError:
1827 if self.autoindent:
1827 if self.autoindent:
1828 self.rl_do_indent = False
1828 self.rl_do_indent = False
1829 self.readline_startup_hook(None)
1829 self.readline_startup_hook(None)
1830 self.write('\n')
1830 self.write('\n')
1831 self.exit()
1831 self.exit()
1832 except bdb.BdbQuit:
1832 except bdb.BdbQuit:
1833 warn('The Python debugger has exited with a BdbQuit exception.\n'
1833 warn('The Python debugger has exited with a BdbQuit exception.\n'
1834 'Because of how pdb handles the stack, it is impossible\n'
1834 'Because of how pdb handles the stack, it is impossible\n'
1835 'for IPython to properly format this particular exception.\n'
1835 'for IPython to properly format this particular exception.\n'
1836 'IPython will resume normal operation.')
1836 'IPython will resume normal operation.')
1837 except:
1837 except:
1838 # exceptions here are VERY RARE, but they can be triggered
1838 # exceptions here are VERY RARE, but they can be triggered
1839 # asynchronously by signal handlers, for example.
1839 # asynchronously by signal handlers, for example.
1840 self.showtraceback()
1840 self.showtraceback()
1841 else:
1841 else:
1842 more = self.push_line(line)
1842 more = self.push_line(line)
1843 if (self.SyntaxTB.last_syntax_error and
1843 if (self.SyntaxTB.last_syntax_error and
1844 self.autoedit_syntax):
1844 self.autoedit_syntax):
1845 self.edit_syntax_error()
1845 self.edit_syntax_error()
1846
1846
1847 # We are off again...
1847 # We are off again...
1848 __builtin__.__dict__['__IPYTHON__active'] -= 1
1848 __builtin__.__dict__['__IPYTHON__active'] -= 1
1849
1849
1850 def safe_execfile(self, fname, *where, **kw):
1850 def safe_execfile(self, fname, *where, **kw):
1851 """A safe version of the builtin execfile().
1851 """A safe version of the builtin execfile().
1852
1852
1853 This version will never throw an exception, but instead print
1853 This version will never throw an exception, but instead print
1854 helpful error messages to the screen. This only works on pure
1854 helpful error messages to the screen. This only works on pure
1855 Python files with the .py extension.
1855 Python files with the .py extension.
1856
1856
1857 Parameters
1857 Parameters
1858 ----------
1858 ----------
1859 fname : string
1859 fname : string
1860 The name of the file to be executed.
1860 The name of the file to be executed.
1861 where : tuple
1861 where : tuple
1862 One or two namespaces, passed to execfile() as (globals,locals).
1862 One or two namespaces, passed to execfile() as (globals,locals).
1863 If only one is given, it is passed as both.
1863 If only one is given, it is passed as both.
1864 exit_ignore : bool (False)
1864 exit_ignore : bool (False)
1865 If True, then don't print errors for non-zero exit statuses.
1865 If True, then don't print errors for non-zero exit statuses.
1866 """
1866 """
1867 kw.setdefault('exit_ignore', False)
1867 kw.setdefault('exit_ignore', False)
1868
1868
1869 fname = os.path.abspath(os.path.expanduser(fname))
1869 fname = os.path.abspath(os.path.expanduser(fname))
1870
1870
1871 # Make sure we have a .py file
1871 # Make sure we have a .py file
1872 if not fname.endswith('.py'):
1872 if not fname.endswith('.py'):
1873 warn('File must end with .py to be run using execfile: <%s>' % fname)
1873 warn('File must end with .py to be run using execfile: <%s>' % fname)
1874
1874
1875 # Make sure we can open the file
1875 # Make sure we can open the file
1876 try:
1876 try:
1877 with open(fname) as thefile:
1877 with open(fname) as thefile:
1878 pass
1878 pass
1879 except:
1879 except:
1880 warn('Could not open file <%s> for safe execution.' % fname)
1880 warn('Could not open file <%s> for safe execution.' % fname)
1881 return
1881 return
1882
1882
1883 # Find things also in current directory. This is needed to mimic the
1883 # Find things also in current directory. This is needed to mimic the
1884 # behavior of running a script from the system command line, where
1884 # behavior of running a script from the system command line, where
1885 # Python inserts the script's directory into sys.path
1885 # Python inserts the script's directory into sys.path
1886 dname = os.path.dirname(fname)
1886 dname = os.path.dirname(fname)
1887
1887
1888 with prepended_to_syspath(dname):
1888 with prepended_to_syspath(dname):
1889 try:
1889 try:
1890 if sys.platform == 'win32' and sys.version_info < (2,5,1):
1890 if sys.platform == 'win32' and sys.version_info < (2,5,1):
1891 # Work around a bug in Python for Windows. The bug was
1891 # Work around a bug in Python for Windows. The bug was
1892 # fixed in in Python 2.5 r54159 and 54158, but that's still
1892 # fixed in in Python 2.5 r54159 and 54158, but that's still
1893 # SVN Python as of March/07. For details, see:
1893 # SVN Python as of March/07. For details, see:
1894 # http://projects.scipy.org/ipython/ipython/ticket/123
1894 # http://projects.scipy.org/ipython/ipython/ticket/123
1895 try:
1895 try:
1896 globs,locs = where[0:2]
1896 globs,locs = where[0:2]
1897 except:
1897 except:
1898 try:
1898 try:
1899 globs = locs = where[0]
1899 globs = locs = where[0]
1900 except:
1900 except:
1901 globs = locs = globals()
1901 globs = locs = globals()
1902 exec file(fname) in globs,locs
1902 exec file(fname) in globs,locs
1903 else:
1903 else:
1904 execfile(fname,*where)
1904 execfile(fname,*where)
1905 except SyntaxError:
1905 except SyntaxError:
1906 self.showsyntaxerror()
1906 self.showsyntaxerror()
1907 warn('Failure executing file: <%s>' % fname)
1907 warn('Failure executing file: <%s>' % fname)
1908 except SystemExit, status:
1908 except SystemExit, status:
1909 # Code that correctly sets the exit status flag to success (0)
1909 # Code that correctly sets the exit status flag to success (0)
1910 # shouldn't be bothered with a traceback. Note that a plain
1910 # shouldn't be bothered with a traceback. Note that a plain
1911 # sys.exit() does NOT set the message to 0 (it's empty) so that
1911 # sys.exit() does NOT set the message to 0 (it's empty) so that
1912 # will still get a traceback. Note that the structure of the
1912 # will still get a traceback. Note that the structure of the
1913 # SystemExit exception changed between Python 2.4 and 2.5, so
1913 # SystemExit exception changed between Python 2.4 and 2.5, so
1914 # the checks must be done in a version-dependent way.
1914 # the checks must be done in a version-dependent way.
1915 show = False
1915 show = False
1916 if status.message!=0 and not kw['exit_ignore']:
1916 if status.message!=0 and not kw['exit_ignore']:
1917 show = True
1917 show = True
1918 if show:
1918 if show:
1919 self.showtraceback()
1919 self.showtraceback()
1920 warn('Failure executing file: <%s>' % fname)
1920 warn('Failure executing file: <%s>' % fname)
1921 except:
1921 except:
1922 self.showtraceback()
1922 self.showtraceback()
1923 warn('Failure executing file: <%s>' % fname)
1923 warn('Failure executing file: <%s>' % fname)
1924
1924
1925 def safe_execfile_ipy(self, fname):
1925 def safe_execfile_ipy(self, fname):
1926 """Like safe_execfile, but for .ipy files with IPython syntax.
1926 """Like safe_execfile, but for .ipy files with IPython syntax.
1927
1927
1928 Parameters
1928 Parameters
1929 ----------
1929 ----------
1930 fname : str
1930 fname : str
1931 The name of the file to execute. The filename must have a
1931 The name of the file to execute. The filename must have a
1932 .ipy extension.
1932 .ipy extension.
1933 """
1933 """
1934 fname = os.path.abspath(os.path.expanduser(fname))
1934 fname = os.path.abspath(os.path.expanduser(fname))
1935
1935
1936 # Make sure we have a .py file
1936 # Make sure we have a .py file
1937 if not fname.endswith('.ipy'):
1937 if not fname.endswith('.ipy'):
1938 warn('File must end with .py to be run using execfile: <%s>' % fname)
1938 warn('File must end with .py to be run using execfile: <%s>' % fname)
1939
1939
1940 # Make sure we can open the file
1940 # Make sure we can open the file
1941 try:
1941 try:
1942 with open(fname) as thefile:
1942 with open(fname) as thefile:
1943 pass
1943 pass
1944 except:
1944 except:
1945 warn('Could not open file <%s> for safe execution.' % fname)
1945 warn('Could not open file <%s> for safe execution.' % fname)
1946 return
1946 return
1947
1947
1948 # Find things also in current directory. This is needed to mimic the
1948 # Find things also in current directory. This is needed to mimic the
1949 # behavior of running a script from the system command line, where
1949 # behavior of running a script from the system command line, where
1950 # Python inserts the script's directory into sys.path
1950 # Python inserts the script's directory into sys.path
1951 dname = os.path.dirname(fname)
1951 dname = os.path.dirname(fname)
1952
1952
1953 with prepended_to_syspath(dname):
1953 with prepended_to_syspath(dname):
1954 try:
1954 try:
1955 with open(fname) as thefile:
1955 with open(fname) as thefile:
1956 script = thefile.read()
1956 script = thefile.read()
1957 # self.runlines currently captures all exceptions
1957 # self.runlines currently captures all exceptions
1958 # raise in user code. It would be nice if there were
1958 # raise in user code. It would be nice if there were
1959 # versions of runlines, execfile that did raise, so
1959 # versions of runlines, execfile that did raise, so
1960 # we could catch the errors.
1960 # we could catch the errors.
1961 self.runlines(script, clean=True)
1961 self.runlines(script, clean=True)
1962 except:
1962 except:
1963 self.showtraceback()
1963 self.showtraceback()
1964 warn('Unknown failure executing file: <%s>' % fname)
1964 warn('Unknown failure executing file: <%s>' % fname)
1965
1965
1966 def _is_secondary_block_start(self, s):
1966 def _is_secondary_block_start(self, s):
1967 if not s.endswith(':'):
1967 if not s.endswith(':'):
1968 return False
1968 return False
1969 if (s.startswith('elif') or
1969 if (s.startswith('elif') or
1970 s.startswith('else') or
1970 s.startswith('else') or
1971 s.startswith('except') or
1971 s.startswith('except') or
1972 s.startswith('finally')):
1972 s.startswith('finally')):
1973 return True
1973 return True
1974
1974
1975 def cleanup_ipy_script(self, script):
1975 def cleanup_ipy_script(self, script):
1976 """Make a script safe for self.runlines()
1976 """Make a script safe for self.runlines()
1977
1977
1978 Currently, IPython is lines based, with blocks being detected by
1978 Currently, IPython is lines based, with blocks being detected by
1979 empty lines. This is a problem for block based scripts that may
1979 empty lines. This is a problem for block based scripts that may
1980 not have empty lines after blocks. This script adds those empty
1980 not have empty lines after blocks. This script adds those empty
1981 lines to make scripts safe for running in the current line based
1981 lines to make scripts safe for running in the current line based
1982 IPython.
1982 IPython.
1983 """
1983 """
1984 res = []
1984 res = []
1985 lines = script.splitlines()
1985 lines = script.splitlines()
1986 level = 0
1986 level = 0
1987
1987
1988 for l in lines:
1988 for l in lines:
1989 lstripped = l.lstrip()
1989 lstripped = l.lstrip()
1990 stripped = l.strip()
1990 stripped = l.strip()
1991 if not stripped:
1991 if not stripped:
1992 continue
1992 continue
1993 newlevel = len(l) - len(lstripped)
1993 newlevel = len(l) - len(lstripped)
1994 if level > 0 and newlevel == 0 and \
1994 if level > 0 and newlevel == 0 and \
1995 not self._is_secondary_block_start(stripped):
1995 not self._is_secondary_block_start(stripped):
1996 # add empty line
1996 # add empty line
1997 res.append('')
1997 res.append('')
1998 res.append(l)
1998 res.append(l)
1999 level = newlevel
1999 level = newlevel
2000
2000
2001 return '\n'.join(res) + '\n'
2001 return '\n'.join(res) + '\n'
2002
2002
2003 def runlines(self, lines, clean=False):
2003 def runlines(self, lines, clean=False):
2004 """Run a string of one or more lines of source.
2004 """Run a string of one or more lines of source.
2005
2005
2006 This method is capable of running a string containing multiple source
2006 This method is capable of running a string containing multiple source
2007 lines, as if they had been entered at the IPython prompt. Since it
2007 lines, as if they had been entered at the IPython prompt. Since it
2008 exposes IPython's processing machinery, the given strings can contain
2008 exposes IPython's processing machinery, the given strings can contain
2009 magic calls (%magic), special shell access (!cmd), etc.
2009 magic calls (%magic), special shell access (!cmd), etc.
2010 """
2010 """
2011
2011
2012 if isinstance(lines, (list, tuple)):
2012 if isinstance(lines, (list, tuple)):
2013 lines = '\n'.join(lines)
2013 lines = '\n'.join(lines)
2014
2014
2015 if clean:
2015 if clean:
2016 lines = self.cleanup_ipy_script(lines)
2016 lines = self.cleanup_ipy_script(lines)
2017
2017
2018 # We must start with a clean buffer, in case this is run from an
2018 # We must start with a clean buffer, in case this is run from an
2019 # interactive IPython session (via a magic, for example).
2019 # interactive IPython session (via a magic, for example).
2020 self.resetbuffer()
2020 self.resetbuffer()
2021 lines = lines.splitlines()
2021 lines = lines.splitlines()
2022 more = 0
2022 more = 0
2023
2023
2024 with nested(self.builtin_trap, self.display_trap):
2024 with nested(self.builtin_trap, self.display_trap):
2025 for line in lines:
2025 for line in lines:
2026 # skip blank lines so we don't mess up the prompt counter, but do
2026 # skip blank lines so we don't mess up the prompt counter, but do
2027 # NOT skip even a blank line if we are in a code block (more is
2027 # NOT skip even a blank line if we are in a code block (more is
2028 # true)
2028 # true)
2029
2029
2030 if line or more:
2030 if line or more:
2031 # push to raw history, so hist line numbers stay in sync
2031 # push to raw history, so hist line numbers stay in sync
2032 self.input_hist_raw.append("# " + line + "\n")
2032 self.input_hist_raw.append("# " + line + "\n")
2033 prefiltered = self.prefilter_manager.prefilter_lines(line,more)
2033 prefiltered = self.prefilter_manager.prefilter_lines(line,more)
2034 more = self.push_line(prefiltered)
2034 more = self.push_line(prefiltered)
2035 # IPython's runsource returns None if there was an error
2035 # IPython's runsource returns None if there was an error
2036 # compiling the code. This allows us to stop processing right
2036 # compiling the code. This allows us to stop processing right
2037 # away, so the user gets the error message at the right place.
2037 # away, so the user gets the error message at the right place.
2038 if more is None:
2038 if more is None:
2039 break
2039 break
2040 else:
2040 else:
2041 self.input_hist_raw.append("\n")
2041 self.input_hist_raw.append("\n")
2042 # final newline in case the input didn't have it, so that the code
2042 # final newline in case the input didn't have it, so that the code
2043 # actually does get executed
2043 # actually does get executed
2044 if more:
2044 if more:
2045 self.push_line('\n')
2045 self.push_line('\n')
2046
2046
2047 def runsource(self, source, filename='<input>', symbol='single'):
2047 def runsource(self, source, filename='<input>', symbol='single'):
2048 """Compile and run some source in the interpreter.
2048 """Compile and run some source in the interpreter.
2049
2049
2050 Arguments are as for compile_command().
2050 Arguments are as for compile_command().
2051
2051
2052 One several things can happen:
2052 One several things can happen:
2053
2053
2054 1) The input is incorrect; compile_command() raised an
2054 1) The input is incorrect; compile_command() raised an
2055 exception (SyntaxError or OverflowError). A syntax traceback
2055 exception (SyntaxError or OverflowError). A syntax traceback
2056 will be printed by calling the showsyntaxerror() method.
2056 will be printed by calling the showsyntaxerror() method.
2057
2057
2058 2) The input is incomplete, and more input is required;
2058 2) The input is incomplete, and more input is required;
2059 compile_command() returned None. Nothing happens.
2059 compile_command() returned None. Nothing happens.
2060
2060
2061 3) The input is complete; compile_command() returned a code
2061 3) The input is complete; compile_command() returned a code
2062 object. The code is executed by calling self.runcode() (which
2062 object. The code is executed by calling self.runcode() (which
2063 also handles run-time exceptions, except for SystemExit).
2063 also handles run-time exceptions, except for SystemExit).
2064
2064
2065 The return value is:
2065 The return value is:
2066
2066
2067 - True in case 2
2067 - True in case 2
2068
2068
2069 - False in the other cases, unless an exception is raised, where
2069 - False in the other cases, unless an exception is raised, where
2070 None is returned instead. This can be used by external callers to
2070 None is returned instead. This can be used by external callers to
2071 know whether to continue feeding input or not.
2071 know whether to continue feeding input or not.
2072
2072
2073 The return value can be used to decide whether to use sys.ps1 or
2073 The return value can be used to decide whether to use sys.ps1 or
2074 sys.ps2 to prompt the next line."""
2074 sys.ps2 to prompt the next line."""
2075
2075
2076 # if the source code has leading blanks, add 'if 1:\n' to it
2076 # if the source code has leading blanks, add 'if 1:\n' to it
2077 # this allows execution of indented pasted code. It is tempting
2077 # this allows execution of indented pasted code. It is tempting
2078 # to add '\n' at the end of source to run commands like ' a=1'
2078 # to add '\n' at the end of source to run commands like ' a=1'
2079 # directly, but this fails for more complicated scenarios
2079 # directly, but this fails for more complicated scenarios
2080 source=source.encode(self.stdin_encoding)
2080 source=source.encode(self.stdin_encoding)
2081 if source[:1] in [' ', '\t']:
2081 if source[:1] in [' ', '\t']:
2082 source = 'if 1:\n%s' % source
2082 source = 'if 1:\n%s' % source
2083
2083
2084 try:
2084 try:
2085 code = self.compile(source,filename,symbol)
2085 code = self.compile(source,filename,symbol)
2086 except (OverflowError, SyntaxError, ValueError, TypeError, MemoryError):
2086 except (OverflowError, SyntaxError, ValueError, TypeError, MemoryError):
2087 # Case 1
2087 # Case 1
2088 self.showsyntaxerror(filename)
2088 self.showsyntaxerror(filename)
2089 return None
2089 return None
2090
2090
2091 if code is None:
2091 if code is None:
2092 # Case 2
2092 # Case 2
2093 return True
2093 return True
2094
2094
2095 # Case 3
2095 # Case 3
2096 # We store the code object so that threaded shells and
2096 # We store the code object so that threaded shells and
2097 # custom exception handlers can access all this info if needed.
2097 # custom exception handlers can access all this info if needed.
2098 # The source corresponding to this can be obtained from the
2098 # The source corresponding to this can be obtained from the
2099 # buffer attribute as '\n'.join(self.buffer).
2099 # buffer attribute as '\n'.join(self.buffer).
2100 self.code_to_run = code
2100 self.code_to_run = code
2101 # now actually execute the code object
2101 # now actually execute the code object
2102 if self.runcode(code) == 0:
2102 if self.runcode(code) == 0:
2103 return False
2103 return False
2104 else:
2104 else:
2105 return None
2105 return None
2106
2106
2107 def runcode(self,code_obj):
2107 def runcode(self,code_obj):
2108 """Execute a code object.
2108 """Execute a code object.
2109
2109
2110 When an exception occurs, self.showtraceback() is called to display a
2110 When an exception occurs, self.showtraceback() is called to display a
2111 traceback.
2111 traceback.
2112
2112
2113 Return value: a flag indicating whether the code to be run completed
2113 Return value: a flag indicating whether the code to be run completed
2114 successfully:
2114 successfully:
2115
2115
2116 - 0: successful execution.
2116 - 0: successful execution.
2117 - 1: an error occurred.
2117 - 1: an error occurred.
2118 """
2118 """
2119
2119
2120 # Set our own excepthook in case the user code tries to call it
2120 # Set our own excepthook in case the user code tries to call it
2121 # directly, so that the IPython crash handler doesn't get triggered
2121 # directly, so that the IPython crash handler doesn't get triggered
2122 old_excepthook,sys.excepthook = sys.excepthook, self.excepthook
2122 old_excepthook,sys.excepthook = sys.excepthook, self.excepthook
2123
2123
2124 # we save the original sys.excepthook in the instance, in case config
2124 # we save the original sys.excepthook in the instance, in case config
2125 # code (such as magics) needs access to it.
2125 # code (such as magics) needs access to it.
2126 self.sys_excepthook = old_excepthook
2126 self.sys_excepthook = old_excepthook
2127 outflag = 1 # happens in more places, so it's easier as default
2127 outflag = 1 # happens in more places, so it's easier as default
2128 try:
2128 try:
2129 try:
2129 try:
2130 self.hooks.pre_runcode_hook()
2130 self.hooks.pre_runcode_hook()
2131 exec code_obj in self.user_global_ns, self.user_ns
2131 exec code_obj in self.user_global_ns, self.user_ns
2132 finally:
2132 finally:
2133 # Reset our crash handler in place
2133 # Reset our crash handler in place
2134 sys.excepthook = old_excepthook
2134 sys.excepthook = old_excepthook
2135 except SystemExit:
2135 except SystemExit:
2136 self.resetbuffer()
2136 self.resetbuffer()
2137 self.showtraceback()
2137 self.showtraceback()
2138 warn("Type %exit or %quit to exit IPython "
2138 warn("Type %exit or %quit to exit IPython "
2139 "(%Exit or %Quit do so unconditionally).",level=1)
2139 "(%Exit or %Quit do so unconditionally).",level=1)
2140 except self.custom_exceptions:
2140 except self.custom_exceptions:
2141 etype,value,tb = sys.exc_info()
2141 etype,value,tb = sys.exc_info()
2142 self.CustomTB(etype,value,tb)
2142 self.CustomTB(etype,value,tb)
2143 except:
2143 except:
2144 self.showtraceback()
2144 self.showtraceback()
2145 else:
2145 else:
2146 outflag = 0
2146 outflag = 0
2147 if softspace(sys.stdout, 0):
2147 if softspace(sys.stdout, 0):
2148 print
2148 print
2149 # Flush out code object which has been run (and source)
2149 # Flush out code object which has been run (and source)
2150 self.code_to_run = None
2150 self.code_to_run = None
2151 return outflag
2151 return outflag
2152
2152
2153 def push_line(self, line):
2153 def push_line(self, line):
2154 """Push a line to the interpreter.
2154 """Push a line to the interpreter.
2155
2155
2156 The line should not have a trailing newline; it may have
2156 The line should not have a trailing newline; it may have
2157 internal newlines. The line is appended to a buffer and the
2157 internal newlines. The line is appended to a buffer and the
2158 interpreter's runsource() method is called with the
2158 interpreter's runsource() method is called with the
2159 concatenated contents of the buffer as source. If this
2159 concatenated contents of the buffer as source. If this
2160 indicates that the command was executed or invalid, the buffer
2160 indicates that the command was executed or invalid, the buffer
2161 is reset; otherwise, the command is incomplete, and the buffer
2161 is reset; otherwise, the command is incomplete, and the buffer
2162 is left as it was after the line was appended. The return
2162 is left as it was after the line was appended. The return
2163 value is 1 if more input is required, 0 if the line was dealt
2163 value is 1 if more input is required, 0 if the line was dealt
2164 with in some way (this is the same as runsource()).
2164 with in some way (this is the same as runsource()).
2165 """
2165 """
2166
2166
2167 # autoindent management should be done here, and not in the
2167 # autoindent management should be done here, and not in the
2168 # interactive loop, since that one is only seen by keyboard input. We
2168 # interactive loop, since that one is only seen by keyboard input. We
2169 # need this done correctly even for code run via runlines (which uses
2169 # need this done correctly even for code run via runlines (which uses
2170 # push).
2170 # push).
2171
2171
2172 #print 'push line: <%s>' % line # dbg
2172 #print 'push line: <%s>' % line # dbg
2173 for subline in line.splitlines():
2173 for subline in line.splitlines():
2174 self._autoindent_update(subline)
2174 self._autoindent_update(subline)
2175 self.buffer.append(line)
2175 self.buffer.append(line)
2176 more = self.runsource('\n'.join(self.buffer), self.filename)
2176 more = self.runsource('\n'.join(self.buffer), self.filename)
2177 if not more:
2177 if not more:
2178 self.resetbuffer()
2178 self.resetbuffer()
2179 return more
2179 return more
2180
2180
2181 def _autoindent_update(self,line):
2181 def _autoindent_update(self,line):
2182 """Keep track of the indent level."""
2182 """Keep track of the indent level."""
2183
2183
2184 #debugx('line')
2184 #debugx('line')
2185 #debugx('self.indent_current_nsp')
2185 #debugx('self.indent_current_nsp')
2186 if self.autoindent:
2186 if self.autoindent:
2187 if line:
2187 if line:
2188 inisp = num_ini_spaces(line)
2188 inisp = num_ini_spaces(line)
2189 if inisp < self.indent_current_nsp:
2189 if inisp < self.indent_current_nsp:
2190 self.indent_current_nsp = inisp
2190 self.indent_current_nsp = inisp
2191
2191
2192 if line[-1] == ':':
2192 if line[-1] == ':':
2193 self.indent_current_nsp += 4
2193 self.indent_current_nsp += 4
2194 elif dedent_re.match(line):
2194 elif dedent_re.match(line):
2195 self.indent_current_nsp -= 4
2195 self.indent_current_nsp -= 4
2196 else:
2196 else:
2197 self.indent_current_nsp = 0
2197 self.indent_current_nsp = 0
2198
2198
2199 def resetbuffer(self):
2199 def resetbuffer(self):
2200 """Reset the input buffer."""
2200 """Reset the input buffer."""
2201 self.buffer[:] = []
2201 self.buffer[:] = []
2202
2202
2203 def raw_input(self,prompt='',continue_prompt=False):
2203 def raw_input(self,prompt='',continue_prompt=False):
2204 """Write a prompt and read a line.
2204 """Write a prompt and read a line.
2205
2205
2206 The returned line does not include the trailing newline.
2206 The returned line does not include the trailing newline.
2207 When the user enters the EOF key sequence, EOFError is raised.
2207 When the user enters the EOF key sequence, EOFError is raised.
2208
2208
2209 Optional inputs:
2209 Optional inputs:
2210
2210
2211 - prompt(''): a string to be printed to prompt the user.
2211 - prompt(''): a string to be printed to prompt the user.
2212
2212
2213 - continue_prompt(False): whether this line is the first one or a
2213 - continue_prompt(False): whether this line is the first one or a
2214 continuation in a sequence of inputs.
2214 continuation in a sequence of inputs.
2215 """
2215 """
2216 # growl.notify("raw_input: ", "prompt = %r\ncontinue_prompt = %s" % (prompt, continue_prompt))
2216 # growl.notify("raw_input: ", "prompt = %r\ncontinue_prompt = %s" % (prompt, continue_prompt))
2217
2217
2218 # Code run by the user may have modified the readline completer state.
2218 # Code run by the user may have modified the readline completer state.
2219 # We must ensure that our completer is back in place.
2219 # We must ensure that our completer is back in place.
2220
2220
2221 if self.has_readline:
2221 if self.has_readline:
2222 self.set_completer()
2222 self.set_completer()
2223
2223
2224 try:
2224 try:
2225 line = raw_input_original(prompt).decode(self.stdin_encoding)
2225 line = raw_input_original(prompt).decode(self.stdin_encoding)
2226 except ValueError:
2226 except ValueError:
2227 warn("\n********\nYou or a %run:ed script called sys.stdin.close()"
2227 warn("\n********\nYou or a %run:ed script called sys.stdin.close()"
2228 " or sys.stdout.close()!\nExiting IPython!")
2228 " or sys.stdout.close()!\nExiting IPython!")
2229 self.ask_exit()
2229 self.ask_exit()
2230 return ""
2230 return ""
2231
2231
2232 # Try to be reasonably smart about not re-indenting pasted input more
2232 # Try to be reasonably smart about not re-indenting pasted input more
2233 # than necessary. We do this by trimming out the auto-indent initial
2233 # than necessary. We do this by trimming out the auto-indent initial
2234 # spaces, if the user's actual input started itself with whitespace.
2234 # spaces, if the user's actual input started itself with whitespace.
2235 #debugx('self.buffer[-1]')
2235 #debugx('self.buffer[-1]')
2236
2236
2237 if self.autoindent:
2237 if self.autoindent:
2238 if num_ini_spaces(line) > self.indent_current_nsp:
2238 if num_ini_spaces(line) > self.indent_current_nsp:
2239 line = line[self.indent_current_nsp:]
2239 line = line[self.indent_current_nsp:]
2240 self.indent_current_nsp = 0
2240 self.indent_current_nsp = 0
2241
2241
2242 # store the unfiltered input before the user has any chance to modify
2242 # store the unfiltered input before the user has any chance to modify
2243 # it.
2243 # it.
2244 if line.strip():
2244 if line.strip():
2245 if continue_prompt:
2245 if continue_prompt:
2246 self.input_hist_raw[-1] += '%s\n' % line
2246 self.input_hist_raw[-1] += '%s\n' % line
2247 if self.has_readline and self.readline_use:
2247 if self.has_readline and self.readline_use:
2248 try:
2248 try:
2249 histlen = self.readline.get_current_history_length()
2249 histlen = self.readline.get_current_history_length()
2250 if histlen > 1:
2250 if histlen > 1:
2251 newhist = self.input_hist_raw[-1].rstrip()
2251 newhist = self.input_hist_raw[-1].rstrip()
2252 self.readline.remove_history_item(histlen-1)
2252 self.readline.remove_history_item(histlen-1)
2253 self.readline.replace_history_item(histlen-2,
2253 self.readline.replace_history_item(histlen-2,
2254 newhist.encode(self.stdin_encoding))
2254 newhist.encode(self.stdin_encoding))
2255 except AttributeError:
2255 except AttributeError:
2256 pass # re{move,place}_history_item are new in 2.4.
2256 pass # re{move,place}_history_item are new in 2.4.
2257 else:
2257 else:
2258 self.input_hist_raw.append('%s\n' % line)
2258 self.input_hist_raw.append('%s\n' % line)
2259 # only entries starting at first column go to shadow history
2259 # only entries starting at first column go to shadow history
2260 if line.lstrip() == line:
2260 if line.lstrip() == line:
2261 self.shadowhist.add(line.strip())
2261 self.shadowhist.add(line.strip())
2262 elif not continue_prompt:
2262 elif not continue_prompt:
2263 self.input_hist_raw.append('\n')
2263 self.input_hist_raw.append('\n')
2264 try:
2264 try:
2265 lineout = self.prefilter_manager.prefilter_lines(line,continue_prompt)
2265 lineout = self.prefilter_manager.prefilter_lines(line,continue_prompt)
2266 except:
2266 except:
2267 # blanket except, in case a user-defined prefilter crashes, so it
2267 # blanket except, in case a user-defined prefilter crashes, so it
2268 # can't take all of ipython with it.
2268 # can't take all of ipython with it.
2269 self.showtraceback()
2269 self.showtraceback()
2270 return ''
2270 return ''
2271 else:
2271 else:
2272 return lineout
2272 return lineout
2273
2273
2274 #-------------------------------------------------------------------------
2274 #-------------------------------------------------------------------------
2275 # Working with components
2275 # Working with components
2276 #-------------------------------------------------------------------------
2276 #-------------------------------------------------------------------------
2277
2277
2278 def get_component(self, name=None, klass=None):
2278 def get_component(self, name=None, klass=None):
2279 """Fetch a component by name and klass in my tree."""
2279 """Fetch a component by name and klass in my tree."""
2280 c = Component.get_instances(root=self, name=name, klass=klass)
2280 c = Component.get_instances(root=self, name=name, klass=klass)
2281 if len(c) == 1:
2281 if len(c) == 1:
2282 return c[0]
2282 return c[0]
2283 else:
2283 else:
2284 return c
2284 return c
2285
2285
2286 #-------------------------------------------------------------------------
2286 #-------------------------------------------------------------------------
2287 # IPython extensions
2287 # IPython extensions
2288 #-------------------------------------------------------------------------
2288 #-------------------------------------------------------------------------
2289
2289
2290 def load_extension(self, module_str):
2290 def load_extension(self, module_str):
2291 """Load an IPython extension by its module name.
2291 """Load an IPython extension by its module name.
2292
2292
2293 An IPython extension is an importable Python module that has
2293 An IPython extension is an importable Python module that has
2294 a function with the signature::
2294 a function with the signature::
2295
2295
2296 def load_ipython_extension(ipython):
2296 def load_ipython_extension(ipython):
2297 # Do things with ipython
2297 # Do things with ipython
2298
2298
2299 This function is called after your extension is imported and the
2299 This function is called after your extension is imported and the
2300 currently active :class:`InteractiveShell` instance is passed as
2300 currently active :class:`InteractiveShell` instance is passed as
2301 the only argument. You can do anything you want with IPython at
2301 the only argument. You can do anything you want with IPython at
2302 that point, including defining new magic and aliases, adding new
2302 that point, including defining new magic and aliases, adding new
2303 components, etc.
2303 components, etc.
2304
2304
2305 The :func:`load_ipython_extension` will be called again is you
2305 The :func:`load_ipython_extension` will be called again is you
2306 load or reload the extension again. It is up to the extension
2306 load or reload the extension again. It is up to the extension
2307 author to add code to manage that.
2307 author to add code to manage that.
2308
2308
2309 You can put your extension modules anywhere you want, as long as
2309 You can put your extension modules anywhere you want, as long as
2310 they can be imported by Python's standard import mechanism. However,
2310 they can be imported by Python's standard import mechanism. However,
2311 to make it easy to write extensions, you can also put your extensions
2311 to make it easy to write extensions, you can also put your extensions
2312 in ``os.path.join(self.ipythondir, 'extensions')``. This directory
2312 in ``os.path.join(self.ipythondir, 'extensions')``. This directory
2313 is added to ``sys.path`` automatically.
2313 is added to ``sys.path`` automatically.
2314 """
2314 """
2315 from IPython.utils.syspathcontext import prepended_to_syspath
2315 from IPython.utils.syspathcontext import prepended_to_syspath
2316
2316
2317 if module_str not in sys.modules:
2317 if module_str not in sys.modules:
2318 with prepended_to_syspath(self.ipython_extension_dir):
2318 with prepended_to_syspath(self.ipython_extension_dir):
2319 __import__(module_str)
2319 __import__(module_str)
2320 mod = sys.modules[module_str]
2320 mod = sys.modules[module_str]
2321 self._call_load_ipython_extension(mod)
2321 self._call_load_ipython_extension(mod)
2322
2322
2323 def unload_extension(self, module_str):
2323 def unload_extension(self, module_str):
2324 """Unload an IPython extension by its module name.
2324 """Unload an IPython extension by its module name.
2325
2325
2326 This function looks up the extension's name in ``sys.modules`` and
2326 This function looks up the extension's name in ``sys.modules`` and
2327 simply calls ``mod.unload_ipython_extension(self)``.
2327 simply calls ``mod.unload_ipython_extension(self)``.
2328 """
2328 """
2329 if module_str in sys.modules:
2329 if module_str in sys.modules:
2330 mod = sys.modules[module_str]
2330 mod = sys.modules[module_str]
2331 self._call_unload_ipython_extension(mod)
2331 self._call_unload_ipython_extension(mod)
2332
2332
2333 def reload_extension(self, module_str):
2333 def reload_extension(self, module_str):
2334 """Reload an IPython extension by calling reload.
2334 """Reload an IPython extension by calling reload.
2335
2335
2336 If the module has not been loaded before,
2336 If the module has not been loaded before,
2337 :meth:`InteractiveShell.load_extension` is called. Otherwise
2337 :meth:`InteractiveShell.load_extension` is called. Otherwise
2338 :func:`reload` is called and then the :func:`load_ipython_extension`
2338 :func:`reload` is called and then the :func:`load_ipython_extension`
2339 function of the module, if it exists is called.
2339 function of the module, if it exists is called.
2340 """
2340 """
2341 from IPython.utils.syspathcontext import prepended_to_syspath
2341 from IPython.utils.syspathcontext import prepended_to_syspath
2342
2342
2343 with prepended_to_syspath(self.ipython_extension_dir):
2343 with prepended_to_syspath(self.ipython_extension_dir):
2344 if module_str in sys.modules:
2344 if module_str in sys.modules:
2345 mod = sys.modules[module_str]
2345 mod = sys.modules[module_str]
2346 reload(mod)
2346 reload(mod)
2347 self._call_load_ipython_extension(mod)
2347 self._call_load_ipython_extension(mod)
2348 else:
2348 else:
2349 self.load_extension(module_str)
2349 self.load_extension(module_str)
2350
2350
2351 def _call_load_ipython_extension(self, mod):
2351 def _call_load_ipython_extension(self, mod):
2352 if hasattr(mod, 'load_ipython_extension'):
2352 if hasattr(mod, 'load_ipython_extension'):
2353 mod.load_ipython_extension(self)
2353 mod.load_ipython_extension(self)
2354
2354
2355 def _call_unload_ipython_extension(self, mod):
2355 def _call_unload_ipython_extension(self, mod):
2356 if hasattr(mod, 'unload_ipython_extension'):
2356 if hasattr(mod, 'unload_ipython_extension'):
2357 mod.unload_ipython_extension(self)
2357 mod.unload_ipython_extension(self)
2358
2358
2359 #-------------------------------------------------------------------------
2359 #-------------------------------------------------------------------------
2360 # Things related to the prefilter
2360 # Things related to the prefilter
2361 #-------------------------------------------------------------------------
2361 #-------------------------------------------------------------------------
2362
2362
2363 def init_prefilter(self):
2363 def init_prefilter(self):
2364 self.prefilter_manager = PrefilterManager(self, config=self.config)
2364 self.prefilter_manager = PrefilterManager(self, config=self.config)
2365
2365
2366 #-------------------------------------------------------------------------
2366 #-------------------------------------------------------------------------
2367 # Utilities
2367 # Utilities
2368 #-------------------------------------------------------------------------
2368 #-------------------------------------------------------------------------
2369
2369
2370 def getoutput(self, cmd):
2370 def getoutput(self, cmd):
2371 return getoutput(self.var_expand(cmd,depth=2),
2371 return getoutput(self.var_expand(cmd,depth=2),
2372 header=self.system_header,
2372 header=self.system_header,
2373 verbose=self.system_verbose)
2373 verbose=self.system_verbose)
2374
2374
2375 def getoutputerror(self, cmd):
2375 def getoutputerror(self, cmd):
2376 return getoutputerror(self.var_expand(cmd,depth=2),
2376 return getoutputerror(self.var_expand(cmd,depth=2),
2377 header=self.system_header,
2377 header=self.system_header,
2378 verbose=self.system_verbose)
2378 verbose=self.system_verbose)
2379
2379
2380 def var_expand(self,cmd,depth=0):
2380 def var_expand(self,cmd,depth=0):
2381 """Expand python variables in a string.
2381 """Expand python variables in a string.
2382
2382
2383 The depth argument indicates how many frames above the caller should
2383 The depth argument indicates how many frames above the caller should
2384 be walked to look for the local namespace where to expand variables.
2384 be walked to look for the local namespace where to expand variables.
2385
2385
2386 The global namespace for expansion is always the user's interactive
2386 The global namespace for expansion is always the user's interactive
2387 namespace.
2387 namespace.
2388 """
2388 """
2389
2389
2390 return str(ItplNS(cmd,
2390 return str(ItplNS(cmd,
2391 self.user_ns, # globals
2391 self.user_ns, # globals
2392 # Skip our own frame in searching for locals:
2392 # Skip our own frame in searching for locals:
2393 sys._getframe(depth+1).f_locals # locals
2393 sys._getframe(depth+1).f_locals # locals
2394 ))
2394 ))
2395
2395
2396 def mktempfile(self,data=None):
2396 def mktempfile(self,data=None):
2397 """Make a new tempfile and return its filename.
2397 """Make a new tempfile and return its filename.
2398
2398
2399 This makes a call to tempfile.mktemp, but it registers the created
2399 This makes a call to tempfile.mktemp, but it registers the created
2400 filename internally so ipython cleans it up at exit time.
2400 filename internally so ipython cleans it up at exit time.
2401
2401
2402 Optional inputs:
2402 Optional inputs:
2403
2403
2404 - data(None): if data is given, it gets written out to the temp file
2404 - data(None): if data is given, it gets written out to the temp file
2405 immediately, and the file is closed again."""
2405 immediately, and the file is closed again."""
2406
2406
2407 filename = tempfile.mktemp('.py','ipython_edit_')
2407 filename = tempfile.mktemp('.py','ipython_edit_')
2408 self.tempfiles.append(filename)
2408 self.tempfiles.append(filename)
2409
2409
2410 if data:
2410 if data:
2411 tmp_file = open(filename,'w')
2411 tmp_file = open(filename,'w')
2412 tmp_file.write(data)
2412 tmp_file.write(data)
2413 tmp_file.close()
2413 tmp_file.close()
2414 return filename
2414 return filename
2415
2415
2416 def write(self,data):
2416 def write(self,data):
2417 """Write a string to the default output"""
2417 """Write a string to the default output"""
2418 Term.cout.write(data)
2418 Term.cout.write(data)
2419
2419
2420 def write_err(self,data):
2420 def write_err(self,data):
2421 """Write a string to the default error output"""
2421 """Write a string to the default error output"""
2422 Term.cerr.write(data)
2422 Term.cerr.write(data)
2423
2423
2424 def ask_yes_no(self,prompt,default=True):
2424 def ask_yes_no(self,prompt,default=True):
2425 if self.quiet:
2425 if self.quiet:
2426 return True
2426 return True
2427 return ask_yes_no(prompt,default)
2427 return ask_yes_no(prompt,default)
2428
2428
2429 #-------------------------------------------------------------------------
2429 #-------------------------------------------------------------------------
2430 # Things related to IPython exiting
2430 # Things related to IPython exiting
2431 #-------------------------------------------------------------------------
2431 #-------------------------------------------------------------------------
2432
2432
2433 def ask_exit(self):
2433 def ask_exit(self):
2434 """ Call for exiting. Can be overiden and used as a callback. """
2434 """ Call for exiting. Can be overiden and used as a callback. """
2435 self.exit_now = True
2435 self.exit_now = True
2436
2436
2437 def exit(self):
2437 def exit(self):
2438 """Handle interactive exit.
2438 """Handle interactive exit.
2439
2439
2440 This method calls the ask_exit callback."""
2440 This method calls the ask_exit callback."""
2441 if self.confirm_exit:
2441 if self.confirm_exit:
2442 if self.ask_yes_no('Do you really want to exit ([y]/n)?','y'):
2442 if self.ask_yes_no('Do you really want to exit ([y]/n)?','y'):
2443 self.ask_exit()
2443 self.ask_exit()
2444 else:
2444 else:
2445 self.ask_exit()
2445 self.ask_exit()
2446
2446
2447 def atexit_operations(self):
2447 def atexit_operations(self):
2448 """This will be executed at the time of exit.
2448 """This will be executed at the time of exit.
2449
2449
2450 Saving of persistent data should be performed here.
2450 Saving of persistent data should be performed here.
2451 """
2451 """
2452 self.savehist()
2452 self.savehist()
2453
2453
2454 # Cleanup all tempfiles left around
2454 # Cleanup all tempfiles left around
2455 for tfile in self.tempfiles:
2455 for tfile in self.tempfiles:
2456 try:
2456 try:
2457 os.unlink(tfile)
2457 os.unlink(tfile)
2458 except OSError:
2458 except OSError:
2459 pass
2459 pass
2460
2460
2461 # Clear all user namespaces to release all references cleanly.
2461 # Clear all user namespaces to release all references cleanly.
2462 self.reset()
2462 self.reset()
2463
2463
2464 # Run user hooks
2464 # Run user hooks
2465 self.hooks.shutdown_hook()
2465 self.hooks.shutdown_hook()
2466
2466
2467 def cleanup(self):
2467 def cleanup(self):
2468 self.restore_sys_module_state()
2468 self.restore_sys_module_state()
2469
2469
2470
2470
@@ -1,214 +1,214 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # encoding: utf-8
2 # encoding: utf-8
3 """
3 """
4 Tests for IPython.core.component
4 Tests for IPython.core.component
5
5
6 Authors:
6 Authors:
7
7
8 * Brian Granger
8 * Brian Granger
9 * Fernando Perez (design help)
9 * Fernando Perez (design help)
10 """
10 """
11
11
12 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
13 # Copyright (C) 2008-2009 The IPython Development Team
13 # Copyright (C) 2008-2009 The IPython Development Team
14 #
14 #
15 # Distributed under the terms of the BSD License. The full license is in
15 # Distributed under the terms of the BSD License. The full license is in
16 # the file COPYING, distributed as part of this software.
16 # the file COPYING, distributed as part of this software.
17 #-----------------------------------------------------------------------------
17 #-----------------------------------------------------------------------------
18
18
19 #-----------------------------------------------------------------------------
19 #-----------------------------------------------------------------------------
20 # Imports
20 # Imports
21 #-----------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
22
22
23 from unittest import TestCase
23 from unittest import TestCase
24
24
25 from IPython.core.component import Component, ComponentError
25 from IPython.core.component import Component, ComponentError
26 from IPython.utils.traitlets import (
26 from IPython.utils.traitlets import (
27 TraitletError, Int, Float, Str
27 TraitError, Int, Float, Str
28 )
28 )
29 from IPython.config.loader import Config
29 from IPython.config.loader import Config
30
30
31
31
32 #-----------------------------------------------------------------------------
32 #-----------------------------------------------------------------------------
33 # Test cases
33 # Test cases
34 #-----------------------------------------------------------------------------
34 #-----------------------------------------------------------------------------
35
35
36
36
37 class TestComponentMeta(TestCase):
37 class TestComponentMeta(TestCase):
38
38
39 def test_get_instances(self):
39 def test_get_instances(self):
40 class BaseComponent(Component):
40 class BaseComponent(Component):
41 pass
41 pass
42 c1 = BaseComponent(None)
42 c1 = BaseComponent(None)
43 c2 = BaseComponent(c1)
43 c2 = BaseComponent(c1)
44 self.assertEquals(BaseComponent.get_instances(),[c1,c2])
44 self.assertEquals(BaseComponent.get_instances(),[c1,c2])
45
45
46 def test_get_instances_subclass(self):
46 def test_get_instances_subclass(self):
47 class MyComponent(Component):
47 class MyComponent(Component):
48 pass
48 pass
49 class MyOtherComponent(MyComponent):
49 class MyOtherComponent(MyComponent):
50 pass
50 pass
51 c1 = MyComponent(None)
51 c1 = MyComponent(None)
52 c2 = MyOtherComponent(c1)
52 c2 = MyOtherComponent(c1)
53 c3 = MyOtherComponent(c2)
53 c3 = MyOtherComponent(c2)
54 self.assertEquals(MyComponent.get_instances(), [c1, c2, c3])
54 self.assertEquals(MyComponent.get_instances(), [c1, c2, c3])
55 self.assertEquals(MyOtherComponent.get_instances(), [c2, c3])
55 self.assertEquals(MyOtherComponent.get_instances(), [c2, c3])
56
56
57 def test_get_instances_root(self):
57 def test_get_instances_root(self):
58 class MyComponent(Component):
58 class MyComponent(Component):
59 pass
59 pass
60 class MyOtherComponent(MyComponent):
60 class MyOtherComponent(MyComponent):
61 pass
61 pass
62 c1 = MyComponent(None)
62 c1 = MyComponent(None)
63 c2 = MyOtherComponent(c1)
63 c2 = MyOtherComponent(c1)
64 c3 = MyOtherComponent(c2)
64 c3 = MyOtherComponent(c2)
65 c4 = MyComponent(None)
65 c4 = MyComponent(None)
66 c5 = MyComponent(c4)
66 c5 = MyComponent(c4)
67 self.assertEquals(MyComponent.get_instances(root=c1), [c1, c2, c3])
67 self.assertEquals(MyComponent.get_instances(root=c1), [c1, c2, c3])
68 self.assertEquals(MyComponent.get_instances(root=c4), [c4, c5])
68 self.assertEquals(MyComponent.get_instances(root=c4), [c4, c5])
69
69
70
70
71 class TestComponent(TestCase):
71 class TestComponent(TestCase):
72
72
73 def test_parent_child(self):
73 def test_parent_child(self):
74 c1 = Component(None)
74 c1 = Component(None)
75 c2 = Component(c1)
75 c2 = Component(c1)
76 c3 = Component(c1)
76 c3 = Component(c1)
77 c4 = Component(c3)
77 c4 = Component(c3)
78 self.assertEquals(c1.parent, None)
78 self.assertEquals(c1.parent, None)
79 self.assertEquals(c2.parent, c1)
79 self.assertEquals(c2.parent, c1)
80 self.assertEquals(c3.parent, c1)
80 self.assertEquals(c3.parent, c1)
81 self.assertEquals(c4.parent, c3)
81 self.assertEquals(c4.parent, c3)
82 self.assertEquals(c1.children, [c2, c3])
82 self.assertEquals(c1.children, [c2, c3])
83 self.assertEquals(c2.children, [])
83 self.assertEquals(c2.children, [])
84 self.assertEquals(c3.children, [c4])
84 self.assertEquals(c3.children, [c4])
85 self.assertEquals(c4.children, [])
85 self.assertEquals(c4.children, [])
86
86
87 def test_root(self):
87 def test_root(self):
88 c1 = Component(None)
88 c1 = Component(None)
89 c2 = Component(c1)
89 c2 = Component(c1)
90 c3 = Component(c1)
90 c3 = Component(c1)
91 c4 = Component(c3)
91 c4 = Component(c3)
92 self.assertEquals(c1.root, c1.root)
92 self.assertEquals(c1.root, c1.root)
93 self.assertEquals(c2.root, c1)
93 self.assertEquals(c2.root, c1)
94 self.assertEquals(c3.root, c1)
94 self.assertEquals(c3.root, c1)
95 self.assertEquals(c4.root, c1)
95 self.assertEquals(c4.root, c1)
96
96
97 def test_change_parent(self):
97 def test_change_parent(self):
98 c1 = Component(None)
98 c1 = Component(None)
99 c2 = Component(None)
99 c2 = Component(None)
100 c3 = Component(c1)
100 c3 = Component(c1)
101 self.assertEquals(c3.root, c1)
101 self.assertEquals(c3.root, c1)
102 self.assertEquals(c3.parent, c1)
102 self.assertEquals(c3.parent, c1)
103 self.assertEquals(c1.children,[c3])
103 self.assertEquals(c1.children,[c3])
104 c3.parent = c2
104 c3.parent = c2
105 self.assertEquals(c3.root, c2)
105 self.assertEquals(c3.root, c2)
106 self.assertEquals(c3.parent, c2)
106 self.assertEquals(c3.parent, c2)
107 self.assertEquals(c2.children,[c3])
107 self.assertEquals(c2.children,[c3])
108 self.assertEquals(c1.children,[])
108 self.assertEquals(c1.children,[])
109
109
110 def test_subclass_parent(self):
110 def test_subclass_parent(self):
111 c1 = Component(None)
111 c1 = Component(None)
112 self.assertRaises(TraitletError, setattr, c1, 'parent', 10)
112 self.assertRaises(TraitError, setattr, c1, 'parent', 10)
113
113
114 class MyComponent(Component):
114 class MyComponent(Component):
115 pass
115 pass
116 c1 = Component(None)
116 c1 = Component(None)
117 c2 = MyComponent(c1)
117 c2 = MyComponent(c1)
118 self.assertEquals(MyComponent.parent.this_class, Component)
118 self.assertEquals(MyComponent.parent.this_class, Component)
119 self.assertEquals(c2.parent, c1)
119 self.assertEquals(c2.parent, c1)
120
120
121 def test_bad_root(self):
121 def test_bad_root(self):
122 c1 = Component(None)
122 c1 = Component(None)
123 c2 = Component(None)
123 c2 = Component(None)
124 c3 = Component(None)
124 c3 = Component(None)
125 self.assertRaises(ComponentError, setattr, c1, 'root', c2)
125 self.assertRaises(ComponentError, setattr, c1, 'root', c2)
126 c1.parent = c2
126 c1.parent = c2
127 self.assertEquals(c1.root, c2)
127 self.assertEquals(c1.root, c2)
128 self.assertRaises(ComponentError, setattr, c1, 'root', c3)
128 self.assertRaises(ComponentError, setattr, c1, 'root', c3)
129
129
130
130
131 class TestComponentConfig(TestCase):
131 class TestComponentConfig(TestCase):
132
132
133 def test_default(self):
133 def test_default(self):
134 c1 = Component(None)
134 c1 = Component(None)
135 c2 = Component(c1)
135 c2 = Component(c1)
136 c3 = Component(c2)
136 c3 = Component(c2)
137 self.assertEquals(c1.config, c2.config)
137 self.assertEquals(c1.config, c2.config)
138 self.assertEquals(c2.config, c3.config)
138 self.assertEquals(c2.config, c3.config)
139
139
140 def test_custom(self):
140 def test_custom(self):
141 config = Config()
141 config = Config()
142 config.foo = 'foo'
142 config.foo = 'foo'
143 config.bar = 'bar'
143 config.bar = 'bar'
144 c1 = Component(None, config=config)
144 c1 = Component(None, config=config)
145 c2 = Component(c1)
145 c2 = Component(c1)
146 c3 = Component(c2)
146 c3 = Component(c2)
147 self.assertEquals(c1.config, config)
147 self.assertEquals(c1.config, config)
148 self.assertEquals(c2.config, config)
148 self.assertEquals(c2.config, config)
149 self.assertEquals(c3.config, config)
149 self.assertEquals(c3.config, config)
150 # Test that copies are not made
150 # Test that copies are not made
151 self.assert_(c1.config is config)
151 self.assert_(c1.config is config)
152 self.assert_(c2.config is config)
152 self.assert_(c2.config is config)
153 self.assert_(c3.config is config)
153 self.assert_(c3.config is config)
154 self.assert_(c1.config is c2.config)
154 self.assert_(c1.config is c2.config)
155 self.assert_(c2.config is c3.config)
155 self.assert_(c2.config is c3.config)
156
156
157 def test_inheritance(self):
157 def test_inheritance(self):
158 class MyComponent(Component):
158 class MyComponent(Component):
159 a = Int(1, config=True)
159 a = Int(1, config=True)
160 b = Float(1.0, config=True)
160 b = Float(1.0, config=True)
161 c = Str('no config')
161 c = Str('no config')
162 config = Config()
162 config = Config()
163 config.MyComponent.a = 2
163 config.MyComponent.a = 2
164 config.MyComponent.b = 2.0
164 config.MyComponent.b = 2.0
165 c1 = MyComponent(None, config=config)
165 c1 = MyComponent(None, config=config)
166 c2 = MyComponent(c1)
166 c2 = MyComponent(c1)
167 self.assertEquals(c1.a, config.MyComponent.a)
167 self.assertEquals(c1.a, config.MyComponent.a)
168 self.assertEquals(c1.b, config.MyComponent.b)
168 self.assertEquals(c1.b, config.MyComponent.b)
169 self.assertEquals(c2.a, config.MyComponent.a)
169 self.assertEquals(c2.a, config.MyComponent.a)
170 self.assertEquals(c2.b, config.MyComponent.b)
170 self.assertEquals(c2.b, config.MyComponent.b)
171 c4 = MyComponent(c2, config=Config())
171 c4 = MyComponent(c2, config=Config())
172 self.assertEquals(c4.a, 1)
172 self.assertEquals(c4.a, 1)
173 self.assertEquals(c4.b, 1.0)
173 self.assertEquals(c4.b, 1.0)
174
174
175 def test_parent(self):
175 def test_parent(self):
176 class Foo(Component):
176 class Foo(Component):
177 a = Int(0, config=True)
177 a = Int(0, config=True)
178 b = Str('nope', config=True)
178 b = Str('nope', config=True)
179 class Bar(Foo):
179 class Bar(Foo):
180 b = Str('gotit', config=False)
180 b = Str('gotit', config=False)
181 c = Float(config=True)
181 c = Float(config=True)
182 config = Config()
182 config = Config()
183 config.Foo.a = 10
183 config.Foo.a = 10
184 config.Foo.b = "wow"
184 config.Foo.b = "wow"
185 config.Bar.b = 'later'
185 config.Bar.b = 'later'
186 config.Bar.c = 100.0
186 config.Bar.c = 100.0
187 f = Foo(None, config=config)
187 f = Foo(None, config=config)
188 b = Bar(f)
188 b = Bar(f)
189 self.assertEquals(f.a, 10)
189 self.assertEquals(f.a, 10)
190 self.assertEquals(f.b, 'wow')
190 self.assertEquals(f.b, 'wow')
191 self.assertEquals(b.b, 'gotit')
191 self.assertEquals(b.b, 'gotit')
192 self.assertEquals(b.c, 100.0)
192 self.assertEquals(b.c, 100.0)
193
193
194
194
195 class TestComponentName(TestCase):
195 class TestComponentName(TestCase):
196
196
197 def test_default(self):
197 def test_default(self):
198 class MyComponent(Component):
198 class MyComponent(Component):
199 pass
199 pass
200 c1 = Component(None)
200 c1 = Component(None)
201 c2 = MyComponent(None)
201 c2 = MyComponent(None)
202 c3 = Component(c2)
202 c3 = Component(c2)
203 self.assertNotEquals(c1.name, c2.name)
203 self.assertNotEquals(c1.name, c2.name)
204 self.assertNotEquals(c1.name, c3.name)
204 self.assertNotEquals(c1.name, c3.name)
205
205
206 def test_manual(self):
206 def test_manual(self):
207 class MyComponent(Component):
207 class MyComponent(Component):
208 pass
208 pass
209 c1 = Component(None, name='foo')
209 c1 = Component(None, name='foo')
210 c2 = MyComponent(None, name='bar')
210 c2 = MyComponent(None, name='bar')
211 c3 = Component(c2, name='bah')
211 c3 = Component(c2, name='bah')
212 self.assertEquals(c1.name, 'foo')
212 self.assertEquals(c1.name, 'foo')
213 self.assertEquals(c2.name, 'bar')
213 self.assertEquals(c2.name, 'bar')
214 self.assertEquals(c3.name, 'bah')
214 self.assertEquals(c3.name, 'bah')
@@ -1,690 +1,690 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # encoding: utf-8
2 # encoding: utf-8
3 """
3 """
4 Tests for IPython.utils.traitlets.
4 Tests for IPython.utils.traitlets.
5
5
6 Authors:
6 Authors:
7
7
8 * Brian Granger
8 * Brian Granger
9 * Enthought, Inc. Some of the code in this file comes from enthought.traits
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
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.
11 from enthought.traits even though our implementation is very different.
12 """
12 """
13
13
14 #-----------------------------------------------------------------------------
14 #-----------------------------------------------------------------------------
15 # Copyright (C) 2008-2009 The IPython Development Team
15 # Copyright (C) 2008-2009 The IPython Development Team
16 #
16 #
17 # Distributed under the terms of the BSD License. The full license is in
17 # Distributed under the terms of the BSD License. The full license is in
18 # the file COPYING, distributed as part of this software.
18 # the file COPYING, distributed as part of this software.
19 #-----------------------------------------------------------------------------
19 #-----------------------------------------------------------------------------
20
20
21 #-----------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
22 # Imports
22 # Imports
23 #-----------------------------------------------------------------------------
23 #-----------------------------------------------------------------------------
24
24
25 import sys
25 import sys
26 import os
26 import os
27
27
28
28
29 from unittest import TestCase
29 from unittest import TestCase
30
30
31 from IPython.utils.traitlets import (
31 from IPython.utils.traitlets import (
32 HasTraits, MetaHasTraits, TraitletType, Any,
32 HasTraits, MetaHasTraits, TraitType, Any,
33 Int, Long, Float, Complex, Str, Unicode, Bool, TraitletError,
33 Int, Long, Float, Complex, Str, Unicode, Bool, TraitError,
34 Undefined, Type, This, Instance
34 Undefined, Type, This, Instance
35 )
35 )
36
36
37
37
38 #-----------------------------------------------------------------------------
38 #-----------------------------------------------------------------------------
39 # Helper classes for testing
39 # Helper classes for testing
40 #-----------------------------------------------------------------------------
40 #-----------------------------------------------------------------------------
41
41
42
42
43 class HasTraitletsStub(HasTraits):
43 class HasTraitsStub(HasTraits):
44
44
45 def _notify_traitlet(self, name, old, new):
45 def _notify_trait(self, name, old, new):
46 self._notify_name = name
46 self._notify_name = name
47 self._notify_old = old
47 self._notify_old = old
48 self._notify_new = new
48 self._notify_new = new
49
49
50
50
51 #-----------------------------------------------------------------------------
51 #-----------------------------------------------------------------------------
52 # Test classes
52 # Test classes
53 #-----------------------------------------------------------------------------
53 #-----------------------------------------------------------------------------
54
54
55
55
56 class TestTraitletType(TestCase):
56 class TestTraitType(TestCase):
57
57
58 def test_get_undefined(self):
58 def test_get_undefined(self):
59 class A(HasTraits):
59 class A(HasTraits):
60 a = TraitletType
60 a = TraitType
61 a = A()
61 a = A()
62 self.assertEquals(a.a, Undefined)
62 self.assertEquals(a.a, Undefined)
63
63
64 def test_set(self):
64 def test_set(self):
65 class A(HasTraitletsStub):
65 class A(HasTraitsStub):
66 a = TraitletType
66 a = TraitType
67
67
68 a = A()
68 a = A()
69 a.a = 10
69 a.a = 10
70 self.assertEquals(a.a, 10)
70 self.assertEquals(a.a, 10)
71 self.assertEquals(a._notify_name, 'a')
71 self.assertEquals(a._notify_name, 'a')
72 self.assertEquals(a._notify_old, Undefined)
72 self.assertEquals(a._notify_old, Undefined)
73 self.assertEquals(a._notify_new, 10)
73 self.assertEquals(a._notify_new, 10)
74
74
75 def test_validate(self):
75 def test_validate(self):
76 class MyTT(TraitletType):
76 class MyTT(TraitType):
77 def validate(self, inst, value):
77 def validate(self, inst, value):
78 return -1
78 return -1
79 class A(HasTraitletsStub):
79 class A(HasTraitsStub):
80 tt = MyTT
80 tt = MyTT
81
81
82 a = A()
82 a = A()
83 a.tt = 10
83 a.tt = 10
84 self.assertEquals(a.tt, -1)
84 self.assertEquals(a.tt, -1)
85
85
86 def test_default_validate(self):
86 def test_default_validate(self):
87 class MyIntTT(TraitletType):
87 class MyIntTT(TraitType):
88 def validate(self, obj, value):
88 def validate(self, obj, value):
89 if isinstance(value, int):
89 if isinstance(value, int):
90 return value
90 return value
91 self.error(obj, value)
91 self.error(obj, value)
92 class A(HasTraits):
92 class A(HasTraits):
93 tt = MyIntTT(10)
93 tt = MyIntTT(10)
94 a = A()
94 a = A()
95 self.assertEquals(a.tt, 10)
95 self.assertEquals(a.tt, 10)
96
96
97 # Defaults are validated when the HasTraits is instantiated
97 # Defaults are validated when the HasTraits is instantiated
98 class B(HasTraits):
98 class B(HasTraits):
99 tt = MyIntTT('bad default')
99 tt = MyIntTT('bad default')
100 self.assertRaises(TraitletError, B)
100 self.assertRaises(TraitError, B)
101
101
102 def test_is_valid_for(self):
102 def test_is_valid_for(self):
103 class MyTT(TraitletType):
103 class MyTT(TraitType):
104 def is_valid_for(self, value):
104 def is_valid_for(self, value):
105 return True
105 return True
106 class A(HasTraits):
106 class A(HasTraits):
107 tt = MyTT
107 tt = MyTT
108
108
109 a = A()
109 a = A()
110 a.tt = 10
110 a.tt = 10
111 self.assertEquals(a.tt, 10)
111 self.assertEquals(a.tt, 10)
112
112
113 def test_value_for(self):
113 def test_value_for(self):
114 class MyTT(TraitletType):
114 class MyTT(TraitType):
115 def value_for(self, value):
115 def value_for(self, value):
116 return 20
116 return 20
117 class A(HasTraits):
117 class A(HasTraits):
118 tt = MyTT
118 tt = MyTT
119
119
120 a = A()
120 a = A()
121 a.tt = 10
121 a.tt = 10
122 self.assertEquals(a.tt, 20)
122 self.assertEquals(a.tt, 20)
123
123
124 def test_info(self):
124 def test_info(self):
125 class A(HasTraits):
125 class A(HasTraits):
126 tt = TraitletType
126 tt = TraitType
127 a = A()
127 a = A()
128 self.assertEquals(A.tt.info(), 'any value')
128 self.assertEquals(A.tt.info(), 'any value')
129
129
130 def test_error(self):
130 def test_error(self):
131 class A(HasTraits):
131 class A(HasTraits):
132 tt = TraitletType
132 tt = TraitType
133 a = A()
133 a = A()
134 self.assertRaises(TraitletError, A.tt.error, a, 10)
134 self.assertRaises(TraitError, A.tt.error, a, 10)
135
135
136
136
137 class TestHasTraitsMeta(TestCase):
137 class TestHasTraitsMeta(TestCase):
138
138
139 def test_metaclass(self):
139 def test_metaclass(self):
140 self.assertEquals(type(HasTraits), MetaHasTraits)
140 self.assertEquals(type(HasTraits), MetaHasTraits)
141
141
142 class A(HasTraits):
142 class A(HasTraits):
143 a = Int
143 a = Int
144
144
145 a = A()
145 a = A()
146 self.assertEquals(type(a.__class__), MetaHasTraits)
146 self.assertEquals(type(a.__class__), MetaHasTraits)
147 self.assertEquals(a.a,0)
147 self.assertEquals(a.a,0)
148 a.a = 10
148 a.a = 10
149 self.assertEquals(a.a,10)
149 self.assertEquals(a.a,10)
150
150
151 class B(HasTraits):
151 class B(HasTraits):
152 b = Int()
152 b = Int()
153
153
154 b = B()
154 b = B()
155 self.assertEquals(b.b,0)
155 self.assertEquals(b.b,0)
156 b.b = 10
156 b.b = 10
157 self.assertEquals(b.b,10)
157 self.assertEquals(b.b,10)
158
158
159 class C(HasTraits):
159 class C(HasTraits):
160 c = Int(30)
160 c = Int(30)
161
161
162 c = C()
162 c = C()
163 self.assertEquals(c.c,30)
163 self.assertEquals(c.c,30)
164 c.c = 10
164 c.c = 10
165 self.assertEquals(c.c,10)
165 self.assertEquals(c.c,10)
166
166
167 def test_this_class(self):
167 def test_this_class(self):
168 class A(HasTraits):
168 class A(HasTraits):
169 t = This()
169 t = This()
170 tt = This()
170 tt = This()
171 class B(A):
171 class B(A):
172 tt = This()
172 tt = This()
173 ttt = This()
173 ttt = This()
174 self.assertEquals(A.t.this_class, A)
174 self.assertEquals(A.t.this_class, A)
175 self.assertEquals(B.t.this_class, A)
175 self.assertEquals(B.t.this_class, A)
176 self.assertEquals(B.tt.this_class, B)
176 self.assertEquals(B.tt.this_class, B)
177 self.assertEquals(B.ttt.this_class, B)
177 self.assertEquals(B.ttt.this_class, B)
178
178
179 class TestHasTraitsNotify(TestCase):
179 class TestHasTraitsNotify(TestCase):
180
180
181 def setUp(self):
181 def setUp(self):
182 self._notify1 = []
182 self._notify1 = []
183 self._notify2 = []
183 self._notify2 = []
184
184
185 def notify1(self, name, old, new):
185 def notify1(self, name, old, new):
186 self._notify1.append((name, old, new))
186 self._notify1.append((name, old, new))
187
187
188 def notify2(self, name, old, new):
188 def notify2(self, name, old, new):
189 self._notify2.append((name, old, new))
189 self._notify2.append((name, old, new))
190
190
191 def test_notify_all(self):
191 def test_notify_all(self):
192
192
193 class A(HasTraits):
193 class A(HasTraits):
194 a = Int
194 a = Int
195 b = Float
195 b = Float
196
196
197 a = A()
197 a = A()
198 a.on_trait_change(self.notify1)
198 a.on_trait_change(self.notify1)
199 a.a = 0
199 a.a = 0
200 self.assertEquals(len(self._notify1),0)
200 self.assertEquals(len(self._notify1),0)
201 a.b = 0.0
201 a.b = 0.0
202 self.assertEquals(len(self._notify1),0)
202 self.assertEquals(len(self._notify1),0)
203 a.a = 10
203 a.a = 10
204 self.assert_(('a',0,10) in self._notify1)
204 self.assert_(('a',0,10) in self._notify1)
205 a.b = 10.0
205 a.b = 10.0
206 self.assert_(('b',0.0,10.0) in self._notify1)
206 self.assert_(('b',0.0,10.0) in self._notify1)
207 self.assertRaises(TraitletError,setattr,a,'a','bad string')
207 self.assertRaises(TraitError,setattr,a,'a','bad string')
208 self.assertRaises(TraitletError,setattr,a,'b','bad string')
208 self.assertRaises(TraitError,setattr,a,'b','bad string')
209 self._notify1 = []
209 self._notify1 = []
210 a.on_trait_change(self.notify1,remove=True)
210 a.on_trait_change(self.notify1,remove=True)
211 a.a = 20
211 a.a = 20
212 a.b = 20.0
212 a.b = 20.0
213 self.assertEquals(len(self._notify1),0)
213 self.assertEquals(len(self._notify1),0)
214
214
215 def test_notify_one(self):
215 def test_notify_one(self):
216
216
217 class A(HasTraits):
217 class A(HasTraits):
218 a = Int
218 a = Int
219 b = Float
219 b = Float
220
220
221 a = A()
221 a = A()
222 a.on_trait_change(self.notify1, 'a')
222 a.on_trait_change(self.notify1, 'a')
223 a.a = 0
223 a.a = 0
224 self.assertEquals(len(self._notify1),0)
224 self.assertEquals(len(self._notify1),0)
225 a.a = 10
225 a.a = 10
226 self.assert_(('a',0,10) in self._notify1)
226 self.assert_(('a',0,10) in self._notify1)
227 self.assertRaises(TraitletError,setattr,a,'a','bad string')
227 self.assertRaises(TraitError,setattr,a,'a','bad string')
228
228
229 def test_subclass(self):
229 def test_subclass(self):
230
230
231 class A(HasTraits):
231 class A(HasTraits):
232 a = Int
232 a = Int
233
233
234 class B(A):
234 class B(A):
235 b = Float
235 b = Float
236
236
237 b = B()
237 b = B()
238 self.assertEquals(b.a,0)
238 self.assertEquals(b.a,0)
239 self.assertEquals(b.b,0.0)
239 self.assertEquals(b.b,0.0)
240 b.a = 100
240 b.a = 100
241 b.b = 100.0
241 b.b = 100.0
242 self.assertEquals(b.a,100)
242 self.assertEquals(b.a,100)
243 self.assertEquals(b.b,100.0)
243 self.assertEquals(b.b,100.0)
244
244
245 def test_notify_subclass(self):
245 def test_notify_subclass(self):
246
246
247 class A(HasTraits):
247 class A(HasTraits):
248 a = Int
248 a = Int
249
249
250 class B(A):
250 class B(A):
251 b = Float
251 b = Float
252
252
253 b = B()
253 b = B()
254 b.on_trait_change(self.notify1, 'a')
254 b.on_trait_change(self.notify1, 'a')
255 b.on_trait_change(self.notify2, 'b')
255 b.on_trait_change(self.notify2, 'b')
256 b.a = 0
256 b.a = 0
257 b.b = 0.0
257 b.b = 0.0
258 self.assertEquals(len(self._notify1),0)
258 self.assertEquals(len(self._notify1),0)
259 self.assertEquals(len(self._notify2),0)
259 self.assertEquals(len(self._notify2),0)
260 b.a = 10
260 b.a = 10
261 b.b = 10.0
261 b.b = 10.0
262 self.assert_(('a',0,10) in self._notify1)
262 self.assert_(('a',0,10) in self._notify1)
263 self.assert_(('b',0.0,10.0) in self._notify2)
263 self.assert_(('b',0.0,10.0) in self._notify2)
264
264
265 def test_static_notify(self):
265 def test_static_notify(self):
266
266
267 class A(HasTraits):
267 class A(HasTraits):
268 a = Int
268 a = Int
269 _notify1 = []
269 _notify1 = []
270 def _a_changed(self, name, old, new):
270 def _a_changed(self, name, old, new):
271 self._notify1.append((name, old, new))
271 self._notify1.append((name, old, new))
272
272
273 a = A()
273 a = A()
274 a.a = 0
274 a.a = 0
275 # This is broken!!!
275 # This is broken!!!
276 self.assertEquals(len(a._notify1),0)
276 self.assertEquals(len(a._notify1),0)
277 a.a = 10
277 a.a = 10
278 self.assert_(('a',0,10) in a._notify1)
278 self.assert_(('a',0,10) in a._notify1)
279
279
280 class B(A):
280 class B(A):
281 b = Float
281 b = Float
282 _notify2 = []
282 _notify2 = []
283 def _b_changed(self, name, old, new):
283 def _b_changed(self, name, old, new):
284 self._notify2.append((name, old, new))
284 self._notify2.append((name, old, new))
285
285
286 b = B()
286 b = B()
287 b.a = 10
287 b.a = 10
288 b.b = 10.0
288 b.b = 10.0
289 self.assert_(('a',0,10) in b._notify1)
289 self.assert_(('a',0,10) in b._notify1)
290 self.assert_(('b',0.0,10.0) in b._notify2)
290 self.assert_(('b',0.0,10.0) in b._notify2)
291
291
292 def test_notify_args(self):
292 def test_notify_args(self):
293
293
294 def callback0():
294 def callback0():
295 self.cb = ()
295 self.cb = ()
296 def callback1(name):
296 def callback1(name):
297 self.cb = (name,)
297 self.cb = (name,)
298 def callback2(name, new):
298 def callback2(name, new):
299 self.cb = (name, new)
299 self.cb = (name, new)
300 def callback3(name, old, new):
300 def callback3(name, old, new):
301 self.cb = (name, old, new)
301 self.cb = (name, old, new)
302
302
303 class A(HasTraits):
303 class A(HasTraits):
304 a = Int
304 a = Int
305
305
306 a = A()
306 a = A()
307 a.on_trait_change(callback0, 'a')
307 a.on_trait_change(callback0, 'a')
308 a.a = 10
308 a.a = 10
309 self.assertEquals(self.cb,())
309 self.assertEquals(self.cb,())
310 a.on_trait_change(callback0, 'a', remove=True)
310 a.on_trait_change(callback0, 'a', remove=True)
311
311
312 a.on_trait_change(callback1, 'a')
312 a.on_trait_change(callback1, 'a')
313 a.a = 100
313 a.a = 100
314 self.assertEquals(self.cb,('a',))
314 self.assertEquals(self.cb,('a',))
315 a.on_trait_change(callback1, 'a', remove=True)
315 a.on_trait_change(callback1, 'a', remove=True)
316
316
317 a.on_trait_change(callback2, 'a')
317 a.on_trait_change(callback2, 'a')
318 a.a = 1000
318 a.a = 1000
319 self.assertEquals(self.cb,('a',1000))
319 self.assertEquals(self.cb,('a',1000))
320 a.on_trait_change(callback2, 'a', remove=True)
320 a.on_trait_change(callback2, 'a', remove=True)
321
321
322 a.on_trait_change(callback3, 'a')
322 a.on_trait_change(callback3, 'a')
323 a.a = 10000
323 a.a = 10000
324 self.assertEquals(self.cb,('a',1000,10000))
324 self.assertEquals(self.cb,('a',1000,10000))
325 a.on_trait_change(callback3, 'a', remove=True)
325 a.on_trait_change(callback3, 'a', remove=True)
326
326
327 self.assertEquals(len(a._traitlet_notifiers['a']),0)
327 self.assertEquals(len(a._trait_notifiers['a']),0)
328
328
329
329
330 class TestHasTraits(TestCase):
330 class TestHasTraits(TestCase):
331
331
332 def test_trait_names(self):
332 def test_trait_names(self):
333 class A(HasTraits):
333 class A(HasTraits):
334 i = Int
334 i = Int
335 f = Float
335 f = Float
336 a = A()
336 a = A()
337 self.assertEquals(a.trait_names(),['i','f'])
337 self.assertEquals(a.trait_names(),['i','f'])
338
338
339 def test_trait_metadata(self):
339 def test_trait_metadata(self):
340 class A(HasTraits):
340 class A(HasTraits):
341 i = Int(config_key='MY_VALUE')
341 i = Int(config_key='MY_VALUE')
342 a = A()
342 a = A()
343 self.assertEquals(a.trait_metadata('i','config_key'), 'MY_VALUE')
343 self.assertEquals(a.trait_metadata('i','config_key'), 'MY_VALUE')
344
344
345 def test_traits(self):
345 def test_traits(self):
346 class A(HasTraits):
346 class A(HasTraits):
347 i = Int
347 i = Int
348 f = Float
348 f = Float
349 a = A()
349 a = A()
350 self.assertEquals(a.traits(), dict(i=A.i, f=A.f))
350 self.assertEquals(a.traits(), dict(i=A.i, f=A.f))
351
351
352 def test_traits_metadata(self):
352 def test_traits_metadata(self):
353 class A(HasTraits):
353 class A(HasTraits):
354 i = Int(config_key='VALUE1', other_thing='VALUE2')
354 i = Int(config_key='VALUE1', other_thing='VALUE2')
355 f = Float(config_key='VALUE3', other_thing='VALUE2')
355 f = Float(config_key='VALUE3', other_thing='VALUE2')
356 j = Int(0)
356 j = Int(0)
357 a = A()
357 a = A()
358 self.assertEquals(a.traits(), dict(i=A.i, f=A.f, j=A.j))
358 self.assertEquals(a.traits(), dict(i=A.i, f=A.f, j=A.j))
359 traitlets = a.traits(config_key='VALUE1', other_thing='VALUE2')
359 traits = a.traits(config_key='VALUE1', other_thing='VALUE2')
360 self.assertEquals(traitlets, dict(i=A.i))
360 self.assertEquals(traits, dict(i=A.i))
361
361
362 # This passes, but it shouldn't because I am replicating a bug in
362 # This passes, but it shouldn't because I am replicating a bug in
363 # traits.
363 # traits.
364 traitlets = a.traits(config_key=lambda v: True)
364 traits = a.traits(config_key=lambda v: True)
365 self.assertEquals(traitlets, dict(i=A.i, f=A.f, j=A.j))
365 self.assertEquals(traits, dict(i=A.i, f=A.f, j=A.j))
366
366
367
367
368 #-----------------------------------------------------------------------------
368 #-----------------------------------------------------------------------------
369 # Tests for specific traitlet types
369 # Tests for specific trait types
370 #-----------------------------------------------------------------------------
370 #-----------------------------------------------------------------------------
371
371
372
372
373 class TestType(TestCase):
373 class TestType(TestCase):
374
374
375 def test_default(self):
375 def test_default(self):
376
376
377 class B(object): pass
377 class B(object): pass
378 class A(HasTraits):
378 class A(HasTraits):
379 klass = Type
379 klass = Type
380
380
381 a = A()
381 a = A()
382 self.assertEquals(a.klass, None)
382 self.assertEquals(a.klass, None)
383
383
384 a.klass = B
384 a.klass = B
385 self.assertEquals(a.klass, B)
385 self.assertEquals(a.klass, B)
386 self.assertRaises(TraitletError, setattr, a, 'klass', 10)
386 self.assertRaises(TraitError, setattr, a, 'klass', 10)
387
387
388 def test_value(self):
388 def test_value(self):
389
389
390 class B(object): pass
390 class B(object): pass
391 class C(object): pass
391 class C(object): pass
392 class A(HasTraits):
392 class A(HasTraits):
393 klass = Type(B)
393 klass = Type(B)
394
394
395 a = A()
395 a = A()
396 self.assertEquals(a.klass, B)
396 self.assertEquals(a.klass, B)
397 self.assertRaises(TraitletError, setattr, a, 'klass', C)
397 self.assertRaises(TraitError, setattr, a, 'klass', C)
398 self.assertRaises(TraitletError, setattr, a, 'klass', object)
398 self.assertRaises(TraitError, setattr, a, 'klass', object)
399 a.klass = B
399 a.klass = B
400
400
401 def test_allow_none(self):
401 def test_allow_none(self):
402
402
403 class B(object): pass
403 class B(object): pass
404 class C(B): pass
404 class C(B): pass
405 class A(HasTraits):
405 class A(HasTraits):
406 klass = Type(B, allow_none=False)
406 klass = Type(B, allow_none=False)
407
407
408 a = A()
408 a = A()
409 self.assertEquals(a.klass, B)
409 self.assertEquals(a.klass, B)
410 self.assertRaises(TraitletError, setattr, a, 'klass', None)
410 self.assertRaises(TraitError, setattr, a, 'klass', None)
411 a.klass = C
411 a.klass = C
412 self.assertEquals(a.klass, C)
412 self.assertEquals(a.klass, C)
413
413
414 def test_validate_klass(self):
414 def test_validate_klass(self):
415
415
416 class A(HasTraits):
416 class A(HasTraits):
417 klass = Type('no strings allowed')
417 klass = Type('no strings allowed')
418
418
419 self.assertRaises(ImportError, A)
419 self.assertRaises(ImportError, A)
420
420
421 class A(HasTraits):
421 class A(HasTraits):
422 klass = Type('rub.adub.Duck')
422 klass = Type('rub.adub.Duck')
423
423
424 self.assertRaises(ImportError, A)
424 self.assertRaises(ImportError, A)
425
425
426 def test_validate_default(self):
426 def test_validate_default(self):
427
427
428 class B(object): pass
428 class B(object): pass
429 class A(HasTraits):
429 class A(HasTraits):
430 klass = Type('bad default', B)
430 klass = Type('bad default', B)
431
431
432 self.assertRaises(ImportError, A)
432 self.assertRaises(ImportError, A)
433
433
434 class C(HasTraits):
434 class C(HasTraits):
435 klass = Type(None, B, allow_none=False)
435 klass = Type(None, B, allow_none=False)
436
436
437 self.assertRaises(TraitletError, C)
437 self.assertRaises(TraitError, C)
438
438
439 def test_str_klass(self):
439 def test_str_klass(self):
440
440
441 class A(HasTraits):
441 class A(HasTraits):
442 klass = Type('IPython.utils.ipstruct.Struct')
442 klass = Type('IPython.utils.ipstruct.Struct')
443
443
444 from IPython.utils.ipstruct import Struct
444 from IPython.utils.ipstruct import Struct
445 a = A()
445 a = A()
446 a.klass = Struct
446 a.klass = Struct
447 self.assertEquals(a.klass, Struct)
447 self.assertEquals(a.klass, Struct)
448
448
449 self.assertRaises(TraitletError, setattr, a, 'klass', 10)
449 self.assertRaises(TraitError, setattr, a, 'klass', 10)
450
450
451 class TestInstance(TestCase):
451 class TestInstance(TestCase):
452
452
453 def test_basic(self):
453 def test_basic(self):
454 class Foo(object): pass
454 class Foo(object): pass
455 class Bar(Foo): pass
455 class Bar(Foo): pass
456 class Bah(object): pass
456 class Bah(object): pass
457
457
458 class A(HasTraits):
458 class A(HasTraits):
459 inst = Instance(Foo)
459 inst = Instance(Foo)
460
460
461 a = A()
461 a = A()
462 self.assert_(a.inst is None)
462 self.assert_(a.inst is None)
463 a.inst = Foo()
463 a.inst = Foo()
464 self.assert_(isinstance(a.inst, Foo))
464 self.assert_(isinstance(a.inst, Foo))
465 a.inst = Bar()
465 a.inst = Bar()
466 self.assert_(isinstance(a.inst, Foo))
466 self.assert_(isinstance(a.inst, Foo))
467 self.assertRaises(TraitletError, setattr, a, 'inst', Foo)
467 self.assertRaises(TraitError, setattr, a, 'inst', Foo)
468 self.assertRaises(TraitletError, setattr, a, 'inst', Bar)
468 self.assertRaises(TraitError, setattr, a, 'inst', Bar)
469 self.assertRaises(TraitletError, setattr, a, 'inst', Bah())
469 self.assertRaises(TraitError, setattr, a, 'inst', Bah())
470
470
471 def test_unique_default_value(self):
471 def test_unique_default_value(self):
472 class Foo(object): pass
472 class Foo(object): pass
473 class A(HasTraits):
473 class A(HasTraits):
474 inst = Instance(Foo,(),{})
474 inst = Instance(Foo,(),{})
475
475
476 a = A()
476 a = A()
477 b = A()
477 b = A()
478 self.assert_(a.inst is not b.inst)
478 self.assert_(a.inst is not b.inst)
479
479
480 def test_args_kw(self):
480 def test_args_kw(self):
481 class Foo(object):
481 class Foo(object):
482 def __init__(self, c): self.c = c
482 def __init__(self, c): self.c = c
483 class Bar(object): pass
483 class Bar(object): pass
484 class Bah(object):
484 class Bah(object):
485 def __init__(self, c, d):
485 def __init__(self, c, d):
486 self.c = c; self.d = d
486 self.c = c; self.d = d
487
487
488 class A(HasTraits):
488 class A(HasTraits):
489 inst = Instance(Foo, (10,))
489 inst = Instance(Foo, (10,))
490 a = A()
490 a = A()
491 self.assertEquals(a.inst.c, 10)
491 self.assertEquals(a.inst.c, 10)
492
492
493 class B(HasTraits):
493 class B(HasTraits):
494 inst = Instance(Bah, args=(10,), kw=dict(d=20))
494 inst = Instance(Bah, args=(10,), kw=dict(d=20))
495 b = B()
495 b = B()
496 self.assertEquals(b.inst.c, 10)
496 self.assertEquals(b.inst.c, 10)
497 self.assertEquals(b.inst.d, 20)
497 self.assertEquals(b.inst.d, 20)
498
498
499 class C(HasTraits):
499 class C(HasTraits):
500 inst = Instance(Foo)
500 inst = Instance(Foo)
501 c = C()
501 c = C()
502 self.assert_(c.inst is None)
502 self.assert_(c.inst is None)
503
503
504 def test_bad_default(self):
504 def test_bad_default(self):
505 class Foo(object): pass
505 class Foo(object): pass
506
506
507 class A(HasTraits):
507 class A(HasTraits):
508 inst = Instance(Foo, allow_none=False)
508 inst = Instance(Foo, allow_none=False)
509
509
510 self.assertRaises(TraitletError, A)
510 self.assertRaises(TraitError, A)
511
511
512 def test_instance(self):
512 def test_instance(self):
513 class Foo(object): pass
513 class Foo(object): pass
514
514
515 def inner():
515 def inner():
516 class A(HasTraits):
516 class A(HasTraits):
517 inst = Instance(Foo())
517 inst = Instance(Foo())
518
518
519 self.assertRaises(TraitletError, inner)
519 self.assertRaises(TraitError, inner)
520
520
521
521
522 class TestThis(TestCase):
522 class TestThis(TestCase):
523
523
524 def test_this_class(self):
524 def test_this_class(self):
525 class Foo(HasTraits):
525 class Foo(HasTraits):
526 this = This
526 this = This
527
527
528 f = Foo()
528 f = Foo()
529 self.assertEquals(f.this, None)
529 self.assertEquals(f.this, None)
530 g = Foo()
530 g = Foo()
531 f.this = g
531 f.this = g
532 self.assertEquals(f.this, g)
532 self.assertEquals(f.this, g)
533 self.assertRaises(TraitletError, setattr, f, 'this', 10)
533 self.assertRaises(TraitError, setattr, f, 'this', 10)
534
534
535 def test_this_inst(self):
535 def test_this_inst(self):
536 class Foo(HasTraits):
536 class Foo(HasTraits):
537 this = This()
537 this = This()
538
538
539 f = Foo()
539 f = Foo()
540 f.this = Foo()
540 f.this = Foo()
541 self.assert_(isinstance(f.this, Foo))
541 self.assert_(isinstance(f.this, Foo))
542
542
543 def test_subclass(self):
543 def test_subclass(self):
544 class Foo(HasTraits):
544 class Foo(HasTraits):
545 t = This()
545 t = This()
546 class Bar(Foo):
546 class Bar(Foo):
547 pass
547 pass
548 f = Foo()
548 f = Foo()
549 b = Bar()
549 b = Bar()
550 f.t = b
550 f.t = b
551 b.t = f
551 b.t = f
552 self.assertEquals(f.t, b)
552 self.assertEquals(f.t, b)
553 self.assertEquals(b.t, f)
553 self.assertEquals(b.t, f)
554
554
555 def test_subclass_override(self):
555 def test_subclass_override(self):
556 class Foo(HasTraits):
556 class Foo(HasTraits):
557 t = This()
557 t = This()
558 class Bar(Foo):
558 class Bar(Foo):
559 t = This()
559 t = This()
560 f = Foo()
560 f = Foo()
561 b = Bar()
561 b = Bar()
562 f.t = b
562 f.t = b
563 self.assertEquals(f.t, b)
563 self.assertEquals(f.t, b)
564 self.assertRaises(TraitletError, setattr, b, 't', f)
564 self.assertRaises(TraitError, setattr, b, 't', f)
565
565
566 class TraitletTestBase(TestCase):
566 class TraitTestBase(TestCase):
567 """A best testing class for basic traitlet types."""
567 """A best testing class for basic trait types."""
568
568
569 def assign(self, value):
569 def assign(self, value):
570 self.obj.value = value
570 self.obj.value = value
571
571
572 def coerce(self, value):
572 def coerce(self, value):
573 return value
573 return value
574
574
575 def test_good_values(self):
575 def test_good_values(self):
576 if hasattr(self, '_good_values'):
576 if hasattr(self, '_good_values'):
577 for value in self._good_values:
577 for value in self._good_values:
578 self.assign(value)
578 self.assign(value)
579 self.assertEquals(self.obj.value, self.coerce(value))
579 self.assertEquals(self.obj.value, self.coerce(value))
580
580
581 def test_bad_values(self):
581 def test_bad_values(self):
582 if hasattr(self, '_bad_values'):
582 if hasattr(self, '_bad_values'):
583 for value in self._bad_values:
583 for value in self._bad_values:
584 self.assertRaises(TraitletError, self.assign, value)
584 self.assertRaises(TraitError, self.assign, value)
585
585
586 def test_default_value(self):
586 def test_default_value(self):
587 if hasattr(self, '_default_value'):
587 if hasattr(self, '_default_value'):
588 self.assertEquals(self._default_value, self.obj.value)
588 self.assertEquals(self._default_value, self.obj.value)
589
589
590
590
591 class AnyTraitlet(HasTraits):
591 class AnyTrait(HasTraits):
592
592
593 value = Any
593 value = Any
594
594
595 class AnyTraitTest(TraitletTestBase):
595 class AnyTraitTest(TraitTestBase):
596
596
597 obj = AnyTraitlet()
597 obj = AnyTrait()
598
598
599 _default_value = None
599 _default_value = None
600 _good_values = [10.0, 'ten', u'ten', [10], {'ten': 10},(10,), None, 1j]
600 _good_values = [10.0, 'ten', u'ten', [10], {'ten': 10},(10,), None, 1j]
601 _bad_values = []
601 _bad_values = []
602
602
603
603
604 class IntTraitlet(HasTraits):
604 class IntTrait(HasTraits):
605
605
606 value = Int(99)
606 value = Int(99)
607
607
608 class TestInt(TraitletTestBase):
608 class TestInt(TraitTestBase):
609
609
610 obj = IntTraitlet()
610 obj = IntTrait()
611 _default_value = 99
611 _default_value = 99
612 _good_values = [10, -10]
612 _good_values = [10, -10]
613 _bad_values = ['ten', u'ten', [10], {'ten': 10},(10,), None, 1j, 10L,
613 _bad_values = ['ten', u'ten', [10], {'ten': 10},(10,), None, 1j, 10L,
614 -10L, 10.1, -10.1, '10L', '-10L', '10.1', '-10.1', u'10L',
614 -10L, 10.1, -10.1, '10L', '-10L', '10.1', '-10.1', u'10L',
615 u'-10L', u'10.1', u'-10.1', '10', '-10', u'10', u'-10']
615 u'-10L', u'10.1', u'-10.1', '10', '-10', u'10', u'-10']
616
616
617
617
618 class LongTraitlet(HasTraits):
618 class LongTrait(HasTraits):
619
619
620 value = Long(99L)
620 value = Long(99L)
621
621
622 class TestLong(TraitletTestBase):
622 class TestLong(TraitTestBase):
623
623
624 obj = LongTraitlet()
624 obj = LongTrait()
625
625
626 _default_value = 99L
626 _default_value = 99L
627 _good_values = [10, -10, 10L, -10L]
627 _good_values = [10, -10, 10L, -10L]
628 _bad_values = ['ten', u'ten', [10], [10l], {'ten': 10},(10,),(10L,),
628 _bad_values = ['ten', u'ten', [10], [10l], {'ten': 10},(10,),(10L,),
629 None, 1j, 10.1, -10.1, '10', '-10', '10L', '-10L', '10.1',
629 None, 1j, 10.1, -10.1, '10', '-10', '10L', '-10L', '10.1',
630 '-10.1', u'10', u'-10', u'10L', u'-10L', u'10.1',
630 '-10.1', u'10', u'-10', u'10L', u'-10L', u'10.1',
631 u'-10.1']
631 u'-10.1']
632
632
633
633
634 class FloatTraitlet(HasTraits):
634 class FloatTrait(HasTraits):
635
635
636 value = Float(99.0)
636 value = Float(99.0)
637
637
638 class TestFloat(TraitletTestBase):
638 class TestFloat(TraitTestBase):
639
639
640 obj = FloatTraitlet()
640 obj = FloatTrait()
641
641
642 _default_value = 99.0
642 _default_value = 99.0
643 _good_values = [10, -10, 10.1, -10.1]
643 _good_values = [10, -10, 10.1, -10.1]
644 _bad_values = [10L, -10L, 'ten', u'ten', [10], {'ten': 10},(10,), None,
644 _bad_values = [10L, -10L, 'ten', u'ten', [10], {'ten': 10},(10,), None,
645 1j, '10', '-10', '10L', '-10L', '10.1', '-10.1', u'10',
645 1j, '10', '-10', '10L', '-10L', '10.1', '-10.1', u'10',
646 u'-10', u'10L', u'-10L', u'10.1', u'-10.1']
646 u'-10', u'10L', u'-10L', u'10.1', u'-10.1']
647
647
648
648
649 class ComplexTraitlet(HasTraits):
649 class ComplexTrait(HasTraits):
650
650
651 value = Complex(99.0-99.0j)
651 value = Complex(99.0-99.0j)
652
652
653 class TestComplex(TraitletTestBase):
653 class TestComplex(TraitTestBase):
654
654
655 obj = ComplexTraitlet()
655 obj = ComplexTrait()
656
656
657 _default_value = 99.0-99.0j
657 _default_value = 99.0-99.0j
658 _good_values = [10, -10, 10.1, -10.1, 10j, 10+10j, 10-10j,
658 _good_values = [10, -10, 10.1, -10.1, 10j, 10+10j, 10-10j,
659 10.1j, 10.1+10.1j, 10.1-10.1j]
659 10.1j, 10.1+10.1j, 10.1-10.1j]
660 _bad_values = [10L, -10L, u'10L', u'-10L', 'ten', [10], {'ten': 10},(10,), None]
660 _bad_values = [10L, -10L, u'10L', u'-10L', 'ten', [10], {'ten': 10},(10,), None]
661
661
662
662
663 class StringTraitlet(HasTraits):
663 class StringTrait(HasTraits):
664
664
665 value = Str('string')
665 value = Str('string')
666
666
667 class TestString(TraitletTestBase):
667 class TestString(TraitTestBase):
668
668
669 obj = StringTraitlet()
669 obj = StringTrait()
670
670
671 _default_value = 'string'
671 _default_value = 'string'
672 _good_values = ['10', '-10', '10L',
672 _good_values = ['10', '-10', '10L',
673 '-10L', '10.1', '-10.1', 'string']
673 '-10L', '10.1', '-10.1', 'string']
674 _bad_values = [10, -10, 10L, -10L, 10.1, -10.1, 1j, [10],
674 _bad_values = [10, -10, 10L, -10L, 10.1, -10.1, 1j, [10],
675 ['ten'],{'ten': 10},(10,), None, u'string']
675 ['ten'],{'ten': 10},(10,), None, u'string']
676
676
677
677
678 class UnicodeTraitlet(HasTraits):
678 class UnicodeTrait(HasTraits):
679
679
680 value = Unicode(u'unicode')
680 value = Unicode(u'unicode')
681
681
682 class TestUnicode(TraitletTestBase):
682 class TestUnicode(TraitTestBase):
683
683
684 obj = UnicodeTraitlet()
684 obj = UnicodeTrait()
685
685
686 _default_value = u'unicode'
686 _default_value = u'unicode'
687 _good_values = ['10', '-10', '10L', '-10L', '10.1',
687 _good_values = ['10', '-10', '10L', '-10L', '10.1',
688 '-10.1', '', u'', 'string', u'string', ]
688 '-10.1', '', u'', 'string', u'string', ]
689 _bad_values = [10, -10, 10L, -10L, 10.1, -10.1, 1j,
689 _bad_values = [10, -10, 10L, -10L, 10.1, -10.1, 1j,
690 [10], ['ten'], [u'ten'], {'ten': 10},(10,), None]
690 [10], ['ten'], [u'ten'], {'ten': 10},(10,), None]
@@ -1,1001 +1,994 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # encoding: utf-8
2 # encoding: utf-8
3 """
3 """
4 A lightweight Traits like module.
4 A lightweight Traits like module.
5
5
6 This is designed to provide a lightweight, simple, pure Python version of
6 This is designed to provide a lightweight, simple, pure Python version of
7 many of the capabilities of enthought.traits. This includes:
7 many of the capabilities of enthought.traits. This includes:
8
8
9 * Validation
9 * Validation
10 * Type specification with defaults
10 * Type specification with defaults
11 * Static and dynamic notification
11 * Static and dynamic notification
12 * Basic predefined types
12 * Basic predefined types
13 * An API that is similar to enthought.traits
13 * An API that is similar to enthought.traits
14
14
15 We don't support:
15 We don't support:
16
16
17 * Delegation
17 * Delegation
18 * Automatic GUI generation
18 * Automatic GUI generation
19 * A full set of trait types. Most importantly, we don't provide container
19 * A full set of trait types. Most importantly, we don't provide container
20 traitlets (list, dict, tuple) that can trigger notifications if their
20 traits (list, dict, tuple) that can trigger notifications if their
21 contents change.
21 contents change.
22 * API compatibility with enthought.traits
22 * API compatibility with enthought.traits
23
23
24 There are also some important difference in our design:
24 There are also some important difference in our design:
25
25
26 * enthought.traits does not validate default values. We do.
26 * enthought.traits does not validate default values. We do.
27
27
28 We choose to create this module because we need these capabilities, but
28 We choose to create this module because we need these capabilities, but
29 we need them to be pure Python so they work in all Python implementations,
29 we need them to be pure Python so they work in all Python implementations,
30 including Jython and IronPython.
30 including Jython and IronPython.
31
31
32 Authors:
32 Authors:
33
33
34 * Brian Granger
34 * Brian Granger
35 * Enthought, Inc. Some of the code in this file comes from enthought.traits
35 * Enthought, Inc. Some of the code in this file comes from enthought.traits
36 and is licensed under the BSD license. Also, many of the ideas also come
36 and is licensed under the BSD license. Also, many of the ideas also come
37 from enthought.traits even though our implementation is very different.
37 from enthought.traits even though our implementation is very different.
38 """
38 """
39
39
40 #-----------------------------------------------------------------------------
40 #-----------------------------------------------------------------------------
41 # Copyright (C) 2008-2009 The IPython Development Team
41 # Copyright (C) 2008-2009 The IPython Development Team
42 #
42 #
43 # Distributed under the terms of the BSD License. The full license is in
43 # Distributed under the terms of the BSD License. The full license is in
44 # the file COPYING, distributed as part of this software.
44 # the file COPYING, distributed as part of this software.
45 #-----------------------------------------------------------------------------
45 #-----------------------------------------------------------------------------
46
46
47 #-----------------------------------------------------------------------------
47 #-----------------------------------------------------------------------------
48 # Imports
48 # Imports
49 #-----------------------------------------------------------------------------
49 #-----------------------------------------------------------------------------
50
50
51
51
52 import inspect
52 import inspect
53 import sys
53 import sys
54 import types
54 import types
55 from types import (
55 from types import (
56 InstanceType, ClassType, FunctionType,
56 InstanceType, ClassType, FunctionType,
57 ListType, TupleType
57 ListType, TupleType
58 )
58 )
59
59
60 def import_item(name):
60 def import_item(name):
61 """Import and return bar given the string foo.bar."""
61 """Import and return bar given the string foo.bar."""
62 package = '.'.join(name.split('.')[0:-1])
62 package = '.'.join(name.split('.')[0:-1])
63 obj = name.split('.')[-1]
63 obj = name.split('.')[-1]
64 execString = 'from %s import %s' % (package, obj)
64 execString = 'from %s import %s' % (package, obj)
65 try:
65 try:
66 exec execString
66 exec execString
67 except SyntaxError:
67 except SyntaxError:
68 raise ImportError("Invalid class specification: %s" % name)
68 raise ImportError("Invalid class specification: %s" % name)
69 exec 'temp = %s' % obj
69 exec 'temp = %s' % obj
70 return temp
70 return temp
71
71
72
72
73 ClassTypes = (ClassType, type)
73 ClassTypes = (ClassType, type)
74
74
75 SequenceTypes = (ListType, TupleType)
75 SequenceTypes = (ListType, TupleType)
76
76
77 #-----------------------------------------------------------------------------
77 #-----------------------------------------------------------------------------
78 # Basic classes
78 # Basic classes
79 #-----------------------------------------------------------------------------
79 #-----------------------------------------------------------------------------
80
80
81
81
82 class NoDefaultSpecified ( object ): pass
82 class NoDefaultSpecified ( object ): pass
83 NoDefaultSpecified = NoDefaultSpecified()
83 NoDefaultSpecified = NoDefaultSpecified()
84
84
85
85
86 class Undefined ( object ): pass
86 class Undefined ( object ): pass
87 Undefined = Undefined()
87 Undefined = Undefined()
88
88
89 # The following allows us to test specifically for a TraitletError, or more
90 # generally for a TraitError if we are going for compatability with Enthought
91 # Traits
92 class TraitError(Exception):
89 class TraitError(Exception):
93 pass
90 pass
94
91
95 class TraitletError(TraitError):
96 pass
97
98
99 #-----------------------------------------------------------------------------
92 #-----------------------------------------------------------------------------
100 # Utilities
93 # Utilities
101 #-----------------------------------------------------------------------------
94 #-----------------------------------------------------------------------------
102
95
103
96
104 def class_of ( object ):
97 def class_of ( object ):
105 """ Returns a string containing the class name of an object with the
98 """ Returns a string containing the class name of an object with the
106 correct indefinite article ('a' or 'an') preceding it (e.g., 'an Image',
99 correct indefinite article ('a' or 'an') preceding it (e.g., 'an Image',
107 'a PlotValue').
100 'a PlotValue').
108 """
101 """
109 if isinstance( object, basestring ):
102 if isinstance( object, basestring ):
110 return add_article( object )
103 return add_article( object )
111
104
112 return add_article( object.__class__.__name__ )
105 return add_article( object.__class__.__name__ )
113
106
114
107
115 def add_article ( name ):
108 def add_article ( name ):
116 """ Returns a string containing the correct indefinite article ('a' or 'an')
109 """ Returns a string containing the correct indefinite article ('a' or 'an')
117 prefixed to the specified string.
110 prefixed to the specified string.
118 """
111 """
119 if name[:1].lower() in 'aeiou':
112 if name[:1].lower() in 'aeiou':
120 return 'an ' + name
113 return 'an ' + name
121
114
122 return 'a ' + name
115 return 'a ' + name
123
116
124
117
125 def repr_type(obj):
118 def repr_type(obj):
126 """ Return a string representation of a value and its type for readable
119 """ Return a string representation of a value and its type for readable
127 error messages.
120 error messages.
128 """
121 """
129 the_type = type(obj)
122 the_type = type(obj)
130 if the_type is InstanceType:
123 if the_type is InstanceType:
131 # Old-style class.
124 # Old-style class.
132 the_type = obj.__class__
125 the_type = obj.__class__
133 msg = '%r %r' % (obj, the_type)
126 msg = '%r %r' % (obj, the_type)
134 return msg
127 return msg
135
128
136
129
137 def parse_notifier_name(name):
130 def parse_notifier_name(name):
138 """Convert the name argument to a list of names.
131 """Convert the name argument to a list of names.
139
132
140 Examples
133 Examples
141 --------
134 --------
142
135
143 >>> parse_notifier_name('a')
136 >>> parse_notifier_name('a')
144 ['a']
137 ['a']
145 >>> parse_notifier_name(['a','b'])
138 >>> parse_notifier_name(['a','b'])
146 ['a', 'b']
139 ['a', 'b']
147 >>> parse_notifier_name(None)
140 >>> parse_notifier_name(None)
148 ['anytrait']
141 ['anytrait']
149 """
142 """
150 if isinstance(name, str):
143 if isinstance(name, str):
151 return [name]
144 return [name]
152 elif name is None:
145 elif name is None:
153 return ['anytrait']
146 return ['anytrait']
154 elif isinstance(name, (list, tuple)):
147 elif isinstance(name, (list, tuple)):
155 for n in name:
148 for n in name:
156 assert isinstance(n, str), "names must be strings"
149 assert isinstance(n, str), "names must be strings"
157 return name
150 return name
158
151
159
152
160 class _SimpleTest:
153 class _SimpleTest:
161 def __init__ ( self, value ): self.value = value
154 def __init__ ( self, value ): self.value = value
162 def __call__ ( self, test ):
155 def __call__ ( self, test ):
163 return test == self.value
156 return test == self.value
164 def __repr__(self):
157 def __repr__(self):
165 return "<SimpleTest(%r)" % self.value
158 return "<SimpleTest(%r)" % self.value
166 def __str__(self):
159 def __str__(self):
167 return self.__repr__()
160 return self.__repr__()
168
161
169
162
170 #-----------------------------------------------------------------------------
163 #-----------------------------------------------------------------------------
171 # Base TraitletType for all traitlets
164 # Base TraitType for all traits
172 #-----------------------------------------------------------------------------
165 #-----------------------------------------------------------------------------
173
166
174
167
175 class TraitletType(object):
168 class TraitType(object):
176 """A base class for all traitlet descriptors.
169 """A base class for all trait descriptors.
177
170
178 Notes
171 Notes
179 -----
172 -----
180 Our implementation of traitlets is based on Python's descriptor
173 Our implementation of traits is based on Python's descriptor
181 prototol. This class is the base class for all such descriptors. The
174 prototol. This class is the base class for all such descriptors. The
182 only magic we use is a custom metaclass for the main :class:`HasTraits`
175 only magic we use is a custom metaclass for the main :class:`HasTraits`
183 class that does the following:
176 class that does the following:
184
177
185 1. Sets the :attr:`name` attribute of every :class:`TraitletType`
178 1. Sets the :attr:`name` attribute of every :class:`TraitType`
186 instance in the class dict to the name of the attribute.
179 instance in the class dict to the name of the attribute.
187 2. Sets the :attr:`this_class` attribute of every :class:`TraitletType`
180 2. Sets the :attr:`this_class` attribute of every :class:`TraitType`
188 instance in the class dict to the *class* that declared the traitlet.
181 instance in the class dict to the *class* that declared the trait.
189 This is used by the :class:`This` traitlet to allow subclasses to
182 This is used by the :class:`This` trait to allow subclasses to
190 accept superclasses for :class:`This` values.
183 accept superclasses for :class:`This` values.
191 """
184 """
192
185
193
186
194 metadata = {}
187 metadata = {}
195 default_value = Undefined
188 default_value = Undefined
196 info_text = 'any value'
189 info_text = 'any value'
197
190
198 def __init__(self, default_value=NoDefaultSpecified, **metadata):
191 def __init__(self, default_value=NoDefaultSpecified, **metadata):
199 """Create a TraitletType.
192 """Create a TraitType.
200 """
193 """
201 if default_value is not NoDefaultSpecified:
194 if default_value is not NoDefaultSpecified:
202 self.default_value = default_value
195 self.default_value = default_value
203
196
204 if len(metadata) > 0:
197 if len(metadata) > 0:
205 if len(self.metadata) > 0:
198 if len(self.metadata) > 0:
206 self._metadata = self.metadata.copy()
199 self._metadata = self.metadata.copy()
207 self._metadata.update(metadata)
200 self._metadata.update(metadata)
208 else:
201 else:
209 self._metadata = metadata
202 self._metadata = metadata
210 else:
203 else:
211 self._metadata = self.metadata
204 self._metadata = self.metadata
212
205
213 self.init()
206 self.init()
214
207
215 def init(self):
208 def init(self):
216 pass
209 pass
217
210
218 def get_default_value(self):
211 def get_default_value(self):
219 """Create a new instance of the default value."""
212 """Create a new instance of the default value."""
220 dv = self.default_value
213 dv = self.default_value
221 return dv
214 return dv
222
215
223 def instance_init(self, obj):
216 def instance_init(self, obj):
224 """This is called by :meth:`HasTraits.__new__` to finish init'ing.
217 """This is called by :meth:`HasTraits.__new__` to finish init'ing.
225
218
226 Some stages of initialization must be delayed until the parent
219 Some stages of initialization must be delayed until the parent
227 :class:`HasTraits` instance has been created. This method is
220 :class:`HasTraits` instance has been created. This method is
228 called in :meth:`HasTraits.__new__` after the instance has been
221 called in :meth:`HasTraits.__new__` after the instance has been
229 created.
222 created.
230
223
231 This method trigger the creation and validation of default values
224 This method trigger the creation and validation of default values
232 and also things like the resolution of str given class names in
225 and also things like the resolution of str given class names in
233 :class:`Type` and :class`Instance`.
226 :class:`Type` and :class`Instance`.
234
227
235 Parameters
228 Parameters
236 ----------
229 ----------
237 obj : :class:`HasTraits` instance
230 obj : :class:`HasTraits` instance
238 The parent :class:`HasTraits` instance that has just been
231 The parent :class:`HasTraits` instance that has just been
239 created.
232 created.
240 """
233 """
241 self.set_default_value(obj)
234 self.set_default_value(obj)
242
235
243 def set_default_value(self, obj):
236 def set_default_value(self, obj):
244 """Set the default value on a per instance basis.
237 """Set the default value on a per instance basis.
245
238
246 This method is called by :meth:`instance_init` to create and
239 This method is called by :meth:`instance_init` to create and
247 validate the default value. The creation and validation of
240 validate the default value. The creation and validation of
248 default values must be delayed until the parent :class:`HasTraits`
241 default values must be delayed until the parent :class:`HasTraits`
249 class has been instantiated.
242 class has been instantiated.
250 """
243 """
251 dv = self.get_default_value()
244 dv = self.get_default_value()
252 newdv = self._validate(obj, dv)
245 newdv = self._validate(obj, dv)
253 obj._traitlet_values[self.name] = newdv
246 obj._trait_values[self.name] = newdv
254
247
255 def __get__(self, obj, cls=None):
248 def __get__(self, obj, cls=None):
256 """Get the value of the traitlet by self.name for the instance.
249 """Get the value of the trait by self.name for the instance.
257
250
258 Default values are instantiated when :meth:`HasTraits.__new__`
251 Default values are instantiated when :meth:`HasTraits.__new__`
259 is called. Thus by the time this method gets called either the
252 is called. Thus by the time this method gets called either the
260 default value or a user defined value (they called :meth:`__set__`)
253 default value or a user defined value (they called :meth:`__set__`)
261 is in the :class:`HasTraits` instance.
254 is in the :class:`HasTraits` instance.
262 """
255 """
263 if obj is None:
256 if obj is None:
264 return self
257 return self
265 else:
258 else:
266 try:
259 try:
267 value = obj._traitlet_values[self.name]
260 value = obj._trait_values[self.name]
268 except:
261 except:
269 # HasTraits should call set_default_value to populate
262 # HasTraits should call set_default_value to populate
270 # this. So this should never be reached.
263 # this. So this should never be reached.
271 raise TraitletError('Unexpected error in TraitletType: '
264 raise TraitError('Unexpected error in TraitType: '
272 'default value not set properly')
265 'default value not set properly')
273 else:
266 else:
274 return value
267 return value
275
268
276 def __set__(self, obj, value):
269 def __set__(self, obj, value):
277 new_value = self._validate(obj, value)
270 new_value = self._validate(obj, value)
278 old_value = self.__get__(obj)
271 old_value = self.__get__(obj)
279 if old_value != new_value:
272 if old_value != new_value:
280 obj._traitlet_values[self.name] = new_value
273 obj._trait_values[self.name] = new_value
281 obj._notify_traitlet(self.name, old_value, new_value)
274 obj._notify_trait(self.name, old_value, new_value)
282
275
283 def _validate(self, obj, value):
276 def _validate(self, obj, value):
284 if hasattr(self, 'validate'):
277 if hasattr(self, 'validate'):
285 return self.validate(obj, value)
278 return self.validate(obj, value)
286 elif hasattr(self, 'is_valid_for'):
279 elif hasattr(self, 'is_valid_for'):
287 valid = self.is_valid_for(value)
280 valid = self.is_valid_for(value)
288 if valid:
281 if valid:
289 return value
282 return value
290 else:
283 else:
291 raise TraitletError('invalid value for type: %r' % value)
284 raise TraitError('invalid value for type: %r' % value)
292 elif hasattr(self, 'value_for'):
285 elif hasattr(self, 'value_for'):
293 return self.value_for(value)
286 return self.value_for(value)
294 else:
287 else:
295 return value
288 return value
296
289
297 def info(self):
290 def info(self):
298 return self.info_text
291 return self.info_text
299
292
300 def error(self, obj, value):
293 def error(self, obj, value):
301 if obj is not None:
294 if obj is not None:
302 e = "The '%s' traitlet of %s instance must be %s, but a value of %s was specified." \
295 e = "The '%s' trait of %s instance must be %s, but a value of %s was specified." \
303 % (self.name, class_of(obj),
296 % (self.name, class_of(obj),
304 self.info(), repr_type(value))
297 self.info(), repr_type(value))
305 else:
298 else:
306 e = "The '%s' traitlet must be %s, but a value of %r was specified." \
299 e = "The '%s' trait must be %s, but a value of %r was specified." \
307 % (self.name, self.info(), repr_type(value))
300 % (self.name, self.info(), repr_type(value))
308 raise TraitletError(e)
301 raise TraitError(e)
309
302
310 def get_metadata(self, key):
303 def get_metadata(self, key):
311 return getattr(self, '_metadata', {}).get(key, None)
304 return getattr(self, '_metadata', {}).get(key, None)
312
305
313 def set_metadata(self, key, value):
306 def set_metadata(self, key, value):
314 getattr(self, '_metadata', {})[key] = value
307 getattr(self, '_metadata', {})[key] = value
315
308
316
309
317 #-----------------------------------------------------------------------------
310 #-----------------------------------------------------------------------------
318 # The HasTraits implementation
311 # The HasTraits implementation
319 #-----------------------------------------------------------------------------
312 #-----------------------------------------------------------------------------
320
313
321
314
322 class MetaHasTraits(type):
315 class MetaHasTraits(type):
323 """A metaclass for HasTraits.
316 """A metaclass for HasTraits.
324
317
325 This metaclass makes sure that any TraitletType class attributes are
318 This metaclass makes sure that any TraitType class attributes are
326 instantiated and sets their name attribute.
319 instantiated and sets their name attribute.
327 """
320 """
328
321
329 def __new__(mcls, name, bases, classdict):
322 def __new__(mcls, name, bases, classdict):
330 """Create the HasTraits class.
323 """Create the HasTraits class.
331
324
332 This instantiates all TraitletTypes in the class dict and sets their
325 This instantiates all TraitTypes in the class dict and sets their
333 :attr:`name` attribute.
326 :attr:`name` attribute.
334 """
327 """
335 for k,v in classdict.iteritems():
328 for k,v in classdict.iteritems():
336 if isinstance(v, TraitletType):
329 if isinstance(v, TraitType):
337 v.name = k
330 v.name = k
338 elif inspect.isclass(v):
331 elif inspect.isclass(v):
339 if issubclass(v, TraitletType):
332 if issubclass(v, TraitType):
340 vinst = v()
333 vinst = v()
341 vinst.name = k
334 vinst.name = k
342 classdict[k] = vinst
335 classdict[k] = vinst
343 return super(MetaHasTraits, mcls).__new__(mcls, name, bases, classdict)
336 return super(MetaHasTraits, mcls).__new__(mcls, name, bases, classdict)
344
337
345 def __init__(cls, name, bases, classdict):
338 def __init__(cls, name, bases, classdict):
346 """Finish initializing the HasTraits class.
339 """Finish initializing the HasTraits class.
347
340
348 This sets the :attr:`this_class` attribute of each TraitletType in the
341 This sets the :attr:`this_class` attribute of each TraitType in the
349 class dict to the newly created class ``cls``.
342 class dict to the newly created class ``cls``.
350 """
343 """
351 for k, v in classdict.iteritems():
344 for k, v in classdict.iteritems():
352 if isinstance(v, TraitletType):
345 if isinstance(v, TraitType):
353 v.this_class = cls
346 v.this_class = cls
354 super(MetaHasTraits, cls).__init__(name, bases, classdict)
347 super(MetaHasTraits, cls).__init__(name, bases, classdict)
355
348
356 class HasTraits(object):
349 class HasTraits(object):
357
350
358 __metaclass__ = MetaHasTraits
351 __metaclass__ = MetaHasTraits
359
352
360 def __new__(cls, *args, **kw):
353 def __new__(cls, *args, **kw):
361 # This is needed because in Python 2.6 object.__new__ only accepts
354 # This is needed because in Python 2.6 object.__new__ only accepts
362 # the cls argument.
355 # the cls argument.
363 new_meth = super(HasTraits, cls).__new__
356 new_meth = super(HasTraits, cls).__new__
364 if new_meth is object.__new__:
357 if new_meth is object.__new__:
365 inst = new_meth(cls)
358 inst = new_meth(cls)
366 else:
359 else:
367 inst = new_meth(cls, *args, **kw)
360 inst = new_meth(cls, *args, **kw)
368 inst._traitlet_values = {}
361 inst._trait_values = {}
369 inst._traitlet_notifiers = {}
362 inst._trait_notifiers = {}
370 # Here we tell all the TraitletType instances to set their default
363 # Here we tell all the TraitType instances to set their default
371 # values on the instance.
364 # values on the instance.
372 for key in dir(cls):
365 for key in dir(cls):
373 value = getattr(cls, key)
366 value = getattr(cls, key)
374 if isinstance(value, TraitletType):
367 if isinstance(value, TraitType):
375 value.instance_init(inst)
368 value.instance_init(inst)
376 return inst
369 return inst
377
370
378 # def __init__(self):
371 # def __init__(self):
379 # self._traitlet_values = {}
372 # self._trait_values = {}
380 # self._traitlet_notifiers = {}
373 # self._trait_notifiers = {}
381
374
382 def _notify_traitlet(self, name, old_value, new_value):
375 def _notify_trait(self, name, old_value, new_value):
383
376
384 # First dynamic ones
377 # First dynamic ones
385 callables = self._traitlet_notifiers.get(name,[])
378 callables = self._trait_notifiers.get(name,[])
386 more_callables = self._traitlet_notifiers.get('anytrait',[])
379 more_callables = self._trait_notifiers.get('anytrait',[])
387 callables.extend(more_callables)
380 callables.extend(more_callables)
388
381
389 # Now static ones
382 # Now static ones
390 try:
383 try:
391 cb = getattr(self, '_%s_changed' % name)
384 cb = getattr(self, '_%s_changed' % name)
392 except:
385 except:
393 pass
386 pass
394 else:
387 else:
395 callables.append(cb)
388 callables.append(cb)
396
389
397 # Call them all now
390 # Call them all now
398 for c in callables:
391 for c in callables:
399 # Traits catches and logs errors here. I allow them to raise
392 # Traits catches and logs errors here. I allow them to raise
400 if callable(c):
393 if callable(c):
401 argspec = inspect.getargspec(c)
394 argspec = inspect.getargspec(c)
402 nargs = len(argspec[0])
395 nargs = len(argspec[0])
403 # Bound methods have an additional 'self' argument
396 # Bound methods have an additional 'self' argument
404 # I don't know how to treat unbound methods, but they
397 # I don't know how to treat unbound methods, but they
405 # can't really be used for callbacks.
398 # can't really be used for callbacks.
406 if isinstance(c, types.MethodType):
399 if isinstance(c, types.MethodType):
407 offset = -1
400 offset = -1
408 else:
401 else:
409 offset = 0
402 offset = 0
410 if nargs + offset == 0:
403 if nargs + offset == 0:
411 c()
404 c()
412 elif nargs + offset == 1:
405 elif nargs + offset == 1:
413 c(name)
406 c(name)
414 elif nargs + offset == 2:
407 elif nargs + offset == 2:
415 c(name, new_value)
408 c(name, new_value)
416 elif nargs + offset == 3:
409 elif nargs + offset == 3:
417 c(name, old_value, new_value)
410 c(name, old_value, new_value)
418 else:
411 else:
419 raise TraitletError('a traitlet changed callback '
412 raise TraitError('a trait changed callback '
420 'must have 0-3 arguments.')
413 'must have 0-3 arguments.')
421 else:
414 else:
422 raise TraitletError('a traitlet changed callback '
415 raise TraitError('a trait changed callback '
423 'must be callable.')
416 'must be callable.')
424
417
425
418
426 def _add_notifiers(self, handler, name):
419 def _add_notifiers(self, handler, name):
427 if not self._traitlet_notifiers.has_key(name):
420 if not self._trait_notifiers.has_key(name):
428 nlist = []
421 nlist = []
429 self._traitlet_notifiers[name] = nlist
422 self._trait_notifiers[name] = nlist
430 else:
423 else:
431 nlist = self._traitlet_notifiers[name]
424 nlist = self._trait_notifiers[name]
432 if handler not in nlist:
425 if handler not in nlist:
433 nlist.append(handler)
426 nlist.append(handler)
434
427
435 def _remove_notifiers(self, handler, name):
428 def _remove_notifiers(self, handler, name):
436 if self._traitlet_notifiers.has_key(name):
429 if self._trait_notifiers.has_key(name):
437 nlist = self._traitlet_notifiers[name]
430 nlist = self._trait_notifiers[name]
438 try:
431 try:
439 index = nlist.index(handler)
432 index = nlist.index(handler)
440 except ValueError:
433 except ValueError:
441 pass
434 pass
442 else:
435 else:
443 del nlist[index]
436 del nlist[index]
444
437
445 def on_trait_change(self, handler, name=None, remove=False):
438 def on_trait_change(self, handler, name=None, remove=False):
446 """Setup a handler to be called when a traitlet changes.
439 """Setup a handler to be called when a trait changes.
447
440
448 This is used to setup dynamic notifications of traitlet changes.
441 This is used to setup dynamic notifications of trait changes.
449
442
450 Static handlers can be created by creating methods on a HasTraits
443 Static handlers can be created by creating methods on a HasTraits
451 subclass with the naming convention '_[traitletname]_changed'. Thus,
444 subclass with the naming convention '_[traitname]_changed'. Thus,
452 to create static handler for the traitlet 'a', create the method
445 to create static handler for the trait 'a', create the method
453 _a_changed(self, name, old, new) (fewer arguments can be used, see
446 _a_changed(self, name, old, new) (fewer arguments can be used, see
454 below).
447 below).
455
448
456 Parameters
449 Parameters
457 ----------
450 ----------
458 handler : callable
451 handler : callable
459 A callable that is called when a traitlet changes. Its
452 A callable that is called when a trait changes. Its
460 signature can be handler(), handler(name), handler(name, new)
453 signature can be handler(), handler(name), handler(name, new)
461 or handler(name, old, new).
454 or handler(name, old, new).
462 name : list, str, None
455 name : list, str, None
463 If None, the handler will apply to all traitlets. If a list
456 If None, the handler will apply to all traits. If a list
464 of str, handler will apply to all names in the list. If a
457 of str, handler will apply to all names in the list. If a
465 str, the handler will apply just to that name.
458 str, the handler will apply just to that name.
466 remove : bool
459 remove : bool
467 If False (the default), then install the handler. If True
460 If False (the default), then install the handler. If True
468 then unintall it.
461 then unintall it.
469 """
462 """
470 if remove:
463 if remove:
471 names = parse_notifier_name(name)
464 names = parse_notifier_name(name)
472 for n in names:
465 for n in names:
473 self._remove_notifiers(handler, n)
466 self._remove_notifiers(handler, n)
474 else:
467 else:
475 names = parse_notifier_name(name)
468 names = parse_notifier_name(name)
476 for n in names:
469 for n in names:
477 self._add_notifiers(handler, n)
470 self._add_notifiers(handler, n)
478
471
479 def trait_names(self, **metadata):
472 def trait_names(self, **metadata):
480 """Get a list of all the names of this classes traitlets."""
473 """Get a list of all the names of this classes traits."""
481 return self.traits(**metadata).keys()
474 return self.traits(**metadata).keys()
482
475
483 def traits(self, **metadata):
476 def traits(self, **metadata):
484 """Get a list of all the traitlets of this class.
477 """Get a list of all the traits of this class.
485
478
486 The TraitletTypes returned don't know anything about the values
479 The TraitTypes returned don't know anything about the values
487 that the various HasTraitlet's instances are holding.
480 that the various HasTrait's instances are holding.
488
481
489 This follows the same algorithm as traits does and does not allow
482 This follows the same algorithm as traits does and does not allow
490 for any simple way of specifying merely that a metadata name
483 for any simple way of specifying merely that a metadata name
491 exists, but has any value. This is because get_metadata returns
484 exists, but has any value. This is because get_metadata returns
492 None if a metadata key doesn't exist.
485 None if a metadata key doesn't exist.
493 """
486 """
494 traitlets = dict([memb for memb in inspect.getmembers(self.__class__) if \
487 traits = dict([memb for memb in inspect.getmembers(self.__class__) if \
495 isinstance(memb[1], TraitletType)])
488 isinstance(memb[1], TraitType)])
496
489
497 if len(metadata) == 0:
490 if len(metadata) == 0:
498 return traitlets
491 return traits
499
492
500 for meta_name, meta_eval in metadata.items():
493 for meta_name, meta_eval in metadata.items():
501 if type(meta_eval) is not FunctionType:
494 if type(meta_eval) is not FunctionType:
502 metadata[meta_name] = _SimpleTest(meta_eval)
495 metadata[meta_name] = _SimpleTest(meta_eval)
503
496
504 result = {}
497 result = {}
505 for name, traitlet in traitlets.items():
498 for name, trait in traits.items():
506 for meta_name, meta_eval in metadata.items():
499 for meta_name, meta_eval in metadata.items():
507 if not meta_eval(traitlet.get_metadata(meta_name)):
500 if not meta_eval(trait.get_metadata(meta_name)):
508 break
501 break
509 else:
502 else:
510 result[name] = traitlet
503 result[name] = trait
511
504
512 return result
505 return result
513
506
514 def trait_metadata(self, traitletname, key):
507 def trait_metadata(self, traitname, key):
515 """Get metadata values for traitlet by key."""
508 """Get metadata values for trait by key."""
516 try:
509 try:
517 traitlet = getattr(self.__class__, traitletname)
510 trait = getattr(self.__class__, traitname)
518 except AttributeError:
511 except AttributeError:
519 raise TraitletError("Class %s does not have a traitlet named %s" %
512 raise TraitError("Class %s does not have a trait named %s" %
520 (self.__class__.__name__, traitletname))
513 (self.__class__.__name__, traitname))
521 else:
514 else:
522 return traitlet.get_metadata(key)
515 return trait.get_metadata(key)
523
516
524 #-----------------------------------------------------------------------------
517 #-----------------------------------------------------------------------------
525 # Actual TraitletTypes implementations/subclasses
518 # Actual TraitTypes implementations/subclasses
526 #-----------------------------------------------------------------------------
519 #-----------------------------------------------------------------------------
527
520
528 #-----------------------------------------------------------------------------
521 #-----------------------------------------------------------------------------
529 # TraitletTypes subclasses for handling classes and instances of classes
522 # TraitTypes subclasses for handling classes and instances of classes
530 #-----------------------------------------------------------------------------
523 #-----------------------------------------------------------------------------
531
524
532
525
533 class ClassBasedTraitletType(TraitletType):
526 class ClassBasedTraitType(TraitType):
534 """A traitlet with error reporting for Type, Instance and This."""
527 """A trait with error reporting for Type, Instance and This."""
535
528
536 def error(self, obj, value):
529 def error(self, obj, value):
537 kind = type(value)
530 kind = type(value)
538 if kind is InstanceType:
531 if kind is InstanceType:
539 msg = 'class %s' % value.__class__.__name__
532 msg = 'class %s' % value.__class__.__name__
540 else:
533 else:
541 msg = '%s (i.e. %s)' % ( str( kind )[1:-1], repr( value ) )
534 msg = '%s (i.e. %s)' % ( str( kind )[1:-1], repr( value ) )
542
535
543 super(ClassBasedTraitletType, self).error(obj, msg)
536 super(ClassBasedTraitType, self).error(obj, msg)
544
537
545
538
546 class Type(ClassBasedTraitletType):
539 class Type(ClassBasedTraitType):
547 """A traitlet whose value must be a subclass of a specified class."""
540 """A trait whose value must be a subclass of a specified class."""
548
541
549 def __init__ (self, default_value=None, klass=None, allow_none=True, **metadata ):
542 def __init__ (self, default_value=None, klass=None, allow_none=True, **metadata ):
550 """Construct a Type traitlet
543 """Construct a Type trait
551
544
552 A Type traitlet specifies that its values must be subclasses of
545 A Type trait specifies that its values must be subclasses of
553 a particular class.
546 a particular class.
554
547
555 If only ``default_value`` is given, it is used for the ``klass`` as
548 If only ``default_value`` is given, it is used for the ``klass`` as
556 well.
549 well.
557
550
558 Parameters
551 Parameters
559 ----------
552 ----------
560 default_value : class, str or None
553 default_value : class, str or None
561 The default value must be a subclass of klass. If an str,
554 The default value must be a subclass of klass. If an str,
562 the str must be a fully specified class name, like 'foo.bar.Bah'.
555 the str must be a fully specified class name, like 'foo.bar.Bah'.
563 The string is resolved into real class, when the parent
556 The string is resolved into real class, when the parent
564 :class:`HasTraits` class is instantiated.
557 :class:`HasTraits` class is instantiated.
565 klass : class, str, None
558 klass : class, str, None
566 Values of this traitlet must be a subclass of klass. The klass
559 Values of this trait must be a subclass of klass. The klass
567 may be specified in a string like: 'foo.bar.MyClass'.
560 may be specified in a string like: 'foo.bar.MyClass'.
568 The string is resolved into real class, when the parent
561 The string is resolved into real class, when the parent
569 :class:`HasTraits` class is instantiated.
562 :class:`HasTraits` class is instantiated.
570 allow_none : boolean
563 allow_none : boolean
571 Indicates whether None is allowed as an assignable value. Even if
564 Indicates whether None is allowed as an assignable value. Even if
572 ``False``, the default value may be ``None``.
565 ``False``, the default value may be ``None``.
573 """
566 """
574 if default_value is None:
567 if default_value is None:
575 if klass is None:
568 if klass is None:
576 klass = object
569 klass = object
577 elif klass is None:
570 elif klass is None:
578 klass = default_value
571 klass = default_value
579
572
580 if not (inspect.isclass(klass) or isinstance(klass, basestring)):
573 if not (inspect.isclass(klass) or isinstance(klass, basestring)):
581 raise TraitletError("A Type traitlet must specify a class.")
574 raise TraitError("A Type trait must specify a class.")
582
575
583 self.klass = klass
576 self.klass = klass
584 self._allow_none = allow_none
577 self._allow_none = allow_none
585
578
586 super(Type, self).__init__(default_value, **metadata)
579 super(Type, self).__init__(default_value, **metadata)
587
580
588 def validate(self, obj, value):
581 def validate(self, obj, value):
589 """Validates that the value is a valid object instance."""
582 """Validates that the value is a valid object instance."""
590 try:
583 try:
591 if issubclass(value, self.klass):
584 if issubclass(value, self.klass):
592 return value
585 return value
593 except:
586 except:
594 if (value is None) and (self._allow_none):
587 if (value is None) and (self._allow_none):
595 return value
588 return value
596
589
597 self.error(obj, value)
590 self.error(obj, value)
598
591
599 def info(self):
592 def info(self):
600 """ Returns a description of the trait."""
593 """ Returns a description of the trait."""
601 if isinstance(self.klass, basestring):
594 if isinstance(self.klass, basestring):
602 klass = self.klass
595 klass = self.klass
603 else:
596 else:
604 klass = self.klass.__name__
597 klass = self.klass.__name__
605 result = 'a subclass of ' + klass
598 result = 'a subclass of ' + klass
606 if self._allow_none:
599 if self._allow_none:
607 return result + ' or None'
600 return result + ' or None'
608 return result
601 return result
609
602
610 def instance_init(self, obj):
603 def instance_init(self, obj):
611 self._resolve_classes()
604 self._resolve_classes()
612 super(Type, self).instance_init(obj)
605 super(Type, self).instance_init(obj)
613
606
614 def _resolve_classes(self):
607 def _resolve_classes(self):
615 if isinstance(self.klass, basestring):
608 if isinstance(self.klass, basestring):
616 self.klass = import_item(self.klass)
609 self.klass = import_item(self.klass)
617 if isinstance(self.default_value, basestring):
610 if isinstance(self.default_value, basestring):
618 self.default_value = import_item(self.default_value)
611 self.default_value = import_item(self.default_value)
619
612
620 def get_default_value(self):
613 def get_default_value(self):
621 return self.default_value
614 return self.default_value
622
615
623
616
624 class DefaultValueGenerator(object):
617 class DefaultValueGenerator(object):
625 """A class for generating new default value instances."""
618 """A class for generating new default value instances."""
626
619
627 def __init__(self, *args, **kw):
620 def __init__(self, *args, **kw):
628 self.args = args
621 self.args = args
629 self.kw = kw
622 self.kw = kw
630
623
631 def generate(self, klass):
624 def generate(self, klass):
632 return klass(*self.args, **self.kw)
625 return klass(*self.args, **self.kw)
633
626
634
627
635 class Instance(ClassBasedTraitletType):
628 class Instance(ClassBasedTraitType):
636 """A trait whose value must be an instance of a specified class.
629 """A trait whose value must be an instance of a specified class.
637
630
638 The value can also be an instance of a subclass of the specified class.
631 The value can also be an instance of a subclass of the specified class.
639 """
632 """
640
633
641 def __init__(self, klass=None, args=None, kw=None,
634 def __init__(self, klass=None, args=None, kw=None,
642 allow_none=True, **metadata ):
635 allow_none=True, **metadata ):
643 """Construct an Instance traitlet.
636 """Construct an Instance trait.
644
637
645 This traitlet allows values that are instances of a particular
638 This trait allows values that are instances of a particular
646 class or its sublclasses. Our implementation is quite different
639 class or its sublclasses. Our implementation is quite different
647 from that of enthough.traits as we don't allow instances to be used
640 from that of enthough.traits as we don't allow instances to be used
648 for klass and we handle the ``args`` and ``kw`` arguments differently.
641 for klass and we handle the ``args`` and ``kw`` arguments differently.
649
642
650 Parameters
643 Parameters
651 ----------
644 ----------
652 klass : class, str
645 klass : class, str
653 The class that forms the basis for the traitlet. Class names
646 The class that forms the basis for the trait. Class names
654 can also be specified as strings, like 'foo.bar.Bar'.
647 can also be specified as strings, like 'foo.bar.Bar'.
655 args : tuple
648 args : tuple
656 Positional arguments for generating the default value.
649 Positional arguments for generating the default value.
657 kw : dict
650 kw : dict
658 Keyword arguments for generating the default value.
651 Keyword arguments for generating the default value.
659 allow_none : bool
652 allow_none : bool
660 Indicates whether None is allowed as a value.
653 Indicates whether None is allowed as a value.
661
654
662 Default Value
655 Default Value
663 -------------
656 -------------
664 If both ``args`` and ``kw`` are None, then the default value is None.
657 If both ``args`` and ``kw`` are None, then the default value is None.
665 If ``args`` is a tuple and ``kw`` is a dict, then the default is
658 If ``args`` is a tuple and ``kw`` is a dict, then the default is
666 created as ``klass(*args, **kw)``. If either ``args`` or ``kw`` is
659 created as ``klass(*args, **kw)``. If either ``args`` or ``kw`` is
667 not (but not both), None is replace by ``()`` or ``{}``.
660 not (but not both), None is replace by ``()`` or ``{}``.
668 """
661 """
669
662
670 self._allow_none = allow_none
663 self._allow_none = allow_none
671
664
672 if (klass is None) or (not (inspect.isclass(klass) or isinstance(klass, basestring))):
665 if (klass is None) or (not (inspect.isclass(klass) or isinstance(klass, basestring))):
673 raise TraitletError('The klass argument must be a class'
666 raise TraitError('The klass argument must be a class'
674 ' you gave: %r' % klass)
667 ' you gave: %r' % klass)
675 self.klass = klass
668 self.klass = klass
676
669
677 # self.klass is a class, so handle default_value
670 # self.klass is a class, so handle default_value
678 if args is None and kw is None:
671 if args is None and kw is None:
679 default_value = None
672 default_value = None
680 else:
673 else:
681 if args is None:
674 if args is None:
682 # kw is not None
675 # kw is not None
683 args = ()
676 args = ()
684 elif kw is None:
677 elif kw is None:
685 # args is not None
678 # args is not None
686 kw = {}
679 kw = {}
687
680
688 if not isinstance(kw, dict):
681 if not isinstance(kw, dict):
689 raise TraitletError("The 'kw' argument must be a dict or None.")
682 raise TraitError("The 'kw' argument must be a dict or None.")
690 if not isinstance(args, tuple):
683 if not isinstance(args, tuple):
691 raise TraitletError("The 'args' argument must be a tuple or None.")
684 raise TraitError("The 'args' argument must be a tuple or None.")
692
685
693 default_value = DefaultValueGenerator(*args, **kw)
686 default_value = DefaultValueGenerator(*args, **kw)
694
687
695 super(Instance, self).__init__(default_value, **metadata)
688 super(Instance, self).__init__(default_value, **metadata)
696
689
697 def validate(self, obj, value):
690 def validate(self, obj, value):
698 if value is None:
691 if value is None:
699 if self._allow_none:
692 if self._allow_none:
700 return value
693 return value
701 self.error(obj, value)
694 self.error(obj, value)
702
695
703 if isinstance(value, self.klass):
696 if isinstance(value, self.klass):
704 return value
697 return value
705 else:
698 else:
706 self.error(obj, value)
699 self.error(obj, value)
707
700
708 def info(self):
701 def info(self):
709 if isinstance(self.klass, basestring):
702 if isinstance(self.klass, basestring):
710 klass = self.klass
703 klass = self.klass
711 else:
704 else:
712 klass = self.klass.__name__
705 klass = self.klass.__name__
713 result = class_of(klass)
706 result = class_of(klass)
714 if self._allow_none:
707 if self._allow_none:
715 return result + ' or None'
708 return result + ' or None'
716
709
717 return result
710 return result
718
711
719 def instance_init(self, obj):
712 def instance_init(self, obj):
720 self._resolve_classes()
713 self._resolve_classes()
721 super(Instance, self).instance_init(obj)
714 super(Instance, self).instance_init(obj)
722
715
723 def _resolve_classes(self):
716 def _resolve_classes(self):
724 if isinstance(self.klass, basestring):
717 if isinstance(self.klass, basestring):
725 self.klass = import_item(self.klass)
718 self.klass = import_item(self.klass)
726
719
727 def get_default_value(self):
720 def get_default_value(self):
728 """Instantiate a default value instance.
721 """Instantiate a default value instance.
729
722
730 This is called when the containing HasTraits classes'
723 This is called when the containing HasTraits classes'
731 :meth:`__new__` method is called to ensure that a unique instance
724 :meth:`__new__` method is called to ensure that a unique instance
732 is created for each HasTraits instance.
725 is created for each HasTraits instance.
733 """
726 """
734 dv = self.default_value
727 dv = self.default_value
735 if isinstance(dv, DefaultValueGenerator):
728 if isinstance(dv, DefaultValueGenerator):
736 return dv.generate(self.klass)
729 return dv.generate(self.klass)
737 else:
730 else:
738 return dv
731 return dv
739
732
740
733
741 class This(ClassBasedTraitletType):
734 class This(ClassBasedTraitType):
742 """A traitlet for instances of the class containing this trait.
735 """A trait for instances of the class containing this trait.
743
736
744 Because how how and when class bodies are executed, the ``This``
737 Because how how and when class bodies are executed, the ``This``
745 traitlet can only have a default value of None. This, and because we
738 trait can only have a default value of None. This, and because we
746 always validate default values, ``allow_none`` is *always* true.
739 always validate default values, ``allow_none`` is *always* true.
747 """
740 """
748
741
749 info_text = 'an instance of the same type as the receiver or None'
742 info_text = 'an instance of the same type as the receiver or None'
750
743
751 def __init__(self, **metadata):
744 def __init__(self, **metadata):
752 super(This, self).__init__(None, **metadata)
745 super(This, self).__init__(None, **metadata)
753
746
754 def validate(self, obj, value):
747 def validate(self, obj, value):
755 # What if value is a superclass of obj.__class__? This is
748 # What if value is a superclass of obj.__class__? This is
756 # complicated if it was the superclass that defined the This
749 # complicated if it was the superclass that defined the This
757 # traitlet.
750 # trait.
758 if isinstance(value, self.this_class) or (value is None):
751 if isinstance(value, self.this_class) or (value is None):
759 return value
752 return value
760 else:
753 else:
761 self.error(obj, value)
754 self.error(obj, value)
762
755
763
756
764 #-----------------------------------------------------------------------------
757 #-----------------------------------------------------------------------------
765 # Basic TraitletTypes implementations/subclasses
758 # Basic TraitTypes implementations/subclasses
766 #-----------------------------------------------------------------------------
759 #-----------------------------------------------------------------------------
767
760
768
761
769 class Any(TraitletType):
762 class Any(TraitType):
770 default_value = None
763 default_value = None
771 info_text = 'any value'
764 info_text = 'any value'
772
765
773
766
774 class Int(TraitletType):
767 class Int(TraitType):
775 """A integer traitlet."""
768 """A integer trait."""
776
769
777 evaluate = int
770 evaluate = int
778 default_value = 0
771 default_value = 0
779 info_text = 'an integer'
772 info_text = 'an integer'
780
773
781 def validate(self, obj, value):
774 def validate(self, obj, value):
782 if isinstance(value, int):
775 if isinstance(value, int):
783 return value
776 return value
784 self.error(obj, value)
777 self.error(obj, value)
785
778
786 class CInt(Int):
779 class CInt(Int):
787 """A casting version of the int traitlet."""
780 """A casting version of the int trait."""
788
781
789 def validate(self, obj, value):
782 def validate(self, obj, value):
790 try:
783 try:
791 return int(value)
784 return int(value)
792 except:
785 except:
793 self.error(obj, value)
786 self.error(obj, value)
794
787
795
788
796 class Long(TraitletType):
789 class Long(TraitType):
797 """A long integer traitlet."""
790 """A long integer trait."""
798
791
799 evaluate = long
792 evaluate = long
800 default_value = 0L
793 default_value = 0L
801 info_text = 'a long'
794 info_text = 'a long'
802
795
803 def validate(self, obj, value):
796 def validate(self, obj, value):
804 if isinstance(value, long):
797 if isinstance(value, long):
805 return value
798 return value
806 if isinstance(value, int):
799 if isinstance(value, int):
807 return long(value)
800 return long(value)
808 self.error(obj, value)
801 self.error(obj, value)
809
802
810
803
811 class CLong(Long):
804 class CLong(Long):
812 """A casting version of the long integer traitlet."""
805 """A casting version of the long integer trait."""
813
806
814 def validate(self, obj, value):
807 def validate(self, obj, value):
815 try:
808 try:
816 return long(value)
809 return long(value)
817 except:
810 except:
818 self.error(obj, value)
811 self.error(obj, value)
819
812
820
813
821 class Float(TraitletType):
814 class Float(TraitType):
822 """A float traitlet."""
815 """A float trait."""
823
816
824 evaluate = float
817 evaluate = float
825 default_value = 0.0
818 default_value = 0.0
826 info_text = 'a float'
819 info_text = 'a float'
827
820
828 def validate(self, obj, value):
821 def validate(self, obj, value):
829 if isinstance(value, float):
822 if isinstance(value, float):
830 return value
823 return value
831 if isinstance(value, int):
824 if isinstance(value, int):
832 return float(value)
825 return float(value)
833 self.error(obj, value)
826 self.error(obj, value)
834
827
835
828
836 class CFloat(Float):
829 class CFloat(Float):
837 """A casting version of the float traitlet."""
830 """A casting version of the float trait."""
838
831
839 def validate(self, obj, value):
832 def validate(self, obj, value):
840 try:
833 try:
841 return float(value)
834 return float(value)
842 except:
835 except:
843 self.error(obj, value)
836 self.error(obj, value)
844
837
845 class Complex(TraitletType):
838 class Complex(TraitType):
846 """A traitlet for complex numbers."""
839 """A trait for complex numbers."""
847
840
848 evaluate = complex
841 evaluate = complex
849 default_value = 0.0 + 0.0j
842 default_value = 0.0 + 0.0j
850 info_text = 'a complex number'
843 info_text = 'a complex number'
851
844
852 def validate(self, obj, value):
845 def validate(self, obj, value):
853 if isinstance(value, complex):
846 if isinstance(value, complex):
854 return value
847 return value
855 if isinstance(value, (float, int)):
848 if isinstance(value, (float, int)):
856 return complex(value)
849 return complex(value)
857 self.error(obj, value)
850 self.error(obj, value)
858
851
859
852
860 class CComplex(Complex):
853 class CComplex(Complex):
861 """A casting version of the complex number traitlet."""
854 """A casting version of the complex number trait."""
862
855
863 def validate (self, obj, value):
856 def validate (self, obj, value):
864 try:
857 try:
865 return complex(value)
858 return complex(value)
866 except:
859 except:
867 self.error(obj, value)
860 self.error(obj, value)
868
861
869
862
870 class Str(TraitletType):
863 class Str(TraitType):
871 """A traitlet for strings."""
864 """A trait for strings."""
872
865
873 evaluate = lambda x: x
866 evaluate = lambda x: x
874 default_value = ''
867 default_value = ''
875 info_text = 'a string'
868 info_text = 'a string'
876
869
877 def validate(self, obj, value):
870 def validate(self, obj, value):
878 if isinstance(value, str):
871 if isinstance(value, str):
879 return value
872 return value
880 self.error(obj, value)
873 self.error(obj, value)
881
874
882
875
883 class CStr(Str):
876 class CStr(Str):
884 """A casting version of the string traitlet."""
877 """A casting version of the string trait."""
885
878
886 def validate(self, obj, value):
879 def validate(self, obj, value):
887 try:
880 try:
888 return str(value)
881 return str(value)
889 except:
882 except:
890 try:
883 try:
891 return unicode(value)
884 return unicode(value)
892 except:
885 except:
893 self.error(obj, value)
886 self.error(obj, value)
894
887
895
888
896 class Unicode(TraitletType):
889 class Unicode(TraitType):
897 """A traitlet for unicode strings."""
890 """A trait for unicode strings."""
898
891
899 evaluate = unicode
892 evaluate = unicode
900 default_value = u''
893 default_value = u''
901 info_text = 'a unicode string'
894 info_text = 'a unicode string'
902
895
903 def validate(self, obj, value):
896 def validate(self, obj, value):
904 if isinstance(value, unicode):
897 if isinstance(value, unicode):
905 return value
898 return value
906 if isinstance(value, str):
899 if isinstance(value, str):
907 return unicode(value)
900 return unicode(value)
908 self.error(obj, value)
901 self.error(obj, value)
909
902
910
903
911 class CUnicode(Unicode):
904 class CUnicode(Unicode):
912 """A casting version of the unicode traitlet."""
905 """A casting version of the unicode trait."""
913
906
914 def validate(self, obj, value):
907 def validate(self, obj, value):
915 try:
908 try:
916 return unicode(value)
909 return unicode(value)
917 except:
910 except:
918 self.error(obj, value)
911 self.error(obj, value)
919
912
920
913
921 class Bool(TraitletType):
914 class Bool(TraitType):
922 """A boolean (True, False) traitlet."""
915 """A boolean (True, False) trait."""
923 evaluate = bool
916 evaluate = bool
924 default_value = False
917 default_value = False
925 info_text = 'a boolean'
918 info_text = 'a boolean'
926
919
927 def validate(self, obj, value):
920 def validate(self, obj, value):
928 if isinstance(value, bool):
921 if isinstance(value, bool):
929 return value
922 return value
930 self.error(obj, value)
923 self.error(obj, value)
931
924
932
925
933 class CBool(Bool):
926 class CBool(Bool):
934 """A casting version of the boolean traitlet."""
927 """A casting version of the boolean trait."""
935
928
936 def validate(self, obj, value):
929 def validate(self, obj, value):
937 try:
930 try:
938 return bool(value)
931 return bool(value)
939 except:
932 except:
940 self.error(obj, value)
933 self.error(obj, value)
941
934
942
935
943 class Enum(TraitletType):
936 class Enum(TraitType):
944 """An enum that whose value must be in a given sequence."""
937 """An enum that whose value must be in a given sequence."""
945
938
946 def __init__(self, values, default_value=None, allow_none=True, **metadata):
939 def __init__(self, values, default_value=None, allow_none=True, **metadata):
947 self.values = values
940 self.values = values
948 self._allow_none = allow_none
941 self._allow_none = allow_none
949 super(Enum, self).__init__(default_value, **metadata)
942 super(Enum, self).__init__(default_value, **metadata)
950
943
951 def validate(self, obj, value):
944 def validate(self, obj, value):
952 if value is None:
945 if value is None:
953 if self._allow_none:
946 if self._allow_none:
954 return value
947 return value
955
948
956 if value in self.values:
949 if value in self.values:
957 return value
950 return value
958 self.error(obj, value)
951 self.error(obj, value)
959
952
960 def info(self):
953 def info(self):
961 """ Returns a description of the trait."""
954 """ Returns a description of the trait."""
962 result = 'any of ' + repr(self.values)
955 result = 'any of ' + repr(self.values)
963 if self._allow_none:
956 if self._allow_none:
964 return result + ' or None'
957 return result + ' or None'
965 return result
958 return result
966
959
967 class CaselessStrEnum(Enum):
960 class CaselessStrEnum(Enum):
968 """An enum of strings that are caseless in validate."""
961 """An enum of strings that are caseless in validate."""
969
962
970 def validate(self, obj, value):
963 def validate(self, obj, value):
971 if value is None:
964 if value is None:
972 if self._allow_none:
965 if self._allow_none:
973 return value
966 return value
974
967
975 if not isinstance(value, str):
968 if not isinstance(value, str):
976 self.error(obj, value)
969 self.error(obj, value)
977
970
978 for v in self.values:
971 for v in self.values:
979 if v.lower() == value.lower():
972 if v.lower() == value.lower():
980 return v
973 return v
981 self.error(obj, value)
974 self.error(obj, value)
982
975
983
976
984 class List(Instance):
977 class List(Instance):
985 """An instance of a Python list."""
978 """An instance of a Python list."""
986
979
987 def __init__(self, default_value=None, allow_none=True, **metadata):
980 def __init__(self, default_value=None, allow_none=True, **metadata):
988 """Create a list traitlet type from a list or tuple.
981 """Create a list trait type from a list or tuple.
989
982
990 The default value is created by doing ``list(default_value)``,
983 The default value is created by doing ``list(default_value)``,
991 which creates a copy of the ``default_value``.
984 which creates a copy of the ``default_value``.
992 """
985 """
993 if default_value is None:
986 if default_value is None:
994 args = ((),)
987 args = ((),)
995 elif isinstance(default_value, SequenceTypes):
988 elif isinstance(default_value, SequenceTypes):
996 args = (default_value,)
989 args = (default_value,)
997 else:
990 else:
998 raise TypeError('default value of List was %s' % default_value)
991 raise TypeError('default value of List was %s' % default_value)
999
992
1000 super(List,self).__init__(klass=list, args=args,
993 super(List,self).__init__(klass=list, args=args,
1001 allow_none=allow_none, **metadata)
994 allow_none=allow_none, **metadata)
General Comments 0
You need to be logged in to leave comments. Login now