Show More
@@ -0,0 +1,85 b'' | |||||
|
1 | # -*- coding: utf-8 -*- | |||
|
2 | # This program is free software: you can redistribute it and/or modify | |||
|
3 | # it under the terms of the GNU General Public License as published by | |||
|
4 | # the Free Software Foundation, either version 3 of the License, or | |||
|
5 | # (at your option) any later version. | |||
|
6 | # | |||
|
7 | # This program is distributed in the hope that it will be useful, | |||
|
8 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
|
9 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
|
10 | # GNU General Public License for more details. | |||
|
11 | # | |||
|
12 | # You should have received a copy of the GNU General Public License | |||
|
13 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
|
14 | ||||
|
15 | """ | |||
|
16 | kallithea.lib.inifile | |||
|
17 | ~~~~~~~~~~~~~~~~~~~~~ | |||
|
18 | ||||
|
19 | Handling of .ini files, mainly creating them from Mako templates and adding | |||
|
20 | other custom values. | |||
|
21 | """ | |||
|
22 | ||||
|
23 | import logging | |||
|
24 | import re | |||
|
25 | ||||
|
26 | ||||
|
27 | log = logging.getLogger(__name__) | |||
|
28 | ||||
|
29 | ||||
|
30 | def expand(template, desc, selected_mako_conditionals, mako_variable_values, settings): | |||
|
31 | """Expand mako template and tweak it. | |||
|
32 | Not entirely stable for random templates as input, but good enough for our | |||
|
33 | single template. | |||
|
34 | """ | |||
|
35 | # select the right mako conditionals for the other less sophisticated formats | |||
|
36 | def sub_conditionals(m): | |||
|
37 | """given a %if...%endif match, replace with just the selected | |||
|
38 | conditional sections enabled and the rest as comments | |||
|
39 | """ | |||
|
40 | conditional_lines = m.group(1) | |||
|
41 | def sub_conditional(m): | |||
|
42 | """given a conditional and the corresponding lines, return them raw | |||
|
43 | or commented out, based on whether conditional is selected | |||
|
44 | """ | |||
|
45 | criteria, lines = m.groups() | |||
|
46 | if criteria not in selected_mako_conditionals: | |||
|
47 | lines = '\n'.join((l if not l or l.startswith('#') else '#' + l) for l in lines.split('\n')) | |||
|
48 | return lines | |||
|
49 | conditional_lines = re.sub(r'^%(?:el)?if (.*):\n((?:^[^%\n].*\n|\n)*)', | |||
|
50 | sub_conditional, conditional_lines, flags=re.MULTILINE) | |||
|
51 | return conditional_lines | |||
|
52 | mako_no_conditionals = re.sub(r'^(%if .*\n(?:[^%\n].*\n|%elif .*\n|\n)*)%endif\n', | |||
|
53 | sub_conditionals, template, flags=re.MULTILINE) | |||
|
54 | ||||
|
55 | # expand mako variables | |||
|
56 | def pyrepl(m): | |||
|
57 | return mako_variable_values.get(m.group(1), m.group(0)) | |||
|
58 | mako_no_variables = re.sub(r'\${([^}]*)}', pyrepl, mako_no_conditionals) | |||
|
59 | ||||
|
60 | # remove utf-8 coding header | |||
|
61 | ini_lines = re.sub(r'^## -\*- coding: utf-8 -\*-\n', '', mako_no_variables) | |||
|
62 | ||||
|
63 | ini_lines = re.sub( | |||
|
64 | '# Kallithea - config file generated with kallithea-config *#\n', | |||
|
65 | ''.join('# %-77s#\n' % l.strip() for l in desc.strip().split('\n')), | |||
|
66 | ini_lines) | |||
|
67 | def process_section(m): | |||
|
68 | """process a ini section, replacing values as necessary""" | |||
|
69 | sectionname, lines = m.groups() | |||
|
70 | if sectionname in settings: | |||
|
71 | section_settings = settings[sectionname] | |||
|
72 | def process_line(m): | |||
|
73 | """process a section line and update value if necessary""" | |||
|
74 | key, value = m.groups() | |||
|
75 | line = m.group(0) | |||
|
76 | if key in section_settings: | |||
|
77 | line = '%s = %s' % (key, section_settings[key]) | |||
|
78 | if '$' not in value: | |||
|
79 | line = '#%s = %s\n%s' % (key, value, line) | |||
|
80 | return line.rstrip() | |||
|
81 | lines = re.sub(r'^([^#\n].*) = ?(.*)', process_line, lines, flags=re.MULTILINE) | |||
|
82 | return sectionname + '\n' + lines | |||
|
83 | ini_lines = re.sub(r'^(\[.*\])\n((?:(?:[^[\n].*)?\n)*)', process_section, ini_lines, flags=re.MULTILINE) | |||
|
84 | ||||
|
85 | return ini_lines |
@@ -1,152 +1,106 b'' | |||||
1 | #!/usr/bin/env python2 |
|
1 | #!/usr/bin/env python2 | |
2 | """ |
|
2 | """ | |
3 | Based on kallithea/lib/paster_commands/template.ini.mako, generate |
|
3 | Based on kallithea/lib/paster_commands/template.ini.mako, generate | |
4 | development.ini |
|
4 | development.ini | |
5 | kallithea/tests/test.ini |
|
5 | kallithea/tests/test.ini | |
6 | """ |
|
6 | """ | |
7 |
|
7 | |||
8 | import re |
|
8 | import re | |
9 |
|
9 | |||
|
10 | from kallithea.lib import inifile | |||
|
11 | ||||
10 | makofile = 'kallithea/lib/paster_commands/template.ini.mako' |
|
12 | makofile = 'kallithea/lib/paster_commands/template.ini.mako' | |
11 |
|
13 | |||
12 | # the mako conditionals used in all other ini files and templates |
|
14 | # the mako conditionals used in all other ini files and templates | |
13 | selected_mako_conditionals = set([ |
|
15 | selected_mako_conditionals = set([ | |
14 | "database_engine == 'sqlite'", |
|
16 | "database_engine == 'sqlite'", | |
15 | "http_server == 'waitress'", |
|
17 | "http_server == 'waitress'", | |
16 | "error_aggregation_service == 'appenlight'", |
|
18 | "error_aggregation_service == 'appenlight'", | |
17 | "error_aggregation_service == 'sentry'", |
|
19 | "error_aggregation_service == 'sentry'", | |
18 | ]) |
|
20 | ]) | |
19 |
|
21 | |||
20 | # the mako variables used in all other ini files and templates |
|
22 | # the mako variables used in all other ini files and templates | |
21 | mako_variable_values = { |
|
23 | mako_variable_values = { | |
22 | 'host': '127.0.0.1', |
|
24 | 'host': '127.0.0.1', | |
23 | 'port': '5000', |
|
25 | 'port': '5000', | |
24 | 'uuid()': '${app_instance_uuid}', |
|
26 | 'uuid()': '${app_instance_uuid}', | |
25 | } |
|
27 | } | |
26 |
|
28 | |||
27 | # files to be generated from the mako template |
|
29 | # files to be generated from the mako template | |
28 | ini_files = [ |
|
30 | ini_files = [ | |
29 | ('kallithea/tests/test.ini', |
|
31 | ('kallithea/tests/test.ini', | |
30 | ''' |
|
32 | ''' | |
31 | Kallithea - config for tests: |
|
33 | Kallithea - config for tests: | |
32 | sqlalchemy and kallithea_test.sqlite |
|
34 | sqlalchemy and kallithea_test.sqlite | |
33 | custom logging |
|
35 | custom logging | |
34 | ''', |
|
36 | ''', | |
35 | { |
|
37 | { | |
36 | '[server:main]': { |
|
38 | '[server:main]': { | |
37 | 'port': '4999', |
|
39 | 'port': '4999', | |
38 | }, |
|
40 | }, | |
39 | '[app:main]': { |
|
41 | '[app:main]': { | |
40 | 'app_instance_uuid': 'test', |
|
42 | 'app_instance_uuid': 'test', | |
41 | 'show_revision_number': 'true', |
|
43 | 'show_revision_number': 'true', | |
42 | 'beaker.cache.sql_cache_short.expire': '1', |
|
44 | 'beaker.cache.sql_cache_short.expire': '1', | |
43 | 'beaker.session.secret': '{74e0cd75-b339-478b-b129-07dd221def1f}', |
|
45 | 'beaker.session.secret': '{74e0cd75-b339-478b-b129-07dd221def1f}', | |
44 | }, |
|
46 | }, | |
45 | '[handler_console]': { |
|
47 | '[handler_console]': { | |
46 | 'formatter': 'color_formatter', |
|
48 | 'formatter': 'color_formatter', | |
47 | }, |
|
49 | }, | |
48 | # The 'handler_console_sql' block is very similar to the one in |
|
50 | # The 'handler_console_sql' block is very similar to the one in | |
49 | # development.ini, but without the explicit 'level=DEBUG' setting: |
|
51 | # development.ini, but without the explicit 'level=DEBUG' setting: | |
50 | # it causes duplicate sqlalchemy debug logs, one through |
|
52 | # it causes duplicate sqlalchemy debug logs, one through | |
51 | # handler_console_sql and another through another path. |
|
53 | # handler_console_sql and another through another path. | |
52 | '[handler_console_sql]': { |
|
54 | '[handler_console_sql]': { | |
53 | 'formatter': 'color_formatter_sql', |
|
55 | 'formatter': 'color_formatter_sql', | |
54 | }, |
|
56 | }, | |
55 | }, |
|
57 | }, | |
56 | ), |
|
58 | ), | |
57 | ('development.ini', |
|
59 | ('development.ini', | |
58 | ''' |
|
60 | ''' | |
59 | Kallithea - Development config: |
|
61 | Kallithea - Development config: | |
60 | listening on *:5000 |
|
62 | listening on *:5000 | |
61 | sqlite and kallithea.db |
|
63 | sqlite and kallithea.db | |
62 | initial_repo_scan = true |
|
64 | initial_repo_scan = true | |
63 | debug = true |
|
65 | debug = true | |
64 | verbose and colorful logging |
|
66 | verbose and colorful logging | |
65 | ''', |
|
67 | ''', | |
66 | { |
|
68 | { | |
67 | '[server:main]': { |
|
69 | '[server:main]': { | |
68 | 'host': '0.0.0.0', |
|
70 | 'host': '0.0.0.0', | |
69 | }, |
|
71 | }, | |
70 | '[app:main]': { |
|
72 | '[app:main]': { | |
71 | 'initial_repo_scan': 'true', |
|
73 | 'initial_repo_scan': 'true', | |
72 | 'debug': 'true', |
|
74 | 'debug': 'true', | |
73 | 'app_instance_uuid': 'development-not-secret', |
|
75 | 'app_instance_uuid': 'development-not-secret', | |
74 | 'beaker.session.secret': 'development-not-secret', |
|
76 | 'beaker.session.secret': 'development-not-secret', | |
75 | }, |
|
77 | }, | |
76 | '[handler_console]': { |
|
78 | '[handler_console]': { | |
77 | 'formatter': 'color_formatter', |
|
79 | 'formatter': 'color_formatter', | |
78 | }, |
|
80 | }, | |
79 | '[handler_console_sql]': { |
|
81 | '[handler_console_sql]': { | |
80 | 'formatter': 'color_formatter_sql', |
|
82 | 'formatter': 'color_formatter_sql', | |
81 | }, |
|
83 | }, | |
82 | }, |
|
84 | }, | |
83 | ), |
|
85 | ), | |
84 | ] |
|
86 | ] | |
85 |
|
87 | |||
86 |
|
88 | |||
87 | def main(): |
|
89 | def main(): | |
88 | # make sure all mako lines starting with '#' (the '##' comments) are marked up as <text> |
|
90 | # make sure all mako lines starting with '#' (the '##' comments) are marked up as <text> | |
89 | print 'reading:', makofile |
|
91 | print 'reading:', makofile | |
90 | mako_org = open(makofile).read() |
|
92 | mako_org = open(makofile).read() | |
91 | mako_no_text_markup = re.sub(r'</?%text>', '', mako_org) |
|
93 | mako_no_text_markup = re.sub(r'</?%text>', '', mako_org) | |
92 | mako_marked_up = re.sub(r'\n(##.*)', r'\n<%text>\1</%text>', mako_no_text_markup, flags=re.MULTILINE) |
|
94 | mako_marked_up = re.sub(r'\n(##.*)', r'\n<%text>\1</%text>', mako_no_text_markup, flags=re.MULTILINE) | |
93 | if mako_marked_up != mako_org: |
|
95 | if mako_marked_up != mako_org: | |
94 | print 'writing:', makofile |
|
96 | print 'writing:', makofile | |
95 | open(makofile, 'w').write(mako_marked_up) |
|
97 | open(makofile, 'w').write(mako_marked_up) | |
96 |
|
98 | |||
97 | # select the right mako conditionals for the other less sophisticated formats |
|
|||
98 | def sub_conditionals(m): |
|
|||
99 | """given a %if...%endif match, replace with just the selected |
|
|||
100 | conditional sections enabled and the rest as comments |
|
|||
101 | """ |
|
|||
102 | conditional_lines = m.group(1) |
|
|||
103 | def sub_conditional(m): |
|
|||
104 | """given a conditional and the corresponding lines, return them raw |
|
|||
105 | or commented out, based on whether conditional is selected |
|
|||
106 | """ |
|
|||
107 | criteria, lines = m.groups() |
|
|||
108 | if criteria not in selected_mako_conditionals: |
|
|||
109 | lines = '\n'.join((l if not l or l.startswith('#') else '#' + l) for l in lines.split('\n')) |
|
|||
110 | return lines |
|
|||
111 | conditional_lines = re.sub(r'^%(?:el)?if (.*):\n((?:^[^%\n].*\n|\n)*)', |
|
|||
112 | sub_conditional, conditional_lines, flags=re.MULTILINE) |
|
|||
113 | return conditional_lines |
|
|||
114 | mako_no_conditionals = re.sub(r'^(%if .*\n(?:[^%\n].*\n|%elif .*\n|\n)*)%endif\n', |
|
|||
115 | sub_conditionals, mako_no_text_markup, flags=re.MULTILINE) |
|
|||
116 |
|
||||
117 | # expand mako variables |
|
|||
118 | def pyrepl(m): |
|
|||
119 | return mako_variable_values.get(m.group(1), m.group(0)) |
|
|||
120 | mako_no_variables = re.sub(r'\${([^}]*)}', pyrepl, mako_no_conditionals) |
|
|||
121 |
|
||||
122 | # remove utf-8 coding header |
|
|||
123 | base_ini = re.sub(r'^## -\*- coding: utf-8 -\*-\n', '', mako_no_variables) |
|
|||
124 |
|
||||
125 | # create ini files |
|
99 | # create ini files | |
126 | for fn, desc, settings in ini_files: |
|
100 | for fn, desc, settings in ini_files: | |
127 | print 'updating:', fn |
|
101 | print 'updating:', fn | |
128 | ini_lines = re.sub( |
|
102 | ini_lines = inifile.expand(mako_no_text_markup, desc, selected_mako_conditionals, mako_variable_values, settings) | |
129 | '# Kallithea - config file generated with kallithea-config *#\n', |
|
|||
130 | ''.join('# %-77s#\n' % l.strip() for l in desc.strip().split('\n')), |
|
|||
131 | base_ini) |
|
|||
132 | def process_section(m): |
|
|||
133 | """process a ini section, replacing values as necessary""" |
|
|||
134 | sectionname, lines = m.groups() |
|
|||
135 | if sectionname in settings: |
|
|||
136 | section_settings = settings[sectionname] |
|
|||
137 | def process_line(m): |
|
|||
138 | """process a section line and update value if necessary""" |
|
|||
139 | setting, value = m.groups() |
|
|||
140 | line = m.group(0) |
|
|||
141 | if setting in section_settings: |
|
|||
142 | line = '%s = %s' % (setting, section_settings[setting]) |
|
|||
143 | if '$' not in value: |
|
|||
144 | line = '#%s = %s\n%s' % (setting, value, line) |
|
|||
145 | return line.rstrip() |
|
|||
146 | lines = re.sub(r'^([^#\n].*) = ?(.*)', process_line, lines, flags=re.MULTILINE) |
|
|||
147 | return sectionname + '\n' + lines |
|
|||
148 | ini_lines = re.sub(r'^(\[.*\])\n((?:(?:[^[\n].*)?\n)*)', process_section, ini_lines, flags=re.MULTILINE) |
|
|||
149 | open(fn, 'w').write(ini_lines) |
|
103 | open(fn, 'w').write(ini_lines) | |
150 |
|
104 | |||
151 | if __name__ == '__main__': |
|
105 | if __name__ == '__main__': | |
152 | main() |
|
106 | main() |
General Comments 0
You need to be logged in to leave comments.
Login now