corehttp 1.0.0b5__py3-none-any.whl → 1.0.0b6__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
corehttp/_version.py CHANGED
@@ -9,4 +9,4 @@
9
9
  # regenerated.
10
10
  # --------------------------------------------------------------------------
11
11
 
12
- VERSION = "1.0.0b5"
12
+ VERSION = "1.0.0b6"
corehttp/credentials.py CHANGED
@@ -5,39 +5,71 @@
5
5
  # -------------------------------------------------------------------------
6
6
  from __future__ import annotations
7
7
  from types import TracebackType
8
- from typing import Any, NamedTuple, Optional, AsyncContextManager, Type
8
+ from typing import NamedTuple, Optional, AsyncContextManager, Type, TypedDict, ContextManager
9
9
  from typing_extensions import Protocol, runtime_checkable
10
10
 
11
11
 
12
- class AccessToken(NamedTuple):
13
- """Represents an OAuth access token."""
12
+ class AccessTokenInfo:
13
+ """Information about an OAuth access token.
14
+
15
+ :param str token: The token string.
16
+ :param int expires_on: The token's expiration time in Unix time.
17
+ :keyword str token_type: The type of access token. Defaults to 'Bearer'.
18
+ :keyword int refresh_on: Specifies the time, in Unix time, when the cached token should be proactively
19
+ refreshed. Optional.
20
+ """
14
21
 
15
22
  token: str
23
+ """The token string."""
16
24
  expires_on: int
25
+ """The token's expiration time in Unix time."""
26
+ token_type: str
27
+ """The type of access token."""
28
+ refresh_on: Optional[int]
29
+ """Specifies the time, in Unix time, when the cached token should be proactively refreshed. Optional."""
30
+
31
+ def __init__(
32
+ self, token: str, expires_on: int, *, token_type: str = "Bearer", refresh_on: Optional[int] = None
33
+ ) -> None:
34
+ self.token = token
35
+ self.expires_on = expires_on
36
+ self.token_type = token_type
37
+ self.refresh_on = refresh_on
17
38
 
39
+ def __repr__(self) -> str:
40
+ return "AccessTokenInfo(token='{}', expires_on={}, token_type='{}', refresh_on={})".format(
41
+ self.token, self.expires_on, self.token_type, self.refresh_on
42
+ )
18
43
 
19
- AccessToken.token.__doc__ = """The token string."""
20
- AccessToken.expires_on.__doc__ = """The token's expiration time in Unix time."""
21
44
 
45
+ class TokenRequestOptions(TypedDict, total=False):
46
+ """Options to use for access token requests. All parameters are optional."""
22
47
 
23
- @runtime_checkable
24
- class TokenCredential(Protocol):
25
- """Protocol for classes able to provide OAuth tokens."""
48
+ claims: str
49
+ """Additional claims required in the token, such as those returned in a resource provider's claims
50
+ challenge following an authorization failure."""
51
+ tenant_id: str
52
+ """The tenant ID to include in the token request."""
26
53
 
27
- def get_token(self, *scopes: str, claims: Optional[str] = None, **kwargs: Any) -> AccessToken:
28
- """Request an access token for `scopes`.
29
54
 
30
- :param str scopes: The type of access needed.
55
+ class TokenCredential(Protocol, ContextManager["TokenCredential"]):
56
+ """Protocol for classes able to provide OAuth access tokens."""
31
57
 
32
- :keyword str claims: Additional claims required in the token, such as those returned in a resource
33
- provider's claims challenge following an authorization failure.
58
+ def get_token_info(self, *scopes: str, options: Optional[TokenRequestOptions] = None) -> AccessTokenInfo:
59
+ """Request an access token for `scopes`.
34
60
 
61
+ :param str scopes: The type of access needed.
62
+ :keyword options: A dictionary of options for the token request. Unknown options will be ignored. Optional.
63
+ :paramtype options: TokenRequestOptions
35
64
 
36
- :rtype: AccessToken
37
- :return: An AccessToken instance containing the token string and its expiration time in Unix time.
65
+ :rtype: AccessTokenInfo
66
+ :return: An AccessTokenInfo instance containing information about the token.
38
67
  """
39
68
  ...
40
69
 
70
+ def close(self) -> None:
71
+ pass
72
+
41
73
 
42
74
  class ServiceNamedKey(NamedTuple):
43
75
  """Represents a name and key pair."""
@@ -47,10 +79,11 @@ class ServiceNamedKey(NamedTuple):
47
79
 
48
80
 
49
81
  __all__ = [
50
- "AccessToken",
82
+ "AccessTokenInfo",
51
83
  "ServiceKeyCredential",
52
84
  "ServiceNamedKeyCredential",
53
85
  "TokenCredential",
86
+ "TokenRequestOptions",
54
87
  "AsyncTokenCredential",
55
88
  ]
56
89
 
@@ -134,16 +167,15 @@ class ServiceNamedKeyCredential:
134
167
  class AsyncTokenCredential(Protocol, AsyncContextManager["AsyncTokenCredential"]):
135
168
  """Protocol for classes able to provide OAuth tokens."""
136
169
 
137
- async def get_token(self, *scopes: str, claims: Optional[str] = None, **kwargs: Any) -> AccessToken:
170
+ async def get_token_info(self, *scopes: str, options: Optional[TokenRequestOptions] = None) -> AccessTokenInfo:
138
171
  """Request an access token for `scopes`.
139
172
 
140
173
  :param str scopes: The type of access needed.
174
+ :keyword options: A dictionary of options for the token request. Unknown options will be ignored. Optional.
175
+ :paramtype options: TokenRequestOptions
141
176
 
142
- :keyword str claims: Additional claims required in the token, such as those returned in a resource
143
- provider's claims challenge following an authorization failure.
144
-
145
- :rtype: AccessToken
146
- :return: An AccessToken instance containing the token string and its expiration time in Unix time.
177
+ :rtype: AccessTokenInfo
178
+ :return: An AccessTokenInfo instance containing the token string and its expiration time in Unix time.
147
179
  """
148
180
  ...
149
181
 
corehttp/exceptions.py CHANGED
@@ -72,15 +72,12 @@ class _HttpResponseCommonAPI(Protocol):
72
72
  """
73
73
 
74
74
  @property
75
- def reason(self) -> Optional[str]:
76
- ...
75
+ def reason(self) -> Optional[str]: ...
77
76
 
78
77
  @property
79
- def status_code(self) -> Optional[int]:
80
- ...
78
+ def status_code(self) -> Optional[int]: ...
81
79
 
82
- def text(self) -> str:
83
- ...
80
+ def text(self) -> str: ...
84
81
 
85
82
  @property
86
83
  def request(self) -> object: # object as type, since all we need is str() on it
@@ -190,6 +187,8 @@ class HttpResponseError(BaseError):
190
187
  :vartype status_code: int
191
188
  :ivar response: The response that triggered the exception.
192
189
  :vartype response: ~corehttp.rest.HttpResponse or ~corehttp.rest.AsyncHttpResponse
