Skip to content

Instantly share code, notes, and snippets.

@fuzzy
Last active April 8, 2021 22:19
Show Gist options
  • Save fuzzy/6c117ad488bef2789dba to your computer and use it in GitHub Desktop.
Save fuzzy/6c117ad488bef2789dba to your computer and use it in GitHub Desktop.
parses config files
import os
import re
import json
import shlex
import types
import ConfigParser
_tokens = []
data = {'global': {}}
regex = {
'section': re.compile('^\[[a-zA-Z0-9_]+\]$'),
'string': re.compile('^(\'.*\'|\".*\")$'),
'key': re.compile('^[a-zA-Z_]+:$'),
'macro': re.compile('^\$\{.*\}$')
}
def loadConfig(cfgfile):
global _tokens, data, regex
if not cfgfile:
raise ValueError, 'You must specify a path+filename.'
# We have a 3 pass parser here.
# first pass, pull in the file and parse out comments
_slurpFile(cfgfile)
# second pass, actually parse the file into the data structure
_parseFile()
# and third pass, ensure all macro interpolation is handled
tmp = _interpolate(data)
data = tmp
from pprint import pprint as pp
pp(data)
def _interpolate(node):
global _tokens, data, regex
for key in node.keys():
if type(node[key]) == types.DictType:
t = _interpolate(node[key])
node[key] = t
else:
if regex['macro'].match(node[key]):
if node[key][2:-1].find(':') != -1:
k,v = node[key][2:-1].split(':')
node[key] = data[k][v]
else:
node[key] = node[node[key][2:-1]]
return node
def _parseFile():
global _tokens, data, regex
section = 'global'
for idx in range(0, len(_tokens)):
if not regex['string'].match(_tokens[idx]):
if regex['section'].match(_tokens[idx]):
if _tokens[idx][1:-1] not in data.keys():
section = _tokens[idx][1:-1]
data[section] = {}
elif regex['key'].match(_tokens[idx]):
try:
if regex['string'].match(_tokens[idx+1]):
data[section][_tokens[idx][0:-1]] = json.loads(_tokens[idx+1][1:-1])
else:
data[section][_tokens[idx][0:-1]] = json.loads(_tokens[idx+1])
except ValueError:
print section, idx, _tokens[idx]
data[section][_tokens[idx][0:-1]] = _tokens[idx+1]
def _slurpFile(cfgfile):
global _tokens, data, regex
if not os.path.isfile(cfgfile):
raise ValueError, '%s: no such file' % cfgfile
_cfgfp = open(cfgfile)
buff = []
tbuf = _cfgfp.readline()
# make sure we don't keep comments around
# TODO: support end of line comments
while tbuf:
if tbuf[0] != '#':
buff.append(tbuf)
tbuf = _cfgfp.readline()
# Hand off a shlex parsed set of tokens for pass 2
_tokens = shlex.split(''.join(buff))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment