Spaces:
Build error
Build error
Validify-testbot-1
/
botbuilder-python
/libraries
/botbuilder-dialogs
/botbuilder
/dialogs
/dialog_container.py
# Copyright (c) Microsoft Corporation. All rights reserved. | |
# Licensed under the MIT License. | |
from abc import ABC, abstractmethod | |
from botbuilder.core import NullTelemetryClient, BotTelemetryClient | |
from .dialog import Dialog | |
from .dialog_context import DialogContext | |
from .dialog_event import DialogEvent | |
from .dialog_events import DialogEvents | |
from .dialog_set import DialogSet | |
class DialogContainer(Dialog, ABC): | |
def __init__(self, dialog_id: str = None): | |
super().__init__(dialog_id) | |
self.dialogs = DialogSet() | |
def telemetry_client(self) -> BotTelemetryClient: | |
""" | |
Gets the telemetry client for logging events. | |
""" | |
return self._telemetry_client | |
def telemetry_client(self, value: BotTelemetryClient) -> None: | |
""" | |
Sets the telemetry client for all dialogs in this set. | |
""" | |
if value is None: | |
self._telemetry_client = NullTelemetryClient() | |
else: | |
self._telemetry_client = value | |
# Care! Dialogs.TelemetryClient assignment internally assigns the | |
# TelemetryClient for each dialog which could lead to an eventual stack | |
# overflow in cyclical dialog structures. | |
# Don't set the telemetry client if the candidate instance is the same as | |
# the currently set one. | |
if self.dialogs.telemetry_client != value: | |
self.dialogs.telemetry_client = self._telemetry_client | |
def create_child_context(self, dialog_context: DialogContext) -> DialogContext: | |
raise NotImplementedError() | |
def find_dialog(self, dialog_id: str) -> Dialog: | |
# TODO: deprecate DialogSet.find | |
return self.dialogs.find_dialog(dialog_id) | |
async def on_dialog_event( | |
self, dialog_context: DialogContext, dialog_event: DialogEvent | |
) -> bool: | |
""" | |
Called when an event has been raised, using `DialogContext.emitEvent()`, by either the current dialog or a | |
dialog that the current dialog started. | |
:param dialog_context: The dialog context for the current turn of conversation. | |
:param dialog_event: The event being raised. | |
:return: True if the event is handled by the current dialog and bubbling should stop. | |
""" | |
handled = await super().on_dialog_event(dialog_context, dialog_event) | |
# Trace unhandled "versionChanged" events. | |
if not handled and dialog_event.name == DialogEvents.version_changed: | |
trace_message = ( | |
f"Unhandled dialog event: {dialog_event.name}. Active Dialog: " | |
f"{dialog_context.active_dialog.id}" | |
) | |
await dialog_context.context.send_trace_activity(trace_message) | |
return handled | |
def get_internal_version(self) -> str: | |
""" | |
GetInternalVersion - Returns internal version identifier for this container. | |
DialogContainers detect changes of all sub-components in the container and map that to an DialogChanged event. | |
Because they do this, DialogContainers "hide" the internal changes and just have the .id. This isolates changes | |
to the container level unless a container doesn't handle it. To support this DialogContainers define a | |
protected virtual method GetInternalVersion() which computes if this dialog or child dialogs have changed | |
which is then examined via calls to check_for_version_change_async(). | |
:return: version which represents the change of the internals of this container. | |
""" | |
return self.dialogs.get_version() | |
async def check_for_version_change_async(self, dialog_context: DialogContext): | |
""" | |
:param dialog_context: dialog context. | |
:return: task. | |
Checks to see if a containers child dialogs have changed since the current dialog instance | |
was started. | |
This should be called at the start of `beginDialog()`, `continueDialog()`, and `resumeDialog()`. | |
""" | |
current = dialog_context.active_dialog.version | |
dialog_context.active_dialog.version = self.get_internal_version() | |
# Check for change of previously stored hash | |
if current and current != dialog_context.active_dialog.version: | |
# Give bot an opportunity to handle the change. | |
# - If bot handles it the changeHash will have been updated as to avoid triggering the | |
# change again. | |
await dialog_context.emit_event( | |
DialogEvents.version_changed, self.id, True, False | |
) | |