orionis 0.297.0__py3-none-any.whl → 0.299.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.
@@ -1,4 +1,5 @@
1
1
  import inspect
2
+ import keyword
2
3
  from typing import Any, Callable, Dict, List, Optional, Tuple, Type
3
4
  from orionis.services.asynchrony.coroutines import Coroutine
4
5
  from orionis.services.introspection.dependencies.entities.class_dependencies import ClassDependency
@@ -7,11 +8,9 @@ from orionis.services.introspection.dependencies.reflect_dependencies import Ref
7
8
  from orionis.services.introspection.exceptions.reflection_attribute_error import ReflectionAttributeError
8
9
  from orionis.services.introspection.exceptions.reflection_type_error import ReflectionTypeError
9
10
  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
11
+ from orionis.services.introspection.instances.contracts.reflection_instance import IReflectionInstance
13
12
 
14
- class ReflectionInstance:
13
+ class ReflectionInstance(IReflectionInstance):
15
14
 
16
15
  def __init__(self, instance: Any) -> None:
17
16
  """
@@ -44,6 +43,17 @@ class ReflectionInstance:
44
43
  )
45
44
  self._instance = instance
46
45
 
46
+ def getInstance(self) -> Any:
47
+ """
48
+ Get the instance being reflected upon.
49
+
50
+ Returns
51
+ -------
52
+ Any
53
+ The object instance
54
+ """
55
+ return self._instance
56
+
47
57
  def getClass(self) -> Type:
48
58
  """
49
59
  Get the class of the instance.
@@ -86,7 +96,163 @@ class ReflectionInstance:
86
96
  str
87
97
  The module name
88
98
  """
89
- return f"{self._instance.__class__}.{self._instance.__class__.__module__}"
99
+ return f"{self.getModuleName()}.{self.getClassName()}"
100
+
101
+ def getDocstring(self) -> Optional[str]:
102
+ """
103
+ Get the docstring of the instance's class.
104
+
105
+ Returns
106
+ -------
107
+ Optional[str]
108
+ The class docstring, or None if not available
109
+ """
110
+ return self._instance.__class__.__doc__
111
+
112
+ def getBaseClasses(self) -> Tuple[Type, ...]:
113
+ """
114
+ Get the base classes of the instance's class.
115
+
116
+ Returns
117
+ -------
118
+ Tuple[Type, ...]
119
+ Tuple of base classes
120
+ """
121
+ return self._instance.__class__.__bases__
122
+
123
+ def getSourceCode(self) -> Optional[str]:
124
+ """
125
+ Get the source code of the instance's class.
126
+
127
+ Returns
128
+ -------
129
+ Optional[str]
130
+ The source code if available, None otherwise
131
+ """
132
+ try:
133
+ return inspect.getsource(self._instance.__class__)
134
+ except (TypeError, OSError):
135
+ return None
136
+
137
+ def getFile(self) -> Optional[str]:
138
+ """
139
+ Get the file location where the class is defined.
140
+
141
+ Returns
142
+ -------
143
+ Optional[str]
144
+ The file path if available, None otherwise
145
+ """
146
+ try:
147
+ return inspect.getfile(self._instance.__class__)
148
+ except (TypeError, OSError):
149
+ return None
150
+
151
+ def getAnnotations(self) -> Dict[str, Any]:
152
+ """
153
+ Get type annotations of the class.
154
+
155
+ Returns
156
+ -------
157
+ Dict[str, Any]
158
+ Dictionary of attribute names and their type annotations
159
+ """
160
+ return self._instance.__class__.__annotations__
161
+
162
+ def hasAttribute(self, name: str) -> bool:
163
+ """
164
+ Check if the instance has a specific attribute.
165
+
166
+ Parameters
167
+ ----------
168
+ name : str
169
+ The attribute name to check
170
+
171
+ Returns
172
+ -------
173
+ bool
174
+ True if the attribute exists
175
+ """
176
+ return name in self.getAttributes()
177
+
178
+ def getAttribute(self, name: str) -> Any:
179
+ """
180
+ Get an attribute value by name.
181
+
182
+ Parameters
183
+ ----------
184
+ name : str
185
+ The attribute name
186
+
187
+ Returns
188
+ -------
189
+ Any
190
+ The attribute value
191
+
192
+ Raises
193
+ ------
194
+ AttributeError
195
+ If the attribute doesn't exist
196
+ """
197
+ attrs = self.getAttributes()
198
+ return attrs.get(name, None)
199
+
200
+ def setAttribute(self, name: str, value: Any) -> bool:
201
+ """
202
+ Set an attribute value.
203
+
204
+ Parameters
205
+ ----------
206
+ name : str
207
+ The attribute name
208
+ value : Any
209
+ The value to set
210
+
211
+ Raises
212
+ ------
213
+ ReflectionAttributeError
214
+ If the attribute is read-only
215
+ """
216
+ # Ensure the name is a valid attr name with regular expression
217
+ if not isinstance(name, str) or not name.isidentifier() or keyword.iskeyword(name):
218
+ raise ReflectionAttributeError(f"Invalid method name '{name}'. Must be a valid Python identifier and not a keyword.")
219
+
220
+ # Ensure the value is not callable
221
+ if callable(value):
222
+ raise ReflectionAttributeError(f"Cannot set attribute '{name}' to a callable. Use setMacro instead.")
223
+
224
+ # Handle private attribute name mangling
225
+ if name.startswith("__") and not name.endswith("__"):
226
+ class_name = self.getClassName()
227
+ name = f"_{class_name}{name}"
228
+
229
+ # Check if the attribute already exists
230
+ setattr(self._instance, name, value)
231
+
232
+ # Return True
233
+ return True
234
+
235
+ def removeAttribute(self, name: str) -> bool:
236
+ """
237
+ Remove an attribute from the instance.
238
+
239
+ Parameters
240
+ ----------
241
+ name : str
242
+ The attribute name to remove
243
+
244
+ Raises
245
+ ------
246
+ ReflectionAttributeError
247
+ If the attribute doesn't exist or is read-only
248
+ """
249
+ if self.getAttribute(name) is None:
250
+ raise ReflectionAttributeError(f"'{self.getClassName()}' object has no attribute '{name}'.")
251
+ if name.startswith("__") and not name.endswith("__"):
252
+ class_name = self.getClassName()
253
+ name = f"_{class_name}{name}"
254
+ delattr(self._instance, name)
255
+ return True
90
256
 
91
257
  def getAttributes(self) -> Dict[str, Any]:
92
258
  """
@@ -188,6 +354,208 @@ class ReflectionInstance:
188
354
 
189
355
  return dunder
190
356
 
357
+ def getMagicAttributes(self) -> Dict[str, Any]:
358
+ """
359
+ Get all magic attributes of the instance.
360
+
361
+ Returns
362
+ -------
363
+ Dict[str, Any]
364
+ Dictionary of magic attribute names and their values
365
+ """
366
+ return self.getDunderAttributes()
367
+
368
+ def hasMethod(self, name: str) -> bool:
369
+ """
370
+ Check if the instance has a specific method.
371
+
372
+ Parameters
373
+ ----------
374
+ name : str
375
+ The method name to check
376
+
377
+ Returns
378
+ -------
379
+ bool
380
+ True if the method exists, False otherwise
381
+ """
382
+ # Handle private method name mangling
383
+ if name.startswith("__") and not name.endswith("__"):
384
+ class_name = self.getClassName()
385
+ name = f"_{class_name}{name}"
386
+
387
+ # Check if the method is callable
388
+ if hasattr(self._instance, name):
389
+ return callable(getattr(self._instance, name, None))
390
+
391
+ # Check if the method is a class method or static method
392
+ cls = self._instance.__class__
393
+ if hasattr(cls, name):
394
+ attr = inspect.getattr_static(cls, name)
395
+ return isinstance(attr, (classmethod, staticmethod)) and callable(attr.__func__)
396
+
397
+ # If not found, return False
398
+ return False
399
+
400
+ def callMethod(self, name: str, *args: Any, **kwargs: Any) -> Any:
401
+ """
402
+ Call a method on the instance.
403
+
404
+ Parameters
405
+ ----------
406
+ name : str
407
+ Name of the method to call
408
+ *args : Any
409
+ Positional arguments for the method
410
+ **kwargs : Any
411
+ Keyword arguments for the method
412
+
413
+ Returns
414
+ -------
415
+ Any
416
+ The result of the method call
417
+
418
+ Raises
419
+ ------
420
+ AttributeError
421
+ If the method does not exist on the instance
422
+ TypeError
423
+ If the method is not callable
424
+ """
425
+
426
+ # Hanlde private method name mangling
427
+ if name.startswith("__") and not name.endswith("__"):
428
+ class_name = self.getClassName()
429
+ name = f"_{class_name}{name}"
430
+
431
+ # Try to get the method from the instance
432
+ method = getattr(self._instance, name, None)
433
+
434
+ # If not found, try to get it from the class
435
+ if method is None:
436
+ cls = self._instance.__class__
437
+ method = getattr(cls, name, None)
438
+
439
+ # If still not found, raise an error
440
+ if method is None:
441
+ raise ReflectionAttributeError(f"Method '{name}' does not exist on '{self.getClassName()}'.")
442
+
443
+ # Check if the method is callable
444
+ if not callable(method):
445
+ raise ReflectionTypeError(f"'{name}' is not callable on '{self.getClassName()}'.")
446
+
447
+ # Check if method is coroutine function
448
+ if inspect.iscoroutinefunction(method):
449
+ return Coroutine(method(*args, **kwargs)).run()
450
+
451
+ # Call the method with provided arguments
452
+ return method(*args, **kwargs)
453
+
454
+ def setMethod(self, name: str, value: Callable) -> bool:
455
+ """
456
+ Set a callable attribute value.
457
+
458
+ Parameters
459
+ ----------
460
+ name : str
461
+ The attribute name
462
+ value : Callable
463
+ The callable to set
464
+
465
+ Raises
466
+ ------
467
+ ReflectionAttributeError
468
+ If the attribute is not callable or already exists as a method
469
+ """
470
+ # Ensure the name is a valid method name with regular expression
471
+ if not isinstance(name, str) or not name.isidentifier() or keyword.iskeyword(name):
472
+ raise ReflectionAttributeError(f"Invalid method name '{name}'. Must be a valid Python identifier and not a keyword.")
473
+
474
+ # Ensure the value is callable
475
+ if not callable(value):
476
+ raise ReflectionAttributeError(f"Cannot set attribute '{name}' to a non-callable value.")
477
+
478
+ # Handle private method name mangling
479
+ if name.startswith("__") and not name.endswith("__"):
480
+ class_name = self.getClassName()
481
+ name = f"_{class_name}{name}"
482
+
483
+ # Check if the method already exists
484
+ if hasattr(self._instance, name):
485
+ raise ReflectionAttributeError(f"Attribute '{name}' already exists on '{self.getClassName()}'.")
486
+
487
+ # Set the method on the instance
488
+ setattr(self._instance, name, value)
489
+
490
+ # Return True
491
+ return True
492
+
493
+ def removeMethod(self, name: str) -> None:
494
+ """
495
+ Remove a method from the instance.
496
+
497
+ Parameters
498
+ ----------
499
+ name : str
500
+ The method name to remove
501
+
502
+ Raises
503
+ ------
504
+ ReflectionAttributeError
505
+ If the method does not exist or is not callable
506
+ """
507
+ if not self.hasMethod(name):
508
+ raise ReflectionAttributeError(f"Method '{name}' does not exist on '{self.getClassName()}'.")
509
+ delattr(self._instance, name)
510
+
511
+ def getMethodSignature(self, name: str) -> inspect.Signature:
512
+ """
513
+ Get the signature of a method.
514
+
515
+ Parameters
516
+ ----------
517
+ name : str
518
+ Name of the method
519
+
520
+ Returns
521
+ -------
522
+ inspect.Signature
523
+ The method signature
524
+ """
525
+
526
+ # Handle private method name mangling
527
+ if name.startswith("__") and not name.endswith("__"):
528
+ name = f"_{self.getClassName()}{name}"
529
+
530
+ # Check if the method exists and is callable
531
+ method = getattr(self._instance, name)
532
+ if callable(method):
533
+ return inspect.signature(method)
534
+
535
+ # If the method is not callable, raise an error
536
+ raise ReflectionAttributeError(f"Method '{name}' is not callable on '{self.getClassName()}'.")
537
+
538
+ def getMethods(self) -> List[str]:
539
+ """
540
+ Get all method names of the instance.
541
+
542
+ Returns
543
+ -------
544
+ List[str]
545
+ List of method names
546
+ """
547
+ return [
548
+ *self.getPublicMethods(),
549
+ *self.getProtectedMethods(),
550
+ *self.getPrivateMethods(),
551
+ *self.getPublicClassMethods(),
552
+ *self.getProtectedClassMethods(),
553
+ *self.getPrivateClassMethods(),
554
+ *self.getPublicStaticMethods(),
555
+ *self.getProtectedStaticMethods(),
556
+ *self.getPrivateStaticMethods(),
557
+ ]
558
+
191
559
  def getPublicMethods(self) -> List[str]:
192
560
  """
193
561
  Get all public method names of the instance.
@@ -436,45 +804,78 @@ class ReflectionInstance:
436
804
  # Return the list of public asynchronous class method names
437
805
  return public_class_async_methods
438
806
 
807
+ def getProtectedClassMethods(self) -> List[str]:
808
+ """
809
+ Get all protected class method names of the instance.
439
810
 
811
+ Returns
812
+ -------
813
+ List[str]
814
+ List of protected class method names
815
+ """
816
+ cls = self._instance.__class__
817
+ class_methods = []
440
818
 
819
+ # Iterate over all attributes of the class
820
+ for name in dir(cls):
441
821
 
822
+ # Get the attribute using getattr_static to avoid triggering property getters
823
+ attr = inspect.getattr_static(cls, name)
442
824
 
825
+ # Check if the attribute is a class method
826
+ if isinstance(attr, classmethod):
443
827
 
828
+ # Check is a protected class method
829
+ if name.startswith(f"_") and not name.startswith("__") and not name.startswith(f"_{self.getClassName()}"):
830
+ class_methods.append(name)
444
831
 
832
+ # Return the list of public class method
833
+ return class_methods
445
834
 
835
+ def getProtectedClassSyncMethods(self) -> List[str]:
836
+ """
837
+ Get all protected synchronous class method names of the instance.
446
838
 
839
+ Returns
840
+ -------
841
+ List[str]
842
+ List of protected synchronous class method names
843
+ """
844
+ class_name = self.getClassName()
845
+ cls = self._instance.__class__
846
+ protected_class_sync_methods = []
447
847
 
848
+ # Iterate over all attributes of the class
849
+ for name in dir(cls):
448
850
 
851
+ # Get the attribute using getattr_static to avoid triggering property getters
852
+ attr = inspect.getattr_static(cls, name)
449
853
 
854
+ # Check if the attribute is a class method
855
+ if isinstance(attr, classmethod):
450
856
 
857
+ # Get the underlying function
858
+ func = attr.__func__
451
859
 
860
+ # Check if it's NOT a coroutine function (i.e., synchronous)
861
+ if not inspect.iscoroutinefunction(func) and name.startswith(f"_") and not name.startswith(f"_{class_name}"):
862
+ protected_class_sync_methods.append(str(name).replace(f"_{class_name}", ""))
452
863
 
864
+ # Return the list of protected class method names
865
+ return protected_class_sync_methods
453
866
 
454
-
455
-
456
-
457
-
458
-
459
-
460
-
461
-
462
-
463
-
464
-
465
-
466
- def getProtectedClassMethods(self) -> List[str]:
867
+ def getProtectedClassAsyncMethods(self) -> List[str]:
467
868
  """
468
- Get all protected class method names of the instance.
869
+ Get all protected asynchronous class method names of the instance.
469
870
 
470
871
  Returns
471
872
  -------
472
873
  List[str]
473
- List of protected class method names
874
+ List of protected asynchronous class method names
474
875
  """
475
876
  class_name = self.getClassName()
476
877
  cls = self._instance.__class__
477
- protected_class_methods = []
878
+ protected_class_async_methods = []
478
879
 
479
880
  # Iterate over all attributes of the class
480
881
  for name in dir(cls):
@@ -488,12 +889,12 @@ class ReflectionInstance:
488
889
  # Get the underlying function
489
890
  func = attr.__func__
490
891
 
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}", ""))
892
+ # Check if it's a coroutine function (i.e., asynchronous)
893
+ if inspect.iscoroutinefunction(func) and name.startswith(f"_") and not name.startswith(f"_{class_name}"):
894
+ protected_class_async_methods.append(str(name).replace(f"_{class_name}", ""))
494
895
 
495
- # Return the list of protected class method names
496
- return protected_class_methods
896
+ # Return the list of protected asynchronous class method names
897
+ return protected_class_async_methods
497
898
 
498
899
  def getPrivateClassMethods(self) -> List[str]:
499
900
  """
@@ -520,41 +921,25 @@ class ReflectionInstance:
520
921
  # Get the underlying function
521
922
  func = attr.__func__
522
923
 
523
- # Check if it's NOT a coroutine function (i.e., synchronous)
524
- if not inspect.iscoroutinefunction(func) and name.startswith(f"_{class_name}"):
924
+ # Check if a private class method
925
+ if name.startswith(f"_{class_name}"):
525
926
  private_class_methods.append(str(name).replace(f"_{class_name}", ""))
526
927
 
527
928
  # Return the list of protected class method names
528
929
  return private_class_methods
529
930
 
530
-
531
-
532
-
533
-
534
-
535
-
536
-
537
-
538
-
539
-
540
-
541
-
542
-
543
-
544
-
545
-
546
- def getClassSyncMethods(self) -> List[str]:
931
+ def getPrivateClassSyncMethods(self) -> List[str]:
547
932
  """
548
- Get all synchronous class method names of the instance.
933
+ Get all private synchronous class method names of the instance.
549
934
 
550
935
  Returns
551
936
  -------
552
937
  List[str]
553
- List of synchronous class method names
938
+ List of private synchronous class method names
554
939
  """
555
940
  class_name = self.getClassName()
556
941
  cls = self._instance.__class__
557
- class_sync_methods = []
942
+ private_class_sync_methods = []
558
943
 
559
944
  # Iterate over all attributes of the class
560
945
  for name in dir(cls):
@@ -569,24 +954,24 @@ class ReflectionInstance:
569
954
  func = attr.__func__
570
955
 
571
956
  # 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}", ""))
957
+ if not inspect.iscoroutinefunction(func) and name.startswith(f"_{class_name}"):
958
+ private_class_sync_methods.append(str(name).replace(f"_{class_name}", ""))
574
959
 
575
- # Return the list of synchronous class method names
576
- return class_sync_methods
960
+ # Return the list of private synchronous class method names
961
+ return private_class_sync_methods
577
962
 
578
- def getClassAsyncMethods(self) -> List[str]:
963
+ def getPrivateClassAsyncMethods(self) -> List[str]:
579
964
  """
580
- Get all asynchronous class method names of the instance.
965
+ Get all private asynchronous class method names of the instance.
581
966
 
582
967
  Returns
583
968
  -------
584
969
  List[str]
585
- List of asynchronous class method names
970
+ List of private asynchronous class method names
586
971
  """
587
972
  class_name = self.getClassName()
588
973
  cls = self._instance.__class__
589
- class_async_methods = []
974
+ private_class_async_methods = []
590
975
 
591
976
  # Iterate over all attributes of the class
592
977
  for name in dir(cls):
@@ -601,104 +986,219 @@ class ReflectionInstance:
601
986
  func = attr.__func__
602
987
 
603
988
  # 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}", ""))
989
+ if inspect.iscoroutinefunction(func) and name.startswith(f"_{class_name}"):
990
+ private_class_async_methods.append(str(name).replace(f"_{class_name}", ""))
991
+
992
+ # Return the list of private asynchronous class method names
993
+ return private_class_async_methods
606
994
 
607
- # Return the list of asynchronous class method names
608
- return class_async_methods
995
+ def getPublicStaticMethods(self) -> List[str]:
996
+ """
997
+ Get public static method names of the instance.
609
998
 
999
+ Returns
1000
+ -------
1001
+ List[str]
1002
+ List of static method names
1003
+ """
1004
+ cls = self._instance.__class__
1005
+ static_methods = []
1006
+ for name in dir(cls):
1007
+ attr = inspect.getattr_static(cls, name)
1008
+ if isinstance(attr, staticmethod) and not name.startswith(f"_"):
1009
+ static_methods.append(name)
1010
+ return static_methods
610
1011
 
1012
+ def getPublicStaticSyncMethods(self) -> List[str]:
1013
+ """
1014
+ Get all public synchronous static method names of the instance.
611
1015
 
1016
+ Returns
1017
+ -------
1018
+ List[str]
1019
+ List of public synchronous static method names
1020
+ """
1021
+ class_name = self.getClassName()
1022
+ cls = self._instance.__class__
1023
+ public_static_sync_methods = []
612
1024
 
1025
+ # Iterate over all attributes of the class
1026
+ for name in dir(cls):
613
1027
 
1028
+ # Get the attribute using getattr_static to avoid triggering property getters
1029
+ attr = inspect.getattr_static(cls, name)
614
1030
 
1031
+ # Check if the attribute is a static method
1032
+ if isinstance(attr, staticmethod):
615
1033
 
1034
+ # Get the underlying function
1035
+ func = attr.__func__
616
1036
 
1037
+ # Check if it's NOT a coroutine function (i.e., synchronous)
1038
+ if not inspect.iscoroutinefunction(func) and not name.startswith(f"_"):
1039
+ public_static_sync_methods.append(str(name).replace(f"_{class_name}", ""))
617
1040
 
1041
+ # Return the list of public synchronous static method names
1042
+ return public_static_sync_methods
618
1043
 
1044
+ def getPublicStaticAsyncMethods(self) -> List[str]:
1045
+ """
1046
+ Get all public asynchronous static method names of the instance.
619
1047
 
1048
+ Returns
1049
+ -------
1050
+ List[str]
1051
+ List of public asynchronous static method names
1052
+ """
1053
+ class_name = self.getClassName()
1054
+ cls = self._instance.__class__
1055
+ public_static_async_methods = []
620
1056
 
1057
+ # Iterate over all attributes of the class
1058
+ for name in dir(cls):
621
1059
 
1060
+ # Get the attribute using getattr_static to avoid triggering property getters
1061
+ attr = inspect.getattr_static(cls, name)
622
1062
 
1063
+ # Check if the attribute is a static method
1064
+ if isinstance(attr, staticmethod):
623
1065
 
1066
+ # Get the underlying function
1067
+ func = attr.__func__
624
1068
 
1069
+ # Check if it's a coroutine function (i.e., asynchronous)
1070
+ if inspect.iscoroutinefunction(func) and not name.startswith(f"_"):
1071
+ public_static_async_methods.append(str(name).replace(f"_{class_name}", ""))
625
1072
 
1073
+ # Return the list of public asynchronous static method names
1074
+ return public_static_async_methods
626
1075
 
1076
+ def getProtectedStaticMethods(self) -> List[str]:
1077
+ """
1078
+ Get all protected static method names of the instance.
627
1079
 
1080
+ Returns
1081
+ -------
1082
+ List[str]
1083
+ List of protected static method names
1084
+ """
1085
+ cls = self._instance.__class__
1086
+ protected_static_methods = []
628
1087
 
1088
+ # Iterate over all attributes of the class
1089
+ for name in dir(cls):
629
1090
 
1091
+ # Get the attribute using getattr_static to avoid triggering property getters
1092
+ attr = inspect.getattr_static(cls, name)
630
1093
 
1094
+ # Check if the attribute is a static method
1095
+ if isinstance(attr, staticmethod) and name.startswith(f"_") and not name.startswith("__") and not name.startswith(f"_{self.getClassName()}"):
1096
+ protected_static_methods.append(name)
631
1097
 
1098
+ return protected_static_methods
632
1099
 
1100
+ def getProtectedStaticSyncMethods(self) -> List[str]:
1101
+ """
1102
+ Get all protected synchronous static method names of the instance.
633
1103
 
1104
+ Returns
1105
+ -------
1106
+ List[str]
1107
+ List of protected synchronous static method names
1108
+ """
1109
+ class_name = self.getClassName()
1110
+ cls = self._instance.__class__
1111
+ protected_static_sync_methods = []
634
1112
 
1113
+ # Iterate over all attributes of the class
1114
+ for name in dir(cls):
635
1115
 
1116
+ # Get the attribute using getattr_static to avoid triggering property getters
1117
+ attr = inspect.getattr_static(cls, name)
636
1118
 
1119
+ # Check if the attribute is a static method
1120
+ if isinstance(attr, staticmethod):
637
1121
 
1122
+ # Get the underlying function
1123
+ func = attr.__func__
638
1124
 
1125
+ # Check if it's NOT a coroutine function (i.e., synchronous)
1126
+ if not inspect.iscoroutinefunction(func) and name.startswith(f"_") and not name.startswith(f"_{class_name}"):
1127
+ protected_static_sync_methods.append(str(name).replace(f"_{class_name}", ""))
639
1128
 
1129
+ return protected_static_sync_methods
640
1130
 
641
- def getDunderMethods(self) -> List[str]:
1131
+ def getProtectedStaticAsyncMethods(self) -> List[str]:
642
1132
  """
643
- Get all dunder (double underscore) method names of the instance.
1133
+ Get all protected asynchronous static method names of the instance.
644
1134
 
645
1135
  Returns
646
1136
  -------
647
1137
  List[str]
648
- List of dunder method names
1138
+ List of protected asynchronous static method names
649
1139
  """
650
- dunder_methods = []
1140
+ class_name = self.getClassName()
1141
+ cls = self._instance.__class__
1142
+ protected_static_async_methods = []
651
1143
 
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)
1144
+ # Iterate over all attributes of the class
1145
+ for name in dir(cls):
656
1146
 
657
- return dunder_methods
1147
+ # Get the attribute using getattr_static to avoid triggering property getters
1148
+ attr = inspect.getattr_static(cls, name)
658
1149
 
659
- def getMagicMethods(self) -> List[str]:
660
- """
661
- Get all magic method names of the instance.
1150
+ # Check if the attribute is a static method
1151
+ if isinstance(attr, staticmethod):
662
1152
 
663
- Returns
664
- -------
665
- List[str]
666
- List of magic method names
667
- """
668
- return self.getDunderMethods()
1153
+ # Get the underlying function
1154
+ func = attr.__func__
1155
+
1156
+ # Check if it's a coroutine function (i.e., asynchronous)
1157
+ if inspect.iscoroutinefunction(func) and name.startswith(f"_") and not name.startswith(f"_{class_name}"):
1158
+ protected_static_async_methods.append(str(name).replace(f"_{class_name}", ""))
669
1159
 
670
-
1160
+ return protected_static_async_methods
671
1161
 
672
- def getStaticMethods(self) -> List[str]:
1162
+ def getPrivateStaticMethods(self) -> List[str]:
673
1163
  """
674
- Get all static method names of the instance.
1164
+ Get all private static method names of the instance.
675
1165
 
676
1166
  Returns
677
1167
  -------
678
1168
  List[str]
679
- List of static method names
1169
+ List of private static method names
680
1170
  """
681
1171
  class_name = self.getClassName()
682
1172
  cls = self._instance.__class__
683
- static_methods = []
1173
+ private_static_methods = []
1174
+
1175
+ # Iterate over all attributes of the class
684
1176
  for name in dir(cls):
1177
+
1178
+ # Get the attribute using getattr_static to avoid triggering property getters
685
1179
  attr = inspect.getattr_static(cls, name)
1180
+
1181
+ # Check if the attribute is a static method
686
1182
  if isinstance(attr, staticmethod):
687
- static_methods.append(str(name).replace(f"_{class_name}", ""))
688
- return static_methods
689
1183
 
690
- def getStaticSyncMethods(self) -> List[str]:
1184
+ # Check if a private static method
1185
+ if name.startswith(f"_{class_name}"):
1186
+ private_static_methods.append(str(name).replace(f"_{class_name}", ""))
1187
+
1188
+ return private_static_methods
1189
+
1190
+ def getPrivateStaticSyncMethods(self) -> List[str]:
691
1191
  """
692
- Get all synchronous static method names of the instance.
1192
+ Get all private synchronous static method names of the instance.
693
1193
 
694
1194
  Returns
695
1195
  -------
696
1196
  List[str]
697
- List of synchronous static method names
1197
+ List of private synchronous static method names
698
1198
  """
699
1199
  class_name = self.getClassName()
700
1200
  cls = self._instance.__class__
701
- static_sync_methods = []
1201
+ private_static_sync_methods = []
702
1202
 
703
1203
  # Iterate over all attributes of the class
704
1204
  for name in dir(cls):
@@ -713,24 +1213,23 @@ class ReflectionInstance:
713
1213
  func = attr.__func__
714
1214
 
715
1215
  # 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}", ""))
1216
+ if not inspect.iscoroutinefunction(func) and name.startswith(f"_{class_name}"):
1217
+ private_static_sync_methods.append(str(name).replace(f"_{class_name}", ""))
718
1218
 
719
- # Return the list of synchronous static method names
720
- return static_sync_methods
1219
+ return private_static_sync_methods
721
1220
 
722
- def getStaticAsyncMethods(self) -> List[str]:
1221
+ def getPrivateStaticAsyncMethods(self) -> List[str]:
723
1222
  """
724
- Get all asynchronous static method names of the instance.
1223
+ Get all private asynchronous static method names of the instance.
725
1224
 
726
1225
  Returns
727
1226
  -------
728
1227
  List[str]
729
- List of asynchronous static method names
1228
+ List of private asynchronous static method names
730
1229
  """
731
1230
  class_name = self.getClassName()
732
1231
  cls = self._instance.__class__
733
- static_async_methods = []
1232
+ private_static_async_methods = []
734
1233
 
735
1234
  # Iterate over all attributes of the class
736
1235
  for name in dir(cls):
@@ -745,556 +1244,200 @@ class ReflectionInstance:
745
1244
  func = attr.__func__
746
1245
 
747
1246
  # 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}", ""))
1247
+ if inspect.iscoroutinefunction(func) and name.startswith(f"_{class_name}"):
1248
+ private_static_async_methods.append(str(name).replace(f"_{class_name}", ""))
750
1249
 
751
- # Return the list of asynchronous static method names
752
- return static_async_methods
1250
+ return private_static_async_methods
753
1251
 
754
- # def getMethodDocstring(self, method_name: str) -> Optional[str]:
755
- # """
756
- # Get the docstring of a method.
1252
+ def getDunderMethods(self) -> List[str]:
1253
+ """
1254
+ Get all dunder (double underscore) method names of the instance.
757
1255
 
758
- # Parameters
759
- # ----------
760
- # method_name : str
761
- # Name of the method
1256
+ Returns
1257
+ -------
1258
+ List[str]
1259
+ List of dunder method names
1260
+ """
1261
+ dunder_methods = []
762
1262
 
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()}")
1263
+ # Collect dunder methods (starting and ending with double underscores)
1264
+ for name in dir(self._instance):
1265
+ if name.startswith("__") and name.endswith("__"):
1266
+ dunder_methods.append(name)
773
1267
 
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
1268
+ return dunder_methods
781
1269
 
782
- # # If it's a staticmethod or classmethod, get the underlying function
783
- # if isinstance(method, (staticmethod, classmethod)):
784
- # method = method.__func__
1270
+ def getMagicMethods(self) -> List[str]:
1271
+ """
1272
+ Get all magic method names of the instance.
785
1273
 
786
- # # Return the docstring if available
787
- # return getattr(method, "__doc__", None) or ""
1274
+ Returns
1275
+ -------
1276
+ List[str]
1277
+ List of magic method names
1278
+ """
1279
+ return self.getDunderMethods()
788
1280
 
789
- # def getMethodSignature(self, method_name: str) -> inspect.Signature:
790
- # """
791
- # Get the signature of a method.
1281
+ def getProperties(self) -> Dict:
1282
+ """
1283
+ Get all properties of the instance.
792
1284
 
793
- # Parameters
794
- # ----------
795
- # method_name : str
796
- # Name of the method
1285
+ Returns
1286
+ -------
1287
+ List[str]
1288
+ List of property names
1289
+ """
797
1290
 
798
- # Returns
799
- # -------
800
- # inspect.Signature
801
- # The method signature
1291
+ properties = {}
1292
+ for name, prop in self._instance.__class__.__dict__.items():
1293
+ if isinstance(prop, property):
1294
+ name = name.replace(f"_{self.getClassName()}", "")
1295
+ properties[name] = getattr(self._instance, name, None)
1296
+ return properties
802
1297
 
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}"
1298
+ def getPublicProperties(self) -> Dict:
1299
+ """
1300
+ Get all public properties of the instance.
810
1301
 
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()}'.")
1302
+ Returns
1303
+ -------
1304
+ Dict[str]
1305
+ Dictionary of public property names and their values
1306
+ """
1307
+ properties = {}
1308
+ for name, prop in self._instance.__class__.__dict__.items():
1309
+ if isinstance(prop, property):
1310
+ if not name.startswith(f"_"):
1311
+ properties[name] = getattr(self._instance, name, None)
1312
+ return properties
814
1313
 
815
- # return inspect.signature(method)
1314
+ def getProtectedProperties(self) -> Dict:
1315
+ """
1316
+ Get all protected properties of the instance.
816
1317
 
1318
+ Returns
1319
+ -------
1320
+ Dict[str]
1321
+ Dictionary of protected property names and their values
1322
+ """
1323
+ properties = {}
1324
+ for name, prop in self._instance.__class__.__dict__.items():
1325
+ if isinstance(prop, property):
1326
+ if name.startswith(f"_") and not name.startswith("__") and not name.startswith(f"_{self.getClassName()}"):
1327
+ properties[name] = getattr(self._instance, name, None)
1328
+ return properties
817
1329
 
1330
+ def getPrivateProperties(self) -> Dict:
1331
+ """
1332
+ Get all private properties of the instance.
818
1333
 
1334
+ Returns
1335
+ -------
1336
+ Dict[str]
1337
+ Dictionary of private property names and their values
1338
+ """
1339
+ properties = {}
1340
+ for name, prop in self._instance.__class__.__dict__.items():
1341
+ if isinstance(prop, property):
1342
+ if name.startswith(f"_{self.getClassName()}") and not name.startswith("__"):
1343
+ properties[name.replace(f"_{self.getClassName()}", "")] = getattr(self._instance, name, None)
1344
+ return properties
819
1345
 
1346
+ def getPropierty(self, name: str) -> Any:
1347
+ """
1348
+ Get a specific property of the instance.
820
1349
 
1350
+ Parameters
1351
+ ----------
1352
+ name : str
1353
+ The name of the property to retrieve
821
1354
 
1355
+ Returns
1356
+ -------
1357
+ ClassProperty
1358
+ The value of the specified property
822
1359
 
1360
+ Raises
1361
+ ------
1362
+ ReflectionAttributeError
1363
+ If the property does not exist or is not accessible
1364
+ """
1365
+ # Check if the property name is valid
1366
+ if name in self.getProperties():
823
1367
 
1368
+ # Handle private property name mangling
1369
+ if name.startswith("__") and not name.endswith("__"):
1370
+ class_name = self.getClassName()
1371
+ name = f"_{class_name}{name}"
824
1372
 
1373
+ # Return the property value from the instance
1374
+ return getattr(self._instance, name, None)
825
1375
 
1376
+ # If the property does not exist, raise an error
1377
+ raise ReflectionAttributeError(f"Property '{name}' does not exist on '{self.getClassName()}'.")
826
1378
 
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:
1379
+ def getPropertySignature(self, name: str) -> inspect.Signature:
954
1380
  """
955
1381
  Get the signature of a property.
956
1382
 
957
1383
  Parameters
958
1384
  ----------
959
- property_name : str
1385
+ name : str
960
1386
  Name of the property
961
1387
 
962
1388
  Returns
963
1389
  -------
964
1390
  inspect.Signature
965
1391
  The property signature
966
-
967
- Raises
968
- ------
969
- AttributeError
970
- If the property doesn't exist or is not a property
971
1392
  """
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
1393
+ # Handle private property name mangling
1394
+ original_name = name
1395
+ if name.startswith("__") and not name.endswith("__"):
1396
+ class_name = self.getClassName()
1397
+ name = f"_{class_name}{name}"
1398
+
1399
+ # Check if the property exists
1400
+ prop = getattr(self._instance.__class__, name, None)
1401
+ if isinstance(prop, property):
1402
+ return inspect.signature(prop.fget)
1403
+
1404
+ # If the property does not exist, raise an error
1405
+ raise ReflectionAttributeError(f"Property '{original_name}' does not exist on '{self.getClassName()}'.")
976
1406
 
977
- def getPropertyDoc(self, property_name: str) -> str:
1407
+ def getPropiertyDocstring(self, name: str) -> str:
978
1408
  """
979
1409
  Get the docstring of a property.
980
1410
 
981
1411
  Parameters
982
1412
  ----------
983
- property_name : str
1413
+ name : str
984
1414
  Name of the property
985
1415
 
986
1416
  Returns
987
1417
  -------
988
1418
  str
989
1419
  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
1420
  """
1421
+ # Handle private property name mangling
1422
+ original_name = name
1423
+ if name.startswith("__") and not name.endswith("__"):
1424
+ class_name = self.getClassName()
1425
+ name = f"_{class_name}{name}"
1066
1426
 
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()
1427
+ # Check if the property exists
1428
+ prop = getattr(self._instance.__class__, name, None)
1429
+ if isinstance(prop, property):
1430
+ return prop.fget.__doc__ or ""
1079
1431
 
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)
1432
+ # If the property does not exist, raise an error
1433
+ raise ReflectionAttributeError(f"Property '{original_name}' does not exist on '{self.getClassName()}'.")
1293
1434
 
1294
1435
  def getConstructorDependencies(self) -> ClassDependency:
1295
1436
  """
1296
1437
  Get the resolved and unresolved dependencies from the constructor of the instance's class.
1297
1438
 
1439
+
1440
+
1298
1441
  Returns
1299
1442
  -------
1300
1443
  ClassDependency
@@ -1320,4 +1463,15 @@ class ReflectionInstance:
1320
1463
  - resolved: Dictionary of resolved dependencies with their names and values.
1321
1464
  - unresolved: List of unresolved dependencies (parameter names without default values or annotations).
1322
1465
  """
1323
- return ReflectDependencies(self._instance).getMethodDependencies(method_name)
1466
+
1467
+ # Ensure the method name is a valid identifier
1468
+ if not self.hasMethod(method_name):
1469
+ raise ReflectionAttributeError(f"Method '{method_name}' does not exist on '{self.getClassName()}'.")
1470
+
1471
+ # Handle private method name mangling
1472
+ if method_name.startswith("__") and not method_name.endswith("__"):
1473
+ class_name = self.getClassName()
1474
+ method_name = f"_{class_name}{method_name}"
1475
+
1476
+ # Use ReflectDependencies to get method dependencies
1477
+ return ReflectDependencies(self._instance).getMethodDependencies(method_name)