ripple-down-rules 0.4.7__py3-none-any.whl → 0.4.9__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.
@@ -16,14 +16,27 @@ from dataclasses import is_dataclass, fields
16
16
  from enum import Enum
17
17
  from textwrap import dedent
18
18
  from types import NoneType
19
+ from typing import List
20
+
21
+ try:
22
+ import matplotlib
23
+ from matplotlib import pyplot as plt
24
+ Figure = plt.Figure
25
+ except ImportError as e:
26
+ matplotlib = None
27
+ plt = None
28
+ Figure = None
29
+ logging.debug(f"{e}: matplotlib is not installed")
30
+
31
+ try:
32
+ import networkx as nx
33
+ except ImportError as e:
34
+ nx = None
35
+ logging.debug(f"{e}: networkx is not installed")
19
36
 
20
- import matplotlib
21
- import networkx as nx
22
37
  import requests
23
38
  from anytree import Node, RenderTree
24
39
  from anytree.exporter import DotExporter
25
- from matplotlib import pyplot as plt
26
- from rospy import logwarn
27
40
  from sqlalchemy import MetaData, inspect
28
41
  from sqlalchemy.orm import Mapped, registry, class_mapper, DeclarativeBase as SQLTable, Session
29
42
  from tabulate import tabulate
@@ -107,9 +120,12 @@ def get_imports_from_scope(scope: Dict[str, Any]) -> List[str]:
107
120
  return imports
108
121
 
109
122
 
110
- def extract_imports(file_path):
111
- with open(file_path, "r") as f:
112
- tree = ast.parse(f.read(), filename=file_path)
123
+ def extract_imports(file_path: Optional[str] = None, tree: Optional[ast.AST] = None) -> Dict[str, Any]:
124
+ if tree is None:
125
+ if file_path is None:
126
+ raise ValueError("Either file_path or tree must be provided")
127
+ with open(file_path, "r") as f:
128
+ tree = ast.parse(f.read(), filename=file_path)
113
129
 
114
130
  scope = {}
115
131
 
@@ -131,7 +147,7 @@ def extract_imports(file_path):
131
147
  module = importlib.import_module(module_name)
132
148
  scope[asname] = getattr(module, name)
133
149
  except (ImportError, AttributeError) as e:
134
- logwarn(f"Could not import {module_name}: {e} while extracting imports from {file_path}")
150
+ logging.warning(f"Could not import {module_name}: {e} while extracting imports from {file_path}")
135
151
 
136
152
  return scope
137
153
 
