orionis 0.207.0__py3-none-any.whl → 0.209.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 CHANGED
@@ -5,7 +5,7 @@
5
5
  NAME = "orionis"
6
6
 
7
7
  # Current version of the framework
8
- VERSION = "0.207.0"
8
+ VERSION = "0.209.0"
9
9
 
10
10
  # Full name of the author or maintainer of the project
11
11
  AUTHOR = "Raul Mauricio Uñate Castro"
@@ -54,9 +54,25 @@ class ReflexionAbstract:
54
54
  """
55
55
  methods = []
56
56
  for method in self._abstract.__abstractmethods__:
57
- methods.append(method)
57
+ if not isinstance(getattr(self._abstract, method), property):
58
+ methods.append(method)
58
59
  return set(methods)
59
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)
75
+
60
76
  def getConcreteMethods(self) -> Dict[str, Callable]:
61
77
  """Get all concrete methods implemented in the abstract class.
62
78
 
@@ -154,7 +170,31 @@ class ReflexionAbstract:
154
170
  If the method doesn't exist
155
171
  """
156
172
  method = getattr(self._abstract, methodName)
157
- return inspect.signature(method)
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.")
158
198
 
159
199
  def getDocstring(self) -> Optional[str]:
160
200
  """Get the docstring of the abstract class.
@@ -198,7 +198,37 @@ class ReflexionInstance:
198
198
  '(x, y)'
199
199
  """
200
200
  method = getattr(self._instance, methodName)
201
- return inspect.signature(method)
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.
@@ -1,309 +1,230 @@
1
- from typing import Any, Type, Dict, List, Tuple, Callable, Optional, Set, TypeVar
2
- import inspect
3
1
  import abc
2
+ import inspect
3
+ from typing import Any, Dict, List, Tuple, Type, TypeVar, Union
4
+ from orionis.luminate.support.inspection.reflexion_abstract import ReflexionAbstract
5
+ from orionis.luminate.support.inspection.reflexion_instance import ReflexionInstance
4
6
 
5
7
  T = TypeVar('T')
6
8
  ABC = TypeVar('ABC', bound=abc.ABC)
7
9
 
8
10
  class ReflexionInstanceWithAbstract:
9
- """A reflection object encapsulating a class instance and its abstract parent.
11
+ """Advanced reflection tool for analyzing concrete implementations against abstract bases.
10
12
 
11
- This class provides methods to inspect both the concrete instance and its
12
- abstract parent class, including their relationships and implementations.
13
+ Combines inspection of both concrete instances and their abstract parent classes,
14
+ providing detailed comparison and compatibility analysis.
13
15
 
14
16
  Parameters
15
17
  ----------
16
18
  instance : Any
17
- The instance being reflected upon
19
+ The concrete instance to inspect
18
20
  abstract : Type[ABC]
19
- The abstract parent class
21
+ The abstract base class/interface being implemented
20
22
 
21
23
  Attributes
22
24
  ----------
23
25
  _instance : Any
24
- The encapsulated instance
26
+ The concrete instance being analyzed
25
27
  _abstract : Type[ABC]
26
- The encapsulated abstract parent class
28
+ The abstract base class/interface
29
+ _concrete_reflexion : ReflexionInstance
30
+ Reflection helper for the concrete instance
31
+ _abstract_reflexion : ReflexionAbstract
32
+ Reflection helper for the abstract class
27
33
  """
28
34
 
29
35
  def __init__(self, instance: Any, abstract: Type[ABC]) -> None:
30
- """Initialize with the instance and abstract parent."""
31
36
  self._instance = instance
32
37
  self._abstract = abstract
38
+ self._concrete_reflexion = ReflexionInstance(instance)
39
+ self._abstract_reflexion = ReflexionAbstract(abstract)
33
40
 
34
- def getClassName(self) -> str:
35
- """Get the name of the instance's class.
36
-
37
- Returns
38
- -------
39
- str
40
- The name of the concrete class
41
- """
42
- return self._instance.__class__.__name__
43
-
44
- def getAbstractClassName(self) -> str:
45
- """Get the name of the abstract parent class.
46
-
47
- Returns
48
- -------
49
- str
50
- The name of the abstract class
51
- """
52
- return self._abstract.__name__
53
-
54
- def getImplementationStatus(self) -> Dict[str, bool]:
55
- """Check which abstract methods are implemented.
56
-
57
- Returns
58
- -------
59
- Dict[str, bool]
60
- Dictionary mapping abstract method names to implementation status
61
- """
62
- abstract_methods = getattr(self._abstract, '__abstractmethods__', set())
63
- return {
64
- method: method in dir(self._instance)
65
- for method in abstract_methods
66
- }
41
+ @property
42
+ def concrete(self) -> ReflexionInstance:
43
+ """Access the concrete instance reflection helper."""
44
+ return self._concrete_reflexion
67
45
 
