def test_not_in_imports(input_path: Text, tmpdir_factory: TempdirFactory): root = tmpdir_factory.mktemp("Parent Bot") config_path = str(root / "config.yml") utils.dump_obj_as_yaml_to_file(root / "config.yml", {"imports": ["A/A/A", "A/B/A"]}) importer = MultiProjectImporter(config_path, project_directory=os.getcwd()) assert not importer.is_imported(input_path)
def test_not_in_imports(input_path: Text, tmp_path: Path): config_path = str(tmp_path / "config.yml") utils.dump_obj_as_yaml_to_file(tmp_path / "config.yml", {"imports": ["A/A/A", "A/B/A"]}) importer = MultiProjectImporter(config_path, project_directory=os.getcwd()) assert not importer.is_imported(input_path)
def test_not_importing_e2e_conversation_tests_in_project( tmpdir_factory: TempdirFactory, ): root = tmpdir_factory.mktemp("Parent Bot") config = {"imports": ["bots/Bot A"]} config_path = str(root / "config.yml") utils.dump_obj_as_yaml_to_file(config_path, config) story_file = root / "bots" / "Bot A" / "data" / "stories.md" story_file.write("""## story""", ensure=True) e2e_story_test_file = ( root / "bots" / "Bot A" / DEFAULT_E2E_TESTS_PATH / "conversation_tests.md" ) e2e_story_test_file.write( """## story test""", ensure=True, ) selector = MultiProjectImporter(config_path) # Conversation tests should not be included in story paths expected = { "story_paths": [str(story_file)], "e2e_story_paths": [str(e2e_story_test_file)], } actual = { "story_paths": selector._story_paths, "e2e_story_paths": selector._e2e_story_paths, } assert expected == actual
def test_load_from_none(input_dict: Dict, tmp_path: Path): config_path = tmp_path / "config.yml" utils.dump_obj_as_yaml_to_file(tmp_path / "config.yml", input_dict) actual = MultiProjectImporter(str(config_path)) assert actual._imports == list()
def persist_clean(self, filename: Text) -> None: """Write cleaned domain to a file.""" cleaned_domain_data = self.cleaned_domain() utils.dump_obj_as_yaml_to_file( filename, cleaned_domain_data, should_preserve_key_order=True )
def persist(self, filename: Union[Text, Path]) -> None: """Write domain to a file.""" domain_data = self.as_dict() utils.dump_obj_as_yaml_to_file( filename, domain_data, should_preserve_key_order=True )
def persist_clean(self, filename: Text) -> None: """Write domain to a file. Strips redundant keys with default values.""" data = self.as_dict() for idx, intent_info in enumerate(data["intents"]): for name, intent in intent_info.items(): if intent.get("use_entities"): data["intents"][idx] = name for slot in data["slots"].values(): if slot["initial_value"] is None: del slot["initial_value"] if slot["auto_fill"]: del slot["auto_fill"] if slot["type"].startswith("rasa.core.slots"): slot["type"] = Slot.resolve_by_type(slot["type"]).type_name if data["config"]["store_entities_as_slots"]: del data["config"]["store_entities_as_slots"] # clean empty keys data = { k: v for k, v in data.items() if v != {} and v != [] and v is not None } utils.dump_obj_as_yaml_to_file(filename, data)
def test_load_from_none(input_dict: Dict, tmpdir_factory: TempdirFactory): root = tmpdir_factory.mktemp("Parent Bot") config_path = root / "config.yml" utils.dump_obj_as_yaml_to_file(root / "config.yml", input_dict) actual = MultiProjectImporter(str(config_path)) assert actual._imports == list()
def test_load_if_subskill_is_more_specific_than_parent(tmpdir_factory: TempdirFactory): root = tmpdir_factory.mktemp("Parent Bot") config_path = root / "config.yml" utils.dump_obj_as_yaml_to_file(root / "config.yml", {}) skill_a_directory = root / "Skill A" skill_a_directory.mkdir() skill_a_imports = {"imports": ["Skill B"]} utils.dump_obj_as_yaml_to_file(skill_a_directory / "config.yml", skill_a_imports) actual = SkillSelector.load(config_path) assert actual.is_imported(str(skill_a_directory))
def test_load_if_subproject_is_more_specific_than_parent(tmp_path: Path, ): config_path = str(tmp_path / "config.yml") utils.dump_obj_as_yaml_to_file(tmp_path / "config.yml", {}) project_a_directory = tmp_path / "Project A" project_a_directory.mkdir() project_a_imports = {"imports": ["Project B"]} utils.dump_obj_as_yaml_to_file(project_a_directory / "config.yml", project_a_imports) actual = MultiProjectImporter(config_path) assert actual.is_imported(str(project_a_directory))
def test_single_additional_file(tmp_path: Path): config_path = str(tmp_path / "config.yml") empty_config = {} utils.dump_obj_as_yaml_to_file(config_path, empty_config) additional_file = tmp_path / "directory" / "file.yml" additional_file.parent.mkdir() rasa.shared.utils.io.write_yaml({}, additional_file) selector = MultiProjectImporter(config_path, training_data_paths=str(additional_file)) assert selector.is_imported(str(additional_file))
def test_single_additional_file(tmpdir_factory): root = tmpdir_factory.mktemp("Parent Bot") config_path = str(root / "config.yml") empty_config = {} utils.dump_obj_as_yaml_to_file(config_path, empty_config) additional_file = root / "directory" / "file.yml" additional_file.write({}, ensure=True) selector = MultiProjectImporter(config_path, training_data_paths=str(additional_file)) assert selector.is_imported(str(additional_file))
async def test_only_getting_e2e_conversation_tests_if_e2e_enabled( tmpdir_factory: TempdirFactory, ): from rasa.core.interpreter import RegexInterpreter from rasa.core.training.structures import StoryGraph import rasa.core.training.loading as core_loading root = tmpdir_factory.mktemp("Parent Bot") config = {"imports": ["bots/Bot A"]} config_path = str(root / "config.yml") utils.dump_obj_as_yaml_to_file(config_path, config) story_file = root / "bots" / "Bot A" / "data" / "stories.md" story_file.write( """ ## story * greet - utter_greet """, ensure=True, ) e2e_story_test_file = ( root / "bots" / "Bot A" / DEFAULT_E2E_TESTS_PATH / "conversation_tests.md" ) e2e_story_test_file.write( """ ## story test * greet : "hello" - utter_greet """, ensure=True, ) selector = MultiProjectImporter(config_path) story_steps = await core_loading.load_data_from_resource( resource=str(e2e_story_test_file), domain=Domain.empty(), interpreter=RegexInterpreter(), template_variables=None, use_e2e=True, exclusion_percentage=None, ) expected = StoryGraph(story_steps) actual = await selector.get_stories(use_e2e=True) assert expected.as_story_string() == actual.as_story_string()
def test_load_imports_from_directory_tree(tmp_path: Path): root_imports = {"imports": ["Project A"]} utils.dump_obj_as_yaml_to_file(tmp_path / "config.yml", root_imports) project_a_directory = tmp_path / "Project A" project_a_directory.mkdir() project_a_imports = {"imports": ["../Project B"]} utils.dump_obj_as_yaml_to_file(project_a_directory / "config.yml", project_a_imports) project_b_directory = tmp_path / "Project B" project_b_directory.mkdir() project_b_imports = {"some other": ["../Project C"]} utils.dump_obj_as_yaml_to_file(project_b_directory / "config.yml", project_b_imports) project_b_subproject_directory = project_b_directory / "Project B-1" project_b_subproject_directory.mkdir() project_b_1_imports = {"imports": ["../../Project A"]} # Check if loading from `.yaml` also works utils.dump_obj_as_yaml_to_file( project_b_subproject_directory / "config.yaml", project_b_1_imports) # should not be imported subdirectory_3 = tmp_path / "Project C" subdirectory_3.mkdir() expected = [ os.path.join(str(project_a_directory)), os.path.join(str(project_b_directory)), ] actual = MultiProjectImporter(str(tmp_path / "config.yml")) assert actual._imports == expected
def test_load_domain_from_directory_tree(tmp_path: Path): root_domain = {"actions": ["utter_root", "utter_root2"]} utils.dump_obj_as_yaml_to_file(tmp_path / "domain_pt1.yml", root_domain) subdirectory_1 = tmp_path / "Skill 1" subdirectory_1.mkdir() skill_1_domain = {"actions": ["utter_skill_1"]} utils.dump_obj_as_yaml_to_file(subdirectory_1 / "domain_pt2.yml", skill_1_domain) subdirectory_2 = tmp_path / "Skill 2" subdirectory_2.mkdir() skill_2_domain = {"actions": ["utter_skill_2"]} utils.dump_obj_as_yaml_to_file(subdirectory_2 / "domain_pt3.yml", skill_2_domain) subsubdirectory = subdirectory_2 / "Skill 2-1" subsubdirectory.mkdir() skill_2_1_domain = {"actions": ["utter_subskill", "utter_root"]} # Check if loading from `.yaml` also works utils.dump_obj_as_yaml_to_file( subsubdirectory / "domain_pt4.yaml", skill_2_1_domain ) actual = Domain.load(str(tmp_path)) expected = [ "utter_root", "utter_root2", "utter_skill_1", "utter_skill_2", "utter_subskill", ] assert set(actual.user_actions) == set(expected)
def test_load_imports_from_directory_tree(tmpdir_factory: TempdirFactory): root = tmpdir_factory.mktemp("Parent Bot") root_imports = {"imports": ["Skill A"]} utils.dump_obj_as_yaml_to_file(root / "config.yml", root_imports) skill_a_directory = root / "Skill A" skill_a_directory.mkdir() skill_a_imports = {"imports": ["../Skill B"]} utils.dump_obj_as_yaml_to_file(skill_a_directory / "config.yml", skill_a_imports) skill_b_directory = root / "Skill B" skill_b_directory.mkdir() skill_b_imports = {"some other": ["../Skill C"]} utils.dump_obj_as_yaml_to_file(skill_b_directory / "config.yml", skill_b_imports) skill_b_subskill_directory = skill_b_directory / "Skill B-1" skill_b_subskill_directory.mkdir() skill_b_1_imports = {"imports": ["../../Skill A"]} # Check if loading from `.yaml` also works utils.dump_obj_as_yaml_to_file( skill_b_subskill_directory / "config.yaml", skill_b_1_imports ) # should not be imported subdirectory_3 = root / "Skill C" subdirectory_3.mkdir() actual = SkillSelector.load(root / "config.yml") expected = { os.path.join(str(skill_a_directory)), os.path.join(str(skill_b_directory)), } assert actual._imports == expected
def test_load_if_subproject_is_more_specific_than_parent( tmpdir_factory: TempdirFactory): root = tmpdir_factory.mktemp("Parent Bot") config_path = str(root / "config.yml") utils.dump_obj_as_yaml_to_file(root / "config.yml", {}) project_a_directory = root / "Project A" project_a_directory.mkdir() project_a_imports = {"imports": ["Project B"]} utils.dump_obj_as_yaml_to_file(project_a_directory / "config.yml", project_a_imports) actual = MultiProjectImporter(config_path) assert actual.is_imported(str(project_a_directory))
async def test_only_getting_e2e_conversation_tests_if_e2e_enabled( tmp_path: Path): from rasa.shared.core.training_data.structures import StoryGraph import rasa.shared.core.training_data.loading as core_loading config = {"imports": ["bots/Bot A"]} config_path = str(tmp_path / "config.yml") utils.dump_obj_as_yaml_to_file(config_path, config) story_file = tmp_path / "bots" / "Bot A" / "data" / "stories.yml" story_file.parent.mkdir(parents=True) rasa.shared.utils.io.write_text_file( """ stories: - story: story steps: - intent: greet - action: utter_greet """, story_file, ) test_story = """ stories: - story: story test steps: - user: hello intent: greet - action: utter_greet """ story_test_file = tmp_path / "bots" / "Bot A" / "test_stories.yml" rasa.shared.utils.io.write_text_file(test_story, story_test_file) selector = MultiProjectImporter(config_path) story_steps = await core_loading.load_data_from_resource( resource=str(story_test_file), domain=Domain.empty(), template_variables=None, use_e2e=True, exclusion_percentage=None, ) expected = StoryGraph(story_steps) actual = await selector.get_stories(use_e2e=True) assert expected.as_story_string() == actual.as_story_string()
def test_importing_additional_files(tmpdir_factory): root = tmpdir_factory.mktemp("Parent Bot") config = {"imports": ["bots/Bot A"]} config_path = str(root / "config.yml") utils.dump_obj_as_yaml_to_file(config_path, config) additional_file = root / "directory" / "file.md" # create intermediate directories and fake files additional_file.write("""## story""", ensure=True) selector = MultiProjectImporter( config_path, training_data_paths=[str(root / "directory"), str(additional_file)] ) assert selector.is_imported(str(additional_file)) assert str(additional_file) in selector._story_paths
def test_importing_additional_files(tmp_path: Path): config = {"imports": ["bots/Bot A"]} config_path = str(tmp_path / "config.yml") utils.dump_obj_as_yaml_to_file(config_path, config) additional_file = tmp_path / "directory" / "file.md" additional_file.parent.mkdir() # create intermediate directories and fake files rasa.shared.utils.io.write_text_file("""## story""", additional_file) selector = MultiProjectImporter( config_path, training_data_paths=[str(tmp_path / "directory"), str(additional_file)], ) assert selector.is_imported(str(additional_file)) assert str(additional_file) in selector._story_paths
def test_not_importing_e2e_conversation_tests_in_project(tmp_path: Path,): config = {"imports": ["bots/Bot A"]} config_path = str(tmp_path / "config.yml") utils.dump_obj_as_yaml_to_file(config_path, config) story_file = tmp_path / "bots" / "Bot A" / "data" / "stories.md" story_file.parent.mkdir(parents=True) rasa.shared.utils.io.write_text_file("""## story""", story_file) story_test_file = tmp_path / "bots" / "Bot A" / "test_stories.yml" rasa.shared.utils.io.write_text_file("""stories:""", story_test_file) selector = MultiProjectImporter(config_path) # Conversation tests should not be included in story paths assert [str(story_file)] == selector._story_paths assert [str(story_test_file)] == selector._e2e_story_paths
def test_not_importing_not_relevant_additional_files(tmpdir_factory): root = tmpdir_factory.mktemp("Parent Bot") config = {"imports": ["bots/Bot A"]} config_path = str(root / "config.yml") utils.dump_obj_as_yaml_to_file(config_path, config) additional_file = root / "directory" / "file.yml" selector = MultiProjectImporter( config_path, training_data_paths=[str(root / "data"), str(additional_file)] ) not_relevant_file1 = root / "data" / "another directory" / "file.yml" not_relevant_file1.write({}, ensure=True) not_relevant_file2 = root / "directory" / "another_file.yml" not_relevant_file2.write({}, ensure=True) assert not selector.is_imported(str(not_relevant_file1)) assert not selector.is_imported(str(not_relevant_file2))
def test_not_importing_not_relevant_additional_files(tmp_path: Path): config = {"imports": ["bots/Bot A"]} config_path = str(tmp_path / "config.yml") utils.dump_obj_as_yaml_to_file(config_path, config) additional_file = tmp_path / "directory" / "file.yml" additional_file.parent.mkdir() selector = MultiProjectImporter( config_path, training_data_paths=[str(tmp_path / "data"), str(additional_file)] ) not_relevant_file1 = tmp_path / "data" / "another directory" / "file.yml" not_relevant_file1.parent.mkdir(parents=True) rasa.shared.utils.io.write_text_file("", not_relevant_file1) not_relevant_file2 = tmp_path / "directory" / "another_file.yml" rasa.shared.utils.io.write_text_file("", not_relevant_file2) assert not selector.is_imported(str(not_relevant_file1)) assert not selector.is_imported(str(not_relevant_file2))
def test_load_domain_from_directory_tree(tmpdir_factory: TempdirFactory): root = tmpdir_factory.mktemp("Parent Bot") root_domain = {"actions": ["utter_root", "utter_root2"]} utils.dump_obj_as_yaml_to_file(root / "domain.yml", root_domain) subdirectory_1 = root / "Skill 1" subdirectory_1.mkdir() skill_1_domain = {"actions": ["utter_skill_1"]} utils.dump_obj_as_yaml_to_file(subdirectory_1 / "domain.yml", skill_1_domain) subdirectory_2 = root / "Skill 2" subdirectory_2.mkdir() skill_2_domain = {"actions": ["utter_skill_2"]} utils.dump_obj_as_yaml_to_file(subdirectory_2 / "domain.yml", skill_2_domain) subsubdirectory = subdirectory_2 / "Skill 2-1" subsubdirectory.mkdir() skill_2_1_domain = {"actions": ["utter_subskill", "utter_root"]} # Check if loading from `.yaml` also works utils.dump_obj_as_yaml_to_file(subsubdirectory / "domain.yaml", skill_2_1_domain) subsubdirectory_2 = subdirectory_2 / "Skill 2-2" subsubdirectory_2.mkdir() excluded_domain = {"actions": ["should not be loaded"]} utils.dump_obj_as_yaml_to_file(subsubdirectory_2 / "other_name.yaml", excluded_domain) actual = Domain.load(str(root)) expected = [ "utter_root", "utter_root2", "utter_skill_1", "utter_skill_2", "utter_subskill", ] assert set(actual.user_actions) == set(expected)
def test_load_imports_without_imports(tmp_path: Path): empty_config = {} utils.dump_obj_as_yaml_to_file(tmp_path / "config.yml", empty_config) project_a_directory = tmp_path / "Project A" project_a_directory.mkdir() utils.dump_obj_as_yaml_to_file(project_a_directory / "config.yml", empty_config) project_b_directory = tmp_path / "Project B" project_b_directory.mkdir() utils.dump_obj_as_yaml_to_file(project_b_directory / "config.yml", empty_config) actual = MultiProjectImporter(str(tmp_path / "config.yml")) assert actual.is_imported(str(tmp_path / "Project C"))
def test_load_imports_without_imports(tmpdir_factory: TempdirFactory): empty_config = {} root = tmpdir_factory.mktemp("Parent Bot") utils.dump_obj_as_yaml_to_file(root / "config.yml", empty_config) project_a_directory = root / "Project A" project_a_directory.mkdir() utils.dump_obj_as_yaml_to_file(project_a_directory / "config.yml", empty_config) project_b_directory = root / "Project B" project_b_directory.mkdir() utils.dump_obj_as_yaml_to_file(project_b_directory / "config.yml", empty_config) actual = MultiProjectImporter(str(root / "config.yml")) assert actual.is_imported(str(root / "Project C"))
def test_load_imports_without_imports(tmpdir_factory: TempdirFactory): empty_config = {} root = tmpdir_factory.mktemp("Parent Bot") utils.dump_obj_as_yaml_to_file(root / "config.yml", empty_config) skill_a_directory = root / "Skill A" skill_a_directory.mkdir() utils.dump_obj_as_yaml_to_file(skill_a_directory / "config.yml", empty_config) skill_b_directory = root / "Skill B" skill_b_directory.mkdir() utils.dump_obj_as_yaml_to_file(skill_b_directory / "config.yml", empty_config) actual = SkillSelector.load(root / "config.yml") assert actual.is_imported(root / "Skill C")
def test_import_outside_project_directory(tmpdir_factory): root = tmpdir_factory.mktemp("Parent Bot") skill_imports = {"imports": ["Skill A"]} utils.dump_obj_as_yaml_to_file(root / "config.yml", skill_imports) skill_a_directory = root / "Skill A" skill_a_directory.mkdir() skill_a_imports = {"imports": ["../Skill B"]} utils.dump_obj_as_yaml_to_file(skill_a_directory / "config.yml", skill_a_imports) skill_b_directory = root / "Skill B" skill_b_directory.mkdir() skill_b_imports = {"imports": ["../Skill C"]} utils.dump_obj_as_yaml_to_file(skill_b_directory / "config.yml", skill_b_imports) actual = SkillSelector.load(skill_a_directory / "config.yml") assert actual._imports == {str(skill_b_directory), str(root / "Skill C")}
def test_import_outside_project_directory(tmp_path: Path): project_imports = {"imports": ["Project A"]} utils.dump_obj_as_yaml_to_file(tmp_path / "config.yml", project_imports) project_a_directory = tmp_path / "Project A" project_a_directory.mkdir() project_a_imports = {"imports": ["../Project B"]} utils.dump_obj_as_yaml_to_file( project_a_directory / "config.yml", project_a_imports ) project_b_directory = tmp_path / "Project B" project_b_directory.mkdir() project_b_imports = {"imports": ["../Project C"]} utils.dump_obj_as_yaml_to_file( project_b_directory / "config.yml", project_b_imports ) actual = MultiProjectImporter(str(project_a_directory / "config.yml")) assert actual._imports == [str(project_b_directory), str(tmp_path / "Project C")]
def test_import_outside_project_directory(tmpdir_factory): root = tmpdir_factory.mktemp("Parent Bot") project_imports = {"imports": ["Project A"]} utils.dump_obj_as_yaml_to_file(root / "config.yml", project_imports) project_a_directory = root / "Project A" project_a_directory.mkdir() project_a_imports = {"imports": ["../Project B"]} utils.dump_obj_as_yaml_to_file( project_a_directory / "config.yml", project_a_imports ) project_b_directory = root / "Project B" project_b_directory.mkdir() project_b_imports = {"imports": ["../Project C"]} utils.dump_obj_as_yaml_to_file( project_b_directory / "config.yml", project_b_imports ) actual = MultiProjectImporter(str(project_a_directory / "config.yml")) assert actual._imports == [str(project_b_directory), str(root / "Project C")]