ripple-down-rules 0.5.95__tar.gz → 0.5.97__tar.gz

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.
Files changed (152) hide show
  1. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/PKG-INFO +1 -1
  2. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/src/ripple_down_rules/__init__.py +1 -1
  3. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/src/ripple_down_rules/datastructures/callable_expression.py +7 -1
  4. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/src/ripple_down_rules/datastructures/dataclasses.py +1 -1
  5. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/src/ripple_down_rules/rdr.py +23 -9
  6. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/src/ripple_down_rules/rdr_decorators.py +17 -7
  7. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/src/ripple_down_rules/rules.py +19 -0
  8. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/src/ripple_down_rules/utils.py +15 -1
  9. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/src/ripple_down_rules.egg-info/PKG-INFO +1 -1
  10. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/test_results/datasets_physical_object_is_a_robot/physical_object_is_a_robot_output__scrdr.py +5 -1
  11. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/test_results/datasets_physical_object_is_a_robot/physical_object_is_a_robot_output__scrdr_defs.py +4 -3
  12. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/test_results/datasets_physical_object_is_a_robot/rdr_metadata/datasets_physical_object_is_a_robot.json +8 -2
  13. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/test_results/datasets_physical_object_select_objects_that_are_parts_of_robot/physical_object_select_objects_that_are_parts_of_robot_output__mcrdr.py +1 -1
  14. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/test_results/datasets_physical_object_select_objects_that_are_parts_of_robot/physical_object_select_objects_that_are_parts_of_robot_output__mcrdr_defs.py +3 -3
  15. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/test_results/datasets_physical_object_select_objects_that_are_parts_of_robot/rdr_metadata/datasets_physical_object_select_objects_that_are_parts_of_robot.json +2 -0
  16. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/.github/workflows/build_and_deploy_doc.yml +0 -0
  17. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/.github/workflows/ci.yml +0 -0
  18. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/.github/workflows/publish-to-test-pypi.yml +0 -0
  19. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/.gitignore +0 -0
  20. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/.idea/shelf/Uncommitted_changes_before_Checkout_at_2_4_25,_6_32_PM_[Changes]/shelved.patch +0 -0
  21. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/.idea/shelf/Uncommitted_changes_before_Checkout_at_2_4_25,_6_32_PM_[Changes]1/shelved.patch +0 -0
  22. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/LICENSE +0 -0
  23. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/README.md +0 -0
  24. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/doc/_config.yml +0 -0
  25. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/doc/_toc.yml +0 -0
  26. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/doc/bibliography.md +0 -0
  27. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/doc/intro.md +0 -0
  28. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/doc/references.bib +0 -0
  29. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/doc/requirements.txt +0 -0
  30. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/examples/__init__.py +0 -0
  31. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/examples/animal_species.py +0 -0
  32. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/examples/part_containment_rdr/__init__.py +0 -0
  33. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/examples/part_containment_rdr/rdr_metadata/part_containment_rdr.json +0 -0
  34. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/examples/part_containment_rdr/robot_contained_objects_mcrdr.py +0 -0
  35. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/examples/part_containment_rdr/robot_contained_objects_mcrdr_defs.py +0 -0
  36. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/examples/part_containment_rdr/robot_rdr.py +0 -0
  37. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/examples/relational_example.py +0 -0
  38. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/images/scrdr.dot +0 -0
  39. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/images/scrdr.png +0 -0
  40. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/images/thinking_pr2.jpg +0 -0
  41. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/pyproject.toml +0 -0
  42. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/pytest.ini +0 -0
  43. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/requirements-dev-ci.txt +0 -0
  44. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/requirements-dev.txt +0 -0
  45. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/requirements-gui.txt +0 -0
  46. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/requirements-viz.txt +0 -0
  47. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/requirements.txt +0 -0
  48. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/results/complete_mcrdr_extra.dot +0 -0
  49. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/results/complete_mcrdr_extra.png +0 -0
  50. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/results/complete_mcrdr_stop_only.dot +0 -0
  51. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/results/complete_mcrdr_stop_only.png +0 -0
  52. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/results/complete_mcrdr_stop_plus_rule.dot +0 -0
  53. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/results/complete_mcrdr_stop_plus_rule.png +0 -0
  54. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/results/complete_scrdr.dot +0 -0
  55. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/results/complete_scrdr.png +0 -0
  56. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/results/complete_scrdr_2.dot +0 -0
  57. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/results/complete_scrdr_2.png +0 -0
  58. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/results/complete_scrdr_3.dot +0 -0
  59. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/results/complete_scrdr_3.png +0 -0
  60. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/results/grdr_Habitat.dot +0 -0
  61. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/results/grdr_Habitat.png +0 -0
  62. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/results/grdr_Species.dot +0 -0
  63. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/results/grdr_Species.png +0 -0
  64. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/results/mcrdr_extra.dot +0 -0
  65. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/results/mcrdr_extra.png +0 -0
  66. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/results/mcrdr_extra_classify.dot +0 -0
  67. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/results/mcrdr_extra_classify.png +0 -0
  68. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/results/mcrdr_stop_plus_rule_combined.dot +0 -0
  69. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/results/mcrdr_stop_plus_rule_combined.png +0 -0
  70. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/results/partial_mcrdr_extra.dot +0 -0
  71. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/results/partial_mcrdr_extra.png +0 -0
  72. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/results/relational_scrdr_classify.dot +0 -0
  73. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/results/relational_scrdr_classify.png +0 -0
  74. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/setup.cfg +0 -0
  75. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/src/ripple_down_rules/datastructures/__init__.py +0 -0
  76. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/src/ripple_down_rules/datastructures/case.py +0 -0
  77. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/src/ripple_down_rules/datastructures/enums.py +0 -0
  78. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/src/ripple_down_rules/experts.py +0 -0
  79. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/src/ripple_down_rules/helpers.py +0 -0
  80. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/src/ripple_down_rules/start-code-server.sh +0 -0
  81. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/src/ripple_down_rules/user_interface/__init__.py +0 -0
  82. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/src/ripple_down_rules/user_interface/gui.py +0 -0
  83. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/src/ripple_down_rules/user_interface/ipython_custom_shell.py +0 -0
  84. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/src/ripple_down_rules/user_interface/object_diagram.py +0 -0
  85. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/src/ripple_down_rules/user_interface/prompt.py +0 -0
  86. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/src/ripple_down_rules/user_interface/template_file_creator.py +0 -0
  87. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/src/ripple_down_rules.egg-info/SOURCES.txt +0 -0
  88. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/src/ripple_down_rules.egg-info/dependency_links.txt +0 -0
  89. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/src/ripple_down_rules.egg-info/requires.txt +0 -0
  90. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/src/ripple_down_rules.egg-info/top_level.txt +0 -0
  91. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/__init__.py +0 -0
  92. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/conf/__init__.py +0 -0
  93. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/conf/world/__init__.py +0 -0
  94. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/conf/world/base_config.py +0 -0
  95. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/conf/world/handles_and_containers.py +0 -0
  96. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/conftest.py +0 -0
  97. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/datasets.py +0 -0
  98. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/factories/__init__.py +0 -0
  99. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/factories/world/__init__.py +0 -0
  100. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/factories/world/handles_and_containers.py +0 -0
  101. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/test_expert_answers/correct_drawer_rdr_expert_answers_fit.json +0 -0
  102. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/test_expert_answers/drawer_cabinet_expert_answers_fit.json +0 -0
  103. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/test_expert_answers/grdr_expert_answers_classify.json +0 -0
  104. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/test_expert_answers/grdr_expert_answers_fit.json +0 -0
  105. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/test_expert_answers/grdr_expert_answers_fit_extra.json +0 -0
  106. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/test_expert_answers/grdr_expert_answers_fit_no_targets.json +0 -0
  107. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/test_expert_answers/mcrdr_expert_answers_classify.json +0 -0
  108. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/test_expert_answers/mcrdr_expert_answers_fit_no_targets.json +0 -0
  109. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/test_expert_answers/mcrdr_expert_answers_stop_only_fit.json +0 -0
  110. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/test_expert_answers/mcrdr_extra_expert_answers_classify.json +0 -0
  111. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/test_expert_answers/mcrdr_extra_expert_answers_fit.json +0 -0
  112. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/test_expert_answers/mcrdr_multi_line_expert_answers_fit.json +0 -0
  113. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/test_expert_answers/mcrdr_stop_only_answers_fit.json +0 -0
  114. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/test_expert_answers/mcrdr_stop_plus_rule_answers_fit.json +0 -0
  115. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/test_expert_answers/mcrdr_stop_plus_rule_combined_expert_answers_fit.json +0 -0
  116. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/test_expert_answers/mcrdr_stop_plus_rule_expert_answers_fit.json +0 -0
  117. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/test_expert_answers/mutagenic_expert_answers.json +0 -0
  118. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/test_expert_answers/relational_scrdr_expert_answers_classify.json +0 -0
  119. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/test_expert_answers/scrdr_expert_answers_classify.json +0 -0
  120. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/test_expert_answers/scrdr_expert_answers_fit.json +0 -0
  121. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/test_expert_answers/scrdr_expert_answers_fit_no_targets.json +0 -0
  122. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/test_expert_answers/scrdr_multi_line_expert_answers_fit.json +0 -0
  123. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/test_expert_answers/scrdr_world_expert_answers_fit.json +0 -0
  124. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/test_generated_rdrs/__init__.py +0 -0
  125. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/test_helpers/__init__.py +0 -0
  126. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/test_helpers/helpers.py +0 -0
  127. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/test_helpers/object_diagram_case_query.png +0 -0
  128. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/test_helpers/object_diagram_person.png +0 -0
  129. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/test_json_serialization.py +0 -0
  130. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/test_object_diagram.py +0 -0
  131. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/test_on_mutagenic.py +0 -0
  132. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/test_rdr.py +0 -0
  133. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/test_rdr_alchemy.py +0 -0
  134. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/test_rdr_decorators.py +0 -0
  135. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/test_rdr_helpers_rdrs.py +0 -0
  136. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/test_rdr_world/__init__.py +0 -0
  137. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/test_rdr_world/conftest.py +0 -0
  138. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/test_rdr_world/test_rdr_world.py +0 -0
  139. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/test_relational_rdr.py +0 -0
  140. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/test_relational_rdr_alchemy.py +0 -0
  141. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/test_results/datasets_physical_object_is_a_robot/__init__.py +0 -0
  142. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/test_results/datasets_physical_object_is_a_robot/physical_object_is_a_robot_rdr.py +1 -1
  143. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/test_results/datasets_physical_object_select_objects_that_are_parts_of_robot/__init__.py +0 -0
  144. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/test_results/datasets_physical_object_select_objects_that_are_parts_of_robot/physical_object_select_objects_that_are_parts_of_robot_rdr.py +1 -1
  145. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/test_sql_model.py +0 -0
  146. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/test_template_file_creator.py +0 -0
  147. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/test_user_interface/__init__.py +0 -0
  148. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/test_user_interface/test_ipython.py +0 -0
  149. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/test_user_interface/test_ipython_copilot.py +0 -0
  150. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/test_user_interface/test_prompt.py +0 -0
  151. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/test_user_interface/test_qt_gui_inline.py +0 -0
  152. {ripple_down_rules-0.5.95 → ripple_down_rules-0.5.97}/test/test_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ripple_down_rules
