chiark / gitweb /
Found in crybaby's working tree.
[chopwood] / config.py
CommitLineData
a2916c06
MW
1### -*-python-*-
2###
3### Configuration handling
4###
5### (c) 2013 Mark Wooding
6###
7
8###----- Licensing notice ---------------------------------------------------
9###
10### This file is part of Chopwood: a password-changing service.
11###
12### Chopwood is free software; you can redistribute it and/or modify
13### it under the terms of the GNU Affero General Public License as
14### published by the Free Software Foundation; either version 3 of the
15### License, or (at your option) any later version.
16###
17### Chopwood is distributed in the hope that it will be useful,
18### but WITHOUT ANY WARRANTY; without even the implied warranty of
19### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20### GNU Affero General Public License for more details.
21###
22### You should have received a copy of the GNU Affero General Public
23### License along with Chopwood; if not, see
24### <http://www.gnu.org/licenses/>.
25
26from __future__ import with_statement
27
28import os as OS; ENV = OS.environ
9fc9351d 29import output as O; OUT = O.OUT
a2916c06
MW
30import sys as SYS
31import types as TY
32
33from auto import PACKAGE, VERSION
34
35### Configuration is done by interpreting a file of Python code. We expect
36### the code to define a number of variables in its global scope. We import
37### a number of identifiers (named in the `EXPORT' list) to this module, and
38### also our entire parent module as `chpwd'.
39
40## Names which ought to be exported to the configuration module.
41_EXPORT = {}
42
43## The configuration module.
44CFG = TY.ModuleType('chpwd_config')
45
46## A list of hooks to call once configuration is complete.
47_HOOKS = []
48def hook(func):
49 """Decorator for post-configuration hooks."""
50 _HOOKS.append(func)
51 return func
52
53## A suitable set of defaults.
54DEFAULTS = {}
55
56def export(*names, **kw):
57 """
58 Export the names to the configuration module from the caller's environment.
59 """
60
61 ## Find the caller's global environment. Please don't try this at home.
62 try: raise Exception
63 except: tb = SYS.exc_info()[2]
64 env = tb.tb_frame.f_back.f_globals
65
66 ## Export things.
67 for name in names:
68 _EXPORT[name] = env[name]
69 _EXPORT.update(kw)
70
71## Some things to export for sure.
72export('PACKAGE', 'VERSION', 'ENV', CONF = SYS.modules[__name__])
73
74def loadconfig(config):
75 """
76 Load the configuration, populating the `CFG' module with settings.
77 """
78
79 ## Make a new module for the configuration, and import ourselves into it.
80 d = CFG.__dict__
81 d.update(_EXPORT)
82 d.update(DEFAULTS)
83
84 ## And run the configuration code.
9fc9351d
MW
85 try:
86 with open(config) as f:
87 exec f in d
88 except IOError, e:
89 OUT.warn("couldn't open configuration file `%s': %s" %
90 (config, e.strerror))
a2916c06
MW
91
92 ## Run the hooks.
93 for func in _HOOKS:
94 func()
95
96###----- That's all, folks --------------------------------------------------