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