190
+ :ivar model: The response body model
191
+ :vartype model: Any
193
192
  """
194
193
 
195
194
  def __init__(
@@ -203,6 +202,8 @@ class HttpResponseError(BaseError):
203
202
  self.reason = response.reason
204
203
  self.status_code = response.status_code
205
204
 
205
+ self.model: Optional[Any] = kwargs.pop("model", None)
206
+
206
207
  # By priority, message is:
207
208
  # - parameter "message", OR
208
209
  # - generic message using "reason"
corehttp/rest/_aiohttp.py CHANGED
@@ -30,7 +30,7 @@ import logging
30
30
  from itertools import groupby
31
31
  from typing import Iterator, cast, TYPE_CHECKING
32
32
  from multidict import CIMultiDict
33
- import aiohttp.client_exceptions # pylint: disable=all
33
+ import aiohttp.client_exceptions # pylint: disable=networking-import-outside-azure-core-transport
34
34
 
35
35
  from ._http_response_impl_async import AsyncHttpResponseImpl
36
36
  from ..exceptions import (
@@ -263,7 +263,7 @@ class AioHttpStreamDownloadGenerator(collections.abc.AsyncIterator):
263
263
  self.response = response
264
264
 
265
265
  # TODO: determine if block size should be public on RestAioHttpTransportResponse.
266
- self.block_size = response._block_size # pylint: disable=protected-access
266
+ self.block_size = response._block_size
267
267
  self._decompress = decompress
268
268
  self.content_length = int(response.headers.get("Content-Length", 0))
269
269
  self._decompressor = None
@@ -272,11 +272,11 @@ class AioHttpStreamDownloadGenerator(collections.abc.AsyncIterator):
272
272
  return self.content_length
273
273
 
274
274
  async def __anext__(self):
275
- internal_response = self.response._internal_response # pylint: disable=protected-access
275
+ internal_response = self.response._internal_response
276
276
  try:
277
277
  # TODO: Determine how chunks should be read.
278
278
  # chunk = await self.response.internal_response.content.read(self.block_size)
279
- chunk = await internal_response.content.read(self.block_size) # pylint: disable=protected-access
279
+ chunk = await internal_response.content.read(self.block_size)
280
280
  if not chunk:
281
281
  raise _ResponseStopIteration()
282
282
  if not self._decompress:
@@ -292,12 +292,7 @@ class HttpResponseImpl(_HttpResponseBaseImpl, _HttpResponse):
292
292
  yield self.content[i : i + chunk_size]
293
293
  else:
294
294
  self._stream_download_check()
295
- for part in self._stream_download_generator(
296
- response=self,
297
- pipeline=None,
298
- decompress=True,
299
- ):
300
- yield part
295
+ yield from self._stream_download_generator(response=self, pipeline=None, decompress=True)
301
296
  self.close()
302
297
 
303
298
  def iter_raw(self, **kwargs) -> Iterator[bytes]:
@@ -307,6 +302,5 @@ class HttpResponseImpl(_HttpResponseBaseImpl, _HttpResponse):
307
302
  :rtype: Iterator[str]
308
303
  """
309
304
  self._stream_download_check()
310
- for part in self._stream_download_generator(response=self, pipeline=None, decompress=False):
311
- yield part
305
+ yield from self._stream_download_generator(response=self, pipeline=None, decompress=False)
312
306
  self.close()
corehttp/rest/_httpx.py CHANGED
@@ -177,7 +177,7 @@ class AsyncHttpXStreamDownloadGenerator(AsyncIterator):
177
177
  return self
178
178
 
179
179
  async def __anext__(self):
180
- internal_response = self.response._internal_response # pylint: disable=protected-access
180
+ internal_response = self.response._internal_response
181
181
  try:
182
182
  return await self.iter_content_func.__anext__()
183
183
  except StopAsyncIteration:
@@ -27,8 +27,8 @@ from __future__ import annotations
27
27
  import logging
28
28
  import collections.abc as collections
29
29
  from typing import TYPE_CHECKING, Any
