Coverage for sources/classcore/factories.py: 100%
32 statements
« prev ^ index » next coverage.py v7.9.1, created at 2025-07-01 19:09 +0000
« prev ^ index » next coverage.py v7.9.1, created at 2025-07-01 19: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''' Factories which produce metaclass implementations. '''
24from . import __
25from . import decorators as _decorators
26from . import nomina as _nomina
27from . import utilities as _utilities
30def produce_class_constructor(
31 attributes_namer: _nomina.AttributesNamer,
32 preprocessors: _nomina.ClassConstructionPreprocessors[ __.T ] = ( ),
33 postprocessors: _nomina.ClassConstructionPostprocessors[ __.T ] = ( ),
34) -> _nomina.ClassConstructor[ __.T ]:
35 ''' Produces constructors for classes. '''
37 def construct( # noqa: PLR0913
38 clscls: type[ __.T ],
39 superf: _nomina.ClassConstructorLigation,
40 name: str,
41 bases: tuple[ type, ... ],
42 namespace: dict[ str, __.typx.Any ],
43 arguments: __.NominativeArguments,
44 decorators: _nomina.Decorators[ __.T ],
45 ) -> type:
46 ''' Constructs class, applying decorators and hooks. '''
47 bases_ = list( bases )
48 arguments_ = dict( arguments )
49 decorators_ = list( decorators )
50 for preprocessor in preprocessors:
51 preprocessor(
52 clscls, name, bases_, namespace, arguments_, decorators_ )
53 cls = superf( clscls, name, tuple( bases_ ), namespace, **arguments_ )
54 # Some decorators create new classes, which invokes this method again.
55 # Short-circuit to prevent recursive decoration and other tangles.
56 progress_name = attributes_namer( 'class', 'in_progress' )
57 progress_name_m = _utilities.mangle_name( cls, progress_name )
58 in_progress = getattr( cls, progress_name_m, False )
59 if in_progress: return cls
60 setattr( cls, progress_name_m, True )
61 for postprocessor in postprocessors: postprocessor( cls, decorators_ )
62 cls = _decorators.apply_decorators( cls, decorators_ )
63 setattr( cls, progress_name_m, False )
64 return cls
66 return construct
69def produce_class_initializer(
70 attributes_namer: _nomina.AttributesNamer,
71 completers: _nomina.ClassInitializationCompleters = ( ),
72) -> _nomina.ClassInitializer:
73 ''' Produces initializers for classes. '''
75 def initialize(
76 cls: type,
77 superf: _nomina.InitializerLigation,
78 posargs: __.PositionalArguments,
79 nomargs: __.NominativeArguments,
80 ) -> None:
81 ''' Initializes class, applying hooks. '''
82 superf( *posargs, **nomargs )
83 progress_name = attributes_namer( 'class', 'in_progress' )
84 progress_name_m = _utilities.mangle_name( cls, progress_name )
85 in_progress = getattr( cls, progress_name_m, False )
86 if in_progress: return # If non-empty, then not top-level.
87 delattr( cls, progress_name_m )
88 for completer in completers: completer( cls )
90 return initialize