Skip to content

Commit 5066ef7

Browse files
authored
Image Analysis SDK - updates for Beta 3 release (#36468)
Re-emit from TypeSpec. TypeSpec changes include adding Entra ID auth and rename of some input argument names in the operation methods (instead of image_content, call it image_url and image_data, depending on the method). There is no breaking change in the APIs, since the auto generated operation methods are internal. Public operation methods (handwritten in _patch.py) have not changed, and already include image_url and image_data input arguments in the appropriate overloads. Add two samples with Entra ID auth, using DefaultAzureCredential. Add two tests with Entra ID auth, using get_credential from the test recording library. Updated package, samples and test README files to mention Entra ID related changes. Some minor fixes in sample function names.
1 parent 43a2bec commit 5066ef7

26 files changed

+712
-629
lines changed

sdk/vision/azure-ai-vision-imageanalysis/CHANGELOG.md

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,10 @@
11
# Release History
22

3-
## 1.0.0b3 (Unreleased)
3+
## 1.0.0b3 (2024-07-26)
44

55
### Features Added
66

7-
### Breaking Changes
8-
9-
### Bugs Fixed
10-
11-
### Other Changes
7+
Added support for Entra ID authentication.
128

139
## 1.0.0b2 (2024-02-09)
1410

sdk/vision/azure-ai-vision-imageanalysis/README.md

Lines changed: 55 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -30,19 +30,20 @@ Use the Image Analysis client library to:
3030
```bash
3131
pip install azure-ai-vision-imageanalysis
3232
```
33-
### Set environment variables
3433

35-
To authenticate the `ImageAnalysisClient`, you will need the endpoint and key from your Azure Computer Vision resource in the [Azure Portal](https://portal.azure.com). The code snippet below assumes these values are stored in environment variables:
34+
### Create and authenticate the client
35+
36+
#### Using API key
37+
38+
To authenticate the `ImageAnalysisClient` using api key, you will need the endpoint and api key from your Azure Computer Vision resource in the [Azure Portal](https://portal.azure.com). The code snippet below assumes these values are stored in environment variables:
3639

3740
* Set the environment variable `VISION_ENDPOINT` to the endpoint URL. It has the form `https://your-resource-name.cognitiveservices.azure.com`, where `your-resource-name` is your unique Azure Computer Vision resource name.
3841

3942
* Set the environment variable `VISION_KEY` to the key. The key is a 32-character Hexadecimal number.
4043

41-
Note that the client library does not directly read these environment variable at run time. The endpoint and key must be provided to the constructor of `ImageAnalysisClient` in your code. The code snippet below reads environment variables to promote the practice of not hard-coding secrets in your source code.
42-
43-
### Create and authenticate the client
44+
>Note: The client library does not directly read these environment variable at run time. The endpoint and key must be provided to the constructor of `ImageAnalysisClient` in your code. The code snippet below reads environment variables to promote the practice of not hard-coding secrets in your source code.
4445
45-
Once you define the environment variables, this Python code will create and authenticate a synchronous `ImageAnalysisClient`:
46+
Once you define the environment variables, this Python code will create and authenticate a synchronous `ImageAnalysisClient` using key:
4647

4748
<!-- SNIPPET:sample_caption_image_file.create_client -->
4849

@@ -62,7 +63,8 @@ except KeyError:
6263
print("Set them before running this sample.")
6364
exit()
6465

65-
# Create an Image Analysis client for synchronous operations
66+
# Create an Image Analysis client for synchronous operations,
67+
# using API key authentication
6668
client = ImageAnalysisClient(
6769
endpoint=endpoint,
6870
credential=AzureKeyCredential(key)
@@ -71,16 +73,58 @@ client = ImageAnalysisClient(
7173

7274
<!-- END SNIPPET -->
7375

76+
#### Using Entra ID
77+
78+
You can also authenticate `ImageAnalysisClient` with [Entra ID](https://learn.microsoft.com/entra/fundamentals/whatis) using the [Azure Identity library](https://learn.microsoft.com/python/api/overview/azure/identity-readme?view=azure-python). To use the [DefaultAzureCredential](https://learn.microsoft.com/python/api/azure-identity/azure.identity.defaultazurecredential?view=azure-python) provider shown below, or other credential providers in this library, install the `azure-identity` package:
79+
80+
```bash
81+
pip install azure.identity
82+
```
83+
84+
Assuming you defined the environment variable `VISION_ENDPOINT` mentioned above, this Python code will create and authenticate a synchronous `ImageAnalysisClient` using Entra ID:
85+
86+
<!-- SNIPPET:sample_caption_image_file_entra_id_auth.create_client -->
87+
88+
```python
89+
import os
90+
from azure.ai.vision.imageanalysis import ImageAnalysisClient
91+
from azure.ai.vision.imageanalysis.models import VisualFeatures
92+
from azure.identity import DefaultAzureCredential
93+
94+
# Set the value of your computer vision endpoint as environment variable:
95+
try:
96+
endpoint = os.environ["VISION_ENDPOINT"]
97+
except KeyError:
98+
print("Missing environment variable 'VISION_ENDPOINT'.")
99+
print("Set it before running this sample.")
100+
exit()
101+
102+
# Create an Image Analysis client for synchronous operations,
103+
# using Entra ID authentication
104+
client = ImageAnalysisClient(
105+
endpoint=endpoint,
106+
credential=DefaultAzureCredential(exclude_interactive_browser_credential=False),
107+
)
108+
```
109+
110+
<!-- END SNIPPET -->
111+
112+
### Creating an asynchronous client
113+
74114
A synchronous client supports synchronous analysis methods, meaning they will block until the service responds with analysis results. The code snippets below all use synchronous methods because it's easier for a getting-started guide. The SDK offers equivalent asynchronous APIs which are often preferred. To create an asynchronous client, do the following:
75115

76-
* Update the above code to import `ImageAnalysisClient` from the `aio` namespace:
77-
```python
78-
from azure.ai.vision.imageanalysis.aio import ImageAnalysisClient
79-
```
80116
* Install the additional package [aiohttp](https://pypi.org/project/aiohttp/):
81117
```bash
82118
pip install aiohttp
83119
```
120+
* Update the above code to import `ImageAnalysisClient` from the `azure.ai.vision.imageanalysis.aio`:
121+
```python
122+
from azure.ai.vision.imageanalysis.aio import ImageAnalysisClient
123+
```
124+
* If you are using Entra ID authentication with `DefaultAzureCredential`, update the above code to import `DefaultAzureCredential` from `azure.identity.aio`:
125+
```python
126+
from azure.identity.aio import DefaultAzureCredential
127+
```
84128

85129
## Key concepts
86130

sdk/vision/azure-ai-vision-imageanalysis/assets.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
"AssetsRepo": "Azure/azure-sdk-assets",
33
"AssetsRepoPrefixPath": "python",
44
"TagPrefix": "python/vision/azure-ai-vision-imageanalysis",
5-
"Tag": "python/vision/azure-ai-vision-imageanalysis_c2497c4b3c"
5+
"Tag": "python/vision/azure-ai-vision-imageanalysis_d907590ef4"
66
}

sdk/vision/azure-ai-vision-imageanalysis/azure/ai/vision/imageanalysis/_client.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
# --------------------------------------------------------------------------
88

99
from copy import deepcopy
10-
from typing import Any
10+
from typing import Any, TYPE_CHECKING, Union
11+
from typing_extensions import Self
1112

1213
from azure.core import PipelineClient
1314
from azure.core.credentials import AzureKeyCredential
@@ -18,21 +19,27 @@
1819
from ._operations import ImageAnalysisClientOperationsMixin
1920
from ._serialization import Deserializer, Serializer
2021

22+
if TYPE_CHECKING:
23+
# pylint: disable=unused-import,ungrouped-imports
24+
from azure.core.credentials import TokenCredential
25+
2126

2227
class ImageAnalysisClient(ImageAnalysisClientOperationsMixin): # pylint: disable=client-accepts-api-version-keyword
2328
"""ImageAnalysisClient.
2429
2530
:param endpoint: Azure AI Computer Vision endpoint (protocol and hostname, for example:
2631
https://:code:`<resource-name>`.cognitiveservices.azure.com). Required.
2732
:type endpoint: str
28-
:param credential: Credential needed for the client to connect to Azure. Required.
29-
:type credential: ~azure.core.credentials.AzureKeyCredential
33+
:param credential: Credential used to authenticate requests to the service. Is either a
34+
AzureKeyCredential type or a TokenCredential type. Required.
35+
:type credential: ~azure.core.credentials.AzureKeyCredential or
36+
~azure.core.credentials.TokenCredential
3037
:keyword api_version: The API version to use for this operation. Default value is "2023-10-01".
3138
Note that overriding this default value may result in unsupported behavior.
3239
:paramtype api_version: str
3340
"""
3441

35-
def __init__(self, endpoint: str, credential: AzureKeyCredential, **kwargs: Any) -> None:
42+
def __init__(self, endpoint: str, credential: Union[AzureKeyCredential, "TokenCredential"], **kwargs: Any) -> None:
3643
_endpoint = "{endpoint}/computervision"
3744
self._config = ImageAnalysisClientConfiguration(endpoint=endpoint, credential=credential, **kwargs)
3845
_policies = kwargs.pop("policies", None)
@@ -87,7 +94,7 @@ def send_request(self, request: HttpRequest, *, stream: bool = False, **kwargs:
8794
def close(self) -> None:
8895
self._client.close()
8996

90-
def __enter__(self) -> "ImageAnalysisClient":
97+
def __enter__(self) -> Self:
9198
self._client.__enter__()
9299
return self
93100

sdk/vision/azure-ai-vision-imageanalysis/azure/ai/vision/imageanalysis/_configuration.py

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,17 @@
66
# Changes may cause incorrect behavior and will be lost if the code is regenerated.
77
# --------------------------------------------------------------------------
88

9-
from typing import Any
9+
from typing import Any, TYPE_CHECKING, Union
1010

1111
from azure.core.credentials import AzureKeyCredential
1212
from azure.core.pipeline import policies
1313

1414
from ._version import VERSION
1515

16+
if TYPE_CHECKING:
17+
# pylint: disable=unused-import,ungrouped-imports
18+
from azure.core.credentials import TokenCredential
19+
1620

1721
class ImageAnalysisClientConfiguration: # pylint: disable=too-many-instance-attributes,name-too-long
1822
"""Configuration for ImageAnalysisClient.
@@ -23,14 +27,16 @@ class ImageAnalysisClientConfiguration: # pylint: disable=too-many-instance-att
2327
:param endpoint: Azure AI Computer Vision endpoint (protocol and hostname, for example:
2428
https://:code:`<resource-name>`.cognitiveservices.azure.com). Required.
2529
:type endpoint: str
26-
:param credential: Credential needed for the client to connect to Azure. Required.
27-
:type credential: ~azure.core.credentials.AzureKeyCredential
30+
:param credential: Credential used to authenticate requests to the service. Is either a
31+
AzureKeyCredential type or a TokenCredential type. Required.
32+
:type credential: ~azure.core.credentials.AzureKeyCredential or
33+
~azure.core.credentials.TokenCredential
2834
:keyword api_version: The API version to use for this operation. Default value is "2023-10-01".
2935
Note that overriding this default value may result in unsupported behavior.
3036
:paramtype api_version: str
3137
"""
3238

33-
def __init__(self, endpoint: str, credential: AzureKeyCredential, **kwargs: Any) -> None:
39+
def __init__(self, endpoint: str, credential: Union[AzureKeyCredential, "TokenCredential"], **kwargs: Any) -> None:
3440
api_version: str = kwargs.pop("api_version", "2023-10-01")
3541

3642
if endpoint is None:
@@ -41,10 +47,18 @@ def __init__(self, endpoint: str, credential: AzureKeyCredential, **kwargs: Any)
4147
self.endpoint = endpoint
4248
self.credential = credential
4349
self.api_version = api_version
50+
self.credential_scopes = kwargs.pop("credential_scopes", ["https://cognitiveservices.azure.com/.default"])
4451
kwargs.setdefault("sdk_moniker", "ai-vision-imageanalysis/{}".format(VERSION))
4552
self.polling_interval = kwargs.get("polling_interval", 30)
4653
self._configure(**kwargs)
4754

55+
def _infer_policy(self, **kwargs):
56+
if isinstance(self.credential, AzureKeyCredential):
57+
return policies.AzureKeyCredentialPolicy(self.credential, "Ocp-Apim-Subscription-Key", **kwargs)
58+
if hasattr(self.credential, "get_token"):
59+
return policies.BearerTokenCredentialPolicy(self.credential, *self.credential_scopes, **kwargs)
60+
raise TypeError(f"Unsupported credential: {self.credential}")
61+
4862
def _configure(self, **kwargs: Any) -> None:
4963
self.user_agent_policy = kwargs.get("user_agent_policy") or policies.UserAgentPolicy(**kwargs)
5064
self.headers_policy = kwargs.get("headers_policy") or policies.HeadersPolicy(**kwargs)
@@ -56,6 +70,4 @@ def _configure(self, **kwargs: Any) -> None:
5670
self.retry_policy = kwargs.get("retry_policy") or policies.RetryPolicy(**kwargs)
5771
self.authentication_policy = kwargs.get("authentication_policy")
5872
if self.credential and not self.authentication_policy:
59-
self.authentication_policy = policies.AzureKeyCredentialPolicy(
60-
self.credential, "Ocp-Apim-Subscription-Key", **kwargs
61-
)
73+
self.authentication_policy = self._infer_policy(**kwargs)

0 commit comments

Comments
 (0)