Coverage for sources/classcore/standard/decorators.py: 100%

174 statements  

« prev     ^ index     » next       coverage.py v7.9.1, created at 2025-07-01 05:36 +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''' Standard decorators. ''' 

22# TODO? Add attribute value transformer as standard decorator argument. 

23 

24 

25from .. import factories as _factories 

26from .. import utilities as _utilities 

27from ..decorators import ( 

28 decoration_by, 

29 produce_class_construction_decorator, 

30 produce_class_initialization_decorator, 

31) 

32from . import __ 

33from . import behaviors as _behaviors 

34from . import dynadoc as _dynadoc 

35from . import nomina as _nomina 

36 

37 

38_dataclass_core = __.dcls.dataclass( kw_only = True, slots = True ) 

39_dynadoc_configuration = _dynadoc.produce_dynadoc_configuration( ) 

40 

41 

42def prepare_dataclass_for_instances( 

43 cls: type, 

44 decorators: _nomina.DecoratorsMutable[ __.U ], /, *, 

45 attributes_namer: _nomina.AttributesNamer, 

46) -> None: 

47 ''' Annotates dataclass in support of instantiation machinery. ''' 

48 annotations = __.inspect.get_annotations( cls ) 

49 behaviors_name = attributes_namer( 'instance', 'behaviors' ) 

50 # TODO: Only use mangling if not slotted. 

51 # behaviors_name_ = _utilities.mangle_name( cls, behaviors_name ) 

52 behaviors_name_ = behaviors_name 

53 annotations[ behaviors_name_ ] = set[ str ] 

54 setattr( cls, '__annotations__', annotations ) # in case of absence 

55 setattr( cls, behaviors_name_, __.dcls.field( 

56 compare = False, hash = False, init = False, repr = False ) ) 

57 

58 

59def apply_cfc_core_functions( 

60 clscls: type[ __.T ], /, 

61 attributes_namer: _nomina.AttributesNamer, 

62 assigner_core: __.typx.Optional[ _nomina.AssignerCore ] = None, 

63 deleter_core: __.typx.Optional[ _nomina.DeleterCore ] = None, 

64 surveyor_core: __.typx.Optional[ _nomina.SurveyorCore ] = None, 

65) -> None: 

66 ''' Stores core functions on metaclass. ''' 

67 cores = dict( 

68 classes_assigner_core = assigner_core, 

69 classes_deleter_core = deleter_core, 

70 classes_surveyor_core = surveyor_core ) 

71 cores_default = dict( 

72 assigner = _behaviors.assign_attribute_if_mutable, 

73 deleter = _behaviors.delete_attribute_if_mutable, 

74 surveyor = _behaviors.survey_visible_attributes ) 

75 for core_name in ( 'assigner', 'deleter', 'surveyor' ): 

76 core_function = _behaviors.access_core_function( 

77 clscls, 

78 attributes_namer = attributes_namer, 

79 arguments = cores, 

80 level = 'classes', name = core_name, 

81 default = cores_default[ core_name ] ) 

82 core_aname = attributes_namer( 'classes', f"{core_name}_core" ) 

83 setattr( clscls, core_aname, core_function ) 

84 

85 

86def apply_cfc_dynadoc_configuration( 

87 clscls: type[ __.T ], /, 

88 attributes_namer: _nomina.AttributesNamer, 

89 configuration: _nomina.DynadocConfiguration, 

90) -> None: 

91 ''' Stores Dynadoc configuration on metaclass. ''' 

92 configuration_name = attributes_namer( 'classes', 'dynadoc_configuration' ) 

93 setattr( clscls, configuration_name, configuration ) 

94 

95 

96def apply_cfc_constructor( 

97 clscls: type[ __.T ], /, 

98 attributes_namer: _nomina.AttributesNamer, 

99 error_class_provider: _nomina.ErrorClassProvider, 

100) -> None: 

101 ''' Injects '__new__' method into metaclass. ''' 

102 preprocessors = ( 

103 _behaviors.produce_class_construction_preprocessor( 

104 attributes_namer = attributes_namer ), ) 

105 postprocessors = ( 

106 _behaviors.produce_class_construction_postprocessor( 

107 attributes_namer = attributes_namer, 

108 error_class_provider = error_class_provider ), ) 

