diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/README.md b/sdk/contentunderstanding/azure-ai-contentunderstanding/README.md index d0a87549075a..0de7d0917f10 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/README.md +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/README.md @@ -311,7 +311,7 @@ To run the tests for this package, you need to set up a `.env` file with your te ``` 4. Edit the `.env` file at the repo root and fill in your actual values: - - `CONTENTUNDERSTANDING_ENDPOINT`: Your Azure AI Foundry resource endpoint + - `AZURE_CONTENT_UNDERSTANDING_ENDPOINT`: Your Azure AI Foundry resource endpoint - `AZURE_CONTENT_UNDERSTANDING_KEY`: Your API key (optional if using DefaultAzureCredential) - `AZURE_TEST_RUN_LIVE`: Set to `true` to run tests against real Azure resources - `AZURE_SKIP_LIVE_RECORDING`: Set to `true` to skip recording when running live tests diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/generated_tests/conftest.py b/sdk/contentunderstanding/azure-ai-contentunderstanding/generated_tests/conftest.py deleted file mode 100644 index ebb1cc0e636a..000000000000 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/generated_tests/conftest.py +++ /dev/null @@ -1,45 +0,0 @@ -# coding=utf-8 -# -------------------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for license information. -# Code generated by Microsoft (R) Python Code Generator. -# Changes may cause incorrect behavior and will be lost if the code is regenerated. -# -------------------------------------------------------------------------- -import os -import pytest -from dotenv import load_dotenv -from devtools_testutils import ( - test_proxy, - add_general_regex_sanitizer, - add_body_key_sanitizer, - add_header_regex_sanitizer, -) - -load_dotenv() - - -# For security, please avoid record sensitive identity information in recordings -@pytest.fixture(scope="session", autouse=True) -def add_sanitizers(test_proxy): - contentunderstanding_subscription_id = os.environ.get( - "CONTENTUNDERSTANDING_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000" - ) - contentunderstanding_tenant_id = os.environ.get( - "CONTENTUNDERSTANDING_TENANT_ID", "00000000-0000-0000-0000-000000000000" - ) - contentunderstanding_client_id = os.environ.get( - "CONTENTUNDERSTANDING_CLIENT_ID", "00000000-0000-0000-0000-000000000000" - ) - contentunderstanding_client_secret = os.environ.get( - "CONTENTUNDERSTANDING_CLIENT_SECRET", "00000000-0000-0000-0000-000000000000" - ) - add_general_regex_sanitizer( - regex=contentunderstanding_subscription_id, value="00000000-0000-0000-0000-000000000000" - ) - add_general_regex_sanitizer(regex=contentunderstanding_tenant_id, value="00000000-0000-0000-0000-000000000000") - add_general_regex_sanitizer(regex=contentunderstanding_client_id, value="00000000-0000-0000-0000-000000000000") - add_general_regex_sanitizer(regex=contentunderstanding_client_secret, value="00000000-0000-0000-0000-000000000000") - - add_header_regex_sanitizer(key="Set-Cookie", value="[set-cookie;]") - add_header_regex_sanitizer(key="Cookie", value="cookie;") - add_body_key_sanitizer(json_path="$..access_token", value="access_token") diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/generated_tests/test_content_understanding.py b/sdk/contentunderstanding/azure-ai-contentunderstanding/generated_tests/test_content_understanding.py deleted file mode 100644 index d570db867e1f..000000000000 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/generated_tests/test_content_understanding.py +++ /dev/null @@ -1,301 +0,0 @@ -# coding=utf-8 -# -------------------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for license information. -# Code generated by Microsoft (R) Python Code Generator. -# Changes may cause incorrect behavior and will be lost if the code is regenerated. -# -------------------------------------------------------------------------- -import pytest -from devtools_testutils import recorded_by_proxy -from testpreparer import ContentUnderstandingClientTestBase, ContentUnderstandingPreparer - - -@pytest.mark.skip("you may need to update the auto-generated test case before run it") -class TestContentUnderstanding(ContentUnderstandingClientTestBase): - @ContentUnderstandingPreparer() - @recorded_by_proxy - def test_begin_analyze(self, contentunderstanding_endpoint): - client = self.create_client(endpoint=contentunderstanding_endpoint) - response = client.begin_analyze( - analyzer_id="str", - body={ - "inputs": [ - { - "data": bytes("bytes", encoding="utf-8"), - "mimeType": "str", - "name": "str", - "range": "str", - "url": "str", - } - ], - "modelDeployments": {"str": "str"}, - }, - ).result() # call '.result()' to poll until service return final result - - # please add some check logic here by yourself - # ... - - @ContentUnderstandingPreparer() - @recorded_by_proxy - def test_begin_analyze_binary(self, contentunderstanding_endpoint): - client = self.create_client(endpoint=contentunderstanding_endpoint) - response = client.begin_analyze_binary( - analyzer_id="str", - binary_input=bytes("bytes", encoding="utf-8"), - content_type="str", - ).result() # call '.result()' to poll until service return final result - - # please add some check logic here by yourself - # ... - - @ContentUnderstandingPreparer() - @recorded_by_proxy - def test_begin_copy_analyzer(self, contentunderstanding_endpoint): - client = self.create_client(endpoint=contentunderstanding_endpoint) - response = client.begin_copy_analyzer( - analyzer_id="str", - body={"sourceAnalyzerId": "str", "sourceAzureResourceId": "str", "sourceRegion": "str"}, - source_analyzer_id="str", - ).result() # call '.result()' to poll until service return final result - - # please add some check logic here by yourself - # ... - - @ContentUnderstandingPreparer() - @recorded_by_proxy - def test_begin_create_analyzer(self, contentunderstanding_endpoint): - client = self.create_client(endpoint=contentunderstanding_endpoint) - response = client.begin_create_analyzer( - analyzer_id="str", - resource={ - "analyzerId": "str", - "createdAt": "2020-02-20 00:00:00", - "lastModifiedAt": "2020-02-20 00:00:00", - "status": "str", - "baseAnalyzerId": "str", - "config": { - "annotationFormat": "str", - "chartFormat": "str", - "contentCategories": {"str": {"analyzer": ..., "analyzerId": "str", "description": "str"}}, - "disableFaceBlurring": bool, - "enableFigureAnalysis": bool, - "enableFigureDescription": bool, - "enableFormula": bool, - "enableLayout": bool, - "enableOcr": bool, - "enableSegment": bool, - "estimateFieldSourceAndConfidence": bool, - "locales": ["str"], - "omitContent": bool, - "returnDetails": bool, - "segmentPerPage": bool, - "tableFormat": "str", - }, - "description": "str", - "dynamicFieldSchema": bool, - "fieldSchema": { - "fields": { - "str": { - "$ref": "str", - "description": "str", - "enum": ["str"], - "enumDescriptions": {"str": "str"}, - "estimateSourceAndConfidence": bool, - "examples": ["str"], - "items": ..., - "method": "str", - "properties": {"str": ...}, - "type": "str", - } - }, - "definitions": { - "str": { - "$ref": "str", - "description": "str", - "enum": ["str"], - "enumDescriptions": {"str": "str"}, - "estimateSourceAndConfidence": bool, - "examples": ["str"], - "items": ..., - "method": "str", - "properties": {"str": ...}, - "type": "str", - } - }, - "description": "str", - "name": "str", - }, - "knowledgeSources": ["knowledge_source"], - "models": {"str": "str"}, - "processingLocation": "str", - "supportedModels": {"completion": {"str": "str"}, "embedding": {"str": "str"}}, - "tags": {"str": "str"}, - "warnings": [~azure.core.ODataV4Format], - }, - ).result() # call '.result()' to poll until service return final result - - # please add some check logic here by yourself - # ... - - @ContentUnderstandingPreparer() - @recorded_by_proxy - def test_delete_analyzer(self, contentunderstanding_endpoint): - client = self.create_client(endpoint=contentunderstanding_endpoint) - response = client.delete_analyzer( - analyzer_id="str", - ) - - # please add some check logic here by yourself - # ... - - @ContentUnderstandingPreparer() - @recorded_by_proxy - def test_delete_result(self, contentunderstanding_endpoint): - client = self.create_client(endpoint=contentunderstanding_endpoint) - response = client.delete_result( - operation_id="str", - ) - - # please add some check logic here by yourself - # ... - - @ContentUnderstandingPreparer() - @recorded_by_proxy - def test_get_analyzer(self, contentunderstanding_endpoint): - client = self.create_client(endpoint=contentunderstanding_endpoint) - response = client.get_analyzer( - analyzer_id="str", - ) - - # please add some check logic here by yourself - # ... - - @ContentUnderstandingPreparer() - @recorded_by_proxy - def test_get_defaults(self, contentunderstanding_endpoint): - client = self.create_client(endpoint=contentunderstanding_endpoint) - response = client.get_defaults() - - # please add some check logic here by yourself - # ... - - @ContentUnderstandingPreparer() - @recorded_by_proxy - def test_get_result_file(self, contentunderstanding_endpoint): - client = self.create_client(endpoint=contentunderstanding_endpoint) - response = client.get_result_file( - operation_id="str", - path="str", - ) - - # please add some check logic here by yourself - # ... - - @ContentUnderstandingPreparer() - @recorded_by_proxy - def test_grant_copy_authorization(self, contentunderstanding_endpoint): - client = self.create_client(endpoint=contentunderstanding_endpoint) - response = client.grant_copy_authorization( - analyzer_id="str", - body={"targetAzureResourceId": "str", "targetRegion": "str"}, - target_azure_resource_id="str", - ) - - # please add some check logic here by yourself - # ... - - @ContentUnderstandingPreparer() - @recorded_by_proxy - def test_list_analyzers(self, contentunderstanding_endpoint): - client = self.create_client(endpoint=contentunderstanding_endpoint) - response = client.list_analyzers() - result = [r for r in response] - # please add some check logic here by yourself - # ... - - @ContentUnderstandingPreparer() - @recorded_by_proxy - def test_update_analyzer(self, contentunderstanding_endpoint): - client = self.create_client(endpoint=contentunderstanding_endpoint) - response = client.update_analyzer( - analyzer_id="str", - resource={ - "analyzerId": "str", - "createdAt": "2020-02-20 00:00:00", - "lastModifiedAt": "2020-02-20 00:00:00", - "status": "str", - "baseAnalyzerId": "str", - "config": { - "annotationFormat": "str", - "chartFormat": "str", - "contentCategories": {"str": {"analyzer": ..., "analyzerId": "str", "description": "str"}}, - "disableFaceBlurring": bool, - "enableFigureAnalysis": bool, - "enableFigureDescription": bool, - "enableFormula": bool, - "enableLayout": bool, - "enableOcr": bool, - "enableSegment": bool, - "estimateFieldSourceAndConfidence": bool, - "locales": ["str"], - "omitContent": bool, - "returnDetails": bool, - "segmentPerPage": bool, - "tableFormat": "str", - }, - "description": "str", - "dynamicFieldSchema": bool, - "fieldSchema": { - "fields": { - "str": { - "$ref": "str", - "description": "str", - "enum": ["str"], - "enumDescriptions": {"str": "str"}, - "estimateSourceAndConfidence": bool, - "examples": ["str"], - "items": ..., - "method": "str", - "properties": {"str": ...}, - "type": "str", - } - }, - "definitions": { - "str": { - "$ref": "str", - "description": "str", - "enum": ["str"], - "enumDescriptions": {"str": "str"}, - "estimateSourceAndConfidence": bool, - "examples": ["str"], - "items": ..., - "method": "str", - "properties": {"str": ...}, - "type": "str", - } - }, - "description": "str", - "name": "str", - }, - "knowledgeSources": ["knowledge_source"], - "models": {"str": "str"}, - "processingLocation": "str", - "supportedModels": {"completion": {"str": "str"}, "embedding": {"str": "str"}}, - "tags": {"str": "str"}, - "warnings": [~azure.core.ODataV4Format], - }, - ) - - # please add some check logic here by yourself - # ... - - @ContentUnderstandingPreparer() - @recorded_by_proxy - def test_update_defaults(self, contentunderstanding_endpoint): - client = self.create_client(endpoint=contentunderstanding_endpoint) - response = client.update_defaults( - body={"modelDeployments": {}}, - ) - - # please add some check logic here by yourself - # ... diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/generated_tests/test_content_understanding_async.py b/sdk/contentunderstanding/azure-ai-contentunderstanding/generated_tests/test_content_understanding_async.py deleted file mode 100644 index a587c1be2188..000000000000 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/generated_tests/test_content_understanding_async.py +++ /dev/null @@ -1,310 +0,0 @@ -# coding=utf-8 -# -------------------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for license information. -# Code generated by Microsoft (R) Python Code Generator. -# Changes may cause incorrect behavior and will be lost if the code is regenerated. -# -------------------------------------------------------------------------- -import pytest -from devtools_testutils.aio import recorded_by_proxy_async -from testpreparer import ContentUnderstandingPreparer -from testpreparer_async import ContentUnderstandingClientTestBaseAsync - - -@pytest.mark.skip("you may need to update the auto-generated test case before run it") -class TestContentUnderstandingAsync(ContentUnderstandingClientTestBaseAsync): - @ContentUnderstandingPreparer() - @recorded_by_proxy_async - async def test_begin_analyze(self, contentunderstanding_endpoint): - client = self.create_async_client(endpoint=contentunderstanding_endpoint) - response = await ( - await client.begin_analyze( - analyzer_id="str", - body={ - "inputs": [ - { - "data": bytes("bytes", encoding="utf-8"), - "mimeType": "str", - "name": "str", - "range": "str", - "url": "str", - } - ], - "modelDeployments": {"str": "str"}, - }, - ) - ).result() # call '.result()' to poll until service return final result - - # please add some check logic here by yourself - # ... - - @ContentUnderstandingPreparer() - @recorded_by_proxy_async - async def test_begin_analyze_binary(self, contentunderstanding_endpoint): - client = self.create_async_client(endpoint=contentunderstanding_endpoint) - response = await ( - await client.begin_analyze_binary( - analyzer_id="str", - binary_input=bytes("bytes", encoding="utf-8"), - content_type="str", - ) - ).result() # call '.result()' to poll until service return final result - - # please add some check logic here by yourself - # ... - - @ContentUnderstandingPreparer() - @recorded_by_proxy_async - async def test_begin_copy_analyzer(self, contentunderstanding_endpoint): - client = self.create_async_client(endpoint=contentunderstanding_endpoint) - response = await ( - await client.begin_copy_analyzer( - analyzer_id="str", - body={"sourceAnalyzerId": "str", "sourceAzureResourceId": "str", "sourceRegion": "str"}, - source_analyzer_id="str", - ) - ).result() # call '.result()' to poll until service return final result - - # please add some check logic here by yourself - # ... - - @ContentUnderstandingPreparer() - @recorded_by_proxy_async - async def test_begin_create_analyzer(self, contentunderstanding_endpoint): - client = self.create_async_client(endpoint=contentunderstanding_endpoint) - response = await ( - await client.begin_create_analyzer( - analyzer_id="str", - resource={ - "analyzerId": "str", - "createdAt": "2020-02-20 00:00:00", - "lastModifiedAt": "2020-02-20 00:00:00", - "status": "str", - "baseAnalyzerId": "str", - "config": { - "annotationFormat": "str", - "chartFormat": "str", - "contentCategories": {"str": {"analyzer": ..., "analyzerId": "str", "description": "str"}}, - "disableFaceBlurring": bool, - "enableFigureAnalysis": bool, - "enableFigureDescription": bool, - "enableFormula": bool, - "enableLayout": bool, - "enableOcr": bool, - "enableSegment": bool, - "estimateFieldSourceAndConfidence": bool, - "locales": ["str"], - "omitContent": bool, - "returnDetails": bool, - "segmentPerPage": bool, - "tableFormat": "str", - }, - "description": "str", - "dynamicFieldSchema": bool, - "fieldSchema": { - "fields": { - "str": { - "$ref": "str", - "description": "str", - "enum": ["str"], - "enumDescriptions": {"str": "str"}, - "estimateSourceAndConfidence": bool, - "examples": ["str"], - "items": ..., - "method": "str", - "properties": {"str": ...}, - "type": "str", - } - }, - "definitions": { - "str": { - "$ref": "str", - "description": "str", - "enum": ["str"], - "enumDescriptions": {"str": "str"}, - "estimateSourceAndConfidence": bool, - "examples": ["str"], - "items": ..., - "method": "str", - "properties": {"str": ...}, - "type": "str", - } - }, - "description": "str", - "name": "str", - }, - "knowledgeSources": ["knowledge_source"], - "models": {"str": "str"}, - "processingLocation": "str", - "supportedModels": {"completion": {"str": "str"}, "embedding": {"str": "str"}}, - "tags": {"str": "str"}, - "warnings": [~azure.core.ODataV4Format], - }, - ) - ).result() # call '.result()' to poll until service return final result - - # please add some check logic here by yourself - # ... - - @ContentUnderstandingPreparer() - @recorded_by_proxy_async - async def test_delete_analyzer(self, contentunderstanding_endpoint): - client = self.create_async_client(endpoint=contentunderstanding_endpoint) - response = await client.delete_analyzer( - analyzer_id="str", - ) - - # please add some check logic here by yourself - # ... - - @ContentUnderstandingPreparer() - @recorded_by_proxy_async - async def test_delete_result(self, contentunderstanding_endpoint): - client = self.create_async_client(endpoint=contentunderstanding_endpoint) - response = await client.delete_result( - operation_id="str", - ) - - # please add some check logic here by yourself - # ... - - @ContentUnderstandingPreparer() - @recorded_by_proxy_async - async def test_get_analyzer(self, contentunderstanding_endpoint): - client = self.create_async_client(endpoint=contentunderstanding_endpoint) - response = await client.get_analyzer( - analyzer_id="str", - ) - - # please add some check logic here by yourself - # ... - - @ContentUnderstandingPreparer() - @recorded_by_proxy_async - async def test_get_defaults(self, contentunderstanding_endpoint): - client = self.create_async_client(endpoint=contentunderstanding_endpoint) - response = await client.get_defaults() - - # please add some check logic here by yourself - # ... - - @ContentUnderstandingPreparer() - @recorded_by_proxy_async - async def test_get_result_file(self, contentunderstanding_endpoint): - client = self.create_async_client(endpoint=contentunderstanding_endpoint) - response = await client.get_result_file( - operation_id="str", - path="str", - ) - - # please add some check logic here by yourself - # ... - - @ContentUnderstandingPreparer() - @recorded_by_proxy_async - async def test_grant_copy_authorization(self, contentunderstanding_endpoint): - client = self.create_async_client(endpoint=contentunderstanding_endpoint) - response = await client.grant_copy_authorization( - analyzer_id="str", - body={"targetAzureResourceId": "str", "targetRegion": "str"}, - target_azure_resource_id="str", - ) - - # please add some check logic here by yourself - # ... - - @ContentUnderstandingPreparer() - @recorded_by_proxy_async - async def test_list_analyzers(self, contentunderstanding_endpoint): - client = self.create_async_client(endpoint=contentunderstanding_endpoint) - response = client.list_analyzers() - result = [r async for r in response] - # please add some check logic here by yourself - # ... - - @ContentUnderstandingPreparer() - @recorded_by_proxy_async - async def test_update_analyzer(self, contentunderstanding_endpoint): - client = self.create_async_client(endpoint=contentunderstanding_endpoint) - response = await client.update_analyzer( - analyzer_id="str", - resource={ - "analyzerId": "str", - "createdAt": "2020-02-20 00:00:00", - "lastModifiedAt": "2020-02-20 00:00:00", - "status": "str", - "baseAnalyzerId": "str", - "config": { - "annotationFormat": "str", - "chartFormat": "str", - "contentCategories": {"str": {"analyzer": ..., "analyzerId": "str", "description": "str"}}, - "disableFaceBlurring": bool, - "enableFigureAnalysis": bool, - "enableFigureDescription": bool, - "enableFormula": bool, - "enableLayout": bool, - "enableOcr": bool, - "enableSegment": bool, - "estimateFieldSourceAndConfidence": bool, - "locales": ["str"], - "omitContent": bool, - "returnDetails": bool, - "segmentPerPage": bool, - "tableFormat": "str", - }, - "description": "str", - "dynamicFieldSchema": bool, - "fieldSchema": { - "fields": { - "str": { - "$ref": "str", - "description": "str", - "enum": ["str"], - "enumDescriptions": {"str": "str"}, - "estimateSourceAndConfidence": bool, - "examples": ["str"], - "items": ..., - "method": "str", - "properties": {"str": ...}, - "type": "str", - } - }, - "definitions": { - "str": { - "$ref": "str", - "description": "str", - "enum": ["str"], - "enumDescriptions": {"str": "str"}, - "estimateSourceAndConfidence": bool, - "examples": ["str"], - "items": ..., - "method": "str", - "properties": {"str": ...}, - "type": "str", - } - }, - "description": "str", - "name": "str", - }, - "knowledgeSources": ["knowledge_source"], - "models": {"str": "str"}, - "processingLocation": "str", - "supportedModels": {"completion": {"str": "str"}, "embedding": {"str": "str"}}, - "tags": {"str": "str"}, - "warnings": [~azure.core.ODataV4Format], - }, - ) - - # please add some check logic here by yourself - # ... - - @ContentUnderstandingPreparer() - @recorded_by_proxy_async - async def test_update_defaults(self, contentunderstanding_endpoint): - client = self.create_async_client(endpoint=contentunderstanding_endpoint) - response = await client.update_defaults( - body={"modelDeployments": {}}, - ) - - # please add some check logic here by yourself - # ... diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/generated_tests/testpreparer.py b/sdk/contentunderstanding/azure-ai-contentunderstanding/generated_tests/testpreparer.py deleted file mode 100644 index 59d6d08b3a68..000000000000 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/generated_tests/testpreparer.py +++ /dev/null @@ -1,28 +0,0 @@ -# coding=utf-8 -# -------------------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for license information. -# Code generated by Microsoft (R) Python Code Generator. -# Changes may cause incorrect behavior and will be lost if the code is regenerated. -# -------------------------------------------------------------------------- -from azure.ai.contentunderstanding import ContentUnderstandingClient -from devtools_testutils import AzureRecordedTestCase, PowerShellPreparer -import functools - - -class ContentUnderstandingClientTestBase(AzureRecordedTestCase): - - def create_client(self, endpoint): - credential = self.get_credential(ContentUnderstandingClient) - return self.create_client_from_credential( - ContentUnderstandingClient, - credential=credential, - endpoint=endpoint, - ) - - -ContentUnderstandingPreparer = functools.partial( - PowerShellPreparer, - "contentunderstanding", - contentunderstanding_endpoint="https://fake_contentunderstanding_endpoint.com", -) diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/generated_tests/testpreparer_async.py b/sdk/contentunderstanding/azure-ai-contentunderstanding/generated_tests/testpreparer_async.py deleted file mode 100644 index 1ca8d36c5713..000000000000 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/generated_tests/testpreparer_async.py +++ /dev/null @@ -1,20 +0,0 @@ -# coding=utf-8 -# -------------------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for license information. -# Code generated by Microsoft (R) Python Code Generator. -# Changes may cause incorrect behavior and will be lost if the code is regenerated. -# -------------------------------------------------------------------------- -from azure.ai.contentunderstanding.aio import ContentUnderstandingClient -from devtools_testutils import AzureRecordedTestCase - - -class ContentUnderstandingClientTestBaseAsync(AzureRecordedTestCase): - - def create_async_client(self, endpoint): - credential = self.get_credential(ContentUnderstandingClient, is_async=True) - return self.create_client_from_credential( - ContentUnderstandingClient, - credential=credential, - endpoint=endpoint, - ) diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/tests/README.md b/sdk/contentunderstanding/azure-ai-contentunderstanding/tests/README.md index 43aca8938be9..3438e1d18965 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/tests/README.md +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/tests/README.md @@ -44,7 +44,7 @@ The test framework uses the **test-proxy** for recording and playing back HTTP r By default, the test-proxy starts automatically when you run `pytest`. **No configuration is needed.** -**⚠️ IMPORTANT:** Do NOT set `PROXY_MANUAL_START=false` in your `.env` file. +**⚠️ IMPORTANT:** Do NOT set `PROXY_MANUAL_START=false` in your `.env` file. **Why?** Environment variables are read as strings. Setting `PROXY_MANUAL_START=false` makes it the string `"false"`, which is truthy in Python. This causes the framework to think the proxy is manually started, preventing automatic startup. @@ -77,7 +77,7 @@ If you need to run tests in parallel (`pytest -n auto`), you must manually start ```bash export PROXY_MANUAL_START=true ``` - + Or add to `.env` file: ```bash PROXY_MANUAL_START=true @@ -117,6 +117,16 @@ export AZURE_TEST_RUN_LIVE=true export AZURE_TEST_RECORD_MODE=true ``` +## Environment Variables + +The tests require several environment variables for authentication and configuration. Set these in your [`.env`](../.env) file at the repository root: + +- `AZURE_CONTENT_UNDERSTANDING_ENDPOINT` – The endpoint URL for your Azure Content Understanding resource. Example: `https://.cognitiveservices.azure.com/` +- `AZURE_CONTENT_UNDERSTANDING_KEY` – The API key for key-based authentication. Use this as an alternative to service principal authentication. +- `AZURE_TEST_RUN_LIVE` – Set to `true` to enable live testing mode (tests will make real API calls to Azure). Omit or set to `false` for playback mode. +- `AZURE_SKIP_LIVE_RECORDING` – Set to `true` to skip recording new HTTP interactions during live test runs. Useful for debugging or when you do not want to update recordings. + + ## Troubleshooting ### Connection Refused Errors @@ -142,7 +152,7 @@ MaxRetryError: HTTPConnectionPool(host='localhost', port=5000) **Symptoms:** Tests fail with connection errors, proxy doesn't start. **Solution:** -1. Check `.env` file at repository root (`/home/yslin/repos/azure-sdk-for-python-pr/.env`) +1. Check `.env` file at repository root (`sdk/contentunderstanding/azure-ai-contentunderstanding/.env`) 2. Remove any `PROXY_MANUAL_START=false` line 3. The framework will use the default `False` (boolean) for automatic startup diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/tests/test_analyzer_operation_id.py b/sdk/contentunderstanding/azure-ai-contentunderstanding/tests/test_analyzer_operation_id.py index 62a541a9abce..f8c8c8bdc94a 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/tests/test_analyzer_operation_id.py +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/tests/test_analyzer_operation_id.py @@ -11,12 +11,10 @@ import pytest from unittest.mock import Mock, patch -from azure.core.polling import LROPoller, PollingMethod -from azure.ai.contentunderstanding.operations._patch import ( +from azure.ai.contentunderstanding.models._patch import ( AnalyzeLROPoller, _parse_operation_id, ) -from azure.ai.contentunderstanding.models import AnalyzeInput from azure.ai.contentunderstanding import ContentUnderstandingClient @@ -54,8 +52,8 @@ def test_parse_operation_id_no_match(self): class TestAnalyzeLROPoller: """Test the AnalyzeLROPoller class.""" - def test_details_property_success(self): - """Test the details property when operation ID can be extracted.""" + def test_operation_id_property_success(self): + """Test the operation_id property when operation ID can be extracted.""" # Mock the polling method and initial response mock_polling_method = Mock() mock_initial_response = Mock() @@ -72,13 +70,11 @@ def test_details_property_success(self): client=Mock(), initial_response=Mock(), deserialization_callback=Mock(), polling_method=mock_polling_method ) - # Test details property - details = poller.details - assert details["operation_id"] == "test-op-id" - assert details["operation_type"] == "analyze" + # Test operation_id property + assert poller.operation_id == "test-op-id" - def test_details_property_missing_header(self): - """Test the details property when Operation-Location header is missing.""" + def test_operation_id_property_missing_header(self): + """Test the operation_id property when Operation-Location header is missing.""" # Mock the polling method and initial response mock_polling_method = Mock() mock_initial_response = Mock() @@ -93,14 +89,12 @@ def test_details_property_missing_header(self): client=Mock(), initial_response=Mock(), deserialization_callback=Mock(), polling_method=mock_polling_method ) - # Test details property - details = poller.details - assert details["operation_id"] is None - assert details["operation_type"] == "analyze" - assert "error" in details + # Test operation_id property raises ValueError + with pytest.raises(ValueError, match="Could not extract operation ID"): + _ = poller.operation_id - def test_details_property_invalid_url(self): - """Test the details property when URL format is invalid.""" + def test_operation_id_property_invalid_url(self): + """Test the operation_id property when URL format is invalid.""" # Mock the polling method and initial response mock_polling_method = Mock() mock_initial_response = Mock() @@ -117,11 +111,9 @@ def test_details_property_invalid_url(self): client=Mock(), initial_response=Mock(), deserialization_callback=Mock(), polling_method=mock_polling_method ) - # Test details property - details = poller.details - assert details["operation_id"] is None - assert details["operation_type"] == "analyze" - assert "error" in details + # Test operation_id property raises ValueError + with pytest.raises(ValueError, match="Could not extract operation ID"): + _ = poller.operation_id def test_from_continuation_token(self): """Test the from_continuation_token class method.""" @@ -146,7 +138,7 @@ class TestPollerIntegration: """Test integration with the operations classes.""" def test_analyze_operation_returns_custom_poller(self): - """Test that begin_analyze returns AnalyzeLROPoller with details property.""" + """Test that begin_analyze returns AnalyzeLROPoller with operation_id property.""" # Create a mock client mock_client = Mock(spec=ContentUnderstandingClient) @@ -164,9 +156,7 @@ def test_analyze_operation_returns_custom_poller(self): mock_client, mock_poller._polling_method._initial_response, Mock(), mock_poller._polling_method ) - # Verify it has the details property + # Verify it has the operation_id property assert isinstance(result, AnalyzeLROPoller) - assert hasattr(result, "details") - details = result.details - assert "operation_id" in details - assert details["operation_id"] == "test-op-id-123" + assert hasattr(result, "operation_id") + assert result.operation_id == "test-op-id-123" diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/tests/test_content_understanding_content_analyzers_operations.py b/sdk/contentunderstanding/azure-ai-contentunderstanding/tests/test_content_understanding_content_analyzers_operations.py index 66d3c55bf09f..c55831cb34ec 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/tests/test_content_understanding_content_analyzers_operations.py +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/tests/test_content_understanding_content_analyzers_operations.py @@ -6,27 +6,30 @@ # Code generated by Microsoft (R) Python Code Generator. # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- -import pytest import os import re -from typing import Tuple, Union, Dict, Any, Optional, List, Set -from devtools_testutils import recorded_by_proxy -from testpreparer import ContentUnderstandingPreparer -from testpreparer import ContentUnderstandingClientTestBase -from azure.ai.contentunderstanding.models import ContentAnalyzer +from typing import Any, Dict, List, Optional, Set, Union + +import pytest from azure.ai.contentunderstanding import ContentUnderstandingClient -from azure.ai.contentunderstanding.models import AnalyzeInput +from azure.ai.contentunderstanding.models import ( + AnalyzeInput, + ContentAnalyzer, + ContentAnalyzerConfig, + ContentCategoryDefinition, +) +from azure.core.exceptions import ResourceNotFoundError +from devtools_testutils import is_live_and_not_recording, recorded_by_proxy from test_helpers import ( - generate_analyzer_id, - new_simple_content_analyzer_object, - new_marketing_video_analyzer_object, assert_poller_properties, assert_simple_content_analyzer_result, + generate_analyzer_id, + new_marketing_video_analyzer_object, + new_simple_content_analyzer_object, save_analysis_result_to_file, save_keyframe_image_to_file, ) - -from devtools_testutils import is_live, is_live_and_not_recording +from testpreparer import ContentUnderstandingClientTestBase, ContentUnderstandingPreparer def create_analyzer_and_assert_sync( @@ -48,7 +51,7 @@ def create_analyzer_and_assert_sync( print(f"\nCreating analyzer {analyzer_id}") # Start the analyzer creation operation - poller = client.begin_create_or_replace( + poller = client.begin_create_analyzer( analyzer_id=analyzer_id, resource=resource, ) @@ -86,7 +89,7 @@ def delete_analyzer_and_assert_sync( if created_analyzer: print(f"Cleaning up analyzer {analyzer_id}") try: - client.delete(analyzer_id=analyzer_id) + client.delete_analyzer(analyzer_id=analyzer_id) # Verify deletion print(f"Analyzer {analyzer_id} is deleted successfully") except Exception as e: @@ -217,14 +220,14 @@ class TestContentUnderstandingContentAnalyzersOperations(ContentUnderstandingCli @ContentUnderstandingPreparer() @recorded_by_proxy - def test_content_analyzers_begin_create_with_content_analyzer(self, contentunderstanding_endpoint: str) -> None: + def test_content_analyzers_begin_create_with_content_analyzer(self, azure_content_understanding_endpoint: str) -> None: """ Test Summary: - Create analyzer using ContentAnalyzer object - Verify analyzer creation and poller properties - Clean up created analyzer """ - client: ContentUnderstandingClient = self.create_client(endpoint=contentunderstanding_endpoint) + client: ContentUnderstandingClient = self.create_client(endpoint=azure_content_understanding_endpoint) analyzer_id = generate_analyzer_id(client, "create_sync", is_async=False) created_analyzer = False @@ -251,14 +254,14 @@ def test_content_analyzers_begin_create_with_content_analyzer(self, contentunder @ContentUnderstandingPreparer() @recorded_by_proxy - def test_content_analyzers_begin_create_with_json(self, contentunderstanding_endpoint: str) -> None: + def test_content_analyzers_begin_create_with_json(self, azure_content_understanding_endpoint: str) -> None: """ Test Summary: - Create analyzer using JSON dictionary - Verify analyzer creation and poller properties - Clean up created analyzer """ - client: ContentUnderstandingClient = self.create_client(endpoint=contentunderstanding_endpoint) + client: ContentUnderstandingClient = self.create_client(endpoint=azure_content_understanding_endpoint) analyzer_id = generate_analyzer_id(client, "create_json_sync", is_async=False) created_analyzer = False @@ -294,7 +297,7 @@ def test_content_analyzers_begin_create_with_json(self, contentunderstanding_end @ContentUnderstandingPreparer() @recorded_by_proxy - def test_content_analyzers_update(self, contentunderstanding_endpoint: str) -> None: + def test_content_analyzers_update(self, azure_content_understanding_endpoint: str) -> None: """ Test Summary: - Create initial analyzer @@ -303,7 +306,7 @@ def test_content_analyzers_update(self, contentunderstanding_endpoint: str) -> N - Get analyzer after update to verify changes persisted - Clean up created analyzer """ - client: ContentUnderstandingClient = self.create_client(endpoint=contentunderstanding_endpoint) + client: ContentUnderstandingClient = self.create_client(endpoint=azure_content_understanding_endpoint) analyzer_id = generate_analyzer_id(client, "update_sync", is_async=False) created_analyzer = False @@ -321,7 +324,7 @@ def test_content_analyzers_update(self, contentunderstanding_endpoint: str) -> N # Get the analyzer before update to verify initial state print(f"Getting analyzer {analyzer_id} before update") - analyzer_before_update = client.get(analyzer_id=analyzer_id) + analyzer_before_update = client.get_analyzer(analyzer_id=analyzer_id) assert analyzer_before_update is not None assert analyzer_before_update.analyzer_id == analyzer_id assert analyzer_before_update.description == f"Initial analyzer for update test: {analyzer_id}" @@ -334,20 +337,19 @@ def test_content_analyzers_update(self, contentunderstanding_endpoint: str) -> N updated_analyzer = ContentAnalyzer( base_analyzer_id=analyzer_before_update.base_analyzer_id, models=analyzer_before_update.models, - analyzer_id=analyzer_id, description=f"Updated analyzer description: {analyzer_id}", tags={"updated_tag": "updated_value"}, ) # Update the analyzer print(f"Updating analyzer {analyzer_id}") - response = client.update(analyzer_id=analyzer_id, resource=updated_analyzer) + response = client.update_analyzer(analyzer_id=analyzer_id, resource=updated_analyzer) assert response is not None assert response.analyzer_id == analyzer_id # Get the analyzer after update to verify changes persisted print(f"Getting analyzer {analyzer_id} after update") - analyzer_after_update = client.get(analyzer_id=analyzer_id) + analyzer_after_update = client.get_analyzer(analyzer_id=analyzer_id) assert analyzer_after_update is not None assert analyzer_after_update.analyzer_id == analyzer_id assert analyzer_after_update.description == f"Updated analyzer description: {analyzer_id}" @@ -362,14 +364,14 @@ def test_content_analyzers_update(self, contentunderstanding_endpoint: str) -> N @ContentUnderstandingPreparer() @recorded_by_proxy - def test_content_analyzers_delete(self, contentunderstanding_endpoint: str) -> None: + def test_content_analyzers_delete(self, azure_content_understanding_endpoint: str) -> None: """ Test Summary: - Create analyzer for deletion test - Delete analyzer - Clean up if deletion failed """ - client: ContentUnderstandingClient = self.create_client(endpoint=contentunderstanding_endpoint) + client: ContentUnderstandingClient = self.create_client(endpoint=azure_content_understanding_endpoint) analyzer_id = generate_analyzer_id(client, "delete_sync", is_async=False) created_analyzer = False @@ -387,7 +389,7 @@ def test_content_analyzers_delete(self, contentunderstanding_endpoint: str) -> N # Delete the analyzer print(f"Deleting analyzer {analyzer_id}") - response = client.delete(analyzer_id=analyzer_id) + response = client.delete_analyzer(analyzer_id=analyzer_id) # Verify the delete response assert response is None @@ -398,7 +400,7 @@ def test_content_analyzers_delete(self, contentunderstanding_endpoint: str) -> N @ContentUnderstandingPreparer() @recorded_by_proxy - def test_content_analyzers_begin_analyze_url(self, contentunderstanding_endpoint: str) -> None: + def test_content_analyzers_begin_analyze_url(self, azure_content_understanding_endpoint: str) -> None: """ Test Summary: - Create simple analyzer for URL analysis @@ -409,7 +411,7 @@ def test_content_analyzers_begin_analyze_url(self, contentunderstanding_endpoint - Verify total_amount field exists and equals 110 - Clean up created analyzer """ - client: ContentUnderstandingClient = self.create_client(endpoint=contentunderstanding_endpoint) + client: ContentUnderstandingClient = self.create_client(endpoint=azure_content_understanding_endpoint) analyzer_id = generate_analyzer_id(client, "analyze_url_sync", is_async=False) created_analyzer = False @@ -451,7 +453,7 @@ def test_content_analyzers_begin_analyze_url(self, contentunderstanding_endpoint @ContentUnderstandingPreparer() @recorded_by_proxy - def test_content_analyzers_begin_analyze_binary(self, contentunderstanding_endpoint: str) -> None: + def test_content_analyzers_begin_analyze_binary(self, azure_content_understanding_endpoint: str) -> None: """ Test Summary: - Create simple analyzer for binary analysis @@ -463,7 +465,7 @@ def test_content_analyzers_begin_analyze_binary(self, contentunderstanding_endpo - Verify total_amount field exists and equals 110 - Clean up created analyzer """ - client: ContentUnderstandingClient = self.create_client(endpoint=contentunderstanding_endpoint) + client: ContentUnderstandingClient = self.create_client(endpoint=azure_content_understanding_endpoint) analyzer_id = generate_analyzer_id(client, "analyze_binary_sync", is_async=False) created_analyzer = False @@ -507,7 +509,7 @@ def test_content_analyzers_begin_analyze_binary(self, contentunderstanding_endpo @ContentUnderstandingPreparer() @recorded_by_proxy - def test_content_analyzers_get_result_file(self, contentunderstanding_endpoint: str) -> None: + def test_content_analyzers_get_result_file(self, azure_content_understanding_endpoint: str) -> None: """ Test Summary: - Create marketing video analyzer based on the marketing video template @@ -523,7 +525,7 @@ def test_content_analyzers_get_result_file(self, contentunderstanding_endpoint: "This test requires live mode to run, as it involves large video files that are too big for test proxy to record" ) return - client: ContentUnderstandingClient = self.create_client(endpoint=contentunderstanding_endpoint) + client: ContentUnderstandingClient = self.create_client(endpoint=azure_content_understanding_endpoint) analyzer_id = generate_analyzer_id(client, "get_result_file_sync", is_async=False) created_analyzer = False @@ -556,10 +558,8 @@ def test_content_analyzers_get_result_file(self, contentunderstanding_endpoint: print(f"Waiting for video analysis to complete") analysis_result = analysis_poller.result() - # Get the operation ID from the poller details - details = analysis_poller.details - assert "operation_id" in details, "Details should contain operation_id" - analysis_operation_id = details["operation_id"] + # Get the operation ID from the poller operation_id property + analysis_operation_id = analysis_poller.operation_id assert analysis_operation_id is not None, "Operation ID should not be None" assert len(analysis_operation_id) > 0, "Operation ID should not be empty" print(f"Analysis operation ID: {analysis_operation_id}") @@ -577,8 +577,209 @@ def test_content_analyzers_get_result_file(self, contentunderstanding_endpoint: delete_analyzer_and_assert_sync(client, analyzer_id, created_analyzer) -# def test_content_analyzers_begin_analyze(self, contentunderstanding_endpoint): -# client = self.create_client(endpoint=contentunderstanding_endpoint) + @ContentUnderstandingPreparer() + @recorded_by_proxy + def test_content_analyzers_create_classifier(self, azure_content_understanding_endpoint: str) -> None: + """ + Test Summary: + - Create a classifier with content categories for document categorization + - Verify creation and properties + - Clean up + """ + client: ContentUnderstandingClient = self.create_client(endpoint=azure_content_understanding_endpoint) + analyzer_id = generate_analyzer_id(client, "create_classifier_sync", is_async=False) + created_analyzer = False + + # Define content categories for classification + categories = { + "Loan_Application": ContentCategoryDefinition( + description=( + "Documents submitted by individuals or businesses to request funding, " + "typically including personal or business details, financial history, " + "loan amount, purpose, and supporting documentation." + ) + ), + "Invoice": ContentCategoryDefinition( + description=( + "Billing documents issued by sellers or service providers to request " + "payment for goods or services, detailing items, prices, taxes, totals, " + "and payment terms." + ) + ), + "Bank_Statement": ContentCategoryDefinition( + description=( + "Official statements issued by banks that summarize account activity " + "over a period, including deposits, withdrawals, fees, and balances." + ) + ), + } + + # Create classifier configuration + classifier_config = ContentAnalyzerConfig( + return_details=True, + enable_segment=True, # Automatically split and classify multi-document files + content_categories=categories, + ) + + # Create analyzer object + classifier = ContentAnalyzer( + base_analyzer_id="prebuilt-document", + description="Custom classifier for financial document categorization", + config=classifier_config, + models={"completion": "gpt-4.1"}, # Model used for classification + tags={"sample_type": "classifier_demo", "document_type": "financial"}, + ) + + try: + # Create analyzer using the refactored function + poller = create_analyzer_and_assert_sync(client, analyzer_id, classifier) + created_analyzer = True + + # Retrieve the analyzer to verify properties + retrieved_analyzer = client.get_analyzer(analyzer_id) + assert retrieved_analyzer is not None + assert retrieved_analyzer.analyzer_id == analyzer_id + assert retrieved_analyzer.description == "Custom classifier for financial document categorization" + assert retrieved_analyzer.base_analyzer_id == "prebuilt-document" + assert retrieved_analyzer.status is not None + assert retrieved_analyzer.config is not None + assert retrieved_analyzer.config.return_details is True + assert retrieved_analyzer.config.enable_segment is True + assert retrieved_analyzer.config.content_categories is not None + assert "Loan_Application" in retrieved_analyzer.config.content_categories + assert "Invoice" in retrieved_analyzer.config.content_categories + assert "Bank_Statement" in retrieved_analyzer.config.content_categories + assert retrieved_analyzer.models is not None + assert retrieved_analyzer.models["completion"] == "gpt-4.1" + assert retrieved_analyzer.tags == {"sample_type": "classifier_demo", "document_type": "financial"} + print(f"Classifier {analyzer_id} verified successfully") + + finally: + # Always clean up the created analyzer, even if the test fails + delete_analyzer_and_assert_sync(client, analyzer_id, created_analyzer) + + + @ContentUnderstandingPreparer() + @recorded_by_proxy + def test_content_analyzers_delete_result(self, azure_content_understanding_endpoint: str) -> None: + """ + Test Summary: + - Create simple analyzer for URL analysis + - Begin analysis operation with URL input + - Wait for analysis completion + - Verify result accessibility before deletion + - Delete the analysis result + - Verify deletion by confirming the result is no longer accessible (404 error) + - Clean up created analyzer + """ + client: ContentUnderstandingClient = self.create_client(endpoint=azure_content_understanding_endpoint) + analyzer_id = generate_analyzer_id(client, "delete_result_sync", is_async=False) + created_analyzer = False + + # Create a simple analyzer for URL analysis + content_analyzer = new_simple_content_analyzer_object( + analyzer_id=analyzer_id, + description=f"test analyzer for delete result: {analyzer_id}", + tags={"test_type": "delete_result"}, + ) + + try: + # Create analyzer using the refactored function + poller = create_analyzer_and_assert_sync(client, analyzer_id, content_analyzer) + created_analyzer = True + + # Use the provided URL for the invoice PDF + invoice_url = "https://github.com/Azure-Samples/azure-ai-content-understanding-python/raw/refs/heads/main/data/invoice.pdf" + + print(f"Starting URL analysis with analyzer {analyzer_id}") + + # Begin analysis operation with URL + analysis_poller = client.begin_analyze(analyzer_id=analyzer_id, inputs=[AnalyzeInput(url=invoice_url)]) + assert_poller_properties(analysis_poller, "Analysis poller") + + # Wait for analysis completion + print(f"Waiting for analysis completion") + analysis_result = analysis_poller.result() + print(f" Analysis completed") + + # Get operation ID + operation_id = analysis_poller.operation_id + assert operation_id is not None + + # Verify result accessibility before deletion + print(f"Verifying result accessibility before deletion...") + result_before = client._get_result(operation_id=operation_id) # type: ignore[attr-defined] + assert result_before is not None + print(f"Result accessible before deletion (status: {result_before.status})") + + # Delete the result + print(f"Deleting result for operation {operation_id}") + client.delete_result(operation_id=operation_id) + print(f"Result deleted successfully") + + # Verify deletion by attempting to access the result again + print(f"Verifying deletion...") + print(f" Attempting to access the deleted result...") + with pytest.raises(ResourceNotFoundError): + client._get_result(operation_id=operation_id) # type: ignore[attr-defined] + print(f"Verification successful: Result properly deleted") + print(f" ✓ Confirmed: Result is no longer accessible as expected") + + finally: + # Always clean up the created analyzer, even if the test fails + delete_analyzer_and_assert_sync(client, analyzer_id, created_analyzer) + + + @ContentUnderstandingPreparer() + @recorded_by_proxy + def test_content_analyzers_get_defaults(self, azure_content_understanding_endpoint: str) -> None: + """ + Test Summary: + - Get default model deployments + - Verify response structure + """ + client: ContentUnderstandingClient = self.create_client(endpoint=azure_content_understanding_endpoint) + defaults = client.get_defaults() + assert defaults is not None + # We can't assert specific values as they depend on the resource configuration, + # but we can check if the object has the expected attribute + assert hasattr(defaults, "model_deployments") + print(f"Defaults retrieved: {defaults}") + + + @ContentUnderstandingPreparer() + @recorded_by_proxy + def test_content_analyzers_update_defaults(self, azure_content_understanding_endpoint: str) -> None: + """ + Test Summary: + - Get current defaults + - Update defaults with the same values (to test the API without changing config) + - Verify update success + """ + client: ContentUnderstandingClient = self.create_client(endpoint=azure_content_understanding_endpoint) + + # Get current defaults + defaults = client.get_defaults() + assert defaults is not None + + if defaults.model_deployments: + print(f"Current defaults: {defaults.model_deployments}") + + # Update with same values + updated_defaults = client.update_defaults(model_deployments=defaults.model_deployments) + + assert updated_defaults is not None + assert updated_defaults.model_deployments == defaults.model_deployments + print("Defaults updated successfully") + else: + print("No defaults configured, skipping update test to avoid setting invalid values") + + +# @ContentUnderstandingPreparer() +# @recorded_by_proxy +# @pytest.mark.skip(reason="GA API addition - to be implemented") +# def test_content_analyzers_begin_analyze(self, azure_content_understanding_endpoint): +# client = self.create_client(endpoint=azure_content_understanding_endpoint) # response = client.begin_analyze( # analyzer_id="str", # body={ @@ -602,13 +803,8 @@ def test_content_analyzers_get_result_file(self, contentunderstanding_endpoint: # @ContentUnderstandingPreparer() # @recorded_by_proxy # @pytest.mark.skip(reason="GA API addition - to be implemented") - - -# @ContentUnderstandingPreparer() -# @recorded_by_proxy -# @pytest.mark.skip(reason="GA API addition - to be implemented") -# def test_content_analyzers_begin_copy(self, contentunderstanding_endpoint): -# client = self.create_client(endpoint=contentunderstanding_endpoint) +# def test_content_analyzers_begin_copy(self, azure_content_understanding_endpoint): +# client = self.create_client(endpoint=azure_content_understanding_endpoint) # response = client.begin_copy( # analyzer_id="str", # body={"sourceAnalyzerId": "str", "sourceAzureResourceId": "str", "sourceRegion": "str"}, @@ -622,13 +818,8 @@ def test_content_analyzers_get_result_file(self, contentunderstanding_endpoint: # @ContentUnderstandingPreparer() # @recorded_by_proxy # @pytest.mark.skip(reason="GA API addition - to be implemented") - - -# @ContentUnderstandingPreparer() -# @recorded_by_proxy -# @pytest.mark.skip(reason="GA API addition - to be implemented") -# def test_content_analyzers_begin_create_or_replace(self, contentunderstanding_endpoint): -# client = self.create_client(endpoint=contentunderstanding_endpoint) +# def test_content_analyzers_begin_create_or_replace(self, azure_content_understanding_endpoint): +# client = self.create_client(endpoint=azure_content_understanding_endpoint) # response = client.begin_create_or_replace( # analyzer_id="str", # resource={ @@ -706,47 +897,8 @@ def test_content_analyzers_get_result_file(self, contentunderstanding_endpoint: # @ContentUnderstandingPreparer() # @recorded_by_proxy # @pytest.mark.skip(reason="GA API addition - to be implemented") - - -# @ContentUnderstandingPreparer() -# @recorded_by_proxy -# @pytest.mark.skip(reason="GA API addition - to be implemented") -# def test_content_analyzers_delete_result(self, contentunderstanding_endpoint): -# client = self.create_client(endpoint=contentunderstanding_endpoint) -# response = client.delete_result( -# operation_id="str", -# ) - -# please add some check logic here by yourself -# ... - - -# @ContentUnderstandingPreparer() -# @recorded_by_proxy -# @pytest.mark.skip(reason="GA API addition - to be implemented") - - -# @ContentUnderstandingPreparer() -# @recorded_by_proxy -# @pytest.mark.skip(reason="GA API addition - to be implemented") -# def test_content_analyzers_get_defaults(self, contentunderstanding_endpoint): -# client = self.create_client(endpoint=contentunderstanding_endpoint) -# response = client.get_defaults() - -# please add some check logic here by yourself -# ... - - -# @ContentUnderstandingPreparer() -# @recorded_by_proxy -# @pytest.mark.skip(reason="GA API addition - to be implemented") - - -# @ContentUnderstandingPreparer() -# @recorded_by_proxy -# @pytest.mark.skip(reason="GA API addition - to be implemented") -# def test_content_analyzers_get_operation_status(self, contentunderstanding_endpoint): -# client = self.create_client(endpoint=contentunderstanding_endpoint) +# def test_content_analyzers_get_operation_status(self, azure_content_understanding_endpoint): +# client = self.create_client(endpoint=azure_content_understanding_endpoint) # response = client.get_operation_status( # analyzer_id="str", # operation_id="str", @@ -759,13 +911,8 @@ def test_content_analyzers_get_result_file(self, contentunderstanding_endpoint: # @ContentUnderstandingPreparer() # @recorded_by_proxy # @pytest.mark.skip(reason="GA API addition - to be implemented") - - -# @ContentUnderstandingPreparer() -# @recorded_by_proxy -# @pytest.mark.skip(reason="GA API addition - to be implemented") -# def test_content_analyzers_grant_copy_authorization(self, contentunderstanding_endpoint): -# client = self.create_client(endpoint=contentunderstanding_endpoint) +# def test_content_analyzers_grant_copy_authorization(self, azure_content_understanding_endpoint): +# client = self.create_client(endpoint=azure_content_understanding_endpoint) # response = client.grant_copy_authorization( # analyzer_id="str", # body={"targetAzureResourceId": "str", "targetRegion": "str"}, @@ -775,20 +922,3 @@ def test_content_analyzers_get_result_file(self, contentunderstanding_endpoint: # please add some check logic here by yourself # ... - -# @ContentUnderstandingPreparer() -# @recorded_by_proxy -# @pytest.mark.skip(reason="GA API addition - to be implemented") - - -# @ContentUnderstandingPreparer() -# @recorded_by_proxy -# @pytest.mark.skip(reason="GA API addition - to be implemented") -# def test_content_analyzers_update_defaults(self, contentunderstanding_endpoint): -# client = self.create_client(endpoint=contentunderstanding_endpoint) -# response = client.update_defaults( -# body={"modelDeployments": {}}, -# ) - -# please add some check logic here by yourself -# ... diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/tests/test_content_understanding_content_analyzers_operations_async.py b/sdk/contentunderstanding/azure-ai-contentunderstanding/tests/test_content_understanding_content_analyzers_operations_async.py index 4e7737911a18..72fca12a67b7 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/tests/test_content_understanding_content_analyzers_operations_async.py +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/tests/test_content_understanding_content_analyzers_operations_async.py @@ -6,25 +6,34 @@ # Code generated by Microsoft (R) Python Code Generator. # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- -import pytest import os import re -from typing import Tuple, Union, Dict, Any, Optional, List, Set -from devtools_testutils.aio import recorded_by_proxy_async -from testpreparer_async import ContentUnderstandingClientTestBaseAsync, ContentUnderstandingPreparer -from azure.ai.contentunderstanding.models import ContentAnalyzer +from typing import Any, Dict, List, Optional, Set, Union + +import pytest from azure.ai.contentunderstanding.aio import ContentUnderstandingClient -from azure.ai.contentunderstanding.models import AnalyzeInput +from azure.ai.contentunderstanding.models import ( + AnalyzeInput, + ContentAnalyzer, + ContentAnalyzerConfig, + ContentCategoryDefinition, +) +from azure.core.exceptions import ResourceNotFoundError +from devtools_testutils import is_live_and_not_recording +from devtools_testutils.aio import recorded_by_proxy_async from test_helpers import ( - generate_analyzer_id, - new_simple_content_analyzer_object, - new_marketing_video_analyzer_object, assert_poller_properties, assert_simple_content_analyzer_result, + generate_analyzer_id, + new_marketing_video_analyzer_object, + new_simple_content_analyzer_object, save_analysis_result_to_file, save_keyframe_image_to_file, ) -from devtools_testutils import is_live, is_live_and_not_recording +from testpreparer_async import ( + ContentUnderstandingClientTestBaseAsync, + ContentUnderstandingPreparer, +) async def create_analyzer_and_assert_async( @@ -46,7 +55,7 @@ async def create_analyzer_and_assert_async( print(f"\nCreating analyzer {analyzer_id}") # Start the analyzer creation operation - poller = await client.begin_create_or_replace( + poller = await client.begin_create_analyzer( analyzer_id=analyzer_id, resource=resource, ) @@ -83,7 +92,7 @@ async def delete_analyzer_and_assert( if created_analyzer: print(f"Cleaning up analyzer {analyzer_id}") try: - await client.delete(analyzer_id=analyzer_id) + await client.delete_analyzer(analyzer_id=analyzer_id) except Exception as e: # If deletion fails, the test should fail raise AssertionError(f"Failed to delete analyzer {analyzer_id}: {e}") from e @@ -216,7 +225,7 @@ class TestContentUnderstandingContentAnalyzersOperationsAsync(ContentUnderstandi @ContentUnderstandingPreparer() @recorded_by_proxy_async async def test_content_analyzers_begin_create_with_content_analyzer( - self, contentunderstanding_endpoint: str + self, azure_content_understanding_endpoint: str ) -> None: """ Test Summary: @@ -224,7 +233,12 @@ async def test_content_analyzers_begin_create_with_content_analyzer( - Verify analyzer creation and poller properties - Clean up created analyzer """ - client: ContentUnderstandingClient = self.create_async_client(endpoint=contentunderstanding_endpoint) + # Skip this test if defaults cannot be set (no OpenAI deployments configured) + if not is_live_and_not_recording(): + pytest.skip("This test creates custom analyzers which require ContentUnderstandingDefaults to be set. " + "Defaults are only available in live mode with configured OpenAI deployments.") + + client: ContentUnderstandingClient = self.create_async_client(endpoint=azure_content_understanding_endpoint) analyzer_id = generate_analyzer_id(client, "create_content_analyzer", is_async=True) created_analyzer = False @@ -243,14 +257,14 @@ async def test_content_analyzers_begin_create_with_content_analyzer( @ContentUnderstandingPreparer() @recorded_by_proxy_async - async def test_content_analyzers_begin_create_with_json(self, contentunderstanding_endpoint: str) -> None: + async def test_content_analyzers_begin_create_with_json(self, azure_content_understanding_endpoint: str) -> None: """ Test Summary: - Create analyzer using JSON dictionary - Verify analyzer creation and poller properties - Clean up created analyzer """ - client: ContentUnderstandingClient = self.create_async_client(endpoint=contentunderstanding_endpoint) + client: ContentUnderstandingClient = self.create_async_client(endpoint=azure_content_understanding_endpoint) analyzer_id = generate_analyzer_id(client, "create_json", is_async=True) created_analyzer = False @@ -298,7 +312,7 @@ async def test_content_analyzers_begin_create_with_json(self, contentunderstandi @ContentUnderstandingPreparer() @recorded_by_proxy_async - async def test_content_analyzers_update(self, contentunderstanding_endpoint: str) -> None: + async def test_content_analyzers_update(self, azure_content_understanding_endpoint: str) -> None: """ Test Summary: - Create initial analyzer @@ -307,7 +321,7 @@ async def test_content_analyzers_update(self, contentunderstanding_endpoint: str - Get analyzer after update to verify changes persisted - Clean up created analyzer """ - client: ContentUnderstandingClient = self.create_async_client(endpoint=contentunderstanding_endpoint) + client: ContentUnderstandingClient = self.create_async_client(endpoint=azure_content_understanding_endpoint) analyzer_id = generate_analyzer_id(client, "update", is_async=True) created_analyzer = False @@ -325,7 +339,7 @@ async def test_content_analyzers_update(self, contentunderstanding_endpoint: str # Get the analyzer before update to verify initial state print(f"Getting analyzer {analyzer_id} before update") - analyzer_before_update = await client.get(analyzer_id=analyzer_id) + analyzer_before_update = await client.get_analyzer(analyzer_id=analyzer_id) assert analyzer_before_update is not None assert analyzer_before_update.analyzer_id == analyzer_id assert analyzer_before_update.description == f"Initial analyzer for update test: {analyzer_id}" @@ -347,7 +361,7 @@ async def test_content_analyzers_update(self, contentunderstanding_endpoint: str print(f"Updating analyzer {analyzer_id} with new tag and description") # Update the analyzer - response = await client.update( + response = await client.update_analyzer( analyzer_id=analyzer_id, resource=updated_analyzer, ) @@ -365,9 +379,9 @@ async def test_content_analyzers_update(self, contentunderstanding_endpoint: str print(f"Successfully updated analyzer {analyzer_id} with new tag and description") - # Get the analyzer after update to verify the changes persisted + # Get the analyzer after update to verify changes persisted print(f"Getting analyzer {analyzer_id} after update") - analyzer_after_update = await client.get(analyzer_id=analyzer_id) + analyzer_after_update = await client.get_analyzer(analyzer_id=analyzer_id) assert analyzer_after_update is not None assert analyzer_after_update.analyzer_id == analyzer_id assert analyzer_after_update.description == f"Updated analyzer for update test: {analyzer_id}" @@ -382,14 +396,14 @@ async def test_content_analyzers_update(self, contentunderstanding_endpoint: str @ContentUnderstandingPreparer() @recorded_by_proxy_async - async def test_content_analyzers_get(self, contentunderstanding_endpoint: str) -> None: + async def test_content_analyzers_get(self, azure_content_understanding_endpoint: str) -> None: """ Test Summary: - Get existing prebuilt analyzer - Verify analyzer properties and status """ - client: ContentUnderstandingClient = self.create_async_client(endpoint=contentunderstanding_endpoint) - response = await client.get( + client: ContentUnderstandingClient = self.create_async_client(endpoint=azure_content_understanding_endpoint) + response = await client.get_analyzer( analyzer_id="prebuilt-documentSearch", ) assert response is not None @@ -403,14 +417,14 @@ async def test_content_analyzers_get(self, contentunderstanding_endpoint: str) - @ContentUnderstandingPreparer() @recorded_by_proxy_async - async def test_content_analyzers_delete(self, contentunderstanding_endpoint: str) -> None: + async def test_content_analyzers_delete(self, azure_content_understanding_endpoint: str) -> None: """ Test Summary: - Create analyzer for deletion test - Delete analyzer - Clean up if deletion failed """ - client: ContentUnderstandingClient = self.create_async_client(endpoint=contentunderstanding_endpoint) + client: ContentUnderstandingClient = self.create_async_client(endpoint=azure_content_understanding_endpoint) analyzer_id = generate_analyzer_id(client, "delete", is_async=True) created_analyzer = False @@ -428,7 +442,7 @@ async def test_content_analyzers_delete(self, contentunderstanding_endpoint: str # Delete the analyzer print(f"Deleting analyzer {analyzer_id}") - response = await client.delete(analyzer_id=analyzer_id) + response = await client.delete_analyzer(analyzer_id=analyzer_id) # Verify the delete response assert response is None @@ -439,7 +453,7 @@ async def test_content_analyzers_delete(self, contentunderstanding_endpoint: str if created_analyzer: print(f"Cleaning up analyzer {analyzer_id} that was not properly deleted") try: - await client.delete(analyzer_id=analyzer_id) + await client.delete_analyzer(analyzer_id=analyzer_id) # Verify deletion (NOTE: check disabled - list too long to execute) # client, analyzer_id # ), f"Failed to delete analyzer {analyzer_id} during cleanup" @@ -450,18 +464,18 @@ async def test_content_analyzers_delete(self, contentunderstanding_endpoint: str elif not created_analyzer: print(f"Analyzer {analyzer_id} was not created, no cleanup needed") - @pytest.mark.skip(reason="TEMPORARILY SKIPPED: List operation is too long - too many analyzers") + # @pytest.mark.skip(reason="TEMPORARILY SKIPPED: List operation is too long - too many analyzers") @ContentUnderstandingPreparer() @recorded_by_proxy_async - async def test_content_analyzers_list(self, contentunderstanding_endpoint: str) -> None: + async def test_content_analyzers_list(self, azure_content_understanding_endpoint: str) -> None: """ Test Summary: - List all available analyzers - Verify list response contains expected prebuilt analyzers - Verify each analyzer has required properties """ - client: ContentUnderstandingClient = self.create_async_client(endpoint=contentunderstanding_endpoint) - response = client.list() + client: ContentUnderstandingClient = self.create_async_client(endpoint=azure_content_understanding_endpoint) + response = client.list_analyzers() result = [r async for r in response] assert len(result) > 0, "Should have at least one analyzer in the list" print(f"Found {len(result)} analyzers") @@ -482,7 +496,7 @@ async def test_content_analyzers_list(self, contentunderstanding_endpoint: str) @ContentUnderstandingPreparer() @recorded_by_proxy_async - async def test_content_analyzers_begin_analyze_url(self, contentunderstanding_endpoint: str) -> None: + async def test_content_analyzers_begin_analyze_url(self, azure_content_understanding_endpoint: str) -> None: """ Test Summary: - Create simple analyzer for URL analysis @@ -493,7 +507,7 @@ async def test_content_analyzers_begin_analyze_url(self, contentunderstanding_en - Verify total_amount field exists and equals 110 - Clean up created analyzer """ - client: ContentUnderstandingClient = self.create_async_client(endpoint=contentunderstanding_endpoint) + client: ContentUnderstandingClient = self.create_async_client(endpoint=azure_content_understanding_endpoint) analyzer_id = generate_analyzer_id(client, "analyze_url", is_async=True) created_analyzer = False @@ -540,7 +554,7 @@ async def test_content_analyzers_begin_analyze_url(self, contentunderstanding_en @ContentUnderstandingPreparer() @recorded_by_proxy_async - async def test_content_analyzers_begin_analyze_binary(self, contentunderstanding_endpoint: str) -> None: + async def test_content_analyzers_begin_analyze_binary(self, azure_content_understanding_endpoint: str) -> None: """ Test Summary: - Create simple analyzer for binary analysis @@ -552,7 +566,7 @@ async def test_content_analyzers_begin_analyze_binary(self, contentunderstanding - Verify total_amount field exists and equals 110 - Clean up created analyzer """ - client: ContentUnderstandingClient = self.create_async_client(endpoint=contentunderstanding_endpoint) + client: ContentUnderstandingClient = self.create_async_client(endpoint=azure_content_understanding_endpoint) analyzer_id = generate_analyzer_id(client, "analyze_binary", is_async=True) created_analyzer = False @@ -598,7 +612,7 @@ async def test_content_analyzers_begin_analyze_binary(self, contentunderstanding @ContentUnderstandingPreparer() @recorded_by_proxy_async - async def test_content_analyzers_get_result_file(self, contentunderstanding_endpoint: str) -> None: + async def test_content_analyzers_get_result_file(self, azure_content_understanding_endpoint: str) -> None: """ Test Summary: - Create marketing video analyzer based on the marketing video template @@ -614,7 +628,7 @@ async def test_content_analyzers_get_result_file(self, contentunderstanding_endp "This test requires live mode to run, as it involves large video files that are too big for test proxy to record" ) return # Skip this test in playback mode as it requires large video files is too big for test proxy to record - client: ContentUnderstandingClient = self.create_async_client(endpoint=contentunderstanding_endpoint) + client: ContentUnderstandingClient = self.create_async_client(endpoint=azure_content_understanding_endpoint) analyzer_id = generate_analyzer_id(client, "get_result_file", is_async=True) created_analyzer = False @@ -654,14 +668,12 @@ async def test_content_analyzers_get_result_file(self, contentunderstanding_endp analysis_result, "test_content_analyzers_get_result_file", test_file_dir, analyzer_id ) - # Extract operation ID for get_result_file test using custom poller's details property - from azure.ai.contentunderstanding.aio.operations._patch import AnalyzeAsyncLROPoller + # Extract operation ID for get_result_file test using custom poller's operation_id property + from azure.ai.contentunderstanding.aio.models._patch import AnalyzeAsyncLROPoller assert isinstance(analysis_poller, AnalyzeAsyncLROPoller), "Should return custom AnalyzeAsyncLROPoller" - details = analysis_poller.details - assert "operation_id" in details, "Details should contain operation_id" - analysis_operation_id = details["operation_id"] + analysis_operation_id = analysis_poller.operation_id assert analysis_operation_id is not None, "Operation ID should not be None" assert len(analysis_operation_id) > 0, "Operation ID should not be empty" print(f"Analysis operation ID: {analysis_operation_id}") @@ -678,16 +690,206 @@ async def test_content_analyzers_get_result_file(self, contentunderstanding_endp # Always clean up the created analyzer, even if the test fails await delete_analyzer_and_assert(client, analyzer_id, created_analyzer) - # @ContentUnderstandingPreparer() - # @recorded_by_proxy_async - # @pytest.mark.skip(reason="GA API addition - to be implemented") + @ContentUnderstandingPreparer() + @recorded_by_proxy_async + async def test_content_analyzers_create_classifier(self, azure_content_understanding_endpoint: str) -> None: + """ + Test Summary: + - Create a classifier with content categories for document categorization + - Verify creation and properties + - Clean up + """ + client: ContentUnderstandingClient = self.create_async_client(endpoint=azure_content_understanding_endpoint) + analyzer_id = generate_analyzer_id(client, "create_classifier", is_async=True) + created_analyzer = False + + # Define content categories for classification + categories = { + "Loan_Application": ContentCategoryDefinition( + description=( + "Documents submitted by individuals or businesses to request funding, " + "typically including personal or business details, financial history, " + "loan amount, purpose, and supporting documentation." + ) + ), + "Invoice": ContentCategoryDefinition( + description=( + "Billing documents issued by sellers or service providers to request " + "payment for goods or services, detailing items, prices, taxes, totals, " + "and payment terms." + ) + ), + "Bank_Statement": ContentCategoryDefinition( + description=( + "Official statements issued by banks that summarize account activity " + "over a period, including deposits, withdrawals, fees, and balances." + ) + ), + } + + # Create classifier configuration + classifier_config = ContentAnalyzerConfig( + return_details=True, + enable_segment=True, # Automatically split and classify multi-document files + content_categories=categories, + ) + + # Create analyzer object + classifier = ContentAnalyzer( + base_analyzer_id="prebuilt-document", + description="Custom classifier for financial document categorization", + config=classifier_config, + models={"completion": "gpt-4.1"}, # Model used for classification + tags={"sample_type": "classifier_demo", "document_type": "financial"}, + ) + + try: + # Create analyzer using the refactored function + poller = await create_analyzer_and_assert_async(client, analyzer_id, classifier) + created_analyzer = True + + # Retrieve the analyzer to verify properties + retrieved_analyzer = await client.get_analyzer(analyzer_id) + assert retrieved_analyzer is not None + assert retrieved_analyzer.analyzer_id == analyzer_id + assert retrieved_analyzer.description == "Custom classifier for financial document categorization" + assert retrieved_analyzer.base_analyzer_id == "prebuilt-document" + assert retrieved_analyzer.status is not None + assert retrieved_analyzer.config is not None + assert retrieved_analyzer.config.return_details is True + assert retrieved_analyzer.config.enable_segment is True + assert retrieved_analyzer.config.content_categories is not None + assert "Loan_Application" in retrieved_analyzer.config.content_categories + assert "Invoice" in retrieved_analyzer.config.content_categories + assert "Bank_Statement" in retrieved_analyzer.config.content_categories + assert retrieved_analyzer.models is not None + assert retrieved_analyzer.models["completion"] == "gpt-4.1" + assert retrieved_analyzer.tags == {"sample_type": "classifier_demo", "document_type": "financial"} + print(f"Classifier {analyzer_id} verified successfully") + + finally: + # Always clean up the created analyzer, even if the test fails + await delete_analyzer_and_assert(client, analyzer_id, created_analyzer) + + @ContentUnderstandingPreparer() + @recorded_by_proxy_async + async def test_content_analyzers_delete_result(self, azure_content_understanding_endpoint: str) -> None: + """ + Test Summary: + - Create simple analyzer for URL analysis + - Begin analysis operation with URL input + - Wait for analysis completion + - Verify result accessibility before deletion + - Delete the analysis result + - Verify deletion by confirming the result is no longer accessible (404 error) + - Clean up created analyzer + """ + client: ContentUnderstandingClient = self.create_async_client(endpoint=azure_content_understanding_endpoint) + analyzer_id = generate_analyzer_id(client, "delete_result", is_async=True) + created_analyzer = False + + # Create a simple analyzer for URL analysis + content_analyzer = new_simple_content_analyzer_object( + analyzer_id=analyzer_id, + description=f"test analyzer for delete result: {analyzer_id}", + tags={"test_type": "delete_result"}, + ) + + try: + # Create analyzer using the refactored function + poller = await create_analyzer_and_assert_async(client, analyzer_id, content_analyzer) + created_analyzer = True + + # Use the provided URL for the invoice PDF + invoice_url = "https://github.com/Azure-Samples/azure-ai-content-understanding-python/raw/refs/heads/main/data/invoice.pdf" + + print(f"Starting URL analysis with analyzer {analyzer_id}") + + # Begin analysis operation with URL + analysis_poller = await client.begin_analyze(analyzer_id=analyzer_id, inputs=[AnalyzeInput(url=invoice_url)]) + assert_poller_properties(analysis_poller, "Analysis poller") + + # Wait for analysis completion + print(f"Waiting for analysis completion") + analysis_result = await analysis_poller.result() + print(f" Analysis completed") + + # Get operation ID + operation_id = analysis_poller.operation_id + assert operation_id is not None + + # Verify result accessibility before deletion + print(f"Verifying result accessibility before deletion...") + result_before = await client._get_result(operation_id=operation_id) # type: ignore[attr-defined] + assert result_before is not None + print(f"Result accessible before deletion (status: {result_before.status})") + + # Delete the result + print(f"Deleting result for operation {operation_id}") + await client.delete_result(operation_id=operation_id) + print(f"Result deleted successfully") + + # Verify deletion by attempting to access the result again + print(f"Verifying deletion...") + print(f" Attempting to access the deleted result...") + with pytest.raises(ResourceNotFoundError): + await client._get_result(operation_id=operation_id) # type: ignore[attr-defined] + print(f"Verification successful: Result properly deleted") + print(f" ✓ Confirmed: Result is no longer accessible as expected") + + finally: + # Always clean up the created analyzer, even if the test fails + await delete_analyzer_and_assert(client, analyzer_id, created_analyzer) + + @ContentUnderstandingPreparer() + @recorded_by_proxy_async + async def test_content_analyzers_get_defaults(self, azure_content_understanding_endpoint: str) -> None: + """ + Test Summary: + - Get default model deployments + - Verify response structure + """ + client: ContentUnderstandingClient = self.create_async_client(endpoint=azure_content_understanding_endpoint) + defaults = await client.get_defaults() + assert defaults is not None + # We can't assert specific values as they depend on the resource configuration, + # but we can check if the object has the expected attribute + assert hasattr(defaults, "model_deployments") + print(f"Defaults retrieved: {defaults}") + + @ContentUnderstandingPreparer() + @recorded_by_proxy_async + async def test_content_analyzers_update_defaults(self, azure_content_understanding_endpoint: str) -> None: + """ + Test Summary: + - Get current defaults + - Update defaults with the same values (to test the API without changing config) + - Verify update success + """ + client: ContentUnderstandingClient = self.create_async_client(endpoint=azure_content_understanding_endpoint) + + # Get current defaults + defaults = await client.get_defaults() + assert defaults is not None + + if defaults.model_deployments: + print(f"Current defaults: {defaults.model_deployments}") + + # Update with same values + updated_defaults = await client.update_defaults(model_deployments=defaults.model_deployments) + + assert updated_defaults is not None + assert updated_defaults.model_deployments == defaults.model_deployments + print("Defaults updated successfully") + else: + print("No defaults configured, skipping update test to avoid setting invalid values") # @ContentUnderstandingPreparer() # @recorded_by_proxy_async # @pytest.mark.skip(reason="GA API addition - to be implemented") -# async def test_content_analyzers_begin_analyze(self, contentunderstanding_endpoint): -# client = self.create_async_client(endpoint=contentunderstanding_endpoint) +# async def test_content_analyzers_begin_analyze(self, azure_content_understanding_endpoint): +# client = self.create_async_client(endpoint=azure_content_understanding_endpoint) # response = await ( # await client.begin_analyze( # analyzer_id="str", @@ -710,16 +912,11 @@ async def test_content_analyzers_get_result_file(self, contentunderstanding_endp # ... -# @ContentUnderstandingPreparer() -# @recorded_by_proxy_async -# @pytest.mark.skip(reason="GA API addition - to be implemented") - - # @ContentUnderstandingPreparer() # @recorded_by_proxy_async # @pytest.mark.skip(reason="GA API addition - to be implemented") -# async def test_content_analyzers_begin_copy(self, contentunderstanding_endpoint): -# client = self.create_async_client(endpoint=contentunderstanding_endpoint) +# async def test_content_analyzers_begin_copy(self, azure_content_understanding_endpoint): +# client = self.create_async_client(endpoint=azure_content_understanding_endpoint) # response = await ( # await client.begin_copy( # analyzer_id="str", @@ -732,16 +929,11 @@ async def test_content_analyzers_get_result_file(self, contentunderstanding_endp # ... -# @ContentUnderstandingPreparer() -# @recorded_by_proxy_async -# @pytest.mark.skip(reason="GA API addition - to be implemented") - - # @ContentUnderstandingPreparer() # @recorded_by_proxy_async # @pytest.mark.skip(reason="GA API addition - to be implemented") -# async def test_content_analyzers_begin_create_or_replace(self, contentunderstanding_endpoint): -# client = self.create_async_client(endpoint=contentunderstanding_endpoint) +# async def test_content_analyzers_begin_create_or_replace(self, azure_content_understanding_endpoint): +# client = self.create_async_client(endpoint=azure_content_understanding_endpoint) # response = await ( # await client.begin_create_or_replace( # analyzer_id="str", @@ -818,50 +1010,11 @@ async def test_content_analyzers_get_result_file(self, contentunderstanding_endp # ... -# @ContentUnderstandingPreparer() -# @recorded_by_proxy_async -# @pytest.mark.skip(reason="GA API addition - to be implemented") - - -# @ContentUnderstandingPreparer() -# @recorded_by_proxy_async -# @pytest.mark.skip(reason="GA API addition - to be implemented") -# async def test_content_analyzers_delete_result(self, contentunderstanding_endpoint): -# client = self.create_async_client(endpoint=contentunderstanding_endpoint) -# response = await client.delete_result( -# operation_id="str", -# ) - -# please add some check logic here by yourself -# ... - - -# @ContentUnderstandingPreparer() -# @recorded_by_proxy_async -# @pytest.mark.skip(reason="GA API addition - to be implemented") - - -# @ContentUnderstandingPreparer() -# @recorded_by_proxy_async -# @pytest.mark.skip(reason="GA API addition - to be implemented") -# async def test_content_analyzers_get_defaults(self, contentunderstanding_endpoint): -# client = self.create_async_client(endpoint=contentunderstanding_endpoint) -# response = await client.get_defaults() - -# please add some check logic here by yourself -# ... - - -# @ContentUnderstandingPreparer() -# @recorded_by_proxy_async -# @pytest.mark.skip(reason="GA API addition - to be implemented") - - # @ContentUnderstandingPreparer() # @recorded_by_proxy_async # @pytest.mark.skip(reason="GA API addition - to be implemented") -# async def test_content_analyzers_get_operation_status(self, contentunderstanding_endpoint): -# client = self.create_async_client(endpoint=contentunderstanding_endpoint) +# async def test_content_analyzers_get_operation_status(self, azure_content_understanding_endpoint): +# client = self.create_async_client(endpoint=azure_content_understanding_endpoint) # response = await client.get_operation_status( # analyzer_id="str", # operation_id="str", @@ -871,16 +1024,11 @@ async def test_content_analyzers_get_result_file(self, contentunderstanding_endp # ... -# @ContentUnderstandingPreparer() -# @recorded_by_proxy_async -# @pytest.mark.skip(reason="GA API addition - to be implemented") - - # @ContentUnderstandingPreparer() # @recorded_by_proxy_async # @pytest.mark.skip(reason="GA API addition - to be implemented") -# async def test_content_analyzers_grant_copy_authorization(self, contentunderstanding_endpoint): -# client = self.create_async_client(endpoint=contentunderstanding_endpoint) +# async def test_content_analyzers_grant_copy_authorization(self, azure_content_understanding_endpoint): +# client = self.create_async_client(endpoint=azure_content_understanding_endpoint) # response = await client.grant_copy_authorization( # analyzer_id="str", # body={"targetAzureResourceId": "str", "targetRegion": "str"}, @@ -889,20 +1037,3 @@ async def test_content_analyzers_get_result_file(self, contentunderstanding_endp # please add some check logic here by yourself # ... - - -# @ContentUnderstandingPreparer() -# @recorded_by_proxy_async -# @pytest.mark.skip(reason="GA API addition - to be implemented") - - -# @ContentUnderstandingPreparer() -# @recorded_by_proxy_async -# @pytest.mark.skip(reason="GA API addition - to be implemented") -# async def test_content_analyzers_update_defaults(self, contentunderstanding_endpoint): -# client = self.create_async_client(endpoint=contentunderstanding_endpoint) -# response = await client.update_defaults( -# body={"modelDeployments": {}}, -# ) -# please add some check logic here by yourself -# diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/tests/test_helpers.py b/sdk/contentunderstanding/azure-ai-contentunderstanding/tests/test_helpers.py index f56685e9511a..d33cb3256ab8 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/tests/test_helpers.py +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/tests/test_helpers.py @@ -7,12 +7,9 @@ # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- import os -import uuid -import re import json from datetime import datetime -from typing import Optional, Dict, Any, List -import sys +from typing import Optional, Dict, Any from azure.ai.contentunderstanding.models import ( ContentAnalyzer, ContentAnalyzerConfig, @@ -21,8 +18,6 @@ ) from azure.ai.contentunderstanding.models import GenerationMethod, ContentFieldType, ProcessingLocation -from devtools_testutils import is_live, is_live_and_not_recording - def generate_analyzer_id(client, test_name: str, is_async: bool = False) -> str: """Generate a unique analyzer ID using test name. diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/tests/testpreparer.py b/sdk/contentunderstanding/azure-ai-contentunderstanding/tests/testpreparer.py index e0095d569f6e..b2f33f285c45 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/tests/testpreparer.py +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/tests/testpreparer.py @@ -30,7 +30,7 @@ def get_content_understanding_credential(): class ContentUnderstandingClientTestBase(AzureRecordedTestCase): def create_client(self, endpoint: str) -> ContentUnderstandingClient: - credential = self.get_credential(ContentUnderstandingClient, is_async=False) + credential = get_content_understanding_credential() return cast( ContentUnderstandingClient, self.create_client_from_credential( @@ -43,6 +43,6 @@ def create_client(self, endpoint: str) -> ContentUnderstandingClient: ContentUnderstandingPreparer = functools.partial( PowerShellPreparer, - "contentunderstanding", - contentunderstanding_endpoint="https://fake_contentunderstanding_endpoint.services.ai.azure.com/", + "azure_content_understanding", + azure_content_understanding_endpoint="https://fake_contentunderstanding_endpoint.services.ai.azure.com/", ) diff --git a/sdk/contentunderstanding/azure-ai-contentunderstanding/tests/testpreparer_async.py b/sdk/contentunderstanding/azure-ai-contentunderstanding/tests/testpreparer_async.py index 6de1d243beba..6992a1ff3b83 100644 --- a/sdk/contentunderstanding/azure-ai-contentunderstanding/tests/testpreparer_async.py +++ b/sdk/contentunderstanding/azure-ai-contentunderstanding/tests/testpreparer_async.py @@ -9,7 +9,6 @@ from typing import cast from azure.ai.contentunderstanding.aio import ContentUnderstandingClient from azure.core.credentials import AzureKeyCredential -from azure.identity import DefaultAzureCredential from azure.identity.aio import DefaultAzureCredential as AsyncDefaultAzureCredential from devtools_testutils import AzureRecordedTestCase, PowerShellPreparer import functools @@ -18,7 +17,7 @@ def get_content_understanding_credential_async(): """Get the appropriate async credential for Content Understanding. - Checks for AZURE_CONTENT_UNDERSTANDING_KEY first, then falls back to DefaultAzureCredential. + Checks for AZURE_CONTENT_UNDERSTANDING_KEY first, then falls back to AsyncDefaultAzureCredential. """ key = os.getenv("AZURE_CONTENT_UNDERSTANDING_KEY") @@ -31,7 +30,7 @@ def get_content_understanding_credential_async(): class ContentUnderstandingClientTestBaseAsync(AzureRecordedTestCase): def create_async_client(self, endpoint: str) -> ContentUnderstandingClient: - credential = self.get_credential(ContentUnderstandingClient, is_async=True) + credential = get_content_understanding_credential_async() return cast( ContentUnderstandingClient, self.create_client_from_credential( @@ -45,6 +44,6 @@ def create_async_client(self, endpoint: str) -> ContentUnderstandingClient: ContentUnderstandingPreparer = functools.partial( PowerShellPreparer, - "contentunderstanding", - contentunderstanding_endpoint="https://fake_contentunderstanding_endpoint.services.ai.azure.com/", + "azure_content_understanding", + azure_content_understanding_endpoint="https://fake_contentunderstanding_endpoint.services.ai.azure.com/", )