68
- def getMissingImplementations(self) -> Set[str]:
69
- """Get abstract methods not implemented by the concrete class.
46
+ @property
47
+ def abstract(self) -> ReflexionAbstract:
48
+ """Access the abstract class reflection helper."""
49
+ return self._abstract_reflexion
70
50
 
71
- Returns
72
- -------
73
- Set[str]
74
- Set of abstract method names not implemented
75
- """
76
- abstract_methods = getattr(self._abstract, '__abstractmethods__', set())
77
- return abstract_methods - set(dir(self._instance))
78
-
79
- def isProperImplementation(self) -> bool:
80
- """Check if the instance properly implements all abstract methods.
51
+ def getImplementationAnalysis(self) -> Dict[str, Dict[str, Union[bool, str, inspect.Signature]]]:
52
+ """Comprehensive analysis of implementation compliance.
81
53
 
82
54
  Returns
83
55
  -------
84
- bool
85
- True if all abstract methods are implemented, False otherwise
56
+ Dict[str, Dict[str, Union[bool, str, inspect.Signature]]]
57
+ Detailed analysis including:
58
+ - 'implemented': Whether method is implemented
59
+ - 'signature_match': Whether signatures match
60
+ - 'abstract_signature': Signature from abstract class
61
+ - 'concrete_signature': Signature from concrete class
86
62
  """
87
- return len(self.getMissingImplementations()) == 0
88
-
89
- def getAbstractMethods(self) -> Set[str]:
90
- """Get all abstract methods from the parent class.
91
-
92
- Returns
93
- -------
94
- Set[str]
95
- Set of abstract method names
96
- """
97
- return getattr(self._abstract, '__abstractmethods__', set())
98
-
99
- def getConcreteMethods(self) -> List[str]:
100
- """Get all concrete methods of the instance.
101
-
102
- Returns
103
- -------
104
- List[str]
105
- List of method names implemented by the instance
106
- """
107
- return [name for name, _ in inspect.getmembers(
108
- self._instance,
109
- predicate=inspect.ismethod
110
- )]
111
-
112
- def getOverriddenMethods(self) -> Dict[str, Tuple[Type, Type]]:
113
- """Get methods that override abstract ones with their signatures.
114
-
115
- Returns
116
- -------
117
- Dict[str, Tuple[Type, Type]]
118
- Dictionary mapping method names to tuples of
119
- (abstract_signature, concrete_signature)
120
- """
121
- overridden = {}
122
- abstract_methods = self.getAbstractMethods()
123
-
63
+ analysis = {}
64
+ abstract_methods = self._abstract_reflexion.getAbstractMethods()
124
65
  for method in abstract_methods:
125
- if hasattr(self._instance, method):
126
- abstract_sig = inspect.signature(getattr(self._abstract, method))
127
- concrete_sig = inspect.signature(getattr(self._instance, method))
128
- overridden[method] = (abstract_sig, concrete_sig)
66
+ entry = {
67
+ 'implemented': False,
68
+ 'abstract_signature': None,
69
+ 'concrete_signature': None,
70
+ 'signature_match': False,
71
+ 'type' : 'method'
72
+ }
129
73
 
130
- return overridden
131
-
132
- def checkSignatureCompatibility(self) -> Dict[str, bool]:
133
- """Check if implemented methods match abstract signatures.
74
+ if hasattr(self._instance, method):
75
+ entry['implemented'] = True
76
+ abstract_sig = self._abstract_reflexion.getMethodSignature(method)
77
+ concrete_sig = self._concrete_reflexion.getMethodSignature(method)
78
+
79
+ entry.update({
80
+ 'abstract_signature': abstract_sig,
81
+ 'concrete_signature': concrete_sig,
82
+ 'signature_match': (
83
+ abstract_sig.parameters == concrete_sig.parameters and
84
+ abstract_sig.return_annotation == concrete_sig.return_annotation
85
+ )
86
+ })
87
+
88
+ analysis[method] = entry
89
+
90
+ abstract_properties = self._abstract_reflexion.getAbstractProperties()
91
+ for prop in abstract_properties:
92
+ entry = {
93
+ 'implemented': False,
94
+ 'abstract_signature': None,
95
+ 'concrete_signature': None,
96
+ 'signature_match': False,
97
+ 'type' : 'property'
98
+ }
99
+
100
+ if hasattr(self._instance, prop):
101
+ entry['implemented'] = True
102
+ abstract_sig = self._abstract_reflexion.getPropertySignature(prop)
103
+ concrete_sig = self._concrete_reflexion.getPropertySignature(prop)
104
+
105
+ entry.update({
106
+ 'abstract_signature': abstract_sig,
107
+ 'concrete_signature': concrete_sig,
108
+ 'signature_match': (
109
+ abstract_sig.parameters == concrete_sig.parameters and
110
+ abstract_sig.return_annotation == concrete_sig.return_annotation
111
+ )
112
+ })
113
+
114
+ analysis[prop] = entry
115
+
116
+ return analysis
117
+
118
+ def getNonInheritedImplementation(self) -> Dict[str, Any]:
119
+ """Get implementation details for methods, properties, and attributes not inherited from other parents.
134
120
 
135
121
  Returns
136
122
  -------
137
- Dict[str, bool]
138
- Dictionary mapping method names to compatibility status
139
- """
140
- compatibility = {}
141
- overridden = self.getOverriddenMethods()
142
-
143
- for method, (abstract_sig, concrete_sig) in overridden.items():
144
- compatibility[method] = (
145
- abstract_sig.parameters == concrete_sig.parameters and
146
- abstract_sig.return_annotation == concrete_sig.return_annotation
147
- )
148
-
149
- return compatibility
150
-
151
- def getAbstractProperties(self) -> Set[str]:
152
- """Get all abstract properties from the parent class.
123
+ Dict[str, Any]
124
+ Dictionary containing:
125
+ - 'methods': List of non-inherited method names
126
+ - 'properties': List of non-inherited property names
127
+ - 'attributes': Dict of non-inherited attributes
128
+ """
129
+ # Get all members from concrete class (non-inherited methods, properties, and attributes)
130
+ concrete_members = set(dir(self._instance.__class__))
131
+
132
+ # Get members from the abstract class (base class)
133
+ base_members = set(dir(self._abstract))
134
+
135
+ # Filter out inherited members (methods, properties, and attributes)
136
+ non_inherited_methods = [
137
+ name for name in concrete_members
138
+ if callable(getattr(self._instance.__class__, name)) and name not in base_members
139
+ ]
140
+
141
+ non_inherited_properties = [
142
+ name for name in concrete_members
143
+ if isinstance(getattr(self._instance.__class__, name, None), property) and name not in base_members
144
+ ]
145
+
146
+ non_inherited_attributes = {
147
+ name: getattr(self._instance.__class__, name)
148
+ for name in concrete_members
149
+ if not callable(getattr(self._instance.__class__, name)) and not isinstance(getattr(self._instance.__class__, name, None), property) and name not in base_members
150
+ }
153
151
 
