corehttp 1.0.0b5__py3-none-any.whl → 1.0.0b7__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 +1 -1
- corehttp/credentials.py +66 -25
- corehttp/exceptions.py +7 -6
- corehttp/instrumentation/__init__.py +9 -0
- corehttp/instrumentation/tracing/__init__.py +14 -0
- corehttp/instrumentation/tracing/_decorator.py +189 -0
- corehttp/instrumentation/tracing/_models.py +72 -0
- corehttp/instrumentation/tracing/_tracer.py +69 -0
- corehttp/instrumentation/tracing/opentelemetry.py +277 -0
- corehttp/instrumentation/tracing/utils.py +31 -0
- corehttp/paging.py +13 -0
- corehttp/rest/_aiohttp.py +21 -9
- corehttp/rest/_http_response_impl.py +9 -15
- corehttp/rest/_http_response_impl_async.py +2 -0
- corehttp/rest/_httpx.py +9 -9
- corehttp/rest/_requests_basic.py +17 -10
- corehttp/rest/_rest_py3.py +6 -10
- corehttp/runtime/pipeline/__init__.py +5 -9
- corehttp/runtime/pipeline/_base.py +3 -2
- corehttp/runtime/pipeline/_base_async.py +6 -8
- corehttp/runtime/pipeline/_tools.py +18 -2
- corehttp/runtime/pipeline/_tools_async.py +2 -4
- corehttp/runtime/policies/__init__.py +2 -0
- corehttp/runtime/policies/_authentication.py +76 -24
- corehttp/runtime/policies/_authentication_async.py +66 -21
- corehttp/runtime/policies/_distributed_tracing.py +169 -0
- corehttp/runtime/policies/_retry.py +8 -12
- corehttp/runtime/policies/_retry_async.py +5 -9
- corehttp/runtime/policies/_universal.py +15 -11
- corehttp/serialization.py +237 -3
- corehttp/settings.py +59 -0
- corehttp/transport/_base.py +1 -3
- corehttp/transport/_base_async.py +1 -3
- corehttp/transport/aiohttp/_aiohttp.py +41 -16
- corehttp/transport/requests/_bigger_block_size_http_adapters.py +1 -1
- corehttp/transport/requests/_requests_basic.py +33 -18
- corehttp/utils/_enum_meta.py +1 -1
- corehttp/utils/_utils.py +2 -1
- corehttp-1.0.0b7.dist-info/METADATA +196 -0
- corehttp-1.0.0b7.dist-info/RECORD +61 -0
- {corehttp-1.0.0b5.dist-info → corehttp-1.0.0b7.dist-info}/WHEEL +1 -1
- corehttp-1.0.0b5.dist-info/METADATA +0 -132
- corehttp-1.0.0b5.dist-info/RECORD +0 -52
- {corehttp-1.0.0b5.dist-info → corehttp-1.0.0b7.dist-info/licenses}/LICENSE +0 -0
- {corehttp-1.0.0b5.dist-info → corehttp-1.0.0b7.dist-info}/top_level.txt +0 -0
corehttp/settings.py
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# ------------------------------------
|
|
2
|
+
# Copyright (c) Microsoft Corporation.
|
|
3
|
+
# Licensed under the MIT License.
|
|
4
|
+
# ------------------------------------
|
|
5
|
+
import os
|
|
6
|
+
from typing import Union
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def _convert_bool(value: Union[str, bool]) -> bool:
|
|
10
|
+
"""Convert a string to True or False
|
|
11
|
+
|
|
12
|
+
If a boolean is passed in, it is returned as-is. Otherwise the function
|
|
13
|
+
maps the following strings, ignoring case:
|
|
14
|
+
|
|
15
|
+
* "yes", "1", "on" -> True
|
|
16
|
+
* "no", "0", "off" -> False
|
|
17
|
+
|
|
18
|
+
:param value: the value to convert
|
|
19
|
+
:type value: str or bool
|
|
20
|
+
:returns: A boolean value matching the intent of the input
|
|
21
|
+
:rtype: bool
|
|
22
|
+
:raises ValueError: If conversion to bool fails
|
|
23
|
+
|
|
24
|
+
"""
|
|
25
|
+
if isinstance(value, bool):
|
|
26
|
+
return value
|
|
27
|
+
val = value.lower()
|
|
28
|
+
if val in ["yes", "1", "on", "true", "True"]:
|
|
29
|
+
return True
|
|
30
|
+
if val in ["no", "0", "off", "false", "False"]:
|
|
31
|
+
return False
|
|
32
|
+
raise ValueError("Cannot convert {} to boolean value".format(value))
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class Settings:
|
|
36
|
+
"""Global settings for the SDK."""
|
|
37
|
+
|
|
38
|
+
def __init__(self) -> None:
|
|
39
|
+
self._tracing_enabled: bool = _convert_bool(os.environ.get("SDK_TRACING_ENABLED", False))
|
|
40
|
+
|
|
41
|
+
@property
|
|
42
|
+
def tracing_enabled(self) -> bool:
|
|
43
|
+
"""Whether tracing for SDKs is enabled.
|
|
44
|
+
|
|
45
|
+
:return: True if tracing is enabled, False otherwise.
|
|
46
|
+
:rtype: bool
|
|
47
|
+
"""
|
|
48
|
+
return self._tracing_enabled
|
|
49
|
+
|
|
50
|
+
@tracing_enabled.setter
|
|
51
|
+
def tracing_enabled(self, value: bool):
|
|
52
|
+
self._tracing_enabled = _convert_bool(value)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
settings: Settings = Settings()
|
|
56
|
+
"""The settings global instance.
|
|
57
|
+
|
|
58
|
+
:type settings: Settings
|
|
59
|
+
"""
|
corehttp/transport/_base.py
CHANGED
|
@@ -80,10 +80,8 @@ def _handle_non_stream_rest_response(response: HttpResponse) -> None:
|
|
|
80
80
|
"""
|
|
81
81
|
try:
|
|
82
82
|
response.read()
|
|
83
|
+
finally:
|
|
83
84
|
response.close()
|
|
84
|
-
except Exception as exc:
|
|
85
|
-
response.close()
|
|
86
|
-
raise exc
|
|
87
85
|
|
|
88
86
|
|
|
89
87
|
class HttpTransport(ContextManager["HttpTransport"], abc.ABC, Generic[HTTPRequestType, HTTPResponseType]):
|
|
@@ -46,10 +46,8 @@ async def _handle_non_stream_rest_response(response: AsyncHttpResponse) -> None:
|
|
|
46
46
|
"""
|
|
47
47
|
try:
|
|
48
48
|
await response.read()
|
|
49
|
+
finally:
|
|
49
50
|
await response.close()
|
|
50
|
-
except Exception as exc:
|
|
51
|
-
await response.close()
|
|
52
|
-
raise exc
|
|
53
51
|
|
|
54
52
|
|
|
55
53
|
class _ResponseStopIteration(Exception):
|
|
@@ -24,17 +24,19 @@
|
|
|
24
24
|
#
|
|
25
25
|
# --------------------------------------------------------------------------
|
|
26
26
|
from __future__ import annotations
|
|
27
|
-
from typing import Optional, TYPE_CHECKING, Type,
|
|
27
|
+
from typing import Optional, TYPE_CHECKING, Type, MutableMapping
|
|
28
28
|
from types import TracebackType
|
|
29
29
|
|
|
30
30
|
import logging
|
|
31
31
|
import asyncio
|
|
32
|
-
import aiohttp # pylint: disable=
|
|
33
|
-
import aiohttp.client_exceptions # pylint: disable=
|
|
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,
|
|
37
|
+
ServiceRequestTimeoutError,
|
|
37
38
|
ServiceResponseError,
|
|
39
|
+
ServiceResponseTimeoutError,
|
|
38
40
|
)
|
|
39
41
|
from .._base_async import AsyncHttpTransport, _handle_non_stream_rest_response
|
|
40
42
|
from .._base import _create_connection_config
|
|
@@ -52,6 +54,15 @@ if TYPE_CHECKING:
|
|
|
52
54
|
CONTENT_CHUNK_SIZE = 10 * 1024
|
|
53
55
|
_LOGGER = logging.getLogger(__name__)
|
|
54
56
|
|
|
57
|
+
try:
|
|
58
|
+
# ConnectionTimeoutError was only introduced in aiohttp 3.10 so we want to keep this
|
|
59
|
+
# backwards compatible. If client is using aiohttp <3.10, the behaviour will safely
|
|
60
|
+
# fall back to treating a TimeoutError as a ServiceResponseError (that wont be retried).
|
|
61
|
+
from aiohttp.client_exceptions import ConnectionTimeoutError
|
|
62
|
+
except ImportError:
|
|
63
|
+
|
|
64
|
+
class ConnectionTimeoutError(Exception): ... # type: ignore[no-redef]
|
|
65
|
+
|
|
55
66
|
|
|
56
67
|
class AioHttpTransport(AsyncHttpTransport):
|
|
57
68
|
"""AioHttp HTTP sender implementation.
|
|
@@ -71,6 +82,7 @@ class AioHttpTransport(AsyncHttpTransport):
|
|
|
71
82
|
raise ValueError("session_owner cannot be False if no session is provided")
|
|
72
83
|
self.connection_config = _create_connection_config(**kwargs)
|
|
73
84
|
self._use_env_settings = kwargs.pop("use_env_settings", True)
|
|
85
|
+
self._has_been_opened = False
|
|
74
86
|
|
|
75
87
|
async def __aenter__(self):
|
|
76
88
|
await self.open()
|
|
@@ -86,23 +98,31 @@ class AioHttpTransport(AsyncHttpTransport):
|
|
|
86
98
|
|
|
87
99
|
async def open(self):
|
|
88
100
|
"""Opens the connection."""
|
|
89
|
-
if
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
"
|
|
93
|
-
"
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
self.
|
|
97
|
-
|
|
98
|
-
|
|
101
|
+
if self._has_been_opened and not self.session:
|
|
102
|
+
raise ValueError(
|
|
103
|
+
"HTTP transport has already been closed. "
|
|
104
|
+
"You may check if you're calling a function outside of the `async with` of your client creation, "
|
|
105
|
+
"or if you called `await close()` on your client already."
|
|
106
|
+
)
|
|
107
|
+
if not self.session:
|
|
108
|
+
if self._session_owner:
|
|
109
|
+
jar = aiohttp.DummyCookieJar()
|
|
110
|
+
clientsession_kwargs = {
|
|
111
|
+
"trust_env": self._use_env_settings,
|
|
112
|
+
"cookie_jar": jar,
|
|
113
|
+
"auto_decompress": False,
|
|
114
|
+
}
|
|
115
|
+
self.session = aiohttp.ClientSession(**clientsession_kwargs)
|
|
116
|
+
else:
|
|
117
|
+
raise ValueError("session_owner cannot be False and no session is available")
|
|
118
|
+
|
|
119
|
+
self._has_been_opened = True
|
|
99
120
|
await self.session.__aenter__()
|
|
100
121
|
|
|
101
122
|
async def close(self):
|
|
102
123
|
"""Closes the connection."""
|
|
103
124
|
if self._session_owner and self.session:
|
|
104
125
|
await self.session.close()
|
|
105
|
-
self._session_owner = False
|
|
106
126
|
self.session = None
|
|
107
127
|
|
|
108
128
|
def _build_ssl_config(self, cert, verify):
|
|
@@ -221,11 +241,16 @@ class AioHttpTransport(AsyncHttpTransport):
|
|
|
221
241
|
)
|
|
222
242
|
if not stream:
|
|
223
243
|
await _handle_non_stream_rest_response(response)
|
|
224
|
-
|
|
244
|
+
except AttributeError as err:
|
|
245
|
+
if self.session is None:
|
|
246
|
+
raise ValueError("No session available for request.") from err
|
|
247
|
+
raise
|
|
225
248
|
except aiohttp.client_exceptions.ClientResponseError as err:
|
|
226
249
|
raise ServiceResponseError(err, error=err) from err
|
|
250
|
+
except ConnectionTimeoutError as err:
|
|
251
|
+
raise ServiceRequestTimeoutError(err, error=err) from err
|
|
227
252
|
except asyncio.TimeoutError as err:
|
|
228
|
-
raise
|
|
253
|
+
raise ServiceResponseTimeoutError(err, error=err) from err
|
|
229
254
|
except aiohttp.client_exceptions.ClientError as err:
|
|
230
255
|
raise ServiceRequestError(err, error=err) from err
|
|
231
256
|
return response
|
|
@@ -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=
|
|
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
|
|
|
@@ -24,18 +24,20 @@
|
|
|
24
24
|
#
|
|
25
25
|
# --------------------------------------------------------------------------
|
|
26
26
|
import logging
|
|
27
|
-
from typing import Optional, Union, TypeVar,
|
|
27
|
+
from typing import Optional, Union, TypeVar, MutableMapping, TYPE_CHECKING
|
|
28
28
|
from urllib3.util.retry import Retry
|
|
29
29
|
from urllib3.exceptions import (
|
|
30
30
|
ProtocolError,
|
|
31
31
|
NewConnectionError,
|
|
32
32
|
ConnectTimeoutError,
|
|
33
33
|
)
|
|
34
|
-
import requests # pylint: disable=
|
|
34
|
+
import requests # pylint: disable=networking-import-outside-azure-core-transport
|
|
35
35
|
|
|
36
36
|
from ...exceptions import (
|
|
37
37
|
ServiceRequestError,
|
|
38
|
+
ServiceRequestTimeoutError,
|
|
38
39
|
ServiceResponseError,
|
|
40
|
+
ServiceResponseTimeoutError,
|
|
39
41
|
IncompleteReadError,
|
|
40
42
|
HttpResponseError,
|
|
41
43
|
)
|
|
@@ -84,12 +86,13 @@ class RequestsTransport(HttpTransport):
|
|
|
84
86
|
raise ValueError("session_owner cannot be False if no session is provided")
|
|
85
87
|
self.connection_config = _create_connection_config(**kwargs)
|
|
86
88
|
self._use_env_settings = kwargs.pop("use_env_settings", True)
|
|
89
|
+
self._has_been_opened = False
|
|
87
90
|
|
|
88
91
|
def __enter__(self) -> "RequestsTransport":
|
|
89
92
|
self.open()
|
|
90
93
|
return self
|
|
91
94
|
|
|
92
|
-
def __exit__(self, *args):
|
|
95
|
+
def __exit__(self, *args):
|
|
93
96
|
self.close()
|
|
94
97
|
|
|
95
98
|
def _init_session(self, session: requests.Session) -> None:
|
|
@@ -106,19 +109,26 @@ class RequestsTransport(HttpTransport):
|
|
|
106
109
|
session.mount(p, adapter)
|
|
107
110
|
|
|
108
111
|
def open(self):
|
|
109
|
-
if
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
112
|
+
if self._has_been_opened and not self.session:
|
|
113
|
+
raise ValueError(
|
|
114
|
+
"HTTP transport has already been closed. "
|
|
115
|
+
"You may check if you're calling a function outside of the `with` of your client creation, "
|
|
116
|
+
"or if you called `close()` on your client already."
|
|
117
|
+
)
|
|
118
|
+
if not self.session:
|
|
119
|
+
if self._session_owner:
|
|
120
|
+
self.session = requests.Session()
|
|
121
|
+
self._init_session(self.session)
|
|
122
|
+
else:
|
|
123
|
+
raise ValueError("session_owner cannot be False and no session is available")
|
|
124
|
+
self._has_been_opened = True
|
|
114
125
|
|
|
115
126
|
def close(self):
|
|
116
127
|
if self._session_owner and self.session:
|
|
117
128
|
self.session.close()
|
|
118
|
-
self._session_owner = False
|
|
119
129
|
self.session = None
|
|
120
130
|
|
|
121
|
-
def send(
|
|
131
|
+
def send( # pylint: disable=too-many-statements
|
|
122
132
|
self,
|
|
123
133
|
request: "RestHttpRequest",
|
|
124
134
|
*,
|
|
@@ -165,13 +175,18 @@ class RequestsTransport(HttpTransport):
|
|
|
165
175
|
)
|
|
166
176
|
response.raw.enforce_content_length = True
|
|
167
177
|
|
|
168
|
-
except
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
178
|
+
except AttributeError as err:
|
|
179
|
+
if self.session is None:
|
|
180
|
+
raise ValueError("No session available for request.") from err
|
|
181
|
+
raise
|
|
182
|
+
except NewConnectionError as err:
|
|
172
183
|
error = ServiceRequestError(err, error=err)
|
|
184
|
+
except ConnectTimeoutError as err:
|
|
185
|
+
error = ServiceRequestTimeoutError(err, error=err)
|
|
186
|
+
except requests.exceptions.ConnectTimeout as err:
|
|
187
|
+
error = ServiceRequestTimeoutError(err, error=err)
|
|
173
188
|
except requests.exceptions.ReadTimeout as err:
|
|
174
|
-
error =
|
|
189
|
+
error = ServiceResponseTimeoutError(err, error=err)
|
|
175
190
|
except requests.exceptions.ConnectionError as err:
|
|
176
191
|
if err.args and isinstance(err.args[0], ProtocolError):
|
|
177
192
|
error = ServiceResponseError(err, error=err)
|
|
@@ -180,13 +195,13 @@ class RequestsTransport(HttpTransport):
|
|
|
180
195
|
except requests.exceptions.ChunkedEncodingError as err:
|
|
181
196
|
msg = err.__str__()
|
|
182
197
|
if "IncompleteRead" in msg:
|
|
183
|
-
_LOGGER.warning("Incomplete download
|
|
198
|
+
_LOGGER.warning("Incomplete download.")
|
|
184
199
|
error = IncompleteReadError(err, error=err)
|
|
185
200
|
else:
|
|
186
|
-
_LOGGER.warning("Unable to stream download
|
|
201
|
+
_LOGGER.warning("Unable to stream download.")
|
|
187
202
|
error = HttpResponseError(err, error=err)
|
|
188
203
|
except requests.RequestException as err:
|
|
189
|
-
error =
|
|
204
|
+
error = ServiceResponseError(err, error=err)
|
|
190
205
|
|
|
191
206
|
if error:
|
|
192
207
|
raise error
|
corehttp/utils/_enum_meta.py
CHANGED
|
@@ -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())
|
|
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`.
|
corehttp/utils/_utils.py
CHANGED
|
@@ -169,9 +169,10 @@ def get_file_items(files: "FilesType") -> Sequence[Tuple[str, "FileType"]]:
|
|
|
169
169
|
|
|
170
170
|
def get_running_async_lock() -> AsyncContextManager:
|
|
171
171
|
"""Get a lock instance from the async library that the current context is running under.
|
|
172
|
+
|
|
172
173
|
:return: An instance of the running async library's Lock class.
|
|
173
174
|
:rtype: AsyncContextManager
|
|
174
|
-
:raises
|
|
175
|
+
:raises RuntimeError: if the current context is not running under an async library.
|
|
175
176
|
"""
|
|
176
177
|
|
|
177
178
|
try:
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: corehttp
|
|
3
|
+
Version: 1.0.0b7
|
|
4
|
+
Summary: CoreHTTP Library for Python
|
|
5
|
+
Home-page: https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/core/corehttp
|
|
6
|
+
Author: Microsoft Corporation
|
|
7
|
+
Author-email: azpysdkhelp@microsoft.com
|
|
8
|
+
License: MIT License
|
|
9
|
+
Keywords: typespec,core
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Programming Language :: Python
|
|
12
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
20
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
21
|
+
Requires-Python: >=3.9
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
License-File: LICENSE
|
|
24
|
+
Requires-Dist: typing-extensions>=4.6.0
|
|
25
|
+
Provides-Extra: requests
|
|
26
|
+
Requires-Dist: requests>=2.18.4; extra == "requests"
|
|
27
|
+
Provides-Extra: aiohttp
|
|
28
|
+
Requires-Dist: aiohttp>=3.0; extra == "aiohttp"
|
|
29
|
+
Provides-Extra: httpx
|
|
30
|
+
Requires-Dist: httpx>=0.25.0; extra == "httpx"
|
|
31
|
+
Provides-Extra: tracing
|
|
32
|
+
Requires-Dist: opentelemetry-api~=1.26; extra == "tracing"
|
|
33
|
+
Dynamic: author
|
|
34
|
+
Dynamic: author-email
|
|
35
|
+
Dynamic: classifier
|
|
36
|
+
Dynamic: description
|
|
37
|
+
Dynamic: description-content-type
|
|
38
|
+
Dynamic: home-page
|
|
39
|
+
Dynamic: keywords
|
|
40
|
+
Dynamic: license
|
|
41
|
+
Dynamic: license-file
|
|
42
|
+
Dynamic: provides-extra
|
|
43
|
+
Dynamic: requires-dist
|
|
44
|
+
Dynamic: requires-python
|
|
45
|
+
Dynamic: summary
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
# Core HTTP shared client library for Python
|
|
49
|
+
|
|
50
|
+
`corehttp` provides shared exceptions and modules for Python SDK client libraries.
|
|
51
|
+
|
|
52
|
+
## Getting started
|
|
53
|
+
|
|
54
|
+
Typically, you will not need to install `corehttp`, as it will be installed when you install one of the client libraries using it.
|
|
55
|
+
|
|
56
|
+
### Transports
|
|
57
|
+
|
|
58
|
+
To use `corehttp`, you will need to choose a transport implementation. `corehttp` provides the following transports:
|
|
59
|
+
|
|
60
|
+
Synchronous transports:
|
|
61
|
+
- `RequestsTransport` - A synchronous transport based on the [Requests](https://requests.readthedocs.io/en/master/) library.
|
|
62
|
+
- `HttpXTransport` - An synchronous transport based on the [HTTPX](https://www.python-httpx.org/) library.
|
|
63
|
+
|
|
64
|
+
Asynchronous transports:
|
|
65
|
+
- `AioHttpTransport` - An asynchronous transport based on the [aiohttp](https://docs.aiohttp.org/en/stable/) library.
|
|
66
|
+
- `AsyncHttpXTransport` - An asynchronous transport based on the [HTTPX](https://www.python-httpx.org/) library.
|
|
67
|
+
|
|
68
|
+
Each transport has its own dependencies, which you can install using the `corehttp` extras:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
# Install individually.
|
|
72
|
+
pip install corehttp[requests]
|
|
73
|
+
pip install corehttp[aiohttp]
|
|
74
|
+
pip install corehttp[httpx]
|
|
75
|
+
|
|
76
|
+
# Install multiple.
|
|
77
|
+
pip install corehttp[requests,httpx]
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
If no transports are specified, `corehttp` will default to using `RequestsTransport` for synchronous pipeline requests and `AioHttpTransport` for asynchronous pipeline requests.
|
|
81
|
+
|
|
82
|
+
## Contributing
|
|
83
|
+
|
|
84
|
+
This project welcomes contributions and suggestions. Most contributions require
|
|
85
|
+
you to agree to a Contributor License Agreement (CLA) declaring that you have
|
|
86
|
+
the right to, and actually do, grant us the rights to use your contribution.
|
|
87
|
+
For details, visit [https://cla.microsoft.com](https://cla.microsoft.com).
|
|
88
|
+
|
|
89
|
+
When you submit a pull request, a CLA-bot will automatically determine whether
|
|
90
|
+
you need to provide a CLA and decorate the PR appropriately (e.g., label,
|
|
91
|
+
comment). Simply follow the instructions provided by the bot. You will only
|
|
92
|
+
need to do this once across all repos using our CLA.
|
|
93
|
+
|
|
94
|
+
This project has adopted the
|
|
95
|
+
[Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
|
|
96
|
+
For more information, see the
|
|
97
|
+
[Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/)
|
|
98
|
+
or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any
|
|
99
|
+
additional questions or comments.
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
# Release History
|
|
105
|
+
|
|
106
|
+
## 1.0.0b7 (2026-02-05)
|
|
107
|
+
|
|
108
|
+
### Features Added
|
|
109
|
+
|
|
110
|
+
- Native tracing support was added. [#39172](https://github.com/Azure/azure-sdk-for-python/pull/39172)
|
|
111
|
+
- The `OpenTelemetryTracer` class was added to the `corehttp.instrumentation.tracing.opentelemetry` module. This is a wrapper around the OpenTelemetry tracer that is used to create spans for SDK operations.
|
|
112
|
+
- Added a `get_tracer` method to the new `corehttp.instrumentation` module. This method returns an instance of the `OpenTelemetryTracer` class if OpenTelemetry is available.
|
|
113
|
+
- A `TracingOptions` TypedDict class was added to define the options that SDK users can use to configure tracing per-operation. These options include the ability to enable or disable tracing and set additional attributes on spans.
|
|
114
|
+
- Example usage: `client.method(tracing_options={"enabled": True, "attributes": {"foo": "bar"}})`
|
|
115
|
+
- `DistributedHttpTracingPolicy` and `distributed_trace`/`distributed_trace_async` decorators were added to support OpenTelemetry tracing for SDK operations.
|
|
116
|
+
- SDK clients can define an `_instrumentation_config` class variable to configure the OpenTelemetry tracer used in method span creation. Possible configuration options are `library_name`, `library_version`, `schema_url`, and `attributes`.
|
|
117
|
+
- Added a global settings object, `corehttp.settings`, to the `corehttp` package. This object can be used to set global settings for the `corehttp` package. Currently the only setting is `tracing_enabled` for enabling/disabling tracing. [#39172](https://github.com/Azure/azure-sdk-for-python/pull/39172)
|
|
118
|
+
- Added `start_time` and `context` keyword arguments to `OpenTelemetryTracer.start_span` and `start_as_current_span` methods.
|
|
119
|
+
- Added `set_span_error_status` static method to `OpenTelemetryTracer` for setting a span's status to ERROR.
|
|
120
|
+
- Added `is_generated_model`, `attribute_list`, and `TypeHandlerRegistry` to `corehttp.serialization` module for SDK model handling.
|
|
121
|
+
|
|
122
|
+
### Bugs Fixed
|
|
123
|
+
|
|
124
|
+
- Fixed `retry_backoff_max` being ignored in retry policies when configuring retries.
|
|
125
|
+
- Raise correct exception if transport is used while already closed.
|
|
126
|
+
- A timeout error when using the `aiohttp` transport will now be raised as a `corehttp.exceptions.ServiceResponseTimeoutError`, a subtype of the previously raised `ServiceResponseError`.
|
|
127
|
+
- When using with `aiohttp` 3.10 or later, a connection timeout error will now be raised as a `corehttp.exceptions.ServiceRequestTimeoutError`, which can be retried.
|
|
128
|
+
- Fixed leaked requests and aiohttp exceptions for streamed responses.
|
|
129
|
+
- Improved granularity of `ServiceRequestError` and `ServiceResponseError` exceptions raised in timeout scenarios from the requests and aiohttp transports.
|
|
130
|
+
- `BearerTokenCredentialPolicy` and `AsyncBearerTokenCredentialPolicy` will now properly chain exceptions raised during claims challenge handling. If a credential raises an exception when attempting to acquire a token in response to a claims challenge, that exception will be raised with the original 401 response as the cause.
|
|
131
|
+
|
|
132
|
+
### Other Changes
|
|
133
|
+
|
|
134
|
+
- Added `opentelemetry-api` as an optional dependency for tracing. [#39172](https://github.com/Azure/azure-sdk-for-python/pull/39172)
|
|
135
|
+
|
|
136
|
+
## 1.0.0b6 (2025-03-27)
|
|
137
|
+
|
|
138
|
+
### Features Added
|
|
139
|
+
|
|
140
|
+
- 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)
|
|
141
|
+
- 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)
|
|
142
|
+
- 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)
|
|
143
|
+
- `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)
|
|
144
|
+
- These policies now also check the `refresh_on` attribute when determining if a new token request should be made.
|
|
145
|
+
- 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)
|
|
146
|
+
- Added `auth_flows` support in `BearerTokenCredentialPolicy`. [#40084](https://github.com/Azure/azure-sdk-for-python/pull/40084)
|
|
147
|
+
|
|
148
|
+
### Breaking Changes
|
|
149
|
+
|
|
150
|
+
- 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)
|
|
151
|
+
- The `AccessToken` class has been removed and replaced with a new `AccessTokenInfo` class. [#38346](https://github.com/Azure/azure-sdk-for-python/pull/38346)
|
|
152
|
+
- `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)
|
|
153
|
+
|
|
154
|
+
## 1.0.0b5 (2024-02-29)
|
|
155
|
+
|
|
156
|
+
### Other Changes
|
|
157
|
+
|
|
158
|
+
- Accept float for `retry_after` header.
|
|
159
|
+
|
|
160
|
+
## 1.0.0b4 (2024-02-23)
|
|
161
|
+
|
|
162
|
+
### Other Changes
|
|
163
|
+
|
|
164
|
+
- Relax type checking in `Pipeline` constructors to only check that each user-supplied policy object has either a `send` method or both an `on_request` and `on_response` method. This allows for more flexible policy implementations. [#34296](https://github.com/Azure/azure-sdk-for-python/pull/34296)
|
|
165
|
+
|
|
166
|
+
## 1.0.0b3 (2024-02-01)
|
|
167
|
+
|
|
168
|
+
### Features Added
|
|
169
|
+
|
|
170
|
+
- Support tuple input for `files` values to `corehttp.rest.HttpRequest` #34082
|
|
171
|
+
- Support simultaneous `files` and `data` field entry into `corehttp.rest.HttpRequest` #34082
|
|
172
|
+
|
|
173
|
+
## 1.0.0b2 (2023-11-14)
|
|
174
|
+
|
|
175
|
+
### Features Added
|
|
176
|
+
|
|
177
|
+
- Added the initial implementation of the HTTPX transport. [#32813](https://github.com/Azure/azure-sdk-for-python/pull/32813)
|
|
178
|
+
|
|
179
|
+
### Breaking Changes
|
|
180
|
+
|
|
181
|
+
- Removed `requests` as a default dependency of `corehttp`. This is now an "extras" dependency and can be installed via `corehttp[requests]`. [#32813](https://github.com/Azure/azure-sdk-for-python/pull/32813)
|
|
182
|
+
- Renamed the `aio` extra to `aiohttp`. [#32813](https://github.com/Azure/azure-sdk-for-python/pull/32813)
|
|
183
|
+
|
|
184
|
+
### Bugs Fixed
|
|
185
|
+
|
|
186
|
+
- Fixed an issue with `multipart/form-data` in the async transport where `data` was not getting encoded into the request body. [#32473](https://github.com/Azure/azure-sdk-for-python/pull/32473)
|
|
187
|
+
- Fixed an issue with `connection_verify`, `connection_cert`, and `connection_timeout` not being propagated to underlying transports. [#33057](https://github.com/Azure/azure-sdk-for-python/pull/33057)
|
|
188
|
+
- Fixed an issue with the `aiohttp` transport not using SSL by default. [#33057](https://github.com/Azure/azure-sdk-for-python/pull/33057)
|
|
189
|
+
|
|
190
|
+
### Other Changes
|
|
191
|
+
|
|
192
|
+
- Added extras for `httpx`. [#32813](https://github.com/Azure/azure-sdk-for-python/pull/32813)
|
|
193
|
+
|
|
194
|
+
## 1.0.0b1 (2023-10-18)
|
|
195
|
+
|
|
196
|
+
* Initial Release
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
corehttp/__init__.py,sha256=Wdidh085sV_IhdV_wU79t7FpghhpyxCsRnZGOUoQ0xs,1443
|
|
2
|
+
corehttp/_match_conditions.py,sha256=3TIhb4vBO1hBe7MaQwS_9i-d6p7o4jn5L6M-OiQahkg,1864
|
|
3
|
+
corehttp/_version.py,sha256=VyIft7_Im1KeJZKTuvpUbQW8Bf73j9wwDlOmTytSBiM,494
|
|
4
|
+
corehttp/credentials.py,sha256=0_-W5sMBrrZmHEcv4h51lvAwWNCZBf3tvkslNPgZgo0,7018
|
|
5
|
+
corehttp/exceptions.py,sha256=mKh6wtuYi2aqiZRicNjE_693gBJMkNaWJLuXJ-VE444,11658
|
|
6
|
+
corehttp/paging.py,sha256=H-ctDDRWtp8i3R7xZwFQQEK-5YGNYHSAtk8hdg99efs,10039
|
|
7
|
+
corehttp/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
|
+
corehttp/serialization.py,sha256=MeQVSOpzlzcf4BomkyF3eVjETciABEN75e8sT0Bsakk,13422
|
|
9
|
+
corehttp/settings.py,sha256=7kEnzs09jAHYytt59BGHh8g10y2YHlP7j3SkrTMpD6c,1618
|
|
10
|
+
corehttp/instrumentation/__init__.py,sha256=_zOuDpRLiAvHgJIHcpgI-w-ZVmFZ8Ucl5ikdWnNVVsE,224
|
|
11
|
+
corehttp/instrumentation/tracing/__init__.py,sha256=y6FMPOMDsFwyQNWtpf0KJsemYpvU_sGuWuZ309k0yB4,391
|
|
12
|
+
corehttp/instrumentation/tracing/_decorator.py,sha256=tPiN_C0hEqLAgm4IqRY4-gaJllnsLpVTJcGVg95gmlE,7402
|
|
13
|
+
corehttp/instrumentation/tracing/_models.py,sha256=4RPQ9uQUiLepRnQGLUxWy8-Ohi7JWhmAT1qvFZKNcF0,2273
|
|
14
|
+
corehttp/instrumentation/tracing/_tracer.py,sha256=-q5DMsbAz5L_sD3NrpPf991o4ggC4G9d4iFcmxM5Gx8,2443
|
|
15
|
+
corehttp/instrumentation/tracing/opentelemetry.py,sha256=VTAPfgppUkDkyVg30SwwYYfg5ub2raC3FpzqsVLnzuA,10729
|
|
16
|
+
corehttp/instrumentation/tracing/utils.py,sha256=TIwtUo4BizEIg-HnwCQX0L24yVWAh8X7NV5lmZKvCFI,819
|
|
17
|
+
corehttp/rest/__init__.py,sha256=GwPFwVYZ9aa4DI9f2-oQGr2nfF7wXvVL80V51ymAjAk,1467
|
|
18
|
+
corehttp/rest/_aiohttp.py,sha256=uZmU5CgzKhIjsQd6dEG6HUiRgpgiqFa_GCO4SSqsfX8,11965
|
|
19
|
+
corehttp/rest/_helpers.py,sha256=ZhXhAiAw8DW_gxUPE3tumMplRS1Jt2h6joLVsk-u6yI,7897
|
|
20
|
+
corehttp/rest/_http_response_impl.py,sha256=REWjOWJERB-EBtU2SSilGd3L1wSKCf-jWeTUj6Q6Z0g,11284
|
|
21
|
+
corehttp/rest/_http_response_impl_async.py,sha256=QAcrTYMH1Sp9R5cVQOFrRnZli7wEzjd5Fv9rlJdmDsc,4974
|
|
22
|
+
corehttp/rest/_httpx.py,sha256=dPmiEsB29_Auocm4EdmjIuMjF55zbPjdmk1YjqliJTE,8079
|
|
23
|
+
corehttp/rest/_requests_basic.py,sha256=c2zRx79AMd-gdWwwVZAqxIBSLSoJx8fedQCoQI_ofaQ,7985
|
|
24
|
+
corehttp/rest/_rest_py3.py,sha256=Pj9HfktnJIPIr5lTUpNNIlC-ZU5pXRdX-tRD29yVjOo,14033
|
|
25
|
+
corehttp/runtime/__init__.py,sha256=OeG_5-Oq3Zp9rJcMfRNiYLv3V39wIZxDcQ-unerauDw,1469
|
|
26
|
+
corehttp/runtime/_base.py,sha256=gr2xJQJeWuOmtrudFhM07_6ASIhUX66jR1nxSRMh068,5056
|
|
27
|
+
corehttp/runtime/_pipeline_client.py,sha256=A2R0JEcfFIOe6b38VzuQatAxfbiBhtu_RCpOlM968b0,7099
|
|
28
|
+
corehttp/runtime/_pipeline_client_async.py,sha256=dBUqhntQzcS1kbQ6z7d6C4Y3HDghLr4jrobtlKvbVTw,10378
|
|
29
|
+
corehttp/runtime/pipeline/__init__.py,sha256=LYUDTtHlJ0XOIgraCjk-y9BGjwnNtXWpy-gQg2ufV_Q,7732
|
|
30
|
+
corehttp/runtime/pipeline/_base.py,sha256=FJfhSKy9eaQtmBYllqahfZxYHLGx_S4RocVSN8Sdhpk,6952
|
|
31
|
+
corehttp/runtime/pipeline/_base_async.py,sha256=cBiLHuRsg6poISOvu9lfBl5anXowkN7RGzuIGBfXOhw,7381
|
|
32
|
+
corehttp/runtime/pipeline/_tools.py,sha256=E351oLFCdM9e4jP-CANESD8rifChOTH_W0bapwZndr0,2502
|
|
33
|
+
corehttp/runtime/pipeline/_tools_async.py,sha256=r9Apyo4BOTKSRTfyFjLmcrGiVoulrnpxqkNOmzHOrGg,2151
|
|
34
|
+
corehttp/runtime/policies/__init__.py,sha256=fPT19op2ZlTQJ7jLpaMCZeruB0Ip2Ex_a7uY5wUHxG0,2295
|
|
35
|
+
corehttp/runtime/policies/_authentication.py,sha256=5n4gKzTAJDQBc65U8zI5ezqJEsYNSNRaAGH4W0BGzo8,11632
|
|
36
|
+
corehttp/runtime/policies/_authentication_async.py,sha256=lz4bJh2u6Er7qdgwq2ejXtDDUqS2Qvbq7W_VaOfVNFQ,9356
|
|
37
|
+
corehttp/runtime/policies/_base.py,sha256=zLM4NIwGQwZ75k-KPo3PthmDCpDidHvZy91ok0wnFvQ,5063
|
|
38
|
+
corehttp/runtime/policies/_base_async.py,sha256=nOZ-3lrKmfnFam3FbSY4wd9sOI7r5pI2HSdqgOC4Vz4,2531
|
|
39
|
+
corehttp/runtime/policies/_distributed_tracing.py,sha256=Fky-cFTAiiHeTdarYf6GS8Iq_rbwngun-eTKk7ilxGY,6675
|
|
40
|
+
corehttp/runtime/policies/_retry.py,sha256=Tr_9R_sWNcPrnPUYoakAEqpaY9d1to6T5Lf216xk0Ts,24393
|
|
41
|
+
corehttp/runtime/policies/_retry_async.py,sha256=-g7ZeqarL-5d7MFSDylvyBTLsy8PRazUY5Nz83Qm8co,9122
|
|
42
|
+
corehttp/runtime/policies/_universal.py,sha256=LlE5AIDo3rFn0u6qSNfwCKiLQMuiL2jW4eQpPVIkue0,20028
|
|
43
|
+
corehttp/runtime/policies/_utils.py,sha256=kDnGRpC3MxsW7zHZRfkLyPMArlzY4n7vBhwQQVWKQuI,3596
|
|
44
|
+
corehttp/transport/__init__.py,sha256=6A1i9gjM5isBPb-AL-2JTzxn7pssDj8ux9Ujn6rHjlY,1442
|
|
45
|
+
corehttp/transport/_base.py,sha256=qsIG3LX6xZpSmJaPVxtlJNePW62Uyl1gmoCQOsM_GoI,5048
|
|
46
|
+
corehttp/transport/_base_async.py,sha256=BuoHO2gas9k9qBKW5WiY_taLO9tr-MovkBY-1sOrTCM,3762
|
|
47
|
+
corehttp/transport/aiohttp/__init__.py,sha256=gdCazQ9XMZ6xgJCakm4efxECBFU-IIxKuMF3VmM9dHQ,1381
|
|
48
|
+
corehttp/transport/aiohttp/_aiohttp.py,sha256=M91Yda3dAdLqk8-dWXyISkf3oZBVdLmnp45CCseoFVA,10800
|
|
49
|
+
corehttp/transport/httpx/__init__.py,sha256=IbjUxTxtGljHK9nq6w0kAFeHd73zAl7qtd27qlqCrzg,1412
|
|
50
|
+
corehttp/transport/httpx/_httpx.py,sha256=of8Mxyfzm1Rd4ltYNt8wGz1xuTnJVef0KaiJyl99KfE,8579
|
|
51
|
+
corehttp/transport/requests/__init__.py,sha256=WPdzueqs0eLfvumuedxXPsOIpPCq3dDOvdzmIK4nyHs,1390
|
|
52
|
+
corehttp/transport/requests/_bigger_block_size_http_adapters.py,sha256=S1zE3v6QwPtdEm2cLdu8B5iW5WbETTgpv0datZ9g_eo,2487
|
|
53
|
+
corehttp/transport/requests/_requests_basic.py,sha256=ZMAQv9jFeomXiOn0v16qUP7iUq3J67pbiKBVEq3H9Ts,8948
|
|
54
|
+
corehttp/utils/__init__.py,sha256=_h2vJje1Tb-w_9mXm0hO_s2S1b48HLzI4taIlvz3Eu4,1648
|
|
55
|
+
corehttp/utils/_enum_meta.py,sha256=9rdoxCOiBnYFMUC8-8_yaoCA9s_GdbIkguxk3Z71iyM,2774
|
|
56
|
+
corehttp/utils/_utils.py,sha256=ZSp4H0TBKFZzIXav7-WwadirC3FLjdk8mTWI7fWE19A,6064
|
|
57
|
+
corehttp-1.0.0b7.dist-info/licenses/LICENSE,sha256=_VMkgdgo4ToLE8y1mOAjOKNhd0BnWoYu5r3BVBto6T0,1073
|
|
58
|
+
corehttp-1.0.0b7.dist-info/METADATA,sha256=2CTz5IW8LveWt7D3JkssRH3KrCKYnKe9rkSIOLRnXjk,11139
|
|
59
|
+
corehttp-1.0.0b7.dist-info/WHEEL,sha256=1tXe9gY0PYatrMPMDd6jXqjfpz_B-Wqm32CPfRC58XU,91
|
|
60
|
+
corehttp-1.0.0b7.dist-info/top_level.txt,sha256=NAGJ-rIA_vW2ZJghxC5NqIbnfrXDBMmE-TAd-9ud4i4,9
|
|
61
|
+
corehttp-1.0.0b7.dist-info/RECORD,,
|