🔧 AI Nachrichten Major AI platforms go down in unprecedented simultaneous outage(03.09.2026 um 17:34 Uhr)
🔧 AI Nachrichten ChatGPT, Claude, and Grok Down? Users Report Widespread Outages(03.09.2026 um 19:14 Uhr)
🔧 AI Nachrichten OpenAI Launches GPT-6 Astra, Says We May Have Entered the AGI Era(03.09.2026 um 22:08 Uhr)
🔧 AI Nachrichten Claude Comes to CarPlay as Fifth Major AI Chatbot App(05.09.2026 um 05:31 Uhr)
🔧 AI Nachrichten OpenAI’s GPT-6 Astra Is AGI, Says NVIDIA CEO Jensen Huang(07.09.2026 um 06:31 Uhr)
🔧 AI Nachrichten Blame AI companies for Mac mini and Mac Studio shortage(31.08.2026 um 10:32 Uhr)
🔧 AI Nachrichten Major AI platforms go down in unprecedented simultaneous outage(03.09.2026 um 17:34 Uhr)
🔧 AI Nachrichten ChatGPT, Claude, and Grok Down? Users Report Widespread Outages(03.09.2026 um 19:14 Uhr)
🔧 AI Nachrichten OpenAI Launches GPT-6 Astra, Says We May Have Entered the AGI Era(03.09.2026 um 22:08 Uhr)
🔧 AI Nachrichten Claude Comes to CarPlay as Fifth Major AI Chatbot App(05.09.2026 um 05:31 Uhr)
🔧 AI Nachrichten OpenAI’s GPT-6 Astra Is AGI, Says NVIDIA CEO Jensen Huang(07.09.2026 um 06:31 Uhr)
🔧 AI Nachrichten Blame AI companies for Mac mini and Mac Studio shortage(31.08.2026 um 10:32 Uhr)

🔧 Programmierung 🕛 kürzlich 5 Min Lesezeit
0

Towards Effortless Python Configuration Files Version 3

↗ Quelle (dev.to)
🗣️ Stimme:
📑 Inhaltsübersicht




Introduction



This is the final article in this series. This implemenation seeks to fix the main disadvantage of boiler plate code that I described in the






Developer Code Description



I am going to present the full source code for an application seeking to use this class. I am using the previous properties that we have been discussing in the previous 3 articles.




CODE
from codeallybasic.DynamicConfiguration import DynamicConfiguration
from codeallybasic.DynamicConfiguration import KeyName
from codeallybasic.DynamicConfiguration import SectionName
from codeallybasic.DynamicConfiguration import Sections
from codeallybasic.DynamicConfiguration import ValueDescription
from codeallybasic.DynamicConfiguration import ValueDescriptions
from codeallybasic.SecureConversions import SecureConversions

from codeallybasic.SingletonV3 import SingletonV3

from ByteSizedPython.ImpostorEnumByName import ImpostorEnumByName
from ByteSizedPython.PhoneyEnumByValue import PhoneyEnumByValue

LOGGER_NAME: str = 'Tutorial'
BASE_FILE_NAME: str = 'config.ini'
MODULE_NAME: str = 'version3properties'

DEFAULT_PHONEY_ENUM_BY_VALUE: PhoneyEnumByValue = PhoneyEnumByValue.FakeBrenda
DEFAULT_IMPOSTOR_ENUM_BY_NAME: ImpostorEnumByName = ImpostorEnumByName.High

GENERAL_PROPERTIES: ValueDescriptions = ValueDescriptions(
{
KeyName('debug'): ValueDescription(defaultValue='False', deserializer=SecureConversions.secureBoolean),
KeyName('logLevel'): ValueDescription(defaultValue='Info'),
KeyName('phoneyEnumByValue'): ValueDescription(defaultValue=DEFAULT_PHONEY_ENUM_BY_VALUE.value, enumUseValue=True),
KeyName('impostorEnumByName'): ValueDescription(defaultValue=DEFAULT_IMPOSTOR_ENUM_BY_NAME.name, enumUseName=True),
}
)

DATABASE_PROPERTIES: ValueDescriptions = ValueDescriptions(
{
KeyName('dbName'): ValueDescription(defaultValue='dbName'),
KeyName('dbHost'): ValueDescription(defaultValue='localhost'),
KeyName('dbPort'): ValueDescription(defaultValue='5342', deserializer=SecureConversions.secureInteger),
}
)

CONFIGURATION_SECTIONS: Sections = Sections(
{
SectionName('General'): GENERAL_PROPERTIES,
SectionName('Database'): DATABASE_PROPERTIES,
}
)

class ConfigurationPropertiesVersion3(DynamicConfiguration, metaclass=SingletonV3):
def __init__(self):

self._logger: Logger = getLogger(LOGGER_NAME)

super().__init__(baseFileName=BASE_FILE_NAME, moduleName=MODULE_NAME, sections=CONFIGURATION_SECTIONS)







Lines 45-50 are the code that you have to write. Essentially, your are just ensuring that you pass the file name, module name, and the configuration sections. This Sections type comes from the DynamicConfiguration module.



Lines 21-28 and 30-36 are ValueDescriptions dictionaries. The KeyName is the property and points to a ValueDescription. Notice that the indicator on how to persist an enumeration is moved from the previous implementation's decorator to a boolean attribute in a ValueDescription.






Implementation Code Description



If you look closely at the class diagram for DynamicConfiguration you will see that it implements two Python magic methods. They are the __getattr__(self, name)__ and __setattr__(self, name, value)__ methods.




  • __getattr__(self, name)__ Allows a developer to define behavior when a class consumer attempts to access a non-existent attribute.

  • __setattr__(self, name, value)__ Allows a developer to define behavior for assignment to an attribute.