@@ -162,7 +178,7 @@ def extract_function_source(file_path: str,
162
178
  functions_source: Dict[str, Union[str, List[str]]] = {}
163
179
  line_numbers = []
164
180
  for node in tree.body:
165
- if isinstance(node, ast.FunctionDef) and node.name in function_names:
181
+ if isinstance(node, ast.FunctionDef) and (node.name in function_names or len(function_names) == 0):
166
182
  # Get the line numbers of the function
167
183
  lines = source.splitlines()
168
184
  func_lines = lines[node.lineno - 1:node.end_lineno]
@@ -170,9 +186,9 @@ def extract_function_source(file_path: str,
170
186
  func_lines = func_lines[1:]
171
187
  line_numbers.append((node.lineno, node.end_lineno))
172
188
  functions_source[node.name] = dedent("\n".join(func_lines)) if join_lines else func_lines
173
- if len(functions_source) == len(function_names):
189
+ if len(functions_source) >= len(function_names):
174
190
  break
175
- if len(functions_source) != len(function_names):
191
+ if len(functions_source) < len(function_names):
176
192
  raise ValueError(f"Could not find all functions in {file_path}: {function_names} not found,"
177
193
  f"functions not found: {set(function_names) - set(functions_source.keys())}")
178
194
  if return_line_numbers:
@@ -889,8 +905,8 @@ class SubclassJSONSerializer:
889
905
  if not filename.endswith(".json"):
890
906
  filename += ".json"
891
907
  with open(filename, "r") as f:
892
- scrdr_json = json.load(f)
893
- deserialized_obj = cls.from_json(scrdr_json)
908
+ rdr_json = json.load(f)
909
+ deserialized_obj = cls.from_json(rdr_json)
894
910
  cls.data_class_refs.clear()
895
911
  return deserialized_obj
896
912
 
@@ -937,9 +953,6 @@ class SubclassJSONSerializer:
937
953
 
938
954
  raise ValueError("Unknown type {}".format(data["_type"]))
939
955
 
940
- save = to_json_file
941
- load = from_json_file
942
-
943
956
 
944
957
  def _pickle_thread(thread_obj) -> Any:
945
958
  """Return a plain object with user-defined attributes but no thread behavior."""
@@ -1082,24 +1095,29 @@ def get_origin_and_args_from_type_hint(type_hint: Type) -> Tuple[Optional[Type],
1082
1095
  return origin, args
1083
1096
 
1084
1097
 
1085
- def table_rows_as_str(row_dict: Dict[str, Any], columns_per_row: int = 9):
1098
+ def table_rows_as_str(row_dicts: List[Dict[str, Any]], columns_per_row: int = 20):
1086
1099
  """
1087
1100
  Print a table row.
1088
1101
 
1089
- :param row_dict: The row to print.
1102
+ :param row_dicts: The rows to print.
1090
1103
  :param columns_per_row: The maximum number of columns per row.
1091
1104
  """
1092
- all_items = list(row_dict.items())
1105
+ all_row_dicts_items = [list(row_dict.items()) for row_dict in row_dicts]
1093
1106
  # make items a list of n rows such that each row has a max size of 4
1094
- all_items = [all_items[i:i + columns_per_row] for i in range(0, len(all_items), columns_per_row)]
1107
+ all_items = [all_items[i:i + columns_per_row] for all_items in all_row_dicts_items
1108
+ for i in range(0, len(all_items), columns_per_row)]
1095
1109
  keys = [list(map(lambda i: i[0], row)) for row in all_items]
1096
1110
  values = [list(map(lambda i: i[1], row)) for row in all_items]
1111
+ zipped_keys = list(zip(*keys))
1112
+ zipped_values = list(zip(*values))
1113
+ keys_values = [list(zip(zipped_keys[i], zipped_values[i])) for i in range(len(zipped_keys))]
1114
+ keys_values = [list(r[0]) + list(r[1]) if len(r) > 1 else r[0] for r in keys_values]
1097
1115
  all_table_rows = []
1098
- for row_keys, row_values in zip(keys, values):
1099
- row_values = [str(v) if v is not None else "" for v in row_values]
1100
- row_values = [v.lower() if v in ["True", "False"] else v for v in row_values]
1101
- table = tabulate([row_values], headers=row_keys, tablefmt='plain', maxcolwidths=[20] * len(row_keys))
1102
- all_table_rows.append(table)
1116
+ row_values = [list(map(lambda v: str(v) if v is not None else "", row)) for row in keys_values]
1117
+ row_values = [list(map(lambda v: v[:150] + '...' if len(v) > 150 else v, row)) for row in row_values]
1118
+ row_values = [list(map(lambda v: v.lower() if v in ["True", "False"] else v, row)) for row in row_values]
1119
+ table = tabulate(row_values, tablefmt='simple_grid', maxcolwidths=[150] * 2)
1120
+ all_table_rows.append(table)
1103
1121
  return "\n".join(all_table_rows)
1104
1122
 
1105
1123
 
@@ -1348,7 +1366,7 @@ def render_tree(root: Node, use_dot_exporter: bool = False,
1348
1366
  de.to_picture(f"{filename}{'.png'}")
1349
1367
 
1350
1368
 
1351
- def draw_tree(root: Node, fig: plt.Figure):
1369
+ def draw_tree(root: Node, fig: Figure):
1352
1370
  """
1353
1371
  Draw the tree using matplotlib and networkx.
1354
1372
  """
@@ -1372,3 +1390,25 @@ def draw_tree(root: Node, fig: plt.Figure):
1372
1390
  nx.draw_networkx_edge_labels(graph, pos, edge_labels=nx.get_edge_attributes(graph, 'weight'),
1373
1391
  ax=fig.gca(), rotate=False, clip_on=False)
1374
1392
  plt.pause(0.1)
1393
+
1394
+
1395
+ def encapsulate_code_lines_into_a_function(code_lines: List[str], function_name: str, function_signature: str,
1396
+ func_doc: str, case_query: CaseQuery) -> str:
1397
+ """
1398
+ Encapsulate the given code lines into a function with the specified name, signature, and docstring.
1399
+
1400
+ :param code_lines: The lines of code to include in the user input.
1401
+ :param function_name: The name of the function to include in the user input.
1402
+ :param function_signature: The function signature to include in the user input.
1403
+ :param func_doc: The function docstring to include in the user input.
1404
+ :param case_query: The case query object.
1405
+ """
1406
+ code = '\n'.join(code_lines)
1407
+ code = encapsulate_user_input(code, function_signature, func_doc)
1408
+ if case_query.is_function:
1409
+ args = "**case"
1410
+ else:
1411
+ args = "case"
1412
+ if f"return {function_name}({args})" not in code:
1413
+ code = code.strip() + f"\nreturn {function_name}({args})"
1414
+ return code
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ripple_down_rules
3
- Version: 0.4.7
3
+ Version: 0.4.9
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
@@ -682,21 +682,23 @@ Classifier: Programming Language :: Python :: 3
682
682
  Description-Content-Type: text/markdown
683
683
  License-File: LICENSE
684
684
  Requires-Dist: anytree>=2.8.0
685
- Requires-Dist: pandas>=2.0.3
686
- Requires-Dist: networkx>=3.1
687
685
  Requires-Dist: ordered_set>=4
688
686
  Requires-Dist: pygraphviz>=1.7
689
- Requires-Dist: ucimlrepo>=0.0.7
690
687
  Requires-Dist: typing-extensions>=4.12.2
691
- Requires-Dist: matplotlib>=3.7.5
692
- Requires-Dist: sqlalchemy
693
- Requires-Dist: pyqt6
694
- Requires-Dist: qtconsole
695
688
  Requires-Dist: graphviz
696
689
  Requires-Dist: tabulate
697
690
  Requires-Dist: ipython
698
691
  Requires-Dist: requests
699
692
  Requires-Dist: colorama
693
+ Requires-Dist: pygments
694
+ Requires-Dist: sqlalchemy
695
+ Requires-Dist: pandas
696
+ Provides-Extra: viz
697
+ Requires-Dist: networkx>=3.1; extra == "viz"
698
+ Requires-Dist: matplotlib>=3.7.5; extra == "viz"
699
+ Provides-Extra: gui
700
+ Requires-Dist: pyqt6; extra == "gui"
701
+ Requires-Dist: qtconsole; extra == "gui"
700
702
  Dynamic: license-file
701
703
 
702
704
  # Ripple Down Rules (RDR)
@@ -0,0 +1,26 @@
1
+ ripple_down_rules/__init__.py,sha256=PUnq-y-UONNX6u9U669iIwMK6S5qMXYECFClTLPBrbI,99
2
+ ripple_down_rules/datasets.py,sha256=fJbZ7V-UUYTu5XVVpFinTbuzN3YePCnUB01L3AyZVM8,6837
3
+ ripple_down_rules/experts.py,sha256=9Vc3vx0uhDPy3YlNjwKuWJLl_A-kubRPUU6bMvQhaAg,13237
4
+ ripple_down_rules/failures.py,sha256=E6ajDUsw3Blom8eVLbA7d_Qnov2conhtZ0UmpQ9ZtSE,302
5
+ ripple_down_rules/helpers.py,sha256=TvTJU0BA3dPcAyzvZFvAu7jZqsp8Lu0HAAwvuizlGjg,2018
6
+ ripple_down_rules/rdr.py,sha256=E1OiiZClQyAfGjL64ID-MWYFO4-h8iUAX-Vm9qrOoeQ,48727
7
+ ripple_down_rules/rdr_decorators.py,sha256=pYCKLgMKgQ6x_252WQtF2t4ZNjWPBxnaWtJ6TpGdcc0,7820
8
+ ripple_down_rules/rules.py,sha256=TPNVMqW9T-_46BS4WemrspLg5uG8kP6tsPvWWBAzJxg,17515
9
+ ripple_down_rules/start-code-server.sh,sha256=otClk7VmDgBOX2TS_cjws6K0UwvgAUJhoA0ugkPCLqQ,949
10
+ ripple_down_rules/utils.py,sha256=uS38KcFceRMzT_470DCL1M0LzETdP5RLwE7cCmfo7eI,51086
11
+ ripple_down_rules/datastructures/__init__.py,sha256=V2aNgf5C96Y5-IGghra3n9uiefpoIm_QdT7cc_C8cxQ,111
12
+ ripple_down_rules/datastructures/callable_expression.py,sha256=3EucsD3jWzekhjyzL2y0dyUsucd-aqC9glmgPL0Ubb4,12425
13
+ ripple_down_rules/datastructures/case.py,sha256=r8kjL9xP_wk84ThXusspgPMrAoed2bGQmKi54fzhmH8,15258
14
+ ripple_down_rules/datastructures/dataclasses.py,sha256=PuD-7zWqWT2p4FnGvnihHvZlZKg9A1ctnFgVYf2cs-8,8554
15
+ ripple_down_rules/datastructures/enums.py,sha256=ce7tqS0otfSTNAOwsnXlhsvIn4iW_Y_N3TNebF3YoZs,5700
16
+ ripple_down_rules/user_interface/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
+ ripple_down_rules/user_interface/gui.py,sha256=SB0gUhgReJ3yx-NEHRPMGVuNRLPRUwW8-qup-Kd4Cfo,27182
18
+ ripple_down_rules/user_interface/ipython_custom_shell.py,sha256=24MIFwqnAhC6ofObEO6x5xRWRnyQmPpPmTvxbCKBrzM,6514
19
+ ripple_down_rules/user_interface/object_diagram.py,sha256=tsB6iuLNEbHxp5lR2WjyejjWbnAX_nHF9xS8jNPOQVk,4548
20
+ ripple_down_rules/user_interface/prompt.py,sha256=AkkltdDIaioN43lkRKDPKSjJcmdSSGZDMYz7AL7X9lE,8082
21
+ ripple_down_rules/user_interface/template_file_creator.py,sha256=ycCbddy_BJP8d0Q2Sj21UzamhGtqGZuK_e73VTJqznY,13766
22
+ ripple_down_rules-0.4.9.dist-info/licenses/LICENSE,sha256=ixuiBLtpoK3iv89l7ylKkg9rs2GzF9ukPH7ynZYzK5s,35148
23
+ ripple_down_rules-0.4.9.dist-info/METADATA,sha256=T-Q5WS_rd2wJsVcip0d6-so4qlvygGnUdsYBWLVBKEE,43306
24
+ ripple_down_rules-0.4.9.dist-info/WHEEL,sha256=zaaOINJESkSfm_4HQVc5ssNzHCPXhJm0kEUakpsEHaU,91
25
+ ripple_down_rules-0.4.9.dist-info/top_level.txt,sha256=VeoLhEhyK46M1OHwoPbCQLI1EifLjChqGzhQ6WEUqeM,18
26
+ ripple_down_rules-0.4.9.dist-info/RECORD,,
@@ -1,25 +0,0 @@
1
- ripple_down_rules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- ripple_down_rules/datasets.py,sha256=fJbZ7V-UUYTu5XVVpFinTbuzN3YePCnUB01L3AyZVM8,6837
3
- ripple_down_rules/experts.py,sha256=dEZKv58sdicDByj0T0bu0q6coIBMce6o4t9gJICQy1k,6556
4
- ripple_down_rules/failures.py,sha256=E6ajDUsw3Blom8eVLbA7d_Qnov2conhtZ0UmpQ9ZtSE,302
5
- ripple_down_rules/helpers.py,sha256=TvTJU0BA3dPcAyzvZFvAu7jZqsp8Lu0HAAwvuizlGjg,2018
6
- ripple_down_rules/rdr.py,sha256=jxMvkyQ_2jdyxa5aKmvGRHvD-IJBKjsyOpxvvJbFLPE,45518
7
- ripple_down_rules/rdr_decorators.py,sha256=VdmE0JrE8j89b6Af1R1tLZiKfy3h1VCvhAUefN_FLLQ,6753
8
- ripple_down_rules/rules.py,sha256=PLNaRLn5tQbq7gNsAe-n9hTjKC80p_7MbfkZWgDxLBg,17474
9
- ripple_down_rules/utils.py,sha256=3x6BHCoqEewn40lDtUIWOMQLZ_IA0j7WnY9_YDHvs-o,49192
10
- ripple_down_rules/datastructures/__init__.py,sha256=V2aNgf5C96Y5-IGghra3n9uiefpoIm_QdT7cc_C8cxQ,111
11
- ripple_down_rules/datastructures/callable_expression.py,sha256=jA7424_mWPbOoPICW3eLMX0-ypxnsW6gOqxrJ7JpDbE,11610
12
- ripple_down_rules/datastructures/case.py,sha256=oC8OSdhXvHE-Zx1IIQlad-fsKzQQqr6MZBW24c-dbeU,15191
13
- ripple_down_rules/datastructures/dataclasses.py,sha256=GWnUF4h4zfNHSsyBIz3L9y8sLkrXRv0FK_OxzzLc8L8,8183
14
- ripple_down_rules/datastructures/enums.py,sha256=ce7tqS0otfSTNAOwsnXlhsvIn4iW_Y_N3TNebF3YoZs,5700
15
- ripple_down_rules/user_interface/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
- ripple_down_rules/user_interface/gui.py,sha256=GlVUYGpMRikrd-FjYCAamdKFAuTAeiq21ZzQvjVKJ4g,27588
17
- ripple_down_rules/user_interface/ipython_custom_shell.py,sha256=tc7ms80iPNElm9AYC6i1FlfMKkqHLT8wmOEXg_k9yAU,6275
18
- ripple_down_rules/user_interface/object_diagram.py,sha256=84JlEH0nQmtGmP8Su5iRX3ZfqByYHbVwd0BQYYPuckY,4436
19
- ripple_down_rules/user_interface/prompt.py,sha256=97s5mhmsqrFTQkfmHssYFko0SPLBDxesHoLumqZO0FA,8028
20
- ripple_down_rules/user_interface/template_file_creator.py,sha256=_CEe8H07q62YpImy1p72vXcPHkJ2_Q0n6t56K6g2gPE,12930
21
- ripple_down_rules-0.4.7.dist-info/licenses/LICENSE,sha256=ixuiBLtpoK3iv89l7ylKkg9rs2GzF9ukPH7ynZYzK5s,35148
22
- ripple_down_rules-0.4.7.dist-info/METADATA,sha256=NOxEaLxlUHlfwCGv9lgu_083JZl3ls6fcknejdagcm0,43217
23
- ripple_down_rules-0.4.7.dist-info/WHEEL,sha256=zaaOINJESkSfm_4HQVc5ssNzHCPXhJm0kEUakpsEHaU,91
24
- ripple_down_rules-0.4.7.dist-info/top_level.txt,sha256=VeoLhEhyK46M1OHwoPbCQLI1EifLjChqGzhQ6WEUqeM,18
25
- ripple_down_rules-0.4.7.dist-info/RECORD,,