Skip to content

Commit cb05d56

Browse files
committed
updated patch
1 parent 5b01951 commit cb05d56

File tree

4 files changed

+631
-9
lines changed

4 files changed

+631
-9
lines changed

sdk/cognitivelanguage/azure-ai-language-conversations/azure/ai/language/conversations/_patch.py

Lines changed: 299 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
# pylint: disable=line-too-long,useless-suppression
12
# coding=utf-8
23
# --------------------------------------------------------------------------
34
# Copyright (c) Microsoft Corporation. All rights reserved.
@@ -7,9 +8,303 @@
78
89
Follow our quickstart for examples: https://aka.ms/azsdk/python/dpcodegen/python/customize
910
"""
11+
import json
12+
from typing import Any, Callable, Dict, IO, Mapping, Optional, TypeVar, Union, cast, overload, Generic, TYPE_CHECKING
13+
from collections.abc import MutableMapping # pylint:disable=import-error
14+
from urllib.parse import urlparse
15+
from azure.core.exceptions import (
16+
HttpResponseError,
17+
)
18+
from azure.core.pipeline import PipelineResponse
19+
from azure.core.polling import LROPoller, NoPolling, PollingMethod
20+
from azure.core.polling.base_polling import LROBasePolling
21+
from azure.core.rest import HttpRequest, HttpResponse
22+
from azure.core.tracing.decorator import distributed_trace
23+
from azure.core.utils import case_insensitive_dict
24+
from azure.core.credentials import AzureKeyCredential
25+
from azure.core.paging import ItemPaged
26+
from ._client import ConversationAnalysisClient as AnalysisClientGenerated
27+
from .models import AnalyzeConversationOperationInput, AnalyzeConversationOperationState, ConversationActions
28+
from ._utils.serialization import Serializer
1029

30+
from ._validation import api_version_validation
1131

12-
__all__: list[str] = [] # Add all objects you want publicly available to users at this package level
32+
if TYPE_CHECKING:
33+
from azure.core.credentials import TokenCredential
34+
35+
JSON = MutableMapping[str, Any]
36+
T = TypeVar("T")
37+
ClsType = Optional[Callable[[PipelineResponse[HttpRequest, HttpResponse], T, Dict[str, Any]], Any]]
38+
39+
_SERIALIZER = Serializer()
40+
_SERIALIZER.client_side_validation = False
41+
42+
43+
def _parse_operation_id(op_loc: Optional[str]) -> Optional[str]:
44+
"""Extract the operation ID from an Operation-Location URL.
45+
46+
:param op_loc: The ``Operation-Location`` header value or URL to parse.
47+
If ``None`` or malformed, no ID can be extracted.
48+
:type op_loc: Optional[str]
49+
:return: The trailing path segment as the operation ID, or ``None`` if not found.
50+
:rtype: Optional[str]
51+
"""
52+
if not op_loc:
53+
return None
54+
path = urlparse(op_loc).path.rstrip("/")
55+
if "/" not in path:
56+
return None
57+
return path.rsplit("/", 1)[-1]
58+
59+
60+
PollingReturnType_co = TypeVar("PollingReturnType_co", covariant=True)
61+
62+
63+
class AnalyzeConversationLROPoller(LROPoller[PollingReturnType_co], Generic[PollingReturnType_co]):
64+
"""Custom poller that returns PollingReturnType_co and exposes operation metadata."""
65+
66+
def __init__(self, *args: Any, **kwargs: Any) -> None:
67+
super().__init__(*args, **kwargs)
68+
# populated by the deserialization callback in your begin_* method
69+
self._last_state: Optional["AnalyzeConversationOperationState"] = None
70+
71+
def _record_state_for_details(self, state: "AnalyzeConversationOperationState") -> None:
72+
"""Internal: update the state used by ``.details``.
73+
74+
:param state: The latest operation state to expose via ``details``.
75+
:type state: AnalyzeConversationOperationState
76+
:return: None
77+
:rtype: None
78+
"""
79+
self._last_state = state
80+
81+
@property
82+
def details(self) -> Mapping[str, Any]:
83+
"""Metadata associated with the long-running operation.
84+
85+
:return: A mapping with keys like ``operation_id`` and, when available,
86+
``status``, ``job_id``, ``display_name``, ``created_date_time``,
87+
``last_updated_date_time``, ``expiration_date_time``, ``statistics``,
88+
``errors``, and ``next_link``.
89+
:rtype: Mapping[str, Any]
90+
"""
91+
try:
92+
headers = getattr(self.polling_method(), "_initial_response").http_response.headers # type: ignore[attr-defined]
93+
op_loc = headers.get("Operation-Location") or headers.get("operation-location")
94+
except (AttributeError, TypeError):
95+
# missing attributes in the chain, or headers is not a mapping
96+
op_loc = None
97+
98+
op_id = _parse_operation_id(op_loc)
99+
info: Dict[str, Any] = {"operation_id": op_id}
100+
101+
# Merge fields from the final state (if available)
102+
if self._last_state is not None:
103+
s = self._last_state
104+
info.update(
105+
{
106+
"status": s.status,
107+
"job_id": s.job_id,
108+
"display_name": s.display_name,
109+
"created_date_time": s.created_date_time,
110+
"last_updated_date_time": s.last_updated_date_time,
111+
"expiration_date_time": s.expiration_date_time,
112+
"statistics": s.statistics,
113+
"errors": s.errors,
114+
"next_link": s.next_link,
115+
}
116+
)
117+
return info
118+
119+
@classmethod
120+
def from_continuation_token(
121+
cls,
122+
polling_method: PollingMethod[PollingReturnType_co],
123+
continuation_token: str,
124+
**kwargs: Any,
125+
) -> "AnalyzeConversationLROPoller[PollingReturnType_co]":
126+
client, initial_response, deserialization_callback = polling_method.from_continuation_token(
127+
continuation_token, **kwargs
128+
)
129+
return cls(client, initial_response, deserialization_callback, polling_method)
130+
131+
132+
class ConversationAnalysisClient(AnalysisClientGenerated):
133+
134+
def __init__(
135+
self,
136+
endpoint: str,
137+
credential: Union[AzureKeyCredential, "TokenCredential"],
138+
*,
139+
api_version: Optional[str] = None,
140+
**kwargs: Any,
141+
) -> None:
142+
"""Create a ConversationAnalysisClient.
143+
:param endpoint: Supported Cognitive Services endpoint.
144+
:type endpoint: str
145+
:param credential: Key or token credential.
146+
:type credential: ~azure.core.credentials.AzureKeyCredential or ~azure.core.credentials.TokenCredential
147+
:keyword api_version: The API version to use for this operation. Default value is
148+
"2025-05-15-preview". Note that overriding this default value may result in unsupported
149+
behavior.
150+
:paramtype api_version: str`
151+
"""
152+
if api_version is not None:
153+
kwargs["api_version"] = api_version
154+
super().__init__(endpoint=endpoint, credential=credential, **kwargs)
155+
156+
@overload
157+
def begin_analyze_conversation_job(
158+
self, body: AnalyzeConversationOperationInput, *, content_type: str = "application/json", **kwargs: Any
159+
) -> AnalyzeConversationLROPoller[ItemPaged["ConversationActions"]]:
160+
"""Analyzes the input conversation utterance.
161+
162+
:param body: The input for the analyze conversations operation. Required.
163+
:type body: ~azure.ai.language.conversations.models.AnalyzeConversationOperationInput
164+
:keyword content_type: Body Parameter content-type. Content type parameter for JSON body.
165+
Default value is "application/json".
166+
:paramtype content_type: str
167+
:return: A poller whose ``result()`` yields ``ItemPaged[ConversationActions]`` and exposes metadata via ``.details``.
168+
:rtype: ~azure.ai.language.conversations.AnalyzeConversationLROPoller[
169+
~azure.core.paging.ItemPaged[~azure.ai.language.conversations.models.ConversationActions]]
170+
:raises ~azure.core.exceptions.HttpResponseError:
171+
"""
172+
173+
@overload
174+
def begin_analyze_conversation_job(
175+
self, body: JSON, *, content_type: str = "application/json", **kwargs: Any
176+
) -> AnalyzeConversationLROPoller[ItemPaged["ConversationActions"]]:
177+
"""Analyzes the input conversation utterance.
178+
179+
:param body: The input for the analyze conversations operation. Required.
180+
:type body: JSON
181+
:keyword content_type: Body Parameter content-type. Content type parameter for JSON body.
182+
Default value is "application/json".
183+
:paramtype content_type: str
184+
:return: A poller whose ``result()`` yields ``ItemPaged[ConversationActions]`` and exposes metadata via ``.details``.
185+
:rtype: ~azure.ai.language.conversations.AnalyzeConversationLROPoller[
186+
~azure.core.paging.ItemPaged[~azure.ai.language.conversations.models.ConversationActions]]
187+
:raises ~azure.core.exceptions.HttpResponseError:
188+
"""
189+
190+
@overload
191+
def begin_analyze_conversation_job(
192+
self, body: IO[bytes], *, content_type: str = "application/json", **kwargs: Any
193+
) -> AnalyzeConversationLROPoller[ItemPaged["ConversationActions"]]:
194+
"""Analyzes the input conversation utterance.
195+
196+
:param body: The input for the analyze conversations operation. Required.
197+
:type body: IO[bytes]
198+
:keyword content_type: Body Parameter content-type. Content type parameter for binary body.
199+
Default value is "application/json".
200+
:paramtype content_type: str
201+
:return: A poller whose ``result()`` yields ``ItemPaged[ConversationActions]`` and exposes metadata via ``.details``.
202+
:rtype: ~azure.ai.language.conversations.AnalyzeConversationLROPoller[
203+
~azure.core.paging.ItemPaged[~azure.ai.language.conversations.models.ConversationActions]]
204+
:raises ~azure.core.exceptions.HttpResponseError:
205+
"""
206+
207+
@distributed_trace
208+
@api_version_validation(
209+
method_added_on="2023-04-01",
210+
params_added_on={"2023-04-01": ["api_version", "content_type", "accept"]},
211+
api_versions_list=["2023-04-01", "2024-05-01", "2024-11-01", "2024-11-15-preview", "2025-05-15-preview"],
212+
)
213+
def begin_analyze_conversation_job( # type: ignore[override]
214+
self, body: Union[AnalyzeConversationOperationInput, JSON, IO[bytes]], **kwargs: Any
215+
) -> AnalyzeConversationLROPoller[ItemPaged["ConversationActions"]]:
216+
"""Analyzes the input conversation utterance.
217+
218+
:param body: The input for the analyze conversations operation. Required.
219+
:type body: ~azure.ai.language.conversations.models.AnalyzeConversationOperationInput or JSON or IO[bytes]
220+
:return: A poller whose ``result()`` yields ``ItemPaged[ConversationActions]`` and exposes metadata via ``.details``.
221+
:rtype: ~azure.ai.language.conversations.AnalyzeConversationLROPoller[
222+
~azure.core.paging.ItemPaged[~azure.ai.language.conversations.models.ConversationActions]]
223+
:raises ~azure.core.exceptions.HttpResponseError:
224+
"""
225+
_headers = case_insensitive_dict(kwargs.pop("headers", {}) or {})
226+
_params = kwargs.pop("params", {}) or {}
227+
228+
content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None))
229+
polling: Union[bool, PollingMethod[ItemPaged["ConversationActions"]]] = kwargs.pop("polling", True)
230+
lro_delay = kwargs.pop("polling_interval", self._config.polling_interval)
231+
cont_token: Optional[str] = kwargs.pop("continuation_token", None)
232+
cls = kwargs.pop("cls", None) # optional custom deserializer
233+
kwargs.pop("error_map", None)
234+
235+
path_format_arguments = {
236+
"Endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str"),
237+
}
238+
239+
def _fetch_state_by_next_link(next_link: str) -> AnalyzeConversationOperationState:
240+
req = HttpRequest("GET", next_link)
241+
resp = self._client.send_request(req) # type: ignore[attr-defined]
242+
if resp.status_code != 200:
243+
raise HttpResponseError(response=resp)
244+
data = json.loads(resp.text())
245+
return AnalyzeConversationOperationState(data)
246+
247+
def _build_pager_from_state(state: AnalyzeConversationOperationState) -> ItemPaged["ConversationActions"]:
248+
def extract_data(s: AnalyzeConversationOperationState):
249+
next_link = s.next_link
250+
actions: ConversationActions = s.actions
251+
return next_link, [actions]
252+
253+
def get_next(token: Optional[str]) -> Optional[AnalyzeConversationOperationState]:
254+
if token is None:
255+
return state
256+
if not token:
257+
return None
258+
return _fetch_state_by_next_link(token)
259+
260+
return ItemPaged(get_next, extract_data)
261+
262+
# ----- end paging helpers
263+
264+
# filled after creating the poller; used inside the deserializer
265+
poller_holder: Dict[str, AnalyzeConversationLROPoller[ItemPaged["ConversationActions"]]] = {}
266+
267+
def get_long_running_output(pipeline_response):
268+
final_response = pipeline_response.http_response
269+
if final_response.status_code == 200:
270+
data = json.loads(final_response.text())
271+
op_state = AnalyzeConversationOperationState(data)
272+
273+
# stash state on the custom poller for `.details`
274+
poller_ref = poller_holder["poller"]
275+
poller_ref._record_state_for_details(op_state) # pylint:disable=protected-access
276+
277+
paged = _build_pager_from_state(op_state)
278+
return cls(pipeline_response, paged, {}) if cls else paged
279+
raise HttpResponseError(response=final_response)
280+
281+
# ----- polling method selection
282+
if polling is True:
283+
polling_method: PollingMethod[ItemPaged["ConversationActions"]] = cast(
284+
PollingMethod[ItemPaged["ConversationActions"]],
285+
LROBasePolling(lro_delay, path_format_arguments=path_format_arguments, **kwargs),
286+
)
287+
elif polling is False:
288+
polling_method = cast(PollingMethod[ItemPaged["ConversationActions"]], NoPolling())
289+
else:
290+
polling_method = cast(PollingMethod[ItemPaged["ConversationActions"]], polling)
291+
292+
if cont_token:
293+
return AnalyzeConversationLROPoller[ItemPaged["ConversationActions"]].from_continuation_token(
294+
polling_method=polling_method,
295+
continuation_token=cont_token,
296+
)
297+
298+
# Submit the job
299+
raw_result = self._analyze_conversation_job_initial(
300+
body=body, content_type=content_type, cls=lambda x, y, z: x, headers=_headers, params=_params, **kwargs
301+
)
302+
303+
lro: AnalyzeConversationLROPoller[ItemPaged["ConversationActions"]] = AnalyzeConversationLROPoller(
304+
self._client, raw_result, get_long_running_output, polling_method
305+
)
306+
poller_holder["poller"] = lro
307+
return lro
13308

14309

15310
def patch_sdk():
@@ -19,3 +314,6 @@ def patch_sdk():
19314
you can't accomplish using the techniques described in
20315
https://aka.ms/azsdk/python/dpcodegen/python/customize
21316
"""
317+
318+
319+
__all__ = ["ConversationAnalysisClient", "AnalyzeConversationLROPoller"]

0 commit comments

Comments
 (0)