ripple-down-rules 0.6.42__py3-none-any.whl → 0.6.43__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/rdr.py +50 -50
- ripple_down_rules/rules.py +0 -12
- ripple_down_rules/utils.py +44 -1
- {ripple_down_rules-0.6.42.dist-info → ripple_down_rules-0.6.43.dist-info}/METADATA +1 -1
- {ripple_down_rules-0.6.42.dist-info → ripple_down_rules-0.6.43.dist-info}/RECORD +9 -9
- {ripple_down_rules-0.6.42.dist-info → ripple_down_rules-0.6.43.dist-info}/WHEEL +0 -0
- {ripple_down_rules-0.6.42.dist-info → ripple_down_rules-0.6.43.dist-info}/licenses/LICENSE +0 -0
- {ripple_down_rules-0.6.42.dist-info → ripple_down_rules-0.6.43.dist-info}/top_level.txt +0 -0
ripple_down_rules/__init__.py
CHANGED
ripple_down_rules/rdr.py
CHANGED
@@ -4,10 +4,12 @@ import ast
|
|
4
4
|
import importlib
|
5
5
|
import json
|
6
6
|
import os
|
7
|
+
import sys
|
7
8
|
from abc import ABC, abstractmethod
|
8
9
|
from copy import copy
|
9
10
|
from dataclasses import is_dataclass
|
10
11
|
from io import TextIOWrapper
|
12
|
+
from os.path import dirname
|
11
13
|
from pathlib import Path
|
12
14
|
from types import NoneType, ModuleType
|
13
15
|
|
@@ -42,7 +44,8 @@ except ImportError as e:
|
|
42
44
|
from .utils import draw_tree, make_set, SubclassJSONSerializer, make_list, get_type_from_string, \
|
43
45
|
is_value_conflicting, extract_function_source, extract_imports, get_full_class_name, \
|
44
46
|
is_iterable, str_to_snake_case, get_import_path_from_path, get_imports_from_types, render_tree, \
|
45
|
-
get_types_to_import_from_func_type_hints, get_function_return_type, get_file_that_ends_with
|
47
|
+
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
|
46
49
|
|
47
50
|
|
48
51
|
class RippleDownRules(SubclassJSONSerializer, ABC):
|
@@ -524,7 +527,10 @@ class RippleDownRules(SubclassJSONSerializer, ABC):
|
|
524
527
|
:param model_path: The path to the model directory.
|
525
528
|
:return: The name of the model.
|
526
529
|
"""
|
527
|
-
|
530
|
+
file_name = get_file_that_ends_with(model_path, f"_{cls.get_acronym().lower()}.py")
|
531
|
+
if file_name is None:
|
532
|
+
raise FileNotFoundError(f"Could not find the python file for the model in the given path: {model_path}.")
|
533
|
+
return file_name.replace('.py', '')
|
528
534
|
|
529
535
|
@property
|
530
536
|
def generated_python_file_name(self) -> str:
|
@@ -871,54 +877,27 @@ class RDRWithCodeWriter(RippleDownRules, ABC):
|
|
871
877
|
if not isinstance(rule, MultiClassStopRule)]
|
872
878
|
all_func_names = condition_func_names + conclusion_func_names
|
873
879
|
|
874
|
-
|
875
|
-
|
876
|
-
|
877
|
-
|
878
|
-
|
879
|
-
else:
|
880
|
-
main_file_path = python_file_path
|
881
|
-
if not os.path.exists(main_file_path):
|
882
|
-
raise ModuleNotFoundError(main_file_path)
|
883
|
-
self.generated_python_file_name = Path(main_file_path).name.replace(".py", "")
|
884
|
-
|
885
|
-
defs_file_path = main_file_path.replace(".py", "_defs.py")
|
886
|
-
defs_file_name = Path(defs_file_path).name.replace(".py", "")
|
880
|
+
main_module, defs_module, cases_module = self.get_and_import_model_python_modules(
|
881
|
+
model_dir,
|
882
|
+
python_file_path=python_file_path,
|
883
|
+
parent_package_name=package_name)
|
884
|
+
self.generated_python_file_name = Path(main_module.__file__).name.replace(".py", "")
|
887
885
|
|
888
|
-
|
889
|
-
cases_file_name = Path(cases_path).name.replace(".py", "")
|
890
|
-
model_import_path = get_import_path_from_path(model_dir)
|
891
|
-
cases_import_path = f"{model_import_path}.{cases_file_name}" if model_import_path \
|
892
|
-
else cases_file_name
|
893
|
-
if os.path.exists(cases_path):
|
894
|
-
cases_module = importlib.import_module(cases_import_path, package=package_name)
|
895
|
-
importlib.reload(cases_module)
|
896
|
-
else:
|
897
|
-
cases_module = None
|
898
|
-
|
899
|
-
defs_import_path = f"{model_import_path}.{defs_file_name}" if model_import_path \
|
900
|
-
else defs_file_name
|
901
|
-
defs_module = importlib.import_module(defs_import_path, package=package_name)
|
902
|
-
importlib.reload(defs_module)
|
886
|
+
self.update_rdr_metadata_from_python(main_module)
|
903
887
|
|
904
|
-
|
905
|
-
|
906
|
-
|
907
|
-
main_module = importlib.import_module(main_import_path, package=package_name)
|
908
|
-
importlib.reload(main_module)
|
888
|
+
functions_source = extract_function_source(defs_module.__file__,
|
889
|
+
all_func_names, include_signature=False)
|
890
|
+
scope = extract_imports(defs_module.__file__, package_name=package_name)
|
909
891
|
|
910
|
-
self.start_rule.conclusion_name = main_module.attribute_name
|
911
|
-
self.update_rdr_metadata_from_python(main_module)
|
912
|
-
functions_source = extract_function_source(defs_file_path, all_func_names, include_signature=False)
|
913
|
-
scope = extract_imports(defs_file_path, package_name=package_name)
|
914
892
|
for rule in all_rules:
|
915
893
|
if rule.conditions is not None:
|
916
894
|
conditions_wrapper_func_name = rule.generated_conditions_function_name
|
917
895
|
user_input = functions_source[conditions_wrapper_func_name]
|
918
896
|
rule.conditions = CallableExpression(user_input, (bool,), scope=scope)
|
919
|
-
if
|
897
|
+
if cases_module:
|
920
898
|
rule.corner_case_metadata = cases_module.__dict__.get(rule.generated_corner_case_object_name, None)
|
921
899
|
if not isinstance(rule, MultiClassStopRule):
|
900
|
+
rule.conclusion_name = main_module.attribute_name
|
922
901
|
conclusion_wrapper_func_name = rule.generated_conclusion_function_name
|
923
902
|
user_input = functions_source[conclusion_wrapper_func_name]
|
924
903
|
conclusion_func = defs_module.__dict__.get(rule.generated_conclusion_function_name)
|
@@ -926,6 +905,34 @@ class RDRWithCodeWriter(RippleDownRules, ABC):
|
|
926
905
|
rule.conclusion = CallableExpression(user_input, conclusion_type, scope=scope,
|
927
906
|
mutually_exclusive=self.mutually_exclusive)
|
928
907
|
|
908
|
+
@classmethod
|
909
|
+
def get_and_import_model_python_modules(cls, model_dir: str,
|
910
|
+
python_file_path: Optional[str] = None,
|
911
|
+
parent_package_name: Optional[str] = None)\
|
912
|
+
-> Tuple[ModuleType, ModuleType, ModuleType]:
|
913
|
+
"""
|
914
|
+
Get and import the python modules that contain the RDR classifier function, definitions, and corner cases.
|
915
|
+
|
916
|
+
:param model_dir: The path to the directory where the generated python files are located.
|
917
|
+
:param python_file_path: The path to the generated python file that contains the RDR classifier function.
|
918
|
+
:param parent_package_name: The name of the package that contains the RDR classifier function, this
|
919
|
+
is required in case of relative imports in the generated python file.
|
920
|
+
:return: A tuple containing the main module, defs module, and cases module.
|
921
|
+
"""
|
922
|
+
if python_file_path is None:
|
923
|
+
main_file_path = cls.get_generated_python_file_path(model_dir)
|
924
|
+
else:
|
925
|
+
main_file_path = python_file_path
|
926
|
+
if not os.path.exists(main_file_path):
|
927
|
+
raise ModuleNotFoundError(main_file_path)
|
928
|
+
|
929
|
+
defs_file_path = main_file_path.replace(".py", "_defs.py")
|
930
|
+
cases_path = main_file_path.replace(".py", "_cases.py")
|
931
|
+
|
932
|
+
main_module, defs_module, cases_module = get_and_import_python_modules_in_a_package(
|
933
|
+
[main_file_path, defs_file_path, cases_path], parent_package_name=parent_package_name)
|
934
|
+
return main_module, defs_module, cases_module
|
935
|
+
|
929
936
|
@abstractmethod
|
930
937
|
def write_rules_as_source_code_to_file(self, rule: Rule, file, parent_indent: str = "",
|
931
938
|
defs_file: Optional[str] = None, cases_file: Optional[str] = None,
|
@@ -1532,21 +1539,14 @@ class GeneralRDR(RippleDownRules):
|
|
1532
1539
|
:return: An instance of the class.
|
1533
1540
|
"""
|
1534
1541
|
if python_file_path is None:
|
1535
|
-
|
1536
|
-
main_python_file_path = os.path.join(model_dir, file_name)
|
1542
|
+
main_python_file_path = cls.get_generated_python_file_path(model_dir)
|
1537
1543
|
else:
|
1538
1544
|
main_python_file_path = python_file_path
|
1539
|
-
|
1540
|
-
main_module_import_path = get_import_path_from_path(model_dir)
|
1541
|
-
main_module_import_path = f"{main_module_import_path}.{main_python_file_name}" \
|
1542
|
-
if main_module_import_path else main_python_file_name
|
1543
|
-
main_module = importlib.import_module(main_module_import_path)
|
1544
|
-
importlib.reload(main_module)
|
1545
|
+
main_module = get_and_import_python_module(main_python_file_path, parent_package_name=parent_package_name)
|
1545
1546
|
classifiers_dict = main_module.classifiers_dict
|
1546
1547
|
start_rules_dict = {}
|
1547
1548
|
for rdr_name, rdr_module in classifiers_dict.items():
|
1548
|
-
|
1549
|
-
rdr_acronym = rdr_module_name.split('_')[-1]
|
1549
|
+
rdr_acronym = rdr_module.__name__.split('_')[-1]
|
1550
1550
|
rdr_type = cls.get_rdr_type_from_acronym(rdr_acronym)
|
1551
1551
|
rdr_model_path = main_python_file_path.replace('_rdr.py', f'_{rdr_name}_{rdr_acronym}.py')
|
1552
1552
|
rdr = rdr_type.from_python(model_dir, python_file_path=rdr_model_path, parent_package_name=parent_package_name)
|
ripple_down_rules/rules.py
CHANGED
@@ -286,16 +286,10 @@ class Rule(NodeMixin, SubclassJSONSerializer, ABC):
|
|
286
286
|
pass
|
287
287
|
|
288
288
|
def _to_json(self) -> Dict[str, Any]:
|
289
|
-
# try:
|
290
|
-
# corner_case = SubclassJSONSerializer.to_json_static(self.corner_case) if self.corner_case else None
|
291
|
-
# except Exception as e:
|
292
|
-
# logging.debug("Failed to serialize corner case to json, setting it to None. Error: %s", e)
|
293
|
-
# corner_case = None
|
294
289
|
json_serialization = {"_type": get_full_class_name(type(self)),
|
295
290
|
"conditions": self.conditions.to_json(),
|
296
291
|
"conclusion": conclusion_to_json(self.conclusion),
|
297
292
|
"parent": self.parent.json_serialization if self.parent else None,
|
298
|
-
# "corner_case": corner_case,
|
299
293
|
"conclusion_name": self.conclusion_name,
|
300
294
|
"weight": self.weight,
|
301
295
|
"uid": self.uid}
|
@@ -303,15 +297,9 @@ class Rule(NodeMixin, SubclassJSONSerializer, ABC):
|
|
303
297
|
|
304
298
|
@classmethod
|
305
299
|
def _from_json(cls, data: Dict[str, Any]) -> Rule:
|
306
|
-
# try:
|
307
|
-
# corner_case = Case.from_json(data["corner_case"])
|
308
|
-
# except Exception as e:
|
309
|
-
# logging.debug("Failed to load corner case from json, setting it to None.")
|
310
|
-
# corner_case = None
|
311
300
|
loaded_rule = cls(conditions=CallableExpression.from_json(data["conditions"]),
|
312
301
|
conclusion=CallableExpression.from_json(data["conclusion"]),
|
313
302
|
parent=cls.from_json(data["parent"]),
|
314
|
-
# corner_case=corner_case,
|
315
303
|
conclusion_name=data["conclusion_name"],
|
316
304
|
weight=data["weight"],
|
317
305
|
uid=data["uid"])
|
ripple_down_rules/utils.py
CHANGED
@@ -20,7 +20,7 @@ from pathlib import Path
|
|
20
20
|
from subprocess import check_call
|
21
21
|
from tempfile import NamedTemporaryFile
|
22
22
|
from textwrap import dedent
|
23
|
-
from types import NoneType
|
23
|
+
from types import NoneType, ModuleType
|
24
24
|
import inspect
|
25
25
|
|
26
26
|
import six
|
@@ -60,6 +60,49 @@ if TYPE_CHECKING:
|
|
60
60
|
import ast
|
61
61
|
|
62
62
|
|
63
|
+
def get_and_import_python_modules_in_a_package(file_paths: List[str],
|
64
|
+
parent_package_name: Optional[str] = None) -> List[Optional[ModuleType]]:
|
65
|
+
"""
|
66
|
+
:param file_paths: The paths to the python files to import.
|
67
|
+
:param parent_package_name: The name of the parent package to use for relative imports.
|
68
|
+
:return: The imported modules.
|
69
|
+
"""
|
70
|
+
package_path = dirname(file_paths[0])
|
71
|
+
package_import_path = get_import_path_from_path(package_path)
|
72
|
+
file_names = [Path(file_path).name.replace(".py", "") for file_path in file_paths]
|
73
|
+
module_import_paths = [
|
74
|
+
f"{package_import_path}.{file_name}" if package_import_path else file_name
|
75
|
+
for file_name in file_names
|
76
|
+
]
|
77
|
+
modules = [
|
78
|
+
importlib.import_module(module_import_path, package=parent_package_name)
|
79
|
+
if os.path.exists(file_paths[i]) else None
|
80
|
+
for i, module_import_path in enumerate(module_import_paths)
|
81
|
+
]
|
82
|
+
for module in modules:
|
83
|
+
if module is not None:
|
84
|
+
importlib.reload(module)
|
85
|
+
return modules
|
86
|
+
|
87
|
+
|
88
|
+
def get_and_import_python_module(python_file_path: str, package_import_path: Optional[str] = None,
|
89
|
+
parent_package_name: Optional[str] = None) -> ModuleType:
|
90
|
+
"""
|
91
|
+
:param python_file_path: The path to the python file to import.
|
92
|
+
:param package_import_path: The import path of the package that contains the python file.
|
93
|
+
:param parent_package_name: The name of the parent package to use for relative imports.
|
94
|
+
:return: The imported module.
|
95
|
+
"""
|
96
|
+
if package_import_path is None:
|
97
|
+
package_path = dirname(python_file_path)
|
98
|
+
package_import_path = get_import_path_from_path(package_path)
|
99
|
+
file_name = Path(python_file_path).name.replace(".py", "")
|
100
|
+
module_import_path = f"{package_import_path}.{file_name}" if package_import_path else file_name
|
101
|
+
module = importlib.import_module(module_import_path, package=parent_package_name)
|
102
|
+
importlib.reload(module)
|
103
|
+
return module
|
104
|
+
|
105
|
+
|
63
106
|
def str_to_snake_case(snake_str: str) -> str:
|
64
107
|
"""
|
65
108
|
Convert a string to snake case.
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: ripple_down_rules
|
3
|
-
Version: 0.6.
|
3
|
+
Version: 0.6.43
|
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=NAOJdOIPnZXrnWLryxT1ZsFVSXmALEqXeTLcaySBVa8,99
|
2
2
|
ripple_down_rules/experts.py,sha256=KXwWCmDrCffu9HW3yNewqWc1e5rnPI5Rnc981w_5M7U,17896
|
3
3
|
ripple_down_rules/helpers.py,sha256=X1psHOqrb4_xYN4ssQNB8S9aRKKsqgihAyWJurN0dqk,5499
|
4
|
-
ripple_down_rules/rdr.py,sha256=
|
4
|
+
ripple_down_rules/rdr.py,sha256=wK6Altc7YNP9JR_mUrKignTkojq2kUy9L9g0g9_c7nM,81626
|
5
5
|
ripple_down_rules/rdr_decorators.py,sha256=xoBGsIJMkJYUdsrsEaPZqoAsGuXkuVZAKCoP-xD2Iv8,11668
|
6
|
-
ripple_down_rules/rules.py,sha256=
|
6
|
+
ripple_down_rules/rules.py,sha256=L4Ws-x3g5ljE0GrDt4LAib2qtR1C1_Ra4cRcIB-IQDI,28702
|
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=lMRJoCtrbP6YSMqmgnqB6hY9UyQtn-Db-syUMoLzpUU,80035
|
9
9
|
ripple_down_rules/datastructures/__init__.py,sha256=V2aNgf5C96Y5-IGghra3n9uiefpoIm_QdT7cc_C8cxQ,111
|
10
10
|
ripple_down_rules/datastructures/callable_expression.py,sha256=rzMrpD5oztaCRlt3hQ2B_xZ09cSuJNkYOCePndfQJRA,13684
|
11
11
|
ripple_down_rules/datastructures/case.py,sha256=dfLnrjsHIVF2bgbz-4ID7OdQvw68V71btCeTK372P-g,15667
|
@@ -17,8 +17,8 @@ ripple_down_rules/user_interface/ipython_custom_shell.py,sha256=RLdPqPxx-a0Sh74U
|
|
17
17
|
ripple_down_rules/user_interface/object_diagram.py,sha256=FEa2HaYR9QmTE6NsOwBvZ0jqmu3DKyg6mig2VE5ZP4Y,4956
|
18
18
|
ripple_down_rules/user_interface/prompt.py,sha256=WPbw_8_-8SpF2ISyRZRuFwPKBEuGC4HaX3lbCPFHhh8,10314
|
19
19
|
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.
|
20
|
+
ripple_down_rules-0.6.43.dist-info/licenses/LICENSE,sha256=ixuiBLtpoK3iv89l7ylKkg9rs2GzF9ukPH7ynZYzK5s,35148
|
21
|
+
ripple_down_rules-0.6.43.dist-info/METADATA,sha256=H9Y0gibG6FcFb2LLUiZVwiGWFdKDlXJVY4GYkvZoBeA,48294
|
22
|
+
ripple_down_rules-0.6.43.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
23
|
+
ripple_down_rules-0.6.43.dist-info/top_level.txt,sha256=VeoLhEhyK46M1OHwoPbCQLI1EifLjChqGzhQ6WEUqeM,18
|
24
|
+
ripple_down_rules-0.6.43.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|