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