3
- Version: 0.5.95
3
+ Version: 0.5.97
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,4 +1,4 @@
1
- __version__ = "0.5.95"
1
+ __version__ = "0.5.97"
2
2
 
3
3
  import logging
4
4
  logger = logging.Logger("rdr")
@@ -267,10 +267,16 @@ class CallableExpression(SubclassJSONSerializer):
267
267
 
268
268
  @classmethod
269
269
  def _from_json(cls, data: Dict[str, Any]) -> CallableExpression:
270
+ scope = {}
271
+ for k, v in data['scope'].items():
272
+ try:
273
+ scope[k] = get_type_from_string(v)
274
+ except ModuleNotFoundError:
275
+ pass
270
276
  return cls(user_input=data["user_input"],
271
277
  conclusion_type=tuple(get_type_from_string(t) for t in data["conclusion_type"])
272
278
  if data["conclusion_type"] else None,
273
- scope={k: get_type_from_string(v) for k, v in data["scope"].items()},
279
+ scope=scope,
274
280
  conclusion=SubclassJSONSerializer.from_json(data["conclusion"]),
275
281
  mutually_exclusive=data["mutually_exclusive"])
276
282
 
@@ -139,7 +139,7 @@ class CaseQuery:
139
139
  attribute_types_str = f"Union[{', '.join([t.__name__ for t in self.core_attribute_type])}]"
