1 """Generic configuration system using unrepr.
2
3 Configuration data may be supplied as a Python dictionary, as a filename,
4 or as an open file object. When you supply a filename or file, Python's
5 builtin ConfigParser is used (with some extensions).
6
7 Namespaces
8 ----------
9
10 Configuration keys are separated into namespaces by the first "." in the key.
11
12 The only key that cannot exist in a namespace is the "environment" entry.
13 This special entry 'imports' other config entries from a template stored in
14 the Config.environments dict.
15
16 You can define your own namespaces to be called when new config is merged
17 by adding a named handler to Config.namespaces. The name can be any string,
18 and the handler must be either a callable or a context manager.
19 """
20
21 try:
22
23 from configparser import ConfigParser
24 except ImportError:
25 from ConfigParser import ConfigParser
26
27 try:
28 set
29 except NameError:
30 from sets import Set as set
31
32 try:
33 basestring
34 except NameError:
35 basestring = str
36
37 try:
38
39 import builtins
40 except ImportError:
41
42 import __builtin__ as builtins
43
44 import operator as _operator
45 import sys
46
47
55
56
58
59 """A dict of config namespace names and handlers.
60
61 Each config entry should begin with a namespace name; the corresponding
62 namespace handler will be called once for each config entry in that
63 namespace, and will be passed two arguments: the config key (with the
64 namespace removed) and the config value.
65
66 Namespace handlers may be any Python callable; they may also be
67 Python 2.5-style 'context managers', in which case their __enter__
68 method should return a callable to be used as the handler.
69 See cherrypy.tools (the Toolbox class) for an example.
70 """
71
73 """Iterate through config and pass it to each namespace handler.
74
75 config
76 A flat dict, where keys use dots to separate
77 namespaces, and values are arbitrary.
78
79 The first name in each config key is used to look up the corresponding
80 namespace handler. For example, a config entry of {'tools.gzip.on': v}
81 will call the 'tools' namespace handler with the args: ('gzip.on', v)
82 """
83
84 ns_confs = {}
85 for k in config:
86 if "." in k:
87 ns, name = k.split(".", 1)
88 bucket = ns_confs.setdefault(ns, {})
89 bucket[name] = config[k]
90
91
92
93
94
95
96
97 for ns, handler in self.items():
98 exit = getattr(handler, "__exit__", None)
99 if exit:
100 callable = handler.__enter__()
101 no_exc = True
102 try:
103 try:
104 for k, v in ns_confs.get(ns, {}).items():
105 callable(k, v)
106 except:
107
108 no_exc = False
109 if exit is None:
110 raise
111 if not exit(*sys.exc_info()):
112 raise
113
114 finally:
115
116 if no_exc and exit:
117 exit(None, None, None)
118 else:
119 for k, v in ns_confs.get(ns, {}).items():
120 handler(k, v)
121
123 return "%s.%s(%s)" % (self.__module__, self.__class__.__name__,
124 dict.__repr__(self))
125
127 newobj = self.__class__()
128 newobj.update(self)
129 return newobj
130 copy = __copy__
131
132
134
135 """A dict-like set of configuration data, with defaults and namespaces.
136
137 May take a file, filename, or dict.
138 """
139
140 defaults = {}
141 environments = {}
142 namespaces = NamespaceSet()
143
144 - def __init__(self, file=None, **kwargs):
150
155
167
179
183
184
186
187 """Sub-class of ConfigParser that keeps the case of options and that
188 raises an exception if the file cannot be read.
189 """
190
193
194 - def read(self, filenames):
195 if isinstance(filenames, basestring):
196 filenames = [filenames]
197 for filename in filenames:
198
199
200
201
202 fp = open(filename)
203 try:
204 self._read(fp, filename)
205 finally:
206 fp.close()
207
208 - def as_dict(self, raw=False, vars=None):
209 """Convert an INI file to a dictionary"""
210
211 result = {}
212 for section in self.sections():
213 if section not in result:
214 result[section] = {}
215 for option in self.options(section):
216 value = self.get(section, option, raw=raw, vars=vars)
217 try:
218 value = unrepr(value)
219 except Exception:
220 x = sys.exc_info()[1]
221 msg = ("Config error in section: %r, option: %r, "
222 "value: %r. Config values must be valid Python." %
223 (section, option, value))
224 raise ValueError(msg, x.__class__.__name__, x.args)
225 result[section][option] = value
226 return result
227
229 if hasattr(file, 'read'):
230 self.readfp(file)
231 else:
232 self.read(file)
233 return self.as_dict()
234
235
236
237
238
240
242 m = getattr(self, 'build_' + o.__class__.__name__, None)
243 if m is None:
244 raise TypeError("unrepr does not recognize %s" %
245 repr(o.__class__.__name__))
246 return m(o)
247
249 """Return a Python2 ast Node compiled from a string."""
250 try:
251 import compiler
252 except ImportError:
253
254
255 return eval(s)
256
257 p = compiler.parse("__tempvalue__ = " + s)
258 return p.getChildren()[1].getChildren()[0].getChildren()[1]
259
261 expr, flags, subs = o.getChildren()
262 expr = self.build(expr)
263 subs = self.build(subs)
264 return expr[subs]
265
267 children = o.getChildren()
268
269 callee = self.build(children[0])
270
271 args = []
272 kwargs = {}
273 for child in children[1:]:
274 class_name = child.__class__.__name__
275
276 if class_name == 'NoneType':
277 continue
278
279 if class_name == 'Keyword':
280 kwargs.update(self.build(child))
281
282 else :
283 args.append(self.build(child))
284 return callee(*args, **kwargs)
285
287 key, value_obj = o.getChildren()
288 value = self.build(value_obj)
289 kw_dict = {key: value}
290 return kw_dict
291
293 return map(self.build, o.getChildren())
294
297
299 d = {}
300 i = iter(map(self.build, o.getChildren()))
301 for el in i:
302 d[el] = i.next()
303 return d
304
307
309 name = o.name
310 if name == 'None':
311 return None
312 if name == 'True':
313 return True
314 if name == 'False':
315 return False
316
317
318 try:
319 return modules(name)
320 except ImportError:
321 pass
322
323
324 try:
325 return getattr(builtins, name)
326 except AttributeError:
327 pass
328
329 raise TypeError("unrepr could not resolve the name %s" % repr(name))
330
332 left, right = map(self.build, o.getChildren())
333 return left + right
334
336 left, right = map(self.build, o.getChildren())
337 return left * right
338
340 parent = self.build(o.expr)
341 return getattr(parent, o.attrname)
342
345
347 return -self.build(o.getChildren()[0])
348
350 return self.build(o.getChildren()[0])
351
352
354
356 m = getattr(self, 'build_' + o.__class__.__name__, None)
357 if m is None:
358 raise TypeError("unrepr does not recognize %s" %
359 repr(o.__class__.__name__))
360 return m(o)
361
363 """Return a Python3 ast Node compiled from a string."""
364 try:
365 import ast
366 except ImportError:
367
368
369 return eval(s)
370
371 p = ast.parse("__tempvalue__ = " + s)
372 return p.body[0].value
373
375 return self.build(o.value)[self.build(o.slice)]
376
378 return self.build(o.value)
379
381 callee = self.build(o.func)
382
383 if o.args is None:
384 args = ()
385 else:
386 args = tuple([self.build(a) for a in o.args])
387
388 if o.starargs is None:
389 starargs = ()
390 else:
391 starargs = self.build(o.starargs)
392
393 if o.kwargs is None:
394 kwargs = {}
395 else:
396 kwargs = self.build(o.kwargs)
397
398 return callee(*(args + starargs), **kwargs)
399
401 return list(map(self.build, o.elts))
402
405
408
412
415
417 name = o.id
418 if name == 'None':
419 return None
420 if name == 'True':
421 return True
422 if name == 'False':
423 return False
424
425
426 try:
427 return modules(name)
428 except ImportError:
429 pass
430
431
432 try:
433 import builtins
434 return getattr(builtins, name)
435 except AttributeError:
436 pass
437
438 raise TypeError("unrepr could not resolve the name %s" % repr(name))
439
442
444 op, operand = map(self.build, [o.op, o.operand])
445 return op(operand)
446
448 left, op, right = map(self.build, [o.left, o.op, o.right])
449 return op(left, right)
450
453
456
459
461 parent = self.build(o.value)
462 return getattr(parent, o.attr)
463
466
467
469 """Return a Python object compiled from a string."""
470 if not s:
471 return s
472 if sys.version_info < (3, 0):
473 b = _Builder2()
474 else:
475 b = _Builder3()
476 obj = b.astnode(s)
477 return b.build(obj)
478
479
481 """Load a module and retrieve a reference to that module."""
482 __import__(modulePath)
483 return sys.modules[modulePath]
484
485
487 """Load a module and retrieve an attribute of that module."""
488
489
490 last_dot = full_attribute_name.rfind(".")
491 attr_name = full_attribute_name[last_dot + 1:]
492 mod_path = full_attribute_name[:last_dot]
493
494 mod = modules(mod_path)
495
496 try:
497 attr = getattr(mod, attr_name)
498 except AttributeError:
499 raise AttributeError("'%s' object has no attribute '%s'"
500 % (mod_path, attr_name))
501
502
503 return attr
504