Coverage for sources/frigid/__/dictionaries.py: 100%
35 statements
« prev ^ index » next coverage.py v7.6.10, created at 2025-01-24 04:09 +0000
« prev ^ index » next coverage.py v7.6.10, created at 2025-01-24 04:09 +0000
1# vim: set filetype=python fileencoding=utf-8:
2# -*- coding: utf-8 -*-
4#============================================================================#
5# #
6# Licensed under the Apache License, Version 2.0 (the "License"); #
7# you may not use this file except in compliance with the License. #
8# You may obtain a copy of the License at #
9# #
10# http://www.apache.org/licenses/LICENSE-2.0 #
11# #
12# Unless required by applicable law or agreed to in writing, software #
13# distributed under the License is distributed on an "AS IS" BASIS, #
14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
15# See the License for the specific language governing permissions and #
16# limitations under the License. #
17# #
18#============================================================================#
21''' Internal dictionary. '''
23# pylint: disable=unused-import
24# ruff: noqa: F401
27from __future__ import annotations
29from . import imports as __
30from . import immutables as _immutables
33_H = __.typx.TypeVar( '_H' )
34_V = __.typx.TypeVar( '_V' )
37class ImmutableDictionary(
38 _immutables.ConcealerExtension,
39 dict[ _H, _V ],
40 __.typx.Generic[ _H, _V ],
41):
42 ''' Immutable subclass of :py:class:`dict`.
44 Can be used as an instance dictionary.
46 Prevents attempts to mutate dictionary via inherited interface.
47 '''
49 def __init__(
50 self,
51 *iterables: __.DictionaryPositionalArgument[ _H, _V ],
52 **entries: __.DictionaryNominativeArgument[ _V ],
53 ):
54 self._behaviors_: set[ str ] = set( )
55 super( ).__init__( )
56 from itertools import chain
57 # Add values in order received, enforcing no alteration.
58 for indicator, value in chain.from_iterable( map( # type: ignore
59 lambda element: ( # type: ignore
60 element.items( )
61 if isinstance( element, __.cabc.Mapping )
62 else element
63 ),
64 ( *iterables, entries )
65 ) ): self[ indicator ] = value # type: ignore
66 self._behaviors_.add( _immutables.behavior_label )
68 def __delitem__( self, key: _H ) -> None:
69 from ..exceptions import EntryImmutabilityError
70 raise EntryImmutabilityError( key )
72 def __setitem__( self, key: _H, value: _V ) -> None:
73 from ..exceptions import EntryImmutabilityError
74 default: set[ str ] = set( )
75 if _immutables.behavior_label in getattr(
76 self, '_behaviors_', default
77 ): raise EntryImmutabilityError( key )
78 if key in self: raise EntryImmutabilityError( key )
79 super( ).__setitem__( key, value )
81 def clear( self ) -> __.typx.Never:
82 ''' Raises exception. Cannot clear immutable entries. '''
83 from ..exceptions import OperationInvalidity
84 raise OperationInvalidity( 'clear' )
86 def copy( self ) -> __.typx.Self:
87 ''' Provides fresh copy of dictionary. '''
88 return type( self )( self )
90 def pop( # pylint: disable=unused-argument
91 self, key: _H, default: __.Absential[ _V ] = __.absent
92 ) -> __.typx.Never:
93 ''' Raises exception. Cannot pop immutable entry. '''
94 from ..exceptions import OperationInvalidity
95 raise OperationInvalidity( 'pop' )
97 def popitem( self ) -> __.typx.Never:
98 ''' Raises exception. Cannot pop immutable entry. '''
99 from ..exceptions import OperationInvalidity
100 raise OperationInvalidity( 'popitem' )
102 def update( # type: ignore
103 self, # pylint: disable=unused-argument
104 *iterables: __.DictionaryPositionalArgument[ _H, _V ],
105 **entries: __.DictionaryNominativeArgument[ _V ],
106 ) -> None:
107 ''' Raises exception. Cannot perform mass update. '''
108 from ..exceptions import OperationInvalidity
109 raise OperationInvalidity( 'update' )