154
- Returns
155
- -------
156
- Set[str]
157
- Set of abstract property names
158
- """
159
152
  return {
160
- name for name, member in inspect.getmembers(
161
- self._abstract,
162
- lambda x: isinstance(x, property) and
163
- name in getattr(self._abstract, '__abstractmethods__', set())
164
- )
153
+ 'methods': non_inherited_methods,
154
+ 'properties': non_inherited_properties,
155
+ 'attributes': non_inherited_attributes
165
156
  }
166
157
 
167
- def getInstanceAttributes(self) -> Dict[str, Any]:
168
- """Get all attributes of the concrete instance.
158
+ def validateImplementation(self) -> Tuple[bool, Dict[str, List[str]]]:
159
+ """Validate the implementation against the abstract base.
169
160
 
170
161
  Returns
171
162
  -------
172
- Dict[str, Any]
173
- Dictionary of attribute names and their values
163
+ Tuple[bool, Dict[str, List[str]]]
164
+ - First element: True if fully valid implementation
165
+ - Second element: Dictionary of issues by category:
166
+ * 'missing': Missing required methods
167
+ * 'signature_mismatch': Methods with signature mismatches
168
+ * 'type_mismatch': Methods with return type mismatches
174
169
  """
175
- return vars(self._instance)
176
-
177
- def getAbstractClassDocstring(self) -> Optional[str]:
178
- """Get the docstring of the abstract parent class.
179
-
180
- Returns
181
- -------
182
- Optional[str]
183
- The abstract class docstring, or None if not available
184
- """
185
- return self._abstract.__doc__
186
-
187
- def getConcreteClassDocstring(self) -> Optional[str]:
188
- """Get the docstring of the concrete instance's class.
189
-
190
- Returns
191
- -------
192
- Optional[str]
193
- The concrete class docstring, or None if not available
194
- """
195
- return self._instance.__class__.__doc__
196
-
197
- def getAbstractClassModule(self) -> str:
198
- """Get the module name where the abstract class is defined.
199
-
200
- Returns
201
- -------
202
- str
203
- The module name of the abstract class
204
- """
205
- return self._abstract.__module__
206
-
207
- def getConcreteClassModule(self) -> str:
208
- """Get the module name where the concrete class is defined.
209
-
210
- Returns
211
- -------
212
- str
213
- The module name of the concrete class
214
- """
215
- return self._instance.__class__.__module__
216
-
217
- def isDirectSubclass(self) -> bool:
218
- """Check if the concrete class directly inherits from the abstract class.
219
-
220
- Returns
221
- -------
222
- bool
223
- True if direct subclass, False otherwise
224
- """
225
- return self._abstract in self._instance.__class__.__bases__
170
+ issues = {
171
+ 'missing': [],
172
+ 'signature_mismatch': [],
173
+ 'type_mismatch': []
174
+ }
226
175
 
