orionis 0.295.0__py3-none-any.whl → 0.297.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 (35) hide show
  1. orionis/metadata/framework.py +1 -1
  2. orionis/services/introspection/dependencies/contracts/reflect_dependencies.py +19 -13
  3. orionis/services/introspection/dependencies/entities/class_dependencies.py +24 -12
  4. orionis/services/introspection/dependencies/entities/method_dependencies.py +26 -13
  5. orionis/services/introspection/dependencies/entities/resolved_dependencies.py +31 -18
  6. orionis/services/introspection/dependencies/reflect_dependencies.py +5 -4
  7. orionis/services/introspection/exceptions/reflection_attribute_error.py +26 -0
  8. orionis/services/introspection/exceptions/reflection_type_error.py +26 -0
  9. orionis/services/introspection/exceptions/reflection_value_error.py +26 -0
  10. orionis/services/introspection/instances/entities/class_attributes.py +20 -0
  11. orionis/services/introspection/instances/entities/class_method.py +41 -0
  12. orionis/services/introspection/instances/entities/class_property.py +24 -0
  13. orionis/services/introspection/instances/reflection_instance.py +1323 -0
  14. orionis/support/helpers/__init__.py +0 -0
  15. orionis/support/introspection/instances/contracts/reflection_instance.py +1 -1
  16. orionis/support/introspection/instances/reflection_instance.py +1 -1
  17. {orionis-0.295.0.dist-info → orionis-0.297.0.dist-info}/METADATA +1 -1
  18. {orionis-0.295.0.dist-info → orionis-0.297.0.dist-info}/RECORD +31 -27
  19. tests/support/inspection/fakes/fake_reflect_instance.py +20 -1
  20. orionis/support/introspection/instances/entities/class_attributes.py +0 -11
  21. orionis/support/introspection/instances/entities/class_method.py +0 -18
  22. orionis/support/introspection/instances/entities/class_parsed.py +0 -18
  23. orionis/support/introspection/instances/entities/class_property.py +0 -13
  24. /orionis/services/introspection/{abstracts → instances}/__init__.py +0 -0
  25. /orionis/services/introspection/{abstracts → instances}/entities/__init__.py +0 -0
  26. /orionis/{services/introspection/helpers → support/abstracts}/__init__.py +0 -0
  27. /orionis/{services/introspection/exceptions/types.py → support/abstracts/entities/__init__.py} +0 -0
  28. /orionis/{services/introspection → support}/abstracts/entities/abstract_class_attributes.py +0 -0
  29. /orionis/{services/introspection → support}/abstracts/reflect_abstract.py +0 -0
  30. /orionis/{services/introspection → support}/helpers/functions.py +0 -0
  31. /orionis/{services/introspection → support}/reflection.py +0 -0
  32. {orionis-0.295.0.dist-info → orionis-0.297.0.dist-info}/WHEEL +0 -0
  33. {orionis-0.295.0.dist-info → orionis-0.297.0.dist-info}/licenses/LICENCE +0 -0
  34. {orionis-0.295.0.dist-info → orionis-0.297.0.dist-info}/top_level.txt +0 -0
  35. {orionis-0.295.0.dist-info → orionis-0.297.0.dist-info}/zip-safe +0 -0