140
140
  else:
141
141
  attribute_types_str = self.core_attribute_type[0].__name__
142
- if list in self.attribute_type:
142
+ if all(t in self.attribute_type for t in [list, set]) and len(self.core_attribute_type) > 2:
143
143
  return f"List[{attribute_types_str}]"
144
144
  else:
145
145
  return attribute_types_str
@@ -4,6 +4,7 @@ import importlib
4
4
  import os
5
5
  from abc import ABC, abstractmethod
6
6
  from copy import copy
7
+ from types import NoneType
7
8
 
8
9
  from ripple_down_rules.datastructures.dataclasses import CaseFactoryMetaData
9
10
  from . import logger
@@ -144,7 +145,7 @@ class RippleDownRules(SubclassJSONSerializer, ABC):
144
145
  try:
145
146
  rdr.update_from_python(model_dir, package_name=package_name)
146
147
  rdr.to_json_file(json_file)
147
- except (FileNotFoundError, ValueError) as e:
148
+ except (FileNotFoundError, ValueError, SyntaxError) as e:
148
149
  logger.warning(f"Could not load the python file for the model {model_name} from {model_dir}. "
149
150
  f"Make sure the file exists and is valid.")
150
151
  rdr.save(save_dir=load_dir, model_name=model_name, package_name=package_name)
