Coverage for sources/accretive/__/dictionaries.py: 100%
29 statements
« prev ^ index » next coverage.py v7.9.2, created at 2025-07-05 00:54 +0000
« prev ^ index » next coverage.py v7.9.2, created at 2025-07-05 00:54 +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. '''
24# TODO: Consider a dictionary factory to allow 'mutables' closure
25# to be referenced in the '__setitem__' and '__delitem__' methods.
28from . import imports as __
29from . import nomina as _nomina
32_H = __.typx.TypeVar( '_H' )
33_V = __.typx.TypeVar( '_V' )
36class AccretiveDictionary(
37 dict[ _H, _V ],
38 __.ccstd.Object,
39 __.typx.Generic[ _H, _V ],
40):
41 ''' Accretive subclass of :py:class:`dict`.
43 Can be used as an instance dictionary.
45 Prevents attempts to mutate dictionary via inherited interface.
46 '''
48 def __init__(
49 self,
50 *iterables: _nomina.DictionaryPositionalArgument[ _H, _V ],
51 **entries: _nomina.DictionaryNominativeArgument[ _V ],
52 ):
53 super( ).__init__( )
54 self.update( *iterables, **entries )
56 def __delitem__( self, key: _H ) -> None:
57 from .exceptions import EntryImmutability
58 raise EntryImmutability( key )
60 def __setitem__( self, key: _H, value: _V ) -> None:
61 from .exceptions import EntryImmutability
62 if key in self: raise EntryImmutability( key )
63 super( ).__setitem__( key, value )
65 def clear( self ) -> __.typx.Never:
66 ''' Raises exception. Cannot clear immutable entries. '''
67 from .exceptions import OperationInvalidity
68 raise OperationInvalidity( 'clear' )
70 def copy( self ) -> __.typx.Self:
71 ''' Provides fresh copy of dictionary. '''
72 return type( self )( self )
74 def pop( # pyright: ignore
75 self, key: _H, default: __.Absential[ _V ] = __.absent
76 ) -> __.typx.Never:
77 ''' Raises exception. Cannot pop immutable entry. '''
78 from .exceptions import OperationInvalidity
79 raise OperationInvalidity( 'pop' )
81 def popitem( self ) -> __.typx.Never:
82 ''' Raises exception. Cannot pop immutable entry. '''
83 from .exceptions import OperationInvalidity
84 raise OperationInvalidity( 'popitem' )
86 def update( # pyright: ignore
87 self,
88 *iterables: _nomina.DictionaryPositionalArgument[ _H, _V ],
89 **entries: _nomina.DictionaryNominativeArgument[ _V ],
90 ) -> None:
91 ''' Adds new entries as a batch. '''
92 from itertools import chain
93 # Add values in order received, enforcing no alteration.
94 for indicator, value in chain.from_iterable( map( # pyright: ignore
95 lambda element: ( # pyright: ignore
96 element.items( )
97 if isinstance( element, __.cabc.Mapping )
98 else element
99 ),
100 ( *iterables, entries )
101 ) ): self[ indicator ] = value # pyright: ignore