227
- def getAbstractClassHierarchy(self) -> List[Type]:
228
- """Get the inheritance hierarchy of the abstract class.
176
+ analysis = self.getImplementationAnalysis()
177
+ for method, data in analysis.items():
178
+ if not data['implemented']:
179
+ issues['missing'].append(method)
180
+ elif not data['signature_match']:
181
+ issues['signature_mismatch'].append(method)
182
+ # Check specifically for return type mismatch
183
+ abstract_return = data['abstract_signature'].return_annotation
184
+ concrete_return = data['concrete_signature'].return_annotation
185
+ if abstract_return != concrete_return and abstract_return is not inspect.Parameter.empty:
186
+ issues['type_mismatch'].append(method)
229
187
 
230
- Returns
231
- -------
232
- List[Type]
233
- List of classes in the inheritance hierarchy
234
- """
235
- return inspect.getmro(self._abstract)
188
+ is_valid = not any(issues.values())
189
+ return (is_valid, issues)
236
190
 
237
- def getConcreteClassHierarchy(self) -> List[Type]:
238
- """Get the inheritance hierarchy of the concrete class.
191
+ def getHierarchyAnalysis(self) -> Dict[str, List[str]]:
192
+ """Analyze the class hierarchy relationships.
239
193
 
240
194
  Returns
241
195
  -------
242
- List[Type]
243
- List of classes in the inheritance hierarchy
196
+ Dict[str, List[str]]
197
+ Dictionary containing:
198
+ - 'concrete_hierarchy': List of class names in concrete hierarchy
199
+ - 'abstract_hierarchy': List of class names in abstract hierarchy
200
+ - 'common_ancestors': List of common ancestor class names
244
201
  """
245
- return inspect.getmro(self._instance.__class__)
202
+ concrete_hierarchy = [cls.__name__ for cls in inspect.getmro(self._instance.__class__)]
203
+ abstract_hierarchy = [cls.__name__ for cls in inspect.getmro(self._abstract)]
246
204
 
247
- def getCommonBaseClasses(self) -> List[Type]:
248
- """Get base classes common to both abstract and concrete classes.
249
-
250
- Returns
251
- -------
252
- List[Type]
253
- List of common base classes
254
- """
255
- abstract_bases = set(inspect.getmro(self._abstract))
256
205
  concrete_bases = set(inspect.getmro(self._instance.__class__))
257
- return list(abstract_bases & concrete_bases - {self._abstract, object})
258
-
259
- def getAbstractClassSource(self) -> Optional[str]:
260
- """Get the source code of the abstract class.
261
-
262
- Returns
263
- -------
264
- Optional[str]
265
- The source code if available, None otherwise
266
- """
267
- try:
268
- return inspect.getsource(self._abstract)
269
- except (TypeError, OSError):
270
- return None
271
-
272
- def getConcreteClassSource(self) -> Optional[str]:
273
- """Get the source code of the concrete class.
206
+ abstract_bases = set(inspect.getmro(self._abstract))
207
+ common = concrete_bases & abstract_bases - {self._abstract, object}
274
208
 
275
- Returns
276
- -------
277
- Optional[str]
278
- The source code if available, None otherwise
279
- """
280
- try:
281
- return inspect.getsource(self._instance.__class__)
282
- except (TypeError, OSError):
283
- return None
209
+ return {
210
+ 'concrete_hierarchy': concrete_hierarchy,
211
+ 'abstract_hierarchy': abstract_hierarchy,
212
+ 'common_ancestors': [cls.__name__ for cls in common]
213
+ }
284
214
 
285
- def getAbstractClassFile(self) -> Optional[str]:
286
- """Get the file location of the abstract class definition.
215
+ def getImplementationCoverage(self) -> float:
216
+ """Calculate the percentage of abstract methods implemented.
287
217
 
288
218
  Returns
289
219
  -------
290
- Optional[str]
291
- The file path if available, None otherwise
220
+ float
221
+ Implementation coverage percentage (0.0 to 1.0)
292
222
  """
293
- try:
294
- return inspect.getfile(self._abstract)
295
- except (TypeError, OSError):
296
- return None
297
-
298
- def getConcreteClassFile(self) -> Optional[str]:
299
- """Get the file location of the concrete class definition.
223
+ attr = self.getImplementationAnalysis()
224
+ attr_len = len(attr) * 2
225
+ attr_implemented = 0
226
+ for method in attr.values():
227
+ if method.get('implemented'):
228
+ attr_implemented += 2 if method.get('signature_match') else 1
300
229
 
301
- Returns
302
- -------
303
- Optional[str]
304
- The file path if available, None otherwise
305
- """
306
- try:
307
- return inspect.getfile(self._instance.__class__)
308
- except (TypeError, OSError):
309
- return None
230
+ return attr_implemented / attr_len if attr_len > 0 else 0.0
@@ -0,0 +1,5 @@
1
+ import unittest
2
+ from orionis.luminate.test.test_std_out import TestStdOut
3
+
4
+ class TestCase(unittest.TestCase, TestStdOut):
5
+ pass
@@ -1,8 +1,8 @@
1
+ import os
1
2
  import sys
