rasa-pro 3.9.18__py3-none-any.whl → 3.10.16__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of rasa-pro might be problematic. Click here for more details.
- README.md +0 -374
- rasa/__init__.py +1 -2
- rasa/__main__.py +5 -0
- rasa/anonymization/anonymization_rule_executor.py +2 -2
- rasa/api.py +27 -23
- rasa/cli/arguments/data.py +27 -2
- rasa/cli/arguments/default_arguments.py +25 -3
- rasa/cli/arguments/run.py +9 -9
- rasa/cli/arguments/train.py +11 -3
- rasa/cli/data.py +70 -8
- rasa/cli/e2e_test.py +104 -431
- rasa/cli/evaluate.py +1 -1
- rasa/cli/interactive.py +1 -0
- rasa/cli/llm_fine_tuning.py +398 -0
- rasa/cli/project_templates/calm/endpoints.yml +1 -1
- rasa/cli/project_templates/tutorial/endpoints.yml +1 -1
- rasa/cli/run.py +15 -14
- rasa/cli/scaffold.py +10 -8
- rasa/cli/studio/studio.py +35 -5
- rasa/cli/train.py +56 -8
- rasa/cli/utils.py +22 -5
- rasa/cli/x.py +1 -1
- rasa/constants.py +7 -1
- rasa/core/actions/action.py +98 -49
- rasa/core/actions/action_run_slot_rejections.py +4 -1
- rasa/core/actions/custom_action_executor.py +9 -6
- rasa/core/actions/direct_custom_actions_executor.py +80 -0
- rasa/core/actions/e2e_stub_custom_action_executor.py +68 -0
- rasa/core/actions/grpc_custom_action_executor.py +2 -2
- rasa/core/actions/http_custom_action_executor.py +6 -5
- rasa/core/agent.py +21 -17
- rasa/core/channels/__init__.py +2 -0
- rasa/core/channels/audiocodes.py +1 -16
- rasa/core/channels/voice_aware/__init__.py +0 -0
- rasa/core/channels/voice_aware/jambonz.py +103 -0
- rasa/core/channels/voice_aware/jambonz_protocol.py +344 -0
- rasa/core/channels/voice_aware/utils.py +20 -0
- rasa/core/channels/voice_native/__init__.py +0 -0
- rasa/core/constants.py +6 -1
- rasa/core/information_retrieval/faiss.py +7 -4
- rasa/core/information_retrieval/information_retrieval.py +8 -0
- rasa/core/information_retrieval/milvus.py +9 -2
- rasa/core/information_retrieval/qdrant.py +1 -1
- rasa/core/nlg/contextual_response_rephraser.py +32 -10
- rasa/core/nlg/summarize.py +4 -3
- rasa/core/policies/enterprise_search_policy.py +113 -45
- rasa/core/policies/flows/flow_executor.py +122 -76
- rasa/core/policies/intentless_policy.py +83 -29
- rasa/core/processor.py +72 -54
- rasa/core/run.py +5 -4
- rasa/core/tracker_store.py +8 -4
- rasa/core/training/interactive.py +1 -1
- rasa/core/utils.py +56 -57
- rasa/dialogue_understanding/coexistence/llm_based_router.py +53 -13
- rasa/dialogue_understanding/commands/__init__.py +6 -0
- rasa/dialogue_understanding/commands/restart_command.py +58 -0
- rasa/dialogue_understanding/commands/session_start_command.py +59 -0
- rasa/dialogue_understanding/commands/utils.py +40 -0
- rasa/dialogue_understanding/generator/constants.py +10 -3
- rasa/dialogue_understanding/generator/flow_retrieval.py +21 -5
- rasa/dialogue_understanding/generator/llm_based_command_generator.py +13 -3
- rasa/dialogue_understanding/generator/multi_step/multi_step_llm_command_generator.py +134 -90
- rasa/dialogue_understanding/generator/nlu_command_adapter.py +47 -7
- rasa/dialogue_understanding/generator/single_step/single_step_llm_command_generator.py +127 -41
- rasa/dialogue_understanding/patterns/restart.py +37 -0
- rasa/dialogue_understanding/patterns/session_start.py +37 -0
- rasa/dialogue_understanding/processor/command_processor.py +16 -3
- rasa/dialogue_understanding/processor/command_processor_component.py +6 -2
- rasa/e2e_test/aggregate_test_stats_calculator.py +134 -0
- rasa/e2e_test/assertions.py +1223 -0
- rasa/e2e_test/assertions_schema.yml +106 -0
- rasa/e2e_test/constants.py +20 -0
- rasa/e2e_test/e2e_config.py +220 -0
- rasa/e2e_test/e2e_config_schema.yml +26 -0
- rasa/e2e_test/e2e_test_case.py +131 -8
- rasa/e2e_test/e2e_test_converter.py +363 -0
- rasa/e2e_test/e2e_test_converter_prompt.jinja2 +70 -0
- rasa/e2e_test/e2e_test_coverage_report.py +364 -0
- rasa/e2e_test/e2e_test_result.py +26 -6
- rasa/e2e_test/e2e_test_runner.py +493 -71
- rasa/e2e_test/e2e_test_schema.yml +96 -0
- rasa/e2e_test/pykwalify_extensions.py +39 -0
- rasa/e2e_test/stub_custom_action.py +70 -0
- rasa/e2e_test/utils/__init__.py +0 -0
- rasa/e2e_test/utils/e2e_yaml_utils.py +55 -0
- rasa/e2e_test/utils/io.py +598 -0
- rasa/e2e_test/utils/validation.py +80 -0
- rasa/engine/graph.py +9 -3
- rasa/engine/recipes/default_components.py +0 -2
- rasa/engine/recipes/default_recipe.py +10 -2
- rasa/engine/storage/local_model_storage.py +40 -12
- rasa/engine/validation.py +78 -1
- rasa/env.py +9 -0
- rasa/graph_components/providers/story_graph_provider.py +59 -6
- rasa/llm_fine_tuning/__init__.py +0 -0
- rasa/llm_fine_tuning/annotation_module.py +241 -0
- rasa/llm_fine_tuning/conversations.py +144 -0
- rasa/llm_fine_tuning/llm_data_preparation_module.py +178 -0
- rasa/llm_fine_tuning/notebooks/unsloth_finetuning.ipynb +407 -0
- rasa/llm_fine_tuning/paraphrasing/__init__.py +0 -0
- rasa/llm_fine_tuning/paraphrasing/conversation_rephraser.py +281 -0
- rasa/llm_fine_tuning/paraphrasing/default_rephrase_prompt_template.jina2 +44 -0
- rasa/llm_fine_tuning/paraphrasing/rephrase_validator.py +121 -0
- rasa/llm_fine_tuning/paraphrasing/rephrased_user_message.py +10 -0
- rasa/llm_fine_tuning/paraphrasing_module.py +128 -0
- rasa/llm_fine_tuning/storage.py +174 -0
- rasa/llm_fine_tuning/train_test_split_module.py +441 -0
- rasa/model_training.py +56 -16
- rasa/nlu/persistor.py +157 -36
- rasa/server.py +45 -10
- rasa/shared/constants.py +76 -16
- rasa/shared/core/domain.py +27 -19
- rasa/shared/core/events.py +28 -2
- rasa/shared/core/flows/flow.py +208 -13
- rasa/shared/core/flows/flow_path.py +84 -0
- rasa/shared/core/flows/flows_list.py +33 -11
- rasa/shared/core/flows/flows_yaml_schema.json +269 -193
- rasa/shared/core/flows/validation.py +112 -25
- rasa/shared/core/flows/yaml_flows_io.py +149 -10
- rasa/shared/core/trackers.py +6 -0
- rasa/shared/core/training_data/structures.py +20 -0
- rasa/shared/core/training_data/visualization.html +2 -2
- rasa/shared/exceptions.py +4 -0
- rasa/shared/importers/importer.py +64 -16
- rasa/shared/nlu/constants.py +2 -0
- rasa/shared/providers/_configs/__init__.py +0 -0
- rasa/shared/providers/_configs/azure_openai_client_config.py +183 -0
- rasa/shared/providers/_configs/client_config.py +57 -0
- rasa/shared/providers/_configs/default_litellm_client_config.py +130 -0
- rasa/shared/providers/_configs/huggingface_local_embedding_client_config.py +234 -0
- rasa/shared/providers/_configs/openai_client_config.py +175 -0
- rasa/shared/providers/_configs/self_hosted_llm_client_config.py +176 -0
- rasa/shared/providers/_configs/utils.py +101 -0
- rasa/shared/providers/_ssl_verification_utils.py +124 -0
- rasa/shared/providers/embedding/__init__.py +0 -0
- rasa/shared/providers/embedding/_base_litellm_embedding_client.py +259 -0
- rasa/shared/providers/embedding/_langchain_embedding_client_adapter.py +74 -0
- rasa/shared/providers/embedding/azure_openai_embedding_client.py +277 -0
- rasa/shared/providers/embedding/default_litellm_embedding_client.py +102 -0
- rasa/shared/providers/embedding/embedding_client.py +90 -0
- rasa/shared/providers/embedding/embedding_response.py +41 -0
- rasa/shared/providers/embedding/huggingface_local_embedding_client.py +191 -0
- rasa/shared/providers/embedding/openai_embedding_client.py +172 -0
- rasa/shared/providers/llm/__init__.py +0 -0
- rasa/shared/providers/llm/_base_litellm_client.py +251 -0
- rasa/shared/providers/llm/azure_openai_llm_client.py +338 -0
- rasa/shared/providers/llm/default_litellm_llm_client.py +84 -0
- rasa/shared/providers/llm/llm_client.py +76 -0
- rasa/shared/providers/llm/llm_response.py +50 -0
- rasa/shared/providers/llm/openai_llm_client.py +155 -0
- rasa/shared/providers/llm/self_hosted_llm_client.py +293 -0
- rasa/shared/providers/mappings.py +75 -0
- rasa/shared/utils/cli.py +30 -0
- rasa/shared/utils/io.py +65 -2
- rasa/shared/utils/llm.py +246 -200
- rasa/shared/utils/yaml.py +121 -15
- rasa/studio/auth.py +6 -4
- rasa/studio/config.py +13 -4
- rasa/studio/constants.py +1 -0
- rasa/studio/data_handler.py +10 -3
- rasa/studio/download.py +19 -13
- rasa/studio/train.py +2 -3
- rasa/studio/upload.py +19 -11
- rasa/telemetry.py +113 -58
- rasa/tracing/instrumentation/attribute_extractors.py +32 -17
- rasa/utils/common.py +18 -19
- rasa/utils/endpoints.py +7 -4
- rasa/utils/json_utils.py +60 -0
- rasa/utils/licensing.py +9 -1
- rasa/utils/ml_utils.py +4 -2
- rasa/validator.py +213 -3
- rasa/version.py +1 -1
- rasa_pro-3.10.16.dist-info/METADATA +196 -0
- {rasa_pro-3.9.18.dist-info → rasa_pro-3.10.16.dist-info}/RECORD +179 -113
- rasa/nlu/classifiers/llm_intent_classifier.py +0 -519
- rasa/shared/providers/openai/clients.py +0 -43
- rasa/shared/providers/openai/session_handler.py +0 -110
- rasa_pro-3.9.18.dist-info/METADATA +0 -563
- /rasa/{shared/providers/openai → cli/project_templates/tutorial/actions}/__init__.py +0 -0
- /rasa/cli/project_templates/tutorial/{actions.py → actions/actions.py} +0 -0
- {rasa_pro-3.9.18.dist-info → rasa_pro-3.10.16.dist-info}/NOTICE +0 -0
- {rasa_pro-3.9.18.dist-info → rasa_pro-3.10.16.dist-info}/WHEEL +0 -0
- {rasa_pro-3.9.18.dist-info → rasa_pro-3.10.16.dist-info}/entry_points.txt +0 -0
|
@@ -25,6 +25,97 @@ mapping:
|
|
|
25
25
|
regex;(^[a-zA-Z_]+[a-zA-Z0-9_]*$):
|
|
26
26
|
type: any
|
|
27
27
|
|
|
28
|
+
stub_custom_actions:
|
|
29
|
+
type: map
|
|
30
|
+
mapping:
|
|
31
|
+
regex;(^[a-zA-Z_]+([a-zA-Z0-9_]*::?)*[a-zA-Z0-9_]*$):
|
|
32
|
+
type: map
|
|
33
|
+
mapping:
|
|
34
|
+
events:
|
|
35
|
+
type: seq
|
|
36
|
+
sequence:
|
|
37
|
+
- type: map
|
|
38
|
+
matching: any
|
|
39
|
+
mapping:
|
|
40
|
+
event:
|
|
41
|
+
type: "str"
|
|
42
|
+
enum: ["user", "bot", "slot", "session_started", "action", "reset_slots", "restart", "reminder", "cancel_reminder", "pause", "resume", "followup", "export", "undo", "rewind", "entities", "active_loop", "agent", "loop_interrupted", "action_execution_rejected"]
|
|
43
|
+
timestamp:
|
|
44
|
+
type: float
|
|
45
|
+
metadata:
|
|
46
|
+
type: map
|
|
47
|
+
mapping:
|
|
48
|
+
regex;(^[a-zA-Z_]+[a-zA-Z0-9_]*$):
|
|
49
|
+
type: any
|
|
50
|
+
text:
|
|
51
|
+
type: "str"
|
|
52
|
+
parse_data:
|
|
53
|
+
type: map
|
|
54
|
+
mapping:
|
|
55
|
+
regex;(^[a-zA-Z_]+[a-zA-Z0-9_]*$):
|
|
56
|
+
type: any
|
|
57
|
+
input_channel:
|
|
58
|
+
type: "str"
|
|
59
|
+
data:
|
|
60
|
+
type: map
|
|
61
|
+
mapping:
|
|
62
|
+
regex;(^[a-zA-Z_]+[a-zA-Z0-9_]*$):
|
|
63
|
+
type: any
|
|
64
|
+
name:
|
|
65
|
+
type: "str"
|
|
66
|
+
value:
|
|
67
|
+
type: any
|
|
68
|
+
entities:
|
|
69
|
+
type: any
|
|
70
|
+
intent:
|
|
71
|
+
type: "str"
|
|
72
|
+
kill_on_user_message:
|
|
73
|
+
type: bool
|
|
74
|
+
date_time:
|
|
75
|
+
type: "str"
|
|
76
|
+
policy:
|
|
77
|
+
type: "str"
|
|
78
|
+
confidence:
|
|
79
|
+
type: float
|
|
80
|
+
is_interrupted:
|
|
81
|
+
type: bool
|
|
82
|
+
|
|
83
|
+
responses:
|
|
84
|
+
type: seq
|
|
85
|
+
sequence:
|
|
86
|
+
- type: map
|
|
87
|
+
matching: any
|
|
88
|
+
mapping:
|
|
89
|
+
text:
|
|
90
|
+
type: "str"
|
|
91
|
+
buttons:
|
|
92
|
+
type: "seq"
|
|
93
|
+
sequence:
|
|
94
|
+
- type: map
|
|
95
|
+
mapping:
|
|
96
|
+
payload:
|
|
97
|
+
type: "str"
|
|
98
|
+
title:
|
|
99
|
+
type: "str"
|
|
100
|
+
response:
|
|
101
|
+
type: "str"
|
|
102
|
+
image:
|
|
103
|
+
type: "str"
|
|
104
|
+
attachment:
|
|
105
|
+
type: "str"
|
|
106
|
+
elements:
|
|
107
|
+
type: "seq"
|
|
108
|
+
sequence:
|
|
109
|
+
- type: map
|
|
110
|
+
mapping:
|
|
111
|
+
regex;(^[a-zA-Z_]+[a-zA-Z0-9_]*$):
|
|
112
|
+
type: any
|
|
113
|
+
custom:
|
|
114
|
+
type: map
|
|
115
|
+
mapping:
|
|
116
|
+
regex;(^[a-zA-Z_]+[a-zA-Z0-9_]*$):
|
|
117
|
+
type: any
|
|
118
|
+
|
|
28
119
|
test_cases:
|
|
29
120
|
type: "seq"
|
|
30
121
|
sequence:
|
|
@@ -53,6 +144,11 @@ mapping:
|
|
|
53
144
|
metadata:
|
|
54
145
|
type: "str"
|
|
55
146
|
pattern: ^[a-zA-Z_]+[a-zA-Z0-9_]*$
|
|
147
|
+
assertion_order_enabled:
|
|
148
|
+
type: bool
|
|
149
|
+
assertions:
|
|
150
|
+
# see e2e_test/assertions.yml
|
|
151
|
+
include: assertions
|
|
56
152
|
- type: map
|
|
57
153
|
mapping:
|
|
58
154
|
utter:
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"""This module regroups custom validation functions, and it is
|
|
2
|
+
loaded as an extension of the pykwalify library:
|
|
3
|
+
|
|
4
|
+
https://pykwalify.readthedocs.io/en/latest/extensions.html#extensions
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import Any, Dict, List, Union
|
|
8
|
+
|
|
9
|
+
from pykwalify.errors import SchemaError
|
|
10
|
+
|
|
11
|
+
BOT_UTTERED_KEY = "bot_uttered"
|
|
12
|
+
BUTTONS_KEY = "buttons"
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def require_assertion_keys(
|
|
16
|
+
assertions: List[Dict[str, Any]], _: Dict, __: str
|
|
17
|
+
) -> Union[SchemaError, bool]:
|
|
18
|
+
"""Validates that certain assertion keys are not mapped to empty values."""
|
|
19
|
+
for assertion in assertions:
|
|
20
|
+
if not isinstance(assertion, dict):
|
|
21
|
+
# this is handled by other validation rules
|
|
22
|
+
continue
|
|
23
|
+
|
|
24
|
+
bot_uttered_dict = assertion.get(BOT_UTTERED_KEY)
|
|
25
|
+
if BOT_UTTERED_KEY in assertion and isinstance(bot_uttered_dict, dict):
|
|
26
|
+
if not bot_uttered_dict:
|
|
27
|
+
return SchemaError(
|
|
28
|
+
f"The '{BOT_UTTERED_KEY}' assertion is an empty dictionary."
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
if BUTTONS_KEY in bot_uttered_dict and not bot_uttered_dict.get(
|
|
32
|
+
BUTTONS_KEY
|
|
33
|
+
):
|
|
34
|
+
return SchemaError(
|
|
35
|
+
f"The '{BUTTONS_KEY}' key in the '{BOT_UTTERED_KEY}' assertion "
|
|
36
|
+
f"is mapped to a null value or empty list."
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
return True
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from typing import Any, Dict, List, Text, Optional
|
|
3
|
+
|
|
4
|
+
from rasa.e2e_test.constants import (
|
|
5
|
+
KEY_STUB_CUSTOM_ACTIONS,
|
|
6
|
+
STUB_CUSTOM_ACTION_NAME_SEPARATOR,
|
|
7
|
+
TEST_CASE_NAME,
|
|
8
|
+
TEST_FILE_NAME,
|
|
9
|
+
)
|
|
10
|
+
from rasa.utils.endpoints import EndpointConfig
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@dataclass
|
|
14
|
+
class StubCustomAction:
|
|
15
|
+
"""Class for storing the stub response of the custom action."""
|
|
16
|
+
|
|
17
|
+
action_name: str
|
|
18
|
+
events: List[Dict[Text, Any]]
|
|
19
|
+
responses: List[Dict[Text, Any]]
|
|
20
|
+
|
|
21
|
+
@staticmethod
|
|
22
|
+
def from_dict(action_name: str, stub_data: Dict[Text, Any]) -> "StubCustomAction":
|
|
23
|
+
"""Creates a stub custom action from a dictionary.
|
|
24
|
+
|
|
25
|
+
Example:
|
|
26
|
+
>>> StubCustomAction.from_dict(
|
|
27
|
+
>>> {"action_name": {"events": [], "responses": []}}
|
|
28
|
+
>>> )
|
|
29
|
+
StubCustomAction(name="action_name", events=[], responses=[])
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
action_name (str): Name of the custom action.
|
|
33
|
+
stub_data (Dict[Text, Any]): Stub custom action response.
|
|
34
|
+
"""
|
|
35
|
+
return StubCustomAction(
|
|
36
|
+
action_name=action_name,
|
|
37
|
+
events=[event for event in stub_data.get("events", [])],
|
|
38
|
+
responses=[response for response in stub_data.get("responses", [])],
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
def as_dict(self) -> Dict[Text, Any]:
|
|
42
|
+
"""Returns the metadata as a dictionary."""
|
|
43
|
+
return {"events": self.events, "responses": self.responses}
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def get_stub_custom_action_key(prefix: str, action_name: str) -> str:
|
|
47
|
+
"""Returns the key used to store the StubCustomAction object"""
|
|
48
|
+
return f"{prefix}{STUB_CUSTOM_ACTION_NAME_SEPARATOR}{action_name}"
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def get_stub_custom_action(
|
|
52
|
+
action_endpoint: EndpointConfig, action_name: str
|
|
53
|
+
) -> Optional["StubCustomAction"]:
|
|
54
|
+
"""Returns the StubCustomAction object"""
|
|
55
|
+
test_case_name = action_endpoint.kwargs.get(TEST_CASE_NAME)
|
|
56
|
+
stub_custom_action_test_key = get_stub_custom_action_key(
|
|
57
|
+
test_case_name, action_name
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
test_file_name = action_endpoint.kwargs.get(TEST_FILE_NAME)
|
|
61
|
+
stub_custom_action_file_key = get_stub_custom_action_key(
|
|
62
|
+
test_file_name, action_name
|
|
63
|
+
)
|
|
64
|
+
stub_custom_actions = action_endpoint.kwargs.get(KEY_STUB_CUSTOM_ACTIONS, {})
|
|
65
|
+
|
|
66
|
+
stub = stub_custom_actions.get(
|
|
67
|
+
stub_custom_action_test_key
|
|
68
|
+
) or stub_custom_actions.get(stub_custom_action_file_key)
|
|
69
|
+
|
|
70
|
+
return stub
|
|
File without changes
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
import ruamel
|
|
6
|
+
import structlog
|
|
7
|
+
|
|
8
|
+
from rasa.e2e_test.constants import KEY_TEST_CASES
|
|
9
|
+
|
|
10
|
+
structlogger = structlog.get_logger()
|
|
11
|
+
|
|
12
|
+
DEFAULT_E2E_OUTPUT_TESTS_DIRECTORY = "e2e_tests"
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class E2ETestYAMLWriter:
|
|
16
|
+
def __init__(
|
|
17
|
+
self,
|
|
18
|
+
output_path: str = DEFAULT_E2E_OUTPUT_TESTS_DIRECTORY,
|
|
19
|
+
**kwargs: Any,
|
|
20
|
+
) -> None:
|
|
21
|
+
"""Initializes the E2ETestYAMLWriter with necessary parameters.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
output (str): Directory to save the generated tests.
|
|
25
|
+
"""
|
|
26
|
+
self.output_path = output_path
|
|
27
|
+
|
|
28
|
+
def write_to_file(self, tests: str) -> None:
|
|
29
|
+
"""Writes the provided test cases to a YAML file
|
|
30
|
+
in the specified output directory.
|
|
31
|
+
|
|
32
|
+
Args:
|
|
33
|
+
tests (str): string containing the generated test cases.
|
|
34
|
+
"""
|
|
35
|
+
if not tests.strip():
|
|
36
|
+
structlogger.info("e2e_test_generator.no_tests_provided")
|
|
37
|
+
return
|
|
38
|
+
|
|
39
|
+
output_dir = Path(self.output_path)
|
|
40
|
+
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
|
41
|
+
output_file = output_dir / f"e2e_tests_{timestamp}.yml"
|
|
42
|
+
|
|
43
|
+
if not output_dir.exists():
|
|
44
|
+
output_dir.mkdir(parents=True, exist_ok=True)
|
|
45
|
+
|
|
46
|
+
yaml_data = ruamel.yaml.safe_load(tests)
|
|
47
|
+
|
|
48
|
+
test_cases_yaml = {KEY_TEST_CASES: yaml_data}
|
|
49
|
+
with open(output_file, "w") as outfile:
|
|
50
|
+
yaml = ruamel.yaml.YAML()
|
|
51
|
+
yaml.dump(test_cases_yaml, outfile)
|
|
52
|
+
|
|
53
|
+
structlogger.info(
|
|
54
|
+
"e2e_test_generator.tests_written_to_yaml", output_file=output_file
|
|
55
|
+
)
|