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 |
General Comments 0
You need to be logged in to leave comments.
Login now