classcore 1.4.1__tar.gz → 1.5__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (24) hide show
  1. {classcore-1.4.1 → classcore-1.5}/PKG-INFO +1 -1
  2. {classcore-1.4.1 → classcore-1.5}/sources/classcore/__/doctab.py +0 -6
  3. {classcore-1.4.1 → classcore-1.5}/sources/classcore/__/imports.py +1 -1
  4. {classcore-1.4.1 → classcore-1.5}/sources/classcore/__init__.py +2 -2
  5. {classcore-1.4.1 → classcore-1.5}/sources/classcore/factories.py +3 -3
  6. {classcore-1.4.1 → classcore-1.5}/sources/classcore/nomina.py +68 -39
  7. {classcore-1.4.1 → classcore-1.5}/sources/classcore/standard/behaviors.py +40 -10
  8. {classcore-1.4.1 → classcore-1.5}/sources/classcore/standard/decorators.py +78 -46
  9. {classcore-1.4.1 → classcore-1.5}/sources/classcore/standard/dynadoc.py +20 -20
  10. {classcore-1.4.1 → classcore-1.5}/sources/classcore/standard/modules.py +5 -4
  11. {classcore-1.4.1 → classcore-1.5}/sources/classcore/standard/nomina.py +17 -9
  12. {classcore-1.4.1 → classcore-1.5}/sources/classcore/utilities.py +3 -0
  13. {classcore-1.4.1 → classcore-1.5}/.gitignore +0 -0
  14. {classcore-1.4.1 → classcore-1.5}/LICENSE.txt +0 -0
  15. {classcore-1.4.1 → classcore-1.5}/README.rst +0 -0
  16. {classcore-1.4.1 → classcore-1.5}/pyproject.toml +0 -0
  17. {classcore-1.4.1 → classcore-1.5}/sources/classcore/__/__init__.py +0 -0
  18. {classcore-1.4.1 → classcore-1.5}/sources/classcore/__/nomina.py +0 -0
  19. {classcore-1.4.1 → classcore-1.5}/sources/classcore/decorators.py +0 -0
  20. {classcore-1.4.1 → classcore-1.5}/sources/classcore/exceptions.py +0 -0
  21. {classcore-1.4.1 → classcore-1.5}/sources/classcore/py.typed +0 -0
  22. {classcore-1.4.1 → classcore-1.5}/sources/classcore/standard/__.py +0 -0
  23. {classcore-1.4.1 → classcore-1.5}/sources/classcore/standard/__init__.py +0 -0
  24. {classcore-1.4.1 → classcore-1.5}/sources/classcore/standard/classes.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: classcore
3
- Version: 1.4.1
3
+ Version: 1.5
4
4
  Summary: Foundational class factories and decorators.
5
5
  Project-URL: Homepage, https://github.com/emcd/python-classcore
6
6
  Project-URL: Documentation, https://emcd.github.io/python-classcore
@@ -67,10 +67,4 @@ fragments: _FragmentsTable = __.types.MappingProxyType( {
67
67
 
68
68
  'class dynadoc': ''' Is decorated by Dynadoc. ''',
69
69
 
70
- 'decorators':
71
- ''' Sequence of class decorators.
72
-
73
- Each element takes a class argument and returns a class.
74
- ''',
75
-
76
70
  } )
@@ -33,7 +33,7 @@ import re
33
33
  import sys
34
34
  import types
35
35
 
36
- import dynadoc
36
+ import dynadoc as ddoc
37
37
  import typing_extensions as typx
38
38
  # --- BEGIN: Injected by Copier ---
39
39
  # --- END: Injected by Copier ---
@@ -61,8 +61,8 @@ from .decorators import *
61
61
  from .factories import *
62
62
 
63
63
 
64
- __version__: __.typx.Annotated[ str, __.dynadoc.Visibilities.Reveal ]
65
- __version__ = '1.4.1'
64
+ __version__: __.typx.Annotated[ str, __.ddoc.Visibilities.Reveal ]
65
+ __version__ = '1.5'
66
66
 
67
67
 
68
68
  standard.dynadoc.assign_module_docstring( __name__, table = __.fragments )
@@ -29,8 +29,8 @@ from . import utilities as _utilities
29
29
 
30
30
  def produce_class_constructor(
31
31
  attributes_namer: _nomina.AttributesNamer,
32
- preprocessors: _nomina.ProduceConstructorPreprocsArgument[ __.T ] = ( ),
33
- postprocessors: _nomina.ProduceConstructorPostprocsArgument[ __.T ] = ( ),
32
+ preprocessors: _nomina.ClassConstructionPreprocessors[ __.T ] = ( ),
33
+ postprocessors: _nomina.ClassConstructionPostprocessors[ __.T ] = ( ),
34
34
  ) -> _nomina.ClassConstructor[ __.T ]:
35
35
  ''' Produces constructors for classes. '''
36
36
 