The following is the code for __getattr__. This looks very much like the decorator we used in version 2. The key work happens on the call on line 14 to the protected method _lookupKey(). It returns a full description of the attribute so that we can simulate the attribute retrieval.




CODE
    def __getattr__(self, attrName: str) -> Any:
"""
Does the work of retrieving the named attribute from the configuration parser

Args:
attrName:

Returns: The correctly typed value
"""

self._logger.info(f'{attrName}')

configParser: ConfigParser = self._configParser
result: LookupResult = self._lookupKey(searchKeyName=KeyName(attrName))
valueDescription: ValueDescription = result.keyDescription

valueStr: str = configParser.get(result.sectionName, attrName)

if valueDescription.deserializer is not None:
value: Any = valueDescription.deserializer(valueStr)
else:
value = valueStr

return value







The following is the__setattr__() implementation. Notice the support for enumerations in lines 22-27 and the write-through feature in line 30.




CODE
    def __setattr__(self, key: str, value: Any):
"""
Do the work of writing this back to the configuration/settings/preferences file
Ignores protected and private variables uses by this class

Does a
"write through" to the backing configuration file (.ini)

Args:
key: The property name
value: Its new value
"""

if key.startswith(PROTECTED_PROPERTY_INDICATOR) or key.startswith(PRIVATE_PROPERTY_INDICATOR):
super(DynamicConfiguration, self).__setattr__(key, value)
else:
self._logger.debug(f'Writing `{key}` with `{value}` to configuration file')

configParser: ConfigParser = self._configParser
result: LookupResult = self._lookupKey(searchKeyName=KeyName(key))
valueDescription: ValueDescription = result.keyDescription

if valueDescription.enumUseValue is True:
valueStr: str = value.value
configParser.set(result.sectionName, key, valueStr)
elif valueDescription.enumUseName is True:
configParser.set(result.sectionName, key, value.name)
else:
configParser.set(result.sectionName, key, str(value))

self.saveConfiguration()









Accessing and Modifying Properties



Accessing and modifying properties is exactly the same as in version 2.




CODE
    basicConfig(level=INFO)

config: ConfigurationPropertiesVersion2 = ConfigurationPropertiesVersion2()

logger: Logger = getLogger(LOGGER_NAME)

logger.info(f'{config.debug=}')
logger.info(f'{config.logLevel=}')
logger.info(f'{config.phoneyEnumByValue=}')
logger.info(f'{config.impostorEnumByName=}')
logger.info('Database Properties Follow')
logger.info(f'{config.dbName=}')
logger.info(f'{config.dbHost=}')
logger.info(f'{config.dbPort=}')
logger.info('Mutate Enumeration Properties')
config.phoneyEnumByValue = PhoneyEnumByValue.TheWanderer
logger.info(f'{config.phoneyEnumByValue=}')
config.impostorEnumByName = ImpostorEnumByName.Low
logger.info(f'{config.impostorEnumByName=}')






The above snippet produces the following output.




CODE
INFO:Tutorial:config.debug='False'
INFO:Tutorial:config.logLevel='Info'
INFO:Tutorial:config.phoneyEnumByValue=<PhoneyEnumByValue.FakeBrenda: 'Faker Extraordinaire'>
INFO:Tutorial:config.impostorEnumByName='High'
INFO:Tutorial:Database Properties Follow
INFO:Tutorial:config.dbName='example_db'
INFO:Tutorial:config.dbHost='localhost'
INFO:Tutorial:config.dbPort=5432
INFO:Tutorial:Mutate Enumeration Properties
INFO:Tutorial:config.phoneyEnumByValue=<PhoneyEnumByValue.TheWanderer: 'The Wanderer'>
INFO:Tutorial:config.impostorEnumByName='Low'









Conclusion



The source code for this article is . See the implementation of






Advantages




  • Easy type safe access to application properties

  • Reusable parent class for different implementations

  • Data structure driven code to add new sections and configuration keys

  • No boiler plate code for properties






Disadvantages




  • Since there are no actual properties implemented we do not get IDE support for them

  • Additionally, because of the lookup methods for keys, different keys in different sections cannot have the same name

Vollständiger Original-Bericht
Ausführliche Details, Code-Beispiele & Hersteller-Stellungnahme auf dev.to.
↗ Original-Artikel auf dev.to lesen
Wie bewertest du diesen Beitrag?
1 Klick Feedback
Teilen mit Netzwerk & Team:

Community-Analysen & Experten-Meinungen 0

Verfasse deine eigene Analyse, teile Workarounds oder diskutiere diesen Vorfall im Blog.
Noch keine Community-Analyse verfasst. Markiere einen Textabschnitt oder klicke oben auf Eigene Analyse verfassen“!
Community Pulse: Relevanz-Einschätzung
1 Klick Experten-Votum
🔴 Akute Relevanz 0%
🟡 In Evaluierung 0%
🟢 Keine Auswirkung 0%
Spannende Innovation 0%
Verwandte Story-Cluster & Quellen (Vektor-KI)
Port 8095 Engine
3 Quellen
GPT-6 Astra Release Today? OpenAI’s Next Major AI Model Is Almost Here
1 Quelle
Apple accuses OpenAI of destroying evidence as trade-secrets fight intensifies
1 Quelle
Major AI platforms go down in unprecedented simultaneous outage
Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten Towards Effortless Python Configuration Files Version 3

Thematisch verwandte Begriffe: Towards, Effortless, Python, Configuration · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...