ripple-down-rules 0.3.0__py3-none-any.whl → 0.4.0__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.
@@ -18,6 +18,8 @@ from .rdr_decorators import RDRDecorator
18
18
  def load_cached_dataset(cache_file):
19
19
  """Loads the dataset from cache if it exists."""
20
20
  dataset = {}
21
+ if '.pkl' not in cache_file:
22
+ cache_file += ".pkl"
21
23
  for key in ["features", "targets", "ids"]:
22
24
  part_file = cache_file.replace(".pkl", f"_{key}.pkl")
23
25
  if not os.path.exists(part_file):
@@ -43,6 +45,9 @@ def save_dataset_to_cache(dataset, cache_file):
43
45
 
44
46
  def get_dataset(dataset_id, cache_file: Optional[str] = None):
45
47
  """Fetches dataset from cache or downloads it if not available."""
48
+ if cache_file is not None:
49
+ if not cache_file.endswith(".pkl"):
50
+ cache_file += ".pkl"
46
51
  dataset = load_cached_dataset(cache_file) if cache_file else None
47
52
  if dataset is None:
48
53
  print("Downloading dataset...")
@@ -7,6 +7,20 @@ from typing_extensions import List, Dict, Any, Type
7
7
  from ripple_down_rules.utils import SubclassJSONSerializer
8
8
 
9
9
 
10
+ class InteractionMode(Enum):
11
+ """
12
+ The interaction mode of the RDR.
13
+ """
14
+ IPythonOnly = auto()
15
+ """
16
+ IPythonOnly mode, the mode where the user uses only an Ipython shell to interact with the RDR.
17
+ """
18
+ GUI = auto()
19
+ """
20
+ GUI mode, the mode where the user uses a GUI to interact with the RDR.
21
+ """
22
+
23
+
10
24
  class Editor(str, Enum):
11
25
  """
12
26
  The editor that is used to edit the rules.
@@ -3,15 +3,14 @@ from __future__ import annotations
3
3
  import json
4
4
  from abc import ABC, abstractmethod
5
5
 
6
- from typing_extensions import Optional, Dict, TYPE_CHECKING, List, Type, Any
6
+ from typing_extensions import Optional, TYPE_CHECKING, List
7
7
 
8
- from .datastructures.case import Case, CaseAttribute
9
8
  from .datastructures.callable_expression import CallableExpression
10
9
  from .datastructures.enums import PromptFor
11
10
  from .datastructures.dataclasses import CaseQuery
12
11
  from .datastructures.case import show_current_and_corner_cases
13
- from .prompt import prompt_user_for_expression, IPythonShell
14
- from .utils import get_all_subclasses, make_list
12
+ from .user_interface.gui import RDRCaseViewer
13
+ from .user_interface.prompt import UserPrompt
15
14
 
16
15
  if TYPE_CHECKING:
17
16
  from .rdr import Rule
@@ -66,12 +65,20 @@ class Human(Expert):
66
65
  The Human Expert class, an expert that asks the human to provide differentiating features and conclusions.
67
66
  """
68
67
 
68
+ def __init__(self, use_loaded_answers: bool = False, append: bool = False, viewer: Optional[RDRCaseViewer] = None):
69
+ """
70
+ Initialize the Human expert.
71
+
72
+ :param viewer: The RDRCaseViewer instance to use for prompting the user.
73
+ """
74
+ super().__init__(use_loaded_answers=use_loaded_answers, append=append)
75
+ self.user_prompt = UserPrompt(viewer)
76
+
69
77
  def save_answers(self, path: str):
70
78
  """
71
79
  Save the expert answers to a file.
72
80
 
73
81
  :param path: The path to save the answers to.
74
- :param append: A flag to indicate if the answers should be appended to the file or not.
75
82
  """
76
83
  if self.append:
77
84
  # read the file and append the new answers
@@ -118,7 +125,7 @@ class Human(Expert):
118
125
  if user_input:
119
126
  condition = CallableExpression(user_input, bool, scope=case_query.scope)
120
127
  else:
121
- user_input, condition = prompt_user_for_expression(case_query, PromptFor.Conditions)
128
+ user_input, condition = self.user_prompt.prompt_user_for_expression(case_query, PromptFor.Conditions)
122
129
  if not self.use_loaded_answers:
123
130
  self.all_expert_answers.append(user_input)
124
131
  case_query.conditions = condition
@@ -142,7 +149,7 @@ class Human(Expert):
142
149
  mutually_exclusive=case_query.mutually_exclusive)
143
150
  else:
144
151
  show_current_and_corner_cases(case_query.case)
145
- expert_input, expression = prompt_user_for_expression(case_query, PromptFor.Conclusion)
152
+ expert_input, expression = self.user_prompt.prompt_user_for_expression(case_query, PromptFor.Conclusion)
146
153
  self.all_expert_answers.append(expert_input)
147
154
  case_query.target = expression
148
155
  return expression
ripple_down_rules/rdr.py CHANGED
@@ -883,10 +883,12 @@ class GeneralRDR(RippleDownRules):
883
883
  f.write(f"{' ' * 4}return GeneralRDR._classify(classifiers_dict, case)\n")
884
884
 
885
885
  @property
886
- def case_type(self) -> Type:
886
+ def case_type(self) -> Optional[Type]:
887
887
  """
888
888
  :return: The type of the case (input) to the RDR classifier.
889
889
  """
890
+ if self.start_rule is None or self.start_rule.corner_case is None:
891
+ return None
890
892
  if isinstance(self.start_rule.corner_case, Case):
891
893
  return self.start_rule.corner_case._obj_type
892
894
  else:
@@ -900,10 +902,12 @@ class GeneralRDR(RippleDownRules):
900
902
  return importlib.import_module(f"{file_path.strip('./')}.{self.generated_python_file_name}").classify
901
903
 
902
904
  @property
903
- def _default_generated_python_file_name(self) -> str:
905
+ def _default_generated_python_file_name(self) -> Optional[str]:
904
906
  """
905
907
  :return: The default generated python file name.
906
908
  """
909
+ if self.start_rule is None or self.start_rule.corner_case is None:
910
+ return None
907
911
  if isinstance(self.start_rule.corner_case, Case):
908
912
  name = self.start_rule.corner_case._name
909
913
  else:
File without changes