orionis 0.232.0__py3-none-any.whl → 0.234.0__py3-none-any.whl

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 (61) hide show
  1. orionis/framework.py +1 -1
  2. orionis/luminate/support/inspection/dependencies/contracts/__init__.py +0 -0
  3. orionis/luminate/support/inspection/dependencies/contracts/reflect_dependencies.py +43 -0
  4. orionis/luminate/support/inspection/dependencies/entities/__init__.py +0 -0
  5. orionis/luminate/support/inspection/dependencies/entities/class_dependencies.py +10 -0
  6. orionis/luminate/support/inspection/dependencies/entities/method_dependencies.py +10 -0
  7. orionis/luminate/support/inspection/dependencies/entities/resolved_dependencies.py +12 -0
  8. orionis/luminate/support/inspection/dependencies/reflect_dependencies.py +176 -0
  9. orionis/luminate/support/inspection/helpers/__init__.py +0 -0
  10. orionis/luminate/support/inspection/helpers/functions.py +281 -0
  11. orionis/luminate/support/inspection/reflect_decorators.py +335 -0
  12. orionis/luminate/support/inspection/reflection.py +16 -22
  13. orionis/luminate/support/inspection/reflection_instance.py +801 -0
  14. orionis/luminate/support/inspection/reflexion_concrete_with_abstract.py +1 -1
  15. orionis/luminate/support/inspection/reflexion_instance_with_abstract.py +4 -4
  16. orionis/luminate/test/case.py +9 -0
  17. orionis/luminate/test/cases/__init__.py +0 -0
  18. orionis/luminate/test/cases/test_async.py +32 -0
  19. orionis/luminate/test/cases/test_case.py +23 -0
  20. orionis/luminate/test/cases/test_sync.py +10 -0
  21. orionis/luminate/test/core/__init__.py +0 -0
  22. orionis/luminate/test/core/contracts/__init__.py +0 -0
  23. orionis/luminate/test/{test_suite.py → core/test_suite.py} +2 -2
  24. orionis/luminate/test/{test_unit.py → core/test_unit.py} +4 -4
  25. orionis/luminate/test/entities/__init__.py +0 -0
  26. orionis/luminate/test/{test_result.py → entities/test_result.py} +2 -2
  27. orionis/luminate/test/enums/__init__.py +0 -0
  28. orionis/luminate/test/exceptions/__init__.py +0 -0
  29. orionis/luminate/test/output/__init__.py +0 -0
  30. orionis/luminate/test/{test_std_out.py → output/test_std_out.py} +1 -1
  31. orionis/luminate/test/suite.py +7 -0
  32. {orionis-0.232.0.dist-info → orionis-0.234.0.dist-info}/METADATA +1 -1
  33. {orionis-0.232.0.dist-info → orionis-0.234.0.dist-info}/RECORD +58 -38
  34. tests/example/test_example.py +1 -1
  35. tests/support/adapters/test_doct_dict.py +1 -1
  36. tests/support/async_io/test_async_coroutine.py +1 -1
  37. tests/support/environment/test_env.py +1 -1
  38. tests/support/inspection/fakes/fake_reflection_instance.py +2 -1
  39. tests/support/inspection/test_reflection_abstract.py +19 -1
  40. tests/support/inspection/test_reflection_concrete.py +1 -1
  41. tests/support/inspection/test_reflection_concrete_with_abstract.py +1 -1
  42. tests/support/inspection/test_reflection_instance.py +71 -16
  43. tests/support/inspection/test_reflection_instance_with_abstract.py +1 -1
  44. tests/support/parsers/test_exception_parser.py +1 -1
  45. tests/support/path/test_resolver.py +6 -6
  46. tests/support/patterns/test_singleton.py +1 -1
  47. tests/support/standard/test_std.py +1 -1
  48. orionis/luminate/support/inspection/functions.py +0 -263
  49. orionis/luminate/support/inspection/reflexion_instance.py +0 -527
  50. orionis/luminate/test/test_case.py +0 -62
  51. /orionis/luminate/{test/contracts → support/inspection/dependencies}/__init__.py +0 -0
  52. /orionis/luminate/support/inspection/{reflexion_abstract.py → reflect_abstract.py} +0 -0
  53. /orionis/luminate/test/{contracts → core/contracts}/test_suite.py +0 -0
  54. /orionis/luminate/test/{contracts → core/contracts}/test_unit.py +0 -0
  55. /orionis/luminate/test/{test_status.py → enums/test_status.py} +0 -0
  56. /orionis/luminate/test/{test_exception.py → exceptions/test_exception.py} +0 -0
  57. /orionis/luminate/test/{contracts → output/contracts}/test_std_out.py +0 -0
  58. {orionis-0.232.0.dist-info → orionis-0.234.0.dist-info}/LICENCE +0 -0
  59. {orionis-0.232.0.dist-info → orionis-0.234.0.dist-info}/WHEEL +0 -0
  60. {orionis-0.232.0.dist-info → orionis-0.234.0.dist-info}/entry_points.txt +0 -0
  61. {orionis-0.232.0.dist-info → orionis-0.234.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,801 @@
1
+ import inspect
2
+ from dataclasses import dataclass
3
+ from typing import Any, Callable, Dict, List, Optional, Tuple, Type
4
+ from orionis.luminate.support.asynchrony.async_io import AsyncIO
5
+ from orionis.luminate.support.inspection.dependencies.reflect_dependencies import (
6
+ ClassDependency,
7
+ MethodDependency,
8
+ ReflectDependencies,
9
+ )
10
+
11
+ @dataclass
12
+ class ClassAttributes:
13
+ """
14
+ A class to represent the attributes of a class instance.
15
+ """
16
+ public: Dict[str, Any]
17
+ private: Dict[str, Any]
18
+ protected: Dict[str, Any]
19
+
20
+ @dataclass
21
+ class ClassMethod:
22
+ """
23
+ A class to represent the methods of a class instance.
24
+ """
25
+ public: List[str]
26
+ private: List[str]
27
+ protected: List[str]
28
+ static: List[str]
29
+ asynchronous: List[str]
30
+ synchronous: List[str]
31
+ class_methods: List[str]
32
+ asynchronous_static: List[str]
33
+ synchronous_static: List[str]
34
+ magic: List[str]
35
+
36
+ @dataclass
37
+ class ClassProperty:
38
+ """
39
+ A class to represent a property of a class instance.
40
+ """
41
+ name: str
42
+ value: Any
43
+ signature: inspect.Signature
44
+ doc: str
45
+
46
+ @dataclass
47
+ class ClassParsed:
48
+ """
49
+ A class to represent the parsed information of a class instance.
50
+ """
51
+ name : str = None
52
+ module : str = None
53
+ attributes : ClassAttributes = None
54
+ methods : ClassMethod = None
55
+ properties : List[ClassProperty] = None,
56
+ dependencies : ClassDependency = None
57
+
58
+ class ReflectionInstance:
59
+ """
60
+ A reflection object encapsulating a class instance.
61
+
62
+ Parameters
63
+ ----------
64
+ instance : Any
65
+ The instance being reflected upon
66
+
67
+ Attributes
68
+ ----------
69
+ _instance : Any
70
+ The encapsulated instance
71
+ """
72
+
73
+ def __init__(self, instance: Any) -> None:
74
+ """Initialize with the instance to reflect upon."""
75
+ self._instance = instance
76
+
77
+ def parse(self) -> ClassParsed:
78
+ """
79
+ Parse the instance into a structured representation.
80
+
81
+ This method extracts and organizes various details about the instance,
82
+ including its class name, module, attributes, methods, and properties,
83
+ into a `ClassParsed` object.
84
+
85
+ Returns
86
+ -------
87
+ ClassParsed
88
+ A structured representation of the instance, containing:
89
+ - name: The name of the instance's class.
90
+ - module: The module where the class is defined.
91
+ - attributes: Categorized attributes (public, private, protected).
92
+ - methods: Categorized methods (public, private, protected, static, etc.).
93
+ - properties: A dictionary of properties with their details.
94
+ """
95
+ return ClassParsed(
96
+ name=self.getClassName(),
97
+ module=self.getModuleName(),
98
+ attributes=self.getAllAttributes(),
99
+ methods=self.getAllMethods(),
100
+ properties=list(self.getAllProperties().values()),
101
+ dependencies=self.getConstructorDependencies()
102
+ )
103
+
104
+ def getClassName(self) -> str:
105
+ """
106
+ Get the name of the instance's class.
107
+
108
+ Returns
109
+ -------
110
+ str
111
+ The name of the class
112
+ """
113
+ return self._instance.__class__.__name__
114
+
115
+ def getClass(self) -> Type:
116
+ """
117
+ Get the class of the instance.
118
+
119
+ Returns
120
+ -------
121
+ Type
122
+ The class object of the instance
123
+ """
124
+ return self._instance.__class__
125
+
126
+ def getModuleName(self) -> str:
127
+ """
128
+ Get the name of the module where the class is defined.
129
+
130
+ Returns
131
+ -------
132
+ str
133
+ The module name
134
+ """
135
+ return self._instance.__class__.__module__
136
+
137
+ def getAllAttributes(self) -> ClassAttributes:
138
+ """
139
+ Get all attributes of the instance.
140
+
141
+ Returns
142
+ -------
143
+ Dict[str, Any]
144
+ Dictionary of attribute names and their values
145
+ """
146
+ attributes: dict = vars(self._instance)
147
+ class_name: str = self.getClassName()
148
+ public = {}
149
+ private = {}
150
+ protected = {}
151
+
152
+ for attr, value in attributes.items():
153
+ if str(attr).startswith("_") and not str(attr).startswith("__") and not str(attr).startswith(f"_{class_name}"):
154
+ protected[attr] = value
155
+ elif str(attr).startswith(f"_{class_name}"):
156
+ private[str(attr).replace(f"_{class_name}", "")] = value
157
+ else:
158
+ public[attr] = value
159
+
160
+ return ClassAttributes(
161
+ public=public,
162
+ private=private,
163
+ protected=protected
164
+ )
165
+
166
+ def getAttributes(self) -> Dict[str, Any]:
167
+ """
168
+ Get all attributes of the instance.
169
+
170
+ Returns
171
+ -------
172
+ Dict[str, Any]
173
+ Dictionary of attribute names and their values
174
+ """
175
+ attr = self.getAllAttributes()
176
+ return {**attr.public, **attr.private, **attr.protected}
177
+
178
+ def getPublicAttributes(self) -> Dict[str, Any]:
179
+ """
180
+ Get all public attributes of the instance.
181
+
182
+ Returns
183
+ -------
184
+ Dict[str, Any]
185
+ Dictionary of public attribute names and their values
186
+ """
187
+ attr = self.getAllAttributes()
188
+ return attr.public
189
+
190
+ def getPrivateAttributes(self) -> Dict[str, Any]:
191
+ """
192
+ Get all private attributes of the instance.
193
+
194
+ Returns
195
+ -------
196
+ Dict[str, Any]
197
+ Dictionary of private attribute names and their values
198
+ """
199
+ attr = self.getAllAttributes()
200
+ return attr.private
201
+
202
+ def getProtectedAttributes(self) -> Dict[str, Any]:
203
+ """
204
+ Get all Protected attributes of the instance.
205
+
206
+ Returns
207
+ -------
208
+ Dict[str, Any]
209
+ Dictionary of Protected attribute names and their values
210
+ """
211
+ attr = self.getAllAttributes()
212
+ return attr.protected
213
+
214
+ def getAllMethods(self):
215
+ """
216
+ Retrieves and categorizes all methods of the instance's class into various classifications.
217
+ This method inspects the instance's class and its methods, categorizing them into public, private,
218
+ protected, static, asynchronous, synchronous, class methods, asynchronous static, synchronous static,
219
+ and magic methods.
220
+ Returns
221
+ -------
222
+ ClassMethod
223
+ An object containing categorized lists of method names:
224
+ - public: List of public instance methods.
225
+ - private: List of private instance methods (names without the class prefix).
226
+ - protected: List of protected instance methods.
227
+ - static: List of static methods.
228
+ - asynchronous: List of asynchronous instance methods.
229
+ - synchronous: List of synchronous instance methods.
230
+ - class_methods: List of class methods.
231
+ - asynchronous_static: List of asynchronous static methods.
232
+ - synchronous_static: List of synchronous static methods.
233
+ - magic: List of magic methods (e.g., `__init__`, `__str__`).
234
+ Notes
235
+ -----
236
+ - Magic methods are identified by their double underscore prefix and suffix (e.g., `__init__`).
237
+ - Private methods are identified by a single underscore followed by the class name.
238
+ - Protected methods are identified by a single underscore prefix.
239
+ - Public methods are identified as methods without any leading underscores.
240
+ - Static and class methods are identified using `inspect.getattr_static`.
241
+ - Asynchronous methods are identified using `inspect.iscoroutinefunction`.
242
+ - Synchronous methods are identified as methods that are not asynchronous, static, or class methods.
243
+ """
244
+ class_name = self.getClassName()
245
+ cls = self._instance.__class__
246
+
247
+ result = ClassMethod(
248
+ public=[], private=[], protected=[], static=[],
249
+ asynchronous=[], synchronous=[], class_methods=[],
250
+ asynchronous_static=[], synchronous_static=[], magic=[]
251
+ )
252
+
253
+ # Categorize magic methods
254
+ result.magic = [name for name in dir(self._instance) if name.startswith("__") and name.endswith("__")]
255
+
256
+ # Classify static and class methods
257
+ for name in dir(cls):
258
+ attr = inspect.getattr_static(cls, name)
259
+ if isinstance(attr, staticmethod):
260
+ result.static.append(name)
261
+ elif isinstance(attr, classmethod):
262
+ result.class_methods.append(name)
263
+
264
+ # Classify instance methods
265
+ for name, method in inspect.getmembers(self._instance, predicate=inspect.ismethod):
266
+ if name in result.class_methods or name in result.magic:
267
+ continue
268
+ if name.startswith(f"_{class_name}"):
269
+ result.private.append(name.replace(f"_{class_name}", ""))
270
+ elif name.startswith("_"):
271
+ result.protected.append(name)
272
+ else:
273
+ result.public.append(name)
274
+
275
+ # Classify asynchronous and synchronous methods
276
+ for name, method in inspect.getmembers(cls, predicate=inspect.iscoroutinefunction):
277
+ clean_name = name.replace(f"_{class_name}", "")
278
+ if name in result.static:
279
+ result.asynchronous_static.append(clean_name)
280
+ else:
281
+ result.asynchronous.append(clean_name)
282
+
283
+ for name, method in inspect.getmembers(self._instance, predicate=inspect.ismethod):
284
+ clean_name = name.replace(f"_{class_name}", "")
285
+ if name not in result.static and clean_name not in result.asynchronous and name not in result.class_methods and name not in result.magic:
286
+ result.synchronous.append(clean_name)
287
+
288
+ # Determine synchronous static methods
289
+ for name in result.static:
290
+ if name not in result.asynchronous_static and name not in result.class_methods:
291
+ result.synchronous_static.append(name)
292
+
293
+ return result
294
+
295
+ def getMethods(self) -> List[str]:
296
+ """
297
+ Get all method names of the instance.
298
+
299
+ Returns
300
+ -------
301
+ List[str]
302
+ List of method names
303
+ """
304
+ methods = self.getAllMethods()
305
+ return methods.public + methods.private + methods.protected + methods.static + methods.class_methods
306
+
307
+ def getProtectedMethods(self) -> List[str]:
308
+ """
309
+ Get all protected method names of the instance.
310
+
311
+ Returns
312
+ -------
313
+ List[str]
314
+ List of protected method names, excluding private methods (starting with '_')
315
+ """
316
+ methods = self.getAllMethods()
317
+ return methods.protected
318
+
319
+ def getPrivateMethods(self) -> List[str]:
320
+ """
321
+ Get all private method names of the instance.
322
+
323
+ Returns
324
+ -------
325
+ List[str]
326
+ List of private method names, excluding protected methods (starting with '_')
327
+ """
328
+ methods = self.getAllMethods()
329
+ return methods.private
330
+
331
+ def getStaticMethods(self) -> List[str]:
332
+ """
333
+ Get all static method names of the instance.
334
+
335
+ Returns
336
+ -------
337
+ List[str]
338
+ List of static method names.
339
+ """
340
+ methods = self.getAllMethods()
341
+ return methods.static
342
+
343
+ def getAsyncMethods(self) -> List[str]:
344
+ """
345
+ Get all asynchronous method names of the instance that are not static methods.
346
+
347
+ Returns
348
+ -------
349
+ List[str]
350
+ List of asynchronous method names
351
+ """
352
+ methods = self.getAllMethods()
353
+ return methods.asynchronous
354
+
355
+ def getSyncMethods(self) -> List[str]:
356
+ """
357
+ Get all synchronous method names of the instance that are not static methods.
358
+
359
+ Returns
360
+ -------
361
+ List[str]
362
+ List of synchronous method names
363
+ """
364
+ methods = self.getAllMethods()
365
+ return methods.synchronous
366
+
367
+ def getClassMethods(self) -> List[str]:
368
+ """
369
+ Get all class method names of the instance.
370
+
371
+ Returns
372
+ -------
373
+ List[str]
374
+ List of class method names.
375
+ """
376
+ methods = self.getAllMethods()
377
+ return methods.class_methods
378
+
379
+ def getAsyncStaticMethods(self) -> List[str]:
380
+ """
381
+ Get all asynchronous method names of the instance that are not static methods.
382
+
383
+ Returns
384
+ -------
385
+ List[str]
386
+ List of asynchronous method names
387
+ """
388
+ methods = self.getAllMethods()
389
+ return methods.asynchronous_static
390
+
391
+ def getSyncStaticMethods(self) -> List[str]:
392
+ """
393
+ Get all synchronous static method names of the instance.
394
+
395
+ Returns
396
+ -------
397
+ List[str]
398
+ List of synchronous static method names
399
+ """
400
+ methods = self.getAllMethods()
401
+ return methods.synchronous_static
402
+
403
+ def getMagicMethods(self) -> List[str]:
404
+ """
405
+ Get all magic method names of the instance.
406
+
407
+ Returns
408
+ -------
409
+ List[str]
410
+ List of magic method names
411
+ """
412
+ methods = self.getAllMethods()
413
+ return methods.magic
414
+
415
+ def getAllProperties(self) -> Dict[str, ClassProperty]:
416
+ """
417
+ Get all properties of the instance.
418
+
419
+ Returns
420
+ -------
421
+ List[str]
422
+ List of property names
423
+ """
424
+
425
+ properties = {}
426
+ for name, prop in self._instance.__class__.__dict__.items():
427
+ if isinstance(prop, property):
428
+ properties[name] = ClassProperty(
429
+ name=name,
430
+ value=getattr(self._instance, name, None),
431
+ signature=inspect.signature(prop.fget) if prop.fget else None,
432
+ doc=prop.__doc__ or ""
433
+ )
434
+ return properties
435
+
436
+ def getPropertyNames(self) -> List[str]:
437
+ """
438
+ Get all property names of the instance.
439
+
440
+ Returns
441
+ -------
442
+ List[str]
443
+ List of property names
444
+ """
445
+ return self.getAllProperties().keys()
446
+
447
+ def getProperty(self, property_name: str) -> Any:
448
+ """
449
+ Get the value of a property.
450
+
451
+ Parameters
452
+ ----------
453
+ property_name : str
454
+ Name of the property
455
+
456
+ Returns
457
+ -------
458
+ Any
459
+ The value of the property
460
+
461
+ Raises
462
+ ------
463
+ AttributeError
464
+ If the property doesn't exist or is not a property
465
+ """
466
+ all_prop = self.getAllProperties()
467
+ if property_name not in all_prop:
468
+ raise ValueError(f"Property '{property_name}' not found.")
469
+ return all_prop[property_name].value
470
+
471
+ def getPropertySignature(self, property_name: str) -> inspect.Signature:
472
+ """
473
+ Get the signature of a property.
474
+
475
+ Parameters
476
+ ----------
477
+ property_name : str
478
+ Name of the property
479
+
480
+ Returns
481
+ -------
482
+ inspect.Signature
483
+ The property signature
484
+
485
+ Raises
486
+ ------
487
+ AttributeError
488
+ If the property doesn't exist or is not a property
489
+ """
490
+ all_prop = self.getAllProperties()
491
+ if property_name not in all_prop:
492
+ raise ValueError(f"Property '{property_name}' not found.")
493
+ return all_prop[property_name].signature
494
+
495
+ def getPropertyDoc(self, property_name: str) -> str:
496
+ """
497
+ Get the docstring of a property.
498
+
499
+ Parameters
500
+ ----------
501
+ property_name : str
502
+ Name of the property
503
+
504
+ Returns
505
+ -------
506
+ str
507
+ The docstring of the property
508
+
509
+ Raises
510
+ ------
511
+ AttributeError
512
+ If the property doesn't exist or is not a property
513
+ """
514
+ all_prop = self.getAllProperties()
515
+ if property_name not in all_prop:
516
+ raise ValueError(f"Property '{property_name}' not found.")
517
+ return all_prop[property_name].doc
518
+
519
+ def callMethod(self, method_name: str, *args: Any, **kwargs: Any) -> Any:
520
+ """
521
+ Call a method on the instance.
522
+
523
+ Parameters
524
+ ----------
525
+ method_name : str
526
+ Name of the method to call
527
+ *args : Any
528
+ Positional arguments for the method
529
+ **kwargs : Any
530
+ Keyword arguments for the method
531
+
532
+ Returns
533
+ -------
534
+ Any
535
+ The result of the method call
536
+
537
+ Raises
538
+ ------
539
+ AttributeError
540
+ If the method does not exist on the instance
541
+ TypeError
542
+ If the method is not callable
543
+ """
544
+
545
+ if method_name in self.getPrivateMethods():
546
+ method_name = f"_{self.getClassName()}{method_name}"
547
+
548
+ method = getattr(self._instance, method_name, None)
549
+
550
+ if method is None:
551
+ raise AttributeError(f"'{self.getClassName()}' object has no method '{method_name}'.")
552
+ if not callable(method):
553
+ raise TypeError(f"'{method_name}' is not callable on '{self.getClassName()}'.")
554
+
555
+ if inspect.iscoroutinefunction(method):
556
+ return AsyncIO.run(method(*args, **kwargs))
557
+
558
+ return method(*args, **kwargs)
559
+
560
+ def getMethodSignature(self, method_name: str) -> inspect.Signature:
561
+ """
562
+ Get the signature of a method.
563
+
564
+ Parameters
565
+ ----------
566
+ method_name : str
567
+ Name of the method
568
+
569
+ Returns
570
+ -------
571
+ inspect.Signature
572
+ The method signature
573
+ """
574
+ if method_name in self.getPrivateMethods():
575
+ method_name = f"_{self.getClassName()}{method_name}"
576
+
577
+ method = getattr(self._instance, method_name)
578
+ if callable(method):
579
+ return inspect.signature(method)
580
+
581
+ def getDocstring(self) -> Optional[str]:
582
+ """
583
+ Get the docstring of the instance's class.
584
+
585
+ Returns
586
+ -------
587
+ Optional[str]
588
+ The class docstring, or None if not available
589
+ """
590
+ return self._instance.__class__.__doc__
591
+
592
+ def getBaseClasses(self) -> Tuple[Type, ...]:
593
+ """
594
+ Get the base classes of the instance's class.
595
+
596
+ Returns
597
+ -------
598
+ Tuple[Type, ...]
599
+ Tuple of base classes
600
+ """
601
+ return self._instance.__class__.__bases__
602
+
603
+ def isInstanceOf(self, cls: Type) -> bool:
604
+ """
605
+ Check if the instance is of a specific class.
606
+
607
+ Parameters
608
+ ----------
609
+ cls : Type
610
+ The class to check against
611
+
612
+ Returns
613
+ -------
614
+ bool
615
+ True if the instance is of the specified class
616
+ """
617
+ return isinstance(self._instance, cls)
618
+
619
+ def getSourceCode(self) -> Optional[str]:
620
+ """
621
+ Get the source code of the instance's class.
622
+
623
+ Returns
624
+ -------
625
+ Optional[str]
626
+ The source code if available, None otherwise
627
+ """
628
+ try:
629
+ return inspect.getsource(self._instance.__class__)
630
+ except (TypeError, OSError):
631
+ return None
632
+
633
+ def getFileLocation(self) -> Optional[str]:
634
+ """
635
+ Get the file location where the class is defined.
636
+
637
+ Returns
638
+ -------
639
+ Optional[str]
640
+ The file path if available, None otherwise
641
+ """
642
+ try:
643
+ return inspect.getfile(self._instance.__class__)
644
+ except (TypeError, OSError):
645
+ return None
646
+
647
+ def getAnnotations(self) -> Dict[str, Any]:
648
+ """
649
+ Get type annotations of the class.
650
+
651
+ Returns
652
+ -------
653
+ Dict[str, Any]
654
+ Dictionary of attribute names and their type annotations
655
+ """
656
+ return self._instance.__class__.__annotations__
657
+
658
+ def hasAttribute(self, name: str) -> bool:
659
+ """
660
+ Check if the instance has a specific attribute.
661
+
662
+ Parameters
663
+ ----------
664
+ name : str
665
+ The attribute name to check
666
+
667
+ Returns
668
+ -------
669
+ bool
670
+ True if the attribute exists
671
+ """
672
+ return hasattr(self._instance, name)
673
+
674
+ def getAttribute(self, name: str) -> Any:
675
+ """
676
+ Get an attribute value by name.
677
+
678
+ Parameters
679
+ ----------
680
+ name : str
681
+ The attribute name
682
+
683
+ Returns
684
+ -------
685
+ Any
686
+ The attribute value
687
+
688
+ Raises
689
+ ------
690
+ AttributeError
691
+ If the attribute doesn't exist
692
+ """
693
+ attrs = self.getAttributes()
694
+ return attrs.get(name, getattr(self._instance, name, None))
695
+
696
+ def setAttribute(self, name: str, value: Any) -> None:
697
+ """
698
+ Set an attribute value.
699
+
700
+ Parameters
701
+ ----------
702
+ name : str
703
+ The attribute name
704
+ value : Any
705
+ The value to set
706
+
707
+ Raises
708
+ ------
709
+ AttributeError
710
+ If the attribute is read-only
711
+ """
712
+ if callable(value):
713
+ raise AttributeError(f"Cannot set attribute '{name}' to a callable. Use setMacro instead.")
714
+ setattr(self._instance, name, value)
715
+
716
+ def removeAttribute(self, name: str) -> None:
717
+ """
718
+ Remove an attribute from the instance.
719
+
720
+ Parameters
721
+ ----------
722
+ name : str
723
+ The attribute name to remove
724
+
725
+ Raises
726
+ ------
727
+ AttributeError
728
+ If the attribute doesn't exist or is read-only
729
+ """
730
+ if not hasattr(self._instance, name):
731
+ raise AttributeError(f"'{self.getClassName()}' object has no attribute '{name}'.")
732
+ delattr(self._instance, name)
733
+
734
+ def setMacro(self, name: str, value: Callable) -> None:
735
+ """
736
+ Set a callable attribute value.
737
+
738
+ Parameters
739
+ ----------
740
+ name : str
741
+ The attribute name
742
+ value : Callable
743
+ The callable to set
744
+
745
+ Raises
746
+ ------
747
+ AttributeError
748
+ If the value is not callable
749
+ """
750
+ if not callable(value):
751
+ raise AttributeError(f"The value for '{name}' must be a callable.")
752
+ setattr(self._instance, name, value)
753
+
754
+ def removeMacro(self, name: str) -> None:
755
+ """
756
+ Remove a callable attribute from the instance.
757
+
758
+ Parameters
759
+ ----------
760
+ name : str
761
+ The attribute name to remove
762
+
763
+ Raises
764
+ ------
765
+ AttributeError
766
+ If the attribute doesn't exist or is not callable
767
+ """
768
+ if not hasattr(self._instance, name) or not callable(getattr(self._instance, name)):
769
+ raise AttributeError(f"'{self.getClassName()}' object has no callable macro '{name}'.")
770
+ delattr(self._instance, name)
771
+
772
+ def getConstructorDependencies(self) -> ClassDependency:
773
+ """
774
+ Get the resolved and unresolved dependencies from the constructor of the instance's class.
775
+
776
+ Returns
777
+ -------
778
+ ClassDependency
779
+ A structured representation of the constructor dependencies, containing:
780
+ - resolved: Dictionary of resolved dependencies with their names and values.
781
+ - unresolved: List of unresolved dependencies (parameter names without default values or annotations).
782
+ """
783
+ return ReflectDependencies(self._instance.__class__).getConstructorDependencies()
784
+
785
+ def getMethodDependencies(self, method_name: str) -> MethodDependency:
786
+ """
787
+ Get the resolved and unresolved dependencies from a method of the instance's class.
788
+
789
+ Parameters
790
+ ----------
791
+ method_name : str
792
+ The name of the method to inspect
793
+
794
+ Returns
795
+ -------
796
+ MethodDependency
797
+ A structured representation of the method dependencies, containing:
798
+ - resolved: Dictionary of resolved dependencies with their names and values.
799
+ - unresolved: List of unresolved dependencies (parameter names without default values or annotations).
800
+ """
801
+ return ReflectDependencies(self._instance).getMethodDependencies(method_name)