@@ -546,6 +547,8 @@ class RDRWithCodeWriter(RippleDownRules, ABC):
546
547
  main_types = set()
547
548
  main_types.add(self.case_type)
548
549
  main_types.update(make_set(self.conclusion_type))
550
+ main_types.update({Union, Optional})
551
+ defs_types.add(Union)
549
552
  main_types.update({Case, create_case})
550
553
  main_types = main_types.difference(defs_types)
551
554
  return main_types, defs_types, cases_types
@@ -673,12 +676,12 @@ class SingleClassRDR(RDRWithCodeWriter):
673
676
  :param case_query: The case query containing the case and the target category to compare the case with.
674
677
  """
675
678
  pred = self.evaluate(case)
676
- conclusion = pred.conclusion(case) if pred is not None else None
679
+ conclusion = pred.conclusion(case) if pred is not None else self.default_conclusion
677
680
  if pred is not None and pred.fired and case_query is not None:
678
681
  if pred.corner_case_metadata is None and conclusion is not None \
679
682
  and type(conclusion) in case_query.core_attribute_type:
680
683
  pred.corner_case_metadata = CaseFactoryMetaData.from_case_query(case_query)
681
- return conclusion if pred is not None and pred.fired else self.default_conclusion
684
+ return conclusion
682
685
 
683
686
  def evaluate(self, case: Case) -> SingleClassRule:
684
687
  """
@@ -689,9 +692,8 @@ class SingleClassRDR(RDRWithCodeWriter):
689
692
 
690
693
  def _write_to_python(self, model_dir: str, package_name: Optional[str] = None):
691
694
  super()._write_to_python(model_dir, package_name=package_name)
692
- if self.default_conclusion is not None:
693
- with open(model_dir + f"/{self.generated_python_file_name}.py", "a") as f:
694
- f.write(f"{' ' * 4}else:\n{' ' * 8}return {self.default_conclusion}\n")
695
+ with open(model_dir + f"/{self.generated_python_file_name}.py", "a") as f:
696
+ f.write(f"{' ' * 4}else:\n{' ' * 8}return {self.default_conclusion}\n")
695
697
 
