QUOTATION_MARKS = {'"', '\''} KEY_VALUE_LINE = 0 GROUP_HEADER_LINE = 1 COMMENT_LINE = 2 def reverse_dict(d): return {k: v for k, v in list(reversed(d.items()))} def parse_key_value_line(line): if '=' not in line: return {'': ''} return {line.split('=')[0].strip(): '='.join(line.split('=')[1:]).strip()} def parse_group_header(line): if line.startswith('[') and line.endswith(']'): return line[1:-1] def parse_line_type(line): line = line.strip() if line.startswith('#'): return COMMENT_LINE if line.startswith('[') and line.endswith(']'): return GROUP_HEADER_LINE if '=' in line: return KEY_VALUE_LINE def compress_conf(conf): while '\n\n' in conf: conf = conf.replace('\n\n', '\n') return conf.strip() def parse_ini(conf): conf = compress_conf(conf) result = {} current_group = {} for line in list(reversed(conf.split('\n'))): line = line.strip() if parse_line_type(line) == COMMENT_LINE: continue if parse_line_type(line) == GROUP_HEADER_LINE: result[parse_group_header(line)] = reverse_dict(current_group) current_group = {} if parse_line_type(line) == KEY_VALUE_LINE: current_group = current_group | parse_key_value_line(line) return reverse_dict(result)