2
3
  from orionis.luminate.console.output.console import Console
3
- import os
4
4
 
5
- class PrinterInTest:
5
+ class TestStdOut:
6
6
  """
7
7
  A utility class for printing debug information during testing. This class temporarily
8
8
  redirects the standard output and error streams to their original states to ensure
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: orionis
3
- Version: 0.207.0
3
+ Version: 0.209.0
4
4
  Summary: Orionis Framework – Elegant, Fast, and Powerful.
5
5
  Home-page: https://github.com/orionis-framework/framework
6
6
  Author: Raul Mauricio Uñate Castro
@@ -1,6 +1,6 @@
1
1
  orionis/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  orionis/console.py,sha256=4gYWxf0fWYgJ4RKwARvnTPh06FL3GJ6SAZ7R2NzOICw,1342
3
- orionis/framework.py,sha256=eb4WxXbyAXkX44A065Y_hEHg-PyA8LWfMluqcfrxYJA,1469
3
+ orionis/framework.py,sha256=U51WcK-STfeqKJkXH8t51BUJpV_Zg8o-exE-7tgVj8k,1469
4
4
  orionis/installer/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
5
  orionis/installer/manager.py,sha256=Li4TVziRXWfum02xNG4JHwbnLk-u8xzHjdqKz-D894k,2755
6
6
  orionis/installer/output.py,sha256=7O9qa2xtXMB_4ZvVi-Klneom9YazwygAd_4uYAoxhbU,8548
@@ -171,18 +171,19 @@ orionis/luminate/support/inspection/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQ
171
171
  orionis/luminate/support/inspection/container_integrity.py,sha256=6d9FsGk-Rm1AXgqBS3Nww49dR7n1ptXTTNyGUuBHgNY,10111
172
172
  orionis/luminate/support/inspection/functions.py,sha256=XVDLdygONcfDNlH7CZ6muNdtYHLgNp5RybqC3smL4Y4,6400
173
173
  orionis/luminate/support/inspection/reflection.py,sha256=x_UHBY9pBSKgct13-u1WbhoONqLoGG60OpgoCsKE0AI,20368
174
- orionis/luminate/support/inspection/reflexion_abstract.py,sha256=pKjLZFAfCHcve39FiIeAyAJiSxKhOWBkMsPub3Sa-RI,9313
174
+ orionis/luminate/support/inspection/reflexion_abstract.py,sha256=U_VAGQN0ZDMgjxYPhNrLxFt6F8_-8zXcA_B5djTV4GE,10731
175
175
  orionis/luminate/support/inspection/reflexion_concrete.py,sha256=0WOlLeTWLwMeAUReoaJetqlnT1_TxW_jMnbk_yXRR0g,549
176
176
  orionis/luminate/support/inspection/reflexion_concrete_with_abstract.py,sha256=ZuAFoSPkgbOFMIbVR0hvlkKsm1dIpY1_bsXxZxvXcmU,801
177
- orionis/luminate/support/inspection/reflexion_instance.py,sha256=k6bpRYjLeTUDqquluYrDZUtBLpLuGe4wm7PMUM8Sz-E,9914
178
- orionis/luminate/support/inspection/reflexion_instance_with_abstract.py,sha256=dag6QdVp1CydREWdpQvzAyOPX3q-lSb0_XzB0u3odQE,9629
177
+ orionis/luminate/support/inspection/reflexion_instance.py,sha256=LNAgw4sZvHT7UMiObHTGk7xgqpIeKYHAQRgRpuPfEas,10842
178
+ orionis/luminate/support/inspection/reflexion_instance_with_abstract.py,sha256=PI_VSH8baxjPgheOYc9tQAlLq9mjxGm5zCOr-bLVksg,9406
179
179
  orionis/luminate/support/inspection/reflexion_module.py,sha256=OgBXpqNJHkmq-gX4rqFStv-WVNe9R38RsgUgfHpak8k,405
180
180
  orionis/luminate/support/inspection/reflexion_module_with_classname.py,sha256=YZHZI0XUZkSWnq9wrGxrIXtI64nY9yVSZoMe7PZXq8Y,620
181
181
  orionis/luminate/test/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
182
+ orionis/luminate/test/test_case.py,sha256=jFhNcUZWuDTDFpe_nYJTqXQChA4z5kxu0I2YCONGSVk,134
182
183
  orionis/luminate/test/test_exception.py,sha256=21PILTXnMuL5-wT3HGKjIklt8VeIYDcQDN346i-BbJw,1336
183
- orionis/luminate/test/test_output.py,sha256=7QvkxbKOp56GcznjaJSX9I072gkut1NvuaexqO3v8BM,2768
184
184
  orionis/luminate/test/test_result.py,sha256=Px2_M70r_y7BntRITk_h0IPTbSTW5XhDyklMKHm3JJI,999
185
185
  orionis/luminate/test/test_status.py,sha256=vNKRmp1lud_ZGTayf3A8wO_0vEYdFABy_oMw-RcEc1c,673
186
+ orionis/luminate/test/test_std_out.py,sha256=annYLGDkskRpMuLwTAswwrgrYmwsXIyKE02M_ePv-qc,2765
186
187
  orionis/luminate/test/tests.py,sha256=KZRFHB6C8S2DN6JHqJ2sIuSNAUMh9JW1Yn-XGjXjjTw,2218
187
188
  orionis/luminate/test/unit_test.py,sha256=HtPDWzFXpgFwWYej8z2BArU4k5lItH57K_E-l21MBWo,12070
188
189
  orionis/static/ascii/icon.ascii,sha256=IgrlVjcYxcCrr0cJuJkOnEz0aEdAQBTyLzO5ainKsWc,398
@@ -196,17 +197,19 @@ orionis/static/logos/OrionisFramework2.png,sha256=Z_-yBHNSo33QeSTyi-8GfiFozdRqUo
196
197
  orionis/static/logos/OrionisFramework3.png,sha256=BPG9ZB58vDALavI9OMmr8Ym0DQa44s5NL_3M4M6dIYs,193734
197
198
  tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
198
199
  tests/example/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
199
- tests/example/test_example.py,sha256=MNYissCEa0mzx1YA2gTiqXRX8r2v_vfB_Ew0jBFmBag,556
200
+ tests/example/test_example.py,sha256=8EYjl1b-J_479dmJdQoAcKCKr7JUydW7EmPQpeiF13Y,586
200
201
  tests/support/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
201
202
  tests/support/inspection/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
202
- tests/support/inspection/test_reflection_abstract.py,sha256=ntrwbhYdZBWWCuHI0k_Vttd4jclhZ-wLwopb1XhAB_k,8750
203
- tests/support/inspection/test_reflection_instance.py,sha256=4aBFeLgOmNvO5rbyd6EFioU4_DgXddV5pL3el23mFtA,6681
203
+ tests/support/inspection/test_reflection_abstract.py,sha256=K78avxUlI_dYKofSvVcuaVLAz-CivWSe3RkhrO-IRcA,9185
204
+ tests/support/inspection/test_reflection_instance.py,sha256=qwYu_y3wiZzhegrRo97r1bWxW2YGxDdnnU-Hq4lZtAE,6930
205
+ tests/support/inspection/test_reflection_instance_with_abstract.py,sha256=RNLf9RfRtM2nTY6Yfc8rPibSEVZkl8Pw2w962vsragk,4048
204
206
  tests/support/inspection/fakes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
205
207
  tests/support/inspection/fakes/fake_reflection_abstract.py,sha256=7qtz44brfFzE4oNYi9kIsvdWP79nP2FnzSz-0bU__pg,5045
206
208
  tests/support/inspection/fakes/fake_reflection_instance.py,sha256=G16rZdJWC3L8SGEQkmwktvw4n7IAusIIx9Tm-ZFLcg4,1419
207
- orionis-0.207.0.dist-info/LICENCE,sha256=-_4cF2EBKuYVS_SQpy1uapq0oJPUU1vl_RUWSy2jJTo,1111
208
- orionis-0.207.0.dist-info/METADATA,sha256=OTZC93qgIgplcgvUxPIBdQtjs_420Y0HUyWXCy4mshU,3003
209
- orionis-0.207.0.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
210
- orionis-0.207.0.dist-info/entry_points.txt,sha256=a_e0faeSqyUCVZd0MqljQ2oaHHdlsz6g9sU_bMqi5zQ,49
211
- orionis-0.207.0.dist-info/top_level.txt,sha256=2bdoHgyGZhOtLAXS6Om8OCTmL24dUMC_L1quMe_ETbk,14
212
- orionis-0.207.0.dist-info/RECORD,,
209
+ tests/support/inspection/fakes/fake_reflection_instance_with_abstract.py,sha256=SfL8FuFmr650RlzXTrP4tGMfsPVZLhOxVnBXu_g1POg,1471
210
+ orionis-0.209.0.dist-info/LICENCE,sha256=-_4cF2EBKuYVS_SQpy1uapq0oJPUU1vl_RUWSy2jJTo,1111
211
+ orionis-0.209.0.dist-info/METADATA,sha256=C6g0E0x63bfx_67XUWursBiX083LFbgx4gehabf_lR0,3003
212
+ orionis-0.209.0.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
213
+ orionis-0.209.0.dist-info/entry_points.txt,sha256=a_e0faeSqyUCVZd0MqljQ2oaHHdlsz6g9sU_bMqi5zQ,49
214
+ orionis-0.209.0.dist-info/top_level.txt,sha256=2bdoHgyGZhOtLAXS6Om8OCTmL24dUMC_L1quMe_ETbk,14
215
+ orionis-0.209.0.dist-info/RECORD,,
@@ -1,5 +1,6 @@
1
- import unittest
2
- class TestExample(unittest.TestCase):
1
+ from orionis.luminate.test.test_case import TestCase
2
+
3
+ class TestExample(TestCase):
3
4
  """