109 constructor: _nomina.ClassConstructor[ __.T ] = ( 

110 _factories.produce_class_constructor( 

111 attributes_namer = attributes_namer, 

112 preprocessors = preprocessors, 

113 postprocessors = postprocessors ) ) 

114 decorator = produce_class_construction_decorator( 

115 attributes_namer = attributes_namer, constructor = constructor ) 

116 decorator( clscls ) 

117 

118 

119def apply_cfc_initializer( 

120 clscls: type[ __.T ], /, attributes_namer: _nomina.AttributesNamer 

121) -> None: 

122 ''' Injects '__init__' method into metaclass. ''' 

123 completers = ( 

124 _behaviors.produce_class_initialization_completer( 

125 attributes_namer = attributes_namer ), ) 

126 initializer = ( 

127 _factories.produce_class_initializer( 

128 attributes_namer = attributes_namer, 

129 completers = completers ) ) 

130 decorator = produce_class_initialization_decorator( 

131 attributes_namer = attributes_namer, initializer = initializer ) 

132 decorator( clscls ) 

133 

134 

135def apply_cfc_attributes_assigner( 

136 clscls: type[ __.T ], /, 

137 attributes_namer: _nomina.AttributesNamer, 

138 error_class_provider: _nomina.ErrorClassProvider, 

139 implementation_core: __.typx.Optional[ _nomina.AssignerCore ], 

140) -> None: 

141 ''' Injects '__setattr__' method into metaclass. ''' 

142 decorator = produce_attributes_assignment_decorator( 

143 level = 'classes', 

144 attributes_namer = attributes_namer, 

145 error_class_provider = error_class_provider, 

146 implementation_core = implementation_core ) 

147 decorator( clscls ) 

148 

149 

150def apply_cfc_attributes_deleter( 

151 clscls: type[ __.T ], /, 

152 attributes_namer: _nomina.AttributesNamer, 

153 error_class_provider: _nomina.ErrorClassProvider, 

154 implementation_core: __.typx.Optional[ _nomina.DeleterCore ], 

155) -> None: 

156 ''' Injects '__delattr__' method into metaclass. ''' 

157 decorator = produce_attributes_deletion_decorator( 

158 level = 'classes', 

159 attributes_namer = attributes_namer, 

160 error_class_provider = error_class_provider, 

161 implementation_core = implementation_core ) 

162 decorator( clscls ) 

163 

164 

165def apply_cfc_attributes_surveyor( 

166 clscls: type[ __.T ], 

167 attributes_namer: _nomina.AttributesNamer, 

168 implementation_core: __.typx.Optional[ _nomina.SurveyorCore ], 

169) -> None: 

170 ''' Injects '__dir__' method into metaclass. ''' 

171 decorator = produce_attributes_surveillance_decorator( 

172 level = 'classes', 

173 attributes_namer = attributes_namer, 

174 implementation_core = implementation_core ) 

175 decorator( clscls ) 

176 

177 

178def class_factory( # noqa: PLR0913 

179 attributes_namer: _nomina.AttributesNamer = __.calculate_attrname, 

180 error_class_provider: _nomina.ErrorClassProvider = __.provide_error_class, 

181 assigner_core: __.typx.Optional[ _nomina.AssignerCore ] = None, 

182 deleter_core: __.typx.Optional[ _nomina.DeleterCore ] = None, 

183 surveyor_core: __.typx.Optional[ _nomina.SurveyorCore ] = None, 

184 dynadoc_configuration: __.cabc.Mapping[ str, __.typx.Any ] = ( 

185 _dynadoc_configuration ), 

186) -> _nomina.Decorator[ __.T ]: 

187 ''' Produces decorator to apply standard behaviors to metaclass. ''' 

188 def decorate( clscls: type[ __.T ] ) -> type[ __.T ]: 

189 apply_cfc_core_functions( 

190 clscls, 

191 attributes_namer = attributes_namer, 

192 assigner_core = assigner_core, 

193 deleter_core = deleter_core, 

194 surveyor_core = surveyor_core ) 

195 apply_cfc_dynadoc_configuration( 

196 clscls, 

197 attributes_namer = attributes_namer, 

198 configuration = dynadoc_configuration ) 

