Coverage for sources/accretive/classes.py: 100%
25 statements
« prev ^ index » next coverage.py v7.5.4, created at 2024-07-06 17:17 +0000
« prev ^ index » next coverage.py v7.5.4, created at 2024-07-06 17:17 +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''' Accretive classes. '''
24from __future__ import annotations
26from . import __
27from . import _annotations as _a
30class Class( type ):
31 ''' Accretive classes. '''
33 def __new__(
34 factory: _a.Type[ type ],
35 name: str,
36 bases: _a.Tuple[ type, ... ],
37 namespace: _a.MutableMapping[ str, _a.Any ],
38 docstring: str = None,
39 **nomargs: _a.Any
40 ) -> Class:
41 if docstring: namespace[ '__doc__' ] = docstring
42 return _a.cast(
43 Class,
44 super( ).__new__( factory, name, bases, namespace, **nomargs ) )
46 def __delattr__( class_, name: str ) -> None:
47 from .exceptions import IndelibleAttributeError
48 raise IndelibleAttributeError( name )
50 def __setattr__( class_, name: str, value: _a.Any ) -> None:
51 from .exceptions import IndelibleAttributeError
52 if hasattr( class_, name ): raise IndelibleAttributeError( name )
53 # Note: CPython cell class is not set in all circumstances.
54 # When it is, then we use two-argument form.
55 # Else, we use three-argument form.
56 try: super( ).__setattr__( name, value )
57 except TypeError:
58 super( ).__setattr__( # type: ignore[call-arg]
59 class_, name, value ) # type: ignore[arg-type]
61Class.__doc__ = __.generate_docstring(
62 Class,
63 'description of class factory class',
64 'class attributes accretion'
65)
68class ABCFactory( Class, __.ABCFactory ): # type: ignore[misc]
69 ''' Accretive abstract base classes (ABC). '''
71 def __setattr__( class_, name: str, value: _a.Any ) -> None:
72 # Bypass accretion machinery for ABC magic attributes.
73 if ( # pylint: disable=magic-value-comparison
74 '__abstractmethods__' == name or name.startswith( '_abc_' )
75 ):
76 __.ABCFactory.__setattr__( class_, name, value )
77 return
78 super( ).__setattr__( name, value )
80ABCFactory.__doc__ = __.generate_docstring(
81 ABCFactory,
82 'description of class factory class',
83 'class attributes accretion',
84 'abc attributes exemption',
85)
88__all__ = __.discover_public_attributes( globals( ) )