From bc783380cc293356dfe48c4ad564f176d0d2bc6d Mon Sep 17 00:00:00 2001 From: Krista Pratico Date: Mon, 14 Jun 2021 11:47:27 -0700 Subject: [PATCH 1/3] work in progress --- .../azure/ai/textanalytics/_models.py | 25 +++++---- .../ai/textanalytics/_request_handlers.py | 13 ++++- .../ai/textanalytics/_response_handlers.py | 51 ++++++++----------- .../textanalytics/_text_analytics_client.py | 23 ++++----- .../tests/test_analyze.py | 20 ++++++++ 5 files changed, 78 insertions(+), 54 deletions(-) diff --git a/sdk/textanalytics/azure-ai-textanalytics/azure/ai/textanalytics/_models.py b/sdk/textanalytics/azure-ai-textanalytics/azure/ai/textanalytics/_models.py index d2bfdd7dc4cc..d055e6b10ed0 100644 --- a/sdk/textanalytics/azure-ai-textanalytics/azure/ai/textanalytics/_models.py +++ b/sdk/textanalytics/azure-ai-textanalytics/azure/ai/textanalytics/_models.py @@ -1465,13 +1465,14 @@ def __repr__(self, **kwargs): return "RecognizeEntitiesAction(model_version={}, string_index_type={}, disable_service_logs={})" \ .format(self.model_version, self.string_index_type, self.disable_service_logs)[:1024] - def to_generated(self): + def to_generated(self, task_id): return _latest_preview_models.EntitiesTask( parameters=_latest_preview_models.EntitiesTaskParameters( model_version=self.model_version, string_index_type=self.string_index_type, logging_opt_out=self.disable_service_logs, - ) + ), + task_name=task_id ) @@ -1536,14 +1537,15 @@ def __repr__(self, **kwargs): self.disable_service_logs, )[:1024] - def to_generated(self): + def to_generated(self, task_id): return _latest_preview_models.SentimentAnalysisTask( parameters=_latest_preview_models.SentimentAnalysisTaskParameters( model_version=self.model_version, opinion_mining=self.show_opinion_mining, string_index_type=self.string_index_type, logging_opt_out=self.disable_service_logs, - ) + ), + task_name=task_id ) @@ -1602,14 +1604,15 @@ def __repr__(self, **kwargs): self.disable_service_logs, )[:1024] - def to_generated(self): + def to_generated(self, task_id): return _latest_preview_models.PiiTask( parameters=_latest_preview_models.PiiTaskParameters( model_version=self.model_version, domain=self.domain_filter, string_index_type=self.string_index_type, logging_opt_out=self.disable_service_logs - ) + ), + task_name=task_id ) @@ -1649,12 +1652,13 @@ def __repr__(self, **kwargs): return "ExtractKeyPhrasesAction(model_version={}, disable_service_logs={})" \ .format(self.model_version, self.disable_service_logs)[:1024] - def to_generated(self): + def to_generated(self, task_id): return _latest_preview_models.KeyPhrasesTask( parameters=_latest_preview_models.KeyPhrasesTaskParameters( model_version=self.model_version, logging_opt_out=self.disable_service_logs, - ) + ), + task_name=task_id ) @@ -1705,11 +1709,12 @@ def __repr__(self, **kwargs): self.model_version, self.string_index_type, self.disable_service_logs )[:1024] - def to_generated(self): + def to_generated(self, task_id): return _latest_preview_models.EntityLinkingTask( parameters=_latest_preview_models.EntityLinkingTaskParameters( model_version=self.model_version, string_index_type=self.string_index_type, logging_opt_out=self.disable_service_logs, - ) + ), + task_name=task_id ) diff --git a/sdk/textanalytics/azure-ai-textanalytics/azure/ai/textanalytics/_request_handlers.py b/sdk/textanalytics/azure-ai-textanalytics/azure/ai/textanalytics/_request_handlers.py index 25352abd4ac9..8ce2f364fe9b 100644 --- a/sdk/textanalytics/azure-ai-textanalytics/azure/ai/textanalytics/_request_handlers.py +++ b/sdk/textanalytics/azure-ai-textanalytics/azure/ai/textanalytics/_request_handlers.py @@ -6,7 +6,7 @@ import six - +from ._generated.models import EntitiesTask, PiiTask, EntityLinkingTask, SentimentAnalysisTask from ._models import ( DetectLanguageInput, TextDocumentInput, @@ -80,6 +80,17 @@ def _determine_action_type(action): return AnalyzeActionsType.ANALYZE_SENTIMENT return AnalyzeActionsType.EXTRACT_KEY_PHRASES +def _determine_task_type(action): + if isinstance(action, EntitiesTask): + return AnalyzeActionsType.RECOGNIZE_ENTITIES + if isinstance(action, PiiTask): + return AnalyzeActionsType.RECOGNIZE_PII_ENTITIES + if isinstance(action, EntityLinkingTask): + return AnalyzeActionsType.RECOGNIZE_LINKED_ENTITIES + if isinstance(action, SentimentAnalysisTask): + return AnalyzeActionsType.ANALYZE_SENTIMENT + return AnalyzeActionsType.EXTRACT_KEY_PHRASES + def _check_string_index_type_arg(string_index_type_arg, api_version, string_index_type_default="UnicodeCodePoint"): string_index_type = None diff --git a/sdk/textanalytics/azure-ai-textanalytics/azure/ai/textanalytics/_response_handlers.py b/sdk/textanalytics/azure-ai-textanalytics/azure/ai/textanalytics/_response_handlers.py index 9af6d2a069ca..3747a6f5bc56 100644 --- a/sdk/textanalytics/azure-ai-textanalytics/azure/ai/textanalytics/_response_handlers.py +++ b/sdk/textanalytics/azure-ai-textanalytics/azure/ai/textanalytics/_response_handlers.py @@ -252,42 +252,35 @@ def _get_mapped_errors(analyze_job_state): def _get_error_index(error): return _get_indices(error.target)[-1] -def _get_good_result(current_task_type, index_of_task_result, doc_id_order, response_headers, returned_tasks_object): - deserialization_callback = _get_deserialization_callback_from_task_type(current_task_type) +def _get_good_result(task, doc_id_order, response_headers, returned_tasks_object): + current_task_type, task_name = task[0], task[1] property_name = _get_property_name_from_task_type(current_task_type) - response_task_to_deserialize = getattr(returned_tasks_object, property_name)[index_of_task_result] - document_results = deserialization_callback( + response_task_to_deserialize = [task for task in getattr(returned_tasks_object, property_name) if task.task_name == task_name][0] + return deserialization_callback( doc_id_order, response_task_to_deserialize.results, response_headers, lro=True ) - return AnalyzeActionsResult( - document_results=document_results, - action_type=current_task_type, - completed_on=response_task_to_deserialize.last_update_date_time, - ) def get_iter_items(doc_id_order, task_order, response_headers, analyze_job_state): - iter_items = [] - task_type_to_index = defaultdict(int) # need to keep track of how many of each type of tasks we've seen + iter_items = defaultdict(list) # map doc id to action results + # task_type_to_index = defaultdict(int) # need to keep track of how many of each type of tasks we've seen returned_tasks_object = analyze_job_state.tasks - mapped_errors = _get_mapped_errors(analyze_job_state) - for current_task_type in task_order: - index_of_task_result = task_type_to_index[current_task_type] - try: - # try to deserailize as error. If fails, we know it's good - # kind of a weird way to order things, but we can fail when deserializing - # the curr response as an error, not when deserializing as a good response. - - current_task_type_errors = mapped_errors[current_task_type] - error = next(err for err in current_task_type_errors if err[0] == index_of_task_result) - result = AnalyzeActionsError._from_generated(error[1]) # pylint: disable=protected-access - except StopIteration: - result = _get_good_result( - current_task_type, index_of_task_result, doc_id_order, response_headers, returned_tasks_object - ) - iter_items.append(result) - task_type_to_index[current_task_type] += 1 - return iter_items + for task in task_order: + # index_of_task_result = task_type_to_index[current_task_type] + results = _get_good_result( + task, + doc_id_order, + response_headers, + returned_tasks_object, + ) + for result in results: + iter_items[result.id].append(result) + # task_type_to_index[current_task_type] += 1 + return [ + iter_items[doc_id] + for doc_id in doc_id_order + if doc_id in iter_items + ] def analyze_extract_page_data(doc_id_order, task_order, response_headers, analyze_job_state): # return next link, list of diff --git a/sdk/textanalytics/azure-ai-textanalytics/azure/ai/textanalytics/_text_analytics_client.py b/sdk/textanalytics/azure-ai-textanalytics/azure/ai/textanalytics/_text_analytics_client.py index 8c46e594bffb..69b3820d5449 100644 --- a/sdk/textanalytics/azure-ai-textanalytics/azure/ai/textanalytics/_text_analytics_client.py +++ b/sdk/textanalytics/azure-ai-textanalytics/azure/ai/textanalytics/_text_analytics_client.py @@ -19,6 +19,7 @@ from ._request_handlers import ( _validate_input, _determine_action_type, + _determine_task_type, _check_string_index_type_arg ) from ._response_handlers import ( @@ -882,32 +883,26 @@ def begin_analyze_actions( # type: ignore continuation_token = kwargs.pop("continuation_token", None) doc_id_order = [doc.get("id") for doc in docs.documents] - task_order = [_determine_action_type(action) for action in actions] + generated_tasks = [action.to_generated(str(idx)) for idx, action in enumerate(actions)] + task_order = [(_determine_task_type(a), a.task_name) for a in generated_tasks] try: analyze_tasks = self._client.models(api_version='v3.1').JobManifestTasks( entity_recognition_tasks=[ - t.to_generated() for t in - [a for a in actions if _determine_action_type(a) == AnalyzeActionsType.RECOGNIZE_ENTITIES] + a for a in generated_tasks if _determine_task_type(a) == AnalyzeActionsType.RECOGNIZE_ENTITIES ], entity_recognition_pii_tasks=[ - t.to_generated() for t in - [a for a in actions if _determine_action_type(a) == AnalyzeActionsType.RECOGNIZE_PII_ENTITIES] + a for a in generated_tasks if _determine_task_type(a) == AnalyzeActionsType.RECOGNIZE_PII_ENTITIES ], key_phrase_extraction_tasks=[ - t.to_generated() for t in - [a for a in actions if _determine_action_type(a) == AnalyzeActionsType.EXTRACT_KEY_PHRASES] + a for a in generated_tasks if _determine_task_type(a) == AnalyzeActionsType.EXTRACT_KEY_PHRASES ], entity_linking_tasks=[ - t.to_generated() for t in - [ - a for a in actions - if _determine_action_type(a) == AnalyzeActionsType.RECOGNIZE_LINKED_ENTITIES - ] + a for a in generated_tasks + if _determine_task_type(a) == AnalyzeActionsType.RECOGNIZE_LINKED_ENTITIES ], sentiment_analysis_tasks=[ - t.to_generated() for t in - [a for a in actions if _determine_action_type(a) == AnalyzeActionsType.ANALYZE_SENTIMENT] + a for a in generated_tasks if _determine_task_type(a) == AnalyzeActionsType.ANALYZE_SENTIMENT ] ) analyze_body = self._client.models(api_version='v3.1').AnalyzeBatchInput( diff --git a/sdk/textanalytics/azure-ai-textanalytics/tests/test_analyze.py b/sdk/textanalytics/azure-ai-textanalytics/tests/test_analyze.py index 96e7419257fc..3424a425f733 100644 --- a/sdk/textanalytics/azure-ai-textanalytics/tests/test_analyze.py +++ b/sdk/textanalytics/azure-ai-textanalytics/tests/test_analyze.py @@ -698,3 +698,23 @@ def callback(resp): polling_interval=self._interval(), raw_response_hook=callback, ).result() + + + @GlobalTextAnalyticsAccountPreparer() + @TextAnalyticsClientPreparer() + def test_partial(self, client): # TODO: verify behavior of service + docs = [{"id": "1", "language": "tr", "text": "I did not like the hotel we stayed at."},{"id": "2", "language": "en", "text": "I did not like the hotel we stayed at."}] + + + response = client.begin_analyze_actions( + docs, + actions=[ + AnalyzeSentimentAction(), + RecognizePiiEntitiesAction(), + # RecognizePiiEntitiesAction(domain_filter="phi"), + ], + polling_interval=self._interval(), + ).result() + + action_results = list(response) + print(action_results) From a97fa79032c4bcf4ab5f03f5a4874b926efdf49b Mon Sep 17 00:00:00 2001 From: Krista Pratico Date: Mon, 14 Jun 2021 13:50:39 -0700 Subject: [PATCH 2/3] fixes, add impl to async, add test --- .../ai/textanalytics/_request_handlers.py | 10 +-- .../ai/textanalytics/_response_handlers.py | 8 +- .../aio/_text_analytics_client_async.py | 28 +++--- .../tests/test_analyze.py | 71 +++++++++++++-- .../tests/test_analyze_async.py | 89 +++++++++++++++++++ 5 files changed, 174 insertions(+), 32 deletions(-) diff --git a/sdk/textanalytics/azure-ai-textanalytics/azure/ai/textanalytics/_request_handlers.py b/sdk/textanalytics/azure-ai-textanalytics/azure/ai/textanalytics/_request_handlers.py index b4e369819cbb..b02a3da824ac 100644 --- a/sdk/textanalytics/azure-ai-textanalytics/azure/ai/textanalytics/_request_handlers.py +++ b/sdk/textanalytics/azure-ai-textanalytics/azure/ai/textanalytics/_request_handlers.py @@ -82,14 +82,14 @@ def _determine_action_type(action): def _determine_task_type(action): if isinstance(action, EntitiesTask): - return AnalyzeActionsType.RECOGNIZE_ENTITIES + return _AnalyzeActionsType.RECOGNIZE_ENTITIES if isinstance(action, PiiTask): - return AnalyzeActionsType.RECOGNIZE_PII_ENTITIES + return _AnalyzeActionsType.RECOGNIZE_PII_ENTITIES if isinstance(action, EntityLinkingTask): - return AnalyzeActionsType.RECOGNIZE_LINKED_ENTITIES + return _AnalyzeActionsType.RECOGNIZE_LINKED_ENTITIES if isinstance(action, SentimentAnalysisTask): - return AnalyzeActionsType.ANALYZE_SENTIMENT - return AnalyzeActionsType.EXTRACT_KEY_PHRASES + return _AnalyzeActionsType.ANALYZE_SENTIMENT + return _AnalyzeActionsType.EXTRACT_KEY_PHRASES def _check_string_index_type_arg(string_index_type_arg, api_version, string_index_type_default="UnicodeCodePoint"): string_index_type = None diff --git a/sdk/textanalytics/azure-ai-textanalytics/azure/ai/textanalytics/_response_handlers.py b/sdk/textanalytics/azure-ai-textanalytics/azure/ai/textanalytics/_response_handlers.py index 33529a8946d3..d6d6c5ddbc12 100644 --- a/sdk/textanalytics/azure-ai-textanalytics/azure/ai/textanalytics/_response_handlers.py +++ b/sdk/textanalytics/azure-ai-textanalytics/azure/ai/textanalytics/_response_handlers.py @@ -201,21 +201,20 @@ def _get_property_name_from_task_type(task_type): return "key_phrase_extraction_tasks" def _get_good_result(task, doc_id_order, response_headers, returned_tasks_object): - current_task_type, task_name = task[0], task[1] + current_task_type, task_name = task deserialization_callback = _get_deserialization_callback_from_task_type(current_task_type) property_name = _get_property_name_from_task_type(current_task_type) - response_task_to_deserialize = [task for task in getattr(returned_tasks_object, property_name) if task.task_name == task_name][0] + response_task_to_deserialize = \ + [task for task in getattr(returned_tasks_object, property_name) if task.task_name == task_name][0] return deserialization_callback( doc_id_order, response_task_to_deserialize.results, response_headers, lro=True ) def get_iter_items(doc_id_order, task_order, response_headers, analyze_job_state): iter_items = defaultdict(list) # map doc id to action results - # task_type_to_index = defaultdict(int) # need to keep track of how many of each type of tasks we've seen returned_tasks_object = analyze_job_state.tasks for task in task_order: - # index_of_task_result = task_type_to_index[current_task_type] results = _get_good_result( task, doc_id_order, @@ -224,7 +223,6 @@ def get_iter_items(doc_id_order, task_order, response_headers, analyze_job_state ) for result in results: iter_items[result.id].append(result) - # task_type_to_index[current_task_type] += 1 return [ iter_items[doc_id] for doc_id in doc_id_order diff --git a/sdk/textanalytics/azure-ai-textanalytics/azure/ai/textanalytics/aio/_text_analytics_client_async.py b/sdk/textanalytics/azure-ai-textanalytics/azure/ai/textanalytics/aio/_text_analytics_client_async.py index d3dbdfdc81c0..8b29023939f5 100644 --- a/sdk/textanalytics/azure-ai-textanalytics/azure/ai/textanalytics/aio/_text_analytics_client_async.py +++ b/sdk/textanalytics/azure-ai-textanalytics/azure/ai/textanalytics/aio/_text_analytics_client_async.py @@ -17,7 +17,7 @@ from azure.core.exceptions import HttpResponseError from azure.core.credentials import AzureKeyCredential from ._base_client_async import AsyncTextAnalyticsClientBase -from .._request_handlers import _validate_input, _determine_action_type, _check_string_index_type_arg +from .._request_handlers import _validate_input, _determine_task_type, _check_string_index_type_arg from .._response_handlers import ( process_http_response_error, entities_result, @@ -838,7 +838,7 @@ async def begin_analyze_actions( # type: ignore :keyword bool show_stats: If set to true, response will contain document level statistics. :keyword int polling_interval: Waiting time between two polls for LRO operations if no Retry-After header is present. Defaults to 30 seconds. - :return: An instance of an LROPoller. Call `result()` on the poller + :return: An instance of an AsyncAnalyzeActionsLROPoller. Call `result()` on the poller object to return a pageable heterogeneous list of lists. This list of lists is first ordered by the documents you input, then ordered by the actions you input. For example, if you have documents input ["Hello", "world"], and actions @@ -850,7 +850,7 @@ async def begin_analyze_actions( # type: ignore Then, you will get the :class:`~azure.ai.textanalytics.RecognizeEntitiesResult` and :class:`~azure.ai.textanalytics.AnalyzeSentimentResult` of "world". :rtype: - ~azure.core.polling.AsyncLROPoller[~azure.core.async_paging.AsyncItemPaged[ + ~azure.core.polling.AsyncAnalyzeActionsLROPoller[~azure.core.async_paging.AsyncItemPaged[ list[ RecognizeEntitiesResult or RecognizeLinkedEntitiesResult or RecognizePiiEntitiesResult or ExtractKeyPhrasesResult or AnalyzeSentimentResult @@ -879,32 +879,26 @@ async def begin_analyze_actions( # type: ignore continuation_token = kwargs.pop("continuation_token", None) doc_id_order = [doc.get("id") for doc in docs.documents] - task_order = [_determine_action_type(action) for action in actions] + generated_tasks = [action.to_generated(str(idx)) for idx, action in enumerate(actions)] + task_order = [(_determine_task_type(a), a.task_name) for a in generated_tasks] try: analyze_tasks = self._client.models(api_version='v3.1').JobManifestTasks( entity_recognition_tasks=[ - t.to_generated() for t in - [a for a in actions if _determine_action_type(a) == _AnalyzeActionsType.RECOGNIZE_ENTITIES] + a for a in generated_tasks if _determine_task_type(a) == _AnalyzeActionsType.RECOGNIZE_ENTITIES ], entity_recognition_pii_tasks=[ - t.to_generated() for t in - [a for a in actions if _determine_action_type(a) == _AnalyzeActionsType.RECOGNIZE_PII_ENTITIES] + a for a in generated_tasks if _determine_task_type(a) == _AnalyzeActionsType.RECOGNIZE_PII_ENTITIES ], key_phrase_extraction_tasks=[ - t.to_generated() for t in - [a for a in actions if _determine_action_type(a) == _AnalyzeActionsType.EXTRACT_KEY_PHRASES] + a for a in generated_tasks if _determine_task_type(a) == _AnalyzeActionsType.EXTRACT_KEY_PHRASES ], entity_linking_tasks=[ - t.to_generated() for t in - [ - a for a in actions if \ - _determine_action_type(a) == _AnalyzeActionsType.RECOGNIZE_LINKED_ENTITIES - ] + a for a in generated_tasks + if _determine_task_type(a) == _AnalyzeActionsType.RECOGNIZE_LINKED_ENTITIES ], sentiment_analysis_tasks=[ - t.to_generated() for t in - [a for a in actions if _determine_action_type(a) == _AnalyzeActionsType.ANALYZE_SENTIMENT] + a for a in generated_tasks if _determine_task_type(a) == _AnalyzeActionsType.ANALYZE_SENTIMENT ] ) analyze_body = self._client.models(api_version='v3.1').AnalyzeBatchInput( diff --git a/sdk/textanalytics/azure-ai-textanalytics/tests/test_analyze.py b/sdk/textanalytics/azure-ai-textanalytics/tests/test_analyze.py index 0930e94355bc..5b10a74ea7f0 100644 --- a/sdk/textanalytics/azure-ai-textanalytics/tests/test_analyze.py +++ b/sdk/textanalytics/azure-ai-textanalytics/tests/test_analyze.py @@ -680,22 +680,83 @@ def callback(resp): raw_response_hook=callback, ).result() - @GlobalTextAnalyticsAccountPreparer() @TextAnalyticsClientPreparer() - def test_partial(self, client): # TODO: verify behavior of service - docs = [{"id": "1", "language": "tr", "text": "I did not like the hotel we stayed at."},{"id": "2", "language": "en", "text": "I did not like the hotel we stayed at."}] + def test_partial_success_for_actions(self, client): + docs = [{"id": "1", "language": "tr", "text": "I did not like the hotel we stayed at."}, + {"id": "2", "language": "en", "text": "I did not like the hotel we stayed at."}] + response = client.begin_analyze_actions( + docs, + actions=[ + AnalyzeSentimentAction(), + RecognizePiiEntitiesAction(), + ], + polling_interval=self._interval(), + ).result() + + action_results = list(response) + assert len(action_results) == len(docs) + action_order = [ + _AnalyzeActionsType.ANALYZE_SENTIMENT, + _AnalyzeActionsType.RECOGNIZE_PII_ENTITIES, + ] + + assert len(action_results[0]) == len(action_order) + assert len(action_results[1]) == len(action_order) + + # first doc + assert isinstance(action_results[0][0], AnalyzeSentimentResult) + assert action_results[0][0].id == "1" + assert action_results[0][1].is_error + assert action_results[0][1].id == "1" + + # second doc + assert isinstance(action_results[1][0], AnalyzeSentimentResult) + assert action_results[1][0].id == "2" + assert isinstance(action_results[1][1], RecognizePiiEntitiesResult) + assert action_results[1][1].id == "2" + + @pytest.skip("Service bug - https://msazure.visualstudio.com/Cognitive%20Services/_workitems/edit/10145316") + @GlobalTextAnalyticsAccountPreparer() + @TextAnalyticsClientPreparer() + def test_multiple_of_same_action(self, client): + docs = [{"id": "1", "text": "My SSN is 859-98-0987."}, + {"id": "2", "text": "Is 998.214.865-68 your Brazilian CPF number?"}] response = client.begin_analyze_actions( docs, actions=[ AnalyzeSentimentAction(), RecognizePiiEntitiesAction(), - # RecognizePiiEntitiesAction(domain_filter="phi"), + RecognizePiiEntitiesAction(domain_filter="phi"), ], polling_interval=self._interval(), ).result() action_results = list(response) - print(action_results) + assert len(action_results) == len(docs) + action_order = [ + _AnalyzeActionsType.ANALYZE_SENTIMENT, + _AnalyzeActionsType.RECOGNIZE_PII_ENTITIES, + _AnalyzeActionsType.RECOGNIZE_PII_ENTITIES, + ] + + assert len(action_results[0]) == len(action_order) + assert len(action_results[1]) == len(action_order) + + # first doc + assert isinstance(action_results[0][0], AnalyzeSentimentResult) + assert action_results[0][0].id == "1" + assert isinstance(action_results[0][1], RecognizePiiEntitiesResult) + assert action_results[0][1].id == "1" + assert isinstance(action_results[0][2], RecognizePiiEntitiesResult) + assert action_results[0][2].id == "1" + + # second doc + assert isinstance(action_results[1][0], AnalyzeSentimentResult) + assert action_results[1][0].id == "2" + assert isinstance(action_results[1][1], RecognizePiiEntitiesResult) + assert action_results[1][1].id == "2" + assert isinstance(action_results[1][2], RecognizePiiEntitiesResult) + assert action_results[1][2].id == "2" diff --git a/sdk/textanalytics/azure-ai-textanalytics/tests/test_analyze_async.py b/sdk/textanalytics/azure-ai-textanalytics/tests/test_analyze_async.py index dea8e8e93ca2..4983270de097 100644 --- a/sdk/textanalytics/azure-ai-textanalytics/tests/test_analyze_async.py +++ b/sdk/textanalytics/azure-ai-textanalytics/tests/test_analyze_async.py @@ -737,3 +737,92 @@ async def test_disable_service_logs(self, client): actions=actions, polling_interval=self._interval(), )).result() + + @GlobalTextAnalyticsAccountPreparer() + @TextAnalyticsClientPreparer() + async def test_partial_success_for_actions(self, client): + docs = [{"id": "1", "language": "tr", "text": "I did not like the hotel we stayed at."}, + {"id": "2", "language": "en", "text": "I did not like the hotel we stayed at."}] + + async with client: + response = await (await client.begin_analyze_actions( + docs, + actions=[ + AnalyzeSentimentAction(), + RecognizePiiEntitiesAction(), + ], + polling_interval=self._interval(), + )).result() + + action_results = [] + async for p in response: + action_results.append(p) + + assert len(action_results) == len(docs) + action_order = [ + _AnalyzeActionsType.ANALYZE_SENTIMENT, + _AnalyzeActionsType.RECOGNIZE_PII_ENTITIES, + ] + + assert len(action_results[0]) == len(action_order) + assert len(action_results[1]) == len(action_order) + + # first doc + assert isinstance(action_results[0][0], AnalyzeSentimentResult) + assert action_results[0][0].id == "1" + assert action_results[0][1].is_error + assert action_results[0][1].id == "1" + + # second doc + assert isinstance(action_results[1][0], AnalyzeSentimentResult) + assert action_results[1][0].id == "2" + assert isinstance(action_results[1][1], RecognizePiiEntitiesResult) + assert action_results[1][1].id == "2" + + @pytest.skip("Service bug - https://msazure.visualstudio.com/Cognitive%20Services/_workitems/edit/10145316") + @GlobalTextAnalyticsAccountPreparer() + @TextAnalyticsClientPreparer() + async def test_multiple_of_same_action(self, client): + docs = [{"id": "1", "text": "My SSN is 859-98-0987."}, + {"id": "2", "text": "Is 998.214.865-68 your Brazilian CPF number?"}] + + async with client: + response = await (await client.begin_analyze_actions( + docs, + actions=[ + AnalyzeSentimentAction(), + RecognizePiiEntitiesAction(), + RecognizePiiEntitiesAction(domain_filter="phi"), + ], + polling_interval=self._interval(), + )).result() + + action_results = [] + async for p in response: + action_results.append(p) + + assert len(action_results) == len(docs) + action_order = [ + _AnalyzeActionsType.ANALYZE_SENTIMENT, + _AnalyzeActionsType.RECOGNIZE_PII_ENTITIES, + _AnalyzeActionsType.RECOGNIZE_PII_ENTITIES, + ] + + assert len(action_results[0]) == len(action_order) + assert len(action_results[1]) == len(action_order) + + # first doc + assert isinstance(action_results[0][0], AnalyzeSentimentResult) + assert action_results[0][0].id == "1" + assert isinstance(action_results[0][1], RecognizePiiEntitiesResult) + assert action_results[0][1].id == "1" + assert isinstance(action_results[0][2], RecognizePiiEntitiesResult) + assert action_results[0][2].id == "1" + + # second doc + assert isinstance(action_results[1][0], AnalyzeSentimentResult) + assert action_results[1][0].id == "2" + assert isinstance(action_results[1][1], RecognizePiiEntitiesResult) + assert action_results[1][1].id == "2" + assert isinstance(action_results[1][2], RecognizePiiEntitiesResult) + assert action_results[1][2].id == "2" From 08a0075c88331ffc9d467378d0be4a858298e7e8 Mon Sep 17 00:00:00 2001 From: Krista Pratico Date: Mon, 14 Jun 2021 15:33:23 -0700 Subject: [PATCH 3/3] fix pytest skip --- sdk/textanalytics/azure-ai-textanalytics/tests/test_analyze.py | 2 +- .../azure-ai-textanalytics/tests/test_analyze_async.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sdk/textanalytics/azure-ai-textanalytics/tests/test_analyze.py b/sdk/textanalytics/azure-ai-textanalytics/tests/test_analyze.py index 5b10a74ea7f0..11a16a934b27 100644 --- a/sdk/textanalytics/azure-ai-textanalytics/tests/test_analyze.py +++ b/sdk/textanalytics/azure-ai-textanalytics/tests/test_analyze.py @@ -717,7 +717,7 @@ def test_partial_success_for_actions(self, client): assert isinstance(action_results[1][1], RecognizePiiEntitiesResult) assert action_results[1][1].id == "2" - @pytest.skip("Service bug - https://msazure.visualstudio.com/Cognitive%20Services/_workitems/edit/10145316") + @pytest.mark.skip("Service bug - https://msazure.visualstudio.com/Cognitive%20Services/_workitems/edit/10145316") @GlobalTextAnalyticsAccountPreparer() @TextAnalyticsClientPreparer() def test_multiple_of_same_action(self, client): diff --git a/sdk/textanalytics/azure-ai-textanalytics/tests/test_analyze_async.py b/sdk/textanalytics/azure-ai-textanalytics/tests/test_analyze_async.py index 4983270de097..c62140eed63d 100644 --- a/sdk/textanalytics/azure-ai-textanalytics/tests/test_analyze_async.py +++ b/sdk/textanalytics/azure-ai-textanalytics/tests/test_analyze_async.py @@ -779,7 +779,7 @@ async def test_partial_success_for_actions(self, client): assert isinstance(action_results[1][1], RecognizePiiEntitiesResult) assert action_results[1][1].id == "2" - @pytest.skip("Service bug - https://msazure.visualstudio.com/Cognitive%20Services/_workitems/edit/10145316") + @pytest.mark.skip("Service bug - https://msazure.visualstudio.com/Cognitive%20Services/_workitems/edit/10145316") @GlobalTextAnalyticsAccountPreparer() @TextAnalyticsClientPreparer() async def test_multiple_of_same_action(self, client):