ripple-down-rules 0.5.71__py3-none-any.whl → 0.5.75__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/datastructures/dataclasses.py +3 -3
- ripple_down_rules/rdr.py +29 -22
- ripple_down_rules/rules.py +2 -3
- ripple_down_rules/utils.py +19 -10
- {ripple_down_rules-0.5.71.dist-info → ripple_down_rules-0.5.75.dist-info}/METADATA +1 -1
- {ripple_down_rules-0.5.71.dist-info → ripple_down_rules-0.5.75.dist-info}/RECORD +10 -10
- {ripple_down_rules-0.5.71.dist-info → ripple_down_rules-0.5.75.dist-info}/WHEEL +0 -0
- {ripple_down_rules-0.5.71.dist-info → ripple_down_rules-0.5.75.dist-info}/licenses/LICENSE +0 -0
- {ripple_down_rules-0.5.71.dist-info → ripple_down_rules-0.5.75.dist-info}/top_level.txt +0 -0
ripple_down_rules/__init__.py
CHANGED
@@ -9,7 +9,7 @@ from omegaconf import MISSING
|
|
9
9
|
from sqlalchemy.orm import DeclarativeBase as SQLTable
|
10
10
|
from typing_extensions import Any, Optional, Dict, Type, Tuple, Union, List, get_origin, Set, Callable
|
11
11
|
|
12
|
-
from ..utils import get_method_name,
|
12
|
+
from ..utils import get_method_name, get_function_import_data, get_function_representation
|
13
13
|
from .callable_expression import CallableExpression
|
14
14
|
from .case import create_case, Case
|
15
15
|
from ..utils import copy_case, make_list, make_set, get_origin_and_args_from_type_hint, get_value_type_from_type_hint, \
|
@@ -274,9 +274,9 @@ class CaseFactoryMetaData:
|
|
274
274
|
factory_method_repr = None
|
275
275
|
scenario_repr = None
|
276
276
|
if self.factory_method is not None:
|
277
|
-
|
277
|
+
factory_method_repr = get_function_representation(self.factory_method)
|
278
278
|
if self.scenario is not None:
|
279
|
-
|
279
|
+
scenario_repr = get_function_representation(self.scenario)
|
280
280
|
return (f"CaseFactoryMetaData("
|
281
281
|
f"factory_method={factory_method_repr}, "
|
282
282
|
f"factory_idx={self.factory_idx}, "
|
ripple_down_rules/rdr.py
CHANGED
@@ -39,7 +39,7 @@ except ImportError as e:
|
|
39
39
|
from .utils import draw_tree, make_set, copy_case, \
|
40
40
|
SubclassJSONSerializer, make_list, get_type_from_string, \
|
41
41
|
is_conflicting, get_imports_from_scope, extract_function_source, extract_imports, get_full_class_name, \
|
42
|
-
is_iterable, str_to_snake_case, get_import_path_from_path
|
42
|
+
is_iterable, str_to_snake_case, get_import_path_from_path, get_imports_from_types
|
43
43
|
|
44
44
|
|
45
45
|
class RippleDownRules(SubclassJSONSerializer, ABC):
|
@@ -401,12 +401,9 @@ class RippleDownRules(SubclassJSONSerializer, ABC):
|
|
401
401
|
# remove from imports if exists first
|
402
402
|
package_name = get_import_path_from_path(package_name)
|
403
403
|
name = f"{package_name}.{self.generated_python_file_name}" if package_name else self.generated_python_file_name
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
except ModuleNotFoundError:
|
408
|
-
pass
|
409
|
-
return importlib.import_module(name).classify
|
404
|
+
module = importlib.import_module(name)
|
405
|
+
importlib.reload(module)
|
406
|
+
return module.classify
|
410
407
|
|
411
408
|
|
412
409
|
class RDRWithCodeWriter(RippleDownRules, ABC):
|
@@ -434,7 +431,9 @@ class RDRWithCodeWriter(RippleDownRules, ABC):
|
|
434
431
|
rule.conditions.user_input = functions_source[f"conditions_{rule.uid}"]
|
435
432
|
rule.conditions.scope = scope
|
436
433
|
if os.path.exists(cases_path):
|
437
|
-
|
434
|
+
module = importlib.import_module(cases_import_path)
|
435
|
+
importlib.reload(module)
|
436
|
+
rule.corner_case_metadata = module.__dict__.get(f"corner_case_{rule.uid}", None)
|
438
437
|
if rule.conclusion is not None and not isinstance(rule, MultiClassStopRule):
|
439
438
|
rule.conclusion.user_input = functions_source[f"conclusion_{rule.uid}"]
|
440
439
|
rule.conclusion.scope = scope
|
@@ -471,8 +470,10 @@ class RDRWithCodeWriter(RippleDownRules, ABC):
|
|
471
470
|
# clear the files first
|
472
471
|
with open(defs_file_name, "w") as f:
|
473
472
|
f.write(defs_imports + "\n\n")
|
473
|
+
case_factory_import = get_imports_from_types([CaseFactoryMetaData])
|
474
474
|
with open(cases_file_name, "w") as cases_f:
|
475
475
|
cases_f.write("# This file contains the corner cases for the rules.\n")
|
476
|
+
cases_f.write('\n'.join(case_factory_import) + "\n\n\n")
|
476
477
|
with open(file_name, "w") as f:
|
477
478
|
imports += f"from .{self.generated_python_defs_file_name} import *\n"
|
478
479
|
f.write(imports + "\n\n")
|
@@ -482,8 +483,8 @@ class RDRWithCodeWriter(RippleDownRules, ABC):
|
|
482
483
|
f.write(f"\n\n{func_def}")
|
483
484
|
f.write(f"{' ' * 4}if not isinstance(case, Case):\n"
|
484
485
|
f"{' ' * 4} case = create_case(case, max_recursion_idx=3)\n""")
|
485
|
-
|
486
|
-
|
486
|
+
self.write_rules_as_source_code_to_file(self.start_rule, file_name, " " * 4, defs_file=defs_file_name,
|
487
|
+
cases_file=cases_file_name)
|
487
488
|
|
488
489
|
@property
|
489
490
|
@abstractmethod
|
@@ -663,7 +664,7 @@ class SingleClassRDR(RDRWithCodeWriter):
|
|
663
664
|
with open(model_dir + f"/{self.generated_python_file_name}.py", "a") as f:
|
664
665
|
f.write(f"{' ' * 4}else:\n{' ' * 8}return {self.default_conclusion}\n")
|
665
666
|
|
666
|
-
def write_rules_as_source_code_to_file(self, rule: SingleClassRule,
|
667
|
+
def write_rules_as_source_code_to_file(self, rule: SingleClassRule, filename: str, parent_indent: str = "",
|
667
668
|
defs_file: Optional[str] = None, cases_file: Optional[str] = None):
|
668
669
|
"""
|
669
670
|
Write the rules as source code to a file.
|
@@ -671,16 +672,18 @@ class SingleClassRDR(RDRWithCodeWriter):
|
|
671
672
|
if rule.conditions:
|
672
673
|
rule.write_corner_case_as_source_code(cases_file)
|
673
674
|
if_clause = rule.write_condition_as_source_code(parent_indent, defs_file)
|
674
|
-
|
675
|
+
with open(filename, "a") as file:
|
676
|
+
file.write(if_clause)
|
675
677
|
if rule.refinement:
|
676
|
-
self.write_rules_as_source_code_to_file(rule.refinement,
|
678
|
+
self.write_rules_as_source_code_to_file(rule.refinement, filename, parent_indent + " ",
|
677
679
|
defs_file=defs_file, cases_file=cases_file)
|
678
680
|
|
679
681
|
conclusion_call = rule.write_conclusion_as_source_code(parent_indent, defs_file)
|
680
|
-
|
682
|
+
with open(filename, "a") as file:
|
683
|
+
file.write(conclusion_call)
|
681
684
|
|
682
685
|
if rule.alternative:
|
683
|
-
self.write_rules_as_source_code_to_file(rule.alternative,
|
686
|
+
self.write_rules_as_source_code_to_file(rule.alternative, filename, parent_indent, defs_file=defs_file,
|
684
687
|
cases_file=cases_file)
|
685
688
|
|
686
689
|
@property
|
@@ -785,26 +788,30 @@ class MultiClassRDR(RDRWithCodeWriter):
|
|
785
788
|
return self.conclusions
|
786
789
|
|
787
790
|
def write_rules_as_source_code_to_file(self, rule: Union[MultiClassTopRule, MultiClassStopRule],
|
788
|
-
|
791
|
+
filename: str, parent_indent: str = "", defs_file: Optional[str] = None,
|
789
792
|
cases_file: Optional[str] = None):
|
790
793
|
if rule == self.start_rule:
|
791
|
-
|
794
|
+
with open(filename, "a") as file:
|
795
|
+
file.write(f"{parent_indent}conclusions = set()\n")
|
792
796
|
if rule.conditions:
|
793
797
|
rule.write_corner_case_as_source_code(cases_file)
|
794
798
|
if_clause = rule.write_condition_as_source_code(parent_indent, defs_file)
|
795
|
-
|
799
|
+
with open(filename, "a") as file:
|
800
|
+
file.write(if_clause)
|
796
801
|
conclusion_indent = parent_indent
|
797
802
|
if hasattr(rule, "refinement") and rule.refinement:
|
798
|
-
self.write_rules_as_source_code_to_file(rule.refinement,
|
803
|
+
self.write_rules_as_source_code_to_file(rule.refinement, filename, parent_indent + " ",
|
799
804
|
defs_file=defs_file, cases_file=cases_file)
|
800
805
|
conclusion_indent = parent_indent + " " * 4
|
801
|
-
|
806
|
+
with open(filename, "a") as file:
|
807
|
+
file.write(f"{conclusion_indent}else:\n")
|
802
808
|
|
803
809
|
conclusion_call = rule.write_conclusion_as_source_code(conclusion_indent, defs_file)
|
804
|
-
|
810
|
+
with open(filename, "a") as file:
|
811
|
+
file.write(conclusion_call)
|
805
812
|
|
806
813
|
if rule.alternative:
|
807
|
-
self.write_rules_as_source_code_to_file(rule.alternative,
|
814
|
+
self.write_rules_as_source_code_to_file(rule.alternative, filename, parent_indent, defs_file=defs_file,
|
808
815
|
cases_file=cases_file)
|
809
816
|
|
810
817
|
@property
|
ripple_down_rules/rules.py
CHANGED
@@ -8,11 +8,11 @@ from uuid import uuid4
|
|
8
8
|
|
9
9
|
from anytree import NodeMixin
|
10
10
|
from sqlalchemy.orm import DeclarativeBase as SQLTable
|
11
|
-
from typing_extensions import List, Optional, Self, Union, Dict, Any, Tuple
|
11
|
+
from typing_extensions import List, Optional, Self, Union, Dict, Any, Tuple
|
12
12
|
|
13
13
|
from .datastructures.callable_expression import CallableExpression
|
14
14
|
from .datastructures.case import Case
|
15
|
-
from .datastructures.dataclasses import CaseFactoryMetaData,
|
15
|
+
from .datastructures.dataclasses import CaseFactoryMetaData, CaseQuery
|
16
16
|
from .datastructures.enums import RDREdge, Stop
|
17
17
|
from .utils import SubclassJSONSerializer, conclusion_to_json, get_full_class_name, get_imports_from_types
|
18
18
|
|
@@ -117,7 +117,6 @@ class Rule(NodeMixin, SubclassJSONSerializer, ABC):
|
|
117
117
|
types_to_import.add(self.corner_case_metadata.scenario)
|
118
118
|
if self.corner_case_metadata.case_conf is not None:
|
119
119
|
types_to_import.add(self.corner_case_metadata.case_conf)
|
120
|
-
types_to_import.add(CaseFactoryMetaData)
|
121
120
|
imports = get_imports_from_types(list(types_to_import))
|
122
121
|
with open(cases_file, 'a') as f:
|
123
122
|
f.write("\n".join(imports) + "\n\n\n")
|
ripple_down_rules/utils.py
CHANGED
@@ -799,7 +799,7 @@ def get_import_path_from_path(path: str) -> Optional[str]:
|
|
799
799
|
return package_name
|
800
800
|
|
801
801
|
|
802
|
-
def
|
802
|
+
def get_function_import_data(func: Callable) -> Tuple[str, str]:
|
803
803
|
"""
|
804
804
|
Get the import path of a function.
|
805
805
|
|
@@ -813,12 +813,24 @@ def get_function_import_path_and_representation(func: Callable) -> Tuple[str, st
|
|
813
813
|
func_import_path = get_import_path_from_path(dirname(func_file_path))
|
814
814
|
func_import_path = f"{func_import_path}.{func_file_name}" if func_import_path else func_file_name
|
815
815
|
if func_class_name and func_class_name != func_name:
|
816
|
-
|
817
|
-
func_representation = f"{func_class_name}.{func_name}"
|
816
|
+
func_import_name = func_class_name
|
818
817
|
else:
|
819
|
-
|
820
|
-
|
821
|
-
|
818
|
+
func_import_name = func_name
|
819
|
+
return func_import_path, func_import_name
|
820
|
+
|
821
|
+
|
822
|
+
def get_function_representation(func: Callable) -> str:
|
823
|
+
"""
|
824
|
+
Get a string representation of a function, including its module and class if applicable.
|
825
|
+
|
826
|
+
:param func: The function to represent.
|
827
|
+
:return: A string representation of the function.
|
828
|
+
"""
|
829
|
+
func_name = get_method_name(func)
|
830
|
+
func_class_name = get_method_class_name_if_exists(func)
|
831
|
+
if func_class_name and func_class_name != func_name:
|
832
|
+
return f"{func_class_name}.{func_name}"
|
833
|
+
return func_name
|
822
834
|
|
823
835
|
|
824
836
|
def get_imports_from_types(type_objs: List[Type]) -> List[str]:
|
@@ -836,10 +848,7 @@ def get_imports_from_types(type_objs: List[Type]) -> List[str]:
|
|
836
848
|
module = tp.__module__
|
837
849
|
name = tp.__qualname__
|
838
850
|
elif callable(tp):
|
839
|
-
|
840
|
-
if import_ is not None:
|
841
|
-
other_imports.append(import_)
|
842
|
-
module = None
|
851
|
+
module, name = get_function_import_data(tp)
|
843
852
|
elif hasattr(type(tp), "__module__"):
|
844
853
|
module = type(tp).__module__
|
845
854
|
name = type(tp).__qualname__
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: ripple_down_rules
|
3
|
-
Version: 0.5.
|
3
|
+
Version: 0.5.75
|
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,15 +1,15 @@
|
|
1
|
-
ripple_down_rules/__init__.py,sha256=
|
1
|
+
ripple_down_rules/__init__.py,sha256=6Ze00N3Py1dmFEMGBz3jz63qsUVLz8WzFn7qx3lJnfM,100
|
2
2
|
ripple_down_rules/experts.py,sha256=bwozulI1rv0uyaMZQqEgapDO-s8wvW0D6Jqxmvu5fik,12610
|
3
3
|
ripple_down_rules/helpers.py,sha256=v4oE7C5PfQUVJfSUs1FfLHEwrJXEHJLn4vJhJMvyCR8,4453
|
4
|
-
ripple_down_rules/rdr.py,sha256=
|
4
|
+
ripple_down_rules/rdr.py,sha256=Mqh7lDjQu6wZUcJiJ57CZ3P0-hM4WfhFuV4s1jZnRv8,51833
|
5
5
|
ripple_down_rules/rdr_decorators.py,sha256=0sk7izDB53lTKSB9fm33vQahmY_05FyCOWljyQOMB0U,9072
|
6
|
-
ripple_down_rules/rules.py,sha256=
|
6
|
+
ripple_down_rules/rules.py,sha256=ctf9yREG5l99HPFcYosjppKXTOwplZmzQbm4R1DMVaA,20107
|
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=iwfpTlsxUqLHWpYqSKwrDnEEa_FYFHYb2LugEVDH_kk,57132
|
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=1zSaXUljaH6z3SgMGzYPoDyjotNam791KpYgvxuMh90,15463
|
12
|
-
ripple_down_rules/datastructures/dataclasses.py,sha256=
|
12
|
+
ripple_down_rules/datastructures/dataclasses.py,sha256=qoTFHV8Hi-X8VtfC9VdvH4tif73YjF3dUe8dyHXTYts,10993
|
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
|
@@ -17,8 +17,8 @@ ripple_down_rules/user_interface/ipython_custom_shell.py,sha256=Jrf7NxOdlrwGXH0X
|
|
17
17
|
ripple_down_rules/user_interface/object_diagram.py,sha256=FEa2HaYR9QmTE6NsOwBvZ0jqmu3DKyg6mig2VE5ZP4Y,4956
|
18
18
|
ripple_down_rules/user_interface/prompt.py,sha256=AkkltdDIaioN43lkRKDPKSjJcmdSSGZDMYz7AL7X9lE,8082
|
19
19
|
ripple_down_rules/user_interface/template_file_creator.py,sha256=VLS9Nxg6gPNa-YYliJ_VNsTvLPlZ003EVkJ2t8zuDgE,13563
|
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.75.dist-info/licenses/LICENSE,sha256=ixuiBLtpoK3iv89l7ylKkg9rs2GzF9ukPH7ynZYzK5s,35148
|
21
|
+
ripple_down_rules-0.5.75.dist-info/METADATA,sha256=M1N-k7Zp8qzOsGlF8K4n889agx_bLu_rWO9_c-cEViQ,48214
|
22
|
+
ripple_down_rules-0.5.75.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
23
|
+
ripple_down_rules-0.5.75.dist-info/top_level.txt,sha256=VeoLhEhyK46M1OHwoPbCQLI1EifLjChqGzhQ6WEUqeM,18
|
24
|
+
ripple_down_rules-0.5.75.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|