Config master.py: Difference between revisions
Jump to navigation
Jump to search
mNo edit summary |
mNo edit summary |
||
| Line 1: | Line 1: | ||
{{menuPromptEngineerCode}} | {{menuPromptEngineerCode}} | ||
<pre style="width:880px; padding:10px; color:lime; background-color:#302; margin:0 auto;"> | <pre style="width:880px; padding:10px; color:lime; background-color:#302; margin:0 auto;"> | ||
""" | """ | ||
ConfigMaster Class | ConfigMaster Class v.2024.05.15 | ||
v.2024.05.15 | |||
Author: Claude (Opus 3 LLM @claude.ai) | Author: Claude (Opus 3 LLM @claude.ai) | ||
| Line 11: | Line 11: | ||
This module provides a class for handling configuration files in a simple and intuitive way. | This module provides a class for handling configuration files in a simple and intuitive way. | ||
The ConfigMaster class allows reading, writing, and manipulating configuration data | The ConfigMaster class allows reading, writing, and manipulating configuration data | ||
stored in a format similar to INI files. It supports | stored in a format similar to INI files. It supports a variety of data types, including | ||
integers, floats, booleans, lists, tuples, and datetimes, with convenient methods for | |||
retrieving values of specific types. | |||
Features: | Features: | ||
- Load and save configuration data from/to files | - Load and save configuration data from/to files | ||
- Get, set, update, and remove values in sections | - Get, set, update, and remove values in sections | ||
- Support for different data types (int, float, boolean, list, tuple, datetime) | |||
- Case-insensitive section and key names | - Case-insensitive section and key names | ||
- Support for default values | - Support for default values and fallback values | ||
- Handling of comment lines | - Handling of comment lines | ||
- Dictionary-like access to sections and key-value pairs | - Dictionary-like access to sections and key-value pairs | ||
| Line 25: | Line 26: | ||
- Merging configuration data from multiple sources | - Merging configuration data from multiple sources | ||
- Error handling and validation for section and key names | - Error handling and validation for section and key names | ||
Usage: | Usage: | ||
| Line 41: | Line 40: | ||
config.save() | config.save() | ||
5. | 5. Retrieve values of specific data types: | ||
int_value = config.getint('Section1', 'IntKey', fallback=0) | |||
float_value = config.getfloat('Section1', 'FloatKey', fallback=0.0) | |||
bool_value = config.getboolean('Section1', 'BoolKey', fallback=False) | |||
list_value = config.getlist('Section1', 'ListKey', fallback=[]) | |||
tuple_value = config.gettuple('Section1', 'TupleKey', fallback=()) | |||
datetime_value = config.getdatetime('Section1', 'DateTimeKey', fallback=None) | |||
Example configuration file format: | Example configuration file format: | ||
| Line 61: | Line 63: | ||
import os | import os | ||
from datetime import datetime | |||
class ConfigMaster: | class ConfigMaster: | ||
def __init__(self, file_path): | def __init__(self, file_path): | ||
self.file_path = file_path | self.file_path = file_path | ||
self.config = {} | self.config = {} | ||
self.comments = [] | self.comments = [] | ||
self.load() | self.load() | ||
def load(self): | def load(self): | ||
if not os.path.isfile(self.file_path): | if not os.path.isfile(self.file_path): | ||
self.config = {'default': {}} | |||
self.config = {} | |||
else: | else: | ||
current_section = 'default' | |||
current_section = | self.config[current_section] = {} | ||
with open(self.file_path, 'r') as config_file: | with open(self.file_path, 'r') as config_file: | ||
for line in config_file: | for line in config_file: | ||
| Line 91: | Line 89: | ||
key, value = line.split(':', 1) | key, value = line.split(':', 1) | ||
self.config[current_section][key.strip().lower()] = value.strip() | self.config[current_section][key.strip().lower()] = value.strip() | ||
def save(self): | def save(self): | ||
with open(self.file_path, 'w') as config_file: | with open(self.file_path, 'w') as config_file: | ||
config_file.writelines(line + '\n' for line in self.comments) | config_file.writelines(line + '\n' for line in self.comments) | ||
| Line 106: | Line 100: | ||
config_file.write("\n") | config_file.write("\n") | ||
def get(self, section, key, | def get(self, section, key, fallback=None): | ||
section = section.lower() | section = section.lower() | ||
key = key.lower() | key = key.lower() | ||
| Line 116: | Line 106: | ||
return self.config[section][key] | return self.config[section][key] | ||
else: | else: | ||
return fallback | |||
self. | |||
return | def getint(self, section, key, fallback=None): | ||
value = self.get(section, key, fallback=None) | |||
if value is None: | |||
return fallback | |||
try: | |||
return int(value) | |||
except ValueError: | |||
return fallback | |||
def getfloat(self, section, key, fallback=None): | |||
value = self.get(section, key, fallback=None) | |||
if value is None: | |||
return fallback | |||
try: | |||
return float(value) | |||
except ValueError: | |||
return fallback | |||
def getboolean(self, section, key, fallback=None): | |||
value = self.get(section, key, fallback=None) | |||
if value is None: | |||
return fallback | |||
value = value.lower() | |||
if value in ['true', 'yes', '1']: | |||
return True | |||
elif value in ['false', 'no', '0']: | |||
return False | |||
else: | |||
return fallback | |||
def getlist(self, section, key, fallback=None, delimiter=','): | |||
value = self.get(section, key, fallback=None) | |||
if value is None: | |||
return fallback | |||
return [item.strip() for item in value.split(delimiter)] | |||
def gettuple(self, section, key, fallback=None, delimiter=','): | |||
value = self.get(section, key, fallback=None) | |||
if value is None: | |||
return fallback | |||
return tuple(item.strip() for item in value.split(delimiter)) | |||
def getdatetime(self, section, key, fallback=None, format='%Y-%m-%d %H:%M:%S'): | |||
value = self.get(section, key, fallback=None) | |||
if value is None: | |||
return fallback | |||
try: | |||
return datetime.strptime(value, format) | |||
except ValueError: | |||
return fallback | |||
def set(self, section, key, value): | def set(self, section, key, value): | ||
section = section.lower() | section = section.lower() | ||
key = key.lower() | key = key.lower() | ||
| Line 133: | Line 168: | ||
def update(self, section, data): | def update(self, section, data): | ||
section = section.lower() | section = section.lower() | ||
self._validate_section(section) | self._validate_section(section) | ||
| Line 142: | Line 173: | ||
def remove(self, section, key): | def remove(self, section, key): | ||
section = section.lower() | section = section.lower() | ||
key = key.lower() | key = key.lower() | ||
| Line 151: | Line 179: | ||
def add_section(self, section): | def add_section(self, section): | ||
section = section.lower() | section = section.lower() | ||
if section not in self.config: | if section not in self.config: | ||
self.config[section] = {} | self.config[section] = {} | ||
def remove_section(self, section): | def remove_section(self, section): | ||
section = section.lower() | section = section.lower() | ||
if section in self.config: | if section in self.config: | ||
| Line 168: | Line 189: | ||
def has_key(self, section, key): | def has_key(self, section, key): | ||
section = section.lower() | section = section.lower() | ||
key = key.lower() | key = key.lower() | ||
| Line 176: | Line 194: | ||
def has_section(self, section): | def has_section(self, section): | ||
return section.lower() in self.config | return section.lower() in self.config | ||
def sections(self): | def sections(self): | ||
return list(self.config.keys()) | return list(self.config.keys()) | ||
def items(self, section): | def items(self, section): | ||
section = section.lower() | section = section.lower() | ||
return list(self.config.get(section, {}).items()) | return list(self.config.get(section, {}).items()) | ||
def merge(self, other_config): | def merge(self, other_config): | ||
if isinstance(other_config, ConfigMaster): | if isinstance(other_config, ConfigMaster): | ||
other_config = other_config.config | other_config = other_config.config | ||
| Line 206: | Line 210: | ||
def _validate_section_key(self, section, key): | def _validate_section_key(self, section, key): | ||
if not section or not key: | if not section or not key: | ||
raise ValueError("Section and key cannot be empty") | raise ValueError("Section and key cannot be empty") | ||
| Line 216: | Line 216: | ||
def _validate_section(self, section): | def _validate_section(self, section): | ||
if not section: | if not section: | ||
raise ValueError("Section cannot be empty") | raise ValueError("Section cannot be empty") | ||
def __getitem__(self, section): | def __getitem__(self, section): | ||
return self.config[section.lower()] | return self.config[section.lower()] | ||
def __setitem__(self, section, section_config): | def __setitem__(self, section, section_config): | ||
self.config[section.lower()] = {k.lower(): v for k, v in section_config.items()} | self.config[section.lower()] = {k.lower(): v for k, v in section_config.items()} | ||
def __delitem__(self, section): | def __delitem__(self, section): | ||
del self.config[section.lower()] | del self.config[section.lower()] | ||
def __contains__(self, section): | def __contains__(self, section): | ||
return section.lower() in self.config | return section.lower() in self.config | ||
if __name__ == "__main__": | |||
# Quick test of the ConfigMaster class | |||
config = ConfigMaster("test_config.ini") | |||
# Set values of different data types | |||
config.set("Section1", "IntKey", "10") | |||
config.set("Section1", "FloatKey", "3.14") | |||
config.set("Section1", "BoolKey", "true") | |||
config.set("Section1", "ListKey", "apple, banana, cherry") | |||
config.set("Section1", "TupleKey", "red, green, blue") | |||
config.set("Section1", "DateTimeKey", "2023-06-08 12:30:00") | |||
# Save the configuration to the file | |||
config.save() | |||
# Retrieve values of different data types | |||
int_value = config.getint("Section1", "IntKey", fallback=0) | |||
float_value = config.getfloat("Section1", "FloatKey", fallback=0.0) | |||
bool_value = config.getboolean("Section1", "BoolKey", fallback=False) | |||
list_value = config.getlist("Section1", "ListKey", fallback=[]) | |||
tuple_value = config.gettuple("Section1", "TupleKey", fallback=()) | |||
datetime_value = config.getdatetime("Section1", "DateTimeKey", fallback=None) | |||
# Print the retrieved values | |||
print("Int Value:", int_value) | |||
print("Float Value:", float_value) | |||
print("Bool Value:", bool_value) | |||
print("List Value:", list_value) | |||
print("Tuple Value:", tuple_value) | |||
print("DateTime Value:", datetime_value) | |||
</pre> | </pre> | ||
Revision as of 14:17, 15 May 2024
"""
ConfigMaster Class v.2024.05.15
Author: Claude (Opus 3 LLM @claude.ai)
Prompt Engineer: XenoEngineer@groupKOS.com (Catcliffe Development)
Copyright (c) 2024, Catcliffe Development
This module provides a class for handling configuration files in a simple and intuitive way.
The ConfigMaster class allows reading, writing, and manipulating configuration data
stored in a format similar to INI files. It supports a variety of data types, including
integers, floats, booleans, lists, tuples, and datetimes, with convenient methods for
retrieving values of specific types.
Features:
- Load and save configuration data from/to files
- Get, set, update, and remove values in sections
- Support for different data types (int, float, boolean, list, tuple, datetime)
- Case-insensitive section and key names
- Support for default values and fallback values
- Handling of comment lines
- Dictionary-like access to sections and key-value pairs
- Iteration over sections and key-value pairs
- Merging configuration data from multiple sources
- Error handling and validation for section and key names
Usage:
1. Create an instance of the ConfigMaster class with the file path:
config = ConfigMaster('config.txt')
2. Get values from sections with default values:
value = config.get('Section1', 'Key1', 'DefaultValue')
3. Set values in sections:
config.set('Section1', 'Key1', 'Value1')
4. Save the configuration to the file:
config.save()
5. Retrieve values of specific data types:
int_value = config.getint('Section1', 'IntKey', fallback=0)
float_value = config.getfloat('Section1', 'FloatKey', fallback=0.0)
bool_value = config.getboolean('Section1', 'BoolKey', fallback=False)
list_value = config.getlist('Section1', 'ListKey', fallback=[])
tuple_value = config.gettuple('Section1', 'TupleKey', fallback=())
datetime_value = config.getdatetime('Section1', 'DateTimeKey', fallback=None)
Example configuration file format:
[Section1]
Key1: Value1
Key2: Value2
[Section2]
Key3: Value3
; This is a comment
# This is also a comment
Developed as a collaboration between Claude (LLM) and XenoEngineer (Catcliffe Development).
"""
import os
from datetime import datetime
class ConfigMaster:
def __init__(self, file_path):
self.file_path = file_path
self.config = {}
self.comments = []
self.load()
def load(self):
if not os.path.isfile(self.file_path):
self.config = {'default': {}}
else:
current_section = 'default'
self.config[current_section] = {}
with open(self.file_path, 'r') as config_file:
for line in config_file:
line = line.strip()
if line.startswith(';') or line.startswith('#'):
self.comments.append(line)
elif line.startswith('[') and line.endswith(']'):
current_section = line[1:-1].lower()
self.config[current_section] = {}
elif ':' in line:
key, value = line.split(':', 1)
self.config[current_section][key.strip().lower()] = value.strip()
def save(self):
with open(self.file_path, 'w') as config_file:
config_file.writelines(line + '\n' for line in self.comments)
for section, section_config in self.config.items():
if section != 'default':
config_file.write(f"[{section}]\n")
for key, value in section_config.items():
config_file.write(f"{key}: {value}\n")
config_file.write("\n")
def get(self, section, key, fallback=None):
section = section.lower()
key = key.lower()
if section in self.config and key in self.config[section]:
return self.config[section][key]
else:
return fallback
def getint(self, section, key, fallback=None):
value = self.get(section, key, fallback=None)
if value is None:
return fallback
try:
return int(value)
except ValueError:
return fallback
def getfloat(self, section, key, fallback=None):
value = self.get(section, key, fallback=None)
if value is None:
return fallback
try:
return float(value)
except ValueError:
return fallback
def getboolean(self, section, key, fallback=None):
value = self.get(section, key, fallback=None)
if value is None:
return fallback
value = value.lower()
if value in ['true', 'yes', '1']:
return True
elif value in ['false', 'no', '0']:
return False
else:
return fallback
def getlist(self, section, key, fallback=None, delimiter=','):
value = self.get(section, key, fallback=None)
if value is None:
return fallback
return [item.strip() for item in value.split(delimiter)]
def gettuple(self, section, key, fallback=None, delimiter=','):
value = self.get(section, key, fallback=None)
if value is None:
return fallback
return tuple(item.strip() for item in value.split(delimiter))
def getdatetime(self, section, key, fallback=None, format='%Y-%m-%d %H:%M:%S'):
value = self.get(section, key, fallback=None)
if value is None:
return fallback
try:
return datetime.strptime(value, format)
except ValueError:
return fallback
def set(self, section, key, value):
section = section.lower()
key = key.lower()
self._validate_section_key(section, key)
if section not in self.config:
self.config[section] = {}
self.config[section][key] = value
def update(self, section, data):
section = section.lower()
self._validate_section(section)
self.config.setdefault(section, {}).update({k.lower(): v for k, v in data.items()})
def remove(self, section, key):
section = section.lower()
key = key.lower()
if section in self.config and key in self.config[section]:
del self.config[section][key]
def add_section(self, section):
section = section.lower()
if section not in self.config:
self.config[section] = {}
def remove_section(self, section):
section = section.lower()
if section in self.config:
del self.config[section]
def has_key(self, section, key):
section = section.lower()
key = key.lower()
return section in self.config and key in self.config[section]
def has_section(self, section):
return section.lower() in self.config
def sections(self):
return list(self.config.keys())
def items(self, section):
section = section.lower()
return list(self.config.get(section, {}).items())
def merge(self, other_config):
if isinstance(other_config, ConfigMaster):
other_config = other_config.config
for section, section_config in other_config.items():
self.config.setdefault(section.lower(), {}).update({k.lower(): v for k, v in section_config.items()})
def _validate_section_key(self, section, key):
if not section or not key:
raise ValueError("Section and key cannot be empty")
if ':' in key:
raise ValueError("Key cannot contain ':' character")
def _validate_section(self, section):
if not section:
raise ValueError("Section cannot be empty")
def __getitem__(self, section):
return self.config[section.lower()]
def __setitem__(self, section, section_config):
self.config[section.lower()] = {k.lower(): v for k, v in section_config.items()}
def __delitem__(self, section):
del self.config[section.lower()]
def __contains__(self, section):
return section.lower() in self.config
if __name__ == "__main__":
# Quick test of the ConfigMaster class
config = ConfigMaster("test_config.ini")
# Set values of different data types
config.set("Section1", "IntKey", "10")
config.set("Section1", "FloatKey", "3.14")
config.set("Section1", "BoolKey", "true")
config.set("Section1", "ListKey", "apple, banana, cherry")
config.set("Section1", "TupleKey", "red, green, blue")
config.set("Section1", "DateTimeKey", "2023-06-08 12:30:00")
# Save the configuration to the file
config.save()
# Retrieve values of different data types
int_value = config.getint("Section1", "IntKey", fallback=0)
float_value = config.getfloat("Section1", "FloatKey", fallback=0.0)
bool_value = config.getboolean("Section1", "BoolKey", fallback=False)
list_value = config.getlist("Section1", "ListKey", fallback=[])
tuple_value = config.gettuple("Section1", "TupleKey", fallback=())
datetime_value = config.getdatetime("Section1", "DateTimeKey", fallback=None)
# Print the retrieved values
print("Int Value:", int_value)
print("Float Value:", float_value)
print("Bool Value:", bool_value)
print("List Value:", list_value)
print("Tuple Value:", tuple_value)
print("DateTime Value:", datetime_value)