Skip to content

Commit

Permalink
Image Analysis SDK - updates for Beta 3 release (Azure#36468)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
dargilco authored Jul 23, 2024
1 parent 43a2bec commit 5066ef7
Show file tree
Hide file tree
Showing 26 changed files with 712 additions and 629 deletions.
8 changes: 2 additions & 6 deletions sdk/vision/azure-ai-vision-imageanalysis/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
# Release History

## 1.0.0b3 (Unreleased)
## 1.0.0b3 (2024-07-26)

### Features Added

### Breaking Changes

### Bugs Fixed

### Other Changes
Added support for Entra ID authentication.

## 1.0.0b2 (2024-02-09)

Expand Down
66 changes: 55 additions & 11 deletions sdk/vision/azure-ai-vision-imageanalysis/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,19 +30,20 @@ Use the Image Analysis client library to:
```bash
pip install azure-ai-vision-imageanalysis
```
### Set environment variables

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:
### Create and authenticate the client

#### Using API key

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:

* 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.

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

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.

### Create and authenticate the client
>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.
Once you define the environment variables, this Python code will create and authenticate a synchronous `ImageAnalysisClient`:
Once you define the environment variables, this Python code will create and authenticate a synchronous `ImageAnalysisClient` using key:

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

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

# Create an Image Analysis client for synchronous operations
# Create an Image Analysis client for synchronous operations,
# using API key authentication
client = ImageAnalysisClient(
endpoint=endpoint,
credential=AzureKeyCredential(key)
Expand All @@ -71,16 +73,58 @@ client = ImageAnalysisClient(

<!-- END SNIPPET -->

#### Using Entra ID

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:

```bash
pip install azure.identity
```

Assuming you defined the environment variable `VISION_ENDPOINT` mentioned above, this Python code will create and authenticate a synchronous `ImageAnalysisClient` using Entra ID:

<!-- SNIPPET:sample_caption_image_file_entra_id_auth.create_client -->

```python
import os
from azure.ai.vision.imageanalysis import ImageAnalysisClient
from azure.ai.vision.imageanalysis.models import VisualFeatures
from azure.identity import DefaultAzureCredential

# Set the value of your computer vision endpoint as environment variable:
try:
endpoint = os.environ["VISION_ENDPOINT"]
except KeyError:
print("Missing environment variable 'VISION_ENDPOINT'.")
print("Set it before running this sample.")
exit()

# Create an Image Analysis client for synchronous operations,
# using Entra ID authentication
client = ImageAnalysisClient(
endpoint=endpoint,
credential=DefaultAzureCredential(exclude_interactive_browser_credential=False),
)
```

<!-- END SNIPPET -->

### Creating an asynchronous client

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:

* Update the above code to import `ImageAnalysisClient` from the `aio` namespace:
```python
from azure.ai.vision.imageanalysis.aio import ImageAnalysisClient
```
* Install the additional package [aiohttp](https://pypi.org/project/aiohttp/):
```bash
pip install aiohttp
```
* Update the above code to import `ImageAnalysisClient` from the `azure.ai.vision.imageanalysis.aio`:
```python
from azure.ai.vision.imageanalysis.aio import ImageAnalysisClient
```
* If you are using Entra ID authentication with `DefaultAzureCredential`, update the above code to import `DefaultAzureCredential` from `azure.identity.aio`:
```python
from azure.identity.aio import DefaultAzureCredential
```

## Key concepts

Expand Down
2 changes: 1 addition & 1 deletion sdk/vision/azure-ai-vision-imageanalysis/assets.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
"AssetsRepo": "Azure/azure-sdk-assets",
"AssetsRepoPrefixPath": "python",
"TagPrefix": "python/vision/azure-ai-vision-imageanalysis",
"Tag": "python/vision/azure-ai-vision-imageanalysis_c2497c4b3c"
"Tag": "python/vision/azure-ai-vision-imageanalysis_d907590ef4"
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
# --------------------------------------------------------------------------

from copy import deepcopy
from typing import Any
from typing import Any, TYPE_CHECKING, Union
from typing_extensions import Self

from azure.core import PipelineClient
from azure.core.credentials import AzureKeyCredential
Expand All @@ -18,21 +19,27 @@
from ._operations import ImageAnalysisClientOperationsMixin
from ._serialization import Deserializer, Serializer

if TYPE_CHECKING:
# pylint: disable=unused-import,ungrouped-imports
from azure.core.credentials import TokenCredential


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

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

def __enter__(self) -> "ImageAnalysisClient":
def __enter__(self) -> Self:
self._client.__enter__()
return self

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,17 @@
# Changes may cause incorrect behavior and will be lost if the code is regenerated.
# --------------------------------------------------------------------------

from typing import Any
from typing import Any, TYPE_CHECKING, Union

from azure.core.credentials import AzureKeyCredential
from azure.core.pipeline import policies

from ._version import VERSION

if TYPE_CHECKING:
# pylint: disable=unused-import,ungrouped-imports
from azure.core.credentials import TokenCredential


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

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

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

def _infer_policy(self, **kwargs):
if isinstance(self.credential, AzureKeyCredential):
return policies.AzureKeyCredentialPolicy(self.credential, "Ocp-Apim-Subscription-Key", **kwargs)
if hasattr(self.credential, "get_token"):
return policies.BearerTokenCredentialPolicy(self.credential, *self.credential_scopes, **kwargs)
raise TypeError(f"Unsupported credential: {self.credential}")

def _configure(self, **kwargs: Any) -> None:
self.user_agent_policy = kwargs.get("user_agent_policy") or policies.UserAgentPolicy(**kwargs)
self.headers_policy = kwargs.get("headers_policy") or policies.HeadersPolicy(**kwargs)
Expand All @@ -56,6 +70,4 @@ def _configure(self, **kwargs: Any) -> None:
self.retry_policy = kwargs.get("retry_policy") or policies.RetryPolicy(**kwargs)
self.authentication_policy = kwargs.get("authentication_policy")
if self.credential and not self.authentication_policy:
self.authentication_policy = policies.AzureKeyCredentialPolicy(
self.credential, "Ocp-Apim-Subscription-Key", **kwargs
)
self.authentication_policy = self._infer_policy(**kwargs)
Loading

0 comments on commit 5066ef7

Please sign in to comment.