ripple-down-rules 0.6.44__py3-none-any.whl → 0.6.46__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.
- ripple_down_rules/__init__.py +1 -1
- ripple_down_rules/failures.py +4 -0
- ripple_down_rules/rdr.py +43 -10
- ripple_down_rules/rdr_decorators.py +1 -3
- ripple_down_rules/utils.py +16 -4
- {ripple_down_rules-0.6.44.dist-info → ripple_down_rules-0.6.46.dist-info}/METADATA +1 -1
- {ripple_down_rules-0.6.44.dist-info → ripple_down_rules-0.6.46.dist-info}/RECORD +10 -9
- {ripple_down_rules-0.6.44.dist-info → ripple_down_rules-0.6.46.dist-info}/WHEEL +0 -0
- {ripple_down_rules-0.6.44.dist-info → ripple_down_rules-0.6.46.dist-info}/licenses/LICENSE +0 -0
- {ripple_down_rules-0.6.44.dist-info → ripple_down_rules-0.6.46.dist-info}/top_level.txt +0 -0
ripple_down_rules/__init__.py
CHANGED
ripple_down_rules/rdr.py
CHANGED
@@ -15,6 +15,7 @@ from types import NoneType, ModuleType
|
|
15
15
|
|
16
16
|
from ripple_down_rules.datastructures.dataclasses import CaseFactoryMetaData
|
17
17
|
from . import logger
|
18
|
+
from .failures import RDRLoadError
|
18
19
|
|
19
20
|
try:
|
20
21
|
from matplotlib import pyplot as plt
|
@@ -45,7 +46,7 @@ from .utils import draw_tree, make_set, SubclassJSONSerializer, make_list, get_t
|
|
45
46
|
is_value_conflicting, extract_function_source, extract_imports, get_full_class_name, \
|
46
47
|
is_iterable, str_to_snake_case, get_import_path_from_path, get_imports_from_types, render_tree, \
|
47
48
|
get_types_to_import_from_func_type_hints, get_function_return_type, get_file_that_ends_with, \
|
48
|
-
get_and_import_python_module, get_and_import_python_modules_in_a_package
|
49
|
+
get_and_import_python_module, get_and_import_python_modules_in_a_package, get_type_from_type_hint
|
49
50
|
|
50
51
|
|
51
52
|
class RippleDownRules(SubclassJSONSerializer, ABC):
|
@@ -217,10 +218,10 @@ class RippleDownRules(SubclassJSONSerializer, ABC):
|
|
217
218
|
if os.path.exists(json_file + ".json"):
|
218
219
|
rdr = cls.from_json_file(json_file)
|
219
220
|
try:
|
221
|
+
acronym = cls.get_acronym().lower()
|
222
|
+
python_file_name = get_file_that_ends_with(model_dir, f"_{acronym}.py")
|
223
|
+
python_file_path = os.path.join(model_dir, python_file_name)
|
220
224
|
if rdr is None:
|
221
|
-
acronym = cls.get_acronym().lower()
|
222
|
-
python_file_name = get_file_that_ends_with(model_dir, f"_{acronym}.py")
|
223
|
-
python_file_path = os.path.join(model_dir, python_file_name)
|
224
225
|
rdr = cls.from_python(model_dir, parent_package_name=package_name, python_file_path=python_file_path)
|
225
226
|
else:
|
226
227
|
rdr.update_from_python(model_dir, package_name=package_name)
|
@@ -228,6 +229,8 @@ class RippleDownRules(SubclassJSONSerializer, ABC):
|
|
228
229
|
except (FileNotFoundError, ValueError, SyntaxError, ModuleNotFoundError) as e:
|
229
230
|
logger.warning(f"Could not load the python file for the model {model_name} from {model_dir}. "
|
230
231
|
f"Make sure the file exists and is valid.")
|
232
|
+
if rdr is None:
|
233
|
+
raise RDRLoadError(f"Could not load the rdr model {model_name} from {model_dir}, error is {e}")
|
231
234
|
rdr.save(save_dir=load_dir, model_name=model_name, package_name=package_name)
|
232
235
|
rdr.save_dir = load_dir
|
233
236
|
rdr.model_name = model_name
|
@@ -886,22 +889,52 @@ class RDRWithCodeWriter(RippleDownRules, ABC):
|
|
886
889
|
self.update_rdr_metadata_from_python(main_module)
|
887
890
|
|
888
891
|
functions_source = extract_function_source(defs_module.__file__,
|
889
|
-
all_func_names, include_signature=
|
892
|
+
all_func_names, include_signature=True)
|
890
893
|
scope = extract_imports(defs_module.__file__, package_name=package_name)
|
891
894
|
|
895
|
+
cases_source, cases_scope = None, None
|
896
|
+
if cases_module:
|
897
|
+
with open(cases_module.__file__, "r") as f:
|
898
|
+
cases_source = f.read()
|
899
|
+
cases_scope = extract_imports(cases_module.__file__, package_name=package_name)
|
900
|
+
|
901
|
+
with open(main_module.__file__, "r") as f:
|
902
|
+
main_source = f.read()
|
903
|
+
main_scope = extract_imports(main_module.__file__, package_name=package_name)
|
904
|
+
attribute_name_line = [l for l in main_source.split('\n') if "attribute_name = " in l]
|
905
|
+
conclusion_name = None
|
906
|
+
if len(attribute_name_line) > 0:
|
907
|
+
conclusion_name = eval(attribute_name_line[0].split('=')[-1].strip(), main_scope)
|
908
|
+
|
892
909
|
for rule in all_rules:
|
893
910
|
if rule.conditions is not None:
|
894
911
|
conditions_wrapper_func_name = rule.generated_conditions_function_name
|
895
912
|
user_input = functions_source[conditions_wrapper_func_name]
|
913
|
+
user_input = '\n'.join(user_input.split("\n")[1:]) # Remove the function signature line
|
896
914
|
rule.conditions = CallableExpression(user_input, (bool,), scope=scope)
|
897
915
|
if cases_module:
|
898
|
-
|
916
|
+
try:
|
917
|
+
rule.corner_case_metadata = cases_module.__dict__[rule.generated_corner_case_object_name]
|
918
|
+
except KeyError:
|
919
|
+
case_def_lines = [l for l in cases_source.split('\n') if rule.generated_corner_case_object_name in l]
|
920
|
+
if len(case_def_lines) > 0:
|
921
|
+
case_def_line = case_def_lines[0].split('=')[-1].strip()
|
922
|
+
rule.corner_case_metadata = eval(case_def_line, cases_scope)
|
923
|
+
|
899
924
|
if not isinstance(rule, MultiClassStopRule):
|
900
|
-
|
901
|
-
|
902
|
-
user_input = functions_source[
|
925
|
+
if conclusion_name:
|
926
|
+
rule.conclusion_name = conclusion_name
|
927
|
+
user_input = functions_source[rule.generated_conclusion_function_name]
|
928
|
+
split_user_input = user_input.split("\n")
|
929
|
+
user_input = '\n'.join(split_user_input[1:])
|
903
930
|
conclusion_func = defs_module.__dict__.get(rule.generated_conclusion_function_name)
|
904
|
-
|
931
|
+
if conclusion_func is None:
|
932
|
+
function_signature = split_user_input[0]
|
933
|
+
return_type_hint_str = function_signature.split('->')[-1].strip(' :')
|
934
|
+
return_type_hint = eval(return_type_hint_str, scope)
|
935
|
+
conclusion_type = get_type_from_type_hint(return_type_hint)
|
936
|
+
else:
|
937
|
+
conclusion_type = get_function_return_type(conclusion_func)
|
905
938
|
rule.conclusion = CallableExpression(user_input, conclusion_type, scope=scope,
|
906
939
|
mutually_exclusive=self.mutually_exclusive)
|
907
940
|
|
@@ -213,9 +213,7 @@ class RDRDecorator:
|
|
213
213
|
"""
|
214
214
|
self.rdr = None
|
215
215
|
if self.model_name is not None:
|
216
|
-
|
217
|
-
if os.path.exists(os.path.join(self.rdr_models_dir, model_path)):
|
218
|
-
self.rdr = GeneralRDR.load(self.rdr_models_dir, self.model_name, package_name=self.package_name)
|
216
|
+
self.rdr = GeneralRDR.load(self.rdr_models_dir, self.model_name, package_name=self.package_name)
|
219
217
|
if self.rdr is None:
|
220
218
|
self.rdr = GeneralRDR(save_dir=self.rdr_models_dir, model_name=self.model_name)
|
221
219
|
|
ripple_down_rules/utils.py
CHANGED
@@ -168,20 +168,28 @@ def extract_imports(file_path: Optional[str] = None, tree: Optional[ast.AST] = N
|
|
168
168
|
try:
|
169
169
|
scope[asname] = importlib.import_module(module_name, package=package_name)
|
170
170
|
except ImportError as e:
|
171
|
-
|
171
|
+
logger.warning(f"Could not import {module_name}: {e}")
|
172
172
|
elif isinstance(node, ast.ImportFrom):
|
173
173
|
module_name = node.module
|
174
174
|
for alias in node.names:
|
175
175
|
name = alias.name
|
176
176
|
asname = alias.asname or name
|
177
177
|
try:
|
178
|
+
if node.level > 0: # Handle relative imports
|
179
|
+
package_name = get_import_path_from_path(Path(os.path.join(file_path, *['..'] * node.level)).resolve())
|
178
180
|
if package_name is not None and node.level > 0: # Handle relative imports
|
179
181
|
module_rel_path = Path(os.path.join(file_path, *['..'] * node.level, module_name)).resolve()
|
180
182
|
idx = str(module_rel_path).rfind(package_name)
|
181
183
|
if idx != -1:
|
182
184
|
module_name = str(module_rel_path)[idx:].replace(os.path.sep, '.')
|
183
|
-
|
184
|
-
|
185
|
+
try:
|
186
|
+
module = importlib.import_module(module_name, package=package_name)
|
187
|
+
except ModuleNotFoundError:
|
188
|
+
module = importlib.import_module(f"{package_name}.{module_name}")
|
189
|
+
if name == "*":
|
190
|
+
scope.update(module.__dict__)
|
191
|
+
else:
|
192
|
+
scope[asname] = getattr(module, name)
|
185
193
|
except (ImportError, AttributeError) as e:
|
186
194
|
logger.warning(f"Could not import {module_name}: {e} while extracting imports from {file_path}")
|
187
195
|
|
@@ -782,10 +790,14 @@ def get_function_return_type(func: Callable) -> Union[Type, None, Tuple[Type, ..
|
|
782
790
|
if sig.return_annotation == inspect.Signature.empty:
|
783
791
|
return None
|
784
792
|
type_hint = sig.return_annotation
|
793
|
+
return get_type_from_type_hint(type_hint)
|
794
|
+
|
795
|
+
|
796
|
+
def get_type_from_type_hint(type_hint: Type) -> Union[Type, Tuple[Type, ...]]:
|
785
797
|
origin = get_origin(type_hint)
|
786
798
|
args = get_args(type_hint)
|
787
799
|
if origin not in [list, set, None, Union]:
|
788
|
-
raise TypeError(f"{origin} is not a handled return type for
|
800
|
+
raise TypeError(f"{origin} is not a handled return type for type hint {type_hint}")
|
789
801
|
if origin is None:
|
790
802
|
return typing_to_python_type(type_hint)
|
791
803
|
if args is None or len(args) == 0:
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: ripple_down_rules
|
3
|
-
Version: 0.6.
|
3
|
+
Version: 0.6.46
|
4
4
|
Summary: Implements the various versions of Ripple Down Rules (RDR) for knowledge representation and reasoning.
|
5
5
|
Author-email: Abdelrhman Bassiouny <abassiou@uni-bremen.de>
|
6
6
|
License: GNU GENERAL PUBLIC LICENSE
|
@@ -1,11 +1,12 @@
|
|
1
|
-
ripple_down_rules/__init__.py,sha256=
|
1
|
+
ripple_down_rules/__init__.py,sha256=BK-q-yssQG0Y05Fkmc-Gm7xHrKf32lFrbtphnAm2XD8,99
|
2
2
|
ripple_down_rules/experts.py,sha256=KXwWCmDrCffu9HW3yNewqWc1e5rnPI5Rnc981w_5M7U,17896
|
3
|
+
ripple_down_rules/failures.py,sha256=ZPypPwKjyVcJkY9YG6p538ld8ZzpdW6CrC1RmJi44Ek,42
|
3
4
|
ripple_down_rules/helpers.py,sha256=X1psHOqrb4_xYN4ssQNB8S9aRKKsqgihAyWJurN0dqk,5499
|
4
|
-
ripple_down_rules/rdr.py,sha256=
|
5
|
-
ripple_down_rules/rdr_decorators.py,sha256=
|
5
|
+
ripple_down_rules/rdr.py,sha256=Dq5bEuBuf3vct_I6Y3WmTtoTUzNsvHXNYvF5DFoKO14,83468
|
6
|
+
ripple_down_rules/rdr_decorators.py,sha256=ehK9YFYCh21fnbuzOX000yBwVDXL-QqYuEfKoWNYyDU,11468
|
6
7
|
ripple_down_rules/rules.py,sha256=L4Ws-x3g5ljE0GrDt4LAib2qtR1C1_Ra4cRcIB-IQDI,28702
|
7
8
|
ripple_down_rules/start-code-server.sh,sha256=otClk7VmDgBOX2TS_cjws6K0UwvgAUJhoA0ugkPCLqQ,949
|
8
|
-
ripple_down_rules/utils.py,sha256=
|
9
|
+
ripple_down_rules/utils.py,sha256=5UL4h-m5Q4l7RyCYqmUmDDxUAkFqPYpFa3QldDYoJUE,80752
|
9
10
|
ripple_down_rules/datastructures/__init__.py,sha256=V2aNgf5C96Y5-IGghra3n9uiefpoIm_QdT7cc_C8cxQ,111
|
10
11
|
ripple_down_rules/datastructures/callable_expression.py,sha256=rzMrpD5oztaCRlt3hQ2B_xZ09cSuJNkYOCePndfQJRA,13684
|
11
12
|
ripple_down_rules/datastructures/case.py,sha256=dfLnrjsHIVF2bgbz-4ID7OdQvw68V71btCeTK372P-g,15667
|
@@ -17,8 +18,8 @@ ripple_down_rules/user_interface/ipython_custom_shell.py,sha256=RLdPqPxx-a0Sh74U
|
|
17
18
|
ripple_down_rules/user_interface/object_diagram.py,sha256=FEa2HaYR9QmTE6NsOwBvZ0jqmu3DKyg6mig2VE5ZP4Y,4956
|
18
19
|
ripple_down_rules/user_interface/prompt.py,sha256=WPbw_8_-8SpF2ISyRZRuFwPKBEuGC4HaX3lbCPFHhh8,10314
|
19
20
|
ripple_down_rules/user_interface/template_file_creator.py,sha256=uSbosZS15MOR3Nv7M3MrFuoiKXyP4cBId-EK3I6stHM,13660
|
20
|
-
ripple_down_rules-0.6.
|
21
|
-
ripple_down_rules-0.6.
|
22
|
-
ripple_down_rules-0.6.
|
23
|
-
ripple_down_rules-0.6.
|
24
|
-
ripple_down_rules-0.6.
|
21
|
+
ripple_down_rules-0.6.46.dist-info/licenses/LICENSE,sha256=ixuiBLtpoK3iv89l7ylKkg9rs2GzF9ukPH7ynZYzK5s,35148
|
22
|
+
ripple_down_rules-0.6.46.dist-info/METADATA,sha256=9BzQNnZOCR9GYOIM3DuKycWbsZzjyhRhFz22IVcUCOU,48294
|
23
|
+
ripple_down_rules-0.6.46.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
24
|
+
ripple_down_rules-0.6.46.dist-info/top_level.txt,sha256=VeoLhEhyK46M1OHwoPbCQLI1EifLjChqGzhQ6WEUqeM,18
|
25
|
+
ripple_down_rules-0.6.46.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|