199 apply_cfc_constructor( 

200 clscls, 

201 attributes_namer = attributes_namer, 

202 error_class_provider = error_class_provider ) 

203 apply_cfc_initializer( clscls, attributes_namer = attributes_namer ) 

204 apply_cfc_attributes_assigner( 

205 clscls, 

206 attributes_namer = attributes_namer, 

207 error_class_provider = error_class_provider, 

208 implementation_core = assigner_core ) 

209 apply_cfc_attributes_deleter( 

210 clscls, 

211 attributes_namer = attributes_namer, 

212 error_class_provider = error_class_provider, 

213 implementation_core = deleter_core ) 

214 apply_cfc_attributes_surveyor( 

215 clscls, 

216 attributes_namer = attributes_namer, 

217 implementation_core = surveyor_core ) 

218 return clscls 

219 

220 return decorate 

221 

222 

223def produce_instances_initialization_decorator( # noqa: PLR0913 

224 attributes_namer: _nomina.AttributesNamer, 

225 assigner_core: __.typx.Optional[ _nomina.AssignerCore ], 

226 deleter_core: __.typx.Optional[ _nomina.DeleterCore ], 

227 surveyor_core: __.typx.Optional[ _nomina.SurveyorCore ], 

228 mutables: _nomina.BehaviorExclusionVerifiersOmni, 

229 visibles: _nomina.BehaviorExclusionVerifiersOmni, 

230) -> _nomina.Decorator[ __.U ]: 

231 ''' Produces decorator to inject '__init__' method into class. ''' 

232 cores = dict( 

233 instances_assigner_core = assigner_core, 

234 instances_deleter_core = deleter_core, 

235 instances_surveyor_core = surveyor_core ) 

236 cores_default = dict( 

237 assigner = _behaviors.assign_attribute_if_mutable, 

238 deleter = _behaviors.delete_attribute_if_mutable, 

239 surveyor = _behaviors.survey_visible_attributes ) 

240 

241 def decorate( cls: type[ __.U ] ) -> type[ __.U ]: 

242 for core_name in ( 'assigner', 'deleter', 'surveyor' ): 

243 core_function = _behaviors.access_core_function( 

244 cls, 

245 attributes_namer = attributes_namer, 

246 arguments = cores, 

247 level = 'instances', name = core_name, 

248 default = cores_default[ core_name ] ) 

249 core_aname = attributes_namer( 'instances', f"{core_name}_core" ) 

250 setattr( cls, core_aname, core_function ) 

251 behaviors: set[ str ] = set( ) 

252 behaviors_name = attributes_namer( 'instance', 'behaviors' ) 

253 _behaviors.record_behavior( 

254 cls, attributes_namer = attributes_namer, 

255 level = 'instances', basename = 'mutables', 

256 label = _nomina.immutability_label, behaviors = behaviors, 

257 verifiers = mutables ) 

258 _behaviors.record_behavior( 

259 cls, attributes_namer = attributes_namer, 

260 level = 'instances', basename = 'visibles', 

261 label = _nomina.concealment_label, behaviors = behaviors, 

262 verifiers = visibles ) 

263 original = cls.__dict__.get( '__init__' ) 

264 

265 if original is None: 

266 

267 def initialize_with_super( 

268 self: object, *posargs: __.typx.Any, **nomargs: __.typx.Any 

269 ) -> None: 

270 super( cls, self ).__init__( *posargs, **nomargs ) 

271 # Only record behaviors at start of MRO. 

272 if cls is not type( self ): return 

273 behaviors_: set[ str ] = ( 

274 _utilities.getattr0( self, behaviors_name, set( ) ) ) 

275 behaviors_.update( behaviors ) 

276 _utilities.setattr0( 

277 self, behaviors_name, frozenset( behaviors_ ) ) 

278 

279 cls.__init__ = initialize_with_super 

280 

281 else: 

282 

283 @__.funct.wraps( original ) 

284 def initialize_with_original( 

285 self: object, *posargs: __.typx.Any, **nomargs: __.typx.Any 

286 ) -> None: 

287 original( self, *posargs, **nomargs ) 

288 # Only record behaviors at start of MRO. 

