Namespace¶
Immutable namespaces are similar to types.SimpleNamespace
, but
prevent any modification of attributes after creation. This makes them ideal for
configuration objects, settings, or any data structure that should remain
completely unchanged after initialization.
>>> from frigid import Namespace
Let’s illustrate this with a configuration namespace for a database connection:
>>> db_config = Namespace(
... host = 'localhost',
... port = 5432,
... name = 'myapp',
... user = 'admin',
... password = 'secret',
... pool_size = 10,
... ssl = True,
... )
Initialization¶
Immutable namespaces can be initialized from zero or more dictionaries or iterables over key-value pairs and zero or more keyword arguments.
>>> # From key-value pairs
>>> cache = Namespace(
... [ ( 'backend', 'redis' ), ( 'timeout', 300 ) ],
... )
>>> # From dictionary
>>> logging = Namespace(
... { 'level': 'INFO', 'format': '%(levelname)s: %(message)s' },
... )
>>> # Mixed initialization
>>> server = Namespace(
... { 'host': 'example.com' },
... [ ( 'port', 443 ) ],
... ssl = True,
... workers = 4,
... )
Immutability¶
Once created, a namespace becomes completely immutable. Attempts to modify existing attributes will raise an error:
>>> db_config.port = 3306
Traceback (most recent call last):
...
frigid.exceptions.AttributeImmutabilityError: Cannot assign or delete attribute 'port'.
Attempts to delete attributes are also prevented:
>>> del db_config.password
Traceback (most recent call last):
...
frigid.exceptions.AttributeImmutabilityError: Cannot assign or delete attribute 'password'.
Unlike types.SimpleNamespace
, new attributes cannot be added after
creation:
>>> db_config.timeout = 30
Traceback (most recent call last):
...
frigid.exceptions.AttributeImmutabilityError: Cannot assign or delete attribute 'timeout'.
Attribute Access¶
Attributes can be accessed normally through dot notation:
>>> db_config.host
'localhost'
>>> db_config.port
5432
Attempting to access non-existent attributes raises an AttributeError:
>>> db_config.missing
Traceback (most recent call last):
...
AttributeError: 'Namespace' object has no attribute 'missing'
Representation¶
Namespaces have a clear string representation that shows all their attributes:
>>> cache
frigid.namespaces.Namespace( backend = 'redis', timeout = 300 )
>>> logging
frigid.namespaces.Namespace( level = 'INFO', format = '%(levelname)s: %(message)s' )
Empty namespaces are also represented appropriately:
>>> empty = Namespace()
>>> empty
frigid.namespaces.Namespace( )
Comparison¶
Namespaces can be compared with other namespaces or SimpleNamespaces. Two namespaces are considered equal if they have the same attributes with the same values:
>>> from types import SimpleNamespace
>>> ns1 = Namespace( x = 1, y = 2 )
>>> ns2 = Namespace( x = 1, y = 2 )
>>> ns3 = SimpleNamespace( x = 1, y = 2 )
>>> ns1 == ns2 # Same type, same content
True
>>> ns1 == ns3 # Different type, same content
True
>>> ns1 == Namespace( x = 1, z = 3 ) # Different content
False
Copying¶
To create a copy of a namespace, access its underlying __dict__
and use it
to initialize a new namespace:
>>> original = Namespace( x = 1, y = 2 )
>>> copy = Namespace( **original.__dict__ ) #**
>>> original == copy
True
This pattern is particularly useful when you need to create a modified version of an existing configuration:
>>> # Create new dict with overridden values
>>> test_config = dict( db_config.__dict__ )
>>> test_config.update( name = 'test_myapp', host = 'test.localhost' )
>>> test_db = Namespace( **test_config ) #**
>>> test_db.name
'test_myapp'
>>> test_db.port # Preserved from original
5432