ripple-down-rules 0.6.43__py3-none-any.whl → 0.6.45__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.
@@ -1,4 +1,4 @@
1
- __version__ = "0.6.43"
1
+ __version__ = "0.6.45"
2
2
 
3
3
  import logging
4
4
  logger = logging.Logger("rdr")
ripple_down_rules/rdr.py CHANGED
@@ -45,7 +45,7 @@ from .utils import draw_tree, make_set, SubclassJSONSerializer, make_list, get_t
45
45
  is_value_conflicting, extract_function_source, extract_imports, get_full_class_name, \
46
46
  is_iterable, str_to_snake_case, get_import_path_from_path, get_imports_from_types, render_tree, \
47
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
48
+ get_and_import_python_module, get_and_import_python_modules_in_a_package, get_type_from_type_hint
49
49
 
50
50
 
51
51
  class RippleDownRules(SubclassJSONSerializer, ABC):
@@ -217,10 +217,10 @@ class RippleDownRules(SubclassJSONSerializer, ABC):
217
217
  if os.path.exists(json_file + ".json"):
218
218
  rdr = cls.from_json_file(json_file)
219
219
  try:
220
+ acronym = cls.get_acronym().lower()
221
+ python_file_name = get_file_that_ends_with(model_dir, f"_{acronym}.py")
222
+ python_file_path = os.path.join(model_dir, python_file_name)
220
223
  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
224
  rdr = cls.from_python(model_dir, parent_package_name=package_name, python_file_path=python_file_path)
225
225
  else:
226
226
  rdr.update_from_python(model_dir, package_name=package_name)
@@ -886,22 +886,52 @@ class RDRWithCodeWriter(RippleDownRules, ABC):
886
886
  self.update_rdr_metadata_from_python(main_module)
887
887
 
888
888
  functions_source = extract_function_source(defs_module.__file__,
889
- all_func_names, include_signature=False)
889
+ all_func_names, include_signature=True)
890
890
  scope = extract_imports(defs_module.__file__, package_name=package_name)
891
891
 
892
+ cases_source, cases_scope = None, None
893
+ if cases_module:
894
+ with open(cases_module.__file__, "r") as f:
895
+ cases_source = f.read()
896
+ cases_scope = extract_imports(cases_module.__file__, package_name=package_name)
897
+
898
+ with open(main_module.__file__, "r") as f:
899
+ main_source = f.read()
900
+ main_scope = extract_imports(main_module.__file__, package_name=package_name)
901
+ attribute_name_line = [l for l in main_source.split('\n') if "attribute_name = " in l]
902
+ conclusion_name = None
903
+ if len(attribute_name_line) > 0:
904
+ conclusion_name = eval(attribute_name_line[0].split('=')[-1].strip(), main_scope)
905
+
892
906
  for rule in all_rules:
893
907
  if rule.conditions is not None:
894
908
  conditions_wrapper_func_name = rule.generated_conditions_function_name
895
909
  user_input = functions_source[conditions_wrapper_func_name]
910
+ user_input = '\n'.join(user_input.split("\n")[1:]) # Remove the function signature line
896
911
  rule.conditions = CallableExpression(user_input, (bool,), scope=scope)
897
912
  if cases_module:
898
- rule.corner_case_metadata = cases_module.__dict__.get(rule.generated_corner_case_object_name, None)
913
+ try:
914
+ rule.corner_case_metadata = cases_module.__dict__[rule.generated_corner_case_object_name]
915
+ except KeyError:
916
+ case_def_lines = [l for l in cases_source.split('\n') if rule.generated_corner_case_object_name in l]
917
+ if len(case_def_lines) > 0:
918
+ case_def_line = case_def_lines[0].split('=')[-1].strip()
919
+ rule.corner_case_metadata = eval(case_def_line, cases_scope)
920
+
899
921
  if not isinstance(rule, MultiClassStopRule):
900
- rule.conclusion_name = main_module.attribute_name
901
- conclusion_wrapper_func_name = rule.generated_conclusion_function_name
902
- user_input = functions_source[conclusion_wrapper_func_name]
922
+ if conclusion_name:
923
+ rule.conclusion_name = conclusion_name
924
+ user_input = functions_source[rule.generated_conclusion_function_name]
925
+ split_user_input = user_input.split("\n")
926
+ user_input = '\n'.join(split_user_input[1:])
903
927
  conclusion_func = defs_module.__dict__.get(rule.generated_conclusion_function_name)
904
- conclusion_type = get_function_return_type(conclusion_func)
928
+ if conclusion_func is None:
929
+ function_signature = split_user_input[0]
930
+ return_type_hint_str = function_signature.split('->')[-1].strip(' :')
931
+ return_type_hint = eval(return_type_hint_str, scope)
932
+ conclusion_type = get_type_from_type_hint(return_type_hint)
933
+ else:
934
+ conclusion_type = get_function_return_type(conclusion_func)
905
935
  rule.conclusion = CallableExpression(user_input, conclusion_type, scope=scope,
906
936
  mutually_exclusive=self.mutually_exclusive)
