ripple-down-rules 0.6.27__tar.gz → 0.6.29__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.
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/PKG-INFO +1 -1
- ripple_down_rules-0.6.29/src/ripple_down_rules/__init__.py +5 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/src/ripple_down_rules/datastructures/callable_expression.py +4 -2
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/src/ripple_down_rules/datastructures/enums.py +13 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/src/ripple_down_rules/experts.py +45 -32
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/src/ripple_down_rules/rdr.py +15 -17
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/src/ripple_down_rules/rdr_decorators.py +1 -2
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/src/ripple_down_rules/user_interface/gui.py +5 -2
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/src/ripple_down_rules/user_interface/prompt.py +14 -12
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/src/ripple_down_rules/utils.py +21 -8
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/src/ripple_down_rules.egg-info/PKG-INFO +1 -1
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/src/ripple_down_rules.egg-info/SOURCES.txt +9 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/test/conftest.py +3 -2
- ripple_down_rules-0.6.29/test/test_expert_answers/grdr_expert_answers_fit.py +105 -0
- ripple_down_rules-0.6.29/test/test_expert_answers/grdr_expert_answers_fit_no_targets.py +224 -0
- ripple_down_rules-0.6.29/test/test_expert_answers/mcrdr_expert_answers_fit_no_targets.py +573 -0
- ripple_down_rules-0.6.29/test/test_expert_answers/mcrdr_expert_answers_stop_only_fit.py +378 -0
- ripple_down_rules-0.6.29/test/test_expert_answers/mcrdr_multi_line_expert_answers_fit.py +133 -0
- ripple_down_rules-0.6.29/test/test_expert_answers/scrdr_expert_answers_fit.py +252 -0
- ripple_down_rules-0.6.29/test/test_expert_answers/scrdr_expert_answers_fit_no_targets.py +552 -0
- ripple_down_rules-0.6.29/test/test_expert_answers/scrdr_multi_line_expert_answers_fit.py +111 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/test/test_helpers/helpers.py +3 -3
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/test/test_rdr.py +2 -1
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/test/test_rdr_world/conftest.py +3 -2
- ripple_down_rules-0.6.29/test/test_results/datasets_physical_object_select_objects_that_are_parts_of_robot/__init__.py +1 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/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 +3 -3
- ripple_down_rules-0.6.27/src/ripple_down_rules/__init__.py +0 -5
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/.github/workflows/build_and_deploy_doc.yml +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/.github/workflows/ci.yml +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/.github/workflows/publish-to-test-pypi.yml +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/.gitignore +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/.idea/shelf/Uncommitted_changes_before_Checkout_at_2_4_25,_6_32_PM_[Changes]/shelved.patch +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/.idea/shelf/Uncommitted_changes_before_Checkout_at_2_4_25,_6_32_PM_[Changes]1/shelved.patch +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/LICENSE +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/README.md +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/doc/_config.yml +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/doc/_toc.yml +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/doc/bibliography.md +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/doc/intro.md +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/doc/references.bib +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/doc/requirements.txt +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/examples/__init__.py +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/examples/animal_species.py +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/examples/part_containment_rdr/__init__.py +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/examples/part_containment_rdr/rdr_metadata/part_containment_rdr.json +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/examples/part_containment_rdr/robot_contained_objects_mcrdr.py +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/examples/part_containment_rdr/robot_contained_objects_mcrdr_defs.py +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/examples/part_containment_rdr/robot_rdr.py +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/examples/relational_example.py +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/images/scrdr.dot +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/images/scrdr.png +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/images/thinking_pr2.jpg +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/pyproject.toml +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/pytest.ini +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/requirements-dev-ci.txt +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/requirements-dev.txt +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/requirements-gui.txt +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/requirements-viz.txt +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/requirements.txt +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/results/complete_mcrdr_extra.dot +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/results/complete_mcrdr_extra.png +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/results/complete_mcrdr_stop_only.dot +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/results/complete_mcrdr_stop_only.png +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/results/complete_mcrdr_stop_plus_rule.dot +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/results/complete_mcrdr_stop_plus_rule.png +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/results/complete_scrdr.dot +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/results/complete_scrdr.png +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/results/complete_scrdr_2.dot +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/results/complete_scrdr_2.png +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/results/complete_scrdr_3.dot +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/results/complete_scrdr_3.png +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/results/grdr_Habitat.dot +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/results/grdr_Habitat.png +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/results/grdr_Species.dot +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/results/grdr_Species.png +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/results/mcrdr_extra.dot +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/results/mcrdr_extra.png +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/results/mcrdr_extra_classify.dot +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/results/mcrdr_extra_classify.png +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/results/mcrdr_stop_plus_rule_combined.dot +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/results/mcrdr_stop_plus_rule_combined.png +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/results/partial_mcrdr_extra.dot +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/results/partial_mcrdr_extra.png +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/results/relational_scrdr_classify.dot +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/results/relational_scrdr_classify.png +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/scripts/live_dot_server_client.py +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/setup.cfg +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/src/ripple_down_rules/datastructures/__init__.py +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/src/ripple_down_rules/datastructures/case.py +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/src/ripple_down_rules/datastructures/dataclasses.py +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/src/ripple_down_rules/helpers.py +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/src/ripple_down_rules/rules.py +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/src/ripple_down_rules/start-code-server.sh +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/src/ripple_down_rules/user_interface/__init__.py +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/src/ripple_down_rules/user_interface/ipython_custom_shell.py +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/src/ripple_down_rules/user_interface/object_diagram.py +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/src/ripple_down_rules/user_interface/template_file_creator.py +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/src/ripple_down_rules.egg-info/dependency_links.txt +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/src/ripple_down_rules.egg-info/requires.txt +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/src/ripple_down_rules.egg-info/top_level.txt +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/test/__init__.py +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/test/conf/__init__.py +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/test/conf/world/__init__.py +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/test/conf/world/base_config.py +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/test/conf/world/handles_and_containers.py +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/test/datasets.py +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/test/factories/__init__.py +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/test/factories/world/__init__.py +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/test/factories/world/handles_and_containers.py +0 -0
- {ripple_down_rules-0.6.27/test/test_results/datasets_physical_object_is_a_robot → ripple_down_rules-0.6.29/test/test_expert_answers}/__init__.py +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/test/test_expert_answers/correct_drawer_rdr_expert_answers_fit.json +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/test/test_expert_answers/drawer_cabinet_expert_answers_fit.json +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/test/test_expert_answers/grdr_expert_answers_classify.json +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/test/test_expert_answers/grdr_expert_answers_fit.json +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/test/test_expert_answers/grdr_expert_answers_fit_extra.json +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/test/test_expert_answers/grdr_expert_answers_fit_no_targets.json +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/test/test_expert_answers/mcrdr_expert_answers_classify.json +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/test/test_expert_answers/mcrdr_expert_answers_fit_no_targets.json +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/test/test_expert_answers/mcrdr_expert_answers_stop_only_fit.json +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/test/test_expert_answers/mcrdr_extra_expert_answers_classify.json +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/test/test_expert_answers/mcrdr_extra_expert_answers_fit.json +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/test/test_expert_answers/mcrdr_multi_line_expert_answers_fit.json +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/test/test_expert_answers/mcrdr_stop_only_answers_fit.json +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/test/test_expert_answers/mcrdr_stop_plus_rule_answers_fit.json +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/test/test_expert_answers/mcrdr_stop_plus_rule_combined_expert_answers_fit.json +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/test/test_expert_answers/mcrdr_stop_plus_rule_expert_answers_fit.json +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/test/test_expert_answers/mutagenic_expert_answers.json +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/test/test_expert_answers/relational_scrdr_expert_answers_classify.json +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/test/test_expert_answers/scrdr_expert_answers_classify.json +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/test/test_expert_answers/scrdr_expert_answers_fit.json +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/test/test_expert_answers/scrdr_expert_answers_fit_no_targets.json +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/test/test_expert_answers/scrdr_multi_line_expert_answers_fit.json +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/test/test_expert_answers/scrdr_world_expert_answers_fit.json +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/test/test_generated_rdrs/__init__.py +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/test/test_helpers/__init__.py +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/test/test_helpers/object_diagram_case_query.png +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/test/test_helpers/object_diagram_person.png +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/test/test_json_serialization.py +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/test/test_object_diagram.py +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/test/test_on_mutagenic.py +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/test/test_rdr_alchemy.py +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/test/test_rdr_decorators.py +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/test/test_rdr_helpers_rdrs.py +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/test/test_rdr_world/__init__.py +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/test/test_rdr_world/test_rdr_world.py +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/test/test_relational_rdr.py +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/test/test_relational_rdr_alchemy.py +0 -0
- {ripple_down_rules-0.6.27/test/test_results/datasets_physical_object_select_objects_that_are_parts_of_robot → ripple_down_rules-0.6.29/test/test_results/datasets_physical_object_is_a_robot}/__init__.py +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/test/test_results/datasets_physical_object_is_a_robot/physical_object_is_a_robot_output__scrdr.py +2 -2
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/test/test_results/datasets_physical_object_is_a_robot/physical_object_is_a_robot_output__scrdr_defs.py +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/test/test_results/datasets_physical_object_is_a_robot/physical_object_is_a_robot_rdr.py +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/test/test_results/datasets_physical_object_is_a_robot/rdr_metadata/datasets_physical_object_is_a_robot.json +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/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 +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/test/test_results/datasets_physical_object_select_objects_that_are_parts_of_robot/physical_object_select_objects_that_are_parts_of_robot_rdr.py +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/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 +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/test/test_sql_model.py +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/test/test_template_file_creator.py +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/test/test_user_interface/__init__.py +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/test/test_user_interface/test_ipython.py +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/test/test_user_interface/test_ipython_copilot.py +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/test/test_user_interface/test_prompt.py +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/test/test_user_interface/test_qt_gui_inline.py +0 -0
- {ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/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.6.
|
3
|
+
Version: 0.6.29
|
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
|
@@ -120,7 +120,9 @@ class CallableExpression(SubclassJSONSerializer):
|
|
120
120
|
self.user_defined_name = user_input.split('(')[0].replace('def ', '')
|
121
121
|
else:
|
122
122
|
self.user_defined_name = user_input
|
123
|
-
self.
|
123
|
+
if f"def {self.encapsulating_function_name}" not in user_input:
|
124
|
+
user_input = encapsulate_user_input(user_input, self.get_encapsulating_function())
|
125
|
+
self._user_input: str = user_input
|
124
126
|
if conclusion_type is not None:
|
125
127
|
if is_iterable(conclusion_type):
|
126
128
|
conclusion_type = tuple(conclusion_type)
|
@@ -308,7 +310,7 @@ def parse_string_to_expression(expression_str: str) -> AST:
|
|
308
310
|
:param expression_str: The string which will be parsed.
|
309
311
|
:return: The parsed expression.
|
310
312
|
"""
|
311
|
-
if not expression_str.startswith(CallableExpression.
|
313
|
+
if not expression_str.startswith(f"def {CallableExpression.encapsulating_function_name}"):
|
312
314
|
expression_str = encapsulate_user_input(expression_str, CallableExpression.get_encapsulating_function())
|
313
315
|
mode = 'exec' if expression_str.startswith('def') else 'eval'
|
314
316
|
tree = ast.parse(expression_str, mode=mode)
|
{ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/src/ripple_down_rules/datastructures/enums.py
RENAMED
@@ -7,6 +7,19 @@ from typing_extensions import List, Dict, Any, Type
|
|
7
7
|
from ripple_down_rules.utils import SubclassJSONSerializer
|
8
8
|
|
9
9
|
|
10
|
+
class ExitStatus(Enum):
|
11
|
+
"""
|
12
|
+
Describes the status at exit of the user interface.
|
13
|
+
"""
|
14
|
+
CLOSE = auto()
|
15
|
+
"""
|
16
|
+
The user wants to stop the program.
|
17
|
+
"""
|
18
|
+
SUCCESS = auto()
|
19
|
+
"""
|
20
|
+
The user completed the task successfully.
|
21
|
+
"""
|
22
|
+
|
10
23
|
class InteractionMode(Enum):
|
11
24
|
"""
|
12
25
|
The interaction mode of the RDR.
|
@@ -6,6 +6,8 @@ import logging
|
|
6
6
|
import os
|
7
7
|
import uuid
|
8
8
|
from abc import ABC, abstractmethod
|
9
|
+
from textwrap import dedent, indent
|
10
|
+
from typing import Tuple, Dict
|
9
11
|
|
10
12
|
from typing_extensions import Optional, TYPE_CHECKING, List
|
11
13
|
|
@@ -13,6 +15,7 @@ from .datastructures.callable_expression import CallableExpression
|
|
13
15
|
from .datastructures.enums import PromptFor
|
14
16
|
from .datastructures.dataclasses import CaseQuery
|
15
17
|
from .datastructures.case import show_current_and_corner_cases
|
18
|
+
from .user_interface.template_file_creator import TemplateFileCreator
|
16
19
|
from .utils import extract_imports, extract_function_source, get_imports_from_scope, encapsulate_user_input
|
17
20
|
|
18
21
|
try:
|
@@ -46,14 +49,12 @@ class Expert(ABC):
|
|
46
49
|
answers_save_path: Optional[str] = None):
|
47
50
|
self.all_expert_answers = []
|
48
51
|
self.use_loaded_answers = use_loaded_answers
|
49
|
-
self.append =
|
52
|
+
self.append = True
|
50
53
|
self.answers_save_path = answers_save_path
|
51
54
|
if answers_save_path is not None and os.path.exists(answers_save_path + '.py'):
|
52
55
|
if use_loaded_answers:
|
53
56
|
self.load_answers(answers_save_path)
|
54
|
-
|
55
|
-
os.remove(answers_save_path + '.py')
|
56
|
-
self.append = True
|
57
|
+
os.remove(answers_save_path + '.py')
|
57
58
|
|
58
59
|
@abstractmethod
|
59
60
|
def ask_for_conditions(self, case_query: CaseQuery, last_evaluated_rule: Optional[Rule] = None) \
|
@@ -89,28 +90,26 @@ class Expert(ABC):
|
|
89
90
|
"answers_save_path attribute.")
|
90
91
|
if path is None:
|
91
92
|
path = self.answers_save_path
|
92
|
-
if os.path.exists(path + '.json'):
|
93
|
-
os.remove(path + '.json')
|
94
93
|
if os.path.exists(path + '.py'):
|
95
94
|
os.remove(path + '.py')
|
96
95
|
self.all_expert_answers = []
|
97
96
|
|
98
|
-
def save_answers(self, path: Optional[str] = None):
|
97
|
+
def save_answers(self, path: Optional[str] = None, expert_answers: Optional[List[Tuple[Dict, str]]] = None):
|
99
98
|
"""
|
100
99
|
Save the expert answers to a file.
|
101
100
|
|
102
101
|
:param path: The path to save the answers to.
|
102
|
+
:param expert_answers: The expert answers to save.
|
103
103
|
"""
|
104
|
+
expert_answers = expert_answers if expert_answers else self.all_expert_answers
|
105
|
+
if not any(expert_answers):
|
106
|
+
return
|
104
107
|
if path is None and self.answers_save_path is None:
|
105
108
|
raise ValueError("No path provided to save expert answers, either provide a path or set the "
|
106
109
|
"answers_save_path attribute.")
|
107
110
|
if path is None:
|
108
111
|
path = self.answers_save_path
|
109
|
-
|
110
|
-
if is_json:
|
111
|
-
self._save_to_json(path)
|
112
|
-
else:
|
113
|
-
self._save_to_python(path)
|
112
|
+
self._save_to_python(path, expert_answers=expert_answers)
|
114
113
|
|
115
114
|
def _save_to_json(self, path: str):
|
116
115
|
"""
|
@@ -127,12 +126,14 @@ class Expert(ABC):
|
|
127
126
|
with open(path + '.json', "w") as f:
|
128
127
|
json.dump(all_answers, f)
|
129
128
|
|
130
|
-
def _save_to_python(self, path: str):
|
129
|
+
def _save_to_python(self, path: str, expert_answers: Optional[List[Tuple[Dict, str]]] = None):
|
131
130
|
"""
|
132
131
|
Save the expert answers to a Python file.
|
133
132
|
|
134
133
|
:param path: The path to save the answers to.
|
134
|
+
:param expert_answers: The expert answers to save.
|
135
135
|
"""
|
136
|
+
expert_answers = expert_answers if expert_answers else self.all_expert_answers
|
136
137
|
dir_name = os.path.dirname(path)
|
137
138
|
if not os.path.exists(dir_name + '/__init__.py'):
|
138
139
|
os.makedirs(dir_name, exist_ok=True)
|
@@ -145,18 +146,13 @@ class Expert(ABC):
|
|
145
146
|
current_file_data = f.read()
|
146
147
|
action = 'a' if self.append and current_file_data is not None else 'w'
|
147
148
|
with open(path + '.py', action) as f:
|
148
|
-
for scope, func_source in
|
149
|
+
for scope, func_source in expert_answers:
|
149
150
|
if len(scope) > 0:
|
150
151
|
imports = '\n'.join(get_imports_from_scope(scope)) + '\n\n\n'
|
151
152
|
else:
|
152
153
|
imports = ''
|
153
|
-
if func_source is
|
154
|
-
uid = uuid.uuid4().hex
|
155
|
-
func_source = encapsulate_user_input(func_source, CallableExpression.get_encapsulating_function(f'_{uid}'))
|
156
|
-
else:
|
154
|
+
if func_source is None:
|
157
155
|
func_source = 'pass # No user input provided for this case.\n'
|
158
|
-
if current_file_data is not None and func_source[1:] in current_file_data:
|
159
|
-
continue
|
160
156
|
f.write(imports + func_source + '\n' + '\n\n\n\'===New Answer===\'\n\n\n')
|
161
157
|
|
162
158
|
def load_answers(self, path: Optional[str] = None):
|
@@ -170,11 +166,10 @@ class Expert(ABC):
|
|
170
166
|
"answers_save_path attribute.")
|
171
167
|
if path is None:
|
172
168
|
path = self.answers_save_path
|
173
|
-
|
174
|
-
if is_json:
|
175
|
-
self._load_answers_from_json(path)
|
176
|
-
elif os.path.exists(path + '.py'):
|
169
|
+
if os.path.exists(path + '.py'):
|
177
170
|
self._load_answers_from_python(path)
|
171
|
+
elif os.path.exists(path + '.json'):
|
172
|
+
self._load_answers_from_json(path)
|
178
173
|
|
179
174
|
def _load_answers_from_json(self, path: str):
|
180
175
|
"""
|
@@ -195,15 +190,15 @@ class Expert(ABC):
|
|
195
190
|
file_path = path + '.py'
|
196
191
|
with open(file_path, "r") as f:
|
197
192
|
all_answers = f.read().split('\n\n\n\'===New Answer===\'\n\n\n')[:-1]
|
198
|
-
all_function_sources =
|
199
|
-
all_function_sources_names = list(extract_function_source(file_path, []).keys())
|
193
|
+
all_function_sources = extract_function_source(file_path, [], as_list=True)
|
200
194
|
for i, answer in enumerate(all_answers):
|
201
195
|
answer = answer.strip('\n').strip()
|
202
196
|
if 'def ' not in answer and 'pass' in answer:
|
203
197
|
self.all_expert_answers.append(({}, None))
|
204
198
|
continue
|
205
199
|
scope = extract_imports(tree=ast.parse(answer))
|
206
|
-
|
200
|
+
func_name = all_function_sources[i].split('def ')[1].split('(')[0]
|
201
|
+
function_source = all_function_sources[i].replace(func_name,
|
207
202
|
CallableExpression.encapsulating_function_name)
|
208
203
|
self.all_expert_answers.append((scope, function_source))
|
209
204
|
|
@@ -213,14 +208,12 @@ class Human(Expert):
|
|
213
208
|
The Human Expert class, an expert that asks the human to provide differentiating features and conclusions.
|
214
209
|
"""
|
215
210
|
|
216
|
-
def __init__(self,
|
211
|
+
def __init__(self, **kwargs):
|
217
212
|
"""
|
218
213
|
Initialize the Human expert.
|
219
|
-
|
220
|
-
:param viewer: The RDRCaseViewer instance to use for prompting the user.
|
221
214
|
"""
|
222
215
|
super().__init__(**kwargs)
|
223
|
-
self.user_prompt = UserPrompt(
|
216
|
+
self.user_prompt = UserPrompt()
|
224
217
|
|
225
218
|
def ask_for_conditions(self, case_query: CaseQuery,
|
226
219
|
last_evaluated_rule: Optional[Rule] = None) \
|
@@ -251,6 +244,8 @@ class Human(Expert):
|
|
251
244
|
if user_input is not None:
|
252
245
|
case_query.scope.update(loaded_scope)
|
253
246
|
condition = CallableExpression(user_input, bool, scope=case_query.scope)
|
247
|
+
if self.answers_save_path is not None and not any(loaded_scope):
|
248
|
+
self.convert_json_answer_to_python_answer(case_query, user_input, condition, PromptFor.Conditions)
|
254
249
|
else:
|
255
250
|
user_input, condition = self.user_prompt.prompt_user_for_expression(case_query, PromptFor.Conditions, prompt_str=data_to_show)
|
256
251
|
if user_input == 'exit':
|
@@ -262,6 +257,20 @@ class Human(Expert):
|
|
262
257
|
case_query.conditions = condition
|
263
258
|
return condition
|
264
259
|
|
260
|
+
def convert_json_answer_to_python_answer(self, case_query: CaseQuery, user_input: str,
|
261
|
+
callable_expression: CallableExpression,
|
262
|
+
prompt_for: PromptFor):
|
263
|
+
case_query.scope['case'] = case_query.case
|
264
|
+
tfc = TemplateFileCreator(case_query, prompt_for=prompt_for)
|
265
|
+
code = tfc.build_boilerplate_code()
|
266
|
+
if user_input.startswith('def'):
|
267
|
+
user_input = '\n'.join(user_input.split('\n')[1:])
|
268
|
+
user_input = indent(dedent(user_input), " " * 4).strip()
|
269
|
+
code = code.replace('pass', user_input)
|
270
|
+
else:
|
271
|
+
code = code.replace('pass', f"return {user_input}")
|
272
|
+
self.save_answers(expert_answers=[({}, code)])
|
273
|
+
|
265
274
|
def ask_for_conclusion(self, case_query: CaseQuery) -> Optional[CallableExpression]:
|
266
275
|
"""
|
267
276
|
Ask the expert to provide a conclusion for the case.
|
@@ -281,13 +290,17 @@ class Human(Expert):
|
|
281
290
|
expression = CallableExpression(expert_input, case_query.attribute_type,
|
282
291
|
scope=case_query.scope,
|
283
292
|
mutually_exclusive=case_query.mutually_exclusive)
|
293
|
+
if self.answers_save_path is not None and not any(loaded_scope):
|
294
|
+
self.convert_json_answer_to_python_answer(case_query, expert_input, expression,
|
295
|
+
PromptFor.Conclusion)
|
284
296
|
except IndexError:
|
285
297
|
self.use_loaded_answers = False
|
286
298
|
if not self.use_loaded_answers:
|
287
299
|
data_to_show = None
|
288
300
|
if self.user_prompt.viewer is None:
|
289
301
|
data_to_show = show_current_and_corner_cases(case_query.case)
|
290
|
-
expert_input, expression = self.user_prompt.prompt_user_for_expression(case_query, PromptFor.Conclusion,
|
302
|
+
expert_input, expression = self.user_prompt.prompt_user_for_expression(case_query, PromptFor.Conclusion,
|
303
|
+
prompt_str=data_to_show)
|
291
304
|
if expert_input is None:
|
292
305
|
self.all_expert_answers.append(({}, None))
|
293
306
|
elif expert_input != 'exit':
|
@@ -83,23 +83,18 @@ class RippleDownRules(SubclassJSONSerializer, ABC):
|
|
83
83
|
Whether the output of the classification of this rdr allows only one possible conclusion or not.
|
84
84
|
"""
|
85
85
|
|
86
|
-
def __init__(self, start_rule: Optional[Rule] = None,
|
86
|
+
def __init__(self, start_rule: Optional[Rule] = None,
|
87
87
|
save_dir: Optional[str] = None, model_name: Optional[str] = None):
|
88
88
|
"""
|
89
89
|
:param start_rule: The starting rule for the classifier.
|
90
|
-
:param viewer: The viewer gui to use for the classifier. If None, no viewer is used.
|
91
90
|
:param save_dir: The directory to save the classifier to.
|
92
91
|
"""
|
93
92
|
self.model_name: Optional[str] = model_name
|
94
93
|
self.save_dir = save_dir
|
95
94
|
self.start_rule = start_rule
|
96
95
|
self.fig: Optional[Figure] = None
|
97
|
-
self.viewer: Optional[RDRCaseViewer] =
|
98
|
-
|
99
|
-
if len(RDRCaseViewer.instances) > 0:
|
100
|
-
self.viewer = RDRCaseViewer.instances[0]
|
101
|
-
logger.error("No viewer was provided, but there is already an existing viewer. "
|
102
|
-
"Using the existing viewer.")
|
96
|
+
self.viewer: Optional[RDRCaseViewer] = RDRCaseViewer.instances[0]\
|
97
|
+
if RDRCaseViewer and any(RDRCaseViewer.instances) else None
|
103
98
|
self.input_node: Optional[Rule] = None
|
104
99
|
|
105
100
|
@property
|
@@ -107,10 +102,10 @@ class RippleDownRules(SubclassJSONSerializer, ABC):
|
|
107
102
|
return self._viewer
|
108
103
|
|
109
104
|
@viewer.setter
|
110
|
-
def viewer(self,
|
111
|
-
self._viewer =
|
112
|
-
if
|
113
|
-
|
105
|
+
def viewer(self, viewer):
|
106
|
+
self._viewer = viewer
|
107
|
+
if viewer:
|
108
|
+
viewer.set_save_function(self.save)
|
114
109
|
|
115
110
|
def render_evaluated_rule_tree(self, filename: str, show_full_tree: bool = False) -> None:
|
116
111
|
if show_full_tree:
|
@@ -235,7 +230,8 @@ class RippleDownRules(SubclassJSONSerializer, ABC):
|
|
235
230
|
num_rules: int = 0
|
236
231
|
while not stop_iterating:
|
237
232
|
for case_query in case_queries:
|
238
|
-
pred_cat = self.fit_case(case_query, expert=expert,
|
233
|
+
pred_cat = self.fit_case(case_query, expert=expert, clear_expert_answers=False,
|
234
|
+
**kwargs_for_fit_case)
|
239
235
|
if case_query.target is None:
|
240
236
|
continue
|
241
237
|
target = {case_query.attribute_name: case_query.target(case_query.case)}
|
@@ -313,6 +309,7 @@ class RippleDownRules(SubclassJSONSerializer, ABC):
|
|
313
309
|
update_existing_rules: bool = True,
|
314
310
|
scenario: Optional[Callable] = None,
|
315
311
|
ask_now: Callable = lambda _: True,
|
312
|
+
clear_expert_answers: bool = True,
|
316
313
|
**kwargs) \
|
317
314
|
-> Union[CallableExpression, Dict[str, CallableExpression]]:
|
318
315
|
"""
|
@@ -324,7 +321,8 @@ class RippleDownRules(SubclassJSONSerializer, ABC):
|
|
324
321
|
:param update_existing_rules: Whether to update the existing same conclusion type rules that already gave
|
325
322
|
some conclusions with the type required by the case query.
|
326
323
|
:param scenario: The scenario at which the case was created, this is used to recreate the case if needed.
|
327
|
-
:ask_now: Whether to ask the expert for refinements or alternatives.
|
324
|
+
:param ask_now: Whether to ask the expert for refinements or alternatives.
|
325
|
+
:param clear_expert_answers: Whether to clear expert answers after saving the new rule.
|
328
326
|
:return: The category that the case belongs to.
|
329
327
|
"""
|
330
328
|
if case_query is None:
|
@@ -335,8 +333,7 @@ class RippleDownRules(SubclassJSONSerializer, ABC):
|
|
335
333
|
self.case_name = case_query.case_name if self.case_name is None else self.case_name
|
336
334
|
case_query.scenario = scenario if case_query.scenario is None else case_query.scenario
|
337
335
|
|
338
|
-
expert = expert or Human(
|
339
|
-
answers_save_path=self.save_dir + '/expert_answers'
|
336
|
+
expert = expert or Human(answers_save_path=self.save_dir + '/expert_answers'
|
340
337
|
if self.save_dir else None)
|
341
338
|
if case_query.target is None:
|
342
339
|
case_query_cp = copy(case_query)
|
@@ -354,7 +351,8 @@ class RippleDownRules(SubclassJSONSerializer, ABC):
|
|
354
351
|
|
355
352
|
if self.save_dir is not None:
|
356
353
|
self.save()
|
357
|
-
|
354
|
+
if clear_expert_answers:
|
355
|
+
expert.clear_answers()
|
358
356
|
|
359
357
|
return fit_case_result
|
360
358
|
|
{ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/src/ripple_down_rules/rdr_decorators.py
RENAMED
@@ -96,8 +96,7 @@ class RDRDecorator:
|
|
96
96
|
if len(self.parsed_output_type) == 0:
|
97
97
|
self.parsed_output_type = self.parse_output_type(func, self.output_type, *args)
|
98
98
|
if self.expert is None:
|
99
|
-
self.expert = Human(
|
100
|
-
answers_save_path=self.rdr_models_dir + f'/{self.model_name}/expert_answers')
|
99
|
+
self.expert = Human(answers_save_path=self.rdr_models_dir + f'/{self.model_name}/expert_answers')
|
101
100
|
case_query = self.create_case_query_from_method(func, func_output,
|
102
101
|
self.parsed_output_type,
|
103
102
|
self.mutual_exclusive,
|
{ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/src/ripple_down_rules/user_interface/gui.py
RENAMED
@@ -21,7 +21,7 @@ except ImportError as e:
|
|
21
21
|
from typing_extensions import Optional, Any, List, Dict, Callable
|
22
22
|
|
23
23
|
from ..datastructures.dataclasses import CaseQuery
|
24
|
-
from ..datastructures.enums import PromptFor
|
24
|
+
from ..datastructures.enums import PromptFor, ExitStatus
|
25
25
|
from .template_file_creator import TemplateFileCreator
|
26
26
|
from ..utils import is_iterable, contains_return_statement, encapsulate_code_lines_into_a_function
|
27
27
|
from .object_diagram import generate_object_graph
|
@@ -283,11 +283,13 @@ class RDRCaseViewer(QMainWindow):
|
|
283
283
|
attributes_widget: Optional[QWidget] = None
|
284
284
|
save_function: Optional[Callable[str, str], None] = None
|
285
285
|
instances: List[RDRCaseViewer] = []
|
286
|
+
exit_status: ExitStatus = ExitStatus.CLOSE
|
286
287
|
|
287
288
|
def __init__(self, parent=None,
|
288
289
|
save_dir: Optional[str] = None,
|
289
290
|
save_model_name: Optional[str] = None):
|
290
291
|
super().__init__(parent)
|
292
|
+
self.exit_status = ExitStatus.CLOSE
|
291
293
|
self.instances.clear()
|
292
294
|
self.instances.append(self)
|
293
295
|
self.save_dir = save_dir
|
@@ -328,7 +330,7 @@ class RDRCaseViewer(QMainWindow):
|
|
328
330
|
|
329
331
|
# Add both to main layout
|
330
332
|
main_layout.addWidget(self.attributes_widget, stretch=1)
|
331
|
-
main_layout.addWidget(middle_widget, stretch=
|
333
|
+
main_layout.addWidget(middle_widget, stretch=2)
|
332
334
|
main_layout.addWidget(self.obj_diagram_viewer, stretch=2)
|
333
335
|
|
334
336
|
def set_save_function(self, save_function: Callable[[str, str], None]) -> None:
|
@@ -474,6 +476,7 @@ class RDRCaseViewer(QMainWindow):
|
|
474
476
|
return button_widget
|
475
477
|
|
476
478
|
def _accept(self):
|
479
|
+
self.exit_status = ExitStatus.SUCCESS
|
477
480
|
# close the window
|
478
481
|
self.close()
|
479
482
|
|
{ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/src/ripple_down_rules/user_interface/prompt.py
RENAMED
@@ -4,7 +4,7 @@ from _ast import AST
|
|
4
4
|
|
5
5
|
try:
|
6
6
|
from PyQt6.QtWidgets import QApplication
|
7
|
-
from .gui import RDRCaseViewer
|
7
|
+
from .gui import RDRCaseViewer, style
|
8
8
|
except ImportError:
|
9
9
|
QApplication = None
|
10
10
|
RDRCaseViewer = None
|
@@ -17,7 +17,7 @@ from typing_extensions import Optional, Tuple
|
|
17
17
|
|
18
18
|
from ..datastructures.callable_expression import CallableExpression, parse_string_to_expression
|
19
19
|
from ..datastructures.dataclasses import CaseQuery
|
20
|
-
from ..datastructures.enums import PromptFor
|
20
|
+
from ..datastructures.enums import PromptFor, ExitStatus
|
21
21
|
from .ipython_custom_shell import IPythonShell
|
22
22
|
from ..utils import make_list
|
23
23
|
from threading import RLock
|
@@ -29,15 +29,12 @@ class UserPrompt:
|
|
29
29
|
"""
|
30
30
|
shell_lock: RLock = RLock() # To ensure that only one thread can access the shell at a time
|
31
31
|
|
32
|
-
def __init__(self
|
32
|
+
def __init__(self):
|
33
33
|
"""
|
34
34
|
Initialize the UserPrompt class.
|
35
|
-
|
36
|
-
:param viewer: The RDRCaseViewer instance to use for prompting the user.
|
37
35
|
"""
|
38
|
-
self.viewer =
|
39
|
-
self.print_func = print if viewer
|
40
|
-
|
36
|
+
self.viewer = RDRCaseViewer.instances[0] if RDRCaseViewer and any(RDRCaseViewer.instances) else None
|
37
|
+
self.print_func = self.viewer.print if self.viewer else print
|
41
38
|
|
42
39
|
def prompt_user_for_expression(self, case_query: CaseQuery, prompt_for: PromptFor, prompt_str: Optional[str] = None) \
|
43
40
|
-> Tuple[Optional[str], Optional[CallableExpression]]:
|
@@ -99,19 +96,20 @@ class UserPrompt:
|
|
99
96
|
:return: The user input, and the executable expression that was parsed from the user input.
|
100
97
|
"""
|
101
98
|
self.print_func("Entered shell")
|
102
|
-
|
99
|
+
initial_prompt_str = f"{prompt_str}\n" if prompt_str is not None else ''
|
103
100
|
if prompt_for == PromptFor.Conclusion:
|
104
|
-
|
101
|
+
prompt_for_str = f"Give possible value(s) for:"
|
105
102
|
else:
|
106
|
-
|
103
|
+
prompt_for_str = f"Give conditions for:"
|
107
104
|
case_query.scope.update({'case': case_query.case})
|
108
105
|
shell = None
|
109
106
|
if self.viewer is None:
|
107
|
+
prompt_str = f"{Fore.WHITE}{initial_prompt_str}{Fore.MAGENTA}{prompt_for_str}"
|
110
108
|
prompt_str = self.construct_prompt_str_for_shell(case_query, prompt_for, prompt_str)
|
111
109
|
shell = IPythonShell(header=prompt_str, prompt_for=prompt_for, case_query=case_query,
|
112
110
|
code_to_modify=code_to_modify)
|
113
111
|
else:
|
114
|
-
|
112
|
+
prompt_str = initial_prompt_str + prompt_for_str
|
115
113
|
self.viewer.update_for_case_query(case_query, prompt_str,
|
116
114
|
prompt_for=prompt_for, code_to_modify=code_to_modify)
|
117
115
|
user_input, expression_tree = self.prompt_user_input_and_parse_to_expression(shell=shell)
|
@@ -176,6 +174,8 @@ class UserPrompt:
|
|
176
174
|
"""
|
177
175
|
if self.viewer is None:
|
178
176
|
shell = IPythonShell() if shell is None else shell
|
177
|
+
if not hasattr(shell.shell, "auto_match"):
|
178
|
+
shell.shell.auto_match = True # or True, depending on your preference
|
179
179
|
shell.run()
|
180
180
|
user_input = shell.user_input
|
181
181
|
else:
|
@@ -184,5 +184,7 @@ class UserPrompt:
|
|
184
184
|
raise RuntimeError("QApplication instance is None. Please run the application first.")
|
185
185
|
self.viewer.show()
|
186
186
|
app.exec()
|
187
|
+
if self.viewer.exit_status == ExitStatus.CLOSE:
|
188
|
+
exit(0)
|
187
189
|
user_input = self.viewer.user_input
|
188
190
|
return user_input
|
@@ -146,7 +146,8 @@ def extract_imports(file_path: Optional[str] = None, tree: Optional[ast.AST] = N
|
|
146
146
|
def extract_function_source(file_path: str,
|
147
147
|
function_names: List[str], join_lines: bool = True,
|
148
148
|
return_line_numbers: bool = False,
|
149
|
-
include_signature: bool = True
|
149
|
+
include_signature: bool = True,
|
150
|
+
as_list: bool = False) \
|
150
151
|
-> Union[Dict[str, Union[str, List[str]]],
|
151
152
|
Tuple[Dict[str, Union[str, List[str]]], Dict[str, Tuple[int, int]]]]:
|
152
153
|
"""
|
@@ -157,6 +158,8 @@ def extract_function_source(file_path: str,
|
|
157
158
|
:param join_lines: Whether to join the lines of the function.
|
158
159
|
:param return_line_numbers: Whether to return the line numbers of the function.
|
159
160
|
:param include_signature: Whether to include the function signature in the source code.
|
161
|
+
:param as_list: Whether to return a list of function sources instead of dict (useful when there is multiple
|
162
|
+
functions with same name).
|
160
163
|
:return: A dictionary mapping function names to their source code as a string if join_lines is True,
|
161
164
|
otherwise as a list of strings.
|
162
165
|
"""
|
@@ -167,7 +170,9 @@ def extract_function_source(file_path: str,
|
|
167
170
|
tree = ast.parse(source)
|
168
171
|
function_names = make_list(function_names)
|
169
172
|
functions_source: Dict[str, Union[str, List[str]]] = {}
|
173
|
+
functions_source_list: List[Union[str, List[str]]] = []
|
170
174
|
line_numbers: Dict[str, Tuple[int, int]] = {}
|
175
|
+
line_numbers_list: List[Tuple[int, int]] = []
|
171
176
|
for node in tree.body:
|
172
177
|
if isinstance(node, ast.FunctionDef) and (node.name in function_names or len(function_names) == 0):
|
173
178
|
# Get the line numbers of the function
|
@@ -175,16 +180,24 @@ def extract_function_source(file_path: str,
|
|
175
180
|
func_lines = lines[node.lineno - 1:node.end_lineno]
|
176
181
|
if not include_signature:
|
177
182
|
func_lines = func_lines[1:]
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
+
if as_list:
|
184
|
+
line_numbers_list.append((node.lineno, node.end_lineno))
|
185
|
+
else:
|
186
|
+
line_numbers[node.name] = (node.lineno, node.end_lineno)
|
187
|
+
parsed_function = dedent("\n".join(func_lines)) if join_lines else func_lines
|
188
|
+
if as_list:
|
189
|
+
functions_source_list.append(parsed_function)
|
190
|
+
else:
|
191
|
+
functions_source[node.name] = parsed_function
|
192
|
+
if len(function_names) > 0:
|
193
|
+
if len(functions_source) >= len(function_names) or len(functions_source_list) >= len(function_names):
|
194
|
+
break
|
195
|
+
if len(functions_source) < len(function_names) and len(functions_source_list) < len(function_names):
|
183
196
|
logger.warning(f"Could not find all functions in {file_path}: {function_names} not found, "
|
184
197
|
f"functions not found: {set(function_names) - set(functions_source.keys())}")
|
185
198
|
if return_line_numbers:
|
186
|
-
return functions_source, line_numbers
|
187
|
-
return functions_source
|
199
|
+
return functions_source if not as_list else functions_source_list, line_numbers if not as_list else line_numbers_list
|
200
|
+
return functions_source if not as_list else functions_source_list
|
188
201
|
|
189
202
|
|
190
203
|
def encapsulate_user_input(user_input: str, func_signature: str, func_doc: Optional[str] = None) -> str:
|
{ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/src/ripple_down_rules.egg-info/PKG-INFO
RENAMED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: ripple_down_rules
|
3
|
-
Version: 0.6.
|
3
|
+
Version: 0.6.29
|
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
|
{ripple_down_rules-0.6.27 → ripple_down_rules-0.6.29}/src/ripple_down_rules.egg-info/SOURCES.txt
RENAMED
@@ -103,18 +103,24 @@ test/conf/world/handles_and_containers.py
|
|
103
103
|
test/factories/__init__.py
|
104
104
|
test/factories/world/__init__.py
|
105
105
|
test/factories/world/handles_and_containers.py
|
106
|
+
test/test_expert_answers/__init__.py
|
106
107
|
test/test_expert_answers/correct_drawer_rdr_expert_answers_fit.json
|
107
108
|
test/test_expert_answers/drawer_cabinet_expert_answers_fit.json
|
108
109
|
test/test_expert_answers/grdr_expert_answers_classify.json
|
109
110
|
test/test_expert_answers/grdr_expert_answers_fit.json
|
111
|
+
test/test_expert_answers/grdr_expert_answers_fit.py
|
110
112
|
test/test_expert_answers/grdr_expert_answers_fit_extra.json
|
111
113
|
test/test_expert_answers/grdr_expert_answers_fit_no_targets.json
|
114
|
+
test/test_expert_answers/grdr_expert_answers_fit_no_targets.py
|
112
115
|
test/test_expert_answers/mcrdr_expert_answers_classify.json
|
113
116
|
test/test_expert_answers/mcrdr_expert_answers_fit_no_targets.json
|
117
|
+
test/test_expert_answers/mcrdr_expert_answers_fit_no_targets.py
|
114
118
|
test/test_expert_answers/mcrdr_expert_answers_stop_only_fit.json
|
119
|
+
test/test_expert_answers/mcrdr_expert_answers_stop_only_fit.py
|
115
120
|
test/test_expert_answers/mcrdr_extra_expert_answers_classify.json
|
116
121
|
test/test_expert_answers/mcrdr_extra_expert_answers_fit.json
|
117
122
|
test/test_expert_answers/mcrdr_multi_line_expert_answers_fit.json
|
123
|
+
test/test_expert_answers/mcrdr_multi_line_expert_answers_fit.py
|
118
124
|
test/test_expert_answers/mcrdr_stop_only_answers_fit.json
|
119
125
|
test/test_expert_answers/mcrdr_stop_plus_rule_answers_fit.json
|
120
126
|
test/test_expert_answers/mcrdr_stop_plus_rule_combined_expert_answers_fit.json
|
@@ -123,8 +129,11 @@ test/test_expert_answers/mutagenic_expert_answers.json
|
|
123
129
|
test/test_expert_answers/relational_scrdr_expert_answers_classify.json
|
124
130
|
test/test_expert_answers/scrdr_expert_answers_classify.json
|
125
131
|
test/test_expert_answers/scrdr_expert_answers_fit.json
|
132
|
+
test/test_expert_answers/scrdr_expert_answers_fit.py
|
126
133
|
test/test_expert_answers/scrdr_expert_answers_fit_no_targets.json
|
134
|
+
test/test_expert_answers/scrdr_expert_answers_fit_no_targets.py
|
127
135
|
test/test_expert_answers/scrdr_multi_line_expert_answers_fit.json
|
136
|
+
test/test_expert_answers/scrdr_multi_line_expert_answers_fit.py
|
128
137
|
test/test_expert_answers/scrdr_world_expert_answers_fit.json
|
129
138
|
test/test_generated_rdrs/__init__.py
|
130
139
|
test/test_helpers/__init__.py
|
@@ -21,8 +21,9 @@ from ripple_down_rules.rdr import GeneralRDR
|
|
21
21
|
|
22
22
|
app: Optional[QApplication] = None
|
23
23
|
viewer: Optional[RDRCaseViewer] = None
|
24
|
+
use_gui: bool = False
|
24
25
|
|
25
|
-
if RDRCaseViewer is not None and QApplication is not None:
|
26
|
+
if RDRCaseViewer is not None and QApplication is not None and use_gui:
|
26
27
|
app = QApplication(sys.argv)
|
27
28
|
viewer = RDRCaseViewer(save_dir="./test_generated_rdrs")
|
28
29
|
|
@@ -69,7 +70,7 @@ def view_rdr(handles_and_containers_world, views=(Drawer, Cabinet),
|
|
69
70
|
save_answers: bool = False,
|
70
71
|
append: bool = False) -> GeneralRDR:
|
71
72
|
world = handles_and_containers_world
|
72
|
-
expert = Human(use_loaded_answers=use_loaded_answers, append=append
|
73
|
+
expert = Human(use_loaded_answers=use_loaded_answers, append=append)
|
73
74
|
filename = os.path.join(os.getcwd(), "test_expert_answers/view_rdr_expert_answers_fit")
|
74
75
|
if use_loaded_answers:
|
75
76
|
expert.load_answers(filename)
|