289 if cls is not type( self ): return 

290 behaviors_: set[ str ] = ( 

291 _utilities.getattr0( self, behaviors_name, set( ) ) ) 

292 behaviors_.update( behaviors ) 

293 _utilities.setattr0( 

294 self, behaviors_name, frozenset( behaviors_ ) ) 

295 

296 cls.__init__ = initialize_with_original 

297 

298 return cls 

299 

300 return decorate 

301 

302 

303def produce_attributes_assignment_decorator( 

304 level: str, 

305 attributes_namer: _nomina.AttributesNamer, 

306 error_class_provider: _nomina.ErrorClassProvider, 

307 implementation_core: __.typx.Optional[ _nomina.AssignerCore ], 

308) -> _nomina.Decorator[ __.U ]: 

309 ''' Produces decorator to inject '__setattr__' method into class. ''' 

310 def decorate( cls: type[ __.U ] ) -> type[ __.U ]: 

311 leveli = 'class' if level == 'classes' else level 

312 original = cls.__dict__.get( '__setattr__' ) 

313 core = _behaviors.access_core_function( 

314 cls, 

315 attributes_namer = attributes_namer, 

316 arguments = { f"{level}_assigner": implementation_core }, 

317 level = level, name = 'assigner', 

318 default = _behaviors.assign_attribute_if_mutable ) 

319 

320 if original is None: 

321 

322 def assign_with_super( 

323 self: object, name: str, value: __.typx.Any 

324 ) -> None: 

325 ligation = super( cls, self ).__setattr__ 

326 # Only enforce behaviors at start of MRO. 

327 if cls is not type( self ): 

328 ligation( name, value ) 

329 return 

330 core( 

331 self, 

332 ligation = ligation, 

333 attributes_namer = attributes_namer, 

334 error_class_provider = error_class_provider, 

335 level = leveli, 

336 name = name, value = value ) 

337 

338 cls.__setattr__ = assign_with_super 

339 

340 else: 

341 

342 @__.funct.wraps( original ) 

343 def assign_with_original( 

344 self: object, name: str, value: __.typx.Any 

345 ) -> None: 

346 ligation = __.funct.partial( original, self ) 

347 # Only enforce behaviors at start of MRO. 

348 if cls is not type( self ): 

349 ligation( name, value ) 

350 return 

351 core( 

352 self, 

353 ligation = ligation, 

354 attributes_namer = attributes_namer, 

355 error_class_provider = error_class_provider, 

356 level = leveli, 

357 name = name, value = value ) 

358 

359 cls.__setattr__ = assign_with_original 

360 

361 return cls 

362 

363 return decorate 

364 

365 

366def produce_attributes_deletion_decorator( 

367 level: str, 

368 attributes_namer: _nomina.AttributesNamer, 

369 error_class_provider: _nomina.ErrorClassProvider, 

370 implementation_core: __.typx.Optional[ _nomina.DeleterCore ], 

371) -> _nomina.Decorator[ __.U ]: 

372 ''' Produces decorator to inject '__delattr__' method into class. ''' 

373 def decorate( cls: type[ __.U ] ) -> type[ __.U ]: 

374 leveli = 'class' if level == 'classes' else level 

375 original = cls.__dict__.get( '__delattr__' ) 

376 core = _behaviors.access_core_function( 

377 cls, 

378 attributes_namer = attributes_namer, 

379 arguments = { f"{level}_deleter": implementation_core }, 

380 level = level, name = 'deleter', 

381 default = _behaviors.delete_attribute_if_mutable ) 

382 

383 if original is None: 

384 

385 def delete_with_super( self: object, name: str ) -> None: 

386 ligation = super( cls, self ).__delattr__ 

387 # Only enforce behaviors at start of MRO. 

388 if cls is not type( self ): 

389 ligation( name ) 

390 return 

391 core( 

392 self, 

393 ligation = ligation, 

394 attributes_namer = attributes_namer, 

395 error_class_provider = error_class_provider, 

396 level = leveli, 

397 name = name ) 

398 

399 cls.__delattr__ = delete_with_super 

400 

401 else: 

402 

403 @__.funct.wraps( original ) 

404 def delete_with_original( self: object, name: str ) -> None: 

