Coverage for sources/classcore/factories.py: 100%

32 statements  

« prev     ^ index     » next       coverage.py v7.10.7, created at 2025-09-24 19:22 +0000

1# vim: set filetype=python fileencoding=utf-8: 

2# -*- coding: utf-8 -*- 

3 

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#============================================================================# 

19 

20 

21''' Factories which produce metaclass implementations. ''' 

22 

23 

24from . import __ 

25from . import decorators as _decorators 

26from . import nomina as _nomina 

27from . import utilities as _utilities 

28 

29 

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. ''' 

36 

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 

65 

66 return construct 

67 

68 

69def produce_class_initializer( 

70 attributes_namer: _nomina.AttributesNamer, 

71 completers: _nomina.ClassInitializationCompleters = ( ), 

72) -> _nomina.ClassInitializer: 

73 ''' Produces initializers for classes. ''' 

74 

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 ) 

89 

90 return initialize