##// END OF EJS Templates
ini: only keep default value as comment if the custom value actually is different
Mads Kiilerich -
r7117:06ae370f default
parent child Browse files
Show More
@@ -1,160 +1,162 b''
1 1 # -*- coding: utf-8 -*-
2 2 # This program is free software: you can redistribute it and/or modify
3 3 # it under the terms of the GNU General Public License as published by
4 4 # the Free Software Foundation, either version 3 of the License, or
5 5 # (at your option) any later version.
6 6 #
7 7 # This program is distributed in the hope that it will be useful,
8 8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 10 # GNU General Public License for more details.
11 11 #
12 12 # You should have received a copy of the GNU General Public License
13 13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 14
15 15 """
16 16 kallithea.lib.inifile
17 17 ~~~~~~~~~~~~~~~~~~~~~
18 18
19 19 Handling of .ini files, mainly creating them from Mako templates and adding
20 20 other custom values.
21 21 """
22 22
23 23 import logging
24 24 import re
25 25 import os
26 26
27 27 import mako.template
28 28
29 29
30 30 log = logging.getLogger(__name__)
31 31
32 32
33 33 template_file = os.path.join(
34 34 os.path.dirname(os.path.dirname(os.path.dirname(__file__))),
35 35 'kallithea/lib/paster_commands/template.ini.mako')
36 36
37 37 default_variables = {
38 38 'database_engine': 'sqlite',
39 39 'http_server': 'waitress',
40 40 'host': '127.0.0.1',
41 41 'port': '5000',
42 42 'uuid': lambda: 'VERY-SECRET',
43 43 }
44 44
45 45
46 46 def expand(template, mako_variable_values, settings):
47 47 """Expand mako template and tweak it.
48 48 Not entirely stable for random templates as input, but good enough for our
49 49 single template.
50 50
51 51 >>> template = '''
52 52 ... [first-section]
53 53 ...
54 54 ... variable=${mako_variable}
55 55 ... variable2 =\tvalue after tab
56 56 ... ## This section had some whitespace and stuff
57 57 ...
58 58 ...
59 59 ... # ${mako_function()}
60 60 ... [second-section]
61 61 ... %if conditional_options == 'option-a':
62 62 ... # option a was chosen
63 63 ... %elif conditional_options == 'option-b':
64 64 ... some_variable = "never mind - option-b will not be used anyway ..."
65 65 ... %endif
66 66 ... '''
67 67 >>> selected_mako_conditionals = []
68 68 >>> mako_variable_values = {'mako_variable': 'VALUE', 'mako_function': (lambda: 'FUNCTION RESULT'),
69 69 ... 'conditional_options': 'option-a'}
70 70 >>> settings = { # only partially used
71 71 ... '[first-section]': {'variable2': 'VAL2', 'first_extra': 'EXTRA'},
72 72 ... '[third-section]': {'third_extra': ' 3'},
73 73 ... '[fourth-section]': {'fourth_extra': '4', 'fourth': '"four"'},
74 74 ... }
75 75 >>> print expand(template, mako_variable_values, settings)
76 76 <BLANKLINE>
77 77 [first-section]
78 78 <BLANKLINE>
79 79 variable=VALUE
80 80 #variable2 = value after tab
81 81 variable2 = VAL2
82 82 <BLANKLINE>
83 83 first_extra = EXTRA
84 84 <BLANKLINE>
85 85 <BLANKLINE>
86 86 # FUNCTION RESULT
87 87 [second-section]
88 88 # option a was chosen
89 89 <BLANKLINE>
90 90 [fourth-section]
91 91 fourth = "four"
92 92 fourth_extra = 4
93 93 <BLANKLINE>
94 94 [third-section]
95 95 third_extra = 3
96 96 <BLANKLINE>
97 97 """
98 98 mako_variables = dict(default_variables)
99 99 mako_variables.update(mako_variable_values or {})
100 100 settings = dict((k, dict(v)) for k, v in settings.items()) # deep copy before mutating
101 101
102 102 ini_lines = mako.template.Template(template).render(**mako_variables)
103 103
104 104 def process_section(m):
105 105 """process a ini section, replacing values as necessary"""
106 106 sectionname, lines = m.groups()
107 107 if sectionname in settings:
108 108 section_settings = settings.pop(sectionname)
109 109
110 110 def process_line(m):
111 111 """process a section line and update value if necessary"""
112 112 key, value = m.groups()
113 113 line = m.group(0)
114 114 if key in section_settings:
115 new_line = '%s = %s' % (key, section_settings.pop(key))
116 if new_line != line:
115 117 # keep old entry as example - comments might refer to it
116 line = '#%s\n%s = %s' % (line, key, section_settings.pop(key))
118 line = '#%s\n%s' % (line, new_line)
117 119 return line.rstrip()
118 120
119 121 # process lines that not are comments or empty and look like name=value
120 122 lines = re.sub(r'^([^#\n\s]*)[ \t]*=[ \t]*(.*)$', process_line, lines, flags=re.MULTILINE)
121 123 # add unused section settings
122 124 if section_settings:
123 125 lines += '\n' + ''.join('%s = %s\n' % (key, value) for key, value in sorted(section_settings.items()))
124 126
125 127 return sectionname + '\n' + lines
126 128
127 129 # process sections until comments before next section or end
128 130 ini_lines = re.sub(r'''^
129 131 (\[.*\])\n
130 132 # after the section name, a number of chunks with:
131 133 (
132 134 (?:
133 135 # a number of comments or empty lines
134 136 (?:[#].*\n|\n)*
135 137 # one or more non-empty non-comments non-section-start lines
136 138 (?:[^\n#[].*\n)+
137 139 # a number of comments - not empty lines
138 140 (?:[#].*\n)*
139 141 )*
140 142 )
141 143 ''',
142 144 process_section, ini_lines, flags=re.MULTILINE|re.VERBOSE) \
143 145 + \
144 146 ''.join(
145 147 '\n' + sectionname + '\n' + ''.join('%s = %s\n' % (key, value) for key, value in sorted(section_settings.items()))
146 148 for sectionname, section_settings in sorted(settings.items())
147 149 if section_settings)
148 150
149 151 return ini_lines
150 152
151 153
152 154 def create(dest_file, mako_variable_values, settings):
153 155 """Create an ini file at dest_file"""
154 156 with open(template_file, 'rb') as f:
155 157 template = f.read().decode('utf-8')
156 158
157 159 ini_lines = expand(template, mako_variable_values, settings)
158 160
159 161 with open(dest_file, 'wb') as f:
160 162 f.write(ini_lines.encode('utf-8'))
General Comments 0
You need to be logged in to leave comments. Login now