4
5
  Unit tests for basic example functionality.
5
6
  """
@@ -0,0 +1,45 @@
1
+ from abc import ABC, abstractmethod
2
+ from typing import List, Dict
3
+
4
+ class IDataProcessor(ABC):
5
+ """Interfaz para procesamiento de datos."""
6
+
7
+ @property
8
+ @abstractmethod
9
+ def config(self) -> Dict[str, str]:
10
+ """Configuración del procesador."""
11
+ pass
12
+
13
+ @abstractmethod
14
+ def process(self, data: List[float]) -> Dict[str, float]:
15
+ """Procesa una lista de números y devuelve métricas."""
16
+ pass
17
+
18
+ @abstractmethod
19
+ def validate_input(self, raw_data: str) -> bool:
20
+ """Valida si los datos en crudo pueden ser procesados."""
21
+ pass
22
+
23
+ class FakeDataProcessor:
24
+ """Implementación concreta fake de IDataProcessor."""
25
+
26
+ def __init__(self):
27
+ self._config = {"mode": "standard"}
28
+ self._version = "1.0"
29
+
30
+ @property
31
+ def config(self) -> Dict[str, str]:
32
+ """Implementación correcta de la propiedad."""
33
+ return self._config
34
+
35
+ def process(self, values: List[float]) -> Dict[str, float]:
36
+ """Implementación con tipo de retorno incorrecto (float vs Dict)."""
37
+ return sum(values) / len(values) if values else 0.0
38
+
39
+ def validate_input(self, source: str) -> bool:
40
+ """Implementación con parámetro renombrado (source vs raw_data)."""
41
+ return bool(source)
42
+
43
+ def extra_method(self) -> str:
44
+ """Método adicional no definido en la interfaz."""
45
+ return f"Processing with version {self._version}"
@@ -1,10 +1,9 @@
1
1
  from abc import ABC
2
- import unittest
3
2
  from orionis.luminate.support.inspection.reflection import Reflection
4
- from orionis.luminate.test.test_output import PrinterInTest
3
+ from orionis.luminate.test.test_case import TestCase
5
4
  from tests.support.inspection.fakes.fake_reflection_abstract import FakeAbstractClass
6
5
 
7
- class TestReflexionAbstract(unittest.TestCase, PrinterInTest):
6
+ class TestReflexionAbstract(TestCase):
8
7
  """Test cases for ReflexionAbstract using FakeAbstractClass.
