ripple-down-rules 0.5.93__py3-none-any.whl → 0.5.95__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/helpers.py +1 -1
- ripple_down_rules/rdr.py +8 -5
- ripple_down_rules/rdr_decorators.py +1 -1
- ripple_down_rules/user_interface/ipython_custom_shell.py +1 -1
- ripple_down_rules/utils.py +33 -46
- {ripple_down_rules-0.5.93.dist-info → ripple_down_rules-0.5.95.dist-info}/METADATA +1 -1
- {ripple_down_rules-0.5.93.dist-info → ripple_down_rules-0.5.95.dist-info}/RECORD +11 -11
- {ripple_down_rules-0.5.93.dist-info → ripple_down_rules-0.5.95.dist-info}/WHEEL +0 -0
- {ripple_down_rules-0.5.93.dist-info → ripple_down_rules-0.5.95.dist-info}/licenses/LICENSE +0 -0
- {ripple_down_rules-0.5.93.dist-info → ripple_down_rules-0.5.95.dist-info}/top_level.txt +0 -0
ripple_down_rules/__init__.py
CHANGED
ripple_down_rules/helpers.py
CHANGED
@@ -36,7 +36,7 @@ def general_rdr_classify(classifiers_dict: Dict[str, Union[ModuleType, RippleDow
|
|
36
36
|
new_conclusions = {}
|
37
37
|
for attribute_name, rdr in classifiers_dict.items():
|
38
38
|
pred_atts = rdr.classify(case_cp, case_query=case_query)
|
39
|
-
if pred_atts is None:
|
39
|
+
if pred_atts is None and type(None) not in rdr.conclusion_type:
|
40
40
|
continue
|
41
41
|
if rdr.mutually_exclusive:
|
42
42
|
if attribute_name not in conclusions or \
|
ripple_down_rules/rdr.py
CHANGED
@@ -139,13 +139,15 @@ class RippleDownRules(SubclassJSONSerializer, ABC):
|
|
139
139
|
model_dir = os.path.join(load_dir, model_name)
|
140
140
|
json_file = os.path.join(model_dir, cls.metadata_folder, model_name)
|
141
141
|
rdr = cls.from_json_file(json_file)
|
142
|
+
rdr.save_dir = load_dir
|
143
|
+
rdr.model_name = model_name
|
142
144
|
try:
|
143
145
|
rdr.update_from_python(model_dir, package_name=package_name)
|
146
|
+
rdr.to_json_file(json_file)
|
144
147
|
except (FileNotFoundError, ValueError) as e:
|
145
148
|
logger.warning(f"Could not load the python file for the model {model_name} from {model_dir}. "
|
146
149
|
f"Make sure the file exists and is valid.")
|
147
|
-
|
148
|
-
rdr.model_name = model_name
|
150
|
+
rdr.save(save_dir=load_dir, model_name=model_name, package_name=package_name)
|
149
151
|
return rdr
|
150
152
|
|
151
153
|
@abstractmethod
|
@@ -296,7 +298,7 @@ class RippleDownRules(SubclassJSONSerializer, ABC):
|
|
296
298
|
:param update_existing: Whether to update rules that gave the required type of conclusions.
|
297
299
|
:return: True if the rdr should ask the expert, False otherwise.
|
298
300
|
"""
|
299
|
-
if conclusions is None:
|
301
|
+
if conclusions is None and type(None) not in case_query.core_attribute_type:
|
300
302
|
return True
|
301
303
|
elif is_iterable(conclusions) and len(conclusions) == 0:
|
302
304
|
return True
|
@@ -571,8 +573,9 @@ class RDRWithCodeWriter(RippleDownRules, ABC):
|
|
571
573
|
:return: The type of the conclusion of the RDR classifier.
|
572
574
|
"""
|
573
575
|
all_types = []
|
574
|
-
|
575
|
-
|
576
|
+
if self.start_rule is not None:
|
577
|
+
for rule in [self.start_rule] + list(self.start_rule.descendants):
|
578
|
+
all_types.extend(list(rule.conclusion.conclusion_type))
|
576
579
|
return tuple(set(all_types))
|
577
580
|
|
578
581
|
@property
|
@@ -120,7 +120,7 @@ class RDRDecorator:
|
|
120
120
|
func_args_type_hints = get_type_hints(func)
|
121
121
|
output_name = list(func_output.keys())[0]
|
122
122
|
func_args_type_hints.update({output_name: Union[tuple(output_type)]})
|
123
|
-
return CaseQuery(case, output_name,
|
123
|
+
return CaseQuery(case, output_name, tuple(output_type),
|
124
124
|
mutual_exclusive, scope=scope,
|
125
125
|
is_function=True, function_args_type_hints=func_args_type_hints)
|
126
126
|
|
ripple_down_rules/utils.py
CHANGED
@@ -85,30 +85,6 @@ def are_results_subclass_of_types(result_types: List[Any], types_: List[Type]) -
|
|
85
85
|
return True
|
86
86
|
|
87
87
|
|
88
|
-
def _get_imports_from_types(types: List[Type]) -> List[str]:
|
89
|
-
"""
|
90
|
-
Get the import statements for a list of types.
|
91
|
-
|
92
|
-
:param types: The types to get the import statements for.
|
93
|
-
:return: The import statements as a string.
|
94
|
-
"""
|
95
|
-
imports = map(get_import_from_type, types)
|
96
|
-
return list({i for i in imports if i is not None})
|
97
|
-
|
98
|
-
|
99
|
-
def get_import_from_type(type_: Type) -> Optional[str]:
|
100
|
-
"""
|
101
|
-
Get the import statement for a given type.
|
102
|
-
|
103
|
-
:param type_: The type to get the import statement for.
|
104
|
-
:return: The import statement as a string.
|
105
|
-
"""
|
106
|
-
if hasattr(type_, "__module__") and hasattr(type_, "__name__"):
|
107
|
-
if type_.__module__ == "builtins":
|
108
|
-
return
|
109
|
-
return f"from {type_.__module__} import {type_.__name__}"
|
110
|
-
|
111
|
-
|
112
88
|
def get_imports_from_scope(scope: Dict[str, Any]) -> List[str]:
|
113
89
|
"""
|
114
90
|
Get the imports from the given scope.
|
@@ -116,12 +92,7 @@ def get_imports_from_scope(scope: Dict[str, Any]) -> List[str]:
|
|
116
92
|
:param scope: The scope to get the imports from.
|
117
93
|
:return: The imports as a string.
|
118
94
|
"""
|
119
|
-
|
120
|
-
for k, v in scope.items():
|
121
|
-
if not hasattr(v, "__module__") or not hasattr(v, "__name__") or v.__module__ is None:
|
122
|
-
continue
|
123
|
-
imports.append(f"from {v.__module__} import {v.__name__}")
|
124
|
-
return imports
|
95
|
+
return get_imports_from_types(list(scope.values()))
|
125
96
|
|
126
97
|
|
127
98
|
def extract_imports(file_path: Optional[str] = None, tree: Optional[ast.AST] = None,
|
@@ -861,16 +832,18 @@ def get_relative_import(target_file_path, imported_module_path: Optional[str] =
|
|
861
832
|
:return: A relative import path as a string.
|
862
833
|
"""
|
863
834
|
# Convert to absolute paths
|
864
|
-
target_path = Path(target_file_path).resolve()
|
865
|
-
if package_name is not None:
|
866
|
-
target_path = Path(get_path_starting_from_latest_encounter_of(str(target_path), package_name))
|
867
835
|
if module is not None:
|
868
836
|
imported_module_path = sys.modules[module].__file__
|
869
837
|
if imported_module_path is None:
|
870
838
|
raise ValueError("Either imported_module_path or module must be provided")
|
839
|
+
target_path = Path(target_file_path).resolve()
|
840
|
+
imported_file_name = Path(imported_module_path).name
|
841
|
+
target_file_name = Path(target_file_path).name
|
842
|
+
if package_name is not None:
|
843
|
+
target_path = Path(get_path_starting_from_latest_encounter_of(str(target_path), package_name, [target_file_name]))
|
871
844
|
imported_path = Path(imported_module_path).resolve()
|
872
845
|
if package_name is not None:
|
873
|
-
imported_path = Path(get_path_starting_from_latest_encounter_of(str(imported_path), package_name))
|
846
|
+
imported_path = Path(get_path_starting_from_latest_encounter_of(str(imported_path), package_name, [imported_file_name]))
|
874
847
|
|
875
848
|
# Compute relative path from target to imported module
|
876
849
|
rel_path = os.path.relpath(imported_path.parent, target_path.parent)
|
@@ -879,28 +852,40 @@ def get_relative_import(target_file_path, imported_module_path: Optional[str] =
|
|
879
852
|
rel_parts = [part.replace('..', '.') for part in Path(rel_path).parts]
|
880
853
|
rel_parts = rel_parts if rel_parts else ['']
|
881
854
|
dot_parts = [part for part in rel_parts if part == '.']
|
882
|
-
non_dot_parts = [part for part in rel_parts if part != '.']
|
883
|
-
|
855
|
+
non_dot_parts = [part for part in rel_parts if part != '.'] + [imported_path.stem]
|
884
856
|
|
885
|
-
# Join the parts
|
886
|
-
joined_parts = "".join(dot_parts) + ".".join(non_dot_parts)
|
887
|
-
joined_parts = f".{joined_parts}" if not joined_parts.startswith(".") else joined_parts
|
857
|
+
# Join the parts
|
858
|
+
joined_parts = "." + "".join(dot_parts) + ".".join(non_dot_parts)
|
888
859
|
|
889
860
|
return joined_parts
|
890
861
|
|
891
862
|
|
892
|
-
def get_path_starting_from_latest_encounter_of(path: str, package_name: str) ->
|
863
|
+
def get_path_starting_from_latest_encounter_of(path: str, package_name: str, should_contain: List[str]) -> str:
|
893
864
|
"""
|
894
865
|
Get the path starting from the package name.
|
895
866
|
|
896
867
|
:param path: The full path to the file.
|
897
868
|
:param package_name: The name of the package to start from.
|
898
|
-
:
|
899
|
-
|
900
|
-
|
901
|
-
|
902
|
-
|
903
|
-
|
869
|
+
:param should_contain: The names of the files or directorys to look for.
|
870
|
+
:return: The path starting from the package name that contains all the names in should_contain, otherwise raise an error.
|
871
|
+
:raise ValueError: If the path does not contain all the names in should_contain.
|
872
|
+
"""
|
873
|
+
path_parts = path.split(os.path.sep)
|
874
|
+
if package_name not in path_parts:
|
875
|
+
raise ValueError(f"Could not find {package_name} in {path}")
|
876
|
+
idx = path_parts.index(package_name)
|
877
|
+
prev_idx = idx
|
878
|
+
while all(sc in path_parts[idx:] for sc in should_contain):
|
879
|
+
prev_idx = idx
|
880
|
+
try:
|
881
|
+
idx = path_parts.index(package_name, idx + 1)
|
882
|
+
except ValueError:
|
883
|
+
break
|
884
|
+
if all(sc in path_parts[idx:] for sc in should_contain):
|
885
|
+
path_parts = path_parts[prev_idx:]
|
886
|
+
return os.path.join(*path_parts)
|
887
|
+
else:
|
888
|
+
raise ValueError(f"Could not find {should_contain} in {path}")
|
904
889
|
|
905
890
|
|
906
891
|
def get_imports_from_types(type_objs: Iterable[Type],
|
@@ -937,6 +922,8 @@ def get_imports_from_types(type_objs: Iterable[Type],
|
|
937
922
|
or module in sys.builtin_module_names or module in excluded_modules or "<" in module \
|
938
923
|
or name in exclueded_names:
|
939
924
|
continue
|
925
|
+
if module == "typing":
|
926
|
+
module = "typing_extensions"
|
940
927
|
module_to_types[module].append(name)
|
941
928
|
except AttributeError:
|
942
929
|
continue
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: ripple_down_rules
|
3
|
-
Version: 0.5.
|
3
|
+
Version: 0.5.95
|
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,11 @@
|
|
1
|
-
ripple_down_rules/__init__.py,sha256=
|
1
|
+
ripple_down_rules/__init__.py,sha256=2YbCMVId4Rq_iPakA2uby2d6kRHClQ90FEJIWdgjG3c,100
|
2
2
|
ripple_down_rules/experts.py,sha256=4-dMIVeMzFXCLYl_XBG_P7_Xs4sZih9-vZxCIPri6dA,12958
|
3
|
-
ripple_down_rules/helpers.py,sha256=
|
4
|
-
ripple_down_rules/rdr.py,sha256=
|
5
|
-
ripple_down_rules/rdr_decorators.py,sha256=
|
3
|
+
ripple_down_rules/helpers.py,sha256=sY8nFbYdLOO6EG5UQugCCxjSjcCQsDUCPgawfQA4Ui8,4495
|
4
|
+
ripple_down_rules/rdr.py,sha256=weOkaB2Z8PdudKJfSSdkCPYjk2o4Woduupg-_gHh2vU,55449
|
5
|
+
ripple_down_rules/rdr_decorators.py,sha256=riAFmL8jc1rw9dFkNbT023CfB5FbmOWHNiVKO2bAXsE,9195
|
6
6
|
ripple_down_rules/rules.py,sha256=iVevv6iZ-6L2IPI0ZYbBjxBymXEQMmJGRFhiKUS-NmA,20352
|
7
7
|
ripple_down_rules/start-code-server.sh,sha256=otClk7VmDgBOX2TS_cjws6K0UwvgAUJhoA0ugkPCLqQ,949
|
8
|
-
ripple_down_rules/utils.py,sha256=
|
8
|
+
ripple_down_rules/utils.py,sha256=IDVcKd4YGGvFzO1KaGIEk9u8xh13MrpsFM97VmvTfyw,61881
|
9
9
|
ripple_down_rules/datastructures/__init__.py,sha256=V2aNgf5C96Y5-IGghra3n9uiefpoIm_QdT7cc_C8cxQ,111
|
10
10
|
ripple_down_rules/datastructures/callable_expression.py,sha256=f3wUPTrLa1INO-1qfgVz87ryrCABronfyq0_JKWoZCs,12800
|
11
11
|
ripple_down_rules/datastructures/case.py,sha256=PJ7_-AdxYic6BO5z816piFODj6nU5J6Jt1YzTFH-dds,15510
|
@@ -13,12 +13,12 @@ ripple_down_rules/datastructures/dataclasses.py,sha256=qoTFHV8Hi-X8VtfC9VdvH4tif
|
|
13
13
|
ripple_down_rules/datastructures/enums.py,sha256=ce7tqS0otfSTNAOwsnXlhsvIn4iW_Y_N3TNebF3YoZs,5700
|
14
14
|
ripple_down_rules/user_interface/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
15
15
|
ripple_down_rules/user_interface/gui.py,sha256=_lgZAUXxxaBUFQJAHjA5TBPp6XEvJ62t-kSN8sPsocE,27379
|
16
|
-
ripple_down_rules/user_interface/ipython_custom_shell.py,sha256=
|
16
|
+
ripple_down_rules/user_interface/ipython_custom_shell.py,sha256=yp-F8YRWGhj1PLB33HE6vJkdYWFN5Zn2244S2DUWRTM,6576
|
17
17
|
ripple_down_rules/user_interface/object_diagram.py,sha256=FEa2HaYR9QmTE6NsOwBvZ0jqmu3DKyg6mig2VE5ZP4Y,4956
|
18
18
|
ripple_down_rules/user_interface/prompt.py,sha256=JceEUGYsd0lIvd-v2y3D3swoo96_C0lxfp3CxM7Vfts,8900
|
19
19
|
ripple_down_rules/user_interface/template_file_creator.py,sha256=kwBbFLyN6Yx2NTIHPSwOoytWgbJDYhgrUOVFw_jkDQ4,13522
|
20
|
-
ripple_down_rules-0.5.
|
21
|
-
ripple_down_rules-0.5.
|
22
|
-
ripple_down_rules-0.5.
|
23
|
-
ripple_down_rules-0.5.
|
24
|
-
ripple_down_rules-0.5.
|
20
|
+
ripple_down_rules-0.5.95.dist-info/licenses/LICENSE,sha256=ixuiBLtpoK3iv89l7ylKkg9rs2GzF9ukPH7ynZYzK5s,35148
|
21
|
+
ripple_down_rules-0.5.95.dist-info/METADATA,sha256=5sPvCDBc_3yV4wBp5f6YRDtQkmNrd1-d_Ce7ijm6NZ0,48214
|
22
|
+
ripple_down_rules-0.5.95.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
23
|
+
ripple_down_rules-0.5.95.dist-info/top_level.txt,sha256=VeoLhEhyK46M1OHwoPbCQLI1EifLjChqGzhQ6WEUqeM,18
|
24
|
+
ripple_down_rules-0.5.95.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|