orionis 0.211.0__py3-none-any.whl → 0.213.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_concrete_with_abstract.py +162 -8
- {orionis-0.211.0.dist-info → orionis-0.213.0.dist-info}/METADATA +1 -1
- {orionis-0.211.0.dist-info → orionis-0.213.0.dist-info}/RECORD +10 -8
- tests/support/inspection/fakes/fake_reflection_concrete_with_abstract.py +78 -0
- tests/support/inspection/test_reflection_concrete_with_abstract.py +87 -0
- {orionis-0.211.0.dist-info → orionis-0.213.0.dist-info}/LICENCE +0 -0
- {orionis-0.211.0.dist-info → orionis-0.213.0.dist-info}/WHEEL +0 -0
- {orionis-0.211.0.dist-info → orionis-0.213.0.dist-info}/entry_points.txt +0 -0
- {orionis-0.211.0.dist-info → orionis-0.213.0.dist-info}/top_level.txt +0 -0
orionis/framework.py
CHANGED
@@ -1,31 +1,185 @@
|
|
1
|
-
from typing import Type, TypeVar
|
2
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_concrete import ReflexionConcrete
|
3
6
|
|
4
7
|
T = TypeVar('T')
|
5
8
|
ABC = TypeVar('ABC', bound=abc.ABC)
|
6
9
|
|
7
|
-
|
8
10
|
class ReflexionConcreteWithAbstract:
|
9
|
-
"""
|
11
|
+
"""Advanced reflection tool for analyzing concrete classes against abstract bases.
|
12
|
+
|
13
|
+
Allows static analysis of class definitions to verify compatibility
|
14
|
+
and adherence to interface contracts without instantiation.
|
10
15
|
|
11
16
|
Parameters
|
12
17
|
----------
|
13
18
|
concrete : Type[T]
|
14
|
-
The concrete class
|
19
|
+
The concrete class to inspect
|
15
20
|
abstract : Type[ABC]
|
16
|
-
The abstract
|
21
|
+
The abstract base class/interface being implemented
|
17
22
|
|
18
23
|
Attributes
|
19
24
|
----------
|
20
25
|
_concrete : Type[T]
|
21
|
-
The
|
26
|
+
The concrete class being analyzed
|
22
27
|
_abstract : Type[ABC]
|
23
|
-
The
|
28
|
+
The abstract base class/interface
|
29
|
+
_concrete_reflexion : ReflexionConcrete
|
30
|
+
Reflection helper for the concrete class
|
31
|
+
_abstract_reflexion : ReflexionAbstract
|
32
|
+
Reflection helper for the abstract class
|
24
33
|
"""
|
25
34
|
|
26
35
|
def __init__(self, concrete: Type[T], abstract: Type[ABC]) -> None:
|
27
|
-
"""Initialize with the concrete class and abstract parent."""
|
28
36
|
self._concrete = concrete
|
29
37
|
self._abstract = abstract
|
38
|
+
self._concrete_reflexion = ReflexionConcrete(concrete)
|
39
|
+
self._abstract_reflexion = ReflexionAbstract(abstract)
|
40
|
+
|
41
|
+
@property
|
42
|
+
def concrete(self) -> ReflexionConcrete:
|
43
|
+
"""Access the concrete class reflection helper."""
|
44
|
+
return self._concrete_reflexion
|
45
|
+
|
46
|
+
@property
|
47
|
+
def abstract(self) -> ReflexionAbstract:
|
48
|
+
"""Access the abstract class reflection helper."""
|
49
|
+
return self._abstract_reflexion
|
50
|
+
|
51
|
+
def getImplementationAnalysis(self) -> Dict[str, Dict[str, Union[bool, str, inspect.Signature]]]:
|
52
|
+
"""Comprehensive analysis of implementation compliance."""
|
53
|
+
analysis = {}
|
54
|
+
|
55
|
+
abstract_methods = self._abstract_reflexion.getAbstractMethods()
|
56
|
+
for method in abstract_methods:
|
57
|
+
entry = {
|
58
|
+
'implemented': False,
|
59
|
+
'abstract_signature': None,
|
60
|
+
'concrete_signature': None,
|
61
|
+
'signature_match': False,
|
62
|
+
'type': 'method'
|
63
|
+
}
|
64
|
+
|
65
|
+
if hasattr(self._concrete, method):
|
66
|
+
entry['implemented'] = True
|
67
|
+
abstract_sig = self._abstract_reflexion.getMethodSignature(method)
|
68
|
+
concrete_sig = self._concrete_reflexion.getMethodSignature(method)
|
69
|
+
|
70
|
+
entry.update({
|
71
|
+
'abstract_signature': abstract_sig,
|
72
|
+
'concrete_signature': concrete_sig,
|
73
|
+
'signature_match': (
|
74
|
+
abstract_sig.parameters == concrete_sig.parameters and
|
75
|
+
abstract_sig.return_annotation == concrete_sig.return_annotation
|
76
|
+
)
|
77
|
+
})
|
78
|
+
|
79
|
+
analysis[method] = entry
|
80
|
+
|
81
|
+
abstract_properties = self._abstract_reflexion.getAbstractProperties()
|
82
|
+
for prop in abstract_properties:
|
83
|
+
entry = {
|
84
|
+
'implemented': False,
|
85
|
+
'abstract_signature': None,
|
86
|
+
'concrete_signature': None,
|
87
|
+
'signature_match': False,
|
88
|
+
'type': 'property'
|
89
|
+
}
|
90
|
+
|
91
|
+
if hasattr(self._concrete, prop):
|
92
|
+
entry['implemented'] = True
|
93
|
+
abstract_sig = self._abstract_reflexion.getPropertySignature(prop)
|
94
|
+
concrete_sig = self._concrete_reflexion.getPropertySignature(prop)
|
95
|
+
|
96
|
+
entry.update({
|
97
|
+
'abstract_signature': abstract_sig,
|
98
|
+
'concrete_signature': concrete_sig,
|
99
|
+
'signature_match': (
|
100
|
+
abstract_sig.parameters == concrete_sig.parameters and
|
101
|
+
abstract_sig.return_annotation == concrete_sig.return_annotation
|
102
|
+
)
|
103
|
+
})
|
104
|
+
|
105
|
+
analysis[prop] = entry
|
106
|
+
|
107
|
+
return analysis
|
108
|
+
|
109
|
+
def validateImplementation(self) -> Tuple[bool, Dict[str, List[str]]]:
|
110
|
+
"""Validate the implementation against the abstract base."""
|
111
|
+
issues = {
|
112
|
+
'missing': [],
|
113
|
+
'signature_mismatch': [],
|
114
|
+
'type_mismatch': []
|
115
|
+
}
|
116
|
+
|
117
|
+
analysis = self.getImplementationAnalysis()
|
118
|
+
for name, data in analysis.items():
|
119
|
+
if not data['implemented']:
|
120
|
+
issues['missing'].append(name)
|
121
|
+
elif not data['signature_match']:
|
122
|
+
issues['signature_mismatch'].append(name)
|
123
|
+
abstract_return = data['abstract_signature'].return_annotation
|
124
|
+
concrete_return = data['concrete_signature'].return_annotation
|
125
|
+
if abstract_return != concrete_return and abstract_return is not inspect.Parameter.empty:
|
126
|
+
issues['type_mismatch'].append(name)
|
127
|
+
|
128
|
+
is_valid = not any(issues.values())
|
129
|
+
return (is_valid, issues)
|
130
|
+
|
131
|
+
def getImplementationCoverage(self) -> float:
|
132
|
+
"""Calculate the percentage of abstract methods/properties implemented."""
|
133
|
+
analysis = self.getImplementationAnalysis()
|
134
|
+
total = len(analysis) * 2
|
135
|
+
implemented = 0
|
136
|
+
for item in analysis.values():
|
137
|
+
if item['implemented']:
|
138
|
+
implemented += 2 if item['signature_match'] else 1
|
139
|
+
return implemented / total if total else 0.0
|
140
|
+
|
141
|
+
def getNonInheritedImplementation(self) -> Dict[str, Any]:
|
142
|
+
"""Get implementation details for methods, properties, and attributes not inherited from the abstract base."""
|
143
|
+
concrete_members = set(dir(self._concrete))
|
144
|
+
base_members = set(dir(self._abstract))
|
145
|
+
|
146
|
+
non_inherited_methods = [
|
147
|
+
name for name in concrete_members
|
148
|
+
if callable(getattr(self._concrete, name, None)) and name not in base_members
|
149
|
+
]
|
150
|
+
|
151
|
+
non_inherited_properties = [
|
152
|
+
name for name in concrete_members
|
153
|
+
if isinstance(getattr(self._concrete, name, None), property) and name not in base_members
|
154
|
+
]
|
155
|
+
|
156
|
+
non_inherited_attributes = {
|
157
|
+
name: getattr(self._concrete, name, None)
|
158
|
+
for name in concrete_members
|
159
|
+
if (
|
160
|
+
not callable(getattr(self._concrete, name, None)) and
|
161
|
+
not isinstance(getattr(self._concrete, name, None), property) and
|
162
|
+
name not in base_members
|
163
|
+
)
|
164
|
+
}
|
165
|
+
|
166
|
+
return {
|
167
|
+
'methods': non_inherited_methods,
|
168
|
+
'properties': non_inherited_properties,
|
169
|
+
'attributes': non_inherited_attributes
|
170
|
+
}
|
171
|
+
|
172
|
+
def getHierarchyAnalysis(self) -> Dict[str, List[str]]:
|
173
|
+
"""Analyze the class hierarchy relationships."""
|
174
|
+
concrete_hierarchy = [cls.__name__ for cls in inspect.getmro(self._concrete)]
|
175
|
+
abstract_hierarchy = [cls.__name__ for cls in inspect.getmro(self._abstract)]
|
30
176
|
|
177
|
+
concrete_bases = set(inspect.getmro(self._concrete))
|
178
|
+
abstract_bases = set(inspect.getmro(self._abstract))
|
179
|
+
common = concrete_bases & abstract_bases - {self._abstract, object}
|
31
180
|
|
181
|
+
return {
|
182
|
+
'concrete_hierarchy': concrete_hierarchy,
|
183
|
+
'abstract_hierarchy': abstract_hierarchy,
|
184
|
+
'common_ancestors': [cls.__name__ for cls in common]
|
185
|
+
}
|
@@ -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=
|
3
|
+
orionis/framework.py,sha256=h535GtyAp9Bsjr4Ao052lL6yCui73xb5BWR70PDbLig,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,7 +171,7 @@ orionis/luminate/support/inspection/functions.py,sha256=4wDT7iNp-5l4vuHk0UsIxN9w
|
|
171
171
|
orionis/luminate/support/inspection/reflection.py,sha256=mOCamaKv1ED-Q60_01HMzsCAhoCFeDK7ZqYZ3iYepsM,7716
|
172
172
|
orionis/luminate/support/inspection/reflexion_abstract.py,sha256=U_VAGQN0ZDMgjxYPhNrLxFt6F8_-8zXcA_B5djTV4GE,10731
|
173
173
|
orionis/luminate/support/inspection/reflexion_concrete.py,sha256=1ISuy2L6Oser-EhmpuGALmbauh7Z-X8Rx1YYgt5CabQ,7543
|
174
|
-
orionis/luminate/support/inspection/reflexion_concrete_with_abstract.py,sha256=
|
174
|
+
orionis/luminate/support/inspection/reflexion_concrete_with_abstract.py,sha256=z1cAscuG6a1E4ZJmwkp9HVQ0yhTAeFYKfnnyR_M-RFI,7480
|
175
175
|
orionis/luminate/support/inspection/reflexion_instance.py,sha256=LNAgw4sZvHT7UMiObHTGk7xgqpIeKYHAQRgRpuPfEas,10842
|
176
176
|
orionis/luminate/support/inspection/reflexion_instance_with_abstract.py,sha256=PI_VSH8baxjPgheOYc9tQAlLq9mjxGm5zCOr-bLVksg,9406
|
177
177
|
orionis/luminate/support/inspection/reflexion_module.py,sha256=OgBXpqNJHkmq-gX4rqFStv-WVNe9R38RsgUgfHpak8k,405
|
@@ -200,16 +200,18 @@ tests/support/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
200
200
|
tests/support/inspection/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
201
201
|
tests/support/inspection/test_reflection_abstract.py,sha256=K78avxUlI_dYKofSvVcuaVLAz-CivWSe3RkhrO-IRcA,9185
|
202
202
|
tests/support/inspection/test_reflection_concrete.py,sha256=dvO7dduJMCsioCxZ5i2WW6V5-3z5LR6gIgGvBGaQcNI,6542
|
203
|
+
tests/support/inspection/test_reflection_concrete_with_abstract.py,sha256=G29gqevXQd7TBOluaPpK6ER-24a4uK-zaImamig7cEE,4650
|
203
204
|
tests/support/inspection/test_reflection_instance.py,sha256=iwwf-QY-O3kR_HTHdATUnu9iXn6Nat7d8Y8Hxhwfpb0,6938
|
204
205
|
tests/support/inspection/test_reflection_instance_with_abstract.py,sha256=RQkw2BYY8TLuk6h_9NIa_5JfRL7RG8004ro252t6YF8,4059
|
205
206
|
tests/support/inspection/fakes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
206
207
|
tests/support/inspection/fakes/fake_reflection_abstract.py,sha256=7qtz44brfFzE4oNYi9kIsvdWP79nP2FnzSz-0bU__pg,5045
|
207
208
|
tests/support/inspection/fakes/fake_reflection_concrete.py,sha256=j6gzsxE3xq5oJ30H_Hm1RsUwEY3jOYBu4sclxtD1ayo,1047
|
209
|
+
tests/support/inspection/fakes/fake_reflection_concrete_with_abstract.py,sha256=ibCjrtNM6BMf5Z5VMvat7E6zOAk5g9z--gj4ykKJWY8,2118
|
208
210
|
tests/support/inspection/fakes/fake_reflection_instance.py,sha256=G16rZdJWC3L8SGEQkmwktvw4n7IAusIIx9Tm-ZFLcg4,1419
|
209
211
|
tests/support/inspection/fakes/fake_reflection_instance_with_abstract.py,sha256=SfL8FuFmr650RlzXTrP4tGMfsPVZLhOxVnBXu_g1POg,1471
|
210
|
-
orionis-0.
|
211
|
-
orionis-0.
|
212
|
-
orionis-0.
|
213
|
-
orionis-0.
|
214
|
-
orionis-0.
|
215
|
-
orionis-0.
|
212
|
+
orionis-0.213.0.dist-info/LICENCE,sha256=-_4cF2EBKuYVS_SQpy1uapq0oJPUU1vl_RUWSy2jJTo,1111
|
213
|
+
orionis-0.213.0.dist-info/METADATA,sha256=AAJOh4awPCmTybz8JgS7tMkkRL6nv6mLVrptKugaYS0,3003
|
214
|
+
orionis-0.213.0.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
215
|
+
orionis-0.213.0.dist-info/entry_points.txt,sha256=a_e0faeSqyUCVZd0MqljQ2oaHHdlsz6g9sU_bMqi5zQ,49
|
216
|
+
orionis-0.213.0.dist-info/top_level.txt,sha256=2bdoHgyGZhOtLAXS6Om8OCTmL24dUMC_L1quMe_ETbk,14
|
217
|
+
orionis-0.213.0.dist-info/RECORD,,
|
@@ -0,0 +1,78 @@
|
|
1
|
+
import abc
|
2
|
+
from typing import Any, Dict, List
|
3
|
+
|
4
|
+
class AbstractService(abc.ABC):
|
5
|
+
"""
|
6
|
+
Abstract interface for service-like behavior.
|
7
|
+
|
8
|
+
Methods
|
9
|
+
-------
|
10
|
+
process(data: str) -> bool
|
11
|
+
Perform processing on input data.
|
12
|
+
|
13
|
+
reset() -> None
|
14
|
+
Reset the internal state of the service.
|
15
|
+
|
16
|
+
configure(options: Dict[str, Any]) -> None
|
17
|
+
Apply configuration settings to the service.
|
18
|
+
|
19
|
+
get_logs(limit: int = 10) -> List[str]
|
20
|
+
Retrieve a limited number of log messages.
|
21
|
+
|
22
|
+
Properties
|
23
|
+
----------
|
24
|
+
status : str
|
25
|
+
Current status of the service.
|
26
|
+
"""
|
27
|
+
|
28
|
+
@abc.abstractmethod
|
29
|
+
def process(self, data: str) -> bool:
|
30
|
+
"""Perform processing on input data."""
|
31
|
+
pass
|
32
|
+
|
33
|
+
@abc.abstractmethod
|
34
|
+
def reset(self) -> None:
|
35
|
+
"""Reset the internal state of the service."""
|
36
|
+
pass
|
37
|
+
|
38
|
+
@abc.abstractmethod
|
39
|
+
def configure(self, options: Dict[str, Any]) -> None:
|
40
|
+
"""Apply configuration settings to the service."""
|
41
|
+
pass
|
42
|
+
|
43
|
+
@abc.abstractmethod
|
44
|
+
def get_logs(self, limit: int = 10) -> List[str]:
|
45
|
+
"""Retrieve a limited number of log messages."""
|
46
|
+
pass
|
47
|
+
|
48
|
+
@property
|
49
|
+
@abc.abstractmethod
|
50
|
+
def status(self) -> str:
|
51
|
+
"""Current status of the service."""
|
52
|
+
pass
|
53
|
+
|
54
|
+
class PartiallyImplementedService:
|
55
|
+
"""
|
56
|
+
A partial implementation of AbstractService.
|
57
|
+
|
58
|
+
This class mimics the interface but lacks some methods/properties,
|
59
|
+
making it useful for testing reflection-based validation.
|
60
|
+
"""
|
61
|
+
|
62
|
+
def process(self, data: str) -> bool:
|
63
|
+
"""Basic processing implementation."""
|
64
|
+
return bool(data)
|
65
|
+
|
66
|
+
def get_logs(self, limit: int = 10) -> List[str]:
|
67
|
+
"""Return a fixed list of logs (mock implementation)."""
|
68
|
+
return [f"log {i}" for i in range(limit)]
|
69
|
+
|
70
|
+
# ❌ Missing: reset()
|
71
|
+
# ❌ Missing: configure()
|
72
|
+
# ❌ Missing: status (property)
|
73
|
+
|
74
|
+
def extra(self) -> str:
|
75
|
+
"""An extra method not part of the abstract interface."""
|
76
|
+
return "Just extra"
|
77
|
+
|
78
|
+
version: str = "1.0"
|
@@ -0,0 +1,87 @@
|
|
1
|
+
from orionis.luminate.support.inspection.reflexion_concrete_with_abstract import ReflexionConcreteWithAbstract
|
2
|
+
from orionis.luminate.test.test_case import TestCase
|
3
|
+
from tests.support.inspection.fakes.fake_reflection_concrete_with_abstract import AbstractService, PartiallyImplementedService
|
4
|
+
|
5
|
+
class TestReflexionConcreteWithAbstract(TestCase):
|
6
|
+
|
7
|
+
def testReflexionInstanceWithAbstractGetImplementationAnalysis(self):
|
8
|
+
"""Test reflexion con AbstractService y PartiallyImplementedService."""
|
9
|
+
inspector = ReflexionConcreteWithAbstract(PartiallyImplementedService, AbstractService)
|
10
|
+
|
11
|
+
# Get Implementation analysis
|
12
|
+
analysis = inspector.getImplementationAnalysis()
|
13
|
+
|
14
|
+
# Verifying implemented methods
|
15
|
+
self.assertFalse(analysis['configure']['implemented'])
|
16
|
+
self.assertIsNone(analysis['configure']['abstract_signature'])
|
17
|
+
self.assertIsNone(analysis['configure']['concrete_signature'])
|
18
|
+
self.assertFalse(analysis['configure']['signature_match'])
|
19
|
+
self.assertEqual(analysis['configure']['type'], 'method')
|
20
|
+
|
21
|
+
self.assertTrue(analysis['get_logs']['implemented'])
|
22
|
+
self.assertEqual(str(analysis['get_logs']['abstract_signature']), "(self, limit: int = 10) -> List[str]")
|
23
|
+
self.assertEqual(str(analysis['get_logs']['concrete_signature']), "(self, limit: int = 10) -> List[str]")
|
24
|
+
self.assertTrue(analysis['get_logs']['signature_match'])
|
25
|
+
self.assertEqual(analysis['get_logs']['type'], 'method')
|
26
|
+
|
27
|
+
self.assertFalse(analysis['reset']['implemented'])
|
28
|
+
self.assertIsNone(analysis['reset']['abstract_signature'])
|
29
|
+
self.assertIsNone(analysis['reset']['concrete_signature'])
|
30
|
+
self.assertFalse(analysis['reset']['signature_match'])
|
31
|
+
self.assertEqual(analysis['reset']['type'], 'method')
|
32
|
+
|
33
|
+
self.assertTrue(analysis['process']['implemented'])
|
34
|
+
self.assertEqual(str(analysis['process']['abstract_signature']), "(self, data: str) -> bool")
|
35
|
+
self.assertEqual(str(analysis['process']['concrete_signature']), "(self, data: str) -> bool")
|
36
|
+
self.assertTrue(analysis['process']['signature_match'])
|
37
|
+
self.assertEqual(analysis['process']['type'], 'method')
|
38
|
+
|
39
|
+
self.assertFalse(analysis['status']['implemented'])
|
40
|
+
self.assertIsNone(analysis['status']['abstract_signature'])
|
41
|
+
self.assertIsNone(analysis['status']['concrete_signature'])
|
42
|
+
self.assertFalse(analysis['status']['signature_match'])
|
43
|
+
self.assertEqual(analysis['status']['type'], 'property')
|
44
|
+
|
45
|
+
def testReflexionConcreteWithAbstractGetNonInheritedImplementation(self):
|
46
|
+
"""Test reflexion con AbstractService y PartiallyImplementedService."""
|
47
|
+
inspector = ReflexionConcreteWithAbstract(PartiallyImplementedService, AbstractService)
|
48
|
+
|
49
|
+
# Get Non-Inherited implementation analysis
|
50
|
+
analysis = inspector.getNonInheritedImplementation()
|
51
|
+
|
52
|
+
self.assertIn('extra', analysis['methods'])
|
53
|
+
self.assertListEqual(analysis['properties'], [])
|
54
|
+
self.assertIn('__annotations__', analysis['attributes'])
|
55
|
+
|
56
|
+
def testReflexionConcreteWithAbstractValidateImplementation(self):
|
57
|
+
"""Test reflexion con AbstractService y PartiallyImplementedService."""
|
58
|
+
inspector = ReflexionConcreteWithAbstract(PartiallyImplementedService, AbstractService)
|
59
|
+
|
60
|
+
# Get Implementation analysis
|
61
|
+
is_valid, issues = inspector.validateImplementation()
|
62
|
+
|
63
|
+
# Verifying implemented methods
|
64
|
+
self.assertFalse(is_valid)
|
65
|
+
self.assertIn('reset', issues['missing'])
|
66
|
+
|
67
|
+
def testReflexionConcreteWithAbstractGetHierarchyAnalysis(self):
|
68
|
+
"""Test reflexion con AbstractService y PartiallyImplementedService."""
|
69
|
+
inspector = ReflexionConcreteWithAbstract(PartiallyImplementedService, AbstractService)
|
70
|
+
|
71
|
+
# Get Hierarchy analysis
|
72
|
+
analysis = inspector.getHierarchyAnalysis()
|
73
|
+
|
74
|
+
# Verifying implemented methods
|
75
|
+
self.assertEqual(analysis['common_ancestors'], [])
|
76
|
+
self.assertIn('AbstractService', analysis['abstract_hierarchy'])
|
77
|
+
self.assertIn('PartiallyImplementedService', analysis['concrete_hierarchy'])
|
78
|
+
|
79
|
+
def testReflexionConcreteWithAbstractGetImplementationCoverage(self):
|
80
|
+
"""Test reflexion con AbstractService y PartiallyImplementedService."""
|
81
|
+
inspector = ReflexionConcreteWithAbstract(PartiallyImplementedService, AbstractService)
|
82
|
+
|
83
|
+
# Get Implementation coverage
|
84
|
+
coverage = inspector.getImplementationCoverage()
|
85
|
+
|
86
|
+
# Verifying implemented methods
|
87
|
+
self.assertTrue(coverage >= 0.4)
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|