405 ligation = __.funct.partial( original, self ) 

406 # Only enforce behaviors at start of MRO. 

407 if cls is not type( self ): 

408 ligation( name ) 

409 return 

410 core( 

411 self, 

412 ligation = ligation, 

413 attributes_namer = attributes_namer, 

414 error_class_provider = error_class_provider, 

415 level = leveli, 

416 name = name ) 

417 

418 cls.__delattr__ = delete_with_original 

419 

420 return cls 

421 

422 return decorate 

423 

424 

425def produce_attributes_surveillance_decorator( 

426 level: str, 

427 attributes_namer: _nomina.AttributesNamer, 

428 implementation_core: __.typx.Optional[ _nomina.SurveyorCore ], 

429) -> _nomina.Decorator[ __.U ]: 

430 ''' Produces decorator to inject '__dir__' method into class. ''' 

431 def decorate( cls: type[ __.U ] ) -> type[ __.U ]: 

432 leveli = 'class' if level == 'classes' else level 

433 original = cls.__dict__.get( '__dir__' ) 

434 core = _behaviors.access_core_function( 

435 cls, 

436 attributes_namer = attributes_namer, 

437 arguments = { f"{level}_surveyor": implementation_core }, 

438 level = level, name = 'surveyor', 

439 default = _behaviors.survey_visible_attributes ) 

440 

441 if original is None: 

442 

443 def survey_with_super( 

444 self: object 

445 ) -> __.cabc.Iterable[ str ]: 

446 ligation = super( cls, self ).__dir__ 

447 # Only enforce behaviors at start of MRO. 

448 if cls is not type( self ): return ligation( ) 

449 return core( 

450 self, 

451 ligation = ligation, 

452 attributes_namer = attributes_namer, 

453 level = leveli ) 

454 

455 cls.__dir__ = survey_with_super 

456 

457 else: 

458 

459 @__.funct.wraps( original ) 

460 def survey_with_original( 

461 self: object 

462 ) -> __.cabc.Iterable[ str ]: 

463 ligation = __.funct.partial( original, self ) 

464 # Only enforce behaviors at start of MRO. 

465 if cls is not type( self ): return ligation( ) 

466 return core( 

467 self, 

468 ligation = ligation, 

469 attributes_namer = attributes_namer, 

470 level = leveli ) 

471 

472 cls.__dir__ = survey_with_original 

473 

474 return cls 

475 

476 return decorate 

477 

478 

479@__.typx.dataclass_transform( frozen_default = True, kw_only_default = True ) 

480def dataclass_with_standard_behaviors( # noqa: PLR0913 

481 attributes_namer: _nomina.AttributesNamer = __.calculate_attrname, 

482 error_class_provider: _nomina.ErrorClassProvider = __.provide_error_class, 

483 decorators: _nomina.Decorators[ __.U ] = ( ), 

484 assigner_core: __.typx.Optional[ _nomina.AssignerCore ] = None, 

485 deleter_core: __.typx.Optional[ _nomina.DeleterCore ] = None, 

486 surveyor_core: __.typx.Optional[ _nomina.SurveyorCore ] = None, 

487 mutables: _nomina.BehaviorExclusionVerifiersOmni = __.mutables_default, 

488 visibles: _nomina.BehaviorExclusionVerifiersOmni = __.visibles_default, 

489) -> _nomina.Decorator[ __.U ]: 

490 # https://github.com/microsoft/pyright/discussions/10344 

491 ''' Dataclass decorator factory. ''' 

492 decorators_: _nomina.Decorators[ __.U ] = ( 

493 _produce_instances_decorators( 

494 attributes_namer = attributes_namer, 

495 error_class_provider = error_class_provider, 

496 assigner_core = assigner_core, 

497 deleter_core = deleter_core, 

498 surveyor_core = surveyor_core, 

499 mutables = mutables, 

500 visibles = visibles ) ) 

501 preparers: _nomina.DecorationPreparers[ __.U ] = ( 

502 _produce_instances_decoration_preparers( 

503 attributes_namer = attributes_namer, 

504 error_class_provider = error_class_provider, 

505 class_preparer = prepare_dataclass_for_instances ) ) 