30
- import requests # pylint: disable=all
31
- from requests.structures import CaseInsensitiveDict # pylint: disable=all
30
+ import requests # pylint: disable=networking-import-outside-azure-core-transport
31
+ from requests.structures import CaseInsensitiveDict # pylint: disable=networking-import-outside-azure-core-transport
32
32
  from urllib3.exceptions import (
33
33
  DecodeError as CoreDecodeError,
34
34
  ReadTimeoutError,
@@ -122,7 +122,7 @@ class StreamDownloadGenerator:
122
122
  self.response = response
123
123
 
124
124
  # TODO: determine if block size should be public on RestTransportResponse.
125
- self.block_size = response._block_size # pylint: disable=protected-access
125
+ self.block_size = response._block_size
126
126
  decompress = kwargs.pop("decompress", True)
127
127
  if len(kwargs) > 0:
128
128
  raise TypeError("Got an unexpected keyword argument: {}".format(list(kwargs.keys())[0]))
@@ -172,8 +172,7 @@ def _read_raw_stream(response, chunk_size=1):
172
172
  # Special case for urllib3.
173
173
  if hasattr(response.raw, "stream"):
174
174
  try:
175
- for chunk in response.raw.stream(chunk_size, decode_content=False):
176
- yield chunk
175
+ yield from response.raw.stream(chunk_size, decode_content=False)
177
176
  except ProtocolError as e:
178
177
  raise ServiceResponseError(e, error=e) from e
179
178
  except CoreDecodeError as e:
@@ -329,16 +329,13 @@ class HttpResponse(_HttpResponseBase):
329
329
  """
330
330
 
331
331
  @abc.abstractmethod
332
- def __enter__(self) -> "HttpResponse":
333
- ...
332
+ def __enter__(self) -> "HttpResponse": ...
334
333
 
335
334
  @abc.abstractmethod
336
- def __exit__(self, *args: Any) -> None:
337
- ...
335
+ def __exit__(self, *args: Any) -> None: ...
338
336
 
339
337
  @abc.abstractmethod
340
- def close(self) -> None:
341
- ...
338
+ def close(self) -> None: ...
342
339
 
343
340
  @abc.abstractmethod
344
341
  def read(self) -> bytes:
@@ -415,5 +412,4 @@ class AsyncHttpResponse(_HttpResponseBase, AsyncContextManager["AsyncHttpRespons
415
412
  yield # pylint: disable=unreachable
416
413
 
417
414
  @abc.abstractmethod
418
- async def close(self) -> None:
419
- ...
415
+ async def close(self) -> None: ...
@@ -51,9 +51,7 @@ class PipelineContext(Dict[str, Any]):
51
51
 
52
52
  _PICKLE_CONTEXT = {"deserialized_data"}
53
53
 
54
- def __init__(
55
- self, transport: Optional["TransportType"], **kwargs: Any
56
- ) -> None: # pylint: disable=super-init-not-called
54
+ def __init__(self, transport: Optional["TransportType"], **kwargs: Any) -> None:
57
55
  self.transport: Optional["TransportType"] = transport
58
56
  self.options = kwargs
59
57
  self._protected = ["transport", "options"]
@@ -113,12 +111,10 @@ class PipelineContext(Dict[str, Any]):
113
111
  raise TypeError("Context objects cannot be updated.")
114
112
 
115
113
  @overload
116
- def pop(self, __key: str) -> Any:
117
- ...
114
+ def pop(self, __key: str) -> Any: ...
118
115
 
119
116
  @overload
120
- def pop(self, __key: str, __default: Optional[Any]) -> Any:
121
- ...
117
+ def pop(self, __key: str, __default: Optional[Any]) -> Any: ...
122
118
 
123
119
  def pop(self, *args: Any) -> Any:
124
120
  """Removes specified key and returns the value.
@@ -153,7 +153,7 @@ class Pipeline(ContextManager["Pipeline"], Generic[HTTPRequestType, HTTPResponse
153
153
  self._transport.__enter__()
154
154
  return self
155
155
 
156
- def __exit__(self, *exc_details: Any) -> None: # pylint: disable=arguments-differ
156
+ def __exit__(self, *exc_details: Any) -> None:
157
157
  self._transport.__exit__(*exc_details)
158
158
 
159
159
  def run(self, request: HTTPRequestType, **kwargs: Any) -> PipelineResponse[HTTPRequestType, HTTPResponseType]:
@@ -26,8 +26,8 @@
26
26
  from __future__ import annotations
27
27
  import inspect
28
28
  from types import TracebackType
29
- from typing import Any, Union, Generic, TypeVar, List, Optional, Iterable, Type
30
- from typing_extensions import AsyncContextManager, TypeGuard
29
+ from typing import Any, Union, Generic, TypeVar, List, Optional, Iterable, Type, AsyncContextManager
30
+ from typing_extensions import TypeGuard
31
31
 
32
32
  from . import PipelineRequest, PipelineResponse, PipelineContext
33
33
  from ..policies import AsyncHTTPPolicy, SansIOHTTPPolicy
@@ -45,9 +45,7 @@ def is_async_http_policy(policy: object) -> TypeGuard[AsyncHTTPPolicy]:
45
45
  return False
46
46
 
47
47
 
48
- class _SansIOAsyncHTTPPolicyRunner(
49
- AsyncHTTPPolicy[HTTPRequestType, AsyncHTTPResponseType]
50
- ): # pylint: disable=unsubscriptable-object
48
+ class _SansIOAsyncHTTPPolicyRunner(AsyncHTTPPolicy[HTTPRequestType, AsyncHTTPResponseType]):
51
49
  """Async implementation of the SansIO policy.
52
50
 
53
51
  Modifies the request and sends to the next policy in the chain.
@@ -76,9 +74,7 @@ class _SansIOAsyncHTTPPolicyRunner(
76
74
  return response
77
75
 
78
76
 
79
- class _AsyncTransportRunner(
80
- AsyncHTTPPolicy[HTTPRequestType, AsyncHTTPResponseType]
81
- ): # pylint: disable=unsubscriptable-object
77
+ class _AsyncTransportRunner(AsyncHTTPPolicy[HTTPRequestType, AsyncHTTPResponseType]):
82
78
  """Async Transport runner.
83
79
 
84
80
  Uses specified HTTP transport type to send request and returns response.
@@ -31,13 +31,11 @@ T = TypeVar("T")
31
31
 
32
32
 
33
33
  @overload
34
- async def await_result(func: Callable[P, Awaitable[T]], *args: P.args, **kwargs: P.kwargs) -> T:
35
- ...
34
+ async def await_result(func: Callable[P, Awaitable[T]], *args: P.args, **kwargs: P.kwargs) -> T: ...
36
35
 
37
36
 
38
37
  @overload
39
- async def await_result(func: Callable[P, T], *args: P.args, **kwargs: P.kwargs) -> T:
40
- ...
38
+ async def await_result(func: Callable[P, T], *args: P.args, **kwargs: P.kwargs) -> T: ...
41
39
 
42
40
 
43
41
  async def await_result(func: Callable[P, Union[T, Awaitable[T]]], *args: P.args, **kwargs: P.kwargs) -> T:
@@ -5,16 +5,17 @@
5
5
  # -------------------------------------------------------------------------
6
6
  from __future__ import annotations
7
7
  import time
8
- from typing import TYPE_CHECKING, Optional, TypeVar, MutableMapping, Any
8
+ from typing import TYPE_CHECKING, Optional, TypeVar, MutableMapping, Any, Union
9
9
 
10
+ from ...credentials import TokenRequestOptions
10
11
  from ...rest import HttpResponse, HttpRequest
11
12
  from . import HTTPPolicy, SansIOHTTPPolicy
12
13
  from ...exceptions import ServiceRequestError
13
14
 
14
15
  if TYPE_CHECKING:
15
- # pylint:disable=unused-import
16
+
16
17
  from ...credentials import (
17
- AccessToken,
18
+ AccessTokenInfo,
18
19
  TokenCredential,
19
20
  ServiceKeyCredential,
20
21
  )
@@ -31,15 +32,23 @@ class _BearerTokenCredentialPolicyBase:
31
32
  :param credential: The credential.
32
33
  :type credential: ~corehttp.credentials.TokenCredential
33
34
  :param str scopes: Lets you specify the type of access needed.
35
+ :keyword auth_flows: A list of authentication flows to use for the credential.
36
+ :paramtype auth_flows: list[dict[str, Union[str, list[dict[str, str]]]]]
34
37
  """
35
38
 
39
+ # pylint: disable=unused-argument
36
40
  def __init__(
37
- self, credential: "TokenCredential", *scopes: str, **kwargs: Any # pylint: disable=unused-argument
41
+ self,
42
+ credential: "TokenCredential",
43
+ *scopes: str,
44
+ auth_flows: Optional[list[dict[str, Union[str, list[dict[str, str]]]]]] = None,
45
+ **kwargs: Any,
38
46
  ) -> None:
39
47
  super(_BearerTokenCredentialPolicyBase, self).__init__()
40
48
  self._scopes = scopes
41
49
  self._credential = credential
42
- self._token: Optional["AccessToken"] = None
50
+ self._token: Optional["AccessTokenInfo"] = None
51
+ self._auth_flows = auth_flows
43
52
 
44
53
  @staticmethod
45
54
  def _enforce_https(request: PipelineRequest[HTTPRequestType]) -> None:
@@ -68,7 +77,12 @@ class _BearerTokenCredentialPolicyBase:
68
77
 
69
78
  @property
70
79
  def _need_new_token(self) -> bool:
71
- return not self._token or self._token.expires_on - time.time() < 300
80
+ now = time.time()
81
+ return (
82
+ not self._token
83
+ or (self._token.refresh_on is not None and self._token.refresh_on <= now)
84
+ or (self._token.expires_on - now < 300)
85
+ )
72
86
 
73
87
 
74
88
  class BearerTokenCredentialPolicy(_BearerTokenCredentialPolicyBase, HTTPPolicy[HTTPRequestType, HTTPResponseType]):
@@ -77,20 +91,30 @@ class BearerTokenCredentialPolicy(_BearerTokenCredentialPolicyBase, HTTPPolicy[H
77
91
  :param credential: The credential.
78
92
  :type credential: ~corehttp.TokenCredential
79
93
  :param str scopes: Lets you specify the type of access needed.
94
+ :keyword auth_flows: A list of authentication flows to use for the credential.
95
+ :paramtype auth_flows: list[dict[str, Union[str, list[dict[str, str]]]]]
80
96
  :raises: :class:`~corehttp.exceptions.ServiceRequestError`
81
97
  """
82
98
 
83
- def on_request(self, request: PipelineRequest[HTTPRequestType]) -> None:
99
+ def on_request(
100
+ self,
101
+ request: PipelineRequest[HTTPRequestType],
102
+ *,
103
+ auth_flows: Optional[list[dict[str, Union[str, list[dict[str, str]]]]]] = None,
104
+ ) -> None:
84
105
  """Called before the policy sends a request.
85
106
 
86
107
  The base implementation authorizes the request with a bearer token.
87
108
 
88
109
  :param ~corehttp.runtime.pipeline.PipelineRequest request: the request
110
+ :keyword auth_flows: A list of authentication flows to use for the credential.
111
+ :paramtype auth_flows: list[dict[str, Union[str, list[dict[str, str]]]]]
89
112
  """
90
113
  self._enforce_https(request)
91
114
 
92
115
  if self._token is None or self._need_new_token:
93
- self._token = self._credential.get_token(*self._scopes)
116
+ options: TokenRequestOptions = {"auth_flows": auth_flows} if auth_flows else {} # type: ignore
117
+ self._token = self._credential.get_token_info(*self._scopes, options=options)
94
118
  self._update_headers(request.http_request.headers, self._token.token)
95
119
 
96
120
  def authorize_request(self, request: PipelineRequest[HTTPRequestType], *scopes: str, **kwargs: Any) -> None:
@@ -102,7 +126,12 @@ class BearerTokenCredentialPolicy(_BearerTokenCredentialPolicyBase, HTTPPolicy[H
102
126
  :param ~corehttp.runtime.pipeline.PipelineRequest request: the request
103
127
  :param str scopes: required scopes of authentication
104
128
  """
105
- self._token = self._credential.get_token(*scopes, **kwargs)
129
+ options: TokenRequestOptions = {}
130
+ # Loop through all the keyword arguments and check if they are part of the TokenRequestOptions.
131
+ for key in list(kwargs.keys()):
132
+ if key in TokenRequestOptions.__annotations__: # pylint:disable=no-member
133
+ options[key] = kwargs.pop(key) # type: ignore[literal-required]
134
+ self._token = self._credential.get_token_info(*scopes, options=options)
106
135
  self._update_headers(request.http_request.headers, self._token.token)
107
136
 
108
137
  def send(self, request: PipelineRequest[HTTPRequestType]) -> PipelineResponse[HTTPRequestType, HTTPResponseType]:
@@ -113,25 +142,25 @@ class BearerTokenCredentialPolicy(_BearerTokenCredentialPolicyBase, HTTPPolicy[H
113
142
  :return: The pipeline response object
114
143
  :rtype: ~corehttp.runtime.pipeline.PipelineResponse
115
144
  """
116
- self.on_request(request)
145
+ self.on_request(request, auth_flows=self._auth_flows)
117
146
  try:
118
147
  response = self.next.send(request)
119
- self.on_response(request, response)
120
- except Exception: # pylint:disable=broad-except
148
+ except Exception:
121
149
  self.on_exception(request)
122
150
  raise
123
- else:
124
- if response.http_response.status_code == 401:
125
- self._token = None # any cached token is invalid
126
- if "WWW-Authenticate" in response.http_response.headers:
127
- request_authorized = self.on_challenge(request, response)
128
- if request_authorized:
129
- try:
130
- response = self.next.send(request)
131
- self.on_response(request, response)
132
- except Exception: # pylint:disable=broad-except
133
- self.on_exception(request)
134
- raise
151
+
152
+ self.on_response(request, response)
153
+ if response.http_response.status_code == 401:
154
+ self._token = None # any cached token is invalid
155
+ if "WWW-Authenticate" in response.http_response.headers:
156
+ request_authorized = self.on_challenge(request, response)
157
+ if request_authorized:
158
+ try:
159
+ response = self.next.send(request)
160
+ self.on_response(request, response)
161
+ except Exception:
162
+ self.on_exception(request)
163
+ raise
135
164
 
136
165
  return response
137
166
 
@@ -5,9 +5,9 @@
5
5
  # -------------------------------------------------------------------------
6
6
  from __future__ import annotations
7
7
  import time
8
- from typing import TYPE_CHECKING, Any, Awaitable, Optional, cast, TypeVar
8
+ from typing import TYPE_CHECKING, Any, Awaitable, Optional, cast, TypeVar, Union
9
9
 
10
- from ...credentials import AccessToken
10
+ from ...credentials import AccessTokenInfo, TokenRequestOptions
11
11
  from ..pipeline import PipelineRequest, PipelineResponse
12
12
  from ..pipeline._tools_async import await_result
13
13
  from ._base_async import AsyncHTTPPolicy
@@ -29,16 +29,24 @@ class AsyncBearerTokenCredentialPolicy(AsyncHTTPPolicy[HTTPRequestType, AsyncHTT
29
29
  :param credential: The credential.
30
30
  :type credential: ~corehttp.credentials.TokenCredential
31
31
  :param str scopes: Lets you specify the type of access needed.
32
+ :keyword auth_flows: A list of authentication flows to use for the credential.
33
+ :paramtype auth_flows: list[dict[str, Union[str, list[dict[str, str]]]]]
32
34
  """
33
35
 
36
+ # pylint: disable=unused-argument
34
37
  def __init__(
35
- self, credential: "AsyncTokenCredential", *scopes: str, **kwargs: Any # pylint: disable=unused-argument
38
+ self,
39
+ credential: "AsyncTokenCredential",
40
+ *scopes: str,
41
+ auth_flows: Optional[list[dict[str, Union[str, list[dict[str, str]]]]]] = None,
42
+ **kwargs: Any,
36
43
  ) -> None:
37
44
  super().__init__()
38
45
  self._credential = credential
39
46
  self._lock_instance = None
40
47
  self._scopes = scopes
41
- self._token: Optional["AccessToken"] = None
48
+ self._token: Optional[AccessTokenInfo] = None
49
+ self._auth_flows = auth_flows
42
50
 
43
51
  @property
44
52
  def _lock(self):
@@ -46,21 +54,29 @@ class AsyncBearerTokenCredentialPolicy(AsyncHTTPPolicy[HTTPRequestType, AsyncHTT
46
54
  self._lock_instance = get_running_async_lock()
47
55
  return self._lock_instance
48
56
 
49
- async def on_request(self, request: PipelineRequest[HTTPRequestType]) -> None:
57
+ async def on_request(
58
+ self,
59
+ request: PipelineRequest[HTTPRequestType],
60
+ *,
61
+ auth_flows: Optional[list[dict[str, Union[str, list[dict[str, str]]]]]] = None,
62
+ ) -> None:
50
63
  """Adds a bearer token Authorization header to request and sends request to next policy.
51
64
 
52
65
  :param request: The pipeline request object to be modified.
53
66
  :type request: ~corehttp.runtime.pipeline.PipelineRequest
67
+ :keyword auth_flows: A list of authentication flows to use for the credential.
68
+ :paramtype auth_flows: list[dict[str, Union[str, list[dict[str, str]]]]]
54
69
  :raises: :class:`~corehttp.exceptions.ServiceRequestError`
55
70
  """
56
71
  _BearerTokenCredentialPolicyBase._enforce_https(request) # pylint:disable=protected-access
57
72
 
58
- if self._token is None or self._need_new_token():
73
+ if self._token is None or self._need_new_token:
59
74
  async with self._lock:
60
75
  # double check because another coroutine may have acquired a token while we waited to acquire the lock
61
- if self._token is None or self._need_new_token():
62
- self._token = await await_result(self._credential.get_token, *self._scopes)
63
- request.http_request.headers["Authorization"] = "Bearer " + cast(AccessToken, self._token).token
76
+ if self._token is None or self._need_new_token:
77
+ options: TokenRequestOptions = {"auth_flows": auth_flows} if auth_flows else {} # type: ignore
78
+ self._token = await await_result(self._credential.get_token_info, *self._scopes, options=options)
79
+ request.http_request.headers["Authorization"] = "Bearer " + cast(AccessTokenInfo, self._token).token
64
80
 
65
81
  async def authorize_request(self, request: PipelineRequest[HTTPRequestType], *scopes: str, **kwargs: Any) -> None:
66
82
  """Acquire a token from the credential and authorize the request with it.
@@ -71,9 +87,15 @@ class AsyncBearerTokenCredentialPolicy(AsyncHTTPPolicy[HTTPRequestType, AsyncHTT
71
87
  :param ~corehttp.runtime.pipeline.PipelineRequest request: the request
72
88
  :param str scopes: required scopes of authentication
73
89
  """
90
+ options: TokenRequestOptions = {}
91
+ # Loop through all the keyword arguments and check if they are part of the TokenRequestOptions.
92
+ for key in list(kwargs.keys()):
93
+ if key in TokenRequestOptions.__annotations__: # pylint:disable=no-member
94
+ options[key] = kwargs.pop(key) # type: ignore[literal-required]
95
+
74
96
  async with self._lock:
75
- self._token = await await_result(self._credential.get_token, *scopes, **kwargs)
76
- request.http_request.headers["Authorization"] = "Bearer " + cast(AccessToken, self._token).token
97
+ self._token = await await_result(self._credential.get_token_info, *scopes, options=options)
98
+ request.http_request.headers["Authorization"] = "Bearer " + cast(AccessTokenInfo, self._token).token
77
99
 
78
100
  async def send(
79
101
  self, request: PipelineRequest[HTTPRequestType]
@@ -85,14 +107,13 @@ class AsyncBearerTokenCredentialPolicy(AsyncHTTPPolicy[HTTPRequestType, AsyncHTT
85
107
  :return: The pipeline response object
86
108
  :rtype: ~corehttp.runtime.pipeline.PipelineResponse
87
109
  """
88
- await await_result(self.on_request, request)
110
+ await await_result(self.on_request, request, auth_flows=self._auth_flows)
89
111
  try:
90
112
  response = await self.next.send(request)
91
- except Exception: # pylint:disable=broad-except
113
+ except Exception:
92
114
  await await_result(self.on_exception, request)
93
115
  raise
94
- else:
95
- await await_result(self.on_response, request, response)
116
+ await await_result(self.on_response, request, response)
96
117
 
97
118
  if response.http_response.status_code == 401:
98
119
  self._token = None # any cached token is invalid
@@ -101,11 +122,10 @@ class AsyncBearerTokenCredentialPolicy(AsyncHTTPPolicy[HTTPRequestType, AsyncHTT
101
122
  if request_authorized:
102
123
  try:
103
124
  response = await self.next.send(request)
104
- except Exception: # pylint:disable=broad-except
125
+ except Exception:
105
126
  await await_result(self.on_exception, request)
106
127
  raise
107
- else:
108
- await await_result(self.on_response, request, response)
128
+ await await_result(self.on_response, request, response)
109
129
 
110
130
  return response
111
131
 
@@ -151,5 +171,11 @@ class AsyncBearerTokenCredentialPolicy(AsyncHTTPPolicy[HTTPRequestType, AsyncHTT
151
171
  # pylint: disable=unused-argument
152
172
  return
153
173
 
174
+ @property
154
175
  def _need_new_token(self) -> bool:
155
- return not self._token or self._token.expires_on - time.time() < 300
176
+ now = time.time()
177
+ return (
178
+ not self._token
179
+ or (self._token.refresh_on is not None and self._token.refresh_on <= now)
180
+ or (self._token.expires_on - now < 300)
181
+ )
@@ -513,7 +513,7 @@ class RetryPolicy(RetryPolicyBase, HTTPPolicy[HttpRequest, HttpResponse]):
513
513
  is_response_error = True
514
514
  continue
515
515
  break
516
- except ClientAuthenticationError: # pylint:disable=try-except-raise
516
+ except ClientAuthenticationError:
517
517
  # the authentication policy failed such that the client's request can't
518
518
  # succeed--we'll never have a response to it, so propagate the exception
519
519
  raise
@@ -174,7 +174,7 @@ class AsyncRetryPolicy(RetryPolicyBase, AsyncHTTPPolicy[HttpRequest, AsyncHttpRe
174
174
  is_response_error = True
175
175
  continue
176
176
  break
177
- except ClientAuthenticationError: # pylint:disable=try-except-raise
177
+ except ClientAuthenticationError:
178
178
  # the authentication policy failed such that the client's request can't
179
179
  # succeed--we'll never have a response to it, so propagate the exception
180
180
  raise
@@ -64,9 +64,7 @@ class HeadersPolicy(SansIOHTTPPolicy[HTTPRequestType, HTTPResponseType]):
64
64
  :param dict base_headers: Headers to send with the request.
65
65
  """
66
66
 
67
- def __init__(
68
- self, base_headers: Optional[Dict[str, str]] = None, **kwargs: Any
69
- ) -> None: # pylint: disable=super-init-not-called
67
+ def __init__(self, base_headers: Optional[Dict[str, str]] = None, **kwargs: Any) -> None:
70
68
  self._headers: Dict[str, str] = base_headers or {}
71
69
  self._headers.update(kwargs.pop("headers", {}))
72
70
 
@@ -114,9 +112,7 @@ class UserAgentPolicy(SansIOHTTPPolicy[HTTPRequestType, HTTPResponseType]):
114
112
  _USERAGENT = "User-Agent"
115
113
  _ENV_ADDITIONAL_USER_AGENT = "CORE_HTTP_USER_AGENT"
116
114
 
117
- def __init__(
118
- self, base_user_agent: Optional[str] = None, **kwargs: Any
119
- ) -> None: # pylint: disable=super-init-not-called
115
+ def __init__(self, base_user_agent: Optional[str] = None, **kwargs: Any) -> None:
120
116
  self.overwrite: bool = kwargs.pop("user_agent_overwrite", False)
121
117
  self.use_env: bool = kwargs.pop("user_agent_use_env", True)
122
118
  application_id: Optional[str] = kwargs.pop("user_agent", None)
@@ -172,7 +168,6 @@ class UserAgentPolicy(SansIOHTTPPolicy[HTTPRequestType, HTTPResponseType]):
172
168
 
173
169
 
174
170
  class NetworkTraceLoggingPolicy(SansIOHTTPPolicy[HTTPRequestType, HTTPResponseType]):
175
-
176
171
  """The logging policy in the pipeline is used to output HTTP network trace to the configured logger.
177
172
 
178
173
  This accepts both global configuration, and per-request level with "enable_http_logger"
@@ -183,9 +178,7 @@ class NetworkTraceLoggingPolicy(SansIOHTTPPolicy[HTTPRequestType, HTTPResponseTy
183
178
  def __init__(self, logging_enable: bool = False, **kwargs: Any): # pylint: disable=unused-argument
184
179
  self.enable_http_logger = logging_enable
185
180
 
186
- def on_request(
187
- self, request: PipelineRequest[HTTPRequestType]
188
- ) -> None: # pylint: disable=too-many-return-statements
181
+ def on_request(self, request: PipelineRequest[HTTPRequestType]) -> None:
189
182
  """Logs HTTP request to the DEBUG logger.
190
183
 
191
184
  :param request: The PipelineRequest object.
@@ -455,7 +448,7 @@ class ProxyPolicy(SansIOHTTPPolicy[HTTPRequestType, HTTPResponseType]):
455
448
 
456
449
  def __init__(
457
450
  self, proxies: Optional[MutableMapping[str, str]] = None, **kwargs: Any
458
- ): # pylint: disable=unused-argument,super-init-not-called
451
+ ): # pylint: disable=unused-argument
459
452
  self.proxies = proxies
460
453
 
461
454
  def on_request(self, request: PipelineRequest[HTTPRequestType]) -> None:
corehttp/serialization.py CHANGED
@@ -114,7 +114,7 @@ def _datetime_as_isostr(dt: Union[datetime, date, time, timedelta]) -> str:
114
114
  class CoreJSONEncoder(JSONEncoder):
115
115
  """A JSON encoder that's capable of serializing datetime objects and bytes."""
116
116
 
117
- def default(self, o: Any) -> Any: # pylint: disable=too-many-return-statements
117
+ def default(self, o: Any) -> Any:
118
118
  if isinstance(o, (bytes, bytearray)):
119
119
  return base64.b64encode(o).decode()
120
120
  try:
@@ -29,8 +29,8 @@ from types import TracebackType
29
29
 
30
30
  import logging
31
31
  import asyncio
32
- import aiohttp # pylint: disable=all
33
- import aiohttp.client_exceptions # pylint: disable=all
32
+ import aiohttp # pylint: disable=networking-import-outside-azure-core-transport
33
+ import aiohttp.client_exceptions # pylint: disable=networking-import-outside-azure-core-transport
34
34
 
35
35
  from ...exceptions import (
36
36
  ServiceRequestError,
@@ -27,7 +27,7 @@
27
27
  import sys
28
28
  from typing import MutableMapping, Optional
29
29
 
30
- from requests.adapters import HTTPAdapter # pylint: disable=all
30
+ from requests.adapters import HTTPAdapter # pylint: disable=networking-import-outside-azure-core-transport
31
31
  from urllib3.connectionpool import ConnectionPool
32
32
 
33
33
 
@@ -31,7 +31,7 @@ from urllib3.exceptions import (
31
31
  NewConnectionError,
32
32
  ConnectTimeoutError,
33
33
  )
34
- import requests # pylint: disable=all
34
+ import requests # pylint: disable=networking-import-outside-azure-core-transport
35
35
 
36
36
  from ...exceptions import (
37
37
  ServiceRequestError,
@@ -89,7 +89,7 @@ class RequestsTransport(HttpTransport):
89
89
  self.open()
90
90
  return self
91
91
 
92
- def __exit__(self, *args): # pylint: disable=arguments-differ
92
+ def __exit__(self, *args):
93
93
  self.close()
94
94
 
95
95
  def _init_session(self, session: requests.Session) -> None:
@@ -45,7 +45,7 @@ class CaseInsensitiveEnumMeta(EnumMeta):
45
45
 
46
46
  def __getitem__(cls, name: str) -> Any:
47
47
  # disabling pylint bc of pylint bug https://github.com/PyCQA/astroid/issues/713
48
- return super(CaseInsensitiveEnumMeta, cls).__getitem__(name.upper()) # pylint: disable=no-value-for-parameter
48
+ return super(CaseInsensitiveEnumMeta, cls).__getitem__(name.upper())
49
49
 
50
50
  def __getattr__(cls, name: str) -> Enum:
51
51
  """Return the enum member matching `name`.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: corehttp
3
- Version: 1.0.0b5
3
+ Version: 1.0.0b6
4
4
  Summary: CoreHTTP Library for Python
5
5
  Home-page: https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/core/corehttp
6
6
  Author: Microsoft Corporation
@@ -20,13 +20,13 @@ Classifier: License :: OSI Approved :: MIT License
20
20
  Requires-Python: >=3.8
21
21
  Description-Content-Type: text/markdown
22
22
  License-File: LICENSE
23
- Requires-Dist: typing-extensions >=4.6.0
23
+ Requires-Dist: typing-extensions>=4.6.0
24
24
  Provides-Extra: aiohttp
25
- Requires-Dist: aiohttp >=3.0 ; extra == 'aiohttp'
25
+ Requires-Dist: aiohttp>=3.0; extra == "aiohttp"
26
26
  Provides-Extra: httpx
27
- Requires-Dist: httpx >=0.25.0 ; extra == 'httpx'
27
+ Requires-Dist: httpx>=0.25.0; extra == "httpx"
28
28
  Provides-Extra: requests
29
- Requires-Dist: requests >=2.18.4 ; extra == 'requests'
29
+ Requires-Dist: requests>=2.18.4; extra == "requests"
30
30
 
31
31
 
32
32
  # Core HTTP shared client library for Python
@@ -87,6 +87,24 @@ additional questions or comments.
87
87
 
88
88
  # Release History
89
89
 
90
+ ## 1.0.0b6 (2025-03-27)
91
+
92
+ ### Features Added
93
+
94
+ - The `TokenCredential` and `AsyncTokenCredential` protocols have been updated to include a new `get_token_info` method. This method should be used to acquire tokens and return an `AccessTokenInfo` object. [#38346](https://github.com/Azure/azure-sdk-for-python/pull/38346)
95
+ - Added a new `TokenRequestOptions` class, which is a `TypedDict` with optional parameters, that can be used to define options for token requests through the `get_token_info` method. [#38346](https://github.com/Azure/azure-sdk-for-python/pull/38346)
96
+ - Added a new `AccessTokenInfo` class, which is returned by `get_token_info` implementations. This class contains the token, its expiration time, and optional additional information like when a token should be refreshed. [#38346](https://github.com/Azure/azure-sdk-for-python/pull/38346)
97
+ - `BearerTokenCredentialPolicy` and `AsyncBearerTokenCredentialPolicy` now check if a credential has the `get_token_info` method defined. If so, the `get_token_info` method is used to acquire a token. [#38346](https://github.com/Azure/azure-sdk-for-python/pull/38346)
98
+ - These policies now also check the `refresh_on` attribute when determining if a new token request should be made.
99
+ - Added `model` attribute to `HttpResponseError` to allow accessing error attributes based on a known model. [#39636](https://github.com/Azure/azure-sdk-for-python/pull/39636)
100
+ - Added `auth_flows` support in `BearerTokenCredentialPolicy`. [#40084](https://github.com/Azure/azure-sdk-for-python/pull/40084)
101
+
102
+ ### Breaking Changes
103
+
104
+ - The `get_token` method has been removed from the `TokenCredential` and `AsyncTokenCredential` protocols. Implementations should now use the new `get_token_info` method to acquire tokens. [#38346](https://github.com/Azure/azure-sdk-for-python/pull/38346)
105
+ - The `AccessToken` class has been removed and replaced with a new `AccessTokenInfo` class. [#38346](https://github.com/Azure/azure-sdk-for-python/pull/38346)
106
+ - `BearerTokenCredentialPolicy` and `AsyncBearerTokenCredentialPolicy` now rely on credentials having the `get_token_info` method defined. [#38346](https://github.com/Azure/azure-sdk-for-python/pull/38346)
107
+
90
108
  ## 1.0.0b5 (2024-02-29)
91
109
 
92
110
  ### Other Changes
@@ -1,52 +1,52 @@
1
1
  corehttp/__init__.py,sha256=Wdidh085sV_IhdV_wU79t7FpghhpyxCsRnZGOUoQ0xs,1443
2
2
  corehttp/_match_conditions.py,sha256=3TIhb4vBO1hBe7MaQwS_9i-d6p7o4jn5L6M-OiQahkg,1864
3
- corehttp/_version.py,sha256=Adx1gY_uaehKHdReRn2zLYGyMjbGV43k9smdJngNeLo,494
4
- corehttp/credentials.py,sha256=xx94AN5Nekiz3SNHJNV6ncS2o4ObCc5U_Ya62QzTfaM,5237
5
- corehttp/exceptions.py,sha256=qSqzPJVD_ufGO5HEAbNY8BNmVUoXPCgBeVrw195QvF4,11554
3
+ corehttp/_version.py,sha256=uCj-R1Y_ZRGSi794naubDn0UkPzXOuqPQYRdRChKvBw,494
4
+ corehttp/credentials.py,sha256=EM0k1It1y4_q4cSCRE_m7SjF8npN9aGVBcGhBBfxsmc,6672
5
+ corehttp/exceptions.py,sha256=mKh6wtuYi2aqiZRicNjE_693gBJMkNaWJLuXJ-VE444,11658
6
6
  corehttp/paging.py,sha256=zI-fFLBUgMRZmFegD2T6Q52s_3PFDb6lLjtR7-XSZDc,9520
7
7
  corehttp/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
- corehttp/serialization.py,sha256=Q4ZPuh2pHl37T0Lvb96xfXGpMB6oPrmzscLEe0N4Bsw,4090
8
+ corehttp/serialization.py,sha256=HicFY3mGePD0F5F24ryjQ_Igq3XE3vsHOQw0l36w1EI,4044
9
9
  corehttp/rest/__init__.py,sha256=GwPFwVYZ9aa4DI9f2-oQGr2nfF7wXvVL80V51ymAjAk,1467
10
- corehttp/rest/_aiohttp.py,sha256=-_Nym7nY7sy34wNXU_7nA9pngZ24NazuzAheRU2PBJM,11301
10
+ corehttp/rest/_aiohttp.py,sha256=Ld_WrYVOpHodReET9tCJqYfbyNsPDq_uWeDczA1fXUM,11236
11
11
  corehttp/rest/_helpers.py,sha256=ZhXhAiAw8DW_gxUPE3tumMplRS1Jt2h6joLVsk-u6yI,7897
12
- corehttp/rest/_http_response_impl.py,sha256=9I0flIplRZ6-JaWzhcCSTAVnxp_tf6XVCci2nkHCSco,11381
12
+ corehttp/rest/_http_response_impl.py,sha256=qvbvNLyatApp8EMRDxkTHdZMaUoNBp0LJxncUL-uH10,11264
13
13
  corehttp/rest/_http_response_impl_async.py,sha256=lmdtY-l0hrNy5PbhWrl2hZrfHzZkn6LZPMR2fTy54WY,4972
14
- corehttp/rest/_httpx.py,sha256=7mmpEIQ0-GLf3G_Wg3-f2dQnk-mvw4xbqtL9eoPhhwY,8173
15
- corehttp/rest/_requests_basic.py,sha256=rw2GwxDMMrG5A4onTKLwQpsQe98MtUaowA_-BfTgsuc,7527
16
- corehttp/rest/_rest_py3.py,sha256=JLLGz6svFF-UwxS_GyGUq5c2KHcNL26TB-ARxfBIOY8,14096
14
+ corehttp/rest/_httpx.py,sha256=5-zpxrd4DyYOx9aNy4H1wHITf0Q38TNTAOhYBoH6liY,8137
15
+ corehttp/rest/_requests_basic.py,sha256=Ihy_y4VMfa4rk-JruYfMYkRmRjX-dgypNL03vm2cQCM,7546
16
+ corehttp/rest/_rest_py3.py,sha256=YFxoRoZgppwve-x0JVv4IZiXuGEwt_1SZyCII5X3Y0c,14064
17
17
  corehttp/runtime/__init__.py,sha256=OeG_5-Oq3Zp9rJcMfRNiYLv3V39wIZxDcQ-unerauDw,1469
18
18
  corehttp/runtime/_base.py,sha256=gr2xJQJeWuOmtrudFhM07_6ASIhUX66jR1nxSRMh068,5056
19
19
  corehttp/runtime/_pipeline_client.py,sha256=A2R0JEcfFIOe6b38VzuQatAxfbiBhtu_RCpOlM968b0,7099
20
20
  corehttp/runtime/_pipeline_client_async.py,sha256=dBUqhntQzcS1kbQ6z7d6C4Y3HDghLr4jrobtlKvbVTw,10378
21
- corehttp/runtime/pipeline/__init__.py,sha256=gRGAsJ1ZDE20TMp6JDw8OpekZdfA7ZzZvOhVHclNpDI,7727
22
- corehttp/runtime/pipeline/_base.py,sha256=WVLDonxHv5knC-Ffq7YW2cRHr22rtZQjRtZ2N9FWzLw,6900
23
- corehttp/runtime/pipeline/_base_async.py,sha256=4hvZDFlJ9odUs6Z6etQUlXfm9b1Bt_avZxxEee_h3Sw,7370
21
+ corehttp/runtime/pipeline/__init__.py,sha256=5fxBfA1YQK0gEE2lVmaBdPdlyIk31utG29r959PWxq0,7656
22
+ corehttp/runtime/pipeline/_base.py,sha256=rKJaw4Bv6yq8OzahNuqfSn-ro1pEz7HcbA3DvbFagtw,6864
23
+ corehttp/runtime/pipeline/_base_async.py,sha256=eaFAOMvgvZEM9T8Z7LMWaeLV5EgO6AMgP9ps2A8ZiAs,7274
24
24
  corehttp/runtime/pipeline/_tools.py,sha256=iol34Mo_R6-Rezal7WSFFSzFa1V3dXf90AQydnxRnSQ,2004
25
- corehttp/runtime/pipeline/_tools_async.py,sha256=OvEJjH8NuGnSOrcbJBCIlN_TsO8w87kgEJ0LJcwcYH0,2159
25
+ corehttp/runtime/pipeline/_tools_async.py,sha256=r9Apyo4BOTKSRTfyFjLmcrGiVoulrnpxqkNOmzHOrGg,2151
26
26
  corehttp/runtime/policies/__init__.py,sha256=_LPYWjRNkDq45FAHUvyMJ92BL0W6pf7-KrjxSZSkF5c,2196
27
- corehttp/runtime/policies/_authentication.py,sha256=mgacXdydBBKPQ-5NujqNNWNNCsbt9ETWJBBdqMqgfGc,8819
28
- corehttp/runtime/policies/_authentication_async.py,sha256=QUUYFlcsc6vJDox7vw1Ggg165c1KXEWiwM70BInoidM,6946
27
+ corehttp/runtime/policies/_authentication.py,sha256=FTu02pWeo3relph_SMvVSDt9xieWTbVypC0bk7WPNPk,10155
28
+ corehttp/runtime/policies/_authentication_async.py,sha256=VabVsVXAjgQhhCtfigMWUIlczS1zi8S6w2m8_e-Irb8,8168
29
29
  corehttp/runtime/policies/_base.py,sha256=zLM4NIwGQwZ75k-KPo3PthmDCpDidHvZy91ok0wnFvQ,5063
30
30
  corehttp/runtime/policies/_base_async.py,sha256=nOZ-3lrKmfnFam3FbSY4wd9sOI7r5pI2HSdqgOC4Vz4,2531
31
- corehttp/runtime/policies/_retry.py,sha256=vM40m1JSD-l6yBclxmQV06_ZOK4WAcy1PTqQQpTr3ts,24367
32
- corehttp/runtime/policies/_retry_async.py,sha256=rsVFxlQMDyU1Z34FKd1trfxj2VkwGt-Ap7uqiErMeAc,9131
33
- corehttp/runtime/policies/_universal.py,sha256=6qfC2MAQbp1KQgWnbbcBKuwprzEZaftx7tfY6QuHmpo,19835
31
+ corehttp/runtime/policies/_retry.py,sha256=9b7Zts-BemkDRMKxT_P8FkUIr-WZrStN5KbiNLeQU8Q,24332
32
+ corehttp/runtime/policies/_retry_async.py,sha256=eCUqP4IgB7ZMVC9u5DUCDt8JEWikTypLqwUvmF4R-PQ,9096
33
+ corehttp/runtime/policies/_universal.py,sha256=mGXqLgOjKdzuiY62V_ibMaSBiLMKVh9kEAbZ4uxYKqQ,19642
34
34
  corehttp/runtime/policies/_utils.py,sha256=kDnGRpC3MxsW7zHZRfkLyPMArlzY4n7vBhwQQVWKQuI,3596
35
35
  corehttp/transport/__init__.py,sha256=6A1i9gjM5isBPb-AL-2JTzxn7pssDj8ux9Ujn6rHjlY,1442
36
36
  corehttp/transport/_base.py,sha256=5gFTZ1u--3Ik9DyrAe10RtObasd-OXX1y9sRSkbvoyY,5107
37
37
  corehttp/transport/_base_async.py,sha256=9zl1Sa8Vm6QBdn8Nf-J3w2qZ-wsjcV9bv1EX5Jr28w4,3827
38
38
  corehttp/transport/aiohttp/__init__.py,sha256=gdCazQ9XMZ6xgJCakm4efxECBFU-IIxKuMF3VmM9dHQ,1381
39
- corehttp/transport/aiohttp/_aiohttp.py,sha256=EesPhF2tAIMxgM0qwFfUu4IUzwF8mHLHbnCD5-Zv8Nk,9565
39
+ corehttp/transport/aiohttp/_aiohttp.py,sha256=HqQWbGhx8kvP4ibqlB3mJEutzpwxAapwnu5EAWwHtiQ,9651
40
40
  corehttp/transport/httpx/__init__.py,sha256=IbjUxTxtGljHK9nq6w0kAFeHd73zAl7qtd27qlqCrzg,1412
41
41
  corehttp/transport/httpx/_httpx.py,sha256=of8Mxyfzm1Rd4ltYNt8wGz1xuTnJVef0KaiJyl99KfE,8579
42
42
  corehttp/transport/requests/__init__.py,sha256=WPdzueqs0eLfvumuedxXPsOIpPCq3dDOvdzmIK4nyHs,1390
43
- corehttp/transport/requests/_bigger_block_size_http_adapters.py,sha256=0SkJ3lQHdbh1iBlCCbc9NCshDRJsVLZUZdWL-frZ_4Q,2444
44
- corehttp/transport/requests/_requests_basic.py,sha256=ChsXobJeBdwLTnNnDzWLZi5JYVg6M95kcxXfcgPZ3r0,8179
43
+ corehttp/transport/requests/_bigger_block_size_http_adapters.py,sha256=S1zE3v6QwPtdEm2cLdu8B5iW5WbETTgpv0datZ9g_eo,2487
44
+ corehttp/transport/requests/_requests_basic.py,sha256=dU8gup_4IytJIyfYtMMBb8sIMP2LsNJYjGxjnBwzP3o,8186
45
45
  corehttp/utils/__init__.py,sha256=_h2vJje1Tb-w_9mXm0hO_s2S1b48HLzI4taIlvz3Eu4,1648
46
- corehttp/utils/_enum_meta.py,sha256=l2K1mZfpwljsruKxknabYckl0ZbsVftOxfbRhpzF_-s,2816
46
+ corehttp/utils/_enum_meta.py,sha256=9rdoxCOiBnYFMUC8-8_yaoCA9s_GdbIkguxk3Z71iyM,2774
47
47
  corehttp/utils/_utils.py,sha256=TN2IplPve8b6xJPMvIVE-2oF3u_SK89XtYmCb70UDr4,6063
48
- corehttp-1.0.0b5.dist-info/LICENSE,sha256=_VMkgdgo4ToLE8y1mOAjOKNhd0BnWoYu5r3BVBto6T0,1073
49
- corehttp-1.0.0b5.dist-info/METADATA,sha256=aTKL6zrEYPPerCUAbEj_uhl07Ex2CsbndYBd3nwjShA,5363
50
- corehttp-1.0.0b5.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
51
- corehttp-1.0.0b5.dist-info/top_level.txt,sha256=NAGJ-rIA_vW2ZJghxC5NqIbnfrXDBMmE-TAd-9ud4i4,9
52
- corehttp-1.0.0b5.dist-info/RECORD,,
48
+ corehttp-1.0.0b6.dist-info/LICENSE,sha256=_VMkgdgo4ToLE8y1mOAjOKNhd0BnWoYu5r3BVBto6T0,1073
49
+ corehttp-1.0.0b6.dist-info/METADATA,sha256=2gL4eNLJqe2RZthG1GvAQ0zHKZZn7nqrDFshWc8UdmQ,7548
50
+ corehttp-1.0.0b6.dist-info/WHEEL,sha256=iAkIy5fosb7FzIOwONchHf19Qu7_1wCWyFNR5gu9nU0,91
51
+ corehttp-1.0.0b6.dist-info/top_level.txt,sha256=NAGJ-rIA_vW2ZJghxC5NqIbnfrXDBMmE-TAd-9ud4i4,9
52
+ corehttp-1.0.0b6.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.42.0)
2
+ Generator: setuptools (75.3.2)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5