696
698
  def write_rules_as_source_code_to_file(self, rule: SingleClassRule, filename: str, parent_indent: str = "",
697
699
  defs_file: Optional[str] = None, cases_file: Optional[str] = None,
@@ -719,7 +721,19 @@ class SingleClassRDR(RDRWithCodeWriter):
719
721
 
720
722
  @property
721
723
  def conclusion_type_hint(self) -> str:
722
- return self.conclusion_type[0].__name__
724
+ all_types = set(list(self.conclusion_type) + [type(self.default_conclusion)])
725
+ if NoneType in all_types:
726
+ return f"Optional[{', '.join([t.__name__ for t in all_types if t is not NoneType])}]"
727
+ return f"Union[{', '.join([t.__name__ for t in all_types])}]"
728
+
729
+ def _get_types_to_import(self) -> Tuple[Set[Type], Set[Type], Set[Type]]:
730
+ main_types, def_types, case_types = super()._get_types_to_import()
731
+ main_types.add(type(self.default_conclusion))
732
+ def_types.add(type(self.default_conclusion))
733
+ if self.default_conclusion is None:
734
+ main_types.add(Optional)
735
+ def_types.add(Optional)
736
+ return main_types, def_types, case_types
723
737
 
724
738
  @property
725
739
  def conclusion_type(self) -> Tuple[Type]:
@@ -857,8 +871,8 @@ class MultiClassRDR(RDRWithCodeWriter):
857
871
 
858
872
  def _get_types_to_import(self) -> Tuple[Set[Type], Set[Type], Set[Type]]:
859
873
  main_types, defs_types, cases_types = super()._get_types_to_import()
860
- main_types.update({Set, Union, make_set})
861
- defs_types.add(Union)
874
+ main_types.update({Set, make_set})
875
+ defs_types.update({List, Set})
862
876
  return main_types, defs_types, cases_types
863
877
 
864
878
  def update_start_rule(self, case_query: CaseQuery, expert: Expert):
@@ -31,7 +31,8 @@ class RDRDecorator:
31
31
  expert: Optional[Expert] = None,
32
32
  update_existing_rules: bool = True,
33
33
  viewer: Optional[RDRCaseViewer] = None,
34
- package_name: Optional[str] = None):
34
+ package_name: Optional[str] = None,
35
+ use_generated_classifier: bool = False):
35
36
  """
36
37
  :param models_dir: The directory to save/load the RDR models.
37
38
  :param output_type: The type of the output. This is used to create the RDR model.
@@ -47,6 +48,7 @@ class RDRDecorator:
47
48
  even if they gave an output.
48
49
  :param viewer: The viewer to use for the RDR model. If None, no viewer will be used.
49
50
  :param package_name: The package name to use for relative imports in the RDR model.
51
+ :param use_generated_classifier: If True, the function will use the generated classifier instead of the RDR model.
50
52
  :return: A decorator to use a GeneralRDR as a classifier that monitors and modifies the function's output.
51
53
  """
52
54
  self.rdr_models_dir = models_dir
@@ -60,6 +62,8 @@ class RDRDecorator:
60
62
  self.update_existing_rules = update_existing_rules
61
63
  self.viewer = viewer
62
64
  self.package_name = package_name
65
+ self.use_generated_classifier = use_generated_classifier
66
+ self.generated_classifier: Optional[Callable] = None
63
67
  self.load()
64
68
 
65
69
  def decorator(self, func: Callable) -> Callable:
@@ -67,17 +71,17 @@ class RDRDecorator:
67
71
  @wraps(func)
68
72
  def wrapper(*args, **kwargs) -> Optional[Any]:
69
73
 
70
- if len(self.parsed_output_type) == 0:
71
- self.parsed_output_type = self.parse_output_type(func, self.output_type, *args)
72
74
  if self.model_name is None:
