-
Notifications
You must be signed in to change notification settings - Fork 0
Open
Description
📌 Problem
In many applications, configuration data (e.g., database credentials, API keys, feature flags) is loaded at startup and should remain unchanged throughout the program's lifecycle. However, Python dictionaries are mutable by default, which can lead to accidental or unauthorized modifications.
✅ Goal
Create a fully immutable configuration object, including nested dictionaries, lists, and sets, to ensure the integrity of application settings after initialization.
🛠️ Solution: Custom ImmutableConfig Class
We define a class that:
- Recursively freezes nested structures (
dict,list,set) - Exposes read-only access via
__getitem__ - Optionally provides a method to export the config as a regular
dict
from types import MappingProxyType
class ImmutableConfig:
def __init__(self, data):
self._data = self._deep_freeze(data)
def _deep_freeze(self, obj):
if isinstance(obj, dict):
return MappingProxyType({k: self._deep_freeze(v) for k, v in obj.items()})
elif isinstance(obj, list):
return tuple(self._deep_freeze(i) for i in obj)
elif isinstance(obj, set):
return frozenset(self._deep_freeze(i) for i in obj)
else:
return obj
def __getitem__(self, key):
return self._data[key]
def __repr__(self):
return f"ImmutableConfig({dict(self._data)})"
def to_dict(self):
# Optional: return a deep copy as a regular dict
import copy
return copy.deepcopy(self._data)🧪 Example Usage
config_data = {
'db': {'host': 'localhost', 'port': 5432},
'api': {'key': 'abc123', 'timeout': 30},
'features': ['auth', 'logging']
}
config = ImmutableConfig(config_data)
print(config['db']['host']) # Output: 'localhost'
# Attempting to mutate will raise an error
config['db']['host'] = '127.0.0.1' # ❌ TypeError📎 Notes
- Requires Python 3.3+ (
MappingProxyTypeis part of the standardtypesmodule). - You can extend the class to support:
- JSON serialization
- Schema validation
- Logging access or audit trails
Let me know if you'd like a version with JSON export or schema validation built in!
Metadata
Metadata
Assignees
Labels
No labels