dc6079821b
Docs Tests / Check for file changes (push) Has been cancelled
Docs Tests / Test Documentation (push) Has been cancelled
Docs Tests / Documentation Linting Checks (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.10, test-performance) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.10, test-policies) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.8, test-cli) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.8, test-core-featurizers) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.8, test-full-model-training) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.8, test-nlu-featurizers) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.8, test-nlu-predictors) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.8, test-other-unit-tests) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.8, test-performance) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.8, test-policies) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.9, test-cli) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.9, test-core-featurizers) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.9, test-full-model-training) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.9, test-nlu-featurizers) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.9, test-nlu-predictors) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.9, test-other-unit-tests) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.9, test-performance) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.9, test-policies) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.10, test-cli) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.10, test-core-featurizers) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.10, test-full-model-training) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.10, test-nlu-featurizers) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.10, test-nlu-predictors) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.10, test-other-unit-tests) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.10, test-performance) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.10, test-policies) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.8, test-cli) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.8, test-core-featurizers) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.8, test-full-model-training) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.8, test-nlu-featurizers) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.8, test-nlu-predictors) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.8, test-other-unit-tests) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.8, test-performance) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.8, test-policies) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.9, test-cli) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.9, test-core-featurizers) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.9, test-full-model-training) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.9, test-nlu-featurizers) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.9, test-nlu-predictors) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.9, test-other-unit-tests) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.9, test-performance) (push) Has been cancelled
Continuous Integration / Run Tests (windows-2022, 3.9, test-policies) (push) Has been cancelled
Continuous Integration / Run Flaky Tests (ubuntu-24.04, 3.10) (push) Has been cancelled
Continuous Integration / Run Flaky Tests (ubuntu-24.04, 3.8) (push) Has been cancelled
Continuous Integration / Run Flaky Tests (ubuntu-24.04, 3.9) (push) Has been cancelled
Continuous Integration / Run Flaky Tests (windows-2022, 3.10) (push) Has been cancelled
Continuous Integration / Run Flaky Tests (windows-2022, 3.8) (push) Has been cancelled
Continuous Integration / Run Flaky Tests (windows-2022, 3.9) (push) Has been cancelled
Continuous Integration / Check for file changes (push) Has been cancelled
Continuous Integration / Wait for docs tests (push) Has been cancelled
Continuous Integration / Code Quality (push) Has been cancelled
Continuous Integration / Check for changelog (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.10, test-cli) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.10, test-core-featurizers) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.10, test-full-model-training) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.10, test-nlu-featurizers) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.10, test-nlu-predictors) (push) Has been cancelled
Continuous Integration / Run Tests (ubuntu-24.04, 3.10, test-other-unit-tests) (push) Has been cancelled
Continuous Integration / Upload coverage reports to codeclimate (push) Has been cancelled
Continuous Integration / Run Non-Sequential Integration Tests (push) Has been cancelled
Continuous Integration / Run Broker Integration Tests (push) Has been cancelled
Continuous Integration / Run Sequential Integration Tests (push) Has been cancelled
Continuous Integration / Build Docker base images and setup environment (push) Has been cancelled
Continuous Integration / Build Docker (default) (push) Has been cancelled
Continuous Integration / Build Docker (full) (push) Has been cancelled
Continuous Integration / Build Docker (mitie-en) (push) Has been cancelled
Continuous Integration / Build Docker (spacy-de) (push) Has been cancelled
Continuous Integration / Build Docker (spacy-en) (push) Has been cancelled
Continuous Integration / Build Docker (spacy-it) (push) Has been cancelled
Continuous Integration / Deploy to PyPI (push) Has been cancelled
Continuous Integration / Notify Slack & Publish Release Notes (push) Has been cancelled
Publish Documentation / Evaluate release tag (push) Has been cancelled
Publish Documentation / Prebuild Docs (push) Has been cancelled
Publish Documentation / Preview Docs (push) Has been cancelled
Publish Documentation / Check for file changes (push) Has been cancelled
Publish Documentation / Publish Docs (push) Has been cancelled
Automatic PR Merger / mergepal (push) Has been cancelled
CI Github Actions / Run Tests (push) Has been cancelled
Semgrep / Semgrep Workflow Security Scan (push) Has been cancelled
667 lines
19 KiB
Python
667 lines
19 KiB
Python
import builtins
|
|
import sys
|
|
import os
|
|
import string
|
|
import textwrap
|
|
import uuid
|
|
from collections import OrderedDict
|
|
from typing import Callable, Text, List, Set, Any, Dict
|
|
import copy
|
|
|
|
from pathlib import Path
|
|
import numpy as np
|
|
import pytest
|
|
from _pytest.monkeypatch import MonkeyPatch
|
|
from unittest.mock import MagicMock
|
|
|
|
import rasa.shared
|
|
from rasa.shared.nlu.training_data.features import Features
|
|
from rasa.shared.exceptions import FileIOException, FileNotFoundException, RasaException
|
|
import rasa.shared.utils.io
|
|
import rasa.shared.utils.validation
|
|
from rasa.shared.constants import NEXT_MAJOR_VERSION_FOR_DEPRECATIONS
|
|
from rasa.utils import io as io_utils
|
|
|
|
os.environ["USER_NAME"] = "user"
|
|
os.environ["PASS"] = "pass"
|
|
|
|
|
|
@pytest.mark.parametrize("file, parents", [("A/test.yml", "A"), ("A", "A")])
|
|
def test_file_in_path(file, parents):
|
|
assert rasa.shared.utils.io.is_subdirectory(file, parents)
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"file, parents", [("A", "A/B"), ("B", "A"), ("A/test.yml", "A/B"), (None, "A")]
|
|
)
|
|
def test_file_not_in_path(file, parents):
|
|
assert not rasa.shared.utils.io.is_subdirectory(file, parents)
|
|
|
|
|
|
def test_raise_user_warning():
|
|
with pytest.warns(UserWarning) as record:
|
|
rasa.shared.utils.io.raise_warning("My warning.")
|
|
|
|
assert len(record) == 1
|
|
assert record[0].message.args[0] == "My warning."
|
|
|
|
|
|
def test_raise_future_warning():
|
|
with pytest.warns(FutureWarning) as record:
|
|
rasa.shared.utils.io.raise_warning("My future warning.", FutureWarning)
|
|
|
|
assert len(record) == 1
|
|
assert record[0].message.args[0] == "My future warning."
|
|
|
|
|
|
def test_raise_deprecation():
|
|
with pytest.warns(DeprecationWarning) as record:
|
|
rasa.shared.utils.io.raise_warning("My warning.", DeprecationWarning)
|
|
|
|
assert len(record) == 1
|
|
assert record[0].message.args[0] == "My warning."
|
|
assert isinstance(record[0].message, DeprecationWarning)
|
|
|
|
|
|
def test_read_file_with_not_existing_path():
|
|
with pytest.raises(FileNotFoundException):
|
|
rasa.shared.utils.io.read_file("some path")
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"list_function, expected",
|
|
[
|
|
(
|
|
rasa.shared.utils.io.list_directory,
|
|
{"subdirectory", "subdirectory/sub_file.txt", "file.txt"},
|
|
),
|
|
(rasa.shared.utils.io.list_files, {"subdirectory/sub_file.txt", "file.txt"}),
|
|
(rasa.shared.utils.io.list_subdirectories, {"subdirectory"}),
|
|
],
|
|
)
|
|
def test_list_directory(
|
|
tmpdir: Path, list_function: Callable[[Text], List[Text]], expected: Set[Text]
|
|
):
|
|
subdirectory = tmpdir / "subdirectory"
|
|
subdirectory.mkdir()
|
|
|
|
sub_sub_directory = subdirectory / "subdirectory"
|
|
sub_sub_directory.mkdir()
|
|
|
|
sub_sub_file = sub_sub_directory / "sub_file.txt"
|
|
sub_sub_file.write_text("", encoding=rasa.shared.utils.io.DEFAULT_ENCODING)
|
|
|
|
file1 = subdirectory / "file.txt"
|
|
file1.write_text("", encoding="utf-8")
|
|
|
|
hidden_directory = subdirectory / ".hidden"
|
|
hidden_directory.mkdir()
|
|
|
|
hidden_file = subdirectory / ".test.text"
|
|
hidden_file.write_text("", encoding="utf-8")
|
|
|
|
expected = {str(subdirectory / entry) for entry in expected}
|
|
|
|
assert set(list_function(str(subdirectory))) == expected
|
|
|
|
|
|
def test_read_yaml_string():
|
|
config_without_env_var = """
|
|
user: user
|
|
password: pass
|
|
"""
|
|
content = rasa.shared.utils.io.read_yaml(config_without_env_var)
|
|
assert content["user"] == "user" and content["password"] == "pass"
|
|
|
|
|
|
def test_read_yaml_string_with_env_var():
|
|
config_with_env_var = """
|
|
user: ${USER_NAME}
|
|
password: ${PASS}
|
|
"""
|
|
content = rasa.shared.utils.io.read_yaml(config_with_env_var)
|
|
assert content["user"] == "user" and content["password"] == "pass"
|
|
|
|
|
|
def test_read_yaml_string_with_multiple_env_vars_per_line():
|
|
config_with_env_var = """
|
|
user: ${USER_NAME} ${PASS}
|
|
password: ${PASS}
|
|
"""
|
|
content = rasa.shared.utils.io.read_yaml(config_with_env_var)
|
|
assert content["user"] == "user pass" and content["password"] == "pass"
|
|
|
|
|
|
def test_read_yaml_string_with_env_var_prefix():
|
|
config_with_env_var_prefix = """
|
|
user: db_${USER_NAME}
|
|
password: db_${PASS}
|
|
"""
|
|
content = rasa.shared.utils.io.read_yaml(config_with_env_var_prefix)
|
|
assert content["user"] == "db_user" and content["password"] == "db_pass"
|
|
|
|
|
|
def test_read_yaml_string_with_env_var_postfix():
|
|
config_with_env_var_postfix = """
|
|
user: ${USER_NAME}_admin
|
|
password: ${PASS}_admin
|
|
"""
|
|
content = rasa.shared.utils.io.read_yaml(config_with_env_var_postfix)
|
|
assert content["user"] == "user_admin" and content["password"] == "pass_admin"
|
|
|
|
|
|
def test_read_yaml_string_with_env_var_infix():
|
|
config_with_env_var_infix = """
|
|
user: db_${USER_NAME}_admin
|
|
password: db_${PASS}_admin
|
|
"""
|
|
content = rasa.shared.utils.io.read_yaml(config_with_env_var_infix)
|
|
assert content["user"] == "db_user_admin" and content["password"] == "db_pass_admin"
|
|
|
|
|
|
def test_read_yaml_string_with_env_var_not_exist():
|
|
config_with_env_var_not_exist = """
|
|
user: ${USER_NAME}
|
|
password: ${PASSWORD}
|
|
"""
|
|
with pytest.raises(RasaException):
|
|
rasa.shared.utils.io.read_yaml(config_with_env_var_not_exist)
|
|
|
|
|
|
def test_environment_variable_not_existing():
|
|
content = "model: \n test: ${variable}"
|
|
with pytest.raises(RasaException):
|
|
rasa.shared.utils.io.read_yaml(content)
|
|
|
|
|
|
def test_environment_variable_dict_without_prefix_and_postfix():
|
|
os.environ["variable"] = "test"
|
|
content = "model: \n test: ${variable}"
|
|
|
|
content = rasa.shared.utils.io.read_yaml(content)
|
|
|
|
assert content["model"]["test"] == "test"
|
|
|
|
|
|
def test_environment_variable_in_list():
|
|
os.environ["variable"] = "test"
|
|
content = "model: \n - value\n - ${variable}"
|
|
|
|
content = rasa.shared.utils.io.read_yaml(content)
|
|
|
|
assert content["model"][1] == "test"
|
|
|
|
|
|
def test_environment_variable_dict_with_prefix():
|
|
os.environ["variable"] = "test"
|
|
content = "model: \n test: dir/${variable}"
|
|
|
|
content = rasa.shared.utils.io.read_yaml(content)
|
|
|
|
assert content["model"]["test"] == "dir/test"
|
|
|
|
|
|
def test_environment_variable_dict_with_postfix():
|
|
os.environ["variable"] = "test"
|
|
content = "model: \n test: ${variable}/dir"
|
|
|
|
content = rasa.shared.utils.io.read_yaml(content)
|
|
|
|
assert content["model"]["test"] == "test/dir"
|
|
|
|
|
|
def test_environment_variable_dict_with_prefix_and_with_postfix():
|
|
os.environ["variable"] = "test"
|
|
content = "model: \n test: dir/${variable}/dir"
|
|
|
|
content = rasa.shared.utils.io.read_yaml(content)
|
|
|
|
assert content["model"]["test"] == "dir/test/dir"
|
|
|
|
|
|
def test_environment_variable_with_dollar_char():
|
|
os.environ["variable1"] = "$test1"
|
|
os.environ["variable2"] = "test2"
|
|
content = "model: \n test1: ${variable1}\n test2: ${variable2}"
|
|
|
|
content = rasa.shared.utils.io.read_yaml(content)
|
|
|
|
assert content["model"]["test1"] == "$test1"
|
|
assert content["model"]["test2"] == "test2"
|
|
|
|
|
|
def test_environment_variable_with_dollar_char_in_the_middle():
|
|
os.environ["variable1"] = "test$123"
|
|
content = "model: \n test1: ${variable1}"
|
|
|
|
content = rasa.shared.utils.io.read_yaml(content)
|
|
|
|
assert content["model"]["test1"] == "test$123"
|
|
|
|
|
|
def test_emojis_in_yaml():
|
|
test_data = """
|
|
data:
|
|
- one 😁💯 👩🏿💻👨🏿💻
|
|
- two £ (?u)\\b\\w+\\b f\u00fcr
|
|
"""
|
|
content = rasa.shared.utils.io.read_yaml(test_data)
|
|
|
|
assert content["data"][0] == "one 😁💯 👩🏿💻👨🏿💻"
|
|
assert content["data"][1] == "two £ (?u)\\b\\w+\\b für"
|
|
|
|
|
|
def test_emojis_in_tmp_file():
|
|
test_data = """
|
|
data:
|
|
- one 😁💯 👩🏿💻👨🏿💻
|
|
- two £ (?u)\\b\\w+\\b f\u00fcr
|
|
"""
|
|
test_file = io_utils.create_temporary_file(test_data)
|
|
content = rasa.shared.utils.io.read_yaml_file(test_file)
|
|
|
|
assert content["data"][0] == "one 😁💯 👩🏿💻👨🏿💻"
|
|
assert content["data"][1] == "two £ (?u)\\b\\w+\\b für"
|
|
|
|
|
|
def test_read_emojis_from_json():
|
|
import json
|
|
|
|
d = {"text": "hey 😁💯 👩🏿💻👨🏿💻🧜♂️(?u)\\b\\w+\\b} f\u00fcr"}
|
|
json_string = json.dumps(d, indent=2)
|
|
|
|
content = rasa.shared.utils.io.read_yaml(json_string)
|
|
|
|
expected = "hey 😁💯 👩🏿💻👨🏿💻🧜♂️(?u)\\b\\w+\\b} für"
|
|
assert content.get("text") == expected
|
|
|
|
|
|
def test_bool_str():
|
|
test_data = """
|
|
one: "yes"
|
|
two: "true"
|
|
three: "True"
|
|
"""
|
|
|
|
content = rasa.shared.utils.io.read_yaml(test_data)
|
|
|
|
assert content["one"] == "yes"
|
|
assert content["two"] == "true"
|
|
assert content["three"] == "True"
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"should_preserve_key_order, expected_keys",
|
|
[(True, list(reversed(string.ascii_lowercase)))],
|
|
)
|
|
def test_dump_yaml_key_order(
|
|
tmp_path: Path, should_preserve_key_order: bool, expected_keys: List[Text]
|
|
):
|
|
file = tmp_path / "test.yml"
|
|
|
|
# create YAML file with keys in reverse-alphabetical order
|
|
content = ""
|
|
for i in reversed(string.ascii_lowercase):
|
|
content += f"{i}: {uuid.uuid4().hex}\n"
|
|
|
|
file.write_text(content)
|
|
|
|
# load this file and ensure keys are in correct reverse-alphabetical order
|
|
data = rasa.shared.utils.io.read_yaml_file(file)
|
|
assert list(data.keys()) == list(reversed(string.ascii_lowercase))
|
|
|
|
# dumping `data` will result in alphabetical or reverse-alphabetical list of keys,
|
|
# depending on the value of `should_preserve_key_order`
|
|
rasa.shared.utils.io.write_yaml(
|
|
data, file, should_preserve_key_order=should_preserve_key_order
|
|
)
|
|
with file.open() as f:
|
|
keys = [line.split(":")[0] for line in f.readlines()]
|
|
|
|
assert keys == expected_keys
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"source, target",
|
|
[
|
|
# ordinary dictionary
|
|
({"b": "b", "a": "a"}, OrderedDict({"b": "b", "a": "a"})),
|
|
# dict with list
|
|
({"b": [1, 2, 3]}, OrderedDict({"b": [1, 2, 3]})),
|
|
# nested dict
|
|
({"b": {"c": "d"}}, OrderedDict({"b": OrderedDict({"c": "d"})})),
|
|
# doubly-nested dict
|
|
(
|
|
{"b": {"c": {"d": "e"}}},
|
|
OrderedDict({"b": OrderedDict({"c": OrderedDict({"d": "e"})})}),
|
|
),
|
|
# a list is not affected
|
|
([1, 2, 3], [1, 2, 3]),
|
|
# a string also isn't
|
|
("hello", "hello"),
|
|
],
|
|
)
|
|
def test_convert_to_ordered_dict(source: Any, target: Any):
|
|
assert rasa.shared.utils.io.convert_to_ordered_dict(source) == target
|
|
|
|
def _recursively_check_dict_is_ordered_dict(d):
|
|
if isinstance(d, dict):
|
|
assert isinstance(d, OrderedDict)
|
|
for value in d.values():
|
|
_recursively_check_dict_is_ordered_dict(value)
|
|
|
|
# ensure nested dicts are converted correctly
|
|
_recursively_check_dict_is_ordered_dict(target)
|
|
|
|
|
|
def test_create_directory_for_file(tmp_path: Path):
|
|
file = str(tmp_path / "dir" / "test.txt")
|
|
|
|
rasa.shared.utils.io.create_directory_for_file(str(file))
|
|
assert not os.path.exists(file)
|
|
assert os.path.exists(os.path.dirname(file))
|
|
|
|
|
|
def test_write_utf_8_yaml_file(tmp_path: Path):
|
|
"""This test makes sure that dumping a yaml doesn't result in Uxxxx sequences
|
|
but rather directly dumps the unicode character."""
|
|
|
|
file_path = str(tmp_path / "test.yml")
|
|
data = {"data": "amazing 🌈"}
|
|
|
|
rasa.shared.utils.io.write_yaml(data, file_path)
|
|
assert rasa.shared.utils.io.read_file(file_path) == "data: amazing 🌈\n"
|
|
|
|
|
|
def test_write_json_file(tmp_path: Path):
|
|
expected = {"abc": "dasds", "list": [1, 2, 3, 4], "nested": {"a": "b"}}
|
|
file_path = str(tmp_path / "abc.txt")
|
|
|
|
rasa.shared.utils.io.dump_obj_as_json_to_file(file_path, expected)
|
|
assert rasa.shared.utils.io.read_json_file(file_path) == expected
|
|
|
|
|
|
def test_create_directory_if_new(tmp_path: Path):
|
|
directory = str(tmp_path / "a" / "b")
|
|
rasa.shared.utils.io.create_directory(directory)
|
|
|
|
assert os.path.exists(directory)
|
|
|
|
|
|
def test_create_directory_if_already_exists(tmp_path: Path):
|
|
# This should not throw an exception
|
|
rasa.shared.utils.io.create_directory(str(tmp_path))
|
|
assert True
|
|
|
|
|
|
def test_raise_deprecation_warning():
|
|
with pytest.warns(FutureWarning) as record:
|
|
rasa.shared.utils.io.raise_deprecation_warning(
|
|
"This feature is deprecated.", warn_until_version="3.0.0"
|
|
)
|
|
|
|
assert len(record) == 1
|
|
assert (
|
|
record[0].message.args[0]
|
|
== "This feature is deprecated. (will be removed in 3.0.0)"
|
|
)
|
|
|
|
|
|
def test_raise_deprecation_warning_version_already_in_message():
|
|
with pytest.warns(FutureWarning) as record:
|
|
rasa.shared.utils.io.raise_deprecation_warning(
|
|
"This feature is deprecated and will be removed in 3.0.0!",
|
|
warn_until_version="3.0.0",
|
|
)
|
|
|
|
assert len(record) == 1
|
|
assert (
|
|
record[0].message.args[0]
|
|
== "This feature is deprecated and will be removed in 3.0.0!"
|
|
)
|
|
|
|
|
|
def test_raise_deprecation_warning_default():
|
|
with pytest.warns(FutureWarning) as record:
|
|
rasa.shared.utils.io.raise_deprecation_warning("This feature is deprecated.")
|
|
|
|
assert len(record) == 1
|
|
assert record[0].message.args[0] == (
|
|
f"This feature is deprecated. "
|
|
f"(will be removed in {NEXT_MAJOR_VERSION_FOR_DEPRECATIONS})"
|
|
)
|
|
|
|
|
|
def test_read_file_with_wrong_encoding(tmp_path: Path):
|
|
file = tmp_path / "myfile.txt"
|
|
file.write_text("ä", encoding="latin-1")
|
|
with pytest.raises(FileIOException):
|
|
rasa.shared.utils.io.read_file(file)
|
|
|
|
|
|
@pytest.mark.parametrize("config_file", Path("data", "configs_for_docs").glob("*.yml"))
|
|
def test_validate_config_file(config_file: Path):
|
|
# does not raise
|
|
rasa.shared.utils.io.read_model_configuration(config_file)
|
|
|
|
|
|
def test_validate_config_file_with_extra_keys(tmp_path: Path):
|
|
content = textwrap.dedent(
|
|
"""
|
|
recipe: default.v1
|
|
language: en
|
|
pipeline:
|
|
policies:
|
|
|
|
importers:
|
|
- RasaFileImporter
|
|
"""
|
|
)
|
|
config_file = tmp_path / "config.yml"
|
|
config_file.write_text(content)
|
|
|
|
rasa.shared.utils.io.read_model_configuration(config_file)
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"config",
|
|
[
|
|
# Pre 2.x pipeline templates are invalid
|
|
textwrap.dedent(
|
|
"""
|
|
pipeline: supervised_embeddings
|
|
"""
|
|
),
|
|
# Each list item needs the `name` property
|
|
textwrap.dedent(
|
|
"""
|
|
pipeline:
|
|
- DIETClassier
|
|
policies:
|
|
"""
|
|
),
|
|
# Name property is missing
|
|
textwrap.dedent(
|
|
"""
|
|
pipeline:
|
|
policies:
|
|
- some_attribute: "lala"
|
|
"""
|
|
),
|
|
# Name property is not a string
|
|
textwrap.dedent(
|
|
"""
|
|
pipeline:
|
|
policies:
|
|
- name: 1234
|
|
"""
|
|
),
|
|
# Invalid training data version
|
|
textwrap.dedent(
|
|
"""
|
|
version: 2.0
|
|
policies:
|
|
pipeline:
|
|
"""
|
|
),
|
|
# Language has wrong type
|
|
textwrap.dedent(
|
|
"""
|
|
language: []
|
|
policies:
|
|
pipeline:
|
|
"""
|
|
),
|
|
],
|
|
)
|
|
def test_invalid_config_files(config: Text, tmp_path: Path):
|
|
config_file = tmp_path / "config.yml"
|
|
config_file.write_text(config)
|
|
with pytest.raises(rasa.shared.utils.validation.YamlValidationException):
|
|
rasa.shared.utils.io.read_model_configuration(config_file)
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"content, expected",
|
|
[
|
|
("rest:", {"rest": None}),
|
|
(
|
|
textwrap.dedent(
|
|
"""
|
|
tracker_store:
|
|
password: test
|
|
"""
|
|
),
|
|
{"tracker_store": {"password": "test"}},
|
|
),
|
|
],
|
|
)
|
|
def test_read_config_file(tmp_path: Path, content: Text, expected: Dict):
|
|
config_file = tmp_path / "file.yml"
|
|
config_file.write_text(content)
|
|
|
|
assert rasa.shared.utils.io.read_config_file(config_file) == expected
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"content",
|
|
[
|
|
"text",
|
|
textwrap.dedent(
|
|
"""
|
|
- item1
|
|
- item2
|
|
"""
|
|
),
|
|
],
|
|
)
|
|
def test_read_invalid_config_file(tmp_path: Path, content: Text):
|
|
config_file = tmp_path / "file.yml"
|
|
config_file.write_text(content)
|
|
|
|
with pytest.raises(rasa.shared.utils.validation.YamlValidationException):
|
|
rasa.shared.utils.io.read_model_configuration(config_file)
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"file,keys,expected_result",
|
|
[
|
|
("data/test_yaml_stories/stories.yml", ["stories"], True),
|
|
("data/test_yaml_stories/stories.yml", ["something_else"], False),
|
|
("data/test_yaml_stories/stories.yml", ["stories", "something_else"], True),
|
|
(
|
|
"data/test_domains/default_retrieval_intents.yml",
|
|
["intents", "responses"],
|
|
True,
|
|
),
|
|
("data/test_yaml_stories/rules_without_stories.yml", ["rules"], True),
|
|
("data/test_yaml_stories/rules_without_stories.yml", ["stories"], False),
|
|
],
|
|
)
|
|
async def test_is_key_in_yaml(file: Text, keys: List[Text], expected_result: bool):
|
|
assert rasa.shared.utils.io.is_key_in_yaml(file, *keys) == expected_result
|
|
|
|
|
|
async def test_is_key_in_yaml_with_unicode_files():
|
|
# This shouldn't raise
|
|
assert rasa.shared.utils.io.is_key_in_yaml(
|
|
"./data/test_nlu_no_responses/nlu_with_unicode.yml", "nlu"
|
|
)
|
|
|
|
|
|
@pytest.mark.parametrize("length", [4, 8, 16, 32])
|
|
def test_random_string(length):
|
|
|
|
s = rasa.shared.utils.io.random_string(length)
|
|
s2 = rasa.shared.utils.io.random_string(length)
|
|
|
|
assert len(s) == length
|
|
assert len(s2) == length
|
|
assert s != s2
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"container",
|
|
[
|
|
{},
|
|
{"hello": "world"},
|
|
{1: 2},
|
|
{"foo": ["bar"]},
|
|
{"a": []},
|
|
[],
|
|
["a"],
|
|
[{}],
|
|
[None],
|
|
],
|
|
)
|
|
def test_fingerprint_containers(container):
|
|
assert rasa.shared.utils.io.deep_container_fingerprint(
|
|
container
|
|
) == rasa.shared.utils.io.deep_container_fingerprint(copy.deepcopy(container))
|
|
|
|
|
|
def test_deep_container_fingerprint_can_use_instance_fingerprint():
|
|
m1 = np.asarray([[0.5, 3.1, 3.0], [1.1, 1.2, 1.3], [4.7, 0.3, 2.7]])
|
|
f = Features(m1, "sentence", "text", "CountVectorsFeaturizer")
|
|
assert rasa.shared.utils.io.deep_container_fingerprint(f) == f.fingerprint()
|
|
|
|
|
|
@pytest.mark.skip_on_windows
|
|
def test_handle_print_blocking(monkeypatch: MonkeyPatch):
|
|
mock = MagicMock()
|
|
monkeypatch.setattr(rasa.shared.utils.io, "portalocker", mock)
|
|
|
|
print_output = "Test block handling"
|
|
rasa.shared.utils.io.handle_print_blocking(print_output)
|
|
|
|
assert mock.Lock.called
|
|
assert mock.Lock.call_args[0][0] == sys.stdout
|
|
|
|
# print specific calls
|
|
# STDOUT write call
|
|
assert mock.mock_calls[2][1][0] == print_output
|
|
# STDOUT was flushed before __exit__
|
|
assert "flush" in mock.mock_calls[-2][0]
|
|
|
|
|
|
@pytest.mark.skipif(sys.platform != "win32", reason="Windows only test")
|
|
def test_handle_print_blocking_windows(monkeypatch: MonkeyPatch):
|
|
mock = MagicMock()
|
|
mock_print = MagicMock()
|
|
monkeypatch.setattr(rasa.shared.utils.io, "portalocker", mock)
|
|
monkeypatch.setattr(builtins, "print", mock_print)
|
|
|
|
print_output = "Test block handling"
|
|
rasa.shared.utils.io.handle_print_blocking(print_output)
|
|
|
|
assert mock.Lock.called
|
|
assert mock.Lock.call_args[0][0] == sys.stdout
|
|
|
|
assert mock_print.called
|
|
assert mock_print.call_args[0][0] == print_output
|
|
|
|
from colorama import ansitowin32
|
|
|
|
assert isinstance(mock_print.call_args[1]["file"], ansitowin32.StreamWrapper)
|
|
assert mock_print.call_args[1]["flush"]
|