@@ -0,0 +1,1323 @@
1
+ import inspect
2
+ from typing import Any, Callable, Dict, List, Optional, Tuple, Type
3
+ from orionis.services.asynchrony.coroutines import Coroutine
4
+ from orionis.services.introspection.dependencies.entities.class_dependencies import ClassDependency
5
+ from orionis.services.introspection.dependencies.entities.method_dependencies import MethodDependency
6
+ from orionis.services.introspection.dependencies.reflect_dependencies import ReflectDependencies
7
+ from orionis.services.introspection.exceptions.reflection_attribute_error import ReflectionAttributeError
8
+ from orionis.services.introspection.exceptions.reflection_type_error import ReflectionTypeError
9
+ from orionis.services.introspection.exceptions.reflection_value_error import ReflectionValueError
10
+ from orionis.services.introspection.instances.entities.class_attributes import ClassAttributes
11
+ from orionis.services.introspection.instances.entities.class_method import ClassMethod
12
+ from orionis.services.introspection.instances.entities.class_property import ClassProperty
13
+
14
+ class ReflectionInstance:
15
+
16
+ def __init__(self, instance: Any) -> None:
17
+ """
18
+ Initialize the ReflectionInstance with a given object instance.
19
+
20
+ Parameters
21
+ ----------
22
+ instance : Any
23
+ The object instance to be reflected upon.
24
+
25
+ Raises
26
+ ------
27
+ ReflectionTypeError
28
+ If the provided instance is not a valid object instance.
29
+ ReflectionValueError
30
+ If the instance belongs to a built-in, abstract base class, or '__main__' module.
31
+ """
32
+ if not (isinstance(instance, object) and not isinstance(instance, type)):
33
+ raise ReflectionTypeError(
34
+ f"Expected an object instance, got {type(instance).__name__!r}: {instance!r}"
35
+ )
36
+ module = type(instance).__module__
37
+ if module in {'builtins', 'abc'}:
38
+ raise ReflectionValueError(
39
+ f"Instance of type '{type(instance).__name__}' belongs to disallowed module '{module}'."
40
+ )
41
+ if module == '__main__':
42
+ raise ReflectionValueError(
43
+ "Instance originates from '__main__'; please provide an instance from an importable module."
44
+ )
45
+ self._instance = instance
46
+
47
+ def getClass(self) -> Type:
48
+ """
49
+ Get the class of the instance.
50
+
51
+ Returns
52
+ -------
53
+ Type
54
+ The class object of the instance
55
+ """
56
+ return self._instance.__class__
57
+
58
+ def getClassName(self) -> str:
59
+ """
60
+ Get the name of the instance's class.
61
+
62
+ Returns
63
+ -------
64
+ str
65
+ The name of the class
66
+ """
67
+ return self._instance.__class__.__name__
68
+
69
+ def getModuleName(self) -> str:
70
+ """
71
+ Get the name of the module where the class is defined.
72
+
73
+ Returns
74
+ -------
75
+ str
76
+ The module name
77
+ """
78
+ return self._instance.__class__.__module__
79
+
80
+ def getModuleWithClassName(self) -> str:
81
+ """
82
+ Get the name of the module where the class is defined.
83
+
84
+ Returns
85
+ -------
86
+ str
87
+ The module name
88
+ """
89
+ return f"{self._instance.__class__}.{self._instance.__class__.__module__}"
90
+
91
+ def getAttributes(self) -> Dict[str, Any]:
92
+ """
93
+ Get all attributes of the instance, including public, private, protected, and dunder attributes.
94
+
95
+ Returns
96
+ -------
97
+ Dict[str, Any]
98
+ Dictionary of all attribute names and their values
99
+ """
100
+ return {
101
+ **self.getPublicAttributes(),
102
+ **self.getProtectedAttributes(),
103
+ **self.getPrivateAttributes(),
104
+ **self.getDunderAttributes()
105
+ }
106
+
107
+ def getPublicAttributes(self) -> Dict[str, Any]:
108
+ """
109
+ Get all public attributes of the instance.
110
+
111
+ Returns
112
+ -------
113
+ Dict[str, Any]
114
+ Dictionary of public attribute names and their values
115
+ """
116
+ class_name = self.getClassName()
117
+ attributes = vars(self._instance)
118
+ public = {}
119
+
120
+ # Exclude dunder, protected, and private attributes
121
+ for attr, value in attributes.items():
122
+ if attr.startswith("__") and attr.endswith("__"):
123
+ continue
124
+ if attr.startswith(f"_{class_name}"):
125
+ continue
126
+ if attr.startswith("_"):
127
+ continue
128
+ public[attr] = value
129
+
130
+ return public
131
+
132
+ def getProtectedAttributes(self) -> Dict[str, Any]:
133
+ """
134
+ Get all Protected attributes of the instance.
135
+
136
+ Returns
137
+ -------
138
+ Dict[str, Any]
139
+ Dictionary of Protected attribute names and their values
140
+ """
141
+ class_name = self.getClassName()
142
+ attributes = vars(self._instance)
143
+ protected = {}
144
+
145
+ # Select protected attributes that start with a single underscore
146
+ for attr, value in attributes.items():
147
+ if attr.startswith("_") and not attr.startswith("__") and not attr.startswith(f"_{class_name}"):
148
+ protected[attr] = value
149
+
150
+ return protected
151
+
152
+ def getPrivateAttributes(self) -> Dict[str, Any]:
153
+ """
154
+ Get all private attributes of the instance.
155
+
156
+ Returns
157
+ -------
158
+ Dict[str, Any]
159
+ Dictionary of private attribute names and their values
160
+ """
161
+ class_name = self.getClassName()
162
+ attributes = vars(self._instance)
163
+ private = {}
164
+
165
+ # Select private attributes that start with the class name
166
+ for attr, value in attributes.items():
167
+ if attr.startswith(f"_{class_name}"):
168
+ private[str(attr).replace(f"_{class_name}", "")] = value
169
+
170
+ return private
171
+
172
+ def getDunderAttributes(self) -> Dict[str, Any]:
173
+ """
174
+ Get all dunder (double underscore) attributes of the instance.
175
+
176
+ Returns
177
+ -------
178
+ Dict[str, Any]
179
+ Dictionary of dunder attribute names and their values
180
+ """
181
+ attributes = vars(self._instance)
182
+ dunder = {}
183
+
184
+ # Select dunder attributes that start and end with double underscores
185
+ for attr, value in attributes.items():
186
+ if attr.startswith("__") and attr.endswith("__"):
187
+ dunder[attr] = value
188
+
189
+ return dunder
190
+
191
+ def getPublicMethods(self) -> List[str]:
192
+ """
193
+ Get all public method names of the instance.
194
+
195
+ Returns
196
+ -------
197
+ List[str]
198
+ List of public method names
199
+ """
200
+ class_name = self.getClassName()
201
+ cls = self._instance.__class__
202
+ public_methods = []
203
+
204
+ # Gather all class methods to exclude them
205
+ class_methods = set()
206
+ for name in dir(cls):
207
+ attr = inspect.getattr_static(cls, name)
208
+ if isinstance(attr, classmethod):
209
+ class_methods.add(name)
210
+
211
+ # Collect public instance methods (not static, not class, not private/protected/magic)
212
+ for name, method in inspect.getmembers(self._instance, predicate=inspect.ismethod):
213
+ if (
214
+ name not in class_methods and
215
+ not (name.startswith("__") and name.endswith("__")) and
216
+ not name.startswith(f"_{class_name}") and
217
+ not (name.startswith("_") and not name.startswith(f"_{class_name}"))
218
+ ):
219
+ public_methods.append(name)
220
+
221
+ return public_methods
222
+
223
+ def getPublicSyncMethods(self) -> List[str]:
224
+ """
225
+ Get all public synchronous method names of the instance.
226
+
227
+ Returns
228
+ -------
229
+ List[str]
230
+ List of public synchronous method names
231
+ """
232
+ methods = self.getPublicMethods()
233
+ return [method for method in methods if not inspect.iscoroutinefunction(getattr(self._instance, method))]
234
+
235
+ def getPublicAsyncMethods(self) -> List[str]:
236
+ """
237
+ Get all public asynchronous method names of the instance.
238
+
239
+ Returns
240
+ -------
241
+ List[str]
242
+ List of public asynchronous method names
243
+ """
244
+ methods = self.getPublicMethods()
245
+ return [method for method in methods if inspect.iscoroutinefunction(getattr(self._instance, method))]
246
+
247
+ def getProtectedMethods(self) -> List[str]:
248
+ """
249
+ Get all protected method names of the instance.
250
+
251
+ Returns
252
+ -------
253
+ List[str]
254
+ List of protected method names
255
+ """
256
+ protected_methods = []
257
+
258
+ # Collect protected instance methods (starting with a single underscore)
259
+ for name, method in inspect.getmembers(self._instance, predicate=inspect.ismethod):
260
+ if name.startswith("_") and not name.startswith("__") and not name.startswith(f"_{self.getClassName()}"):
261
+ protected_methods.append(name)
262
+
263
+ return protected_methods
264
+
265
+ def getProtectedSyncMethods(self) -> List[str]:
266
+ """
267
+ Get all protected synchronous method names of the instance.
268
+
269
+ Returns
270
+ -------
271
+ List[str]
272
+ List of protected synchronous method names
273
+ """
274
+ methods = self.getProtectedMethods()
275
+ return [method for method in methods if not inspect.iscoroutinefunction(getattr(self._instance, method))]
276
+
277
+ def getProtectedAsyncMethods(self) -> List[str]:
278
+ """
279
+ Get all protected asynchronous method names of the instance.
280
+
281
+ Returns
282
+ -------
283
+ List[str]
284
+ List of protected asynchronous method names
285
+ """
286
+ methods = self.getProtectedMethods()
287
+ return [method for method in methods if inspect.iscoroutinefunction(getattr(self._instance, method))]
288
+
289
+ def getPrivateMethods(self) -> List[str]:
290
+ """
291
+ Get all private method names of the instance.
292
+
293
+ Returns
294
+ -------
295
+ List[str]
296
+ List of private method names
297
+ """
298
+ class_name = self.getClassName()
299
+ private_methods = []
300
+
301
+ # Collect private instance methods (starting with class name)
302
+ for name, method in inspect.getmembers(self._instance, predicate=inspect.ismethod):
303
+ if name.startswith(f"_{class_name}") and not name.startswith("__"):
304
+ private_methods.append(name.replace(f"_{class_name}", ""))
305
+
306
+ # Return private methods without the class name prefix
307
+ return private_methods
308
+
309
+ def getPrivateSyncMethods(self) -> List[str]:
310
+ """
311
+ Get all private synchronous method names of the instance.
312
+
313
+ Returns
314
+ -------
315
+ List[str]
316
+ List of private synchronous method names
317
+ """
318
+ class_name = self.getClassName()
319
+ private_methods = []
320
+ for name, method in inspect.getmembers(self._instance, predicate=inspect.ismethod):
321
+ if name.startswith(f"_{class_name}") and not name.startswith("__"):
322
+ # Remove the class name prefix for the returned name
323
+ short_name = name.replace(f"_{class_name}", "")
324
+ if not inspect.iscoroutinefunction(method):
325
+ private_methods.append(short_name)
326
+ return private_methods
327
+
328
+ def getPrivateAsyncMethods(self) -> List[str]:
329
+ """
330
+ Get all private asynchronous method names of the instance.
331
+
332
+ Returns
333
+ -------
334
+ List[str]
335
+ List of private asynchronous method names
336
+ """
337
+ class_name = self.getClassName()
338
+ private_methods = []
339
+ for name, method in inspect.getmembers(self._instance, predicate=inspect.ismethod):
340
+ if name.startswith(f"_{class_name}") and not name.startswith("__"):
341
+ # Remove the class name prefix for the returned name
342
+ short_name = name.replace(f"_{class_name}", "")
343
+ if inspect.iscoroutinefunction(method):
344
+ private_methods.append(short_name)
345
+ return private_methods
346
+
347
+ def getPublicClassMethods(self) -> List[str]:
348
+ """
349
+ Get all class method names of the instance.
350
+
351
+ Returns
352
+ -------
353
+ List[str]
354
+ List of class method names
355
+ """
356
+ cls = self._instance.__class__
357
+ class_methods = []
358
+
359
+ # Iterate over all attributes of the class
360
+ for name in dir(cls):
361
+
362
+ # Get the attribute using getattr_static to avoid triggering property getters
363
+ attr = inspect.getattr_static(cls, name)
364
+
365
+ # Check if the attribute is a class method
366
+ if isinstance(attr, classmethod):
367
+
368
+ # Check not private or protected methods
369
+ if not name.startswith(f"_"):
370
+ class_methods.append(name)
371
+
372
+ # Return the list of public class method
373
+ return class_methods
374
+
375
+ def getPublicClassSyncMethods(self) -> List[str]:
376
+ """
377
+ Get all public synchronous class method names of the instance.
378
+
379
+ Returns
380
+ -------
381
+ List[str]
382
+ List of public synchronous class method names
383
+ """
384
+ class_name = self.getClassName()
385
+ cls = self._instance.__class__
386
+ public_class_sync_methods = []
387
+
388
+ # Iterate over all attributes of the class
389
+ for name in dir(cls):
390
+
391
+ # Get the attribute using getattr_static to avoid triggering property getters
392
+ attr = inspect.getattr_static(cls, name)
393
+
394
+ # Check if the attribute is a class method
395
+ if isinstance(attr, classmethod):
396
+
397
+ # Get the underlying function
398
+ func = attr.__func__
399
+
400
+ # Check if it's NOT a coroutine function (i.e., synchronous)
401
+ if not inspect.iscoroutinefunction(func) and not name.startswith(f"_"):
402
+ public_class_sync_methods.append(str(name).replace(f"_{class_name}", ""))
403
+
404
+ # Return the list of public synchronous class method names
405
+ return public_class_sync_methods
406
+
407
+ def getPublicClassAsyncMethods(self) -> List[str]:
408
+ """
409
+ Get all public asynchronous class method names of the instance.
410
+
411
+ Returns
412
+ -------
413
+ List[str]
414
+ List of public asynchronous class method names
415
+ """
416
+ class_name = self.getClassName()
417
+ cls = self._instance.__class__
418
+ public_class_async_methods = []
419
+
420
+ # Iterate over all attributes of the class
421
+ for name in dir(cls):
422
+
423
+ # Get the attribute using getattr_static to avoid triggering property getters
424
+ attr = inspect.getattr_static(cls, name)
425
+
426
+ # Check if the attribute is a class method
427
+ if isinstance(attr, classmethod):
428
+
429
+ # Get the underlying function
430
+ func = attr.__func__
431
+
432
+ # Check if it's a coroutine function (i.e., asynchronous)
433
+ if inspect.iscoroutinefunction(func) and not name.startswith(f"_"):
434
+ public_class_async_methods.append(str(name).replace(f"_{class_name}", ""))
435
+
436
+ # Return the list of public asynchronous class method names
437
+ return public_class_async_methods
438
+
439
+
440
+
441
+
442
+
443
+
444
+
445
+
446
+
447
+
448
+
449
+
450
+
451
+
452
+
453
+
454
+
455
+
456
+
457
+
458
+
459
+
460
+
461
+
462
+
463
+
464
+
465
+
466
+ def getProtectedClassMethods(self) -> List[str]:
467
+ """
468
+ Get all protected class method names of the instance.
469
+
470
+ Returns
471
+ -------
472
+ List[str]
473
+ List of protected class method names
474
+ """
475
+ class_name = self.getClassName()
476
+ cls = self._instance.__class__
477
+ protected_class_methods = []
478
+
479
+ # Iterate over all attributes of the class
480
+ for name in dir(cls):
481
+
482
+ # Get the attribute using getattr_static to avoid triggering property getters
483
+ attr = inspect.getattr_static(cls, name)
484
+
485
+ # Check if the attribute is a class method
486
+ if isinstance(attr, classmethod):
487
+
488
+ # Get the underlying function
489
+ func = attr.__func__
490
+
491
+ # Check if it's NOT a coroutine function (i.e., synchronous)
492
+ if not inspect.iscoroutinefunction(func) and name.startswith(f"_") and not name.startswith("__") and not name.startswith(f"_{class_name}"):
493
+ protected_class_methods.append(str(name).replace(f"_{class_name}", ""))
494
+
495
+ # Return the list of protected class method names
496
+ return protected_class_methods
497
+
498
+ def getPrivateClassMethods(self) -> List[str]:
499
+ """
500
+ Get all private class method names of the instance.
501
+
502
+ Returns
503
+ -------
504
+ List[str]
505
+ List of private class method names
506
+ """
507
+ class_name = self.getClassName()
508
+ cls = self._instance.__class__
509
+ private_class_methods = []
510
+
511
+ # Iterate over all attributes of the class
512
+ for name in dir(cls):
513
+
514
+ # Get the attribute using getattr_static to avoid triggering property getters
515
+ attr = inspect.getattr_static(cls, name)
516
+
517
+ # Check if the attribute is a class method
518
+ if isinstance(attr, classmethod):
519
+
520
+ # Get the underlying function
521
+ func = attr.__func__
522
+
523
+ # Check if it's NOT a coroutine function (i.e., synchronous)
524
+ if not inspect.iscoroutinefunction(func) and name.startswith(f"_{class_name}"):
525
+ private_class_methods.append(str(name).replace(f"_{class_name}", ""))
526
+
527
+ # Return the list of protected class method names
528
+ return private_class_methods
529
+
530
+
531
+
532
+
533
+
534
+
535
+
536
+
537
+
538
+
539
+
540
+
541
+
542
+
543
+
544
+
545
+
546
+ def getClassSyncMethods(self) -> List[str]:
547
+ """
548
+ Get all synchronous class method names of the instance.
549
+
550
+ Returns
551
+ -------
552
+ List[str]
553
+ List of synchronous class method names
554
+ """
555
+ class_name = self.getClassName()
556
+ cls = self._instance.__class__
557
+ class_sync_methods = []
558
+
559
+ # Iterate over all attributes of the class
560
+ for name in dir(cls):
561
+
562
+ # Get the attribute using getattr_static to avoid triggering property getters
563
+ attr = inspect.getattr_static(cls, name)
564
+
565
+ # Check if the attribute is a class method
566
+ if isinstance(attr, classmethod):
567
+
568
+ # Get the underlying function
569
+ func = attr.__func__
570
+
571
+ # Check if it's NOT a coroutine function (i.e., synchronous)
572
+ if not inspect.iscoroutinefunction(func):
573
+ class_sync_methods.append(str(name).replace(f"_{class_name}", ""))
574
+
575
+ # Return the list of synchronous class method names
576
+ return class_sync_methods
577
+
578
+ def getClassAsyncMethods(self) -> List[str]:
579
+ """
580
+ Get all asynchronous class method names of the instance.
581
+
582
+ Returns
583
+ -------
584
+ List[str]
585
+ List of asynchronous class method names
586
+ """
587
+ class_name = self.getClassName()
588
+ cls = self._instance.__class__
589
+ class_async_methods = []
590
+
591
+ # Iterate over all attributes of the class
592
+ for name in dir(cls):
593
+
594
+ # Get the attribute using getattr_static to avoid triggering property getters
595
+ attr = inspect.getattr_static(cls, name)
596
+
597
+ # Check if the attribute is a class method
598
+ if isinstance(attr, classmethod):
599
+
600
+ # Get the underlying function
601
+ func = attr.__func__
602
+
603
+ # Check if it's a coroutine function (i.e., asynchronous)
604
+ if inspect.iscoroutinefunction(func):
605
+ class_async_methods.append(str(name).replace(f"_{class_name}", ""))
606
+
607
+ # Return the list of asynchronous class method names
608
+ return class_async_methods
609
+
610
+
611
+
612
+
613
+
614
+
615
+
616
+
617
+
618
+
619
+
620
+
621
+
622
+
623
+
624
+
625
+
626
+
627
+
628
+
629
+
630
+
631
+
632
+
633
+
634
+
635
+
636
+
637
+
638
+
639
+
640
+
641
+ def getDunderMethods(self) -> List[str]:
642
+ """
643
+ Get all dunder (double underscore) method names of the instance.
644
+
645
+ Returns
646
+ -------
647
+ List[str]
648
+ List of dunder method names
649
+ """
650
+ dunder_methods = []
651
+
652
+ # Collect dunder methods (starting and ending with double underscores)
653
+ for name in dir(self._instance):
654
+ if name.startswith("__") and name.endswith("__"):
655
+ dunder_methods.append(name)
656
+
657
+ return dunder_methods
658
+
659
+ def getMagicMethods(self) -> List[str]:
660
+ """
661
+ Get all magic method names of the instance.
662
+
663
+ Returns
664
+ -------
665
+ List[str]
666
+ List of magic method names
667
+ """
668
+ return self.getDunderMethods()
669
+
670
+
671
+
672
+ def getStaticMethods(self) -> List[str]:
673
+ """
674
+ Get all static method names of the instance.
675
+
676
+ Returns
677
+ -------
678
+ List[str]
679
+ List of static method names
680
+ """
681
+ class_name = self.getClassName()
682
+ cls = self._instance.__class__
683
+ static_methods = []
684
+ for name in dir(cls):
685
+ attr = inspect.getattr_static(cls, name)
686
+ if isinstance(attr, staticmethod):
687
+ static_methods.append(str(name).replace(f"_{class_name}", ""))
688
+ return static_methods
689
+
690
+ def getStaticSyncMethods(self) -> List[str]:
691
+ """
692
+ Get all synchronous static method names of the instance.
693
+
694
+ Returns
695
+ -------
696
+ List[str]
697
+ List of synchronous static method names
698
+ """
699
+ class_name = self.getClassName()
700
+ cls = self._instance.__class__
701
+ static_sync_methods = []
702
+
703
+ # Iterate over all attributes of the class
704
+ for name in dir(cls):
705
+
706
+ # Get the attribute using getattr_static to avoid triggering property getters
707
+ attr = inspect.getattr_static(cls, name)
708
+
709
+ # Check if the attribute is a static method
710
+ if isinstance(attr, staticmethod):
711
+
712
+ # Get the underlying function
713
+ func = attr.__func__
714
+
715
+ # Check if it's NOT a coroutine function (i.e., synchronous)
716
+ if not inspect.iscoroutinefunction(func):
717
+ static_sync_methods.append(str(name).replace(f"_{class_name}", ""))
718
+
719
+ # Return the list of synchronous static method names
720
+ return static_sync_methods
721
+
722
+ def getStaticAsyncMethods(self) -> List[str]:
723
+ """
724
+ Get all asynchronous static method names of the instance.
725
+
726
+ Returns
727
+ -------
728
+ List[str]
729
+ List of asynchronous static method names
730
+ """
731
+ class_name = self.getClassName()
732
+ cls = self._instance.__class__
733
+ static_async_methods = []
734
+
735
+ # Iterate over all attributes of the class
736
+ for name in dir(cls):
737
+
738
+ # Get the attribute using getattr_static to avoid triggering property getters
739
+ attr = inspect.getattr_static(cls, name)
740
+
741
+ # Check if the attribute is a static method
742
+ if isinstance(attr, staticmethod):
743
+
744
+ # Get the underlying function
745
+ func = attr.__func__
746
+
747
+ # Check if it's a coroutine function (i.e., asynchronous)
748
+ if inspect.iscoroutinefunction(func):
749
+ static_async_methods.append(str(name).replace(f"_{class_name}", ""))
750
+
751
+ # Return the list of asynchronous static method names
752
+ return static_async_methods
753
+
754
+ # def getMethodDocstring(self, method_name: str) -> Optional[str]:
755
+ # """
756
+ # Get the docstring of a method.
757
+
758
+ # Parameters
759
+ # ----------
760
+ # method_name : str
761
+ # Name of the method
762
+
763
+ # Returns
764
+ # -------
765
+ # Optional[str]
766
+ # The docstring of the method, or None if not available
767
+ # """
768
+ # # Handle private method name mangling
769
+ # if method_name in self.getPrivateMethods() or method_name in self.getClass
770
+ # method_name = f"_{self.getClassName()}{method_name}"
771
+
772
+ # print(f"Getting docstring for method: {method_name} in class: {self.getPrivateMethods()}")
773
+
774
+ # # Try to get the method from the instance first
775
+ # method = getattr(self._instance, method_name, None)
776
+ # if method is None:
777
+ # # Try to get the method from the class if not found on the instance
778
+ # method = getattr(self._instance.__class__, method_name, None)
779
+ # if method is None:
780
+ # return None
781
+
782
+ # # If it's a staticmethod or classmethod, get the underlying function
783
+ # if isinstance(method, (staticmethod, classmethod)):
784
+ # method = method.__func__
785
+
786
+ # # Return the docstring if available
787
+ # return getattr(method, "__doc__", None) or ""
788
+
789
+ # def getMethodSignature(self, method_name: str) -> inspect.Signature:
790
+ # """
791
+ # Get the signature of a method.
792
+
793
+ # Parameters
794
+ # ----------
795
+ # method_name : str
796
+ # Name of the method
797
+
798
+ # Returns
799
+ # -------
800
+ # inspect.Signature
801
+ # The method signature
802
+
803
+ # Raises
804
+ # ------
805
+ # ReflectionAttributeError
806
+ # If the method does not exist on the instance
807
+ # """
808
+ # if method_name in self.getPrivateMethods():
809
+ # method_name = f"_{self.getClassName()}{method_name}"
810
+
811
+ # method = getattr(self._instance, method_name, None)
812
+ # if method is None or not callable(method):
813
+ # raise ReflectionAttributeError(f"Method '{method_name}' not found in '{self.getClassName()}'.")
814
+
815
+ # return inspect.signature(method)
816
+
817
+
818
+
819
+
820
+
821
+
822
+
823
+
824
+
825
+
826
+
827
+
828
+
829
+
830
+
831
+
832
+
833
+
834
+
835
+
836
+
837
+
838
+
839
+
840
+
841
+
842
+
843
+
844
+
845
+
846
+
847
+
848
+
849
+
850
+
851
+
852
+
853
+
854
+
855
+
856
+
857
+
858
+
859
+
860
+
861
+
862
+
863
+
864
+
865
+
866
+
867
+
868
+
869
+
870
+
871
+
872
+
873
+
874
+
875
+
876
+
877
+
878
+
879
+
880
+
881
+
882
+
883
+
884
+
885
+
886
+
887
+
888
+
889
+
890
+
891
+
892
+
893
+
894
+
895
+
896
+
897
+ def getProperties(self) -> Dict[str, ClassProperty]:
898
+ """
899
+ Get all properties of the instance.
900
+
901
+ Returns
902
+ -------
903
+ List[str]
904
+ List of property names
905
+ """
906
+
907
+ properties = {}
908
+ for name, prop in self._instance.__class__.__dict__.items():
909
+ if isinstance(prop, property):
910
+ properties[name] = ClassProperty(
911
+ name=name,
912
+ value=getattr(self._instance, name, None),
913
+ signature=inspect.signature(prop.fget) if prop.fget else None,
914
+ doc=prop.__doc__ or ""
915
+ )
916
+ return properties
917
+
918
+ def getPropertyNames(self) -> List[str]:
919
+ """
920
+ Get all property names of the instance.
921
+
922
+ Returns
923
+ -------
924
+ List[str]
925
+ List of property names
926
+ """
927
+ return self.getProperties().keys()
928
+
929
+ def getProperty(self, property_name: str) -> Any:
930
+ """
931
+ Get the value of a property.
932
+
933
+ Parameters
934
+ ----------
935
+ property_name : str
936
+ Name of the property
937
+
938
+ Returns
939
+ -------
940
+ Any
941
+ The value of the property
942
+
943
+ Raises
944
+ ------
945
+ AttributeError
946
+ If the property doesn't exist or is not a property
947
+ """
948
+ all_prop = self.getProperties()
949
+ if property_name not in all_prop:
950
+ raise ReflectionValueError(f"Property '{property_name}' not found.")
951
+ return all_prop[property_name].value
952
+
953
+ def getPropertySignature(self, property_name: str) -> inspect.Signature:
954
+ """
955
+ Get the signature of a property.
956
+
957
+ Parameters
958
+ ----------
959
+ property_name : str
960
+ Name of the property
961
+
962
+ Returns
963
+ -------
964
+ inspect.Signature
965
+ The property signature
966
+
967
+ Raises
968
+ ------
969
+ AttributeError
970
+ If the property doesn't exist or is not a property
971
+ """
972
+ all_prop = self.getProperties()
973
+ if property_name not in all_prop:
974
+ raise ReflectionValueError(f"Property '{property_name}' not found.")
975
+ return all_prop[property_name].signature
976
+
977
+ def getPropertyDoc(self, property_name: str) -> str:
978
+ """
979
+ Get the docstring of a property.
980
+
981
+ Parameters
982
+ ----------
983
+ property_name : str
984
+ Name of the property
985
+
986
+ Returns
987
+ -------
988
+ str
989
+ The docstring of the property
990
+
991
+ Raises
992
+ ------
993
+ AttributeError
994
+ If the property doesn't exist or is not a property
995
+ """
996
+ all_prop = self.getProperties()
997
+ if property_name not in all_prop:
998
+ raise ReflectionValueError(f"Property '{property_name}' not found.")
999
+ return all_prop[property_name].doc
1000
+
1001
+
1002
+
1003
+
1004
+
1005
+
1006
+
1007
+
1008
+
1009
+
1010
+
1011
+
1012
+
1013
+
1014
+
1015
+
1016
+
1017
+
1018
+
1019
+
1020
+
1021
+
1022
+
1023
+
1024
+
1025
+
1026
+
1027
+
1028
+
1029
+
1030
+
1031
+
1032
+
1033
+
1034
+
1035
+
1036
+
1037
+
1038
+
1039
+
1040
+
1041
+ def callMethod(self, method_name: str, *args: Any, **kwargs: Any) -> Any:
1042
+ """
1043
+ Call a method on the instance.
1044
+
1045
+ Parameters
1046
+ ----------
1047
+ method_name : str
1048
+ Name of the method to call
1049
+ *args : Any
1050
+ Positional arguments for the method
1051
+ **kwargs : Any
1052
+ Keyword arguments for the method
1053
+
1054
+ Returns
1055
+ -------
1056
+ Any
1057
+ The result of the method call
1058
+
1059
+ Raises
1060
+ ------
1061
+ AttributeError
1062
+ If the method does not exist on the instance
1063
+ TypeError
1064
+ If the method is not callable
1065
+ """
1066
+
1067
+ if method_name in self.getPrivateMethods():
1068
+ method_name = f"_{self.getClassName()}{method_name}"
1069
+
1070
+ method = getattr(self._instance, method_name, None)
1071
+
1072
+ if method is None:
1073
+ raise AttributeError(f"'{self.getClassName()}' object has no method '{method_name}'.")
1074
+ if not callable(method):
1075
+ raise TypeError(f"'{method_name}' is not callable on '{self.getClassName()}'.")
1076
+
1077
+ if inspect.iscoroutinefunction(method):
1078
+ return Coroutine(method(*args, **kwargs)).run()
1079
+
1080
+ return method(*args, **kwargs)
1081
+
1082
+ def getMethodSignature(self, method_name: str) -> inspect.Signature:
1083
+ """
1084
+ Get the signature of a method.
1085
+
1086
+ Parameters
1087
+ ----------
1088
+ method_name : str
1089
+ Name of the method
1090
+
1091
+ Returns
1092
+ -------
1093
+ inspect.Signature
1094
+ The method signature
1095
+ """
1096
+ if method_name in self.getPrivateMethods():
1097
+ method_name = f"_{self.getClassName()}{method_name}"
1098
+
1099
+ method = getattr(self._instance, method_name)
1100
+ if callable(method):
1101
+ return inspect.signature(method)
1102
+
1103
+ def getDocstring(self) -> Optional[str]:
1104
+ """
1105
+ Get the docstring of the instance's class.
1106
+
1107
+ Returns
1108
+ -------
1109
+ Optional[str]
1110
+ The class docstring, or None if not available
1111
+ """
1112
+ return self._instance.__class__.__doc__
1113
+
1114
+ def getBaseClasses(self) -> Tuple[Type, ...]:
1115
+ """
1116
+ Get the base classes of the instance's class.
1117
+
1118
+ Returns
1119
+ -------
1120
+ Tuple[Type, ...]
1121
+ Tuple of base classes
1122
+ """
1123
+ return self._instance.__class__.__bases__
1124
+
1125
+ def isInstanceOf(self, cls: Type) -> bool:
1126
+ """
1127
+ Check if the instance is of a specific class.
1128
+
1129
+ Parameters
1130
+ ----------
1131
+ cls : Type
1132
+ The class to check against
1133
+
1134
+ Returns
1135
+ -------
1136
+ bool
1137
+ True if the instance is of the specified class
1138
+ """
1139
+ return isinstance(self._instance, cls)
1140
+
1141
+ def getSourceCode(self) -> Optional[str]:
1142
+ """
1143
+ Get the source code of the instance's class.
1144
+
1145
+ Returns
1146
+ -------
1147
+ Optional[str]
1148
+ The source code if available, None otherwise
1149
+ """
1150
+ try:
1151
+ return inspect.getsource(self._instance.__class__)
1152
+ except (TypeError, OSError):
1153
+ return None
1154
+
1155
+ def getFileLocation(self) -> Optional[str]:
1156
+ """
1157
+ Get the file location where the class is defined.
1158
+
1159
+ Returns
1160
+ -------
1161
+ Optional[str]
1162
+ The file path if available, None otherwise
1163
+ """
1164
+ try:
1165
+ return inspect.getfile(self._instance.__class__)
1166
+ except (TypeError, OSError):
1167
+ return None
1168
+
1169
+ def getAnnotations(self) -> Dict[str, Any]:
1170
+ """
1171
+ Get type annotations of the class.
1172
+
1173
+ Returns
1174
+ -------
1175
+ Dict[str, Any]
1176
+ Dictionary of attribute names and their type annotations
1177
+ """
1178
+ return self._instance.__class__.__annotations__
1179
+
1180
+ def hasAttribute(self, name: str) -> bool:
1181
+ """
1182
+ Check if the instance has a specific attribute.
1183
+
1184
+ Parameters
1185
+ ----------
1186
+ name : str
1187
+ The attribute name to check
1188
+
1189
+ Returns
1190
+ -------
1191
+ bool
1192
+ True if the attribute exists
1193
+ """
1194
+ return hasattr(self._instance, name)
1195
+
1196
+ def getAttribute(self, name: str) -> Any:
1197
+ """
1198
+ Get an attribute value by name.
1199
+
1200
+ Parameters
1201
+ ----------
1202
+ name : str
1203
+ The attribute name
1204
+
1205
+ Returns
1206
+ -------
1207
+ Any
1208
+ The attribute value
1209
+
1210
+ Raises
1211
+ ------
1212
+ AttributeError
1213
+ If the attribute doesn't exist
1214
+ """
1215
+ attrs = self.getAttributes()
1216
+ return attrs.get(name, getattr(self._instance, name, None))
1217
+
1218
+ def setAttribute(self, name: str, value: Any) -> None:
1219
+ """
1220
+ Set an attribute value.
1221
+
1222
+ Parameters
1223
+ ----------
1224
+ name : str
1225
+ The attribute name
1226
+ value : Any
1227
+ The value to set
1228
+
1229
+ Raises
1230
+ ------
1231
+ AttributeError
1232
+ If the attribute is read-only
1233
+ """
1234
+ if callable(value):
1235
+ raise AttributeError(f"Cannot set attribute '{name}' to a callable. Use setMacro instead.")
1236
+ setattr(self._instance, name, value)
1237
+
1238
+ def removeAttribute(self, name: str) -> None:
1239
+ """
1240
+ Remove an attribute from the instance.
1241
+
1242
+ Parameters
1243
+ ----------
1244
+ name : str
1245
+ The attribute name to remove
1246
+
1247
+ Raises
1248
+ ------
1249
+ AttributeError
1250
+ If the attribute doesn't exist or is read-only
1251
+ """
1252
+ if not hasattr(self._instance, name):
1253
+ raise AttributeError(f"'{self.getClassName()}' object has no attribute '{name}'.")
1254
+ delattr(self._instance, name)
1255
+
1256
+ def setMacro(self, name: str, value: Callable) -> None:
1257
+ """
1258
+ Set a callable attribute value.
1259
+
1260
+ Parameters
1261
+ ----------
1262
+ name : str
1263
+ The attribute name
1264
+ value : Callable
1265
+ The callable to set
1266
+
1267
+ Raises
1268
+ ------
1269
+ AttributeError
1270
+ If the value is not callable
1271
+ """
1272
+ if not callable(value):
1273
+ raise AttributeError(f"The value for '{name}' must be a callable.")
1274
+ setattr(self._instance, name, value)
1275
+
1276
+ def removeMacro(self, name: str) -> None:
1277
+ """
1278
+ Remove a callable attribute from the instance.
1279
+
1280
+ Parameters
1281
+ ----------
1282
+ name : str
1283
+ The attribute name to remove
1284
+
1285
+ Raises
1286
+ ------
1287
+ AttributeError
1288
+ If the attribute doesn't exist or is not callable
1289
+ """
1290
+ if not hasattr(self._instance, name) or not callable(getattr(self._instance, name)):
1291
+ raise AttributeError(f"'{self.getClassName()}' object has no callable macro '{name}'.")
1292
+ delattr(self._instance, name)
1293
+
1294
+ def getConstructorDependencies(self) -> ClassDependency:
1295
+ """
1296
+ Get the resolved and unresolved dependencies from the constructor of the instance's class.
1297
+
1298
+ Returns
1299
+ -------
1300
+ ClassDependency
1301
+ A structured representation of the constructor dependencies, containing:
1302
+ - resolved: Dictionary of resolved dependencies with their names and values.
1303
+ - unresolved: List of unresolved dependencies (parameter names without default values or annotations).
1304
+ """
1305
+ return ReflectDependencies(self._instance.__class__).getConstructorDependencies()
1306
+
1307
+ def getMethodDependencies(self, method_name: str) -> MethodDependency:
1308
+ """
1309
+ Get the resolved and unresolved dependencies from a method of the instance's class.
1310
+
1311
+ Parameters
1312
+ ----------
1313
+ method_name : str
1314
+ The name of the method to inspect
1315
+
1316
+ Returns
1317
+ -------
1318
+ MethodDependency
1319
+ A structured representation of the method dependencies, containing:
1320
+ - resolved: Dictionary of resolved dependencies with their names and values.
1321
+ - unresolved: List of unresolved dependencies (parameter names without default values or annotations).
1322
+ """
1323
+ return ReflectDependencies(self._instance).getMethodDependencies(method_name)