9
8
 
10
9
  This test suite verifies all functionality of the ReflexionAbstract class
@@ -226,4 +225,13 @@ class TestReflexionAbstract(unittest.TestCase, PrinterInTest):
226
225
  Verifies that:
227
226
  - Returns empty set for non-Protocol classes
228
227
  """
229
- self.assertEqual(Reflection.abstract(FakeAbstractClass).getRequiredAttributes(), set())
228
+ self.assertEqual(Reflection.abstract(FakeAbstractClass).getRequiredAttributes(), set())
229
+
230
+ def testReflectionAbstractGetAbstractProperties(self):
231
+ """Test getRequiredMethods() method."""
232
+ self.assertEqual(Reflection.abstract(FakeAbstractClass).getAbstractProperties(), set())
233
+
234
+ def testReflectionAbstractGetPropertySignature(self):
235
+ """Test getPropertySignature() method."""
236
+ signature = Reflection.abstract(FakeAbstractClass).getPropertySignature('computed_property')
237
+ self.assertEqual(str(signature), '(self) -> float')
@@ -1,10 +1,9 @@
1
- import unittest
2
1
  from orionis.luminate.support.inspection.reflection import Reflection
3
2
  from orionis.luminate.support.inspection.reflexion_instance import ReflexionInstance
4
- from orionis.luminate.test.test_output import PrinterInTest
3
+ from orionis.luminate.test.test_case import TestCase
5
4
  from tests.support.inspection.fakes.fake_reflection_instance import BaseFakeClass, FakeClass
6
5
 
7
- class TestReflection(unittest.TestCase, PrinterInTest):
6
+ class TestReflection(TestCase):
8
7
  """
9
8
  Unit tests for the Reflection class.