907
937
 
@@ -168,20 +168,23 @@ 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
- print(f"Could not import {module_name}: {e}")
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 package_name is not None and node.level > 0: # Handle relative imports
179
- module_rel_path = Path(os.path.join(file_path, *['..'] * node.level, module_name)).resolve()
180
- idx = str(module_rel_path).rfind(package_name)
181
- if idx != -1:
182
- module_name = str(module_rel_path)[idx:].replace(os.path.sep, '.')
183
- module = importlib.import_module(module_name, package=package_name)
184
- scope[asname] = getattr(module, name)
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())
180
+ try:
181
+ module = importlib.import_module(module_name, package=package_name)
182
+ except ModuleNotFoundError:
183
+ module = importlib.import_module(f"{package_name}.{module_name}")
184
+ if name == "*":
185
+ scope.update(module.__dict__)
186
+ else:
187
+ scope[asname] = getattr(module, name)
185
188
  except (ImportError, AttributeError) as e:
186
189
  logger.warning(f"Could not import {module_name}: {e} while extracting imports from {file_path}")
187
190
 
@@ -782,10 +785,14 @@ def get_function_return_type(func: Callable) -> Union[Type, None, Tuple[Type, ..
782
785
  if sig.return_annotation == inspect.Signature.empty:
783
786
  return None
784
787
  type_hint = sig.return_annotation
788
+ return get_type_from_type_hint(type_hint)
789
+
790
+
791
+ def get_type_from_type_hint(type_hint: Type) -> Union[Type, Tuple[Type, ...]]:
785
792
  origin = get_origin(type_hint)
786
793
  args = get_args(type_hint)
787
794
  if origin not in [list, set, None, Union]:
788
- raise TypeError(f"{origin} is not a handled return type for function {func.__name__}")
795
+ raise TypeError(f"{origin} is not a handled return type for type hint {type_hint}")
789
796
  if origin is None:
790
797
  return typing_to_python_type(type_hint)
791
798
  if args is None or len(args) == 0:
@@ -2091,7 +2098,10 @@ def render_tree(root: Node, use_dot_exporter: bool = False,
2091
2098
  else:
2092
2099
  filename = filename or "rule_tree"
2093
2100
  de.to_dotfile(f"{filename}{'.dot'}")
2094
- de.to_picture(f"{filename}{'.svg'}")
2101
+ try:
2102
+ de.to_picture(f"{filename}{'.svg'}")
2103
+ except FileNotFoundError as e:
2104
+ logger.warning(f"{e}")
2095
2105
 
2096
2106
 
2097
2107
  def draw_tree(root: Node, fig: Figure):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ripple_down_rules
3
- Version: 0.6.43
3
+ Version: 0.6.45
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=NAOJdOIPnZXrnWLryxT1ZsFVSXmALEqXeTLcaySBVa8,99
1
+ ripple_down_rules/__init__.py,sha256=Z5fiv4M_TwRxBMIvhX3FBYkZZinOcnuaS0BLy7iHusI,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=wK6Altc7YNP9JR_mUrKignTkojq2kUy9L9g0g9_c7nM,81626
4
+ ripple_down_rules/rdr.py,sha256=FgM2Fww2NEn0AyRLR8Nw6OBSj9R5ke13l4veqtm0Hww,83293
5
5
  ripple_down_rules/rdr_decorators.py,sha256=xoBGsIJMkJYUdsrsEaPZqoAsGuXkuVZAKCoP-xD2Iv8,11668
6
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=lMRJoCtrbP6YSMqmgnqB6hY9UyQtn-Db-syUMoLzpUU,80035
8
+ ripple_down_rules/utils.py,sha256=ODmLlSqqSppzsAwsM0udKJVh__ERv4T8fl3WVmrKaVY,80336
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.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,,
20
+ ripple_down_rules-0.6.45.dist-info/licenses/LICENSE,sha256=ixuiBLtpoK3iv89l7ylKkg9rs2GzF9ukPH7ynZYzK5s,35148
21
+ ripple_down_rules-0.6.45.dist-info/METADATA,sha256=Mn4UYgmCtgMHMUl4tLOV9mJnSrawWHnbaKm_EbUylNM,48294
22
+ ripple_down_rules-0.6.45.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
23
+ ripple_down_rules-0.6.45.dist-info/top_level.txt,sha256=VeoLhEhyK46M1OHwoPbCQLI1EifLjChqGzhQ6WEUqeM,18
24
+ ripple_down_rules-0.6.45.dist-info/RECORD,,