@@ -68,7 +68,7 @@ def produce_class_constructor(
68
68
 
69
69
  def produce_class_initializer(
70
70
  attributes_namer: _nomina.AttributesNamer,
71
- completers: _nomina.ProduceInitializerCompletersArgument = ( ),
71
+ completers: _nomina.ClassInitializationCompleters = ( ),
72
72
  ) -> _nomina.ClassInitializer:
73
73
  ''' Produces initializers for classes. '''
74
74
 
@@ -24,36 +24,68 @@
24
24
  from . import __
25
25
 
26
26
 
27
- AttributesNamer: __.typx.TypeAlias = __.cabc.Callable[ [ str, str ], str ]
27
+ AttributesNamer: __.typx.TypeAlias = __.typx.Annotated[
28
+ __.cabc.Callable[ [ str, str ], str ],
29
+ __.ddoc.Doc(
30
+ ''' Names attribute from level and core arguments.
31
+
32
+ Level will be one of 'class', 'instances', or 'instance'.
33
+ Core will be the core of the name as supplied this package.
34
+
35
+ Can be used by downstream packages to determine names of
36
+ bookkeeping attributes assigned by this package.
37
+ ''' ),
38
+ ]
28
39
 
29
40
  Decorator: __.typx.TypeAlias = __.typx.Annotated[
30
41
  __.cabc.Callable[ [ type[ __.U ] ], type[ __.U ] ],
31
- __.dynadoc.Doc(
42
+ __.ddoc.Doc(
32
43
  ''' Class decorator.
33
44
 
34
45
  Takes class argument and returns class.
35
46
  ''' ),
36
47
  ]
37
48
  Decorators: __.typx.TypeAlias = __.typx.Annotated[
38
- __.cabc.Sequence[ Decorator[ __.U ] ], __.dynadoc.Fname( 'decorators' )
49
+ __.cabc.Sequence[ Decorator[ __.U ] ],
50
+ __.ddoc.Doc(
51
+ ''' Sequence of class decorators.
52
+
53
+ Each element takes a class argument and returns a class.
54
+ ''' ),
39
55
  ]
40
56
  DecoratorsMutable: __.typx.TypeAlias = __.typx.Annotated[
41
57
  __.cabc.MutableSequence[ Decorator[ __.U ] ],
42
- __.dynadoc.Fname( 'decorators' ),
43
- __.dynadoc.Doc(
44
- ''' Decorators may be inserted or removed from sequence. ''' ),
58
+ __.ddoc.Doc(
59
+ ''' Sequence of class decorators.
60
+
61
+ Each element takes a class argument and returns a class.
62
+
63
+ Decorators may be inserted or removed from sequence.
64
+ ''' ),
45
65
  ]
46
66
 
47
- DecorationPreparer: __.typx.TypeAlias = (
48
- __.cabc.Callable[ [ type[ __.U ], DecoratorsMutable[ __.U ] ], None ] )
49
- DecorationPreparers: __.typx.TypeAlias = (
50
- __.cabc.Sequence[ DecorationPreparer[ __.U ] ] )
51
- DecorationPreparersFactory: __.typx.TypeAlias = (
52
- __.cabc.Callable[ [ ], DecorationPreparers[ __.U ] ] )
67
+ DecorationPreparer: __.typx.TypeAlias = __.typx.Annotated[
68
+ __.cabc.Callable[ [ type[ __.U ], DecoratorsMutable[ __.U ] ], None ],
69
+ __.ddoc.Doc(
70
+ ''' Class decoration preparer.
71
+
72
+ Takes class and mutable sequence of decorators as arguments.
73
+ Can alter the sequence.
74
+ ''' ),
75
+ ]
76
+ DecorationPreparers: __.typx.TypeAlias = __.typx.Annotated[
77
+ __.cabc.Sequence[ DecorationPreparer[ __.U ] ],
78
+ __.ddoc.Doc(
79
+ ''' Sequence of class decoration preparers.
80
+
81
+ Each element takes class and mutable sequence of decorators as
82
+ arguments. And, each element can alter the sequence.
83
+ ''' ),
84
+ ]
53
85
 
54
86
  ClassConstructorLigation: __.typx.TypeAlias = __.typx.Annotated[
55
87
  __.cabc.Callable[ ..., type ],
56
- __.dynadoc.Doc(
88
+ __.ddoc.Doc(
57
89
  ''' Bound class constructor function.
58
90
 
59
91
  Usually from ``super( ).__new__`` or a partial function.
@@ -61,7 +93,7 @@ ClassConstructorLigation: __.typx.TypeAlias = __.typx.Annotated[
61
93
  ]
62
94
  InitializerLigation: __.typx.TypeAlias = __.typx.Annotated[
63
95
  __.cabc.Callable[ ..., None ],
64
- __.dynadoc.Doc(
96
+ __.ddoc.Doc(
65
97
  ''' Bound initializer function.
66
98
 
67
99
  Usually from ``super( ).__init__`` or a partial function.
@@ -69,7 +101,7 @@ InitializerLigation: __.typx.TypeAlias = __.typx.Annotated[
69
101
  ]
70
102
  AssignerLigation: __.typx.TypeAlias = __.typx.Annotated[
71
103
  __.cabc.Callable[ [ str, __.typx.Any ], None ],
72
- __.dynadoc.Doc(
104
+ __.ddoc.Doc(
73
105
  ''' Bound attributes assigner function.
74
106
 
75
107
  Usually from ``super( ).__setattr__`` or a partial function.
@@ -77,7 +109,7 @@ AssignerLigation: __.typx.TypeAlias = __.typx.Annotated[
77
109
  ]
78
110
  DeleterLigation: __.typx.TypeAlias = __.typx.Annotated[
79
111
  __.cabc.Callable[ [ str ], None ],
80
- __.dynadoc.Doc(
112
+ __.ddoc.Doc(
81
113
  ''' Bound attributes deleter function.
82
114
 
83
115
  Usually from ``super( ).__delattr__`` or a partial function.
@@ -85,7 +117,7 @@ DeleterLigation: __.typx.TypeAlias = __.typx.Annotated[
85
117
  ]
86
118
  SurveyorLigation: __.typx.TypeAlias = __.typx.Annotated[
87
119
  __.cabc.Callable[ [ ], __.cabc.Iterable[ str ] ],
88
- __.dynadoc.Doc(
120
+ __.ddoc.Doc(
89
121
  ''' Bound attributes surveyor function.
90
122
 
91
123
  Usually from ``super( ).__dir__`` or a partial function.
@@ -105,30 +137,44 @@ ClassConstructionPreprocessor: __.typx.TypeAlias = __.typx.Annotated[
105
137
  ],
106
138
  None
107
139
  ],
108
- __.dynadoc.Doc(
140
+ __.ddoc.Doc(
109
141
  ''' Processes class data before construction.
110
142
 
111
143
  For use cases, such as argument conversion.
112
144
  ''' ),
113
145
  ]
146
+ ClassConstructionPreprocessors: __.typx.TypeAlias = __.typx.Annotated[
147
+ __.cabc.Sequence[ ClassConstructionPreprocessor[ __.U ] ],
148
+ __.ddoc.Doc( ''' Processors to apply before construction of class. ''' ),
149
+ ]
114
150
  ClassConstructionPostprocessor: __.typx.TypeAlias = __.typx.Annotated[
115
151
  __.cabc.Callable[ [ type, DecoratorsMutable[ __.U ] ], None ],
116
- __.dynadoc.Doc(
152
+ __.ddoc.Doc(
117
153
  ''' Processes class before decoration.
118
154
 
119
155
  For use cases, such as decorator list manipulation.
120
156
  ''' ),
121
157
  ]
158
+ ClassConstructionPostprocessors: __.typx.TypeAlias = __.typx.Annotated[
159
+ __.cabc.Sequence[ ClassConstructionPostprocessor[ __.U ] ],
160
+ __.ddoc.Doc(
161
+ ''' Processors to apply before decoration of class. ''' ),
162
+ ]
122
163
  # TODO: ClassInitializationPreparer (arguments mutation)
123
164
  ClassInitializationCompleter: __.typx.TypeAlias = __.typx.Annotated[
124
165
  __.cabc.Callable[ [ type ], None ],
125
- __.dynadoc.Doc(
166
+ __.ddoc.Doc(
126
167
  ''' Completes initialization of class.
127
168
 
128
169
  For use cases, such as enabling immutability once all other
129
170
  initialization has occurred.
130
171
  ''' ),
131
172
  ]
173
+ ClassInitializationCompleters: __.typx.TypeAlias = __.typx.Annotated[
174
+ __.cabc.Sequence[ ClassInitializationCompleter ],
175
+ __.ddoc.Doc(
176
+ ''' Processors to apply at final stage of class initialization. ''' ),
177
+ ]
132
178
 
133
179
 
134
180
  ClassConstructor: __.typx.TypeAlias = __.typx.Annotated[
@@ -144,7 +190,7 @@ ClassConstructor: __.typx.TypeAlias = __.typx.Annotated[
144
190
  ],
145
191
  type
146
192
  ],
147
- __.dynadoc.Doc( ''' Constructor to use with metaclass. ''' ),
193
+ __.ddoc.Doc( ''' Constructor to use with metaclass. ''' ),
148
194
  ]
149
195
  ClassInitializer: __.typx.TypeAlias = __.typx.Annotated[
150
196
  __.cabc.Callable[
@@ -156,22 +202,5 @@ ClassInitializer: __.typx.TypeAlias = __.typx.Annotated[
156
202
  ],
157
203
  None
158
204
  ],
159
- __.dynadoc.Doc( ''' Initializer to use with metaclass. ''' ),
160
- ]
161
-
162
-
163
- ProduceConstructorPreprocsArgument: __.typx.TypeAlias = __.typx.Annotated[
164
- __.cabc.Sequence[ ClassConstructionPreprocessor[ __.U ] ],
165
- __.dynadoc.Doc(
166
- ''' Processors to apply before construction of class. ''' ),
167
- ]
168
- ProduceConstructorPostprocsArgument: __.typx.TypeAlias = __.typx.Annotated[
169
- __.cabc.Sequence[ ClassConstructionPostprocessor[ __.U ] ],
170
- __.dynadoc.Doc(
171
- ''' Processors to apply before decoration of class. ''' ),
172
- ]
173
- ProduceInitializerCompletersArgument: __.typx.TypeAlias = __.typx.Annotated[
174
- __.cabc.Sequence[ ClassInitializationCompleter ],
175
- __.dynadoc.Doc(
176
- ''' Processors to apply at final stage of class initialization. ''' ),
205
+ __.ddoc.Doc( ''' Initializer to use with metaclass. ''' ),
177
206
  ]
@@ -28,6 +28,26 @@ from . import __
28
28
  from . import nomina as _nomina
29
29
 
30
30
 
31
+ def access_core_function( # noqa: PLR0913
32
+ cls: type, /, *,
33
+ attributes_namer: _nomina.AttributesNamer,
34
+ arguments: __.cabc.Mapping[ str, __.typx.Any ],
35
+ level: str,
36
+ name: str,
37
+ default: __.cabc.Callable[ ..., __.typx.Any ],
38
+ ) -> __.cabc.Callable[ ..., __.typx.Any ]:
39
+ ''' Accesses core behavior function.
40
+
41
+ First checks for override argument, then checks for heritable
42
+ attribute. Finally, falls back to provided default.
43
+ '''
44
+ argument_name = f"{level}_{name}_core"
45
+ attribute_name = attributes_namer( level, f"{name}_core" )
46
+ return (
47
+ arguments.get( argument_name )
48
+ or getattr( cls, attribute_name, default ) )
49
+
50
+
31
51
  def assign_attribute_if_mutable( # noqa: PLR0913
32
52
  obj: object, /, *,
33
53
  ligation: _nomina.AssignerLigation,
@@ -225,6 +245,10 @@ def produce_class_construction_postprocessor(
225
245
  ) -> _nomina.ClassConstructionPostprocessor[ __.U ]:
226
246
  ''' Produces construction processor which determines class decorators. '''
227
247
  arguments_name = attributes_namer( 'class', 'construction_arguments' )
248
+ cores_default = dict(
249
+ assigner = assign_attribute_if_mutable,
250
+ deleter = delete_attribute_if_mutable,
251
+ surveyor = survey_visible_attributes )
228
252
 
229
253
  def postprocess(
230
254
  cls: type, decorators: _nomina.DecoratorsMutable[ __.U ]
@@ -236,16 +260,19 @@ def produce_class_construction_postprocessor(
236
260
  dynadoc_cfg_name = (
237
261
  attributes_namer( 'classes', 'dynadoc_configuration' ) )
238
262
  dynadoc_cfg = getattr( clscls, dynadoc_cfg_name, { } )
239
- decorators.append( __.dynadoc.with_docstring( **dynadoc_cfg ) )
263
+ decorators.append( __.ddoc.with_docstring( **dynadoc_cfg ) )
240
264
  dcls_spec = getattr( cls, '__dataclass_transform__', None )
241
265
  if not dcls_spec: # either base class or metaclass may be marked
242
266
  dcls_spec = getattr( clscls, '__dataclass_transform__', None )
243
- instances_assigner = arguments.get(
244
- 'instances_assigner_core', assign_attribute_if_mutable )
245
- instances_deleter = arguments.get(
246
- 'instances_deleter_core', delete_attribute_if_mutable )
247
- instances_surveyor = arguments.get(
248
- 'instances_surveyor_core', survey_visible_attributes )
267
+ cores = { }
268
+ for core_name in ( 'assigner', 'deleter', 'surveyor' ):
269
+ core_function = access_core_function(
270
+ cls,
271
+ attributes_namer = attributes_namer,
272
+ arguments = arguments,
273
+ level = 'instances', name = core_name,
274
+ default = cores_default[ core_name ] )
275
+ cores[ core_name ] = core_function
249
276
  instances_mutables = arguments.get(
250
277
  'instances_mutables', __.mutables_default )
251
278
  instances_visibles = arguments.get(
@@ -261,9 +288,12 @@ def produce_class_construction_postprocessor(
261
288
  decorator: _nomina.Decorator[ __.U ] = decorator_factory(
262
289
  attributes_namer = attributes_namer,
263
290
  error_class_provider = error_class_provider,
264
- assigner_core = instances_assigner,
265
- deleter_core = instances_deleter,
266
- surveyor_core = instances_surveyor,
291
+ assigner_core = __.typx.cast(
292
+ _nomina.AssignerCore, cores[ 'assigner' ] ),
293
+ deleter_core = __.typx.cast(
294
+ _nomina.DeleterCore, cores[ 'deleter' ] ),
295
+ surveyor_core = __.typx.cast(
296
+ _nomina.SurveyorCore, cores[ 'surveyor' ] ),
267
297
  mutables = instances_mutables,
268
298
  visibles = instances_visibles )
269
299
  decorators.append( decorator )
@@ -21,8 +21,6 @@
21
21
  ''' Standard decorators. '''
22
22
  # TODO? Add attribute value transformer as standard decorator argument.
23
23
 
24
- # ruff: noqa: F401
25
-
26
24
 
27
25
  from .. import factories as _factories
28
26
  from .. import utilities as _utilities
@@ -190,13 +188,34 @@ def class_factory( # noqa: PLR0913
190
188
  return decorate
191
189
 
192
190
 
193
- def produce_instances_initialization_decorator(
191
+ def produce_instances_initialization_decorator( # noqa: PLR0913
194
192
  attributes_namer: _nomina.AttributesNamer,
193
+ assigner_core: __.typx.Optional[ _nomina.AssignerCore ],
194
+ deleter_core: __.typx.Optional[ _nomina.DeleterCore ],
195
+ surveyor_core: __.typx.Optional[ _nomina.SurveyorCore ],
195
196
  mutables: _nomina.BehaviorExclusionVerifiersOmni,
196
197
  visibles: _nomina.BehaviorExclusionVerifiersOmni,
197
198
  ) -> _nomina.Decorator[ __.U ]:
198
199
  ''' Produces decorator to inject '__init__' method into class. '''
200
+ cores = dict(
201
+ instances_assigner_core = assigner_core,
202
+ instances_deleter_core = deleter_core,
203
+ instances_surveyor_core = surveyor_core )
204
+ cores_default = dict(
205
+ assigner = _behaviors.assign_attribute_if_mutable,
206
+ deleter = _behaviors.delete_attribute_if_mutable,
207
+ surveyor = _behaviors.survey_visible_attributes )
208
+
199
209
  def decorate( cls: type[ __.U ] ) -> type[ __.U ]:
210
+ for core_name in ( 'assigner', 'deleter', 'surveyor' ):
211
+ core_function = _behaviors.access_core_function(
212
+ cls,
213
+ attributes_namer = attributes_namer,
214
+ arguments = cores,
215
+ level = 'instances', name = core_name,
216
+ default = cores_default[ core_name ] )
217
+ core_aname = attributes_namer( 'instances', f"{core_name}_core" )
218
+ setattr( cls, core_aname, core_function )
200
219
  behaviors: set[ str ] = set( )
201
220
  behaviors_name = attributes_namer( 'instance', 'behaviors' )
202
221
  _behaviors.record_behavior(
@@ -253,12 +272,18 @@ def produce_attributes_assignment_decorator(
253
272
  level: str,
254
273
  attributes_namer: _nomina.AttributesNamer,
255
274
  error_class_provider: _nomina.ErrorClassProvider,
256
- implementation_core: _nomina.AssignerCore,
275
+ implementation_core: __.typx.Optional[ _nomina.AssignerCore ],
257
276
  ) -> _nomina.Decorator[ __.U ]:
258
277
  ''' Produces decorator to inject '__setattr__' method into class. '''
259
278
  def decorate( cls: type[ __.U ] ) -> type[ __.U ]:
260
279
  leveli = 'class' if level == 'classes' else level
261
280
  original = cls.__dict__.get( '__setattr__' )
281
+ core = _behaviors.access_core_function(
282
+ cls,
283
+ attributes_namer = attributes_namer,
284
+ arguments = { f"{leveli}_assigner": implementation_core },
285
+ level = leveli, name = 'assigner',
286
+ default = _behaviors.assign_attribute_if_mutable )
262
287
 
263
288
  if original is None:
264
289
 
@@ -270,7 +295,7 @@ def produce_attributes_assignment_decorator(
270
295
  if cls is not type( self ):
271
296
  ligation( name, value )
272
297
  return
273
- implementation_core(
298
+ core(
274
299
  self,
275
300
  ligation = ligation,
276
301
  attributes_namer = attributes_namer,
@@ -291,7 +316,7 @@ def produce_attributes_assignment_decorator(
291
316
  if cls is not type( self ):
292
317
  ligation( name, value )
293
318
  return
294
- implementation_core(
319
+ core(
295
320
  self,
296
321
  ligation = ligation,
297
322
  attributes_namer = attributes_namer,
@@ -310,12 +335,18 @@ def produce_attributes_deletion_decorator(
310
335
  level: str,
311
336
  attributes_namer: _nomina.AttributesNamer,
312
337
  error_class_provider: _nomina.ErrorClassProvider,
313
- implementation_core: _nomina.DeleterCore,
338
+ implementation_core: __.typx.Optional[ _nomina.DeleterCore ],
314
339
  ) -> _nomina.Decorator[ __.U ]:
315
340
  ''' Produces decorator to inject '__delattr__' method into class. '''
316
341
  def decorate( cls: type[ __.U ] ) -> type[ __.U ]:
317
342
  leveli = 'class' if level == 'classes' else level
318
343
  original = cls.__dict__.get( '__delattr__' )
344
+ core = _behaviors.access_core_function(
345
+ cls,
346
+ attributes_namer = attributes_namer,
347
+ arguments = { f"{leveli}_deleter": implementation_core },
348
+ level = leveli, name = 'deleter',
349
+ default = _behaviors.delete_attribute_if_mutable )
319
350
 
320
351
  if original is None:
321
352
 
@@ -325,7 +356,7 @@ def produce_attributes_deletion_decorator(
325
356
  if cls is not type( self ):
326
357
  ligation( name )
327
358
  return
328
- implementation_core(
359
+ core(
329
360
  self,
330
361
  ligation = ligation,
331
362
  attributes_namer = attributes_namer,
@@ -344,7 +375,7 @@ def produce_attributes_deletion_decorator(
344
375
  if cls is not type( self ):
345
376
  ligation( name )
346
377
  return
347
- implementation_core(
378
+ core(
348
379
  self,
349
380
  ligation = ligation,
350
381
  attributes_namer = attributes_namer,
@@ -362,12 +393,18 @@ def produce_attributes_deletion_decorator(
362
393
  def produce_attributes_surveillance_decorator(
363
394
  level: str,
364
395
  attributes_namer: _nomina.AttributesNamer,
365
- implementation_core: _nomina.SurveyorCore,
396
+ implementation_core: __.typx.Optional[ _nomina.SurveyorCore ],
366
397
  ) -> _nomina.Decorator[ __.U ]:
367
398
  ''' Produces decorator to inject '__dir__' method into class. '''
368
399
  def decorate( cls: type[ __.U ] ) -> type[ __.U ]:
369
400
  leveli = 'class' if level == 'classes' else level
370
401
  original = cls.__dict__.get( '__dir__' )
402
+ core = _behaviors.access_core_function(
403
+ cls,
404
+ attributes_namer = attributes_namer,
405
+ arguments = { f"{leveli}_surveyor": implementation_core },
406
+ level = leveli, name = 'surveyor',
407
+ default = _behaviors.survey_visible_attributes )
371
408
 
372
409
  if original is None:
373
410
 
@@ -377,7 +414,7 @@ def produce_attributes_surveillance_decorator(
377
414
  ligation = super( cls, self ).__dir__
378
415
  # Only enforce behaviors at start of MRO.
379
416
  if cls is not type( self ): return ligation( )
380
- return implementation_core(
417
+ return core(
381
418
  self,
382
419
  ligation = ligation,
383
420
  attributes_namer = attributes_namer,
@@ -394,7 +431,7 @@ def produce_attributes_surveillance_decorator(
394
431
  ligation = __.funct.partial( original, self )
395
432
  # Only enforce behaviors at start of MRO.
396
433
  if cls is not type( self ): return ligation( )
397
- return implementation_core(
434
+ return core(
398
435
  self,
399
436
  ligation = ligation,
400
437
  attributes_namer = attributes_namer,
@@ -412,12 +449,9 @@ def dataclass_with_standard_behaviors( # noqa: PLR0913
412
449
  attributes_namer: _nomina.AttributesNamer = __.calculate_attrname,
413
450
  error_class_provider: _nomina.ErrorClassProvider = __.provide_error_class,
414
451
  decorators: _nomina.Decorators[ __.U ] = ( ),
415
- assigner_core: _nomina.AssignerCore = (
416
- _behaviors.assign_attribute_if_mutable ),
417
- deleter_core: _nomina.DeleterCore = (
418
- _behaviors.delete_attribute_if_mutable ),
419
- surveyor_core: _nomina.SurveyorCore = (
420
- _behaviors.survey_visible_attributes ),
452
+ assigner_core: __.typx.Optional[ _nomina.AssignerCore ] = None,
453
+ deleter_core: __.typx.Optional[ _nomina.DeleterCore ] = None,
454
+ surveyor_core: __.typx.Optional[ _nomina.SurveyorCore ] = None,
421
455
  mutables: _nomina.BehaviorExclusionVerifiersOmni = __.mutables_default,
422
456
  visibles: _nomina.BehaviorExclusionVerifiersOmni = __.visibles_default,
423
457
  ) -> _nomina.Decorator[ __.U ]:
@@ -445,12 +479,9 @@ def with_standard_behaviors( # noqa: PLR0913
445
479
  attributes_namer: _nomina.AttributesNamer = __.calculate_attrname,
446
480
  error_class_provider: _nomina.ErrorClassProvider = __.provide_error_class,
447
481
  decorators: _nomina.Decorators[ __.U ] = ( ),
448
- assigner_core: _nomina.AssignerCore = (
449
- _behaviors.assign_attribute_if_mutable ),
450
- deleter_core: _nomina.DeleterCore = (
451
- _behaviors.delete_attribute_if_mutable ),
452
- surveyor_core: _nomina.SurveyorCore = (
453
- _behaviors.survey_visible_attributes ),
482
+ assigner_core: __.typx.Optional[ _nomina.AssignerCore ] = None,
483
+ deleter_core: __.typx.Optional[ _nomina.DeleterCore ] = None,
484
+ surveyor_core: __.typx.Optional[ _nomina.SurveyorCore ] = None,
454
485
  mutables: _nomina.BehaviorExclusionVerifiersOmni = __.mutables_default,
455
486
  visibles: _nomina.BehaviorExclusionVerifiersOmni = __.visibles_default,
456
487
  ) -> _nomina.Decorator[ __.U ]:
@@ -488,9 +519,9 @@ def _produce_instances_decoration_preparers(
488
519
  def _produce_instances_decorators( # noqa: PLR0913
489
520
  attributes_namer: _nomina.AttributesNamer,
490
521
  error_class_provider: _nomina.ErrorClassProvider,
491
- assigner_core: _nomina.AssignerCore,
492
- deleter_core: _nomina.DeleterCore,
493
- surveyor_core: _nomina.SurveyorCore,
522
+ assigner_core: __.typx.Optional[ _nomina.AssignerCore ],
523
+ deleter_core: __.typx.Optional[ _nomina.DeleterCore ],
524
+ surveyor_core: __.typx.Optional[ _nomina.SurveyorCore ],
494
525
  mutables: _nomina.BehaviorExclusionVerifiersOmni,
495
526
  visibles: _nomina.BehaviorExclusionVerifiersOmni,
496
527
  ) -> _nomina.Decorators[ __.U ]:
@@ -499,24 +530,25 @@ def _produce_instances_decorators( # noqa: PLR0913
499
530
  decorators.append(
500
531
  produce_instances_initialization_decorator(
501
532
  attributes_namer = attributes_namer,
533
+ assigner_core = assigner_core,
534
+ deleter_core = deleter_core,
535
+ surveyor_core = surveyor_core,
502
536
  mutables = mutables, visibles = visibles ) )
503
- if mutables != '*':
504
- decorators.append(
505
- produce_attributes_assignment_decorator(
506
- level = 'instances',
507
- attributes_namer = attributes_namer,
508
- error_class_provider = error_class_provider,
509
- implementation_core = assigner_core ) )
510
- decorators.append(
511
- produce_attributes_deletion_decorator(
512
- level = 'instances',
513
- attributes_namer = attributes_namer,
514
- error_class_provider = error_class_provider,
515
- implementation_core = deleter_core ) )
516
- if visibles != '*':
517
- decorators.append(
518
- produce_attributes_surveillance_decorator(
519
- level = 'instances',
520
- attributes_namer = attributes_namer,
521
- implementation_core = surveyor_core ) )
537
+ decorators.append(
538
+ produce_attributes_assignment_decorator(
539
+ level = 'instances',
540
+ attributes_namer = attributes_namer,
541
+ error_class_provider = error_class_provider,
542
+ implementation_core = assigner_core ) )
543
+ decorators.append(
544
+ produce_attributes_deletion_decorator(
545
+ level = 'instances',
546
+ attributes_namer = attributes_namer,
547
+ error_class_provider = error_class_provider,
548
+ implementation_core = deleter_core ) )
549
+ decorators.append(
550
+ produce_attributes_surveillance_decorator(
551
+ level = 'instances',
552
+ attributes_namer = attributes_namer,
553
+ implementation_core = surveyor_core ) )
522
554
  return decorators
@@ -26,34 +26,34 @@ from . import __
26
26
  from . import nomina as _nomina
27
27
 
28
28
 
29
- dynadoc_context = __.dynadoc.produce_context( )
29
+ dynadoc_context = __.ddoc.produce_context( )
30
30
  dynadoc_class_introspection_control = (
31
- __.dynadoc.ClassIntrospectionControl(
31
+ __.ddoc.ClassIntrospectionControl(
32
32
  inheritance = True,
33
33
  introspectors = (
34
- __.dynadoc.introspection.introspect_special_classes, ) ) )
34
+ __.ddoc.introspection.introspect_special_classes, ) ) )
35
35
  dynadoc_module_introspection_control = (
36
- __.dynadoc.ModuleIntrospectionControl( ) )
36
+ __.ddoc.ModuleIntrospectionControl( ) )
37
37
 
38
38
 
39
39
  def dynadoc_avoid_immutables(
40
40
  objct: object,
41
- introspection: __.dynadoc.IntrospectionControl,
41
+ introspection: __.ddoc.IntrospectionControl,
42
42
  attributes_namer: _nomina.AttributesNamer,
43
- ) -> __.dynadoc.IntrospectionControl:
43
+ ) -> __.ddoc.IntrospectionControl:
44
44
  ''' Disables introspection of immutable objects. '''
45
45
  if __.inspect.isclass( objct ):
46
46
  behaviors_name = attributes_namer( 'class', 'behaviors' )
47
47
  behaviors = _utilities.getattr0( objct, behaviors_name, frozenset( ) )
48
48
  if _nomina.immutability_label in behaviors:
49
49
  return introspection.with_limit(
50
- __.dynadoc.IntrospectionLimit( disable = True ) )
50
+ __.ddoc.IntrospectionLimit( disable = True ) )
51
51
  return introspection
52
52
 
53
53
 
54
54
  def produce_dynadoc_introspection_limiter(
55
55
  attributes_namer: _nomina.AttributesNamer = __.calculate_attrname,
56
- ) -> __.dynadoc.IntrospectionLimiter:
56
+ ) -> __.ddoc.IntrospectionLimiter:
57
57
  ''' Produces introspection limiter which avoids immutable objects. '''
58
58
  return __.funct.partial(
59
59
  dynadoc_avoid_immutables, attributes_namer = attributes_namer )
@@ -63,17 +63,17 @@ dynadoc_introspection_limiter = produce_dynadoc_introspection_limiter( )
63
63
 
64
64
  def produce_dynadoc_introspection_control(
65
65
  enable: bool = True,
66
- class_control: __.dynadoc.ClassIntrospectionControl = (
66
+ class_control: __.ddoc.ClassIntrospectionControl = (
67
67
  dynadoc_class_introspection_control ),
68
- module_control: __.dynadoc.ModuleIntrospectionControl = (
68
+ module_control: __.ddoc.ModuleIntrospectionControl = (
69
69
  dynadoc_module_introspection_control ),
70
- limiters: __.dynadoc.IntrospectionLimiters = (
70
+ limiters: __.ddoc.IntrospectionLimiters = (
71
71
  dynadoc_introspection_limiter, ),
72
- targets: __.dynadoc.IntrospectionTargets = (
73
- __.dynadoc.IntrospectionTargetsSansModule ),
74
- ) -> __.dynadoc.IntrospectionControl:
72
+ targets: __.ddoc.IntrospectionTargets = (
73
+ __.ddoc.IntrospectionTargetsSansModule ),
74
+ ) -> __.ddoc.IntrospectionControl:
75
75
  ''' Produces compatible Dynadoc introspection control. '''
76
- return __.dynadoc.IntrospectionControl(
76
+ return __.ddoc.IntrospectionControl(
77
77
  enable = enable,
78
78
  class_control = class_control,
79
79
  module_control = module_control,
@@ -83,18 +83,18 @@ def produce_dynadoc_introspection_control(
83
83
  dynadoc_introspection_on_class = produce_dynadoc_introspection_control( )
84
84
  dynadoc_introspection_on_package = (
85
85
  produce_dynadoc_introspection_control(
86
- targets = __.dynadoc.IntrospectionTargetsOmni ) )
86
+ targets = __.ddoc.IntrospectionTargetsOmni ) )
87
87
 
88
88
 
89
89
  def assign_module_docstring( # noqa: PLR0913
90
90
  module: str | __.types.ModuleType, /,
91
- *fragments: __.dynadoc.interfaces.Fragment,
91
+ *fragments: __.ddoc.interfaces.Fragment,
92
92
  context: _nomina.DynadocContextArgument = dynadoc_context,
93
93
  introspection: _nomina.DynadocIntrospectionArgument = (
94
94
  dynadoc_introspection_on_package ),
95
95
  preserve: _nomina.DynadocPreserveArgument = True,
96
- renderer: __.dynadoc.xtnsapi.Renderer = (
97
- __.dynadoc.assembly.renderer_default ),
96
+ renderer: __.ddoc.xtnsapi.Renderer = (
97
+ __.ddoc.assembly.renderer_default ),
98
98
  table: _nomina.DynadocTableArgument = __.dictproxy_empty,
99
99
  ) -> None:
100
100
  ''' Updates module docstring based on introspection.
@@ -104,7 +104,7 @@ def assign_module_docstring( # noqa: PLR0913
104
104
 
105
105
  By default, ignores previously-decorated immutable classes.
106
106
  '''
107
- __.dynadoc.assign_module_docstring(
107
+ __.ddoc.assign_module_docstring(
108
108
  module,
109
109
  *fragments,
110
110
  context = context,
@@ -34,20 +34,20 @@ class Module( _classes.Object, __.types.ModuleType ):
34
34
  def reclassify_modules(
35
35
  attributes: __.typx.Annotated[
36
36
  __.cabc.Mapping[ str, __.typx.Any ] | __.types.ModuleType | str,
37
- __.dynadoc.Doc(
37
+ __.ddoc.Doc(
38
38
  ''' Module, module name, or dictionary of object attributes. ''' ),
39
39
  ], /, *,
40
40
  attributes_namer: __.typx.Annotated[
41
41
  _nomina.AttributesNamer,
42
- __.dynadoc.Doc(
42
+ __.ddoc.Doc(
43
43
  ''' Attributes namer function with which to seal class. ''' ),
44
44
  ] = __.calculate_attrname,
45
45
  recursive: __.typx.Annotated[
46
- bool, __.dynadoc.Doc( ''' Recursively reclassify package modules? ''' )
46
+ bool, __.ddoc.Doc( ''' Recursively reclassify package modules? ''' )
47
47
  ] = False,
48
48
  replacement_class: __.typx.Annotated[
49
49
  type[ __.types.ModuleType ],
50
- __.dynadoc.Doc( ''' New class for module. ''' ),
50
+ __.ddoc.Doc( ''' New class for module. ''' ),
51
51
  ] = Module,
52
52
  ) -> None:
53
53
  # TODO? Ensure correct operation with namespace packages.
@@ -78,6 +78,7 @@ def reclassify_modules(
78
78
  if recursive:
79
79
  reclassify_modules(
80
80
  value,
81
+ attributes_namer = attributes_namer,
81
82
  recursive = True,
82
83
  replacement_class = replacement_class )
83
84
  if isinstance( value, replacement_class ): continue
@@ -46,8 +46,15 @@ BehaviorExclusionVerifiers: __.typx.TypeAlias = (
46
46
  __.cabc.Sequence[ BehaviorExclusionVerifier ] )
47
47
  BehaviorExclusionVerifiersOmni: __.typx.TypeAlias = (
48
48
  BehaviorExclusionVerifiers | __.typx.Literal[ '*' ] )
49
- ErrorClassProvider: __.typx.TypeAlias = (
50
- __.cabc.Callable[ [ str ], type[ Exception ] ] )
49
+ ErrorClassProvider: __.typx.TypeAlias = __.typx.Annotated[
50
+ __.cabc.Callable[ [ str ], type[ Exception ] ],
51
+ __.ddoc.Doc(
52
+ ''' Takes name of exception class and returns corresponding class.
53
+
54
+ Can be used by downstream packages to provide exceptions from their
55
+ own hierarchies rather than the hierarchy from this package.
56
+ ''' ),
57
+ ]
51
58
 
52
59
 
53
60
  class AssignerCore( __.typx.Protocol ):
@@ -103,9 +110,10 @@ class ClassPreparer( __.typx.Protocol ):
103
110
 
104
111
 
105
112
  DynadocConfiguration: __.typx.TypeAlias = __.cabc.Mapping[ str, __.typx.Any ]
113
+ # TODO: Use argument type aliases from 'dynadoc' package.
106
114
  DynadocContextArgument: __.typx.TypeAlias = __.typx.Annotated[
107
- __.dynadoc.Context,
108
- __.dynadoc.Doc(
115
+ __.ddoc.Context,
116
+ __.ddoc.Doc(
109
117
  ''' Dynadoc context.
110
118
 
111
119
  Renderer, dictionaries for resolution of stringified annotations,
@@ -113,8 +121,8 @@ DynadocContextArgument: __.typx.TypeAlias = __.typx.Annotated[
113
121
  ''' ),
114
122
  ]
115
123
  DynadocIntrospectionArgument: __.typx.TypeAlias = __.typx.Annotated[
116
- __.dynadoc.IntrospectionControl,
117
- __.dynadoc.Doc(
124
+ __.ddoc.IntrospectionControl,
125
+ __.ddoc.Doc(
118
126
  ''' Dynadoc introspection control.
119
127
 
120
128
  Which kinds of object to recursively introspect?
@@ -124,15 +132,15 @@ DynadocIntrospectionArgument: __.typx.TypeAlias = __.typx.Annotated[
124
132
  ''' ),
125
133
  ]
126
134
  DynadocPreserveArgument: __.typx.TypeAlias = __.typx.Annotated[
127
- bool, __.dynadoc.Doc( ''' Preserve existing docstring? ''' )
135
+ bool, __.ddoc.Doc( ''' Preserve existing docstring? ''' )
128
136
  ]
129
137
  DynadocTableArgument: __.typx.TypeAlias = __.typx.Annotated[
130
138
  __.cabc.Mapping[ str, str ],
131
- __.dynadoc.Doc( ''' Table of documentation fragments. ''' ),
139
+ __.ddoc.Doc( ''' Table of documentation fragments. ''' ),
132
140
  ]
133
141
  ProduceDynadocConfigurationReturn: __.typx.TypeAlias = __.typx.Annotated[
134
142
  DynadocConfiguration,
135
- __.dynadoc.Doc(
143
+ __.ddoc.Doc(
136
144
  ''' Dynadoc configuration dictionary.
137
145
 
138
146
  Suitable as a keyword expansion (``**``) argument to
@@ -95,8 +95,11 @@ def mangle_name( objct: object, /, name: str ) -> str:
95
95
  Effectively provides name of private member attribute,
96
96
  which is unique across class inheritance.
97
97
  '''
98
+ # TODO: Replace expensive SHA-256 hash with simple 'id'.
99
+ # Need to debug weird issue with using 'id' early on dataclasses.
98
100
  if not __.inspect.isclass( objct ):
99
101
  return mangle_name( type( objct ), name )
102
+ # return "{name}_{uid}".format( name = name, uid = id( objct ) )
100
103
  namehash = __.hashlib.sha256( )
101
104
  namehash.update( qualify_class_name( objct ).encode( ) )
102
105
  namehash_hex = namehash.hexdigest( )
File without changes
File without changes
File without changes
File without changes