Skip to content

Instantly share code, notes, and snippets.

@danielperezr88
Last active July 15, 2016 12:51
Show Gist options
  • Save danielperezr88/0af32a4e6ac03d74f758407aac62cd8f to your computer and use it in GitHub Desktop.
Save danielperezr88/0af32a4e6ac03d74f758407aac62cd8f to your computer and use it in GitHub Desktop.
ConfigParser applied to php.ini commented and uncommented option parsing
from configparser import ConfigParser
LOGDIR = '/etc/php5/apache2'
### Overload ConfigParser _read method to generate a comment parser
class CommentParser(ConfigParser):
def __init__(self,*args,**kwargs):
super(ConfigParser,self).__init__(*args,**kwargs)
def _read(self, fp, fpname):
from ConfigParser import DEFAULTSECT
from ConfigParser import MissingSectionHeaderError
from ConfigParser import ParsingError
cursect = None # None, or a dictionary
optname = None
lineno = 0
e = None # None, or an exception
while True:
line = fp.readline()
if not line:
break
lineno = lineno + 1
# comment or blank line?
if line.strip() == '' or line[0] not in '#;[':
continue
if line[0] != '[':
line = line[1:]
if re.match(r'^[^\=]*\=[^\=]+',line) == None:
continue
if line.split(None, 1)[0].lower() == 'rem' and line[0] in "rR":
# no leading whitespace
continue
# continuation line?
if line[0].isspace() and cursect is not None and optname:
value = line.strip()
if value:
cursect[optname].append(value)
# a section header or option header?
else:
# is it a section header?
mo = self.SECTCRE.match(line)
if mo:
sectname = mo.group('header')
if sectname in self._sections:
cursect = self._sections[sectname]
elif sectname == DEFAULTSECT:
cursect = self._defaults
else:
cursect = self._dict()
cursect['__name__'] = sectname
self._sections[sectname] = cursect
# So sections can't start with a continuation line
optname = None
# no section header in the file?
elif cursect is None:
raise MissingSectionHeaderError(fpname, lineno, line)
# an option line?
else:
mo = self._optcre.match(line)
if mo:
optname, vi, optval = mo.group('option', 'vi', 'value')
optname = self.optionxform(optname.rstrip())
# This check is fine because the OPTCRE cannot
# match if it would set optval to None
if optval is not None:
if vi in ('=', ':') and ';' in optval:
# ';' is a comment delimiter only if it follows
# a spacing character
pos = optval.find(';')
if pos != -1 and optval[pos-1].isspace():
optval = optval[:pos]
optval = optval.strip()
# allow empty values
if optval == '""':
optval = ''
cursect[optname] = [optval]
else:
# valueless option handling
cursect[optname] = optval
else:
# a non-fatal parsing error occurred. set up the
# exception but keep going. the exception will be
# raised at the end of the file and will contain a
# list of all bogus lines
if not e:
e = ParsingError(fpname)
e.append(lineno, repr(line))
# if any parsing errors occurred, raise an exception
if e:
raise e
# join the multi-line values collected while reading
all_sections = [self._defaults]
all_sections.extend(self._sections.values())
for options in all_sections:
for name, val in options.items():
if isinstance(val, list):
options[name] = '\n'.join(val)
### Parse commented and uncommented options
with open(os.path.join(LOGDIR,'php.ini'),'r') as origfile:
orig = ConfigParser().read_file(origfile)
comm = CommentParser().read_file(origfile)
### Create dict from commented options
comm = dict(
[
(str(name),str(value))
if re.match(r'[\"\']',value[0]+value[-1]) == None
else (name,value[1:-1])
for name, value in {
name:value
for name, value in comm._sections['PHP'].items()
if name != '__name__'
}.items()
]
)
### Set new php.ini from original with some changes
shutil.move(os.path.join(LOGDIR,'php.ini'),os.path.join(LOGDIR,'php.ini.old'))
orig.set('PHP','error_log','/var/log/php-scripts.log')
with open(os.path.join(LOGDIR,'php.ini'),'w') as newfile:
orig.write(newfile)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment