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.
- orionis/metadata/framework.py +1 -1
- orionis/services/introspection/instances/contracts/reflection_instance.py +869 -0
- orionis/services/introspection/instances/reflection_instance.py +746 -592
- {orionis-0.297.0.dist-info → orionis-0.299.0.dist-info}/METADATA +1 -1
- {orionis-0.297.0.dist-info → orionis-0.299.0.dist-info}/RECORD +12 -14
- tests/example/test_example.py +1 -1
- tests/support/inspection/fakes/fake_reflect_instance.py +79 -4
- orionis/services/introspection/instances/entities/class_attributes.py +0 -20
- orionis/services/introspection/instances/entities/class_method.py +0 -41
- orionis/services/introspection/instances/entities/class_property.py +0 -24
- /orionis/services/introspection/instances/{entities → contracts}/__init__.py +0 -0
- {orionis-0.297.0.dist-info → orionis-0.299.0.dist-info}/WHEEL +0 -0
- {orionis-0.297.0.dist-info → orionis-0.299.0.dist-info}/licenses/LICENCE +0 -0
- {orionis-0.297.0.dist-info → orionis-0.299.0.dist-info}/top_level.txt +0 -0
- {orionis-0.297.0.dist-info → orionis-0.299.0.dist-info}/zip-safe +0 -0
@@ -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.
|
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.
|
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
|
-
|
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
|
492
|
-
if
|
493
|
-
|
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
|
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
|
524
|
-
if
|
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
|
-
|
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
|
-
|
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
|
960
|
+
# Return the list of private synchronous class method names
|
961
|
+
return private_class_sync_methods
|
577
962
|
|
578
|
-
def
|
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
|
-
|
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
|
-
|
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
|
-
|
608
|
-
|
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
|
1131
|
+
def getProtectedStaticAsyncMethods(self) -> List[str]:
|
642
1132
|
"""
|
643
|
-
Get all
|
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
|
1138
|
+
List of protected asynchronous static method names
|
649
1139
|
"""
|
650
|
-
|
1140
|
+
class_name = self.getClassName()
|
1141
|
+
cls = self._instance.__class__
|
1142
|
+
protected_static_async_methods = []
|
651
1143
|
|
652
|
-
#
|
653
|
-
for name in dir(
|
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
|
-
|
1147
|
+
# Get the attribute using getattr_static to avoid triggering property getters
|
1148
|
+
attr = inspect.getattr_static(cls, name)
|
658
1149
|
|
659
|
-
|
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
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
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
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
720
|
-
return static_sync_methods
|
1219
|
+
return private_static_sync_methods
|
721
1220
|
|
722
|
-
def
|
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
|
-
|
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
|
-
|
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
|
-
|
752
|
-
return static_async_methods
|
1250
|
+
return private_static_async_methods
|
753
1251
|
|
754
|
-
|
755
|
-
|
756
|
-
|
1252
|
+
def getDunderMethods(self) -> List[str]:
|
1253
|
+
"""
|
1254
|
+
Get all dunder (double underscore) method names of the instance.
|
757
1255
|
|
758
|
-
|
759
|
-
|
760
|
-
|
761
|
-
|
1256
|
+
Returns
|
1257
|
+
-------
|
1258
|
+
List[str]
|
1259
|
+
List of dunder method names
|
1260
|
+
"""
|
1261
|
+
dunder_methods = []
|
762
1262
|
|
763
|
-
|
764
|
-
|
765
|
-
|
766
|
-
|
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
|
-
|
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
|
-
|
783
|
-
|
784
|
-
|
1270
|
+
def getMagicMethods(self) -> List[str]:
|
1271
|
+
"""
|
1272
|
+
Get all magic method names of the instance.
|
785
1273
|
|
786
|
-
|
787
|
-
|
1274
|
+
Returns
|
1275
|
+
-------
|
1276
|
+
List[str]
|
1277
|
+
List of magic method names
|
1278
|
+
"""
|
1279
|
+
return self.getDunderMethods()
|
788
1280
|
|
789
|
-
|
790
|
-
|
791
|
-
|
1281
|
+
def getProperties(self) -> Dict:
|
1282
|
+
"""
|
1283
|
+
Get all properties of the instance.
|
792
1284
|
|
793
|
-
|
794
|
-
|
795
|
-
|
796
|
-
|
1285
|
+
Returns
|
1286
|
+
-------
|
1287
|
+
List[str]
|
1288
|
+
List of property names
|
1289
|
+
"""
|
797
1290
|
|
798
|
-
|
799
|
-
|
800
|
-
|
801
|
-
|
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
|
-
|
804
|
-
|
805
|
-
|
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
|
-
|
812
|
-
|
813
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
973
|
-
|
974
|
-
|
975
|
-
|
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
|
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
|
-
|
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
|
1068
|
-
|
1069
|
-
|
1070
|
-
|
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
|
-
|
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
|
-
|
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)
|