It's 2012 all up in here
[mediagoblin.git] / mediagoblin / init / config.py
CommitLineData
e2c6436e 1# GNU MediaGoblin -- federated, autonomous media hosting
cf29e8a8 2# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
e2c6436e
CAW
3#
4# This program is free software: you can redistribute it and/or modify
5# it under the terms of the GNU Affero General Public License as published by
6# the Free Software Foundation, either version 3 of the License, or
7# (at your option) any later version.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12# GNU Affero General Public License for more details.
13#
14# You should have received a copy of the GNU Affero General Public License
15# along with this program. If not, see <http://www.gnu.org/licenses/>.
16
17import os
18import pkg_resources
19
4fd487f7 20from configobj import ConfigObj, flatten_errors
e2c6436e
CAW
21from validate import Validator
22
23
24CONFIG_SPEC_PATH = pkg_resources.resource_filename(
25 'mediagoblin', 'config_spec.ini')
26
27
28def _setup_defaults(config, config_path):
29 """
30 Setup DEFAULTS in a config object from an (absolute) config_path.
31 """
32 config.setdefault('DEFAULT', {})
33 config['DEFAULT']['here'] = os.path.dirname(config_path)
34 config['DEFAULT']['__file__'] = config_path
35
36
37def read_mediagoblin_config(config_path, config_spec=CONFIG_SPEC_PATH):
38 """
39 Read a config object from config_path.
40
41 Does automatic value transformation based on the config_spec.
42 Also provides %(__file__)s and %(here)s values of this file and
43 its directory respectively similar to paste deploy.
44
4fd487f7
CAW
45 This function doesn't itself raise any exceptions if validation
46 fails, you'll have to do something
47
e2c6436e
CAW
48 Args:
49 - config_path: path to the config file
50 - config_spec: config file that provides defaults and value types
51 for validation / conversion. Defaults to mediagoblin/config_spec.ini
52
53 Returns:
4fd487f7
CAW
54 A tuple like: (config, validation_result)
55 ... where 'conf' is the parsed config object and 'validation_result'
56 is the information from the validation process.
e2c6436e
CAW
57 """
58 config_path = os.path.abspath(config_path)
59
60 config_spec = ConfigObj(
e5aa1ec6 61 config_spec,
e2c6436e
CAW
62 encoding='UTF8', list_values=False, _inspec=True)
63
64 _setup_defaults(config_spec, config_path)
65
4fd487f7 66 config = ConfigObj(
e2c6436e
CAW
67 config_path,
68 configspec=config_spec,
69 interpolation='ConfigParser')
70
4fd487f7
CAW
71 _setup_defaults(config, config_path)
72
73 # For now the validator just works with the default functions,
74 # but in the future if we want to add additional validation/configuration
75 # functions we'd add them to validator.functions here.
243c3843 76 #
4fd487f7
CAW
77 # See also:
78 # http://www.voidspace.org.uk/python/validate.html#adding-functions
79 validator = Validator()
80 validation_result = config.validate(validator, preserve_errors=True)
81
82 return config, validation_result
83
84
9dba44de 85REPORT_HEADER = u"""\
4fd487f7
CAW
86There were validation problems loading this config file:
87--------------------------------------------------------
88"""
89
90
91def generate_validation_report(config, validation_result):
92 """
93 Generate a report if necessary of problems while validating.
94
95 Returns:
96 Either a string describing for a user the problems validating
97 this config or None if there are no problems.
98 """
99 report = []
100
101 # Organize the report
102 for entry in flatten_errors(config, validation_result):
103 # each entry is a tuple
104 section_list, key, error = entry
105
106 if key is not None:
107 section_list.append(key)
108 else:
109 section_list.append(u'[missing section]')
110
111 section_string = u':'.join(section_list)
e2c6436e 112
4fd487f7
CAW
113 if error == False:
114 # We don't care about missing values for now.
115 continue
e2c6436e 116
4fd487f7 117 report.append(u"%s = %s" % (section_string, error))
e2c6436e 118
4fd487f7
CAW
119 if report:
120 return REPORT_HEADER + u"\n".join(report)
121 else:
122 return None