506 return decoration_by( 

507 *decorators, _dataclass_core, *decorators_, preparers = preparers ) 

508 

509 

510def with_standard_behaviors( # noqa: PLR0913 

511 attributes_namer: _nomina.AttributesNamer = __.calculate_attrname, 

512 error_class_provider: _nomina.ErrorClassProvider = __.provide_error_class, 

513 decorators: _nomina.Decorators[ __.U ] = ( ), 

514 assigner_core: __.typx.Optional[ _nomina.AssignerCore ] = None, 

515 deleter_core: __.typx.Optional[ _nomina.DeleterCore ] = None, 

516 surveyor_core: __.typx.Optional[ _nomina.SurveyorCore ] = None, 

517 mutables: _nomina.BehaviorExclusionVerifiersOmni = __.mutables_default, 

518 visibles: _nomina.BehaviorExclusionVerifiersOmni = __.visibles_default, 

519) -> _nomina.Decorator[ __.U ]: 

520 ''' Class decorator factory. ''' 

521 decorators_: _nomina.Decorators[ __.U ] = ( 

522 _produce_instances_decorators( 

523 attributes_namer = attributes_namer, 

524 error_class_provider = error_class_provider, 

525 assigner_core = assigner_core, 

526 deleter_core = deleter_core, 

527 surveyor_core = surveyor_core, 

528 mutables = mutables, 

529 visibles = visibles ) ) 

530 preparers: _nomina.DecorationPreparers[ __.U ] = ( 

531 _produce_instances_decoration_preparers( 

532 attributes_namer = attributes_namer, 

533 error_class_provider = error_class_provider ) ) 

534 return decoration_by( *decorators, *decorators_, preparers = preparers ) 

535 

536 

537def _produce_instances_decoration_preparers( 

538 attributes_namer: _nomina.AttributesNamer, 

539 error_class_provider: _nomina.ErrorClassProvider, 

540 class_preparer: __.typx.Optional[ _nomina.ClassPreparer ] = None, 

541) -> _nomina.DecorationPreparers[ __.U ]: 

542 ''' Produces processors for standard decorators. ''' 

543 preprocessors: list[ _nomina.DecorationPreparer[ __.U ] ] = [ ] 

544 if class_preparer is not None: 

545 preprocessors.append( 

546 __.funct.partial( 

547 class_preparer, attributes_namer = attributes_namer ) ) 

548 return tuple( preprocessors ) 

549 

550 

551def _produce_instances_decorators( # noqa: PLR0913 

552 attributes_namer: _nomina.AttributesNamer, 

553 error_class_provider: _nomina.ErrorClassProvider, 

554 assigner_core: __.typx.Optional[ _nomina.AssignerCore ], 

555 deleter_core: __.typx.Optional[ _nomina.DeleterCore ], 

556 surveyor_core: __.typx.Optional[ _nomina.SurveyorCore ], 

557 mutables: _nomina.BehaviorExclusionVerifiersOmni, 

558 visibles: _nomina.BehaviorExclusionVerifiersOmni, 

559) -> _nomina.Decorators[ __.U ]: 

560 ''' Produces standard decorators. ''' 

561 decorators: list[ _nomina.Decorator[ __.U ] ] = [ ] 

562 decorators.append( 

563 produce_instances_initialization_decorator( 

564 attributes_namer = attributes_namer, 

565 assigner_core = assigner_core, 

566 deleter_core = deleter_core, 

567 surveyor_core = surveyor_core, 

568 mutables = mutables, visibles = visibles ) ) 

569 decorators.append( 

570 produce_attributes_assignment_decorator( 

571 level = 'instances', 

572 attributes_namer = attributes_namer, 

573 error_class_provider = error_class_provider, 

574 implementation_core = assigner_core ) ) 

575 decorators.append( 

576 produce_attributes_deletion_decorator( 

577 level = 'instances', 

578 attributes_namer = attributes_namer, 

579 error_class_provider = error_class_provider, 

580 implementation_core = deleter_core ) ) 

581 decorators.append( 

582 produce_attributes_surveillance_decorator( 

583 level = 'instances', 

584 attributes_namer = attributes_namer, 

585 implementation_core = surveyor_core ) ) 

586 return decorators