orionis 0.206.0__py3-none-any.whl → 0.208.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/framework.py +1 -1
- orionis/luminate/support/inspection/reflexion_abstract.py +110 -28
- orionis/luminate/support/inspection/reflexion_instance.py +31 -1
- orionis/luminate/support/inspection/reflexion_instance_with_abstract.py +172 -251
- {orionis-0.206.0.dist-info → orionis-0.208.0.dist-info}/METADATA +1 -1
- {orionis-0.206.0.dist-info → orionis-0.208.0.dist-info}/RECORD +16 -12
- tests/support/inspection/fakes/fake_reflection_abstract.py +218 -0
- tests/support/inspection/fakes/fake_reflection_instance_with_abstract.py +45 -0
- tests/support/inspection/test_reflection_abstract.py +238 -0
- tests/support/inspection/test_reflection_instance.py +31 -32
- tests/support/inspection/test_reflection_instance_with_abstract.py +80 -0
- {orionis-0.206.0.dist-info → orionis-0.208.0.dist-info}/LICENCE +0 -0
- {orionis-0.206.0.dist-info → orionis-0.208.0.dist-info}/WHEEL +0 -0
- {orionis-0.206.0.dist-info → orionis-0.208.0.dist-info}/entry_points.txt +0 -0
- {orionis-0.206.0.dist-info → orionis-0.208.0.dist-info}/top_level.txt +0 -0
- /tests/support/inspection/fakes/{fake_reflection.py → fake_reflection_instance.py} +0 -0
orionis/framework.py
CHANGED
@@ -1,7 +1,8 @@
|
|
1
|
-
from typing import Any, Type, Dict, List, Tuple, Callable, Optional, TypeVar, Set
|
2
|
-
import inspect
|
3
1
|
import abc
|
4
|
-
|
2
|
+
import ast
|
3
|
+
import inspect
|
4
|
+
import types
|
5
|
+
from typing import Any, Callable, Dict, List, Optional, Set, Tuple, Type, TypeVar
|
5
6
|
|
6
7
|
ABC = TypeVar('ABC', bound=abc.ABC)
|
7
8
|
|
@@ -51,7 +52,26 @@ class ReflexionAbstract:
|
|
51
52
|
Set[str]
|
52
53
|
Set of abstract method names
|
53
54
|
"""
|
54
|
-
|
55
|
+
methods = []
|
56
|
+
for method in self._abstract.__abstractmethods__:
|
57
|
+
if not isinstance(getattr(self._abstract, method), property):
|
58
|
+
methods.append(method)
|
59
|
+
return set(methods)
|
60
|
+
|
61
|
+
def getAbstractProperties(self) -> Set[str]:
|
62
|
+
"""Get all abstract property names required by the class.
|
63
|
+
|
64
|
+
Returns
|
65
|
+
-------
|
66
|
+
Set[str]
|
67
|
+
Set of abstract property names
|
68
|
+
"""
|
69
|
+
properties = []
|
70
|
+
for name in getattr(self._abstract, '__abstractmethods__', set()):
|
71
|
+
attr = getattr(self._abstract, name, None)
|
72
|
+
if isinstance(attr, property):
|
73
|
+
properties.append(name)
|
74
|
+
return set(properties)
|
55
75
|
|
56
76
|
def getConcreteMethods(self) -> Dict[str, Callable]:
|
57
77
|
"""Get all concrete methods implemented in the abstract class.
|
@@ -88,13 +108,32 @@ class ReflexionAbstract:
|
|
88
108
|
Returns
|
89
109
|
-------
|
90
110
|
List[str]
|
91
|
-
List of class method names
|
111
|
+
List of class method names, excluding private/protected methods (starting with '_')
|
112
|
+
|
113
|
+
Notes
|
114
|
+
-----
|
115
|
+
- Uses inspect.getattr_static to avoid method binding
|
116
|
+
- Properly handles both @classmethod decorator and classmethod instances
|
117
|
+
- Filters out private/protected methods (starting with '_')
|
118
|
+
|
119
|
+
Examples
|
120
|
+
--------
|
121
|
+
>>> class MyAbstract(ABC):
|
122
|
+
... @classmethod
|
123
|
+
... def factory(cls): pass
|
124
|
+
... @classmethod
|
125
|
+
... def _protected_factory(cls): pass
|
126
|
+
>>> reflex = ReflexionAbstract(MyAbstract)
|
127
|
+
>>> reflex.getClassMethods()
|
128
|
+
['factory']
|
92
129
|
"""
|
93
130
|
return [
|
94
|
-
name for name
|
95
|
-
|
96
|
-
|
97
|
-
|
131
|
+
name for name in dir(self._abstract)
|
132
|
+
if not name.startswith('_') and
|
133
|
+
isinstance(
|
134
|
+
inspect.getattr_static(self._abstract, name),
|
135
|
+
(classmethod, types.MethodType)
|
136
|
+
)
|
98
137
|
]
|
99
138
|
|
100
139
|
def getProperties(self) -> List[str]:
|
@@ -131,7 +170,31 @@ class ReflexionAbstract:
|
|
131
170
|
If the method doesn't exist
|
132
171
|
"""
|
133
172
|
method = getattr(self._abstract, methodName)
|
134
|
-
|
173
|
+
if callable(method):
|
174
|
+
return inspect.signature(method)
|
175
|
+
|
176
|
+
def getPropertySignature(self, propertyName: str) -> inspect.Signature:
|
177
|
+
"""Get the signature of an abstract property's getter.
|
178
|
+
|
179
|
+
Parameters
|
180
|
+
----------
|
181
|
+
propertyName : str
|
182
|
+
Name of the abstract property
|
183
|
+
|
184
|
+
Returns
|
185
|
+
-------
|
186
|
+
inspect.Signature
|
187
|
+
The getter signature of the abstract property
|
188
|
+
|
189
|
+
Raises
|
190
|
+
------
|
191
|
+
AttributeError
|
192
|
+
If the property doesn't exist or is not an abstract property
|
193
|
+
"""
|
194
|
+
attr = getattr(self._abstract, propertyName, None)
|
195
|
+
if isinstance(attr, property) and attr.fget is not None:
|
196
|
+
return inspect.signature(attr.fget)
|
197
|
+
raise AttributeError(f"{propertyName} is not an abstract property or doesn't have a getter.")
|
135
198
|
|
136
199
|
def getDocstring(self) -> Optional[str]:
|
137
200
|
"""Get the docstring of the abstract class.
|
@@ -153,7 +216,7 @@ class ReflexionAbstract:
|
|
153
216
|
"""
|
154
217
|
return tuple(
|
155
218
|
base for base in self._abstract.__bases__
|
156
|
-
if inspect.isabstract(base)
|
219
|
+
if inspect.isabstract(base) or issubclass(base, abc.ABC) or isinstance(base, abc.ABCMeta)
|
157
220
|
)
|
158
221
|
|
159
222
|
def getInterfaceMethods(self) -> Dict[str, inspect.Signature]:
|
@@ -220,29 +283,48 @@ class ReflexionAbstract:
|
|
220
283
|
"""
|
221
284
|
return self._abstract.__annotations__
|
222
285
|
|
223
|
-
def getDecorators(self, method_name: str) -> List[
|
224
|
-
"""
|
286
|
+
def getDecorators(self, method_name: str) -> List[str]:
|
287
|
+
"""
|
288
|
+
Get decorators applied to a method.
|
225
289
|
|
226
290
|
Parameters
|
227
291
|
----------
|
228
292
|
method_name : str
|
229
|
-
Name of the method
|
230
|
-
|
231
|
-
Returns
|
232
|
-
-------
|
233
|
-
List[Callable]
|
234
|
-
List of decorator functions
|
293
|
+
Name of the method to inspect
|
235
294
|
"""
|
236
|
-
method = getattr(self._abstract, method_name)
|
237
|
-
|
295
|
+
method = getattr(self._abstract, method_name, None)
|
296
|
+
if method is None:
|
297
|
+
return []
|
238
298
|
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
299
|
+
try:
|
300
|
+
source = inspect.getsource(self._abstract)
|
301
|
+
except (OSError, TypeError):
|
302
|
+
return []
|
303
|
+
|
304
|
+
tree = ast.parse(source)
|
305
|
+
|
306
|
+
class DecoratorVisitor(ast.NodeVisitor):
|
307
|
+
def __init__(self):
|
308
|
+
self.decorators = []
|
309
|
+
|
310
|
+
def visit_FunctionDef(self, node):
|
311
|
+
if node.name == method_name:
|
312
|
+
for deco in node.decorator_list:
|
313
|
+
if isinstance(deco, ast.Name):
|
314
|
+
self.decorators.append(deco.id)
|
315
|
+
elif isinstance(deco, ast.Call):
|
316
|
+
# handles decorators with arguments like @deco(arg)
|
317
|
+
if isinstance(deco.func, ast.Name):
|
318
|
+
self.decorators.append(deco.func.id)
|
319
|
+
elif isinstance(deco, ast.Attribute):
|
320
|
+
self.decorators.append(deco.attr)
|
321
|
+
# No need to visit deeper
|
322
|
+
return
|
323
|
+
|
324
|
+
visitor = DecoratorVisitor()
|
325
|
+
visitor.visit(tree)
|
326
|
+
|
327
|
+
return visitor.decorators
|
246
328
|
|
247
329
|
def isProtocol(self) -> bool:
|
248
330
|
"""Check if the abstract class is a Protocol.
|
@@ -198,7 +198,37 @@ class ReflexionInstance:
|
|
198
198
|
'(x, y)'
|
199
199
|
"""
|
200
200
|
method = getattr(self._instance, methodName)
|
201
|
-
|
201
|
+
if callable(method):
|
202
|
+
return inspect.signature(method)
|
203
|
+
|
204
|
+
def getPropertySignature(self, propertyName: str) -> inspect.Signature:
|
205
|
+
"""Get the signature of a property getter.
|
206
|
+
|
207
|
+
Parameters
|
208
|
+
----------
|
209
|
+
propertyName : str
|
210
|
+
Name of the property
|
211
|
+
|
212
|
+
Returns
|
213
|
+
-------
|
214
|
+
inspect.Signature
|
215
|
+
The property's getter method signature
|
216
|
+
|
217
|
+
Raises
|
218
|
+
------
|
219
|
+
AttributeError
|
220
|
+
If the property doesn't exist or is not a property
|
221
|
+
|
222
|
+
Examples
|
223
|
+
--------
|
224
|
+
>>> sig = reflex.getPropertySignature('config')
|
225
|
+
>>> str(sig)
|
226
|
+
'(self)'
|
227
|
+
"""
|
228
|
+
attr = getattr(type(self._instance), propertyName, None)
|
229
|
+
if isinstance(attr, property) and attr.fget is not None:
|
230
|
+
return inspect.signature(attr.fget)
|
231
|
+
raise AttributeError(f"{propertyName} is not a property or doesn't have a getter.")
|
202
232
|
|
203
233
|
def getDocstring(self) -> Optional[str]:
|
204
234
|
"""Get the docstring of the instance's class.
|