73
75
  self.initialize_rdr_model_name_and_load(func)
74
- if self.expert is None:
75
- self.expert = Human(viewer=self.viewer,
76
- answers_save_path=self.rdr_models_dir + f'/{self.model_name}/expert_answers')
77
76
 
78
77
  func_output = {self.output_name: func(*args, **kwargs)}
79
78
 
80
79
  if self.fit:
80
+ if len(self.parsed_output_type) == 0:
81
+ self.parsed_output_type = self.parse_output_type(func, self.output_type, *args)
82
+ if self.expert is None:
83
+ self.expert = Human(viewer=self.viewer,
84
+ answers_save_path=self.rdr_models_dir + f'/{self.model_name}/expert_answers')
81
85
  case_query = self.create_case_query_from_method(func, func_output,
82
86
  self.parsed_output_type,
83
87
  self.mutual_exclusive,
@@ -87,7 +91,13 @@ class RDRDecorator:
87
91
  viewer=self.viewer)
88
92
  else:
89
93
  case, case_dict = self.create_case_from_method(func, func_output, *args, **kwargs)
90
- output = self.rdr.classify(case)
94
+ if self.use_generated_classifier:
95
+ if self.generated_classifier is None:
96
+ model_path = os.path.join(self.rdr_models_dir, self.model_name)
97
+ self.generated_classifier = self.rdr.get_rdr_classifier_from_python_file(model_path)
98
+ output = self.generated_classifier(case)
99
+ else:
100
+ output = self.rdr.classify(case)
91
101
 
92
102
  if self.output_name in output:
93
103
  return output[self.output_name]
@@ -4,6 +4,7 @@ import logging
4
4
  import re
5
5
  from abc import ABC, abstractmethod
6
6
  from pathlib import Path
7
+ from types import NoneType
7
8
  from uuid import uuid4
8
9
 
9
10
  from anytree import NodeMixin
@@ -162,6 +163,22 @@ class Rule(NodeMixin, SubclassJSONSerializer, ABC):
162
163
  # use regex to replace the function name
163
164
  new_function_name = f"def conclusion_{self.uid}"
164
165
  conclusion_lines[0] = re.sub(r"def (\w+)", new_function_name, conclusion_lines[0])
166
+ # add type hint
167
+ if len(self.conclusion.conclusion_type) == 1:
168
+ hint = self.conclusion.conclusion_type[0].__name__
169
+ else:
170
+ if (all(t in self.conclusion.conclusion_type for t in [list, set])
171
+ and len(self.conclusion.conclusion_type) > 2):
172
+ type_names = [t.__name__ for t in self.conclusion.conclusion_type if t not in [list, set]]
173
+ hint = f"List[{', '.join(type_names)}]"
174
+ else:
175
+ if NoneType in self.conclusion.conclusion_type:
176
+ type_names = [t.__name__ for t in self.conclusion.conclusion_type if t is not NoneType]
177
+ hint = f"Optional[{', '.join(type_names)}]"
178
+ else:
179
+ type_names = [t.__name__ for t in self.conclusion.conclusion_type]
180
+ hint = f"Union[{', '.join(type_names)}]"
181
+ conclusion_lines[0] = conclusion_lines[0].replace("):", f") -> {hint}:")
165
182
  func_call = f"{parent_indent} return {new_function_name.replace('def ', '')}(case)\n"
166
183
  return "\n".join(conclusion_lines).strip(' '), func_call
167
184
  else:
@@ -184,6 +201,8 @@ class Rule(NodeMixin, SubclassJSONSerializer, ABC):
184
201
  # use regex to replace the function name
185
202
  new_function_name = f"def conditions_{self.uid}"
186
203
  conditions_lines[0] = re.sub(r"def (\w+)", new_function_name, conditions_lines[0])
204
+ # add type hint
205
+ conditions_lines[0] = conditions_lines[0].replace('):', ') -> bool:')
187
206
  def_code = "\n".join(conditions_lines)
188
207
  with open(defs_file, 'a') as f:
