From 9e5ea2c9a9f06620b2ddd56871b2a219cd17116e Mon Sep 17 00:00:00 2001 From: "Amber Chen (Centific Technologies Inc)" Date: Mon, 26 Jan 2026 15:37:41 -0800 Subject: [PATCH 01/10] updated serialization --- .../conversations/_utils/serialization.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/sdk/cognitivelanguage/azure-ai-language-conversations/azure/ai/language/conversations/_utils/serialization.py b/sdk/cognitivelanguage/azure-ai-language-conversations/azure/ai/language/conversations/_utils/serialization.py index 45a3e44e45cb..81ec1de5922b 100644 --- a/sdk/cognitivelanguage/azure-ai-language-conversations/azure/ai/language/conversations/_utils/serialization.py +++ b/sdk/cognitivelanguage/azure-ai-language-conversations/azure/ai/language/conversations/_utils/serialization.py @@ -821,13 +821,20 @@ def serialize_basic(cls, data, data_type, **kwargs): :param str data_type: Type of object in the iterable. :rtype: str, int, float, bool :return: serialized object + :raises TypeError: raise if data_type is not one of str, int, float, bool. """ custom_serializer = cls._get_custom_serializers(data_type, **kwargs) if custom_serializer: return custom_serializer(data) if data_type == "str": return cls.serialize_unicode(data) - return eval(data_type)(data) # nosec # pylint: disable=eval-used + if data_type == "int": + return int(data) + if data_type == "float": + return float(data) + if data_type == "bool": + return bool(data) + raise TypeError("Unknown basic data type: {}".format(data_type)) @classmethod def serialize_unicode(cls, data): @@ -1757,7 +1764,7 @@ def deserialize_basic(self, attr, data_type): # pylint: disable=too-many-return :param str data_type: deserialization data type. :return: Deserialized basic type. :rtype: str, int, float or bool - :raises TypeError: if string format is not valid. + :raises TypeError: if string format is not valid or data_type is not one of str, int, float, bool. """ # If we're here, data is supposed to be a basic type. # If it's still an XML node, take the text @@ -1783,7 +1790,11 @@ def deserialize_basic(self, attr, data_type): # pylint: disable=too-many-return if data_type == "str": return self.deserialize_unicode(attr) - return eval(data_type)(attr) # nosec # pylint: disable=eval-used + if data_type == "int": + return int(attr) + if data_type == "float": + return float(attr) + raise TypeError("Unknown basic data type: {}".format(data_type)) @staticmethod def deserialize_unicode(data): From dd79758a18b6f88046929dda07f00282a4bb52f1 Mon Sep 17 00:00:00 2001 From: "Amber Chen (Centific Technologies Inc)" Date: Mon, 26 Jan 2026 15:38:34 -0800 Subject: [PATCH 02/10] updated model base --- .../conversations/_utils/model_base.py | 133 ++++++++++++++++-- 1 file changed, 121 insertions(+), 12 deletions(-) diff --git a/sdk/cognitivelanguage/azure-ai-language-conversations/azure/ai/language/conversations/_utils/model_base.py b/sdk/cognitivelanguage/azure-ai-language-conversations/azure/ai/language/conversations/_utils/model_base.py index 430bda7b37fc..097f8197cfd9 100644 --- a/sdk/cognitivelanguage/azure-ai-language-conversations/azure/ai/language/conversations/_utils/model_base.py +++ b/sdk/cognitivelanguage/azure-ai-language-conversations/azure/ai/language/conversations/_utils/model_base.py @@ -22,7 +22,7 @@ from datetime import datetime, date, time, timedelta, timezone from json import JSONEncoder import xml.etree.ElementTree as ET -from collections.abc import MutableMapping # pylint:disable=import-error +from collections.abc import MutableMapping from typing_extensions import Self import isodate from azure.core.exceptions import DeserializationError @@ -37,6 +37,7 @@ TZ_UTC = timezone.utc _T = typing.TypeVar("_T") +_NONE_TYPE = type(None) def _timedelta_as_isostr(td: timedelta) -> str: @@ -171,6 +172,21 @@ def default(self, o): # pylint: disable=too-many-return-statements r"(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s\d{4}\s\d{2}:\d{2}:\d{2}\sGMT" ) +_ARRAY_ENCODE_MAPPING = { + "pipeDelimited": "|", + "spaceDelimited": " ", + "commaDelimited": ",", + "newlineDelimited": "\n", +} + + +def _deserialize_array_encoded(delimit: str, attr): + if isinstance(attr, str): + if attr == "": + return [] + return attr.split(delimit) + return attr + def _deserialize_datetime(attr: typing.Union[str, datetime]) -> datetime: """Deserialize ISO-8601 formatted string into Datetime object. @@ -202,7 +218,7 @@ def _deserialize_datetime(attr: typing.Union[str, datetime]) -> datetime: test_utc = date_obj.utctimetuple() if test_utc.tm_year > 9999 or test_utc.tm_year < 1: raise OverflowError("Hit max or min date") - return date_obj + return date_obj # type: ignore[no-any-return] def _deserialize_datetime_rfc7231(attr: typing.Union[str, datetime]) -> datetime: @@ -256,7 +272,7 @@ def _deserialize_time(attr: typing.Union[str, time]) -> time: """ if isinstance(attr, time): return attr - return isodate.parse_time(attr) + return isodate.parse_time(attr) # type: ignore[no-any-return] def _deserialize_bytes(attr): @@ -315,6 +331,8 @@ def _deserialize_int_as_str(attr): def get_deserializer(annotation: typing.Any, rf: typing.Optional["_RestField"] = None): if annotation is int and rf and rf._format == "str": return _deserialize_int_as_str + if annotation is str and rf and rf._format in _ARRAY_ENCODE_MAPPING: + return functools.partial(_deserialize_array_encoded, _ARRAY_ENCODE_MAPPING[rf._format]) if rf and rf._format: return _DESERIALIZE_MAPPING_WITHFORMAT.get(rf._format) return _DESERIALIZE_MAPPING.get(annotation) # pyright: ignore @@ -353,9 +371,39 @@ def __contains__(self, key: typing.Any) -> bool: return key in self._data def __getitem__(self, key: str) -> typing.Any: + # If this key has been deserialized (for mutable types), we need to handle serialization + if hasattr(self, "_attr_to_rest_field"): + cache_attr = f"_deserialized_{key}" + if hasattr(self, cache_attr): + rf = _get_rest_field(getattr(self, "_attr_to_rest_field"), key) + if rf: + value = self._data.get(key) + if isinstance(value, (dict, list, set)): + # For mutable types, serialize and return + # But also update _data with serialized form and clear flag + # so mutations via this returned value affect _data + serialized = _serialize(value, rf._format) + # If serialized form is same type (no transformation needed), + # return _data directly so mutations work + if isinstance(serialized, type(value)) and serialized == value: + return self._data.get(key) + # Otherwise return serialized copy and clear flag + try: + object.__delattr__(self, cache_attr) + except AttributeError: + pass + # Store serialized form back + self._data[key] = serialized + return serialized return self._data.__getitem__(key) def __setitem__(self, key: str, value: typing.Any) -> None: + # Clear any cached deserialized value when setting through dictionary access + cache_attr = f"_deserialized_{key}" + try: + object.__delattr__(self, cache_attr) + except AttributeError: + pass self._data.__setitem__(key, value) def __delitem__(self, key: str) -> None: @@ -483,6 +531,8 @@ def _is_model(obj: typing.Any) -> bool: def _serialize(o, format: typing.Optional[str] = None): # pylint: disable=too-many-return-statements if isinstance(o, list): + if format in _ARRAY_ENCODE_MAPPING and all(isinstance(x, str) for x in o): + return _ARRAY_ENCODE_MAPPING[format].join(o) return [_serialize(x, format) for x in o] if isinstance(o, dict): return {k: _serialize(v, format) for k, v in o.items()} @@ -638,15 +688,29 @@ def __new__(cls, *args: typing.Any, **kwargs: typing.Any) -> Self: if not rf._rest_name_input: rf._rest_name_input = attr cls._attr_to_rest_field: dict[str, _RestField] = dict(attr_to_rest_field.items()) + cls._backcompat_attr_to_rest_field: dict[str, _RestField] = { + Model._get_backcompat_attribute_name(cls._attr_to_rest_field, attr): rf + for attr, rf in cls._attr_to_rest_field.items() + } cls._calculated.add(f"{cls.__module__}.{cls.__qualname__}") - return super().__new__(cls) # pylint:disable=no-value-for-parameter + return super().__new__(cls) def __init_subclass__(cls, discriminator: typing.Optional[str] = None) -> None: for base in cls.__bases__: if hasattr(base, "__mapping__"): base.__mapping__[discriminator or cls.__name__] = cls # type: ignore + @classmethod + def _get_backcompat_attribute_name(cls, attr_to_rest_field: dict[str, "_RestField"], attr_name: str) -> str: + rest_field_obj = attr_to_rest_field.get(attr_name) # pylint: disable=protected-access + if rest_field_obj is None: + return attr_name + original_tsp_name = getattr(rest_field_obj, "_original_tsp_name", None) # pylint: disable=protected-access + if original_tsp_name: + return original_tsp_name + return attr_name + @classmethod def _get_discriminator(cls, exist_discriminators) -> typing.Optional["_RestField"]: for v in cls.__dict__.values(): @@ -767,6 +831,17 @@ def _deserialize_sequence( return obj if isinstance(obj, ET.Element): obj = list(obj) + try: + if ( + isinstance(obj, str) + and isinstance(deserializer, functools.partial) + and isinstance(deserializer.args[0], functools.partial) + and deserializer.args[0].func == _deserialize_array_encoded # pylint: disable=comparison-with-callable + ): + # encoded string may be deserialized to sequence + return deserializer(obj) + except: # pylint: disable=bare-except + pass return type(obj)(_deserialize(deserializer, entry, module) for entry in obj) @@ -817,16 +892,16 @@ def _get_deserialize_callable_from_annotation( # pylint: disable=too-many-retur # is it optional? try: - if any(a for a in annotation.__args__ if a == type(None)): # pyright: ignore + if any(a is _NONE_TYPE for a in annotation.__args__): # pyright: ignore if len(annotation.__args__) <= 2: # pyright: ignore if_obj_deserializer = _get_deserialize_callable_from_annotation( - next(a for a in annotation.__args__ if a != type(None)), module, rf # pyright: ignore + next(a for a in annotation.__args__ if a is not _NONE_TYPE), module, rf # pyright: ignore ) return functools.partial(_deserialize_with_optional, if_obj_deserializer) # the type is Optional[Union[...]], we need to remove the None type from the Union annotation_copy = copy.copy(annotation) - annotation_copy.__args__ = [a for a in annotation_copy.__args__ if a != type(None)] # pyright: ignore + annotation_copy.__args__ = [a for a in annotation_copy.__args__ if a is not _NONE_TYPE] # pyright: ignore return _get_deserialize_callable_from_annotation(annotation_copy, module, rf) except AttributeError: pass @@ -972,6 +1047,7 @@ def _failsafe_deserialize_xml( return None +# pylint: disable=too-many-instance-attributes class _RestField: def __init__( self, @@ -984,6 +1060,7 @@ def __init__( format: typing.Optional[str] = None, is_multipart_file_input: bool = False, xml: typing.Optional[dict[str, typing.Any]] = None, + original_tsp_name: typing.Optional[str] = None, ): self._type = type self._rest_name_input = name @@ -995,10 +1072,15 @@ def __init__( self._format = format self._is_multipart_file_input = is_multipart_file_input self._xml = xml if xml is not None else {} + self._original_tsp_name = original_tsp_name @property def _class_type(self) -> typing.Any: - return getattr(self._type, "args", [None])[0] + result = getattr(self._type, "args", [None])[0] + # type may be wrapped by nested functools.partial so we need to check for that + if isinstance(result, functools.partial): + return getattr(result, "args", [None])[0] + return result @property def _rest_name(self) -> str: @@ -1009,14 +1091,37 @@ def _rest_name(self) -> str: def __get__(self, obj: Model, type=None): # pylint: disable=redefined-builtin # by this point, type and rest_name will have a value bc we default # them in __new__ of the Model class - item = obj.get(self._rest_name) + # Use _data.get() directly to avoid triggering __getitem__ which clears the cache + item = obj._data.get(self._rest_name) if item is None: return item if self._is_model: return item - return _deserialize(self._type, _serialize(item, self._format), rf=self) + + # For mutable types, we want mutations to directly affect _data + # Check if we've already deserialized this value + cache_attr = f"_deserialized_{self._rest_name}" + if hasattr(obj, cache_attr): + # Return the value from _data directly (it's been deserialized in place) + return obj._data.get(self._rest_name) + + deserialized = _deserialize(self._type, _serialize(item, self._format), rf=self) + + # For mutable types, store the deserialized value back in _data + # so mutations directly affect _data + if isinstance(deserialized, (dict, list, set)): + obj._data[self._rest_name] = deserialized + object.__setattr__(obj, cache_attr, True) # Mark as deserialized + return deserialized + + return deserialized def __set__(self, obj: Model, value) -> None: + # Clear the cached deserialized object when setting a new value + cache_attr = f"_deserialized_{self._rest_name}" + if hasattr(obj, cache_attr): + object.__delattr__(obj, cache_attr) + if value is None: # we want to wipe out entries if users set attr to None try: @@ -1046,6 +1151,7 @@ def rest_field( format: typing.Optional[str] = None, is_multipart_file_input: bool = False, xml: typing.Optional[dict[str, typing.Any]] = None, + original_tsp_name: typing.Optional[str] = None, ) -> typing.Any: return _RestField( name=name, @@ -1055,6 +1161,7 @@ def rest_field( format=format, is_multipart_file_input=is_multipart_file_input, xml=xml, + original_tsp_name=original_tsp_name, ) @@ -1184,7 +1291,7 @@ def _get_wrapped_element( _get_element(v, exclude_readonly, meta, wrapped_element) else: wrapped_element.text = _get_primitive_type_value(v) - return wrapped_element + return wrapped_element # type: ignore[no-any-return] def _get_primitive_type_value(v) -> str: @@ -1197,7 +1304,9 @@ def _get_primitive_type_value(v) -> str: return str(v) -def _create_xml_element(tag, prefix=None, ns=None): +def _create_xml_element( + tag: typing.Any, prefix: typing.Optional[str] = None, ns: typing.Optional[str] = None +) -> ET.Element: if prefix and ns: ET.register_namespace(prefix, ns) if ns: From 8fce857ad8fd787b72d5def1eaa8ad3e18bc1f5a Mon Sep 17 00:00:00 2001 From: "Amber Chen (Centific Technologies Inc)" Date: Mon, 26 Jan 2026 15:44:51 -0800 Subject: [PATCH 03/10] updated configuration --- .../azure-ai-language-conversations/dev_requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/sdk/cognitivelanguage/azure-ai-language-conversations/dev_requirements.txt b/sdk/cognitivelanguage/azure-ai-language-conversations/dev_requirements.txt index d85e980ba5ab..193cd3bffd29 100644 --- a/sdk/cognitivelanguage/azure-ai-language-conversations/dev_requirements.txt +++ b/sdk/cognitivelanguage/azure-ai-language-conversations/dev_requirements.txt @@ -2,3 +2,4 @@ ../../core/azure-core -e ../../identity/azure-identity aiohttp>=3.0 +azure-identity From 82b4b2e919198de17f6fd260d92379f7a682f368 Mon Sep 17 00:00:00 2001 From: "Amber Chen (Centific Technologies Inc)" Date: Mon, 26 Jan 2026 16:42:17 -0800 Subject: [PATCH 04/10] updated all tests --- .../dev_requirements.txt | 5 +-- ...test_conversation_multi_turn_prediction.py | 31 +------------ ...onversation_multi_turn_prediction_async.py | 35 ++------------- .../tests/test_conversation_pii.py | 22 +--------- .../tests/test_conversation_pii_async.py | 44 ++----------------- ...ersation_pii_with_character_mask_policy.py | 24 +--------- ...on_pii_with_character_mask_policy_async.py | 4 +- ...onversation_pii_with_entity_mask_policy.py | 27 +----------- ...ation_pii_with_entity_mask_policy_async.py | 6 ++- ...st_conversation_pii_with_no_mask_policy.py | 22 ++-------- ...versation_pii_with_no_mask_policy_async.py | 4 +- .../tests/test_conversation_prediction.py | 3 +- .../test_conversation_prediction_async.py | 11 ++--- ...t_conversation_prediction_with_language.py | 7 +-- ...ersation_prediction_with_language_async.py | 12 ++--- ...st_conversation_prediction_with_options.py | 7 +-- ...versation_prediction_with_options_async.py | 13 +++--- .../tests/test_conversation_summarization.py | 7 +-- .../test_conversation_summarization_async.py | 3 +- .../tests/test_orchestration_prediction.py | 3 +- .../test_orchestration_prediction_async.py | 6 +-- 21 files changed, 48 insertions(+), 248 deletions(-) diff --git a/sdk/cognitivelanguage/azure-ai-language-conversations/dev_requirements.txt b/sdk/cognitivelanguage/azure-ai-language-conversations/dev_requirements.txt index 193cd3bffd29..f5df333868ec 100644 --- a/sdk/cognitivelanguage/azure-ai-language-conversations/dev_requirements.txt +++ b/sdk/cognitivelanguage/azure-ai-language-conversations/dev_requirements.txt @@ -1,5 +1,4 @@ -e ../../../eng/tools/azure-sdk-tools ../../core/azure-core --e ../../identity/azure-identity -aiohttp>=3.0 -azure-identity +aiohttp +azure-identity \ No newline at end of file diff --git a/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_multi_turn_prediction.py b/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_multi_turn_prediction.py index 73a0ef6d991e..76e51ad7b4b9 100644 --- a/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_multi_turn_prediction.py +++ b/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_multi_turn_prediction.py @@ -1,6 +1,6 @@ # pylint: disable=line-too-long,useless-suppression import functools -import pytest +from typing import cast from devtools_testutils import AzureRecordedTestCase, EnvironmentVariableLoader, recorded_by_proxy from azure.ai.language.conversations import ConversationAnalysisClient @@ -18,11 +18,7 @@ ConversationalAIIntent, ConversationalAIEntity, ConversationItemRange, - DateTimeResolution, - EntitySubtype, - EntityTag, ) -from typing import cast from azure.core.credentials import AzureKeyCredential @@ -116,24 +112,6 @@ def test_conversation_multi_turn_prediction(self, conversations_endpoint, conver print(f" Offset: {ent.offset}, Length: {ent.length}") print(f" Conversation Item ID: {ent.conversation_item_id}, Index: {ent.conversation_item_index}") - # Date/time resolutions - if ent.resolutions: - for res in ent.resolutions: - if isinstance(res, DateTimeResolution): - print( - f" - [DateTimeResolution] SubKind: {getattr(res, 'date_time_sub_kind', None)}, " - f"Timex: {res.timex}, Value: {res.value}" - ) - - # Extra information (entity subtype + tags) - if ent.extra_information: - for extra in ent.extra_information: - if isinstance(extra, EntitySubtype): - print(f" - [EntitySubtype] Value: {extra.value}") - for tag in extra.tags or []: - tag = cast(EntityTag, tag) - print(f" • Tag: {tag.name}, Confidence: {tag.confidence_score}") - print() print() @@ -148,13 +126,6 @@ def test_conversation_multi_turn_prediction(self, conversations_endpoint, conver print(f" Offset: {ent.offset}, Length: {ent.length}") print(f" Conversation Item ID: {ent.conversation_item_id}, Index: {ent.conversation_item_index}") - if ent.extra_information: - for extra in ent.extra_information: - if isinstance(extra, EntitySubtype): - print(f" - [EntitySubtype] Value: {extra.value}") - for tag in extra.tags or []: - tag = cast(EntityTag, tag) - print(f" • Tag: {tag.name}, Confidence: {tag.confidence_score}") print() print("-" * 40) diff --git a/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_multi_turn_prediction_async.py b/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_multi_turn_prediction_async.py index 1b0988f34dbd..8253f61578df 100644 --- a/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_multi_turn_prediction_async.py +++ b/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_multi_turn_prediction_async.py @@ -1,8 +1,10 @@ # pylint: disable=line-too-long,useless-suppression import functools +from typing import cast import pytest -from devtools_testutils import AzureRecordedTestCase, EnvironmentVariableLoader, recorded_by_proxy +from devtools_testutils import AzureRecordedTestCase, EnvironmentVariableLoader +from devtools_testutils.aio import recorded_by_proxy_async from azure.ai.language.conversations.aio import ConversationAnalysisClient from azure.ai.language.conversations.models import ( ConversationalAITask, @@ -18,13 +20,7 @@ ConversationalAIIntent, ConversationalAIEntity, ConversationItemRange, - DateTimeResolution, - EntitySubtype, - EntityTag, ) -from typing import cast -from devtools_testutils.aio import recorded_by_proxy_async -from azure.core.async_paging import AsyncItemPaged from azure.core.credentials import AzureKeyCredential @@ -123,24 +119,6 @@ async def test_conversation_multi_turn_prediction_async(self, conversations_endp f"Index: {ent.conversation_item_index}" ) - # Date/time resolutions - if ent.resolutions: - for res in ent.resolutions: - if isinstance(res, DateTimeResolution): - print( - f" - [DateTimeResolution] SubKind: {getattr(res, 'date_time_sub_kind', None)}, " - f"Timex: {res.timex}, Value: {res.value}" - ) - - # Extra information (entity subtype + tags) - if ent.extra_information: - for extra in ent.extra_information: - if isinstance(extra, EntitySubtype): - print(f" - [EntitySubtype] Value: {extra.value}") - for tag in extra.tags or []: - tag = cast(EntityTag, tag) - print(f" • Tag: {tag.name}, Confidence: {tag.confidence_score}") - print() # Global entities @@ -155,13 +133,6 @@ async def test_conversation_multi_turn_prediction_async(self, conversations_endp f" Conversation Item ID: {ent.conversation_item_id}, " f"Index: {ent.conversation_item_index}" ) - if ent.extra_information: - for extra in ent.extra_information: - if isinstance(extra, EntitySubtype): - print(f" - [EntitySubtype] Value: {extra.value}") - for tag in extra.tags or []: - tag = cast(EntityTag, tag) - print(f" • Tag: {tag.name}, Confidence: {tag.confidence_score}") print("-" * 40) finally: await client.close() diff --git a/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii.py b/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii.py index cc0e75c3f644..73dffd3f23e6 100644 --- a/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii.py +++ b/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii.py @@ -1,5 +1,5 @@ import functools -import pytest +from typing import cast, List from devtools_testutils import AzureRecordedTestCase, EnvironmentVariableLoader, recorded_by_proxy from azure.ai.language.conversations import ConversationAnalysisClient, AnalyzeConversationLROPoller @@ -18,11 +18,9 @@ ConversationalPiiResult, ConversationPiiItemResult, NamedEntity, - InputWarning, ConversationError, AnalyzeConversationOperationAction, ) -from typing import cast, List from azure.core.credentials import AzureKeyCredential @@ -126,23 +124,7 @@ def test_conversation_pii(self, conversations_endpoint, conversations_key): print(f"Conversation: #{conversation.id}") print("Detected Entities:") for item in conversation.conversation_items or []: - item = cast(ConversationPiiItemResult, item) - for entity in item.entities or []: - entity = cast(NamedEntity, entity) - print(f" Category: {entity.category}") - print(f" Subcategory: {entity.subcategory}") - print(f" Text: {entity.text}") - print(f" Offset: {entity.offset}") - print(f" Length: {entity.length}") - print(f" Confidence score: {entity.confidence_score}\n") - entities_detected.append(entity) - - if conversation.warnings: - print("Warnings:") - for warning in conversation.warnings: - warning = cast(InputWarning, warning) - print(f" Code: {warning.code}") - print(f" Message: {warning.message}") + assert isinstance(item, ConversationPiiItemResult) print() else: print(" [No supported results to display for this action type]") diff --git a/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii_async.py b/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii_async.py index 7fb8c7036fb0..7ce74917b785 100644 --- a/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii_async.py +++ b/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii_async.py @@ -1,5 +1,6 @@ # pylint: disable=line-too-long,useless-suppression import functools +from typing import cast, List import pytest from devtools_testutils import AzureRecordedTestCase, EnvironmentVariableLoader @@ -15,15 +16,9 @@ PiiOperationAction, ConversationPiiActionContent, ConversationActions, - AnalyzeConversationOperationResult, - ConversationPiiOperationResult, - ConversationalPiiResult, - ConversationPiiItemResult, NamedEntity, - InputWarning, ConversationError, ) -from typing import cast, List from azure.core.credentials import AzureKeyCredential ConversationsPreparer = functools.partial( @@ -117,47 +112,14 @@ async def test_conversation_pii_async(self, conversations_endpoint, conversation f"Total: {actions_page.total}" ) - for action_result in actions_page.task_results or []: - ar = cast(AnalyzeConversationOperationResult, action_result) - print(f"\nAction Name: {getattr(ar, 'name', None)}") - print(f"Action Status: {getattr(ar, 'status', None)}") - print(f"Kind: {getattr(ar, 'kind', None)}") - - if isinstance(ar, ConversationPiiOperationResult): - for conversation in ar.results.conversations or []: - conversation = cast(ConversationalPiiResult, conversation) - print(f"Conversation: #{conversation.id}") - print("Detected Entities:") - for item in conversation.conversation_items or []: - item = cast(ConversationPiiItemResult, item) - for entity in item.entities or []: - entity = cast(NamedEntity, entity) - print(f" Category: {entity.category}") - print(f" Subcategory: {entity.subcategory}") - print(f" Text: {entity.text}") - print(f" Offset: {entity.offset}") - print(f" Length: {entity.length}") - print(f" Confidence score: {entity.confidence_score}\n") - entities_detected.append(entity) - - if conversation.warnings: - print("Warnings:") - for warning in conversation.warnings: - warning = cast(InputWarning, warning) - print(f" Code: {warning.code}") - print(f" Message: {warning.message}") - print() - else: - print(" [No supported results to display for this action type]") - - # ---- Print errors (from final-state metadata) --------------------- + # Print errors if d.get("errors"): print("\nErrors:") for err in d["errors"]: err = cast(ConversationError, err) print(f" Code: {err.code} - {err.message}") - # ---- Assertions --------------------------------------------------- + # Assertions assert len(entities_detected) > 0, "Expected at least one PII entity." assert (d.get("status") or "").lower() in {"succeeded", "partiallysucceeded"} finally: diff --git a/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii_with_character_mask_policy.py b/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii_with_character_mask_policy.py index 583524816119..3ba8a8d7c34c 100644 --- a/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii_with_character_mask_policy.py +++ b/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii_with_character_mask_policy.py @@ -1,5 +1,5 @@ import functools -import pytest +from typing import cast, List from devtools_testutils import AzureRecordedTestCase, EnvironmentVariableLoader, recorded_by_proxy from azure.ai.language.conversations import ConversationAnalysisClient, AnalyzeConversationLROPoller @@ -17,14 +17,10 @@ ConversationPiiOperationResult, ConversationalPiiResult, ConversationPiiItemResult, - NamedEntity, - InputWarning, - ConversationError, AnalyzeConversationOperationAction, CharacterMaskPolicyType, RedactionCharacter, ) -from typing import cast, List from azure.core.credentials import AzureKeyCredential @@ -111,23 +107,7 @@ def test_conversation_pii_with_character_mask_policy(self, conversations_endpoin for conversation in ar.results.conversations or []: conversation = cast(ConversationalPiiResult, conversation) for item in conversation.conversation_items or []: - item = cast(ConversationPiiItemResult, item) - redacted_text = (getattr(item.redacted_content, "text", None) or "").strip() - if not redacted_text: - continue - - # Only verify when there are detected entities in the original item - if item.entities: - # Ensure original PII text is NOT present and '*' is present - for entity in item.entities: - ent_text = cast(NamedEntity, entity).text or "" - assert ( - ent_text not in redacted_text - ), f"Expected entity '{ent_text}' to be redacted but found in: {redacted_text}" - assert ( - "*" in redacted_text - ), f"Expected redacted text to contain '*', got: {redacted_text}" - redacted_verified.append(redacted_text) + assert isinstance(item, ConversationPiiItemResult) # ---- Assertions ------------------------------------------------------- assert (d.get("status") or "").lower() in {"succeeded", "partiallysucceeded"} diff --git a/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii_with_character_mask_policy_async.py b/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii_with_character_mask_policy_async.py index 2f8888d3f66e..26b11f730f61 100644 --- a/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii_with_character_mask_policy_async.py +++ b/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii_with_character_mask_policy_async.py @@ -1,5 +1,7 @@ # pylint: disable=line-too-long,useless-suppression import functools +from typing import cast, List + import pytest from devtools_testutils import AzureRecordedTestCase, EnvironmentVariableLoader @@ -20,12 +22,10 @@ ConversationalPiiResult, ConversationPiiItemResult, NamedEntity, - InputWarning, ConversationError, CharacterMaskPolicyType, RedactionCharacter, ) -from typing import cast, List from azure.core.credentials import AzureKeyCredential ConversationsPreparer = functools.partial( diff --git a/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii_with_entity_mask_policy.py b/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii_with_entity_mask_policy.py index 0356c86322c4..8701b58687da 100644 --- a/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii_with_entity_mask_policy.py +++ b/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii_with_entity_mask_policy.py @@ -1,6 +1,6 @@ # pylint: disable=line-too-long,useless-suppression import functools -import pytest +from typing import cast, List from devtools_testutils import AzureRecordedTestCase, EnvironmentVariableLoader, recorded_by_proxy from azure.ai.language.conversations import ConversationAnalysisClient, AnalyzeConversationLROPoller @@ -18,16 +18,10 @@ ConversationPiiOperationResult, ConversationalPiiResult, ConversationPiiItemResult, - NamedEntity, - InputWarning, ConversationError, AnalyzeConversationOperationAction, - CharacterMaskPolicyType, - RedactionCharacter, EntityMaskTypePolicyType, ) -from typing import cast, List -import re from azure.core.credentials import AzureKeyCredential @@ -129,25 +123,6 @@ def test_conversation_pii_with_entity_mask_policy(self, conversations_endpoint, redacted_text = (getattr(item.redacted_content, "text", None) or "").strip() print(f"Redacted Text: {redacted_text}") - # Only verify when there are detected entities in the original item - if item.entities and redacted_text: - for entity in item.entities: - entity = cast(NamedEntity, entity) - original_text = entity.text or "" - # 1) original PII should not be present - assert ( - original_text not in redacted_text - ), f"Expected entity '{original_text}' to be redacted but found in: {redacted_text}" - - # 2) redaction should show an entity mask like [Person] or [Person-1] - expected_mask_pattern = rf"\[{re.escape(entity.category)}-?\d*\]" - assert re.search(expected_mask_pattern, redacted_text, flags=re.IGNORECASE), ( - f"Expected redacted text to contain an entity mask similar to " - f"'[{entity.category}]' but got: {redacted_text}" - ) - - redacted_verified.append(redacted_text) - # ---- Assertions ------------------------------------------------------- assert (d.get("status") or "").lower() in {"succeeded", "partiallysucceeded"} assert len(redacted_verified) > 0, "Expected at least one redacted line to be verified." diff --git a/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii_with_entity_mask_policy_async.py b/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii_with_entity_mask_policy_async.py index 1725f1a8be96..c113a03191a7 100644 --- a/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii_with_entity_mask_policy_async.py +++ b/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii_with_entity_mask_policy_async.py @@ -1,5 +1,8 @@ # pylint: disable=line-too-long,useless-suppression import functools +import re +from typing import cast, List + import pytest from devtools_testutils import AzureRecordedTestCase, EnvironmentVariableLoader @@ -23,8 +26,7 @@ ConversationError, EntityMaskTypePolicyType, ) -import re -from typing import cast, List + from azure.core.credentials import AzureKeyCredential ConversationsPreparer = functools.partial( diff --git a/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii_with_no_mask_policy.py b/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii_with_no_mask_policy.py index 5820bb175ede..c7b6112d65cc 100644 --- a/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii_with_no_mask_policy.py +++ b/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii_with_no_mask_policy.py @@ -1,6 +1,6 @@ # pylint: disable=line-too-long,useless-suppression import functools -import pytest +from typing import cast, List from devtools_testutils import AzureRecordedTestCase, EnvironmentVariableLoader, recorded_by_proxy from azure.ai.language.conversations import ConversationAnalysisClient, AnalyzeConversationLROPoller @@ -18,13 +18,10 @@ ConversationPiiOperationResult, ConversationalPiiResult, ConversationPiiItemResult, - NamedEntity, ConversationError, AnalyzeConversationOperationAction, NoMaskPolicyType, ) -from typing import cast, List -import re from azure.core.credentials import AzureKeyCredential @@ -117,19 +114,8 @@ def test_conversation_pii_with_no_mask_policy(self, conversations_endpoint, conv for conversation in ar.results.conversations or []: conversation = cast(ConversationalPiiResult, conversation) for item in conversation.conversation_items or []: - item = cast(ConversationPiiItemResult, item) - # With NoMask, service returns original text in redacted_content - returned_text = (getattr(item.redacted_content, "text", None) or "").strip() - if item.entities and returned_text: - for entity in item.entities: - entity = cast(NamedEntity, entity) - ent_text = entity.text or "" - detected_entities.append(ent_text) - # Ensure the original PII text is still present - assert ( - ent_text in returned_text - ), f"Expected entity '{ent_text}' to be present but was not found in: {returned_text}" - - # ---- Assertions ------------------------------------------------------- + assert isinstance(item, ConversationPiiItemResult) + + # ---- Assertions ------------------------ assert len(detected_entities) > 0, "Expected at least one detected PII entity." assert (d.get("status") or "").lower() in {"succeeded", "partiallysucceeded"} diff --git a/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii_with_no_mask_policy_async.py b/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii_with_no_mask_policy_async.py index d0a7a1d9ea48..9ffa7d06a432 100644 --- a/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii_with_no_mask_policy_async.py +++ b/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii_with_no_mask_policy_async.py @@ -1,5 +1,6 @@ # pylint: disable=line-too-long,useless-suppression import functools +from typing import cast, List import pytest from devtools_testutils import AzureRecordedTestCase, EnvironmentVariableLoader @@ -20,12 +21,9 @@ ConversationalPiiResult, ConversationPiiItemResult, NamedEntity, - InputWarning, ConversationError, NoMaskPolicyType, ) -import re -from typing import cast, List from azure.core.credentials import AzureKeyCredential ConversationsPreparer = functools.partial( diff --git a/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_prediction.py b/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_prediction.py index 3bed1c8091d5..d0697b50ef70 100644 --- a/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_prediction.py +++ b/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_prediction.py @@ -1,5 +1,5 @@ import functools -import pytest +from typing import cast from devtools_testutils import AzureRecordedTestCase, EnvironmentVariableLoader, recorded_by_proxy from azure.ai.language.conversations import ConversationAnalysisClient @@ -13,7 +13,6 @@ DateTimeResolution, ConversationLanguageUnderstandingInput, ) -from typing import cast from azure.core.credentials import AzureKeyCredential diff --git a/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_prediction_async.py b/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_prediction_async.py index ca6ce29260ca..f3aa7df720c8 100644 --- a/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_prediction_async.py +++ b/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_prediction_async.py @@ -1,24 +1,21 @@ import functools -import pytest +from typing import cast -from devtools_testutils import AzureRecordedTestCase, EnvironmentVariableLoader, recorded_by_proxy +import pytest +from devtools_testutils.aio import recorded_by_proxy_async +from devtools_testutils import AzureRecordedTestCase, EnvironmentVariableLoader from azure.ai.language.conversations.aio import ConversationAnalysisClient from azure.ai.language.conversations.models import ( ConversationLanguageUnderstandingInput, ConversationAnalysisInput, TextConversationItem, ConversationActionContent, - AnalyzeConversationActionResult, StringIndexType, ConversationActionResult, ConversationPrediction, DateTimeResolution, ) -from typing import cast -from devtools_testutils.aio import recorded_by_proxy_async -from azure.core.async_paging import AsyncItemPaged - from azure.core.credentials import AzureKeyCredential ConversationsPreparer = functools.partial( diff --git a/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_prediction_with_language.py b/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_prediction_with_language.py index fd44423ce2f8..f54d29a24397 100644 --- a/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_prediction_with_language.py +++ b/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_prediction_with_language.py @@ -1,24 +1,19 @@ import functools -import pytest +from typing import cast from devtools_testutils import AzureRecordedTestCase, EnvironmentVariableLoader, recorded_by_proxy from azure.ai.language.conversations import ConversationAnalysisClient from azure.ai.language.conversations.models import ( - AnalyzeConversationOperationInput, ConversationActionContent, ConversationAnalysisInput, TextConversationItem, ConversationActionResult, ConversationPrediction, - ConversationIntent, - ConversationEntity, StringIndexType, - ResolutionBase, DateTimeResolution, AnalyzeConversationActionResult, ConversationLanguageUnderstandingInput, ) -from typing import cast from azure.core.credentials import AzureKeyCredential diff --git a/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_prediction_with_language_async.py b/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_prediction_with_language_async.py index 1215a665b576..17517f0e413e 100644 --- a/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_prediction_with_language_async.py +++ b/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_prediction_with_language_async.py @@ -1,26 +1,22 @@ import functools +from typing import cast + import pytest -from devtools_testutils import AzureRecordedTestCase, EnvironmentVariableLoader, recorded_by_proxy +from devtools_testutils import AzureRecordedTestCase, EnvironmentVariableLoader +from devtools_testutils.aio import recorded_by_proxy_async from azure.ai.language.conversations.aio import ConversationAnalysisClient from azure.ai.language.conversations.models import ( - AnalyzeConversationOperationInput, ConversationActionContent, ConversationAnalysisInput, TextConversationItem, ConversationActionResult, ConversationPrediction, - ConversationIntent, - ConversationEntity, StringIndexType, - ResolutionBase, DateTimeResolution, ConversationLanguageUnderstandingInput, AnalyzeConversationActionResult, ) -from typing import cast -from devtools_testutils.aio import recorded_by_proxy_async -from azure.core.async_paging import AsyncItemPaged from azure.core.credentials import AzureKeyCredential diff --git a/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_prediction_with_options.py b/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_prediction_with_options.py index 7a5670cb6407..3f1ef395fa52 100644 --- a/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_prediction_with_options.py +++ b/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_prediction_with_options.py @@ -1,23 +1,18 @@ import functools -import pytest +from typing import cast from devtools_testutils import AzureRecordedTestCase, EnvironmentVariableLoader, recorded_by_proxy from azure.ai.language.conversations import ConversationAnalysisClient from azure.ai.language.conversations.models import ( - AnalyzeConversationOperationInput, ConversationActionContent, ConversationAnalysisInput, TextConversationItem, ConversationActionResult, ConversationPrediction, - ConversationIntent, - ConversationEntity, StringIndexType, - ResolutionBase, DateTimeResolution, ConversationLanguageUnderstandingInput, ) -from typing import cast from azure.core.credentials import AzureKeyCredential diff --git a/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_prediction_with_options_async.py b/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_prediction_with_options_async.py index 4023696eea93..2d99f7148ee9 100644 --- a/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_prediction_with_options_async.py +++ b/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_prediction_with_options_async.py @@ -1,25 +1,22 @@ import functools +from typing import cast + import pytest -from devtools_testutils import AzureRecordedTestCase, EnvironmentVariableLoader, recorded_by_proxy +from devtools_testutils import AzureRecordedTestCase, EnvironmentVariableLoader +from devtools_testutils.aio import recorded_by_proxy_async + from azure.ai.language.conversations.aio import ConversationAnalysisClient from azure.ai.language.conversations.models import ( - AnalyzeConversationOperationInput, ConversationActionContent, ConversationAnalysisInput, TextConversationItem, ConversationActionResult, ConversationPrediction, - ConversationIntent, - ConversationEntity, StringIndexType, - ResolutionBase, DateTimeResolution, ConversationLanguageUnderstandingInput, ) -from typing import cast -from devtools_testutils.aio import recorded_by_proxy_async -from azure.core.async_paging import AsyncItemPaged from azure.core.credentials import AzureKeyCredential diff --git a/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_summarization.py b/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_summarization.py index 3a67236a4a63..bcc3647e5253 100644 --- a/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_summarization.py +++ b/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_summarization.py @@ -1,6 +1,6 @@ # pylint: disable=line-too-long,useless-suppression import functools -import pytest +from typing import cast, List from devtools_testutils import AzureRecordedTestCase, EnvironmentVariableLoader, recorded_by_proxy from azure.ai.language.conversations import ConversationAnalysisClient, AnalyzeConversationLROPoller @@ -18,7 +18,6 @@ SummarizationOperationResult, ConversationActions, ) -from typing import cast, List from azure.core.credentials import AzureKeyCredential ConversationsPreparer = functools.partial( @@ -129,10 +128,6 @@ def test_conversation_summarization(self, conversations_endpoint, conversations_ for summary in conversation.summaries: print(f" Aspect: {summary.aspect}") print(f" Text: {summary.text}") - if conversation.warnings: - print(" Warnings:") - for warning in conversation.warnings: - print(f" Code: {warning.code}, Message: {warning.message}") else: print(" [No supported results to display for this action type]") diff --git a/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_summarization_async.py b/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_summarization_async.py index dcfea1c2c16e..263ae25f8687 100644 --- a/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_summarization_async.py +++ b/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_summarization_async.py @@ -1,5 +1,7 @@ # pylint: disable=line-too-long,useless-suppression import functools +from typing import cast, List + import pytest from devtools_testutils import AzureRecordedTestCase, EnvironmentVariableLoader @@ -19,7 +21,6 @@ SummarizationOperationResult, ConversationActions, ) -from typing import cast, List from azure.core.credentials import AzureKeyCredential ConversationsPreparer = functools.partial( diff --git a/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_orchestration_prediction.py b/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_orchestration_prediction.py index 25c1cb5d5aa4..78455ddf7dfe 100644 --- a/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_orchestration_prediction.py +++ b/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_orchestration_prediction.py @@ -1,5 +1,5 @@ import functools -import pytest +from typing import cast from devtools_testutils import AzureRecordedTestCase, EnvironmentVariableLoader, recorded_by_proxy from azure.ai.language.conversations import ConversationAnalysisClient @@ -14,7 +14,6 @@ QuestionAnsweringTargetIntentResult, ConversationActionResult, ) -from typing import cast from azure.core.credentials import AzureKeyCredential diff --git a/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_orchestration_prediction_async.py b/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_orchestration_prediction_async.py index 720119563d08..02e9d155b95e 100644 --- a/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_orchestration_prediction_async.py +++ b/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_orchestration_prediction_async.py @@ -1,11 +1,12 @@ # pylint: disable=line-too-long,useless-suppression import functools +from typing import cast + import pytest from devtools_testutils import AzureRecordedTestCase, EnvironmentVariableLoader from devtools_testutils.aio import recorded_by_proxy_async -from azure.core.async_paging import AsyncItemPaged -from azure.ai.language.conversations.aio import ConversationAnalysisClient, AnalyzeConversationAsyncLROPoller +from azure.ai.language.conversations.aio import ConversationAnalysisClient from azure.ai.language.conversations.models import ( AnalyzeConversationActionResult, ConversationActionContent, @@ -17,7 +18,6 @@ QuestionAnsweringTargetIntentResult, ConversationActionResult, ) -from typing import cast, List from azure.core.credentials import AzureKeyCredential ConversationsPreparer = functools.partial( From bea58ac228c4fd171215256de4548123d562a127 Mon Sep 17 00:00:00 2001 From: "Amber Chen (Centific Technologies Inc)" Date: Mon, 26 Jan 2026 17:13:48 -0800 Subject: [PATCH 05/10] updated samples --- .../async/sample_authentication_async.py | 10 +++---- ...onversation_multi_turn_prediction_async.py | 9 ++---- ...on_pii_with_character_mask_policy_async.py | 1 - ...ation_pii_with_entity_mask_policy_async.py | 1 - ...versation_pii_with_no_mask_policy_async.py | 5 ---- .../samples/sample_authentication.py | 6 ++-- ...mple_conversation_multi_turn_prediction.py | 28 ++----------------- .../samples/sample_conversation_pii.py | 12 +------- ...ersation_pii_with_character_mask_policy.py | 7 ++--- ...onversation_pii_with_entity_mask_policy.py | 5 ++-- ...le_conversation_pii_with_no_mask_policy.py | 7 ++--- ...e_conversation_prediction_with_language.py | 4 +-- ...le_conversation_prediction_with_options.py | 4 +-- .../sample_conversation_summarization.py | 2 +- 14 files changed, 25 insertions(+), 76 deletions(-) diff --git a/sdk/cognitivelanguage/azure-ai-language-conversations/samples/async/sample_authentication_async.py b/sdk/cognitivelanguage/azure-ai-language-conversations/samples/async/sample_authentication_async.py index 0da8e2993fb9..0960f3a7b06c 100644 --- a/sdk/cognitivelanguage/azure-ai-language-conversations/samples/async/sample_authentication_async.py +++ b/sdk/cognitivelanguage/azure-ai-language-conversations/samples/async/sample_authentication_async.py @@ -39,27 +39,27 @@ async def sample_authentication_api_key_async(): endpoint = os.environ["AZURE_CONVERSATIONS_ENDPOINT"] key = os.environ["AZURE_CONVERSATIONS_KEY"] - clu_client = ConversationAnalysisClient(endpoint, AzureKeyCredential(key)) + clu_client = ConversationAnalysisClient(endpoint, AzureKeyCredential(key)) #pylint:disable=unused-variable # [END create_clu_client_with_key_async] -async def sample_authentication_with_azure_active_directory(): +async def sample_authentication_with_aad(): """DefaultAzureCredential will use the values from these environment variables: AZURE_CLIENT_ID, AZURE_TENANT_ID, AZURE_CLIENT_SECRET """ - print("\n.. authentication_with_azure_active_directory") + print("\n.. authentication_with_aad") from azure.ai.language.conversations.aio import ConversationAnalysisClient from azure.identity.aio import DefaultAzureCredential endpoint = os.environ["AZURE_CONVERSATIONS_ENDPOINT"] credential = DefaultAzureCredential() - clu_client = ConversationAnalysisClient(endpoint, credential=credential) + clu_client = ConversationAnalysisClient(endpoint, credential=credential) #pylint:disable=unused-variable async def main(): await sample_authentication_api_key_async() - await sample_authentication_with_azure_active_directory() + await sample_authentication_with_aad() if __name__ == "__main__": diff --git a/sdk/cognitivelanguage/azure-ai-language-conversations/samples/async/sample_conversation_multi_turn_prediction_async.py b/sdk/cognitivelanguage/azure-ai-language-conversations/samples/async/sample_conversation_multi_turn_prediction_async.py index 3e00228b12ce..33439a8246d3 100644 --- a/sdk/cognitivelanguage/azure-ai-language-conversations/samples/async/sample_conversation_multi_turn_prediction_async.py +++ b/sdk/cognitivelanguage/azure-ai-language-conversations/samples/async/sample_conversation_multi_turn_prediction_async.py @@ -46,17 +46,12 @@ # Response/result discriminators ConversationalAITaskResult, ConversationalAIResult, - ConversationalAIAnalysis, - ConversationalAIIntent, - ConversationalAIEntity, - ConversationItemRange, DateTimeResolution, EntitySubtype, - EntityTag, ) -async def sample_conversation_multi_turn_prediction_async(): +async def sample_conv_multi_turn_prediction_async(): # get settings endpoint = os.environ["AZURE_CONVERSATIONS_ENDPOINT"] project_name = os.environ["AZURE_CONVERSATIONS_PROJECT_NAME"] @@ -166,7 +161,7 @@ async def sample_conversation_multi_turn_prediction_async(): async def main(): - await sample_conversation_multi_turn_prediction_async() + await sample_conv_multi_turn_prediction_async() if __name__ == "__main__": diff --git a/sdk/cognitivelanguage/azure-ai-language-conversations/samples/async/sample_conversation_pii_with_character_mask_policy_async.py b/sdk/cognitivelanguage/azure-ai-language-conversations/samples/async/sample_conversation_pii_with_character_mask_policy_async.py index a0c16bb330fa..f2586734c152 100644 --- a/sdk/cognitivelanguage/azure-ai-language-conversations/samples/async/sample_conversation_pii_with_character_mask_policy_async.py +++ b/sdk/cognitivelanguage/azure-ai-language-conversations/samples/async/sample_conversation_pii_with_character_mask_policy_async.py @@ -45,7 +45,6 @@ CharacterMaskPolicyType, RedactionCharacter, ConversationPiiOperationResult, - ConversationError, ) diff --git a/sdk/cognitivelanguage/azure-ai-language-conversations/samples/async/sample_conversation_pii_with_entity_mask_policy_async.py b/sdk/cognitivelanguage/azure-ai-language-conversations/samples/async/sample_conversation_pii_with_entity_mask_policy_async.py index 0ca73229c488..93f667903c9d 100644 --- a/sdk/cognitivelanguage/azure-ai-language-conversations/samples/async/sample_conversation_pii_with_entity_mask_policy_async.py +++ b/sdk/cognitivelanguage/azure-ai-language-conversations/samples/async/sample_conversation_pii_with_entity_mask_policy_async.py @@ -45,7 +45,6 @@ ConversationPiiActionContent, EntityMaskTypePolicyType, ConversationPiiOperationResult, - ConversationError, ) diff --git a/sdk/cognitivelanguage/azure-ai-language-conversations/samples/async/sample_conversation_pii_with_no_mask_policy_async.py b/sdk/cognitivelanguage/azure-ai-language-conversations/samples/async/sample_conversation_pii_with_no_mask_policy_async.py index 20c20060fa0f..ef800d3bc029 100644 --- a/sdk/cognitivelanguage/azure-ai-language-conversations/samples/async/sample_conversation_pii_with_no_mask_policy_async.py +++ b/sdk/cognitivelanguage/azure-ai-language-conversations/samples/async/sample_conversation_pii_with_no_mask_policy_async.py @@ -42,12 +42,7 @@ PiiOperationAction, ConversationPiiActionContent, NoMaskPolicyType, - AnalyzeConversationOperationResult, ConversationPiiOperationResult, - ConversationalPiiResult, - ConversationPiiItemResult, - NamedEntity, - ConversationError, ) diff --git a/sdk/cognitivelanguage/azure-ai-language-conversations/samples/sample_authentication.py b/sdk/cognitivelanguage/azure-ai-language-conversations/samples/sample_authentication.py index 1c494e8f03ba..ba5c134b6480 100644 --- a/sdk/cognitivelanguage/azure-ai-language-conversations/samples/sample_authentication.py +++ b/sdk/cognitivelanguage/azure-ai-language-conversations/samples/sample_authentication.py @@ -39,11 +39,11 @@ def sample_authentication_api_key(): endpoint = os.environ["AZURE_CONVERSATIONS_ENDPOINT"] key = os.environ["AZURE_CONVERSATIONS_KEY"] - clu_client = ConversationAnalysisClient(endpoint, AzureKeyCredential(key)) + clu_client = ConversationAnalysisClient(endpoint, AzureKeyCredential(key)) # pylint:disable=unused-variable # [END create_clu_client_with_key] -def sample_authentication_with_azure_active_directory(): +def sample_authentication_with_aad(): """DefaultAzureCredential will use the values from these environment variables: AZURE_CLIENT_ID, AZURE_TENANT_ID, AZURE_CLIENT_SECRET """ @@ -54,7 +54,7 @@ def sample_authentication_with_azure_active_directory(): endpoint = os.environ["AZURE_CONVERSATIONS_ENDPOINT"] credential = DefaultAzureCredential() - clu_client = ConversationAnalysisClient(endpoint, credential=credential) + clu_client = ConversationAnalysisClient(endpoint, credential=credential) # pylint:disable=unused-variable def main(): diff --git a/sdk/cognitivelanguage/azure-ai-language-conversations/samples/sample_conversation_multi_turn_prediction.py b/sdk/cognitivelanguage/azure-ai-language-conversations/samples/sample_conversation_multi_turn_prediction.py index d0ddfeea9404..44bce24c34b3 100644 --- a/sdk/cognitivelanguage/azure-ai-language-conversations/samples/sample_conversation_multi_turn_prediction.py +++ b/sdk/cognitivelanguage/azure-ai-language-conversations/samples/sample_conversation_multi_turn_prediction.py @@ -42,13 +42,10 @@ TextConversationItem, StringIndexType, ConversationalAITaskResult, - DateTimeResolution, - EntitySubtype, - EntityTag, ) -def sample_conversation_multi_turn_prediction(): +def sample_conv_multi_turn_prediction(): # get settings endpoint = os.environ["AZURE_CONVERSATIONS_ENDPOINT"] project_name = os.environ["AZURE_CONVERSATIONS_PROJECT_NAME"] @@ -117,21 +114,6 @@ def sample_conversation_multi_turn_prediction(): f" Conversation Item ID: {ent.conversation_item_id}, " f"Index: {ent.conversation_item_index}" ) - - # Date/time resolutions - for res in ent.resolutions or []: - if isinstance(res, DateTimeResolution): - print( - f" - [DateTimeResolution] SubKind: {res.date_time_sub_kind}, " - f"Timex: {res.timex}, Value: {res.value}" - ) - - # Extra information (entity subtype + tags) - for extra in ent.extra_information or []: - if isinstance(extra, EntitySubtype): - print(f" - [EntitySubtype] Value: {extra.value}") - for tag in extra.tags or []: - print(f" • Tag: {tag.name}, Confidence: {tag.confidence_score}") print() # Global entities @@ -144,12 +126,6 @@ def sample_conversation_multi_turn_prediction(): print( f" Conversation Item ID: {ent.conversation_item_id}, " f"Index: {ent.conversation_item_index}" ) - - for extra in ent.extra_information or []: - if isinstance(extra, EntitySubtype): - print(f" - [EntitySubtype] Value: {extra.value}") - for tag in extra.tags or []: - print(f" • Tag: {tag.name}, Confidence: {tag.confidence_score}") print("-" * 40) else: print("No Conversational AI result returned.") @@ -159,7 +135,7 @@ def sample_conversation_multi_turn_prediction(): def main(): - sample_conversation_multi_turn_prediction() + sample_conv_multi_turn_prediction() if __name__ == "__main__": diff --git a/sdk/cognitivelanguage/azure-ai-language-conversations/samples/sample_conversation_pii.py b/sdk/cognitivelanguage/azure-ai-language-conversations/samples/sample_conversation_pii.py index 0a2ee2448ecd..dfab28acff99 100644 --- a/sdk/cognitivelanguage/azure-ai-language-conversations/samples/sample_conversation_pii.py +++ b/sdk/cognitivelanguage/azure-ai-language-conversations/samples/sample_conversation_pii.py @@ -38,10 +38,7 @@ AnalyzeConversationOperationInput, PiiOperationAction, ConversationPiiActionContent, - AnalyzeConversationOperationResult, ConversationPiiOperationResult, - InputWarning, - ConversationError, ) @@ -116,7 +113,7 @@ def sample_conversation_pii(): print(f"Display Name: {d.get('display_name')}") # iterate results (sync pageable) - for actions_page in paged_actions: + for actions_page in paged_actions: # pylint:disable=too-many-nested-blocks print( f"Completed: {actions_page.completed}, " f"In Progress: {actions_page.in_progress}, " @@ -143,13 +140,6 @@ def sample_conversation_pii(): print(f" Length: {entity.length}") print(f" Confidence score: {entity.confidence_score}\n") entities_detected.append(entity) - - if conversation.warnings: - print("Warnings:") - for warning in conversation.warnings: - if isinstance(warning, InputWarning): - print(f" Code: {warning.code}") - print(f" Message: {warning.message}") print() else: print(" [No supported results to display for this action type]") diff --git a/sdk/cognitivelanguage/azure-ai-language-conversations/samples/sample_conversation_pii_with_character_mask_policy.py b/sdk/cognitivelanguage/azure-ai-language-conversations/samples/sample_conversation_pii_with_character_mask_policy.py index 174bf4d8ad63..63ceebe778ef 100644 --- a/sdk/cognitivelanguage/azure-ai-language-conversations/samples/sample_conversation_pii_with_character_mask_policy.py +++ b/sdk/cognitivelanguage/azure-ai-language-conversations/samples/sample_conversation_pii_with_character_mask_policy.py @@ -43,11 +43,10 @@ CharacterMaskPolicyType, RedactionCharacter, ConversationPiiOperationResult, - ConversationError, ) -def sample_conversation_pii_with_character_mask_policy(): +def sample_conv_pii_char_mask_policy(): # settings endpoint = os.environ["AZURE_CONVERSATIONS_ENDPOINT"] @@ -117,7 +116,7 @@ def sample_conversation_pii_with_character_mask_policy(): print(f" Code: {err.code} - {err.message}") # iterate results and verify redaction - for actions_page in paged_actions: + for actions_page in paged_actions: # pylint:disable=too-many-nested-blocks for action_result in actions_page.task_results or []: if isinstance(action_result, ConversationPiiOperationResult): for conversation in action_result.results.conversations or []: @@ -142,7 +141,7 @@ def sample_conversation_pii_with_character_mask_policy(): def main(): - sample_conversation_pii_with_character_mask_policy() + sample_conv_pii_char_mask_policy() if __name__ == "__main__": diff --git a/sdk/cognitivelanguage/azure-ai-language-conversations/samples/sample_conversation_pii_with_entity_mask_policy.py b/sdk/cognitivelanguage/azure-ai-language-conversations/samples/sample_conversation_pii_with_entity_mask_policy.py index 683b4bfe4323..5cd633d50a69 100644 --- a/sdk/cognitivelanguage/azure-ai-language-conversations/samples/sample_conversation_pii_with_entity_mask_policy.py +++ b/sdk/cognitivelanguage/azure-ai-language-conversations/samples/sample_conversation_pii_with_entity_mask_policy.py @@ -44,11 +44,10 @@ ConversationPiiActionContent, EntityMaskTypePolicyType, ConversationPiiOperationResult, - ConversationError, ) -def sample_conversation_pii_with_entity_mask_policy(): +def sample_conv_pii_entity_mask_policy(): # settings endpoint = os.environ["AZURE_CONVERSATIONS_ENDPOINT"] credential = DefaultAzureCredential() @@ -151,7 +150,7 @@ def sample_conversation_pii_with_entity_mask_policy(): def main(): - sample_conversation_pii_with_entity_mask_policy() + sample_conv_pii_entity_mask_policy() if __name__ == "__main__": diff --git a/sdk/cognitivelanguage/azure-ai-language-conversations/samples/sample_conversation_pii_with_no_mask_policy.py b/sdk/cognitivelanguage/azure-ai-language-conversations/samples/sample_conversation_pii_with_no_mask_policy.py index 9f8a94c6bad2..4c7a0228cb60 100644 --- a/sdk/cognitivelanguage/azure-ai-language-conversations/samples/sample_conversation_pii_with_no_mask_policy.py +++ b/sdk/cognitivelanguage/azure-ai-language-conversations/samples/sample_conversation_pii_with_no_mask_policy.py @@ -42,13 +42,10 @@ ConversationPiiActionContent, NoMaskPolicyType, ConversationPiiOperationResult, - ConversationalPiiResult, - NamedEntity, - ConversationError, ) -def sample_conversation_pii_with_no_mask_policy(): +def sample_conv_pii_no_mask_policy(): # settings endpoint = os.environ["AZURE_CONVERSATIONS_ENDPOINT"] credential = DefaultAzureCredential() @@ -137,7 +134,7 @@ def sample_conversation_pii_with_no_mask_policy(): def main(): - sample_conversation_pii_with_no_mask_policy() + sample_conv_pii_no_mask_policy() if __name__ == "__main__": diff --git a/sdk/cognitivelanguage/azure-ai-language-conversations/samples/sample_conversation_prediction_with_language.py b/sdk/cognitivelanguage/azure-ai-language-conversations/samples/sample_conversation_prediction_with_language.py index b43e27874c44..123e0720bd60 100644 --- a/sdk/cognitivelanguage/azure-ai-language-conversations/samples/sample_conversation_prediction_with_language.py +++ b/sdk/cognitivelanguage/azure-ai-language-conversations/samples/sample_conversation_prediction_with_language.py @@ -45,7 +45,7 @@ ) -def sample_conversation_prediction_with_language(): +def sample_conv_prediction_language(): # settings endpoint = os.environ["AZURE_CONVERSATIONS_ENDPOINT"] project_name = os.environ["AZURE_CONVERSATIONS_PROJECT_NAME"] @@ -112,7 +112,7 @@ def sample_conversation_prediction_with_language(): def main(): - sample_conversation_prediction_with_language() + sample_conv_prediction_language() if __name__ == "__main__": diff --git a/sdk/cognitivelanguage/azure-ai-language-conversations/samples/sample_conversation_prediction_with_options.py b/sdk/cognitivelanguage/azure-ai-language-conversations/samples/sample_conversation_prediction_with_options.py index ddb054b6f92f..345492749049 100644 --- a/sdk/cognitivelanguage/azure-ai-language-conversations/samples/sample_conversation_prediction_with_options.py +++ b/sdk/cognitivelanguage/azure-ai-language-conversations/samples/sample_conversation_prediction_with_options.py @@ -45,7 +45,7 @@ ) -def sample_conversation_prediction_with_options(): +def sample_conv_prediction_options(): # settings endpoint = os.environ["AZURE_CONVERSATIONS_ENDPOINT"] project_name = os.environ["AZURE_CONVERSATIONS_PROJECT_NAME"] @@ -111,7 +111,7 @@ def sample_conversation_prediction_with_options(): def main(): - sample_conversation_prediction_with_options() + sample_conv_prediction_options() if __name__ == "__main__": diff --git a/sdk/cognitivelanguage/azure-ai-language-conversations/samples/sample_conversation_summarization.py b/sdk/cognitivelanguage/azure-ai-language-conversations/samples/sample_conversation_summarization.py index 09edb2215257..c34099cb1c7b 100644 --- a/sdk/cognitivelanguage/azure-ai-language-conversations/samples/sample_conversation_summarization.py +++ b/sdk/cognitivelanguage/azure-ai-language-conversations/samples/sample_conversation_summarization.py @@ -112,7 +112,7 @@ def sample_conversation_summarization(): print(f"Display Name: {d.get('display_name')}") # Iterate results - for actions_page in paged_actions: + for actions_page in paged_actions: # pylint: disable=too-many-nested-blocks print( f"Completed: {actions_page.completed}, " f"In Progress: {actions_page.in_progress}, " From 1918ba46e602f9eaed60f70459d101a3b4792659 Mon Sep 17 00:00:00 2001 From: "Amber Chen (Centific Technologies Inc)" Date: Tue, 27 Jan 2026 09:41:50 -0800 Subject: [PATCH 06/10] updated samples --- ...onversation_multi_turn_prediction_async.py | 23 -------------- .../async/sample_conversation_pii_async.py | 9 ------ ...on_pii_with_character_mask_policy_async.py | 20 ++---------- ...ation_pii_with_entity_mask_policy_async.py | 31 ++----------------- ...versation_pii_with_no_mask_policy_async.py | 16 ++-------- ...ersation_prediction_with_language_async.py | 4 +-- ...versation_prediction_with_options_async.py | 4 +-- ...onversation_pii_with_entity_mask_policy.py | 27 +--------------- ...le_conversation_pii_with_no_mask_policy.py | 13 +------- 9 files changed, 15 insertions(+), 132 deletions(-) diff --git a/sdk/cognitivelanguage/azure-ai-language-conversations/samples/async/sample_conversation_multi_turn_prediction_async.py b/sdk/cognitivelanguage/azure-ai-language-conversations/samples/async/sample_conversation_multi_turn_prediction_async.py index 33439a8246d3..2f702ff53aa1 100644 --- a/sdk/cognitivelanguage/azure-ai-language-conversations/samples/async/sample_conversation_multi_turn_prediction_async.py +++ b/sdk/cognitivelanguage/azure-ai-language-conversations/samples/async/sample_conversation_multi_turn_prediction_async.py @@ -46,8 +46,6 @@ # Response/result discriminators ConversationalAITaskResult, ConversationalAIResult, - DateTimeResolution, - EntitySubtype, ) @@ -119,21 +117,6 @@ async def sample_conv_multi_turn_prediction_async(): f" Conversation Item ID: {ent.conversation_item_id}, " f"Index: {ent.conversation_item_index}" ) - - # Date/time resolutions - for res in ent.resolutions or []: - if isinstance(res, DateTimeResolution): - print( - f" - [DateTimeResolution] SubKind: {res.date_time_sub_kind}, " - f"Timex: {res.timex}, Value: {res.value}" - ) - - # Extra information (entity subtype + tags) - for extra in ent.extra_information or []: - if isinstance(extra, EntitySubtype): - print(f" - [EntitySubtype] Value: {extra.value}") - for tag in extra.tags or []: - print(f" • Tag: {tag.name}, Confidence: {tag.confidence_score}") print() # Global entities @@ -146,12 +129,6 @@ async def sample_conv_multi_turn_prediction_async(): print( f" Conversation Item ID: {ent.conversation_item_id}, " f"Index: {ent.conversation_item_index}" ) - - for extra in ent.extra_information or []: - if isinstance(extra, EntitySubtype): - print(f" - [EntitySubtype] Value: {extra.value}") - for tag in extra.tags or []: - print(f" • Tag: {tag.name}, Confidence: {tag.confidence_score}") print("-" * 40) else: print("No Conversational AI result returned.") diff --git a/sdk/cognitivelanguage/azure-ai-language-conversations/samples/async/sample_conversation_pii_async.py b/sdk/cognitivelanguage/azure-ai-language-conversations/samples/async/sample_conversation_pii_async.py index 5c06268a4239..f1a7260f67d0 100644 --- a/sdk/cognitivelanguage/azure-ai-language-conversations/samples/async/sample_conversation_pii_async.py +++ b/sdk/cognitivelanguage/azure-ai-language-conversations/samples/async/sample_conversation_pii_async.py @@ -39,10 +39,7 @@ AnalyzeConversationOperationInput, PiiOperationAction, ConversationPiiActionContent, - AnalyzeConversationOperationResult, ConversationPiiOperationResult, - InputWarning, - ConversationError, ) @@ -144,12 +141,6 @@ async def sample_conversation_pii_async(): print(f" Confidence score: {entity.confidence_score}\n") entities_detected.append(entity) - if conversation.warnings: - print("Warnings:") - for warning in conversation.warnings: - if isinstance(warning, InputWarning): - print(f" Code: {warning.code}") - print(f" Message: {warning.message}") print() else: print(" [No supported results to display for this action type]") diff --git a/sdk/cognitivelanguage/azure-ai-language-conversations/samples/async/sample_conversation_pii_with_character_mask_policy_async.py b/sdk/cognitivelanguage/azure-ai-language-conversations/samples/async/sample_conversation_pii_with_character_mask_policy_async.py index f2586734c152..3fa3d1138f2c 100644 --- a/sdk/cognitivelanguage/azure-ai-language-conversations/samples/async/sample_conversation_pii_with_character_mask_policy_async.py +++ b/sdk/cognitivelanguage/azure-ai-language-conversations/samples/async/sample_conversation_pii_with_character_mask_policy_async.py @@ -48,15 +48,13 @@ ) -async def sample_conversation_pii_with_character_mask_policy_async(): +async def sample_conv_pii_char_mask_policy_async(): # settings endpoint = os.environ["AZURE_CONVERSATIONS_ENDPOINT"] # AAD credential credential = DefaultAzureCredential() - redacted_verified: list[str] = [] - async with ConversationAnalysisClient(endpoint, credential=credential) as client: # build input ml_input = MultiLanguageConversationInput( @@ -123,26 +121,14 @@ async def sample_conversation_pii_with_character_mask_policy_async(): for conversation in action_result.results.conversations or []: for item in conversation.conversation_items or []: redacted_text = (item.redacted_content.text or "").strip() - if not redacted_text: - continue - - if item.entities: - for entity in item.entities: - ent_text = entity.text or "" - if ent_text in redacted_text: - print( - f"WARNING: Expected '{ent_text}' to be redacted but found in: {redacted_text}" - ) - - if "*" in redacted_text: - redacted_verified.append(redacted_text) + print(f"Redacted text: '{redacted_text}'") # [END conversation_pii_with_character_mask_policy_async] async def main(): - await sample_conversation_pii_with_character_mask_policy_async() + await sample_conv_pii_char_mask_policy_async() if __name__ == "__main__": diff --git a/sdk/cognitivelanguage/azure-ai-language-conversations/samples/async/sample_conversation_pii_with_entity_mask_policy_async.py b/sdk/cognitivelanguage/azure-ai-language-conversations/samples/async/sample_conversation_pii_with_entity_mask_policy_async.py index 93f667903c9d..23745b7393b9 100644 --- a/sdk/cognitivelanguage/azure-ai-language-conversations/samples/async/sample_conversation_pii_with_entity_mask_policy_async.py +++ b/sdk/cognitivelanguage/azure-ai-language-conversations/samples/async/sample_conversation_pii_with_entity_mask_policy_async.py @@ -30,7 +30,6 @@ # [START conversation_pii_with_entity_mask_policy_async] import os -import re import asyncio from azure.identity.aio import DefaultAzureCredential @@ -48,13 +47,11 @@ ) -async def sample_conversation_pii_with_entity_mask_policy_async(): +async def sample_conv_pii_entity_mask_policy_async(): # settings endpoint = os.environ["AZURE_CONVERSATIONS_ENDPOINT"] credential = DefaultAzureCredential() - redacted_verified = [] - async with ConversationAnalysisClient(endpoint, credential=credential) as client: # build input ml_input = MultiLanguageConversationInput( @@ -121,36 +118,14 @@ async def sample_conversation_pii_with_entity_mask_policy_async(): for conversation in action_result.results.conversations or []: for item in conversation.conversation_items or []: redacted_text = (item.redacted_content.text or "").strip() - if not redacted_text: - continue - if item.entities and redacted_text: - all_ok = True - for entity in item.entities: - original_text = entity.text or "" - # 1) original PII must be removed - if original_text and original_text in redacted_text: - print( - f"WARNING: Expected entity '{original_text}' to be redacted " - f"but found in: {redacted_text}" - ) - all_ok = False - # 2) mask should appear like [Person] or [Person-1] - expected_mask_pattern = rf"\[{re.escape(entity.category)}-?\d*\]" - if not re.search(expected_mask_pattern, redacted_text, flags=re.IGNORECASE): - print( - f"WARNING: Expected entity mask similar to " - f"'[{entity.category}]' but got: {redacted_text}" - ) - all_ok = False - if all_ok: - redacted_verified.append(redacted_text) + print(f"Redacted text: '{redacted_text}'") # [END conversation_pii_with_entity_mask_policy_async] async def main(): - await sample_conversation_pii_with_entity_mask_policy_async() + await sample_conv_pii_entity_mask_policy_async() if __name__ == "__main__": diff --git a/sdk/cognitivelanguage/azure-ai-language-conversations/samples/async/sample_conversation_pii_with_no_mask_policy_async.py b/sdk/cognitivelanguage/azure-ai-language-conversations/samples/async/sample_conversation_pii_with_no_mask_policy_async.py index ef800d3bc029..97ca6741e89e 100644 --- a/sdk/cognitivelanguage/azure-ai-language-conversations/samples/async/sample_conversation_pii_with_no_mask_policy_async.py +++ b/sdk/cognitivelanguage/azure-ai-language-conversations/samples/async/sample_conversation_pii_with_no_mask_policy_async.py @@ -46,13 +46,11 @@ ) -async def sample_conversation_pii_with_no_mask_policy_async(): +async def sample_conv_pii_no_mask_policy_async(): # settings endpoint = os.environ["AZURE_CONVERSATIONS_ENDPOINT"] credential = DefaultAzureCredential() - detected_entities = [] - async with ConversationAnalysisClient(endpoint, credential=credential) as client: # build input ml_input = MultiLanguageConversationInput( @@ -119,22 +117,14 @@ async def sample_conversation_pii_with_no_mask_policy_async(): for item in conversation.conversation_items or []: # NoMaskPolicyType returns original text (no redaction) returned_text = (item.redacted_content.text or "").strip() - if not returned_text: - continue - - if item.entities: - for entity in item.entities: - ent_text = entity.text or "" - detected_entities.append(ent_text) - if ent_text not in returned_text: - print(f"WARNING: Expected entity '{ent_text}' in returned text but not found.") + print(f"Returned text: '{returned_text}'") # [END conversation_pii_with_no_mask_policy_async] async def main(): - await sample_conversation_pii_with_no_mask_policy_async() + await sample_conv_pii_no_mask_policy_async() if __name__ == "__main__": diff --git a/sdk/cognitivelanguage/azure-ai-language-conversations/samples/async/sample_conversation_prediction_with_language_async.py b/sdk/cognitivelanguage/azure-ai-language-conversations/samples/async/sample_conversation_prediction_with_language_async.py index d138299b0674..9be3eaaa65b6 100644 --- a/sdk/cognitivelanguage/azure-ai-language-conversations/samples/async/sample_conversation_prediction_with_language_async.py +++ b/sdk/cognitivelanguage/azure-ai-language-conversations/samples/async/sample_conversation_prediction_with_language_async.py @@ -46,7 +46,7 @@ ) -async def sample_conversation_prediction_with_language_async(): +async def sample_conv_prediction_language_async(): # settings endpoint = os.environ["AZURE_CONVERSATIONS_ENDPOINT"] project_name = os.environ["AZURE_CONVERSATIONS_PROJECT_NAME"] @@ -113,7 +113,7 @@ async def sample_conversation_prediction_with_language_async(): async def main(): - await sample_conversation_prediction_with_language_async() + await sample_conv_prediction_language_async() if __name__ == "__main__": diff --git a/sdk/cognitivelanguage/azure-ai-language-conversations/samples/async/sample_conversation_prediction_with_options_async.py b/sdk/cognitivelanguage/azure-ai-language-conversations/samples/async/sample_conversation_prediction_with_options_async.py index bf4a05ec1f0b..817aba324d4a 100644 --- a/sdk/cognitivelanguage/azure-ai-language-conversations/samples/async/sample_conversation_prediction_with_options_async.py +++ b/sdk/cognitivelanguage/azure-ai-language-conversations/samples/async/sample_conversation_prediction_with_options_async.py @@ -46,7 +46,7 @@ ) -async def sample_conversation_prediction_with_options_async(): +async def sample_conv_prediction_options_async(): # settings endpoint = os.environ["AZURE_CONVERSATIONS_ENDPOINT"] project_name = os.environ["AZURE_CONVERSATIONS_PROJECT_NAME"] @@ -112,7 +112,7 @@ async def sample_conversation_prediction_with_options_async(): async def main(): - await sample_conversation_prediction_with_options_async() + await sample_conv_prediction_options_async() if __name__ == "__main__": diff --git a/sdk/cognitivelanguage/azure-ai-language-conversations/samples/sample_conversation_pii_with_entity_mask_policy.py b/sdk/cognitivelanguage/azure-ai-language-conversations/samples/sample_conversation_pii_with_entity_mask_policy.py index 5cd633d50a69..80ad9c08c493 100644 --- a/sdk/cognitivelanguage/azure-ai-language-conversations/samples/sample_conversation_pii_with_entity_mask_policy.py +++ b/sdk/cognitivelanguage/azure-ai-language-conversations/samples/sample_conversation_pii_with_entity_mask_policy.py @@ -30,7 +30,6 @@ # [START conversation_pii_with_entity_mask_policy] import os -import re from azure.identity import DefaultAzureCredential from azure.ai.language.conversations import ConversationAnalysisClient @@ -52,8 +51,6 @@ def sample_conv_pii_entity_mask_policy(): endpoint = os.environ["AZURE_CONVERSATIONS_ENDPOINT"] credential = DefaultAzureCredential() - redacted_verified = [] - client = ConversationAnalysisClient(endpoint, credential=credential) # build input @@ -121,29 +118,7 @@ def sample_conv_pii_entity_mask_policy(): for conversation in action_result.results.conversations or []: for item in conversation.conversation_items or []: redacted_text = (item.redacted_content.text or "").strip() - if not redacted_text: - continue - if item.entities and redacted_text: - all_ok = True - for entity in item.entities: - original_text = entity.text or "" - # 1) original PII must be removed - if original_text and original_text in redacted_text: - print( - f"WARNING: Expected entity '{original_text}' to be redacted " - f"but found in: {redacted_text}" - ) - all_ok = False - # 2) mask should appear like [Person] or [Person-1] - expected_mask_pattern = rf"\[{re.escape(entity.category)}-?\d*\]" - if not re.search(expected_mask_pattern, redacted_text, flags=re.IGNORECASE): - print( - f"WARNING: Expected entity mask similar to " - f"'[{entity.category}]' but got: {redacted_text}" - ) - all_ok = False - if all_ok: - redacted_verified.append(redacted_text) + print(f"Redacted text: '{redacted_text}'") # [END conversation_pii_with_entity_mask_policy] diff --git a/sdk/cognitivelanguage/azure-ai-language-conversations/samples/sample_conversation_pii_with_no_mask_policy.py b/sdk/cognitivelanguage/azure-ai-language-conversations/samples/sample_conversation_pii_with_no_mask_policy.py index 4c7a0228cb60..6844463474a0 100644 --- a/sdk/cognitivelanguage/azure-ai-language-conversations/samples/sample_conversation_pii_with_no_mask_policy.py +++ b/sdk/cognitivelanguage/azure-ai-language-conversations/samples/sample_conversation_pii_with_no_mask_policy.py @@ -50,8 +50,6 @@ def sample_conv_pii_no_mask_policy(): endpoint = os.environ["AZURE_CONVERSATIONS_ENDPOINT"] credential = DefaultAzureCredential() - detected_entities = [] - client = ConversationAnalysisClient(endpoint, credential=credential) # build input @@ -119,16 +117,7 @@ def sample_conv_pii_no_mask_policy(): for item in conversation.conversation_items or []: # NoMaskPolicyType returns original text (no redaction) returned_text = (item.redacted_content.text or "").strip() - if not returned_text: - continue - - if item.entities: - for entity in item.entities: - ent_text = entity.text or "" - detected_entities.append(ent_text) - if ent_text not in returned_text: - print(f"WARNING: Expected entity '{ent_text}' in returned text but not found.") - + print(f"Returned text: '{returned_text}'") # [END conversation_pii_with_no_mask_policy] From e61af47155e4b936b7e45d97988c8ce2291726e3 Mon Sep 17 00:00:00 2001 From: "Amber Chen (Centific Technologies Inc)" Date: Tue, 27 Jan 2026 10:07:39 -0800 Subject: [PATCH 07/10] updated tests --- .../tests/test_conversation_pii.py | 21 +++++++++- .../tests/test_conversation_pii_async.py | 40 ++++++++++++++++++- ...ersation_pii_with_character_mask_policy.py | 25 ++++++++++-- ...onversation_pii_with_entity_mask_policy.py | 22 +++++++++- ...st_conversation_pii_with_no_mask_policy.py | 14 ++++++- 5 files changed, 113 insertions(+), 9 deletions(-) diff --git a/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii.py b/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii.py index 73dffd3f23e6..f122b8ed973f 100644 --- a/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii.py +++ b/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii.py @@ -20,6 +20,7 @@ NamedEntity, ConversationError, AnalyzeConversationOperationAction, + InputWarning, ) from azure.core.credentials import AzureKeyCredential @@ -104,7 +105,7 @@ def test_conversation_pii(self, conversations_endpoint, conversations_key): print(f"Display Name: {d.get('display_name')}") # ---- Iterate pages and action results -------------------------------- - for actions_page in paged_actions: + for actions_page in paged_actions: # pylint: disable=too-many-nested-blocks print( f"Completed: {actions_page.completed}, " f"In Progress: {actions_page.in_progress}, " @@ -124,7 +125,23 @@ def test_conversation_pii(self, conversations_endpoint, conversations_key): print(f"Conversation: #{conversation.id}") print("Detected Entities:") for item in conversation.conversation_items or []: - assert isinstance(item, ConversationPiiItemResult) + item = cast(ConversationPiiItemResult, item) + for entity in item.entities or []: + entity = cast(NamedEntity, entity) + print(f" Category: {entity.category}") + print(f" Subcategory: {entity.subcategory}") + print(f" Text: {entity.text}") + print(f" Offset: {entity.offset}") + print(f" Length: {entity.length}") + print(f" Confidence score: {entity.confidence_score}\n") + entities_detected.append(entity) + + if conversation.warnings: + print("Warnings:") + for warning in conversation.warnings: + warning = cast(InputWarning, warning) + print(f" Code: {warning.code}") + print(f" Message: {warning.message}") print() else: print(" [No supported results to display for this action type]") diff --git a/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii_async.py b/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii_async.py index 7ce74917b785..3de04b678fa0 100644 --- a/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii_async.py +++ b/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii_async.py @@ -9,6 +9,7 @@ from azure.ai.language.conversations.aio import ConversationAnalysisClient, AnalyzeConversationAsyncLROPoller from azure.ai.language.conversations.models import ( AnalyzeConversationOperationInput, + ConversationPiiOperationResult, MultiLanguageConversationInput, TextConversation, TextConversationItem, @@ -18,6 +19,10 @@ ConversationActions, NamedEntity, ConversationError, + AnalyzeConversationOperationResult, + ConversationalPiiResult, + ConversationPiiItemResult, + InputWarning, ) from azure.core.credentials import AzureKeyCredential @@ -111,7 +116,40 @@ async def test_conversation_pii_async(self, conversations_endpoint, conversation f"Failed: {actions_page.failed}, " f"Total: {actions_page.total}" ) - + for action_result in actions_page.task_results or []: # pylint: disable=too-many-nested-blocks + ar = cast(AnalyzeConversationOperationResult, action_result) + print(f"\nAction Name: {getattr(ar, 'name', None)}") + print(f"Action Status: {getattr(ar, 'status', None)}") + print(f"Kind: {getattr(ar, 'kind', None)}") + + if isinstance(ar, ConversationPiiOperationResult): + for conversation in ar.results.conversations or []: + conversation = cast(ConversationalPiiResult, conversation) + print(f"Conversation: #{conversation.id}") + print("Detected Entities:") + for item in conversation.conversation_items or []: + item = cast(ConversationPiiItemResult, item) + for entity in item.entities or []: + entity = cast(NamedEntity, entity) + print(f" Category: {entity.category}") + print(f" Subcategory: {entity.subcategory}") + print(f" Text: {entity.text}") + print(f" Offset: {entity.offset}") + print(f" Length: {entity.length}") + print(f" Confidence score: {entity.confidence_score}\n") + entities_detected.append(entity) + + if conversation.warnings: + print("Warnings:") + for warning in conversation.warnings: + warning = cast(InputWarning, warning) + print(f" Code: {warning.code}") + print(f" Message: {warning.message}") + print() + else: + print(" [No supported results to display for this action type]") + + # ---- Print errors (from final-state metadata) --------------------- # Print errors if d.get("errors"): print("\nErrors:") diff --git a/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii_with_character_mask_policy.py b/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii_with_character_mask_policy.py index 3ba8a8d7c34c..ff77de632776 100644 --- a/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii_with_character_mask_policy.py +++ b/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii_with_character_mask_policy.py @@ -8,6 +8,7 @@ # request models AnalyzeConversationOperationInput, MultiLanguageConversationInput, + NamedEntity, TextConversation, TextConversationItem, PiiOperationAction, @@ -100,15 +101,31 @@ def test_conversation_pii_with_character_mask_policy(self, conversations_endpoin print(f"Status: {d.get('status')}") # ---- Iterate results and verify redaction ---------------------------- - for actions_page in paged_actions: + for actions_page in paged_actions: # pylint: disable=too-many-nested-blocks for action_result in actions_page.task_results or []: ar = cast(AnalyzeConversationOperationResult, action_result) if isinstance(ar, ConversationPiiOperationResult): for conversation in ar.results.conversations or []: conversation = cast(ConversationalPiiResult, conversation) for item in conversation.conversation_items or []: - assert isinstance(item, ConversationPiiItemResult) - - # ---- Assertions ------------------------------------------------------- + item = cast(ConversationPiiItemResult, item) + redacted_text = (getattr(item.redacted_content, "text", None) or "").strip() + if not redacted_text: + continue + + # Only verify when there are detected entities in the original item + if item.entities: + # Ensure original PII text is NOT present and '*' is present + for entity in item.entities: + ent_text = cast(NamedEntity, entity).text or "" + assert ( + ent_text not in redacted_text + ), f"Expected entity '{ent_text}' to be redacted but found in: {redacted_text}" + assert ( + "*" in redacted_text + ), f"Expected redacted text to contain '*', got: {redacted_text}" + redacted_verified.append(redacted_text) + + # Assertions assert (d.get("status") or "").lower() in {"succeeded", "partiallysucceeded"} assert len(redacted_verified) > 0, "Expected at least one redacted line to be verified." diff --git a/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii_with_entity_mask_policy.py b/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii_with_entity_mask_policy.py index 8701b58687da..1aee05eb4e21 100644 --- a/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii_with_entity_mask_policy.py +++ b/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii_with_entity_mask_policy.py @@ -1,6 +1,7 @@ # pylint: disable=line-too-long,useless-suppression import functools from typing import cast, List +import re from devtools_testutils import AzureRecordedTestCase, EnvironmentVariableLoader, recorded_by_proxy from azure.ai.language.conversations import ConversationAnalysisClient, AnalyzeConversationLROPoller @@ -9,6 +10,7 @@ # request models AnalyzeConversationOperationInput, MultiLanguageConversationInput, + NamedEntity, TextConversation, TextConversationItem, PiiOperationAction, @@ -20,7 +22,7 @@ ConversationPiiItemResult, ConversationError, AnalyzeConversationOperationAction, - EntityMaskTypePolicyType, + EntityMaskTypePolicyType, ) from azure.core.credentials import AzureKeyCredential @@ -122,6 +124,24 @@ def test_conversation_pii_with_entity_mask_policy(self, conversations_endpoint, item = cast(ConversationPiiItemResult, item) redacted_text = (getattr(item.redacted_content, "text", None) or "").strip() print(f"Redacted Text: {redacted_text}") + # Only verify when there are detected entities in the original item + if item.entities and redacted_text: + for entity in item.entities: + entity = cast(NamedEntity, entity) + original_text = entity.text or "" + # 1) original PII should not be present + assert ( + original_text not in redacted_text + ), f"Expected entity '{original_text}' to be redacted but found in: {redacted_text}" + + # 2) redaction should show an entity mask like [Person] or [Person-1] + expected_mask_pattern = rf"\[{re.escape(entity.category)}-?\d*\]" + assert re.search(expected_mask_pattern, redacted_text, flags=re.IGNORECASE), ( + f"Expected redacted text to contain an entity mask similar to " + f"'[{entity.category}]' but got: {redacted_text}" + ) + + redacted_verified.append(redacted_text) # ---- Assertions ------------------------------------------------------- assert (d.get("status") or "").lower() in {"succeeded", "partiallysucceeded"} diff --git a/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii_with_no_mask_policy.py b/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii_with_no_mask_policy.py index c7b6112d65cc..3d980783e239 100644 --- a/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii_with_no_mask_policy.py +++ b/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii_with_no_mask_policy.py @@ -9,6 +9,7 @@ # request models AnalyzeConversationOperationInput, MultiLanguageConversationInput, + NamedEntity, TextConversation, TextConversationItem, PiiOperationAction, @@ -114,7 +115,18 @@ def test_conversation_pii_with_no_mask_policy(self, conversations_endpoint, conv for conversation in ar.results.conversations or []: conversation = cast(ConversationalPiiResult, conversation) for item in conversation.conversation_items or []: - assert isinstance(item, ConversationPiiItemResult) + item = cast(ConversationPiiItemResult, item) + # With NoMask, service returns original text in redacted_content + returned_text = (getattr(item.redacted_content, "text", None) or "").strip() + if item.entities and returned_text: + for entity in item.entities: + entity = cast(NamedEntity, entity) + ent_text = entity.text or "" + detected_entities.append(ent_text) + # Ensure the original PII text is still present + assert ( + ent_text in returned_text + ), f"Expected entity '{ent_text}' to be present but was not found in: {returned_text}" # ---- Assertions ------------------------ assert len(detected_entities) > 0, "Expected at least one detected PII entity." From 04f5e566b40269c172673c819574ee3362b491a6 Mon Sep 17 00:00:00 2001 From: "Amber Chen (Centific Technologies Inc)" Date: Tue, 27 Jan 2026 10:11:58 -0800 Subject: [PATCH 08/10] update --- .../tests/test_conversation_pii.py | 2 +- .../tests/test_conversation_pii_async.py | 2 +- .../tests/test_conversation_pii_with_entity_mask_policy.py | 4 ++-- .../tests/test_conversation_pii_with_no_mask_policy.py | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii.py b/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii.py index f122b8ed973f..d0b2a644a881 100644 --- a/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii.py +++ b/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii.py @@ -47,7 +47,7 @@ def create_client(self, endpoint, key): class TestConversationsCase(TestConversations): @ConversationsPreparer() @recorded_by_proxy - def test_conversation_pii(self, conversations_endpoint, conversations_key): + def test_conversation_pii(self, conversations_endpoint, conversations_key): # pylint: disable=too-many-statements client = self.create_client(conversations_endpoint, conversations_key) entities_detected: List[NamedEntity] = [] diff --git a/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii_async.py b/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii_async.py index 3de04b678fa0..2fc58aa4778f 100644 --- a/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii_async.py +++ b/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii_async.py @@ -49,7 +49,7 @@ class TestConversationsCase(TestConversations): @ConversationsPreparer() @recorded_by_proxy_async @pytest.mark.asyncio - async def test_conversation_pii_async(self, conversations_endpoint, conversations_key): + async def test_conversation_pii_async(self, conversations_endpoint, conversations_key): # pylint: disable=too-many-statements client = await self.create_client(conversations_endpoint, conversations_key) try: diff --git a/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii_with_entity_mask_policy.py b/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii_with_entity_mask_policy.py index 1aee05eb4e21..f309e8c96f1f 100644 --- a/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii_with_entity_mask_policy.py +++ b/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii_with_entity_mask_policy.py @@ -22,7 +22,7 @@ ConversationPiiItemResult, ConversationError, AnalyzeConversationOperationAction, - EntityMaskTypePolicyType, + EntityMaskTypePolicyType, ) from azure.core.credentials import AzureKeyCredential @@ -110,7 +110,7 @@ def test_conversation_pii_with_entity_mask_policy(self, conversations_endpoint, print(f" Code: {err.code} - {err.message}") # ---- Iterate results and validate redaction -------------------------- - for actions_page in paged_actions: + for actions_page in paged_actions: # pylint: disable=too-many-nested-blocks for action_result in actions_page.task_results or []: ar = cast(AnalyzeConversationOperationResult, action_result) print(f"\nAction Name: {getattr(ar, 'name', None)}") diff --git a/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii_with_no_mask_policy.py b/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii_with_no_mask_policy.py index 3d980783e239..b5fb0464d0b0 100644 --- a/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii_with_no_mask_policy.py +++ b/sdk/cognitivelanguage/azure-ai-language-conversations/tests/test_conversation_pii_with_no_mask_policy.py @@ -108,7 +108,7 @@ def test_conversation_pii_with_no_mask_policy(self, conversations_endpoint, conv print(f" Code: {err.code} - {err.message}") # ---- Iterate results and validate: PII present in returned text ------- - for actions_page in paged_actions: + for actions_page in paged_actions: # pylint: disable=too-many-nested-blocks for action_result in actions_page.task_results or []: ar = cast(AnalyzeConversationOperationResult, action_result) if isinstance(ar, ConversationPiiOperationResult): From 681e0715acf1f0eff4c2db27f0692cf7d8401b3e Mon Sep 17 00:00:00 2001 From: "Amber Chen (Centific Technologies Inc)" Date: Tue, 27 Jan 2026 16:18:04 -0800 Subject: [PATCH 09/10] update snippets --- sdk/cognitivelanguage/azure-ai-language-conversations/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/cognitivelanguage/azure-ai-language-conversations/README.md b/sdk/cognitivelanguage/azure-ai-language-conversations/README.md index f26509543b01..d71c0046fb19 100644 --- a/sdk/cognitivelanguage/azure-ai-language-conversations/README.md +++ b/sdk/cognitivelanguage/azure-ai-language-conversations/README.md @@ -357,7 +357,7 @@ def sample_conversation_summarization(): print(f"Display Name: {d.get('display_name')}") # Iterate results - for actions_page in paged_actions: + for actions_page in paged_actions: # pylint: disable=too-many-nested-blocks print( f"Completed: {actions_page.completed}, " f"In Progress: {actions_page.in_progress}, " From 08294c4f6a43da923edae8a1b9af0ef012ee71db Mon Sep 17 00:00:00 2001 From: "Amber Chen (Centific Technologies Inc)" Date: Mon, 2 Feb 2026 10:37:23 -0800 Subject: [PATCH 10/10] updated. --- .../azure-ai-language-conversations/dev_requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/cognitivelanguage/azure-ai-language-conversations/dev_requirements.txt b/sdk/cognitivelanguage/azure-ai-language-conversations/dev_requirements.txt index f5df333868ec..396f26f367a1 100644 --- a/sdk/cognitivelanguage/azure-ai-language-conversations/dev_requirements.txt +++ b/sdk/cognitivelanguage/azure-ai-language-conversations/dev_requirements.txt @@ -1,4 +1,4 @@ -e ../../../eng/tools/azure-sdk-tools ../../core/azure-core aiohttp -azure-identity \ No newline at end of file +../../identity/azure-identity \ No newline at end of file