ripple-down-rules 0.6.29__py3-none-any.whl → 0.6.30__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/case.py +12 -11
- ripple_down_rules/datastructures/dataclasses.py +87 -9
- ripple_down_rules/experts.py +98 -20
- ripple_down_rules/rdr.py +37 -26
- ripple_down_rules/rules.py +15 -1
- ripple_down_rules/user_interface/gui.py +59 -40
- ripple_down_rules/user_interface/ipython_custom_shell.py +36 -7
- ripple_down_rules/user_interface/prompt.py +41 -26
- ripple_down_rules/user_interface/template_file_creator.py +10 -8
- ripple_down_rules/utils.py +57 -8
- {ripple_down_rules-0.6.29.dist-info → ripple_down_rules-0.6.30.dist-info}/METADATA +1 -1
- ripple_down_rules-0.6.30.dist-info/RECORD +24 -0
- ripple_down_rules-0.6.29.dist-info/RECORD +0 -24
- {ripple_down_rules-0.6.29.dist-info → ripple_down_rules-0.6.30.dist-info}/WHEEL +0 -0
- {ripple_down_rules-0.6.29.dist-info → ripple_down_rules-0.6.30.dist-info}/licenses/LICENSE +0 -0
- {ripple_down_rules-0.6.29.dist-info → ripple_down_rules-0.6.30.dist-info}/top_level.txt +0 -0
ripple_down_rules/utils.py
CHANGED
@@ -21,8 +21,10 @@ from subprocess import check_call
|
|
21
21
|
from tempfile import NamedTemporaryFile
|
22
22
|
from textwrap import dedent
|
23
23
|
from types import NoneType
|
24
|
+
import inspect
|
24
25
|
|
25
26
|
import six
|
27
|
+
from graphviz import Source
|
26
28
|
from sqlalchemy.exc import NoInspectionAvailable
|
27
29
|
from . import logger
|
28
30
|
|
@@ -45,7 +47,7 @@ except ImportError as e:
|
|
45
47
|
|
46
48
|
import requests
|
47
49
|
from anytree import Node, RenderTree, PreOrderIter
|
48
|
-
from sqlalchemy import MetaData, inspect
|
50
|
+
from sqlalchemy import MetaData, inspect as sql_inspect
|
49
51
|
from sqlalchemy.orm import Mapped, registry, class_mapper, DeclarativeBase as SQLTable, Session
|
50
52
|
from tabulate import tabulate
|
51
53
|
from typing_extensions import Callable, Set, Any, Type, Dict, TYPE_CHECKING, get_type_hints, \
|
@@ -147,7 +149,8 @@ def extract_function_source(file_path: str,
|
|
147
149
|
function_names: List[str], join_lines: bool = True,
|
148
150
|
return_line_numbers: bool = False,
|
149
151
|
include_signature: bool = True,
|
150
|
-
as_list: bool = False
|
152
|
+
as_list: bool = False,
|
153
|
+
is_class: bool = False) \
|
151
154
|
-> Union[Dict[str, Union[str, List[str]]],
|
152
155
|
Tuple[Dict[str, Union[str, List[str]]], Dict[str, Tuple[int, int]]]]:
|
153
156
|
"""
|
@@ -160,6 +163,7 @@ def extract_function_source(file_path: str,
|
|
160
163
|
:param include_signature: Whether to include the function signature in the source code.
|
161
164
|
:param as_list: Whether to return a list of function sources instead of dict (useful when there is multiple
|
162
165
|
functions with same name).
|
166
|
+
:param is_class: Whether to also look for class definitions
|
163
167
|
:return: A dictionary mapping function names to their source code as a string if join_lines is True,
|
164
168
|
otherwise as a list of strings.
|
165
169
|
"""
|
@@ -173,8 +177,13 @@ def extract_function_source(file_path: str,
|
|
173
177
|
functions_source_list: List[Union[str, List[str]]] = []
|
174
178
|
line_numbers: Dict[str, Tuple[int, int]] = {}
|
175
179
|
line_numbers_list: List[Tuple[int, int]] = []
|
180
|
+
if is_class:
|
181
|
+
look_for_type = ast.ClassDef
|
182
|
+
else:
|
183
|
+
look_for_type = ast.FunctionDef
|
184
|
+
|
176
185
|
for node in tree.body:
|
177
|
-
if isinstance(node,
|
186
|
+
if isinstance(node, look_for_type) and (node.name in function_names or len(function_names) == 0):
|
178
187
|
# Get the line numbers of the function
|
179
188
|
lines = source.splitlines()
|
180
189
|
func_lines = lines[node.lineno - 1:node.end_lineno]
|
@@ -804,6 +813,13 @@ def get_import_path_from_path(path: str) -> Optional[str]:
|
|
804
813
|
return package_name
|
805
814
|
|
806
815
|
|
816
|
+
def get_class_file_path(cls):
|
817
|
+
"""
|
818
|
+
Get the file path of a class.
|
819
|
+
"""
|
820
|
+
return os.path.abspath(inspect.getfile(cls))
|
821
|
+
|
822
|
+
|
807
823
|
def get_function_import_data(func: Callable) -> Tuple[str, str]:
|
808
824
|
"""
|
809
825
|
Get the import path of a function.
|
@@ -1294,7 +1310,7 @@ def copy_orm_instance(instance: SQLTable) -> SQLTable:
|
|
1294
1310
|
:return: The copied instance.
|
1295
1311
|
"""
|
1296
1312
|
try:
|
1297
|
-
session: Session =
|
1313
|
+
session: Session = sql_inspect(instance).session
|
1298
1314
|
except NoInspectionAvailable:
|
1299
1315
|
session = None
|
1300
1316
|
if session is not None:
|
@@ -1846,6 +1862,24 @@ class FilteredDotExporter(object):
|
|
1846
1862
|
yield node
|
1847
1863
|
for edge in self.__iter_edges(indent, nodenamefunc, edgeattrfunc, edgetypefunc):
|
1848
1864
|
yield edge
|
1865
|
+
legend_dot_graph = """
|
1866
|
+
// Color legend as a subgraph
|
1867
|
+
subgraph cluster_legend {
|
1868
|
+
label = "Legend";
|
1869
|
+
style = dashed;
|
1870
|
+
color = gray;
|
1871
|
+
|
1872
|
+
legend_green [label="Fired->Query Related Value", shape=box, style=filled, fillcolor=green, fontcolor=black, size=0.5];
|
1873
|
+
legend_yellow [label="Fired->Some Value", shape=box, style=filled, fillcolor=yellow, fontcolor=black, size=0.5];
|
1874
|
+
legend_orange [label="Fired->Empty Value", shape=box, style=filled, fillcolor=orange, fontcolor=black, size=0.5];
|
1875
|
+
legend_red [label="Evaluated->Not Fired", shape=box, style=filled, fillcolor=red, fontcolor=black, size=0.5];
|
1876
|
+
legend_white [label="Not Evaluated", shape=box, style=filled, fillcolor=white, fontcolor=black, size=0.5];
|
1877
|
+
|
1878
|
+
// Invisible edges to arrange legend vertically
|
1879
|
+
legend_white -> legend_red -> legend_orange -> legend_yellow -> legend_green [style=invis];
|
1880
|
+
}"""
|
1881
|
+
for line in legend_dot_graph.splitlines():
|
1882
|
+
yield "%s" % (line.strip())
|
1849
1883
|
yield "}"
|
1850
1884
|
|
1851
1885
|
def __iter_options(self, indent):
|
@@ -1928,6 +1962,12 @@ class FilteredDotExporter(object):
|
|
1928
1962
|
msg = 'Could not remove temporary file %s' % dotfilename
|
1929
1963
|
logger.warning(msg)
|
1930
1964
|
|
1965
|
+
def to_source(self) -> Source:
|
1966
|
+
"""
|
1967
|
+
Return the source code of the graph as a Source object.
|
1968
|
+
"""
|
1969
|
+
return Source("\n".join(self), filename=self.name)
|
1970
|
+
|
1931
1971
|
@staticmethod
|
1932
1972
|
def esc(value):
|
1933
1973
|
"""Escape Strings."""
|
@@ -1935,7 +1975,9 @@ class FilteredDotExporter(object):
|
|
1935
1975
|
|
1936
1976
|
|
1937
1977
|
def render_tree(root: Node, use_dot_exporter: bool = False,
|
1938
|
-
filename: str = "scrdr", only_nodes: List[Node] = None, show_in_console: bool = False
|
1978
|
+
filename: str = "scrdr", only_nodes: List[Node] = None, show_in_console: bool = False,
|
1979
|
+
color_map: Optional[Callable[[Node], str]] = None,
|
1980
|
+
view: bool = False) -> None:
|
1939
1981
|
"""
|
1940
1982
|
Render the tree using the console and optionally export it to a dot file.
|
1941
1983
|
|
@@ -1944,6 +1986,8 @@ def render_tree(root: Node, use_dot_exporter: bool = False,
|
|
1944
1986
|
:param filename: The name of the file to export the tree to.
|
1945
1987
|
:param only_nodes: A list of nodes to include in the dot export.
|
1946
1988
|
:param show_in_console: Whether to print the tree to the console.
|
1989
|
+
:param color_map: A function that returns a color for certain nodes.
|
1990
|
+
:param view: Whether to view the dot file in a viewer.
|
1947
1991
|
"""
|
1948
1992
|
if not root:
|
1949
1993
|
logger.warning("No rules to render")
|
@@ -1960,10 +2004,15 @@ def render_tree(root: Node, use_dot_exporter: bool = False,
|
|
1960
2004
|
include_nodes=only_nodes,
|
1961
2005
|
nodenamefunc=unique_node_names,
|
1962
2006
|
edgeattrfunc=edge_attr_setter,
|
1963
|
-
nodeattrfunc=lambda node: f'style=filled,
|
2007
|
+
nodeattrfunc=lambda node: f'style=filled,'
|
2008
|
+
f' fillcolor={color_map(node) if color_map else node.color}',
|
1964
2009
|
)
|
1965
|
-
|
1966
|
-
|
2010
|
+
if view:
|
2011
|
+
de.to_source().view()
|
2012
|
+
else:
|
2013
|
+
filename = filename or "rule_tree"
|
2014
|
+
de.to_dotfile(f"{filename}{'.dot'}")
|
2015
|
+
de.to_picture(f"{filename}{'.svg'}")
|
1967
2016
|
|
1968
2017
|
|
1969
2018
|
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.
|
3
|
+
Version: 0.6.30
|
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
|
@@ -0,0 +1,24 @@
|
|
1
|
+
ripple_down_rules/__init__.py,sha256=97mtCfVEw1HwkdrprDGcbF2yNl3fqkWb_6oSEj-rOFo,99
|
2
|
+
ripple_down_rules/experts.py,sha256=KXwWCmDrCffu9HW3yNewqWc1e5rnPI5Rnc981w_5M7U,17896
|
3
|
+
ripple_down_rules/helpers.py,sha256=X1psHOqrb4_xYN4ssQNB8S9aRKKsqgihAyWJurN0dqk,5499
|
4
|
+
ripple_down_rules/rdr.py,sha256=KsZbAbOs8U2PL19YOjFqSer8coXkSMDL3ztIrWHmTCA,62833
|
5
|
+
ripple_down_rules/rdr_decorators.py,sha256=xoBGsIJMkJYUdsrsEaPZqoAsGuXkuVZAKCoP-xD2Iv8,11668
|
6
|
+
ripple_down_rules/rules.py,sha256=W-y4aGKrGn2Xc7fbn1PNyz_jUzufFMtYwhLYiST28Ww,29213
|
7
|
+
ripple_down_rules/start-code-server.sh,sha256=otClk7VmDgBOX2TS_cjws6K0UwvgAUJhoA0ugkPCLqQ,949
|
8
|
+
ripple_down_rules/utils.py,sha256=1fiSF4MOaOUrxlMz8sZA_e10258sMWuX5fG9WDawd2o,76674
|
9
|
+
ripple_down_rules/datastructures/__init__.py,sha256=V2aNgf5C96Y5-IGghra3n9uiefpoIm_QdT7cc_C8cxQ,111
|
10
|
+
ripple_down_rules/datastructures/callable_expression.py,sha256=IrlnufVsKrUDLVkc2owoFQ05oSOby3HiGuNXoFVj4Dw,13494
|
11
|
+
ripple_down_rules/datastructures/case.py,sha256=dfLnrjsHIVF2bgbz-4ID7OdQvw68V71btCeTK372P-g,15667
|
12
|
+
ripple_down_rules/datastructures/dataclasses.py,sha256=3vX52WrAHgVyw0LUSgSBOVFaQNTSxU8hQpdr7cW-tSg,13278
|
13
|
+
ripple_down_rules/datastructures/enums.py,sha256=CvcROl8fE7A6uTbMfs2lLpyxwS_ZFtFcQlBDDKFfoHc,6059
|
14
|
+
ripple_down_rules/user_interface/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
15
|
+
ripple_down_rules/user_interface/gui.py,sha256=K6cvA9TOXIDpk0quGCamrWqDRlvz0QruDaTj4Y4PWWI,28544
|
16
|
+
ripple_down_rules/user_interface/ipython_custom_shell.py,sha256=RLdPqPxx-a0Sh74UZWyRBuxS_OKeXJnzoDfms4i-Aus,7710
|
17
|
+
ripple_down_rules/user_interface/object_diagram.py,sha256=FEa2HaYR9QmTE6NsOwBvZ0jqmu3DKyg6mig2VE5ZP4Y,4956
|
18
|
+
ripple_down_rules/user_interface/prompt.py,sha256=WPbw_8_-8SpF2ISyRZRuFwPKBEuGC4HaX3lbCPFHhh8,10314
|
19
|
+
ripple_down_rules/user_interface/template_file_creator.py,sha256=uSbosZS15MOR3Nv7M3MrFuoiKXyP4cBId-EK3I6stHM,13660
|
20
|
+
ripple_down_rules-0.6.30.dist-info/licenses/LICENSE,sha256=ixuiBLtpoK3iv89l7ylKkg9rs2GzF9ukPH7ynZYzK5s,35148
|
21
|
+
ripple_down_rules-0.6.30.dist-info/METADATA,sha256=5y9rt2-t0p_N1BJt2_fMrLzYk0KZl5W8uDDB27LHiWw,48294
|
22
|
+
ripple_down_rules-0.6.30.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
23
|
+
ripple_down_rules-0.6.30.dist-info/top_level.txt,sha256=VeoLhEhyK46M1OHwoPbCQLI1EifLjChqGzhQ6WEUqeM,18
|
24
|
+
ripple_down_rules-0.6.30.dist-info/RECORD,,
|
@@ -1,24 +0,0 @@
|
|
1
|
-
ripple_down_rules/__init__.py,sha256=RxW-6bq3pIBXNaQQI3F99LSjv47e0QeXHfOWv0IKvdM,99
|
2
|
-
ripple_down_rules/experts.py,sha256=irsHfjs_xXljB9g4aA29OB9kXh1q9skWQmYkld-DGvY,14184
|
3
|
-
ripple_down_rules/helpers.py,sha256=X1psHOqrb4_xYN4ssQNB8S9aRKKsqgihAyWJurN0dqk,5499
|
4
|
-
ripple_down_rules/rdr.py,sha256=Azd2w8otHrmlvXw-tql7M6iaVWNhjZsxivMQ_NmbxBk,61925
|
5
|
-
ripple_down_rules/rdr_decorators.py,sha256=xoBGsIJMkJYUdsrsEaPZqoAsGuXkuVZAKCoP-xD2Iv8,11668
|
6
|
-
ripple_down_rules/rules.py,sha256=N4dEx-xyqxGZpoEYzRd9P5u97_DcDEVLY_UiNhZ4E7g,28726
|
7
|
-
ripple_down_rules/start-code-server.sh,sha256=otClk7VmDgBOX2TS_cjws6K0UwvgAUJhoA0ugkPCLqQ,949
|
8
|
-
ripple_down_rules/utils.py,sha256=TUUNwNwxjPepOl-CiLQkFLe75NKmJR87l5A0U6RecJ0,74642
|
9
|
-
ripple_down_rules/datastructures/__init__.py,sha256=V2aNgf5C96Y5-IGghra3n9uiefpoIm_QdT7cc_C8cxQ,111
|
10
|
-
ripple_down_rules/datastructures/callable_expression.py,sha256=IrlnufVsKrUDLVkc2owoFQ05oSOby3HiGuNXoFVj4Dw,13494
|
11
|
-
ripple_down_rules/datastructures/case.py,sha256=PJ7_-AdxYic6BO5z816piFODj6nU5J6Jt1YzTFH-dds,15510
|
12
|
-
ripple_down_rules/datastructures/dataclasses.py,sha256=kI3Kv8GiVR8igMgA_BlKN6djUYxC2mLecvyh19pqQQA,10998
|
13
|
-
ripple_down_rules/datastructures/enums.py,sha256=CvcROl8fE7A6uTbMfs2lLpyxwS_ZFtFcQlBDDKFfoHc,6059
|
14
|
-
ripple_down_rules/user_interface/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
15
|
-
ripple_down_rules/user_interface/gui.py,sha256=JCz6vA2kWVvRD6CupoUfMbtGz39cvUlmVnGnw_fY6OA,27635
|
16
|
-
ripple_down_rules/user_interface/ipython_custom_shell.py,sha256=yp-F8YRWGhj1PLB33HE6vJkdYWFN5Zn2244S2DUWRTM,6576
|
17
|
-
ripple_down_rules/user_interface/object_diagram.py,sha256=FEa2HaYR9QmTE6NsOwBvZ0jqmu3DKyg6mig2VE5ZP4Y,4956
|
18
|
-
ripple_down_rules/user_interface/prompt.py,sha256=nLIAviClSmVCY80vQgTazDPs4a1AYmNQmT7sksLDJpE,9449
|
19
|
-
ripple_down_rules/user_interface/template_file_creator.py,sha256=kwBbFLyN6Yx2NTIHPSwOoytWgbJDYhgrUOVFw_jkDQ4,13522
|
20
|
-
ripple_down_rules-0.6.29.dist-info/licenses/LICENSE,sha256=ixuiBLtpoK3iv89l7ylKkg9rs2GzF9ukPH7ynZYzK5s,35148
|
21
|
-
ripple_down_rules-0.6.29.dist-info/METADATA,sha256=ntefL7_Z_J2ncA_Jfo0qBt9cO5_0ax2JJM4Os1ucM98,48294
|
22
|
-
ripple_down_rules-0.6.29.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
23
|
-
ripple_down_rules-0.6.29.dist-info/top_level.txt,sha256=VeoLhEhyK46M1OHwoPbCQLI1EifLjChqGzhQ6WEUqeM,18
|
24
|
-
ripple_down_rules-0.6.29.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|