##// END OF EJS Templates
Changed how config files are loaded....
Brian Granger -
Show More
@@ -1,146 +1,148 b''
1 # Get the config being loaded so we can set attributes on it
2 c = get_config()
3
1 4 #-----------------------------------------------------------------------------
2 5 # Global options
3 6 #-----------------------------------------------------------------------------
4 7
5 # Global.display_banner = True
8 # c.Global.display_banner = True
6 9
7 # Global.classic = False
10 # c.Global.classic = False
8 11
9 # Global.nosep = True
12 # c.Global.nosep = True
10 13
11 14 # Set this to determine the detail of what is logged at startup.
12 15 # The default is 30 and possible values are 0,10,20,30,40,50.
13 # Global.log_level = 30
16 c.Global.log_level = 20
14 17
15 18 # This should be a list of importable Python modules that have an
16 19 # load_in_ipython(ip) method. This method gets called when the extension
17 20 # is loaded. You can put your extensions anywhere they can be imported
18 21 # but we add the extensions subdir of the ipython directory to sys.path
19 22 # during extension loading, so you can put them there as well.
20 # Global.extensions = [
23 # c.Global.extensions = [
21 24 # 'myextension'
22 25 # ]
23 26
24 27 # These lines are run in IPython in the user's namespace after extensions
25 28 # are loaded. They can contain full IPython syntax with magics etc.
26 # Global.exec_lines = [
29 # c.Global.exec_lines = [
27 30 # 'import numpy',
28 31 # 'a = 10; b = 20',
29 32 # '1/0'
30 33 # ]
31 34
32 35 # These files are run in IPython in the user's namespace. Files with a .py
33 36 # extension need to be pure Python. Files with a .ipy extension can have
34 37 # custom IPython syntax (like magics, etc.).
35 38 # These files need to be in the cwd, the ipythondir or be absolute paths.
36 # Global.exec_files = [
39 # c.Global.exec_files = [
37 40 # 'mycode.py',
38 41 # 'fancy.ipy'
39 42 # ]
40 43
41 44 #-----------------------------------------------------------------------------
42 45 # InteractiveShell options
43 46 #-----------------------------------------------------------------------------
44 47
48 # c.InteractiveShell.autocall = 1
45 49
46 # InteractiveShell.autocall = 1
47
48 # InteractiveShell.autoedit_syntax = False
50 # c.InteractiveShell.autoedit_syntax = False
49 51
50 # InteractiveShell.autoindent = True
52 # c.InteractiveShell.autoindent = True
51 53
52 # InteractiveShell.automagic = False
54 # c.InteractiveShell.automagic = False
53 55
54 # InteractiveShell.banner1 = 'This if for overriding the default IPython banner'
56 # c.InteractiveShell.banner1 = 'This if for overriding the default IPython banner'
55 57
56 # InteractiveShell.banner2 = "This is for extra banner text"
58 # c.InteractiveShell.banner2 = "This is for extra banner text"
57 59
58 # InteractiveShell.cache_size = 1000
60 # c.InteractiveShell.cache_size = 1000
59 61
60 # InteractiveShell.colors = 'LightBG'
62 # c.InteractiveShell.colors = 'LightBG'
61 63
62 # InteractiveShell.color_info = True
64 # c.InteractiveShell.color_info = True
63 65
64 # InteractiveShell.confirm_exit = True
66 # c.InteractiveShell.confirm_exit = True
65 67
66 # InteractiveShell.deep_reload = False
68 # c.InteractiveShell.deep_reload = False
67 69
68 # InteractiveShell.editor = 'nano'
70 # c.InteractiveShell.editor = 'nano'
69 71
70 # InteractiveShell.logstart = True
72 # c.InteractiveShell.logstart = True
71 73
72 # InteractiveShell.logfile = 'ipython_log.py'
74 # c.InteractiveShell.logfile = 'ipython_log.py'
73 75
74 # InteractiveShell.logplay = 'mylog.py'
76 # c.InteractiveShell.logplay = 'mylog.py'
75 77
76 # InteractiveShell.object_info_string_level = 0
78 # c.InteractiveShell.object_info_string_level = 0
77 79
78 # InteractiveShell.pager = 'less'
80 # c.InteractiveShell.pager = 'less'
79 81
80 # InteractiveShell.pdb = False
82 # c.InteractiveShell.pdb = False
81 83
82 # InteractiveShell.pprint = True
84 # c.InteractiveShell.pprint = True
83 85
84 # InteractiveShell.prompt_in1 = 'In [\#]: '
85 # InteractiveShell.prompt_in2 = ' .\D.: '
86 # InteractiveShell.prompt_out = 'Out[\#]: '
87 # InteractiveShell.prompts_pad_left = True
86 # c.InteractiveShell.prompt_in1 = 'In [\#]: '
87 # c.InteractiveShell.prompt_in2 = ' .\D.: '
88 # c.InteractiveShell.prompt_out = 'Out[\#]: '
89 # c.InteractiveShell.prompts_pad_left = True
88 90
89 # InteractiveShell.quiet = False
91 # c.InteractiveShell.quiet = False
90 92
91 93 # Readline
92 # InteractiveShell.readline_use = True
94 # c.InteractiveShell.readline_use = True
93 95
94 # InteractiveShell.readline_parse_and_bind = [
96 # c.InteractiveShell.readline_parse_and_bind = [
95 97 # 'tab: complete',
96 98 # '"\C-l": possible-completions',
97 99 # 'set show-all-if-ambiguous on',
98 100 # '"\C-o": tab-insert',
99 101 # '"\M-i": " "',
100 102 # '"\M-o": "\d\d\d\d"',
101 103 # '"\M-I": "\d\d\d\d"',
102 104 # '"\C-r": reverse-search-history',
103 105 # '"\C-s": forward-search-history',
104 106 # '"\C-p": history-search-backward',
105 107 # '"\C-n": history-search-forward',
106 108 # '"\e[A": history-search-backward',
107 109 # '"\e[B": history-search-forward',
108 110 # '"\C-k": kill-line',
109 111 # '"\C-u": unix-line-discard',
110 112 # ]
111 # InteractiveShell.readline_remove_delims = '-/~'
112 # InteractiveShell.readline_merge_completions = True
113 # InteractiveShell.readline_omit_names = 0
113 # c.InteractiveShell.readline_remove_delims = '-/~'
114 # c.InteractiveShell.readline_merge_completions = True
115 # c.InteractiveShell.readline_omit_names = 0
114 116
115 # InteractiveShell.screen_length = 0
117 # c.InteractiveShell.screen_length = 0
116 118
117 # InteractiveShell.separate_in = '\n'
118 # InteractiveShell.separate_out = ''
119 # InteractiveShell.separate_out2 = ''
119 # c.InteractiveShell.separate_in = '\n'
120 # c.InteractiveShell.separate_out = ''
121 # c.InteractiveShell.separate_out2 = ''
120 122
121 # InteractiveShell.system_header = "IPython system call: "
123 # c.InteractiveShell.system_header = "IPython system call: "
122 124
123 # InteractiveShell.system_verbose = True
125 # c.InteractiveShell.system_verbose = True
124 126
125 # InteractiveShell.term_title = False
127 # c.InteractiveShell.term_title = False
126 128
127 # InteractiveShell.wildcards_case_sensitive = True
129 # c.InteractiveShell.wildcards_case_sensitive = True
128 130
129 # InteractiveShell.xmode = 'Context'
131 # c.InteractiveShell.xmode = 'Context'
130 132
131 133 #-----------------------------------------------------------------------------
132 134 # PrefilterManager options
133 135 #-----------------------------------------------------------------------------
134 136
135 # PrefilterManager.multi_line_specials = True
137 # c.PrefilterManager.multi_line_specials = True
136 138
137 139 #-----------------------------------------------------------------------------
138 140 # AliasManager options
139 141 #-----------------------------------------------------------------------------
140 142
141 143 # Do this to enable all defaults
142 # AliasManager.default_aliases = []
144 # c.AliasManager.default_aliases = []
143 145
144 # AliasManager.user_aliases = [
145 # ('foo', 'echo Hi')
146 # c.AliasManager.user_aliases = [
147 # ('foo', 'echo Hi')
146 148 # ] No newline at end of file
@@ -1,328 +1,329 b''
1 1 #!/usr/bin/env python
2 2 # encoding: utf-8
3 3 """A simple configuration system.
4 4
5 5 Authors:
6 6
7 7 * Brian Granger
8 8 """
9 9
10 10 #-----------------------------------------------------------------------------
11 11 # Copyright (C) 2008-2009 The IPython Development Team
12 12 #
13 13 # Distributed under the terms of the BSD License. The full license is in
14 14 # the file COPYING, distributed as part of this software.
15 15 #-----------------------------------------------------------------------------
16 16
17 17 #-----------------------------------------------------------------------------
18 18 # Imports
19 19 #-----------------------------------------------------------------------------
20 20
21 21 import __builtin__
22 22 import os
23 23 import sys
24 24
25 25 from IPython.external import argparse
26 26 from IPython.utils.genutils import filefind
27 27
28 28 #-----------------------------------------------------------------------------
29 29 # Exceptions
30 30 #-----------------------------------------------------------------------------
31 31
32 32
33 33 class ConfigError(Exception):
34 34 pass
35 35
36 36
37 37 class ConfigLoaderError(ConfigError):
38 38 pass
39 39
40 40
41 41 #-----------------------------------------------------------------------------
42 42 # Config class for holding config information
43 43 #-----------------------------------------------------------------------------
44 44
45 45
46 46 class Config(dict):
47 47 """An attribute based dict that can do smart merges."""
48 48
49 49 def __init__(self, *args, **kwds):
50 50 dict.__init__(self, *args, **kwds)
51 51 # This sets self.__dict__ = self, but it has to be done this way
52 52 # because we are also overriding __setattr__.
53 53 dict.__setattr__(self, '__dict__', self)
54 54
55 55 def _merge(self, other):
56 56 to_update = {}
57 57 for k, v in other.items():
58 58 if not self.has_key(k):
59 59 to_update[k] = v
60 60 else: # I have this key
61 61 if isinstance(v, Config):
62 62 # Recursively merge common sub Configs
63 63 self[k]._merge(v)
64 64 else:
65 65 # Plain updates for non-Configs
66 66 to_update[k] = v
67 67
68 68 self.update(to_update)
69 69
70 70 def _is_section_key(self, key):
71 71 if key[0].upper()==key[0] and not key.startswith('_'):
72 72 return True
73 73 else:
74 74 return False
75 75
76 76 def has_key(self, key):
77 77 if self._is_section_key(key):
78 78 return True
79 79 else:
80 80 return dict.has_key(self, key)
81 81
82 82 def _has_section(self, key):
83 83 if self._is_section_key(key):
84 84 if dict.has_key(self, key):
85 85 return True
86 86 return False
87 87
88 88 def copy(self):
89 89 return type(self)(dict.copy(self))
90 90
91 91 def __copy__(self):
92 92 return self.copy()
93 93
94 94 def __deepcopy__(self, memo):
95 95 import copy
96 96 return type(self)(copy.deepcopy(self.items()))
97 97
98 98 def __getitem__(self, key):
99 99 # Because we use this for an exec namespace, we need to delegate
100 100 # the lookup of names in __builtin__ to itself. This means
101 101 # that you can't have section or attribute names that are
102 102 # builtins.
103 103 try:
104 104 return getattr(__builtin__, key)
105 105 except AttributeError:
106 106 pass
107 107 if self._is_section_key(key):
108 108 try:
109 109 return dict.__getitem__(self, key)
110 110 except KeyError:
111 111 c = Config()
112 112 dict.__setitem__(self, key, c)
113 113 return c
114 114 else:
115 115 return dict.__getitem__(self, key)
116 116
117 117 def __setitem__(self, key, value):
118 118 # Don't allow names in __builtin__ to be modified.
119 119 if hasattr(__builtin__, key):
120 120 raise ConfigError('Config variable names cannot have the same name '
121 121 'as a Python builtin: %s' % key)
122 122 if self._is_section_key(key):
123 123 if not isinstance(value, Config):
124 124 raise ValueError('values whose keys begin with an uppercase '
125 125 'char must be Config instances: %r, %r' % (key, value))
126 126 else:
127 127 dict.__setitem__(self, key, value)
128 128
129 129 def __getattr__(self, key):
130 130 try:
131 131 return self.__getitem__(key)
132 132 except KeyError, e:
133 133 raise AttributeError(e)
134 134
135 135 def __setattr__(self, key, value):
136 136 try:
137 137 self.__setitem__(key, value)
138 138 except KeyError, e:
139 139 raise AttributeError(e)
140 140
141 141 def __delattr__(self, key):
142 142 try:
143 143 dict.__delitem__(self, key)
144 144 except KeyError, e:
145 145 raise AttributeError(e)
146 146
147 147
148 148 #-----------------------------------------------------------------------------
149 149 # Config loading classes
150 150 #-----------------------------------------------------------------------------
151 151
152 152
153 153 class ConfigLoader(object):
154 154 """A object for loading configurations from just about anywhere.
155 155
156 156 The resulting configuration is packaged as a :class:`Struct`.
157 157
158 158 Notes
159 159 -----
160 160 A :class:`ConfigLoader` does one thing: load a config from a source
161 161 (file, command line arguments) and returns the data as a :class:`Struct`.
162 162 There are lots of things that :class:`ConfigLoader` does not do. It does
163 163 not implement complex logic for finding config files. It does not handle
164 164 default values or merge multiple configs. These things need to be
165 165 handled elsewhere.
166 166 """
167 167
168 168 def __init__(self):
169 169 """A base class for config loaders.
170 170
171 171 Examples
172 172 --------
173 173
174 174 >>> cl = ConfigLoader()
175 175 >>> config = cl.load_config()
176 176 >>> config
177 177 {}
178 178 """
179 179 self.clear()
180 180
181 181 def clear(self):
182 182 self.config = Config()
183 183
184 184 def load_config(self):
185 185 """Load a config from somewhere, return a Struct.
186 186
187 187 Usually, this will cause self.config to be set and then returned.
188 188 """
189 189 return self.config
190 190
191 191
192 192 class FileConfigLoader(ConfigLoader):
193 193 """A base class for file based configurations.
194 194
195 195 As we add more file based config loaders, the common logic should go
196 196 here.
197 197 """
198 198 pass
199 199
200 200
201 201 class PyFileConfigLoader(FileConfigLoader):
202 202 """A config loader for pure python files.
203 203
204 204 This calls execfile on a plain python file and looks for attributes
205 205 that are all caps. These attribute are added to the config Struct.
206 206 """
207 207
208 208 def __init__(self, filename, path=None):
209 209 """Build a config loader for a filename and path.
210 210
211 211 Parameters
212 212 ----------
213 213 filename : str
214 214 The file name of the config file.
215 215 path : str, list, tuple
216 216 The path to search for the config file on, or a sequence of
217 217 paths to try in order.
218 218 """
219 219 super(PyFileConfigLoader, self).__init__()
220 220 self.filename = filename
221 221 self.path = path
222 222 self.full_filename = ''
223 223 self.data = None
224 224
225 225 def load_config(self):
226 226 """Load the config from a file and return it as a Struct."""
227 227 self._find_file()
228 228 self._read_file_as_dict()
229 229 self._convert_to_config()
230 230 return self.config
231 231
232 232 def _find_file(self):
233 233 """Try to find the file by searching the paths."""
234 234 self.full_filename = filefind(self.filename, self.path)
235 235
236 236 def _read_file_as_dict(self):
237 237 """Load the config file into self.config, with recursive loading."""
238 238 # This closure is made available in the namespace that is used
239 239 # to exec the config file. This allows users to call
240 240 # load_subconfig('myconfig.py') to load config files recursively.
241 241 # It needs to be a closure because it has references to self.path
242 242 # and self.config. The sub-config is loaded with the same path
243 243 # as the parent, but it uses an empty config which is then merged
244 244 # with the parents.
245 245 def load_subconfig(fname):
246 246 loader = PyFileConfigLoader(fname, self.path)
247 247 sub_config = loader.load_config()
248 248 self.config._merge(sub_config)
249 249
250 self.config.load_subconfig = load_subconfig
251 try:
252 execfile(self.full_filename, self.config)
253 finally:
254 del self.config.load_subconfig
255 del self.config['__builtins__']
250 # Again, this needs to be a closure and should be used in config
251 # files to get the config being loaded.
252 def get_config():
253 return self.config
254
255 namespace = dict(load_subconfig=load_subconfig, get_config=get_config)
256 execfile(self.full_filename, namespace)
256 257
257 258 def _convert_to_config(self):
258 259 if self.data is None:
259 260 ConfigLoaderError('self.data does not exist')
260 261
261 262
262 263 class CommandLineConfigLoader(ConfigLoader):
263 264 """A config loader for command line arguments.
264 265
265 266 As we add more command line based loaders, the common logic should go
266 267 here.
267 268 """
268 269
269 270
270 271 class NoConfigDefault(object): pass
271 272 NoConfigDefault = NoConfigDefault()
272 273
273 274 class ArgParseConfigLoader(CommandLineConfigLoader):
274 275
275 276 # arguments = [(('-f','--file'),dict(type=str,dest='file'))]
276 277 arguments = ()
277 278
278 279 def __init__(self, *args, **kw):
279 280 """Create a config loader for use with argparse.
280 281
281 282 The args and kwargs arguments here are passed onto the constructor
282 283 of :class:`argparse.ArgumentParser`.
283 284 """
284 285 super(CommandLineConfigLoader, self).__init__()
285 286 self.args = args
286 287 self.kw = kw
287 288
288 289 def load_config(self, args=None):
289 290 """Parse command line arguments and return as a Struct."""
290 291 self._create_parser()
291 292 self._parse_args(args)
292 293 self._convert_to_config()
293 294 return self.config
294 295
295 296 def get_extra_args(self):
296 297 if hasattr(self, 'extra_args'):
297 298 return self.extra_args
298 299 else:
299 300 return []
300 301
301 302 def _create_parser(self):
302 303 self.parser = argparse.ArgumentParser(*self.args, **self.kw)
303 304 self._add_arguments()
304 305 self._add_other_arguments()
305 306
306 307 def _add_other_arguments(self):
307 308 pass
308 309
309 310 def _add_arguments(self):
310 311 for argument in self.arguments:
311 312 if not argument[1].has_key('default'):
312 313 argument[1]['default'] = NoConfigDefault
313 314 self.parser.add_argument(*argument[0],**argument[1])
314 315
315 316 def _parse_args(self, args=None):
316 317 """self.parser->self.parsed_data"""
317 318 if args is None:
318 319 self.parsed_data, self.extra_args = self.parser.parse_known_args()
319 320 else:
320 321 self.parsed_data, self.extra_args = self.parser.parse_known_args(args)
321 322
322 323 def _convert_to_config(self):
323 324 """self.parsed_data->self.config"""
324 325 for k, v in vars(self.parsed_data).items():
325 326 if v is not NoConfigDefault:
326 327 exec_str = 'self.config.' + k + '= v'
327 328 exec exec_str in locals(), globals()
328 329
@@ -1,17 +1,19 b''
1 c = get_config()
2
1 3 # This can be used at any point in a config file to load a sub config
2 4 # and merge it into the current one.
3 5 load_subconfig('ipython_config.py')
4 6
5 7 lines = """
6 8 import cmath
7 9 from math import *
8 10 """
9 11
10 12 # You have to make sure that attributes that are containers already
11 13 # exist before using them. Simple assigning a new list will override
12 14 # all previous values.
13 if hasattr(Global, 'exec_lines'):
14 Global.exec_lines.append(lines)
15 if hasattr(c.Global, 'exec_lines'):
16 c.Global.exec_lines.append(lines)
15 17 else:
16 Global.exec_lines = [lines]
18 c.Global.exec_lines = [lines]
17 19
@@ -1,18 +1,20 b''
1 c = get_config()
2
1 3 # This can be used at any point in a config file to load a sub config
2 4 # and merge it into the current one.
3 5 load_subconfig('ipython_config.py')
4 6
5 7 lines = """
6 8 import numpy
7 9 import scipy
8 10 import numpy as np
9 11 import scipy as sp
10 12 """
11 13
12 14 # You have to make sure that attributes that are containers already
13 15 # exist before using them. Simple assigning a new list will override
14 16 # all previous values.
15 if hasattr(Global, 'exec_lines'):
16 Global.exec_lines.append(lines)
17 if hasattr(c.Global, 'exec_lines'):
18 c.Global.exec_lines.append(lines)
17 19 else:
18 Global.exec_lines = [lines] No newline at end of file
20 c.Global.exec_lines = [lines] No newline at end of file
@@ -1,20 +1,22 b''
1 c = get_config()
2
1 3 # This can be used at any point in a config file to load a sub config
2 4 # and merge it into the current one.
3 5 load_subconfig('ipython_config.py')
4 6
5 7 lines = """
6 8 import matplotlib
7 9 %gui -a wx
8 10 matplotlib.use('wxagg')
9 11 matplotlib.interactive(True)
10 12 from matplotlib import pyplot as plt
11 13 from matplotlib.pyplot import *
12 14 """
13 15
14 16 # You have to make sure that attributes that are containers already
15 17 # exist before using them. Simple assigning a new list will override
16 18 # all previous values.
17 if hasattr(Global, 'exec_lines'):
18 Global.exec_lines.append(lines)
19 if hasattr(c.Global, 'exec_lines'):
20 c.Global.exec_lines.append(lines)
19 21 else:
20 Global.exec_lines = [lines] No newline at end of file
22 c.Global.exec_lines = [lines] No newline at end of file
@@ -1,27 +1,29 b''
1 c = get_config()
2
1 3 # This can be used at any point in a config file to load a sub config
2 4 # and merge it into the current one.
3 5 load_subconfig('ipython_config.py')
4 6
5 InteractiveShell.prompt_in1 = '\C_LightGreen\u@\h\C_LightBlue[\C_LightCyan\Y1\C_LightBlue]\C_Green|\#> '
6 InteractiveShell.prompt_in2 = '\C_Green|\C_LightGreen\D\C_Green> '
7 InteractiveShell.prompt_out = '<\#> '
7 c.InteractiveShell.prompt_in1 = '\C_LightGreen\u@\h\C_LightBlue[\C_LightCyan\Y1\C_LightBlue]\C_Green|\#> '
8 c.InteractiveShell.prompt_in2 = '\C_Green|\C_LightGreen\D\C_Green> '
9 c.InteractiveShell.prompt_out = '<\#> '
8 10
9 InteractiveShell.prompts_pad_left = True
11 c.InteractiveShell.prompts_pad_left = True
10 12
11 InteractiveShell.separate_in = ''
12 InteractiveShell.separate_out = ''
13 InteractiveShell.separate_out2 = ''
13 c.InteractiveShell.separate_in = ''
14 c.InteractiveShell.separate_out = ''
15 c.InteractiveShell.separate_out2 = ''
14 16
15 PrefilterManager.multi_line_specials = True
17 c.PrefilterManager.multi_line_specials = True
16 18
17 19 lines = """
18 20 %rehashx
19 21 """
20 22
21 23 # You have to make sure that attributes that are containers already
22 24 # exist before using them. Simple assigning a new list will override
23 25 # all previous values.
24 if hasattr(Global, 'exec_lines'):
25 Global.exec_lines.append(lines)
26 if hasattr(c.Global, 'exec_lines'):
27 c.Global.exec_lines.append(lines)
26 28 else:
27 Global.exec_lines = [lines] No newline at end of file
29 c.Global.exec_lines = [lines] No newline at end of file
@@ -1,19 +1,21 b''
1 c = get_config()
2
1 3 # This can be used at any point in a config file to load a sub config
2 4 # and merge it into the current one.
3 5 load_subconfig('ipython_config.py')
4 6
5 7 lines = """
6 8 from __future__ import division
7 9 from sympy import *
8 10 x, y, z = symbols('xyz')
9 11 k, m, n = symbols('kmn', integer=True)
10 12 f, g, h = map(Function, 'fgh')
11 13 """
12 14
13 15 # You have to make sure that attributes that are containers already
14 16 # exist before using them. Simple assigning a new list will override
15 17 # all previous values.
16 if hasattr(Global, 'exec_lines'):
17 Global.exec_lines.append(lines)
18 if hasattr(c.Global, 'exec_lines'):
19 c.Global.exec_lines.append(lines)
18 20 else:
19 Global.exec_lines = [lines]
21 c.Global.exec_lines = [lines]
General Comments 0
You need to be logged in to leave comments. Login now