##// END OF EJS Templates
load_subconfig supports profiles...
MinRK -
Show More
@@ -1,524 +1,541 b''
1 """A simple configuration system.
1 """A simple configuration system.
2
2
3 Authors
3 Authors
4 -------
4 -------
5 * Brian Granger
5 * Brian Granger
6 * Fernando Perez
6 * Fernando Perez
7 * Min RK
7 * Min RK
8 """
8 """
9
9
10 #-----------------------------------------------------------------------------
10 #-----------------------------------------------------------------------------
11 # Copyright (C) 2008-2011 The IPython Development Team
11 # Copyright (C) 2008-2011 The IPython Development Team
12 #
12 #
13 # Distributed under the terms of the BSD License. The full license is in
13 # Distributed under the terms of the BSD License. The full license is in
14 # the file COPYING, distributed as part of this software.
14 # the file COPYING, distributed as part of this software.
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16
16
17 #-----------------------------------------------------------------------------
17 #-----------------------------------------------------------------------------
18 # Imports
18 # Imports
19 #-----------------------------------------------------------------------------
19 #-----------------------------------------------------------------------------
20
20
21 import __builtin__
21 import __builtin__
22 import re
22 import re
23 import sys
23 import sys
24
24
25 from IPython.external import argparse
25 from IPython.external import argparse
26 from IPython.utils.path import filefind
26 from IPython.utils.path import filefind, get_ipython_dir
27
27
28 #-----------------------------------------------------------------------------
28 #-----------------------------------------------------------------------------
29 # Exceptions
29 # Exceptions
30 #-----------------------------------------------------------------------------
30 #-----------------------------------------------------------------------------
31
31
32
32
33 class ConfigError(Exception):
33 class ConfigError(Exception):
34 pass
34 pass
35
35
36
36
37 class ConfigLoaderError(ConfigError):
37 class ConfigLoaderError(ConfigError):
38 pass
38 pass
39
39
40 class ArgumentError(ConfigLoaderError):
40 class ArgumentError(ConfigLoaderError):
41 pass
41 pass
42
42
43 #-----------------------------------------------------------------------------
43 #-----------------------------------------------------------------------------
44 # Argparse fix
44 # Argparse fix
45 #-----------------------------------------------------------------------------
45 #-----------------------------------------------------------------------------
46
46
47 # Unfortunately argparse by default prints help messages to stderr instead of
47 # Unfortunately argparse by default prints help messages to stderr instead of
48 # stdout. This makes it annoying to capture long help screens at the command
48 # stdout. This makes it annoying to capture long help screens at the command
49 # line, since one must know how to pipe stderr, which many users don't know how
49 # line, since one must know how to pipe stderr, which many users don't know how
50 # to do. So we override the print_help method with one that defaults to
50 # to do. So we override the print_help method with one that defaults to
51 # stdout and use our class instead.
51 # stdout and use our class instead.
52
52
53 class ArgumentParser(argparse.ArgumentParser):
53 class ArgumentParser(argparse.ArgumentParser):
54 """Simple argparse subclass that prints help to stdout by default."""
54 """Simple argparse subclass that prints help to stdout by default."""
55
55
56 def print_help(self, file=None):
56 def print_help(self, file=None):
57 if file is None:
57 if file is None:
58 file = sys.stdout
58 file = sys.stdout
59 return super(ArgumentParser, self).print_help(file)
59 return super(ArgumentParser, self).print_help(file)
60
60
61 print_help.__doc__ = argparse.ArgumentParser.print_help.__doc__
61 print_help.__doc__ = argparse.ArgumentParser.print_help.__doc__
62
62
63 #-----------------------------------------------------------------------------
63 #-----------------------------------------------------------------------------
64 # Config class for holding config information
64 # Config class for holding config information
65 #-----------------------------------------------------------------------------
65 #-----------------------------------------------------------------------------
66
66
67
67
68 class Config(dict):
68 class Config(dict):
69 """An attribute based dict that can do smart merges."""
69 """An attribute based dict that can do smart merges."""
70
70
71 def __init__(self, *args, **kwds):
71 def __init__(self, *args, **kwds):
72 dict.__init__(self, *args, **kwds)
72 dict.__init__(self, *args, **kwds)
73 # This sets self.__dict__ = self, but it has to be done this way
73 # This sets self.__dict__ = self, but it has to be done this way
74 # because we are also overriding __setattr__.
74 # because we are also overriding __setattr__.
75 dict.__setattr__(self, '__dict__', self)
75 dict.__setattr__(self, '__dict__', self)
76
76
77 def _merge(self, other):
77 def _merge(self, other):
78 to_update = {}
78 to_update = {}
79 for k, v in other.iteritems():
79 for k, v in other.iteritems():
80 if not self.has_key(k):
80 if not self.has_key(k):
81 to_update[k] = v
81 to_update[k] = v
82 else: # I have this key
82 else: # I have this key
83 if isinstance(v, Config):
83 if isinstance(v, Config):
84 # Recursively merge common sub Configs
84 # Recursively merge common sub Configs
85 self[k]._merge(v)
85 self[k]._merge(v)
86 else:
86 else:
87 # Plain updates for non-Configs
87 # Plain updates for non-Configs
88 to_update[k] = v
88 to_update[k] = v
89
89
90 self.update(to_update)
90 self.update(to_update)
91
91
92 def _is_section_key(self, key):
92 def _is_section_key(self, key):
93 if key[0].upper()==key[0] and not key.startswith('_'):
93 if key[0].upper()==key[0] and not key.startswith('_'):
94 return True
94 return True
95 else:
95 else:
96 return False
96 return False
97
97
98 def __contains__(self, key):
98 def __contains__(self, key):
99 if self._is_section_key(key):
99 if self._is_section_key(key):
100 return True
100 return True
101 else:
101 else:
102 return super(Config, self).__contains__(key)
102 return super(Config, self).__contains__(key)
103 # .has_key is deprecated for dictionaries.
103 # .has_key is deprecated for dictionaries.
104 has_key = __contains__
104 has_key = __contains__
105
105
106 def _has_section(self, key):
106 def _has_section(self, key):
107 if self._is_section_key(key):
107 if self._is_section_key(key):
108 if super(Config, self).__contains__(key):
108 if super(Config, self).__contains__(key):
109 return True
109 return True
110 return False
110 return False
111
111
112 def copy(self):
112 def copy(self):
113 return type(self)(dict.copy(self))
113 return type(self)(dict.copy(self))
114
114
115 def __copy__(self):
115 def __copy__(self):
116 return self.copy()
116 return self.copy()
117
117
118 def __deepcopy__(self, memo):
118 def __deepcopy__(self, memo):
119 import copy
119 import copy
120 return type(self)(copy.deepcopy(self.items()))
120 return type(self)(copy.deepcopy(self.items()))
121
121
122 def __getitem__(self, key):
122 def __getitem__(self, key):
123 # We cannot use directly self._is_section_key, because it triggers
123 # We cannot use directly self._is_section_key, because it triggers
124 # infinite recursion on top of PyPy. Instead, we manually fish the
124 # infinite recursion on top of PyPy. Instead, we manually fish the
125 # bound method.
125 # bound method.
126 is_section_key = self.__class__._is_section_key.__get__(self)
126 is_section_key = self.__class__._is_section_key.__get__(self)
127
127
128 # Because we use this for an exec namespace, we need to delegate
128 # Because we use this for an exec namespace, we need to delegate
129 # the lookup of names in __builtin__ to itself. This means
129 # the lookup of names in __builtin__ to itself. This means
130 # that you can't have section or attribute names that are
130 # that you can't have section or attribute names that are
131 # builtins.
131 # builtins.
132 try:
132 try:
133 return getattr(__builtin__, key)
133 return getattr(__builtin__, key)
134 except AttributeError:
134 except AttributeError:
135 pass
135 pass
136 if is_section_key(key):
136 if is_section_key(key):
137 try:
137 try:
138 return dict.__getitem__(self, key)
138 return dict.__getitem__(self, key)
139 except KeyError:
139 except KeyError:
140 c = Config()
140 c = Config()
141 dict.__setitem__(self, key, c)
141 dict.__setitem__(self, key, c)
142 return c
142 return c
143 else:
143 else:
144 return dict.__getitem__(self, key)
144 return dict.__getitem__(self, key)
145
145
146 def __setitem__(self, key, value):
146 def __setitem__(self, key, value):
147 # Don't allow names in __builtin__ to be modified.
147 # Don't allow names in __builtin__ to be modified.
148 if hasattr(__builtin__, key):
148 if hasattr(__builtin__, key):
149 raise ConfigError('Config variable names cannot have the same name '
149 raise ConfigError('Config variable names cannot have the same name '
150 'as a Python builtin: %s' % key)
150 'as a Python builtin: %s' % key)
151 if self._is_section_key(key):
151 if self._is_section_key(key):
152 if not isinstance(value, Config):
152 if not isinstance(value, Config):
153 raise ValueError('values whose keys begin with an uppercase '
153 raise ValueError('values whose keys begin with an uppercase '
154 'char must be Config instances: %r, %r' % (key, value))
154 'char must be Config instances: %r, %r' % (key, value))
155 else:
155 else:
156 dict.__setitem__(self, key, value)
156 dict.__setitem__(self, key, value)
157
157
158 def __getattr__(self, key):
158 def __getattr__(self, key):
159 try:
159 try:
160 return self.__getitem__(key)
160 return self.__getitem__(key)
161 except KeyError, e:
161 except KeyError, e:
162 raise AttributeError(e)
162 raise AttributeError(e)
163
163
164 def __setattr__(self, key, value):
164 def __setattr__(self, key, value):
165 try:
165 try:
166 self.__setitem__(key, value)
166 self.__setitem__(key, value)
167 except KeyError, e:
167 except KeyError, e:
168 raise AttributeError(e)
168 raise AttributeError(e)
169
169
170 def __delattr__(self, key):
170 def __delattr__(self, key):
171 try:
171 try:
172 dict.__delitem__(self, key)
172 dict.__delitem__(self, key)
173 except KeyError, e:
173 except KeyError, e:
174 raise AttributeError(e)
174 raise AttributeError(e)
175
175
176
176
177 #-----------------------------------------------------------------------------
177 #-----------------------------------------------------------------------------
178 # Config loading classes
178 # Config loading classes
179 #-----------------------------------------------------------------------------
179 #-----------------------------------------------------------------------------
180
180
181
181
182 class ConfigLoader(object):
182 class ConfigLoader(object):
183 """A object for loading configurations from just about anywhere.
183 """A object for loading configurations from just about anywhere.
184
184
185 The resulting configuration is packaged as a :class:`Struct`.
185 The resulting configuration is packaged as a :class:`Struct`.
186
186
187 Notes
187 Notes
188 -----
188 -----
189 A :class:`ConfigLoader` does one thing: load a config from a source
189 A :class:`ConfigLoader` does one thing: load a config from a source
190 (file, command line arguments) and returns the data as a :class:`Struct`.
190 (file, command line arguments) and returns the data as a :class:`Struct`.
191 There are lots of things that :class:`ConfigLoader` does not do. It does
191 There are lots of things that :class:`ConfigLoader` does not do. It does
192 not implement complex logic for finding config files. It does not handle
192 not implement complex logic for finding config files. It does not handle
193 default values or merge multiple configs. These things need to be
193 default values or merge multiple configs. These things need to be
194 handled elsewhere.
194 handled elsewhere.
195 """
195 """
196
196
197 def __init__(self):
197 def __init__(self):
198 """A base class for config loaders.
198 """A base class for config loaders.
199
199
200 Examples
200 Examples
201 --------
201 --------
202
202
203 >>> cl = ConfigLoader()
203 >>> cl = ConfigLoader()
204 >>> config = cl.load_config()
204 >>> config = cl.load_config()
205 >>> config
205 >>> config
206 {}
206 {}
207 """
207 """
208 self.clear()
208 self.clear()
209
209
210 def clear(self):
210 def clear(self):
211 self.config = Config()
211 self.config = Config()
212
212
213 def load_config(self):
213 def load_config(self):
214 """Load a config from somewhere, return a :class:`Config` instance.
214 """Load a config from somewhere, return a :class:`Config` instance.
215
215
216 Usually, this will cause self.config to be set and then returned.
216 Usually, this will cause self.config to be set and then returned.
217 However, in most cases, :meth:`ConfigLoader.clear` should be called
217 However, in most cases, :meth:`ConfigLoader.clear` should be called
218 to erase any previous state.
218 to erase any previous state.
219 """
219 """
220 self.clear()
220 self.clear()
221 return self.config
221 return self.config
222
222
223
223
224 class FileConfigLoader(ConfigLoader):
224 class FileConfigLoader(ConfigLoader):
225 """A base class for file based configurations.
225 """A base class for file based configurations.
226
226
227 As we add more file based config loaders, the common logic should go
227 As we add more file based config loaders, the common logic should go
228 here.
228 here.
229 """
229 """
230 pass
230 pass
231
231
232
232
233 class PyFileConfigLoader(FileConfigLoader):
233 class PyFileConfigLoader(FileConfigLoader):
234 """A config loader for pure python files.
234 """A config loader for pure python files.
235
235
236 This calls execfile on a plain python file and looks for attributes
236 This calls execfile on a plain python file and looks for attributes
237 that are all caps. These attribute are added to the config Struct.
237 that are all caps. These attribute are added to the config Struct.
238 """
238 """
239
239
240 def __init__(self, filename, path=None):
240 def __init__(self, filename, path=None):
241 """Build a config loader for a filename and path.
241 """Build a config loader for a filename and path.
242
242
243 Parameters
243 Parameters
244 ----------
244 ----------
245 filename : str
245 filename : str
246 The file name of the config file.
246 The file name of the config file.
247 path : str, list, tuple
247 path : str, list, tuple
248 The path to search for the config file on, or a sequence of
248 The path to search for the config file on, or a sequence of
249 paths to try in order.
249 paths to try in order.
250 """
250 """
251 super(PyFileConfigLoader, self).__init__()
251 super(PyFileConfigLoader, self).__init__()
252 self.filename = filename
252 self.filename = filename
253 self.path = path
253 self.path = path
254 self.full_filename = ''
254 self.full_filename = ''
255 self.data = None
255 self.data = None
256
256
257 def load_config(self):
257 def load_config(self):
258 """Load the config from a file and return it as a Struct."""
258 """Load the config from a file and return it as a Struct."""
259 self.clear()
259 self.clear()
260 self._find_file()
260 self._find_file()
261 self._read_file_as_dict()
261 self._read_file_as_dict()
262 self._convert_to_config()
262 self._convert_to_config()
263 return self.config
263 return self.config
264
264
265 def _find_file(self):
265 def _find_file(self):
266 """Try to find the file by searching the paths."""
266 """Try to find the file by searching the paths."""
267 self.full_filename = filefind(self.filename, self.path)
267 self.full_filename = filefind(self.filename, self.path)
268
268
269 def _read_file_as_dict(self):
269 def _read_file_as_dict(self):
270 """Load the config file into self.config, with recursive loading."""
270 """Load the config file into self.config, with recursive loading."""
271 # This closure is made available in the namespace that is used
271 # This closure is made available in the namespace that is used
272 # to exec the config file. This allows users to call
272 # to exec the config file. It allows users to call
273 # load_subconfig('myconfig.py') to load config files recursively.
273 # load_subconfig('myconfig.py') to load config files recursively.
274 # It needs to be a closure because it has references to self.path
274 # It needs to be a closure because it has references to self.path
275 # and self.config. The sub-config is loaded with the same path
275 # and self.config. The sub-config is loaded with the same path
276 # as the parent, but it uses an empty config which is then merged
276 # as the parent, but it uses an empty config which is then merged
277 # with the parents.
277 # with the parents.
278 def load_subconfig(fname):
278
279 loader = PyFileConfigLoader(fname, self.path)
279 # If a profile is specified, the config file will be loaded
280 # from that profile
281
282 def load_subconfig(fname, profile=None):
283 # import here to prevent circular imports
284 from IPython.core.profiledir import ProfileDir, ProfileDirError
285 if profile is not None:
286 try:
287 profile_dir = ProfileDir.find_profile_dir_by_name(
288 get_ipython_dir(),
289 profile,
290 )
291 except ProfileDirError:
292 return
293 path = profile_dir.location
294 else:
295 path = self.path
296 loader = PyFileConfigLoader(fname, path)
280 try:
297 try:
281 sub_config = loader.load_config()
298 sub_config = loader.load_config()
282 except IOError:
299 except IOError:
283 # Pass silently if the sub config is not there. This happens
300 # Pass silently if the sub config is not there. This happens
284 # when a user us using a profile, but not the default config.
301 # when a user s using a profile, but not the default config.
285 pass
302 pass
286 else:
303 else:
287 self.config._merge(sub_config)
304 self.config._merge(sub_config)
288
305
289 # Again, this needs to be a closure and should be used in config
306 # Again, this needs to be a closure and should be used in config
290 # files to get the config being loaded.
307 # files to get the config being loaded.
291 def get_config():
308 def get_config():
292 return self.config
309 return self.config
293
310
294 namespace = dict(load_subconfig=load_subconfig, get_config=get_config)
311 namespace = dict(load_subconfig=load_subconfig, get_config=get_config)
295 fs_encoding = sys.getfilesystemencoding() or 'ascii'
312 fs_encoding = sys.getfilesystemencoding() or 'ascii'
296 conf_filename = self.full_filename.encode(fs_encoding)
313 conf_filename = self.full_filename.encode(fs_encoding)
297 execfile(conf_filename, namespace)
314 execfile(conf_filename, namespace)
298
315
299 def _convert_to_config(self):
316 def _convert_to_config(self):
300 if self.data is None:
317 if self.data is None:
301 ConfigLoaderError('self.data does not exist')
318 ConfigLoaderError('self.data does not exist')
302
319
303
320
304 class CommandLineConfigLoader(ConfigLoader):
321 class CommandLineConfigLoader(ConfigLoader):
305 """A config loader for command line arguments.
322 """A config loader for command line arguments.
306
323
307 As we add more command line based loaders, the common logic should go
324 As we add more command line based loaders, the common logic should go
308 here.
325 here.
309 """
326 """
310
327
311 kv_pattern = re.compile(r'[A-Za-z]\w*(\.\w+)*\=.*')
328 kv_pattern = re.compile(r'[A-Za-z]\w*(\.\w+)*\=.*')
312 flag_pattern = re.compile(r'\-\-\w+(\-\w)*')
329 flag_pattern = re.compile(r'\-\-\w+(\-\w)*')
313
330
314 class KeyValueConfigLoader(CommandLineConfigLoader):
331 class KeyValueConfigLoader(CommandLineConfigLoader):
315 """A config loader that loads key value pairs from the command line.
332 """A config loader that loads key value pairs from the command line.
316
333
317 This allows command line options to be gives in the following form::
334 This allows command line options to be gives in the following form::
318
335
319 ipython Global.profile="foo" InteractiveShell.autocall=False
336 ipython Global.profile="foo" InteractiveShell.autocall=False
320 """
337 """
321
338
322 def __init__(self, argv=None, aliases=None, flags=None):
339 def __init__(self, argv=None, aliases=None, flags=None):
323 """Create a key value pair config loader.
340 """Create a key value pair config loader.
324
341
325 Parameters
342 Parameters
326 ----------
343 ----------
327 argv : list
344 argv : list
328 A list that has the form of sys.argv[1:] which has unicode
345 A list that has the form of sys.argv[1:] which has unicode
329 elements of the form u"key=value". If this is None (default),
346 elements of the form u"key=value". If this is None (default),
330 then sys.argv[1:] will be used.
347 then sys.argv[1:] will be used.
331 aliases : dict
348 aliases : dict
332 A dict of aliases for configurable traits.
349 A dict of aliases for configurable traits.
333 Keys are the short aliases, Values are the resolved trait.
350 Keys are the short aliases, Values are the resolved trait.
334 Of the form: `{'alias' : 'Configurable.trait'}`
351 Of the form: `{'alias' : 'Configurable.trait'}`
335 flags : dict
352 flags : dict
336 A dict of flags, keyed by str name. Vaues can be Config objects,
353 A dict of flags, keyed by str name. Vaues can be Config objects,
337 dicts, or "key=value" strings. If Config or dict, when the flag
354 dicts, or "key=value" strings. If Config or dict, when the flag
338 is triggered, The flag is loaded as `self.config.update(m)`.
355 is triggered, The flag is loaded as `self.config.update(m)`.
339
356
340 Returns
357 Returns
341 -------
358 -------
342 config : Config
359 config : Config
343 The resulting Config object.
360 The resulting Config object.
344
361
345 Examples
362 Examples
346 --------
363 --------
347
364
348 >>> from IPython.config.loader import KeyValueConfigLoader
365 >>> from IPython.config.loader import KeyValueConfigLoader
349 >>> cl = KeyValueConfigLoader()
366 >>> cl = KeyValueConfigLoader()
350 >>> cl.load_config(["foo='bar'","A.name='brian'","B.number=0"])
367 >>> cl.load_config(["foo='bar'","A.name='brian'","B.number=0"])
351 {'A': {'name': 'brian'}, 'B': {'number': 0}, 'foo': 'bar'}
368 {'A': {'name': 'brian'}, 'B': {'number': 0}, 'foo': 'bar'}
352 """
369 """
353 self.clear()
370 self.clear()
354 if argv is None:
371 if argv is None:
355 argv = sys.argv[1:]
372 argv = sys.argv[1:]
356 self.argv = argv
373 self.argv = argv
357 self.aliases = aliases or {}
374 self.aliases = aliases or {}
358 self.flags = flags or {}
375 self.flags = flags or {}
359
376
360
377
361 def clear(self):
378 def clear(self):
362 super(KeyValueConfigLoader, self).clear()
379 super(KeyValueConfigLoader, self).clear()
363 self.extra_args = []
380 self.extra_args = []
364
381
365
382
366 def load_config(self, argv=None, aliases=None, flags=None):
383 def load_config(self, argv=None, aliases=None, flags=None):
367 """Parse the configuration and generate the Config object.
384 """Parse the configuration and generate the Config object.
368
385
369 After loading, any arguments that are not key-value or
386 After loading, any arguments that are not key-value or
370 flags will be stored in self.extra_args - a list of
387 flags will be stored in self.extra_args - a list of
371 unparsed command-line arguments. This is used for
388 unparsed command-line arguments. This is used for
372 arguments such as input files or subcommands.
389 arguments such as input files or subcommands.
373
390
374 Parameters
391 Parameters
375 ----------
392 ----------
376 argv : list, optional
393 argv : list, optional
377 A list that has the form of sys.argv[1:] which has unicode
394 A list that has the form of sys.argv[1:] which has unicode
378 elements of the form u"key=value". If this is None (default),
395 elements of the form u"key=value". If this is None (default),
379 then self.argv will be used.
396 then self.argv will be used.
380 aliases : dict
397 aliases : dict
381 A dict of aliases for configurable traits.
398 A dict of aliases for configurable traits.
382 Keys are the short aliases, Values are the resolved trait.
399 Keys are the short aliases, Values are the resolved trait.
383 Of the form: `{'alias' : 'Configurable.trait'}`
400 Of the form: `{'alias' : 'Configurable.trait'}`
384 flags : dict
401 flags : dict
385 A dict of flags, keyed by str name. Values can be Config objects
402 A dict of flags, keyed by str name. Values can be Config objects
386 or dicts. When the flag is triggered, The config is loaded as
403 or dicts. When the flag is triggered, The config is loaded as
387 `self.config.update(cfg)`.
404 `self.config.update(cfg)`.
388 """
405 """
389 from IPython.config.configurable import Configurable
406 from IPython.config.configurable import Configurable
390
407
391 self.clear()
408 self.clear()
392 if argv is None:
409 if argv is None:
393 argv = self.argv
410 argv = self.argv
394 if aliases is None:
411 if aliases is None:
395 aliases = self.aliases
412 aliases = self.aliases
396 if flags is None:
413 if flags is None:
397 flags = self.flags
414 flags = self.flags
398
415
399 for item in argv:
416 for item in argv:
400 if kv_pattern.match(item):
417 if kv_pattern.match(item):
401 lhs,rhs = item.split('=',1)
418 lhs,rhs = item.split('=',1)
402 # Substitute longnames for aliases.
419 # Substitute longnames for aliases.
403 if lhs in aliases:
420 if lhs in aliases:
404 lhs = aliases[lhs]
421 lhs = aliases[lhs]
405 exec_str = 'self.config.' + lhs + '=' + rhs
422 exec_str = 'self.config.' + lhs + '=' + rhs
406 try:
423 try:
407 # Try to see if regular Python syntax will work. This
424 # Try to see if regular Python syntax will work. This
408 # won't handle strings as the quote marks are removed
425 # won't handle strings as the quote marks are removed
409 # by the system shell.
426 # by the system shell.
410 exec exec_str in locals(), globals()
427 exec exec_str in locals(), globals()
411 except (NameError, SyntaxError):
428 except (NameError, SyntaxError):
412 # This case happens if the rhs is a string but without
429 # This case happens if the rhs is a string but without
413 # the quote marks. We add the quote marks and see if
430 # the quote marks. We add the quote marks and see if
414 # it succeeds. If it still fails, we let it raise.
431 # it succeeds. If it still fails, we let it raise.
415 exec_str = 'self.config.' + lhs + '="' + rhs + '"'
432 exec_str = 'self.config.' + lhs + '="' + rhs + '"'
416 exec exec_str in locals(), globals()
433 exec exec_str in locals(), globals()
417 elif flag_pattern.match(item):
434 elif flag_pattern.match(item):
418 # trim leading '--'
435 # trim leading '--'
419 m = item[2:]
436 m = item[2:]
420 cfg,_ = flags.get(m, (None,None))
437 cfg,_ = flags.get(m, (None,None))
421 if cfg is None:
438 if cfg is None:
422 raise ArgumentError("Unrecognized flag: %r"%item)
439 raise ArgumentError("Unrecognized flag: %r"%item)
423 elif isinstance(cfg, (dict, Config)):
440 elif isinstance(cfg, (dict, Config)):
424 # don't clobber whole config sections, update
441 # don't clobber whole config sections, update
425 # each section from config:
442 # each section from config:
426 for sec,c in cfg.iteritems():
443 for sec,c in cfg.iteritems():
427 self.config[sec].update(c)
444 self.config[sec].update(c)
428 else:
445 else:
429 raise ValueError("Invalid flag: %r"%flag)
446 raise ValueError("Invalid flag: %r"%flag)
430 elif item.startswith('-'):
447 elif item.startswith('-'):
431 # this shouldn't ever be valid
448 # this shouldn't ever be valid
432 raise ArgumentError("Invalid argument: %r"%item)
449 raise ArgumentError("Invalid argument: %r"%item)
433 else:
450 else:
434 # keep all args that aren't valid in a list,
451 # keep all args that aren't valid in a list,
435 # in case our parent knows what to do with them.
452 # in case our parent knows what to do with them.
436 self.extra_args.append(item)
453 self.extra_args.append(item)
437 return self.config
454 return self.config
438
455
439 class ArgParseConfigLoader(CommandLineConfigLoader):
456 class ArgParseConfigLoader(CommandLineConfigLoader):
440 """A loader that uses the argparse module to load from the command line."""
457 """A loader that uses the argparse module to load from the command line."""
441
458
442 def __init__(self, argv=None, *parser_args, **parser_kw):
459 def __init__(self, argv=None, *parser_args, **parser_kw):
443 """Create a config loader for use with argparse.
460 """Create a config loader for use with argparse.
444
461
445 Parameters
462 Parameters
446 ----------
463 ----------
447
464
448 argv : optional, list
465 argv : optional, list
449 If given, used to read command-line arguments from, otherwise
466 If given, used to read command-line arguments from, otherwise
450 sys.argv[1:] is used.
467 sys.argv[1:] is used.
451
468
452 parser_args : tuple
469 parser_args : tuple
453 A tuple of positional arguments that will be passed to the
470 A tuple of positional arguments that will be passed to the
454 constructor of :class:`argparse.ArgumentParser`.
471 constructor of :class:`argparse.ArgumentParser`.
455
472
456 parser_kw : dict
473 parser_kw : dict
457 A tuple of keyword arguments that will be passed to the
474 A tuple of keyword arguments that will be passed to the
458 constructor of :class:`argparse.ArgumentParser`.
475 constructor of :class:`argparse.ArgumentParser`.
459
476
460 Returns
477 Returns
461 -------
478 -------
462 config : Config
479 config : Config
463 The resulting Config object.
480 The resulting Config object.
464 """
481 """
465 super(CommandLineConfigLoader, self).__init__()
482 super(CommandLineConfigLoader, self).__init__()
466 if argv == None:
483 if argv == None:
467 argv = sys.argv[1:]
484 argv = sys.argv[1:]
468 self.argv = argv
485 self.argv = argv
469 self.parser_args = parser_args
486 self.parser_args = parser_args
470 self.version = parser_kw.pop("version", None)
487 self.version = parser_kw.pop("version", None)
471 kwargs = dict(argument_default=argparse.SUPPRESS)
488 kwargs = dict(argument_default=argparse.SUPPRESS)
472 kwargs.update(parser_kw)
489 kwargs.update(parser_kw)
473 self.parser_kw = kwargs
490 self.parser_kw = kwargs
474
491
475 def load_config(self, argv=None):
492 def load_config(self, argv=None):
476 """Parse command line arguments and return as a Config object.
493 """Parse command line arguments and return as a Config object.
477
494
478 Parameters
495 Parameters
479 ----------
496 ----------
480
497
481 args : optional, list
498 args : optional, list
482 If given, a list with the structure of sys.argv[1:] to parse
499 If given, a list with the structure of sys.argv[1:] to parse
483 arguments from. If not given, the instance's self.argv attribute
500 arguments from. If not given, the instance's self.argv attribute
484 (given at construction time) is used."""
501 (given at construction time) is used."""
485 self.clear()
502 self.clear()
486 if argv is None:
503 if argv is None:
487 argv = self.argv
504 argv = self.argv
488 self._create_parser()
505 self._create_parser()
489 self._parse_args(argv)
506 self._parse_args(argv)
490 self._convert_to_config()
507 self._convert_to_config()
491 return self.config
508 return self.config
492
509
493 def get_extra_args(self):
510 def get_extra_args(self):
494 if hasattr(self, 'extra_args'):
511 if hasattr(self, 'extra_args'):
495 return self.extra_args
512 return self.extra_args
496 else:
513 else:
497 return []
514 return []
498
515
499 def _create_parser(self):
516 def _create_parser(self):
500 self.parser = ArgumentParser(*self.parser_args, **self.parser_kw)
517 self.parser = ArgumentParser(*self.parser_args, **self.parser_kw)
501 self._add_arguments()
518 self._add_arguments()
502
519
503 def _add_arguments(self):
520 def _add_arguments(self):
504 raise NotImplementedError("subclasses must implement _add_arguments")
521 raise NotImplementedError("subclasses must implement _add_arguments")
505
522
506 def _parse_args(self, args):
523 def _parse_args(self, args):
507 """self.parser->self.parsed_data"""
524 """self.parser->self.parsed_data"""
508 # decode sys.argv to support unicode command-line options
525 # decode sys.argv to support unicode command-line options
509 uargs = []
526 uargs = []
510 for a in args:
527 for a in args:
511 if isinstance(a, str):
528 if isinstance(a, str):
512 # don't decode if we already got unicode
529 # don't decode if we already got unicode
513 a = a.decode(sys.stdin.encoding or
530 a = a.decode(sys.stdin.encoding or
514 sys.getdefaultencoding())
531 sys.getdefaultencoding())
515 uargs.append(a)
532 uargs.append(a)
516 self.parsed_data, self.extra_args = self.parser.parse_known_args(uargs)
533 self.parsed_data, self.extra_args = self.parser.parse_known_args(uargs)
517
534
518 def _convert_to_config(self):
535 def _convert_to_config(self):
519 """self.parsed_data->self.config"""
536 """self.parsed_data->self.config"""
520 for k, v in vars(self.parsed_data).iteritems():
537 for k, v in vars(self.parsed_data).iteritems():
521 exec_str = 'self.config.' + k + '= v'
538 exec_str = 'self.config.' + k + '= v'
522 exec exec_str in locals(), globals()
539 exec exec_str in locals(), globals()
523
540
524
541
@@ -1,26 +1,25 b''
1 c = get_config()
1 c = get_config()
2 app = c.IPythonApp
2 app = c.InteractiveShellApp
3
3
4 # This can be used at any point in a config file to load a sub config
4 # This can be used at any point in a config file to load a sub config
5 # and merge it into the current one.
5 # and merge it into the current one.
6 import os
6 load_subconfig('ipython_config.py', profile='default')
7 load_subconfig(os.path.join('..','profile_default', 'ipython_config.py'))
8
7
9 lines = """
8 lines = """
10 from IPython.parallel import *
9 from IPython.parallel import *
11 """
10 """
12
11
13 # You have to make sure that attributes that are containers already
12 # You have to make sure that attributes that are containers already
14 # exist before using them. Simple assigning a new list will override
13 # exist before using them. Simple assigning a new list will override
15 # all previous values.
14 # all previous values.
16 if hasattr(app, 'exec_lines'):
15 if hasattr(app, 'exec_lines'):
17 app.exec_lines.append(lines)
16 app.exec_lines.append(lines)
18 else:
17 else:
19 app.exec_lines = [lines]
18 app.exec_lines = [lines]
20
19
21 # Load the parallelmagic extension to enable %result, %px, %autopx magics.
20 # Load the parallelmagic extension to enable %result, %px, %autopx magics.
22 if hasattr(app, 'extensions'):
21 if hasattr(app, 'extensions'):
23 app.extensions.append('parallelmagic')
22 app.extensions.append('parallelmagic')
24 else:
23 else:
25 app.extensions = ['parallelmagic']
24 app.extensions = ['parallelmagic']
26
25
@@ -1,22 +1,21 b''
1 c = get_config()
1 c = get_config()
2 app = c.IPythonApp
2 app = c.InteractiveShellApp
3
3
4 # This can be used at any point in a config file to load a sub config
4 # This can be used at any point in a config file to load a sub config
5 # and merge it into the current one.
5 # and merge it into the current one.
6 import os
6 load_subconfig('ipython_config.py', profile='default')
7 load_subconfig(os.path.join('..','profile_default', 'ipython_config.py'))
8
7
9 lines = """
8 lines = """
10 import cmath
9 import cmath
11 from math import *
10 from math import *
12 """
11 """
13
12
14 # You have to make sure that attributes that are containers already
13 # You have to make sure that attributes that are containers already
15 # exist before using them. Simple assigning a new list will override
14 # exist before using them. Simple assigning a new list will override
16 # all previous values.
15 # all previous values.
17
16
18 if hasattr(app, 'exec_lines'):
17 if hasattr(app, 'exec_lines'):
19 app.exec_lines.append(lines)
18 app.exec_lines.append(lines)
20 else:
19 else:
21 app.exec_lines = [lines]
20 app.exec_lines = [lines]
22
21
@@ -1,24 +1,23 b''
1 c = get_config()
1 c = get_config()
2 app = c.IPythonApp
2 app = c.InteractiveShellApp
3
3
4 # This can be used at any point in a config file to load a sub config
4 # This can be used at any point in a config file to load a sub config
5 # and merge it into the current one.
5 # and merge it into the current one.
6 import os
6 load_subconfig('ipython_config.py', profile='default')
7 load_subconfig(os.path.join('..','profile_default', 'ipython_config.py'))
8
7
9 lines = """
8 lines = """
10 import matplotlib
9 import matplotlib
11 %gui qt
10 %gui qt
12 matplotlib.use('qtagg')
11 matplotlib.use('qtagg')
13 matplotlib.interactive(True)
12 matplotlib.interactive(True)
14 from matplotlib import pyplot as plt
13 from matplotlib import pyplot as plt
15 from matplotlib.pyplot import *
14 from matplotlib.pyplot import *
16 """
15 """
17
16
18 # You have to make sure that attributes that are containers already
17 # You have to make sure that attributes that are containers already
19 # exist before using them. Simple assigning a new list will override
18 # exist before using them. Simple assigning a new list will override
20 # all previous values.
19 # all previous values.
21 if hasattr(app, 'exec_lines'):
20 if hasattr(app, 'exec_lines'):
22 app.exec_lines.append(lines)
21 app.exec_lines.append(lines)
23 else:
22 else:
24 app.exec_lines = [lines] No newline at end of file
23 app.exec_lines = [lines]
@@ -1,31 +1,30 b''
1 c = get_config()
1 c = get_config()
2 app = c.IPythonApp
2 app = c.InteractiveShellApp
3
3
4 # This can be used at any point in a config file to load a sub config
4 # This can be used at any point in a config file to load a sub config
5 # and merge it into the current one.
5 # and merge it into the current one.
6 import os
6 load_subconfig('ipython_config.py', profile='default')
7 load_subconfig(os.path.join('..','profile_default', 'ipython_config.py'))
8
7
9 c.InteractiveShell.prompt_in1 = '\C_LightGreen\u@\h\C_LightBlue[\C_LightCyan\Y1\C_LightBlue]\C_Green|\#> '
8 c.InteractiveShell.prompt_in1 = '\C_LightGreen\u@\h\C_LightBlue[\C_LightCyan\Y1\C_LightBlue]\C_Green|\#> '
10 c.InteractiveShell.prompt_in2 = '\C_Green|\C_LightGreen\D\C_Green> '
9 c.InteractiveShell.prompt_in2 = '\C_Green|\C_LightGreen\D\C_Green> '
11 c.InteractiveShell.prompt_out = '<\#> '
10 c.InteractiveShell.prompt_out = '<\#> '
12
11
13 c.InteractiveShell.prompts_pad_left = True
12 c.InteractiveShell.prompts_pad_left = True
14
13
15 c.InteractiveShell.separate_in = ''
14 c.InteractiveShell.separate_in = ''
16 c.InteractiveShell.separate_out = ''
15 c.InteractiveShell.separate_out = ''
17 c.InteractiveShell.separate_out2 = ''
16 c.InteractiveShell.separate_out2 = ''
18
17
19 c.PrefilterManager.multi_line_specials = True
18 c.PrefilterManager.multi_line_specials = True
20
19
21 lines = """
20 lines = """
22 %rehashx
21 %rehashx
23 """
22 """
24
23
25 # You have to make sure that attributes that are containers already
24 # You have to make sure that attributes that are containers already
26 # exist before using them. Simple assigning a new list will override
25 # exist before using them. Simple assigning a new list will override
27 # all previous values.
26 # all previous values.
28 if hasattr(app, 'exec_lines'):
27 if hasattr(app, 'exec_lines'):
29 app.exec_lines.append(lines)
28 app.exec_lines.append(lines)
30 else:
29 else:
31 app.exec_lines = [lines] No newline at end of file
30 app.exec_lines = [lines]
@@ -1,31 +1,30 b''
1 c = get_config()
1 c = get_config()
2 app = c.IPythonApp
2 app = c.InteractiveShellApp
3
3
4 # This can be used at any point in a config file to load a sub config
4 # This can be used at any point in a config file to load a sub config
5 # and merge it into the current one.
5 # and merge it into the current one.
6 import os
6 load_subconfig('ipython_config.py', profile='default')
7 load_subconfig(os.path.join('..','profile_default', 'ipython_config.py'))
8
7
9 lines = """
8 lines = """
10 from __future__ import division
9 from __future__ import division
11 from sympy import *
10 from sympy import *
12 x, y, z = symbols('xyz')
11 x, y, z = symbols('xyz')
13 k, m, n = symbols('kmn', integer=True)
12 k, m, n = symbols('kmn', integer=True)
14 f, g, h = map(Function, 'fgh')
13 f, g, h = map(Function, 'fgh')
15 """
14 """
16
15
17 # You have to make sure that attributes that are containers already
16 # You have to make sure that attributes that are containers already
18 # exist before using them. Simple assigning a new list will override
17 # exist before using them. Simple assigning a new list will override
19 # all previous values.
18 # all previous values.
20
19
21 if hasattr(app, 'exec_lines'):
20 if hasattr(app, 'exec_lines'):
22 app.exec_lines.append(lines)
21 app.exec_lines.append(lines)
23 else:
22 else:
24 app.exec_lines = [lines]
23 app.exec_lines = [lines]
25
24
26 # Load the sympy_printing extension to enable nice printing of sympy expr's.
25 # Load the sympy_printing extension to enable nice printing of sympy expr's.
27 if hasattr(app, 'extensions'):
26 if hasattr(app, 'extensions'):
28 app.extensions.append('sympy_printing')
27 app.extensions.append('sympyprinting')
29 else:
28 else:
30 app.extensions = ['sympy_printing']
29 app.extensions = ['sympyprinting']
31
30
@@ -1,220 +1,219 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 An application for managing IPython profiles.
3 An application for managing IPython profiles.
4
4
5 To be invoked as the `ipython profile` subcommand.
5 To be invoked as the `ipython profile` subcommand.
6
6
7 Authors:
7 Authors:
8
8
9 * Min RK
9 * Min RK
10
10
11 """
11 """
12
12
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14 # Copyright (C) 2008-2011 The IPython Development Team
14 # Copyright (C) 2008-2011 The IPython Development Team
15 #
15 #
16 # Distributed under the terms of the BSD License. The full license is in
16 # Distributed under the terms of the BSD License. The full license is in
17 # the file COPYING, distributed as part of this software.
17 # the file COPYING, distributed as part of this software.
18 #-----------------------------------------------------------------------------
18 #-----------------------------------------------------------------------------
19
19
20 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
21 # Imports
21 # Imports
22 #-----------------------------------------------------------------------------
22 #-----------------------------------------------------------------------------
23
23
24 import logging
24 import logging
25 import os
25 import os
26
26
27 from IPython.config.application import Application, boolean_flag
27 from IPython.config.application import Application, boolean_flag
28 from IPython.core.application import (
28 from IPython.core.application import (
29 BaseIPythonApplication, base_flags, base_aliases
29 BaseIPythonApplication, base_flags, base_aliases
30 )
30 )
31 from IPython.core.profiledir import ProfileDir
31 from IPython.core.profiledir import ProfileDir
32 from IPython.utils.path import get_ipython_dir
32 from IPython.utils.path import get_ipython_dir
33 from IPython.utils.traitlets import Unicode, Bool, Dict
33 from IPython.utils.traitlets import Unicode, Bool, Dict
34
34
35 #-----------------------------------------------------------------------------
35 #-----------------------------------------------------------------------------
36 # Constants
36 # Constants
37 #-----------------------------------------------------------------------------
37 #-----------------------------------------------------------------------------
38
38
39 create_help = """Create an ipcluster profile by name
39 create_help = """Create an ipcluster profile by name
40
40
41 Create an ipython profile directory by its name or
41 Create an ipython profile directory by its name or
42 profile directory path. Profile directories contain
42 profile directory path. Profile directories contain
43 configuration, log and security related files and are named
43 configuration, log and security related files and are named
44 using the convention 'profile_<name>'. By default they are
44 using the convention 'profile_<name>'. By default they are
45 located in your ipython directory. Once created, you will
45 located in your ipython directory. Once created, you will
46 can edit the configuration files in the profile
46 can edit the configuration files in the profile
47 directory to configure IPython. Most users will create a
47 directory to configure IPython. Most users will create a
48 cluster directory by profile name,
48 cluster directory by profile name,
49 `ipython profile create myprofile`, which will put the directory
49 `ipython profile create myprofile`, which will put the directory
50 in `<ipython_dir>/profile_myprofile`.
50 in `<ipython_dir>/profile_myprofile`.
51 """
51 """
52 list_help = """List available IPython profiles
52 list_help = """List available IPython profiles
53
53
54 List all available profiles, by profile location, that can
54 List all available profiles, by profile location, that can
55 be found in the current working directly or in the ipython
55 be found in the current working directly or in the ipython
56 directory. Profile directories are named using the convention
56 directory. Profile directories are named using the convention
57 'profile_<profile>'.
57 'profile_<profile>'.
58 """
58 """
59 profile_help = """Manage IPython profiles
59 profile_help = """Manage IPython profiles
60
60
61 Profile directories contain
61 Profile directories contain
62 configuration, log and security related files and are named
62 configuration, log and security related files and are named
63 using the convention 'profile_<name>'. By default they are
63 using the convention 'profile_<name>'. By default they are
64 located in your ipython directory. You can create profiles
64 located in your ipython directory. You can create profiles
65 with `ipython profile create <name>`, or see the profiles you
65 with `ipython profile create <name>`, or see the profiles you
66 already have with `ipython profile list`
66 already have with `ipython profile list`
67
67
68 To get started configuring IPython, simply do:
68 To get started configuring IPython, simply do:
69
69
70 $> ipython profile create
70 $> ipython profile create
71
71
72 and IPython will create the default profile in <ipython_dir>/profile_default,
72 and IPython will create the default profile in <ipython_dir>/profile_default,
73 where you can edit ipython_config.py to start configuring IPython.
73 where you can edit ipython_config.py to start configuring IPython.
74
74
75 """
75 """
76
76
77 #-----------------------------------------------------------------------------
77 #-----------------------------------------------------------------------------
78 # Profile Application Class (for `ipython profile` subcommand)
78 # Profile Application Class (for `ipython profile` subcommand)
79 #-----------------------------------------------------------------------------
79 #-----------------------------------------------------------------------------
80
80
81
81
82
82
83 class ProfileList(Application):
83 class ProfileList(Application):
84 name = u'ipython-profile'
84 name = u'ipython-profile'
85 description = list_help
85 description = list_help
86
86
87 aliases = Dict(dict(
87 aliases = Dict(dict(
88 ipython_dir = 'ProfileList.ipython_dir',
88 ipython_dir = 'ProfileList.ipython_dir',
89 log_level = 'Application.log_level',
89 log_level = 'Application.log_level',
90 ))
90 ))
91 flags = Dict(dict(
91 flags = Dict(dict(
92 debug = ({'Application' : {'log_level' : 0}},
92 debug = ({'Application' : {'log_level' : 0}},
93 "Set log_level to 0, maximizing log output."
93 "Set log_level to 0, maximizing log output."
94 )
94 )
95 ))
95 ))
96 ipython_dir = Unicode(get_ipython_dir(), config=True,
96 ipython_dir = Unicode(get_ipython_dir(), config=True,
97 help="""
97 help="""
98 The name of the IPython directory. This directory is used for logging
98 The name of the IPython directory. This directory is used for logging
99 configuration (through profiles), history storage, etc. The default
99 configuration (through profiles), history storage, etc. The default
100 is usually $HOME/.ipython. This options can also be specified through
100 is usually $HOME/.ipython. This options can also be specified through
101 the environment variable IPYTHON_DIR.
101 the environment variable IPYTHON_DIR.
102 """
102 """
103 )
103 )
104
104
105 def list_profile_dirs(self):
105 def list_profile_dirs(self):
106 # Find the search paths
106 # Find the search paths
107 paths = [os.getcwdu(), self.ipython_dir]
107 paths = [os.getcwdu(), self.ipython_dir]
108
108
109 self.log.warn('Searching for IPython profiles in paths: %r' % paths)
109 self.log.warn('Searching for IPython profiles in paths: %r' % paths)
110 for path in paths:
110 for path in paths:
111 files = os.listdir(path)
111 files = os.listdir(path)
112 for f in files:
112 for f in files:
113 full_path = os.path.join(path, f)
113 full_path = os.path.join(path, f)
114 if os.path.isdir(full_path) and f.startswith('profile_'):
114 if os.path.isdir(full_path) and f.startswith('profile_'):
115 profile = f.split('_',1)[-1]
115 profile = f.split('_',1)[-1]
116 start_cmd = 'ipython profile=%s' % profile
116 start_cmd = 'ipython profile=%s' % profile
117 print start_cmd + " ==> " + full_path
117 print start_cmd + " ==> " + full_path
118
118
119 def start(self):
119 def start(self):
120 self.list_profile_dirs()
120 self.list_profile_dirs()
121
121
122
122
123 create_flags = {}
123 create_flags = {}
124 create_flags.update(base_flags)
124 create_flags.update(base_flags)
125 create_flags.update(boolean_flag('reset', 'ProfileCreate.overwrite',
125 create_flags.update(boolean_flag('reset', 'ProfileCreate.overwrite',
126 "reset config files to defaults", "leave existing config files"))
126 "reset config files to defaults", "leave existing config files"))
127 create_flags.update(boolean_flag('cluster', 'ProfileCreate.cluster',
127 create_flags.update(boolean_flag('cluster', 'ProfileCreate.cluster',
128 "Include parallel computing config files",
128 "Include parallel computing config files",
129 "Don't include parallel computing config files"))
129 "Don't include parallel computing config files"))
130
130
131 class ProfileCreate(BaseIPythonApplication):
131 class ProfileCreate(BaseIPythonApplication):
132 name = u'ipython-profile'
132 name = u'ipython-profile'
133 description = create_help
133 description = create_help
134 auto_create = Bool(True, config=False)
134 auto_create = Bool(True, config=False)
135
135
136 def _copy_config_files_default(self):
136 def _copy_config_files_default(self):
137 return True
137 return True
138
138
139 cluster = Bool(False, config=True,
139 cluster = Bool(False, config=True,
140 help="whether to include parallel computing config files")
140 help="whether to include parallel computing config files")
141 def _cluster_changed(self, name, old, new):
141 def _cluster_changed(self, name, old, new):
142 cluster_files = [ 'ipcontroller_config.py',
142 cluster_files = [ 'ipcontroller_config.py',
143 'ipengine_config.py',
143 'ipengine_config.py',
144 'ipcluster_config.py'
144 'ipcluster_config.py'
145 ]
145 ]
146 if new:
146 if new:
147 for cf in cluster_files:
147 for cf in cluster_files:
148 self.config_files.append(cf)
148 self.config_files.append(cf)
149 else:
149 else:
150 for cf in cluster_files:
150 for cf in cluster_files:
151 if cf in self.config_files:
151 if cf in self.config_files:
152 self.config_files.remove(cf)
152 self.config_files.remove(cf)
153
153
154 def parse_command_line(self, argv):
154 def parse_command_line(self, argv):
155 super(ProfileCreate, self).parse_command_line(argv)
155 super(ProfileCreate, self).parse_command_line(argv)
156 # accept positional arg as profile name
156 # accept positional arg as profile name
157 if self.extra_args:
157 if self.extra_args:
158 self.profile = self.extra_args[0]
158 self.profile = self.extra_args[0]
159
159
160 flags = Dict(create_flags)
160 flags = Dict(create_flags)
161
161
162 aliases = Dict(dict(profile='BaseIPythonApplication.profile'))
162 aliases = Dict(dict(profile='BaseIPythonApplication.profile'))
163
163
164 classes = [ProfileDir]
164 classes = [ProfileDir]
165
165
166 def init_config_files(self):
166 def init_config_files(self):
167 super(ProfileCreate, self).init_config_files()
167 super(ProfileCreate, self).init_config_files()
168 # use local imports, since these classes may import from here
168 # use local imports, since these classes may import from here
169 from IPython.frontend.terminal.ipapp import TerminalIPythonApp
169 from IPython.frontend.terminal.ipapp import TerminalIPythonApp
170 apps = [TerminalIPythonApp]
170 apps = [TerminalIPythonApp]
171 try:
171 try:
172 from IPython.frontend.qt.console.qtconsoleapp import IPythonQtConsoleApp
172 from IPython.frontend.qt.console.qtconsoleapp import IPythonQtConsoleApp
173 except ImportError:
173 except ImportError:
174 pass
174 pass
175 else:
175 else:
176 apps.append(IPythonQtConsoleApp)
176 apps.append(IPythonQtConsoleApp)
177 if self.cluster:
177 if self.cluster:
178 from IPython.parallel.apps.ipcontrollerapp import IPControllerApp
178 from IPython.parallel.apps.ipcontrollerapp import IPControllerApp
179 from IPython.parallel.apps.ipengineapp import IPEngineApp
179 from IPython.parallel.apps.ipengineapp import IPEngineApp
180 from IPython.parallel.apps.ipclusterapp import IPClusterStart
180 from IPython.parallel.apps.ipclusterapp import IPClusterStart
181 from IPython.parallel.apps.iploggerapp import IPLoggerApp
181 from IPython.parallel.apps.iploggerapp import IPLoggerApp
182 apps.extend([
182 apps.extend([
183 IPControllerApp,
183 IPControllerApp,
184 IPEngineApp,
184 IPEngineApp,
185 IPClusterStart,
185 IPClusterStart,
186 IPLoggerApp,
186 IPLoggerApp,
187 ])
187 ])
188 for App in apps:
188 for App in apps:
189 app = App()
189 app = App()
190 app.config.update(self.config)
190 app.config.update(self.config)
191 app.log = self.log
191 app.log = self.log
192 app.overwrite = self.overwrite
192 app.overwrite = self.overwrite
193 app.copy_config_files=True
193 app.copy_config_files=True
194 app.profile = self.profile
194 app.profile = self.profile
195 app.init_profile_dir()
195 app.init_profile_dir()
196 app.init_config_files()
196 app.init_config_files()
197 print 'tic'
198
197
199 def stage_default_config_file(self):
198 def stage_default_config_file(self):
200 pass
199 pass
201
200
202 class ProfileApp(Application):
201 class ProfileApp(Application):
203 name = u'ipython-profile'
202 name = u'ipython-profile'
204 description = profile_help
203 description = profile_help
205
204
206 subcommands = Dict(dict(
205 subcommands = Dict(dict(
207 create = (ProfileCreate, "Create a new profile dir with default config files"),
206 create = (ProfileCreate, "Create a new profile dir with default config files"),
208 list = (ProfileList, "List existing profiles")
207 list = (ProfileList, "List existing profiles")
209 ))
208 ))
210
209
211 def start(self):
210 def start(self):
212 if self.subapp is None:
211 if self.subapp is None:
213 print "No subcommand specified. Must specify one of: %s"%(self.subcommands.keys())
212 print "No subcommand specified. Must specify one of: %s"%(self.subcommands.keys())
214 print
213 print
215 self.print_description()
214 self.print_description()
216 self.print_subcommands()
215 self.print_subcommands()
217 self.exit(1)
216 self.exit(1)
218 else:
217 else:
219 return self.subapp.start()
218 return self.subapp.start()
220
219
General Comments 0
You need to be logged in to leave comments. Login now