10
9
  """
@@ -139,3 +138,8 @@ class TestReflection(unittest.TestCase, PrinterInTest):
139
138
 
140
139
  result = reflex.callMethod("myMacro", reflex._instance, 3)
141
140
  self.assertEqual(result, 25)
141
+
142
+ def testReflectionInstanceGetPropertySignature(self):
143
+ """Ensure getPropertySignature returns the correct property signature."""
144
+ signature = Reflection.instance(FakeClass()).getPropertySignature('computed_property')
145
+ self.assertEqual(str(signature), '(self) -> str')
@@ -0,0 +1,79 @@
1
+ from orionis.luminate.support.inspection.reflexion_instance_with_abstract import ReflexionInstanceWithAbstract
2
+ from orionis.luminate.test.test_case import TestCase
3
+ from tests.support.inspection.fakes.fake_reflection_instance_with_abstract import FakeDataProcessor, IDataProcessor
4
+
5
+ class TestReflexionWithFakes(TestCase):
6
+
7
+ def testReflexionInstanceWithAbstractGetImplementationAnalysis(self):
8
+ """Test reflexion con IDataProcessor y FakeDataProcessor."""
9
+ processor = FakeDataProcessor()
10
+ inspector = ReflexionInstanceWithAbstract(processor, IDataProcessor)
11
+
12
+ # Get Implementation analysis
13
+ analysis = inspector.getImplementationAnalysis()
14
+
15
+ # Verifying implemented methods
16
+ self.assertTrue(analysis['validate_input']['implemented'])
17
+ self.assertEqual(str(analysis['validate_input']['abstract_signature']), "(self, raw_data: str) -> bool")
18
+ self.assertEqual(str(analysis['validate_input']['concrete_signature']), "(source: str) -> bool")
19
+ self.assertFalse(analysis['validate_input']['signature_match'])
20
+ self.assertEqual(analysis['validate_input']['type'], 'method')
21
+
22
+ self.assertTrue(analysis['process']['implemented'])
23
+ self.assertEqual(str(analysis['process']['abstract_signature']), "(self, data: List[float]) -> Dict[str, float]")
24
+ self.assertEqual(str(analysis['process']['concrete_signature']), "(values: List[float]) -> Dict[str, float]")
25
+ self.assertFalse(analysis['process']['signature_match'])
26
+ self.assertEqual(analysis['process']['type'], 'method')
27
+
28
+ self.assertTrue(analysis['config']['implemented'])
29
+ self.assertEqual(str(analysis['config']['abstract_signature']), "(self) -> Dict[str, str]")
30
+ self.assertEqual(str(analysis['config']['concrete_signature']), "(self) -> Dict[str, str]")
31
+ self.assertTrue(analysis['config']['signature_match'])
32
+ self.assertEqual(analysis['config']['type'], 'property')
33
+
34
+ def testReflexionInstanceWithAbstractGetNonInheritedImplementation(self):
35
+ """Test reflexion con IDataProcessor y FakeDataProcessor."""
36
+ processor = FakeDataProcessor()
37
+ inspector = ReflexionInstanceWithAbstract(processor, IDataProcessor)
38
+
39
+ # Get Non-Inherited implementation analysis
40
+ analysis = inspector.getNonInheritedImplementation()
41
+
42
+ # Verifying implemented methods
43
+ self.assertIn('extra_method', analysis['methods'])
44
+
45
+ def testReflexionInstanceWithAbstractValidateImplementation(self):
46
+ """Test reflexion con IDataProcessor y FakeDataProcessor."""
47
+ processor = FakeDataProcessor()
48
+ inspector = ReflexionInstanceWithAbstract(processor, IDataProcessor)
49
+
50
+ # Get Implementation analysis
51
+ is_valid, issues = inspector.validateImplementation()
52
+
53
+ # Verifying implemented methods
54
+ self.assertFalse(is_valid)
55
+ self.assertIn('process', issues['signature_mismatch'])
56
+
57
+ def testReflexionInstanceWithAbstractGetHierarchyAnalysis(self):
58
+ """Test reflexion con IDataProcessor y FakeDataProcessor."""
59
+ processor = FakeDataProcessor()
60
+ inspector = ReflexionInstanceWithAbstract(processor, IDataProcessor)
61
+
62
+ # Get Hierarchy analysis
63
+ analysis = inspector.getHierarchyAnalysis()
64
+
65
+ # Verifying implemented methods
66
+ self.assertEqual(analysis['common_ancestors'], [])
67
+ self.assertIn('IDataProcessor', analysis['abstract_hierarchy'])
68
+ self.assertIn('FakeDataProcessor', analysis['concrete_hierarchy'])
69
+
70
+ def testReflexionInstanceWithAbstractGetImplementationCoverage(self):
71
+ """Test reflexion con IDataProcessor y FakeDataProcessor."""
72
+ processor = FakeDataProcessor()
73
+ inspector = ReflexionInstanceWithAbstract(processor, IDataProcessor)
74
+
75
+ # Get Implementation coverage
76
+ coverage = inspector.getImplementationCoverage()
77
+
78
+ # Verifying implemented methods
79
+ self.assertTrue(coverage >= 0.66)