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