API¶
Package frigid
¶
Data structures which are completely immutable after creation. This behavior is useful for configuration objects, value objects, and other scenarios requiring collections with strong immutability guarantees.
Dictionary
: A dict-like structure that becomes completely immutable after creation. Includes aValidatorDictionary
variant, which validates entries during creation.Namespace
: Similar totypes.SimpleNamespace
but completely immutable after creation.Class
: Metaclass for producing classes with immutable class attributes. Has variants which are compatible withabc.ABCMeta
andtyping.Protocol
.Module
: A module type that enforces complete attribute immutability.reclassify_modules
: Convenience function for making modules in a package immutable.Object
: Base class for objects with immutable attributes.immutable
: Decorator for causing classes to produce immutable instances.one
: Convenience function for producing single-element tuples.
Module frigid.dictionaries
¶
Immutable dictionaries.
Dictionaries which cannot be modified after creation.
Note
While types.MappingProxyType
also provides a read-only view
of a dictionary, it has important differences from
Dictionary
:
A
MappingProxyType
is a view over a mutable dictionary, so its contents can still change if the underlying dictionary is modified.Dictionary
owns its data and guarantees that it will never change.Dictionary
provides set operations (union, intersection) that maintain immutability guarantees.
Use MappingProxyType
when you want to expose a read-only view of a
dictionary that might need to change. Use Dictionary
when you want
to ensure that the data can never change, such as for configuration
objects or other cases requiring strong immutability guarantees.
AbstractDictionary
: Base class defining the immutable dictionary interface. Implementations must provide__getitem__
,__iter__
, and__len__
.Dictionary
: Standard implementation of an immutable dictionary. Supports all usual dict read operations but prevents any modifications.ValidatorDictionary
: Validates entries before addition using a supplied predicate function.
>>> from frigid import Dictionary
>>> d = Dictionary( x = 1, y = 2 )
>>> d[ 'z' ] = 3 # Attempt to add entry
Traceback (most recent call last):
...
frigid.exceptions.EntryImmutabilityError: Cannot assign or delete entry for 'z'.
>>> d[ 'x' ] = 4 # Attempt modification
Traceback (most recent call last):
...
frigid.exceptions.EntryImmutabilityError: Cannot assign or delete entry for 'x'.
>>> del d[ 'y' ] # Attempt removal
Traceback (most recent call last):
...
frigid.exceptions.EntryImmutabilityError: Cannot assign or delete entry for 'y'.
- class frigid.dictionaries.AbstractDictionary¶
Bases:
Mapping
[H
,V
]Abstract base class for immutable dictionaries.
An immutable dictionary prevents modification or removal of entries after creation. This provides a clean interface for dictionaries that should never change.
Implementations must provide __getitem__, __iter__, __len__.
- get(k[, d]) D[k] if k in D, else d. d defaults to None. ¶
- items() a set-like object providing a view on D's items ¶
- keys() a set-like object providing a view on D's keys ¶
- values() an object providing a view on D's values ¶
- class frigid.dictionaries.Dictionary(*iterables: Annotated[Mapping[H, V] | Iterable[tuple[H, V]], Doc('Zero or more iterables from which to initialize dictionary data. Each iterable must be dictionary or sequence of key-value pairs. Duplicate keys will result in an error.')], **entries: Annotated[V, Doc('Zero or more keyword arguments from which to initialize dictionary data.')])¶
Bases:
Object
,_DictionaryOperations
[H
,V
]Immutable dictionary.
Prevents addition, alteration, or removal of dictionary entries after creation.
- copy() Self ¶
Provides fresh copy of dictionary.
- get(key: H, default: V | AbsentSingleton = absence.absent) Annotated[V, Doc('Value of entry, if it exists. Else, supplied default value or ``None``.')] ¶
Retrieves entry associated with key, if it exists.
- values() ValuesView[V] ¶
Provides iterable view over dictionary values.
- with_data(*iterables: Annotated[Mapping[H, V] | Iterable[tuple[H, V]], Doc('Zero or more iterables from which to initialize dictionary data. Each iterable must be dictionary or sequence of key-value pairs. Duplicate keys will result in an error.')], **entries: Annotated[V, Doc('Zero or more keyword arguments from which to initialize dictionary data.')]) Self ¶
Creates new dictionary with same behavior but different data.
- class frigid.dictionaries.ValidatorDictionary(validator: Annotated[Callable[[H, V], bool], Doc('Callable which validates entries before addition to dictionary.')], /, *iterables: Annotated[Mapping[H, V] | Iterable[tuple[H, V]], Doc('Zero or more iterables from which to initialize dictionary data. Each iterable must be dictionary or sequence of key-value pairs. Duplicate keys will result in an error.')], **entries: Annotated[V, Doc('Zero or more keyword arguments from which to initialize dictionary data.')])¶
Bases:
Dictionary
[H
,V
]Immutable dictionary with validation of entries on initialization.
Prevents addition, alteration, or removal of dictionary entries after creation.
When an attempt to create a dictionary with entries, each entry is validated against supplied criteria. If validation fails for any entry, then the dictionary creation is rejected.
- copy() Self ¶
Provides fresh copy of dictionary.
- get(key: H, default: V | AbsentSingleton = absence.absent) Annotated[V, Doc('Value of entry, if it exists. Else, supplied default value or ``None``.')] ¶
Retrieves entry associated with key, if it exists.
- values() ValuesView[V] ¶
Provides iterable view over dictionary values.
- with_data(*iterables: Annotated[Mapping[H, V] | Iterable[tuple[H, V]], Doc('Zero or more iterables from which to initialize dictionary data. Each iterable must be dictionary or sequence of key-value pairs. Duplicate keys will result in an error.')], **entries: Annotated[V, Doc('Zero or more keyword arguments from which to initialize dictionary data.')]) Self ¶
Creates new dictionary with same behavior but different data.
Module frigid.namespaces
¶
Immutable namespaces.
Provides a namespace type with immutable attributes. Similar to
types.SimpleNamespace
, but attributes cannot be modified or
deleted after initialization.
The namespace implementation is modeled after
types.SimpleNamespace
but adds immutability. Like
types.SimpleNamespace
, it provides a simple __repr__
which
lists all attributes.
>>> from frigid import Namespace
>>> ns = Namespace( x = 1, y = 2 )
>>> ns.z = 3 # Attempt to add attribute
Traceback (most recent call last):
...
frigid.exceptions.AttributeImmutabilityError: Cannot assign or delete attribute 'z'.
>>> ns.x = 4 # Attempt modification
Traceback (most recent call last):
...
frigid.exceptions.AttributeImmutabilityError: Cannot assign or delete attribute 'x'.
>>> ns
frigid.namespaces.Namespace( x = 1, y = 2 )
- class frigid.namespaces.Namespace(*iterables: Annotated[Mapping[H, V] | Iterable[tuple[H, V]], Doc('Zero or more iterables from which to initialize dictionary data. Each iterable must be dictionary or sequence of key-value pairs. Duplicate keys will result in an error.')], **attributes: Annotated[V, Doc('Zero or more keyword arguments from which to initialize dictionary data.')])¶
Bases:
Object
Immutable namespaces.
A namespace is an object, whose attributes can be determined from iterables and keyword arguments, at initialization time. The string representation of the namespace object reflects its current instance attributes. Modeled after
types.SimpleNamespace
.Prevents assignment or deletion of instance attributes after instance creation.
Module frigid.modules
¶
Immutable modules.
Provides a module type that enforces complete attribute immutability. This helps ensure that module-level constants remain constant and that module interfaces remain stable during runtime.
The module implementation is derived from types.ModuleType
and
adds immutability. This makes it particularly useful for:
Ensuring constants remain constant
Preventing modification of module interfaces
Also provides a convenience function:
reclassify_modules
: Converts existing modules to immutable modules.
- class frigid.modules.Module(name, doc=None)¶
Bases:
ModuleType
Immutable modules.
Derived from
types.ModuleType
, this class is suitable for use as a Python module class.Prevents assignment or deletion of module attributes after module creation.
This behavior helps ensure that module-level constants remain constant and that module interfaces remain stable during runtime.
- frigid.modules.reclassify_modules(attributes: Annotated[Mapping[str, Any] | ModuleType | str, Doc('Module, module name, or dictionary of object attributes.')], recursive: Annotated[bool, Doc('Recursively reclassify package modules?')] = False) None ¶
Reclassifies modules to be immutable.
Can operate on individual modules or entire package hierarchies.
Notes¶
Only converts modules within the same package to prevent unintended modifications to external modules.
When used with a dictionary, converts any module objects found as values if they belong to the same package.
Has no effect on already-immutable modules.
Module frigid.classes
¶
Immutable classes.
Provides metaclasses for creating classes with immutable attributes. Once a class is initialized, new attributes may not be assigned to it and its existing attributes cannot be reassigned or deleted.
The implementation includes:
Class
: Standard metaclass for immutable classes; derived fromtype
.ABCFactory
: Metaclass for abstract base classes; derived fromabc.ABCMeta
.ProtocolClass
: Metaclass for protocol classes; derived fromtyping.Protocol
.
Additionally, metaclasses for dataclasses are provided as a convenience.
>>> from frigid import Class
>>> class Example( metaclass = Class ):
... x = 1
>>> Example.y = 2 # Attempt assignment
Traceback (most recent call last):
...
frigid.exceptions.AttributeImmutabilityError: Cannot assign or delete attribute 'y'.
>>> Example.x = 3 # Attempt reassignment
Traceback (most recent call last):
...
frigid.exceptions.AttributeImmutabilityError: Cannot assign or delete attribute 'x'.
- class frigid.classes.ABCFactory(name: str, bases: tuple[type, ...], namespace: dict[str, Any], *, decorators: Iterable[Callable[[type], type]] = (), docstring: str | None | AbsentSingleton = absence.absent, mutables: Collection[str] = (), **args: Any)¶
Bases:
ABCMeta
Immutable abstract base class factory.
Derived from
type
, this is a metaclass. A metaclass is a class factory class. I.e., it is a class that produces other classes as its instances.Prevents assignment or deletion of class attributes after class creation.
- mro()¶
Return a type’s method resolution order.
- register(subclass)¶
Register a virtual subclass of an ABC.
Returns the subclass, to allow usage as a class decorator.
- class frigid.classes.Class(name: str, bases: tuple[type, ...], namespace: dict[str, Any], *, decorators: Iterable[Callable[[type], type]] = (), docstring: str | None | AbsentSingleton = absence.absent, mutables: Collection[str] = (), **args: Any)¶
Bases:
type
Immutable class factory.
Derived from
type
, this is a metaclass. A metaclass is a class factory class. I.e., it is a class that produces other classes as its instances.Prevents assignment or deletion of class attributes after class creation.
- mro()¶
Return a type’s method resolution order.
- class frigid.classes.CompleteDataclass(name: str, bases: tuple[type, ...], namespace: dict[str, Any], *, decorators: Iterable[Callable[[type], type]] = (), docstring: str | None | AbsentSingleton = absence.absent, mutables: Collection[str] = (), **args: Any)¶
Bases:
Class
Immutable dataclass factory.
Dataclasses from this factory produce immutable instances.
Derived from
type
, this is a metaclass. A metaclass is a class factory class. I.e., it is a class that produces other classes as its instances.Prevents assignment or deletion of class attributes after class creation.
- mro()¶
Return a type’s method resolution order.
- class frigid.classes.CompleteProtocolDataclass(name: str, bases: tuple[type, ...], namespace: dict[str, Any], *, decorators: Iterable[Callable[[type], type]] = (), docstring: str | None | AbsentSingleton = absence.absent, mutables: Collection[str] = (), **args: Any)¶
Bases:
ProtocolClass
Immutable protocol dataclass factory.
Dataclasses from this factory produce immutable instances.
Derived from
type
, this is a metaclass. A metaclass is a class factory class. I.e., it is a class that produces other classes as its instances.Prevents assignment or deletion of class attributes after class creation.
- mro()¶
Return a type’s method resolution order.
- register(subclass)¶
Register a virtual subclass of an ABC.
Returns the subclass, to allow usage as a class decorator.
- class frigid.classes.Dataclass(name: str, bases: tuple[type, ...], namespace: dict[str, Any], *, decorators: Iterable[Callable[[type], type]] = (), docstring: str | None | AbsentSingleton = absence.absent, mutables: Collection[str] = (), **args: Any)¶
Bases:
Class
Immutable dataclass factory.
Derived from
type
, this is a metaclass. A metaclass is a class factory class. I.e., it is a class that produces other classes as its instances.Prevents assignment or deletion of class attributes after class creation.
- mro()¶
Return a type’s method resolution order.
- class frigid.classes.ProtocolClass(name: str, bases: tuple[type, ...], namespace: dict[str, Any], *, decorators: Iterable[Callable[[type], type]] = (), docstring: str | None | AbsentSingleton = absence.absent, mutables: Collection[str] = (), **args: Any)¶
Bases:
_ProtocolMeta
Immutable protocol class factory.
Derived from
type
, this is a metaclass. A metaclass is a class factory class. I.e., it is a class that produces other classes as its instances.Prevents assignment or deletion of class attributes after class creation.
- mro()¶
Return a type’s method resolution order.
- register(subclass)¶
Register a virtual subclass of an ABC.
Returns the subclass, to allow usage as a class decorator.
- class frigid.classes.ProtocolDataclass(name: str, bases: tuple[type, ...], namespace: dict[str, Any], *, decorators: Iterable[Callable[[type], type]] = (), docstring: str | None | AbsentSingleton = absence.absent, mutables: Collection[str] = (), **args: Any)¶
Bases:
ProtocolClass
Immutable protocol dataclass factory.
Derived from
type
, this is a metaclass. A metaclass is a class factory class. I.e., it is a class that produces other classes as its instances.Prevents assignment or deletion of class attributes after class creation.
- mro()¶
Return a type’s method resolution order.
- register(subclass)¶
Register a virtual subclass of an ABC.
Returns the subclass, to allow usage as a class decorator.
Module frigid.objects
¶
Immutable objects.
Provides a base class and decorator for creating objects with immutable attributes. Once an object is initialized, its attributes cannot be modified or deleted.
>>> from frigid import Object
>>> class Point( Object ):
... def __init__( self, x, y ):
... self.x = x
... self.y = y
... super( ).__init__( )
...
>>> obj = Point( 1, 2 ) # Initialize with attributes
>>> obj.z = 3 # Attempt to add attribute
Traceback (most recent call last):
...
frigid.exceptions.AttributeImmutabilityError: Cannot assign or delete attribute 'z'.
>>> obj.x = 4 # Attempt modification
Traceback (most recent call last):
...
frigid.exceptions.AttributeImmutabilityError: Cannot assign or delete attribute 'x'.
The immutable decorator can be used to make any class immutable:
>>> from frigid import immutable
>>> @immutable
... class Config:
... def __init__( self, verbose = False ):
... self.verbose = verbose
...
>>> config = Config( verbose = True )
>>> config.verbose = False # Attempt to modify attribute
Traceback (most recent call last):
...
frigid.exceptions.AttributeImmutabilityError: ...
- class frigid.objects.Object(*posargs: Any, **nomargs: Any)¶
Bases:
object
Immutable objects.
Prevents assignment or deletion of instance attributes after instance creation.
- frigid.objects.immutable(class_: type[C] | AbsentSingleton = absence.absent, *, docstring: str | None | AbsentSingleton = absence.absent, mutables: Collection[str] = ()) type[C] | Callable[[type[C]], type[C]] ¶
Decorator which makes class immutable after initialization.
Cannot be applied to classes which define their own __setattr__ or __delattr__ methods.
This decorator can be used in different ways:
Simple decorator:
>>> @immutable ... class Config: ... pass
With parameters:
>>> @immutable( mutables = ( 'version', ) ) ... class Config: ... pass
Module frigid.sequences
¶
Immutable sequences.
- frigid.sequences.one(value: _V) tuple[_V, ...] ¶
Produces single-item tuple from value.
Provides a more explicit and readable alternative to the comma-syntax for creating single-item tuples. While Python allows
( x, )
for creating single-item tuples, usingone( x )
can be clearer, especially in certain contexts:List comprehensions and generator expressions
Situations where formatter behavior with trailing commas is undesired
Module frigid.installers
¶
Convenience to expose certain package features as Python builtins.
Module frigid.exceptions
¶
Family of exceptions for package API.
Provides a hierarchy of exceptions that are raised when immutability is violated. The hierarchy is designed to allow both specific and general exception handling.
- exception frigid.exceptions.AttributeImmutabilityError(name: str)¶
Bases:
Omnierror
,AttributeError
,TypeError
Attempt to modify immutable attribute.
- with_traceback()¶
Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.
- args¶
- name¶
attribute name
- obj¶
object
- exception frigid.exceptions.DecoratorCompatibilityError(class_name: str, method_name: str)¶
-
Attempt to apply decorator to incompatible class.
- with_traceback()¶
Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.
- args¶
- exception frigid.exceptions.EntryImmutabilityError(key: Hashable)¶
-
Attempt to modify immutable dictionary entry.
- with_traceback()¶
Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.
- args¶
- exception frigid.exceptions.EntryValidityError(indicator: Hashable, value: Any)¶
Bases:
Omnierror
,ValueError
Attempt to add invalid entry to dictionary.
- with_traceback()¶
Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.
- args¶
- exception frigid.exceptions.Omnierror¶
Bases:
Omniexception
,Exception
Base for error exceptions raised by package API.
- with_traceback()¶
Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.
- args¶
- exception frigid.exceptions.Omniexception¶
Bases:
ImmutableObject
,BaseException
Base for all exceptions raised by package API.
- with_traceback()¶
Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.
- args¶
Module frigid.qaliases
¶
Qualified aliases to immutable data structures.
Provides aliases prefixed with “Immutable” for all core classes. These are useful for avoiding namespace collisions when importing from the package, particularly with common names like “Dictionary” or “Namespace”.
For example, instead of:
>>> from frigid import Dictionary
>>> # Possible conflict with other Dictionary classes
you could use:
>>> from frigid.qaliases import ImmutableDictionary
>>> # Clearly indicates the source and behavior
- frigid.qaliases.AbstractImmutableDictionary
alias of
AbstractDictionary
- frigid.qaliases.ImmutableABCFactory
alias of
ABCFactory
- frigid.qaliases.ImmutableClass
alias of
Class
- frigid.qaliases.ImmutableCompleteDataclass
alias of
CompleteDataclass
- frigid.qaliases.ImmutableCompleteProtocolDataclass
alias of
CompleteProtocolDataclass
- frigid.qaliases.ImmutableDataclass
alias of
Dataclass
- frigid.qaliases.ImmutableDictionary
alias of
Dictionary
- frigid.qaliases.ImmutableModule
alias of
Module
- frigid.qaliases.ImmutableNamespace
alias of
Namespace
- frigid.qaliases.ImmutableObject
alias of
Object
- frigid.qaliases.ImmutableProtocolClass
alias of
ProtocolClass
- frigid.qaliases.ImmutableProtocolDataclass
alias of
ProtocolDataclass
- frigid.qaliases.ImmutableValidatorDictionary
alias of
ValidatorDictionary
- frigid.qaliases.immutable(class_: type[C] | AbsentSingleton = absence.absent, *, docstring: str | None | AbsentSingleton = absence.absent, mutables: Collection[str] = ()) type[C] | Callable[[type[C]], type[C]]
Decorator which makes class immutable after initialization.
Cannot be applied to classes which define their own __setattr__ or __delattr__ methods.
This decorator can be used in different ways:
Simple decorator:
>>> @immutable ... class Config: ... pass
With parameters:
>>> @immutable( mutables = ( 'version', ) ) ... class Config: ... pass
- frigid.qaliases.reclassify_modules_as_immutable(attributes: Annotated[Mapping[str, Any] | ModuleType | str, Doc('Module, module name, or dictionary of object attributes.')], recursive: Annotated[bool, Doc('Recursively reclassify package modules?')] = False) None
Reclassifies modules to be immutable.
Can operate on individual modules or entire package hierarchies.
Notes¶
Only converts modules within the same package to prevent unintended modifications to external modules.
When used with a dictionary, converts any module objects found as values if they belong to the same package.
Has no effect on already-immutable modules.