Files
ppf/comboparse.py
Username 304cdb3b4c
All checks were successful
CI / validate (push) Successful in 19s
comboparse: replace SafeConfigParser with ConfigParser
2026-02-18 21:01:10 +01:00

114 lines
3.5 KiB
Python

#!/usr/bin/env python2
# -*- coding: utf-8 -*-
"""Combined config file and argument parser."""
try:
from ConfigParser import SafeConfigParser as ConfigParser, NoOptionError
except ImportError:
from configparser import ConfigParser, NoOptionError
from argparse import ArgumentParser
import sys
class _Dummy(object):
"""Placeholder for config sections."""
pass
class ComboParser(object):
"""Parse configuration from INI file and command-line arguments.
Command-line arguments override INI file values.
"""
def __init__(self, ini):
self.items = []
self.cparser = ConfigParser()
self.aparser = ArgumentParser()
self.ini = ini
self.loaded = False
self.args = None
def add_item(self, section, name, type, default, desc, required):
"""Add a configuration item."""
def str2bool(val):
return val.lower() in ('true', '1', 'yes')
self.items.append({
'section': section,
'name': name,
'type': type,
'default': default,
'required': required,
})
self.aparser.add_argument(
'--%s.%s' % (section, name),
help='%s (default: %s)' % (desc, default),
type=type if type is not bool else str2bool,
default=None,
required=False
)
def load(self):
"""Load configuration from file and command-line."""
if self.loaded:
return
self.loaded = True
try:
self.cparser.read(self.ini)
except Exception:
pass # Config file missing or unreadable, use defaults
self.args = self.aparser.parse_args()
for item in self.items:
section = item['section']
name = item['name']
# Ensure section object exists
if not hasattr(self, section):
setattr(self, section, _Dummy())
obj = getattr(self, section)
# Start with default value
value = item['default']
found = False
# Try to read from config file
try:
if item['type'] is bool:
value = self.cparser.getboolean(section, name)
elif item['type'] is float:
value = self.cparser.getfloat(section, name)
elif item['type'] is int:
value = self.cparser.getint(section, name)
elif item['type'] is str:
value = self.cparser.get(section, name)
found = True
except NoOptionError:
pass
# Command-line overrides config file
arg_name = '%s.%s' % (section, name)
arg_value = getattr(self.args, arg_name, None)
if arg_value is not None:
value = arg_value
found = True
# Handle missing required items
if not found:
if item['required']:
sys.stderr.write(
'error: required config item "%s" not found in section "%s" of "%s"\n'
% (name, section, self.ini)
)
sys.exit(1)
else:
sys.stderr.write(
'warning: assigned default value of "%s" to "%s.%s"\n'
% (item['default'], section, name)
)
setattr(obj, name, value)