189
208
  f.write(def_code.strip() + "\n\n\n")
@@ -918,6 +918,8 @@ def get_imports_from_types(type_objs: Iterable[Type],
918
918
  name = type(tp).__qualname__
919
919
  else:
920
920
  continue
921
+ if name == "NoneType":
922
+ module = "types"
921
923
  if module is None or module == 'builtins' or module.startswith('_')\
922
924
  or module in sys.builtin_module_names or module in excluded_modules or "<" in module \
923
925
  or name in exclueded_names:
@@ -1053,7 +1055,19 @@ def get_type_from_string(type_path: str):
1053
1055
  :param type_path: The path to the type.
1054
1056
  """
1055
1057
  module_path, class_name = type_path.rsplit(".", 1)
1056
- module = importlib.import_module(module_path)
1058
+ try:
1059
+ module = importlib.import_module(module_path)
1060
+ except ModuleNotFoundError:
1061
+ module_path_parts = module_path.split(".")
1062
+ idx = -1
1063
+ while True:
1064
+ try:
1065
+ module = importlib.import_module('.'.join(module_path_parts[:idx]))
1066
+ break
1067
+ except ModuleNotFoundError:
1068
+ idx -= 1
1069
+ if abs(idx) > len(module_path_parts):
1070
+ raise
1057
1071
  if module == builtins and class_name == 'NoneType':
1058
1072
  return type(None)
1059
1073
  return getattr(module, class_name)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ripple_down_rules
3
- Version: 0.5.95
3
+ Version: 0.5.97
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,4 +1,6 @@
1
1
  from ripple_down_rules.datastructures.case import Case, create_case
2
+ from types import NoneType
3
+ from typing_extensions import Optional
2
4
  from .physical_object_is_a_robot_output__scrdr_defs import *
3
5
 
4
6
 
@@ -7,9 +9,11 @@ conclusion_type = (bool,)
7
9
  mutually_exclusive = True
8
10
 
9
11
 
10
- def classify(case: Dict, **kwargs) -> bool:
12
+ def classify(case: Dict, **kwargs) -> Optional[bool]:
11
13
  if not isinstance(case, Case):
12
14
  case = create_case(case, max_recursion_idx=3)
13
15
 
14
16
  if conditions_226969243620390858682731042391766665817(case):
15
17
  return conclusion_226969243620390858682731042391766665817(case)
18
+ else:
19
+ return None
@@ -1,15 +1,16 @@
1
- from typing_extensions import Dict
1
+ from types import NoneType
2
2
  from ...datasets import PhysicalObject, Robot
3
+ from typing_extensions import Dict, Optional, Union
3
4
 
4
5
 
5
- def conditions_226969243620390858682731042391766665817(case):
6
+ def conditions_226969243620390858682731042391766665817(case) -> bool:
6
7
  def conditions_for_physical_object_is_a_robot(self_: PhysicalObject, output_: bool) -> bool:
7
8
  """Get conditions on whether it's possible to conclude a value for PhysicalObject_is_a_robot.output_ of type ."""
8
9
  return True
9
10
  return conditions_for_physical_object_is_a_robot(**case)
10
11
 
11
12
 
12
- def conclusion_226969243620390858682731042391766665817(case):
13
+ def conclusion_226969243620390858682731042391766665817(case) -> bool:
13
14
  def physical_object_is_a_robot(self_: PhysicalObject, output_: bool) -> bool:
14
15
  """Get possible value(s) for PhysicalObject_is_a_robot.output_ of type ."""
15
16
  return isinstance(self_, Robot)
@@ -14,7 +14,10 @@
14
14
  "scope": {
15
15
  "PhysicalObject": "test.datasets.PhysicalObject",
16
16
  "Robot": "test.datasets.Robot",
17
- "Dict": "typing.Dict"
17
+ "NoneType": "builtins.NoneType",
18
+ "Dict": "typing.Dict",
19
+ "Optional": "typing.Optional",
20
+ "Union": "typing.Union"
18
21
  },
19
22
  "conclusion": {
20
23
  "_type": "builtins.NoneType",
@@ -31,7 +34,10 @@
31
34
  "scope": {
32
35
  "PhysicalObject": "test.datasets.PhysicalObject",
33
36
  "Robot": "test.datasets.Robot",
34
- "Dict": "typing.Dict"
37
+ "NoneType": "builtins.NoneType",
38
+ "Dict": "typing.Dict",
39
+ "Optional": "typing.Optional",
40
+ "Union": "typing.Union"
35
41
  },
36
42
  "conclusion": {
37
43
  "_type": "builtins.NoneType",
@@ -1,4 +1,4 @@
1
- from typing_extensions import Set, Union
1
+ from typing_extensions import Optional, Set
2
2
  from ripple_down_rules.datastructures.case import Case, create_case
3
3
  from ripple_down_rules.utils import make_set
4
4
  from .physical_object_select_objects_that_are_parts_of_robot_output__mcrdr_defs import *
@@ -1,15 +1,15 @@
1
+ from typing_extensions import Dict, List, Set, Union
1
2
  from ...datasets import PhysicalObject, Robot
2
- from typing_extensions import Dict, List, Union
3
3
 
4
4
 
5
- def conditions_164855806603893754507167918997373216146(case):
5
+ def conditions_164855806603893754507167918997373216146(case) -> bool:
6
6
  def conditions_for_physical_object_select_objects_that_are_parts_of_robot(self_: PhysicalObject, objects: List[PhysicalObject], robot: Robot, output_: PhysicalObject) -> bool:
7
7
  """Get conditions on whether it's possible to conclude a value for PhysicalObject_select_objects_that_are_parts_of_robot.output_ of type PhysicalObject."""
8
8
  return robot is not None
9
9
  return conditions_for_physical_object_select_objects_that_are_parts_of_robot(**case)
10
10
 
11
11
 
12
- def conclusion_164855806603893754507167918997373216146(case):
12
+ def conclusion_164855806603893754507167918997373216146(case) -> List[PhysicalObject]:
13
13
  def physical_object_select_objects_that_are_parts_of_robot(self_: PhysicalObject, objects: List[PhysicalObject], robot: Robot, output_: PhysicalObject) -> List[PhysicalObject]:
14
14
  """Get possible value(s) for PhysicalObject_select_objects_that_are_parts_of_robot.output_ of type PhysicalObject."""
15
15
  robot_parts = [obj for obj in objects if obj in robot.parts]
@@ -14,6 +14,7 @@
14
14
  "scope": {
15
15
  "Dict": "typing.Dict",
16
16
  "List": "typing.List",
17
+ "Set": "typing.Set",
17
18
  "Union": "typing.Union",
18
19
  "PhysicalObject": "test.datasets.PhysicalObject",
19
20
  "Robot": "test.datasets.Robot"
@@ -35,6 +36,7 @@
35
36
  "scope": {
36
37
  "Dict": "typing.Dict",
37
38
  "List": "typing.List",
39
+ "Set": "typing.Set",
38
40
  "Union": "typing.Union",
39
41
  "PhysicalObject": "test.datasets.PhysicalObject",
40
42
  "Robot": "test.datasets.Robot"
@@ -1,6 +1,6 @@
1
1
  from typing_extensions import Any, Dict
2
- from ripple_down_rules.helpers import general_rdr_classify
3
2
  from ripple_down_rules.datastructures.case import Case, create_case
3
+ from ripple_down_rules.helpers import general_rdr_classify
4
4
  from . import physical_object_is_a_robot_output__scrdr as output__classifier
5
5
 
6
6
  classifiers_dict = dict()
@@ -1,6 +1,6 @@
1
1
  from typing_extensions import Any, Dict
2
- from ripple_down_rules.helpers import general_rdr_classify
3
2
  from ripple_down_rules.datastructures.case import Case, create_case
3
+ from ripple_down_rules.helpers import general_rdr_classify
4
4
  from . import physical_object_select_objects_that_are_parts_of_robot_output__mcrdr as output__classifier
5
5
 
6
6
  classifiers_dict = dict()