corehttp 1.0.0b4__tar.gz → 1.0.0b6__tar.gz
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-1.0.0b6/CHANGELOG.md +63 -0
- {corehttp-1.0.0b4/corehttp.egg-info → corehttp-1.0.0b6}/PKG-INFO +25 -1
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/corehttp/_version.py +1 -1
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/corehttp/credentials.py +54 -22
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/corehttp/exceptions.py +7 -6
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/corehttp/rest/_aiohttp.py +4 -4
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/corehttp/rest/_http_response_impl.py +2 -8
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/corehttp/rest/_httpx.py +1 -1
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/corehttp/rest/_requests_basic.py +4 -5
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/corehttp/rest/_rest_py3.py +4 -8
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/corehttp/runtime/pipeline/__init__.py +3 -7
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/corehttp/runtime/pipeline/_base.py +1 -1
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/corehttp/runtime/pipeline/_base_async.py +4 -8
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/corehttp/runtime/pipeline/_tools_async.py +2 -4
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/corehttp/runtime/policies/_authentication.py +53 -24
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/corehttp/runtime/policies/_authentication_async.py +45 -19
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/corehttp/runtime/policies/_retry.py +1 -1
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/corehttp/runtime/policies/_retry_async.py +1 -1
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/corehttp/runtime/policies/_universal.py +4 -11
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/corehttp/runtime/policies/_utils.py +1 -1
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/corehttp/serialization.py +1 -1
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/corehttp/transport/aiohttp/_aiohttp.py +2 -2
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/corehttp/transport/requests/_bigger_block_size_http_adapters.py +1 -1
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/corehttp/transport/requests/_requests_basic.py +2 -2
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/corehttp/utils/_enum_meta.py +1 -1
- {corehttp-1.0.0b4 → corehttp-1.0.0b6/corehttp.egg-info}/PKG-INFO +25 -1
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/corehttp.egg-info/SOURCES.txt +8 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/pyproject.toml +1 -1
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/samples/sample_async_pipeline_client.py +0 -10
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/tests/async_tests/test_authentication_async.py +71 -25
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/tests/async_tests/test_rest_http_response_async.py +27 -27
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/tests/async_tests/test_rest_stream_responses_async.py +1 -34
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/tests/async_tests/test_retry_policy_async.py +1 -1
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/tests/async_tests/test_streaming_async.py +34 -148
- corehttp-1.0.0b6/tests/perf_tests/__init__.py +0 -0
- corehttp-1.0.0b6/tests/perf_tests/_test_base.py +258 -0
- corehttp-1.0.0b6/tests/perf_tests/custom_iterator.py +80 -0
- corehttp-1.0.0b6/tests/perf_tests/download_binary.py +94 -0
- corehttp-1.0.0b6/tests/perf_tests/list_entities_json.py +135 -0
- corehttp-1.0.0b6/tests/perf_tests/query_entities_json.py +85 -0
- corehttp-1.0.0b6/tests/perf_tests/update_entity_json.py +92 -0
- corehttp-1.0.0b6/tests/perf_tests/upload_binary.py +91 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/tests/test_authentication.py +77 -32
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/tests/test_exceptions.py +14 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/tests/test_rest_stream_responses.py +0 -53
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/tests/test_retry_policy.py +3 -1
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/tests/test_streaming.py +32 -131
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/tests/test_utils.py +12 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/tests/testserver_tests/coretestserver/coretestserver/test_routes/helpers.py +2 -2
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/tests/testserver_tests/coretestserver/coretestserver/test_routes/multipart.py +1 -7
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/tests/testserver_tests/coretestserver/coretestserver/test_routes/streams.py +14 -0
- corehttp-1.0.0b4/CHANGELOG.md +0 -39
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/LICENSE +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/MANIFEST.in +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/README.md +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/corehttp/__init__.py +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/corehttp/_match_conditions.py +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/corehttp/paging.py +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/corehttp/py.typed +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/corehttp/rest/__init__.py +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/corehttp/rest/_helpers.py +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/corehttp/rest/_http_response_impl_async.py +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/corehttp/runtime/__init__.py +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/corehttp/runtime/_base.py +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/corehttp/runtime/_pipeline_client.py +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/corehttp/runtime/_pipeline_client_async.py +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/corehttp/runtime/pipeline/_tools.py +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/corehttp/runtime/policies/__init__.py +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/corehttp/runtime/policies/_base.py +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/corehttp/runtime/policies/_base_async.py +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/corehttp/transport/__init__.py +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/corehttp/transport/_base.py +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/corehttp/transport/_base_async.py +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/corehttp/transport/aiohttp/__init__.py +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/corehttp/transport/httpx/__init__.py +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/corehttp/transport/httpx/_httpx.py +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/corehttp/transport/requests/__init__.py +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/corehttp/utils/__init__.py +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/corehttp/utils/_utils.py +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/corehttp.egg-info/dependency_links.txt +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/corehttp.egg-info/not-zip-safe +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/corehttp.egg-info/requires.txt +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/corehttp.egg-info/top_level.txt +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/samples/sample_pipeline_client.py +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/setup.cfg +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/setup.py +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/tests/async_tests/conftest.py +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/tests/async_tests/rest_client_async.py +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/tests/async_tests/test_content_length_checking_async.py +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/tests/async_tests/test_paging_async.py +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/tests/async_tests/test_pipeline_async.py +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/tests/async_tests/test_rest_context_manager_async.py +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/tests/async_tests/test_rest_headers_async.py +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/tests/async_tests/test_rest_http_request_async.py +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/tests/async_tests/test_testserver_async.py +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/tests/async_tests/test_universal_http_async.py +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/tests/conftest.py +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/tests/rest_client.py +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/tests/test_content_length_checking.py +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/tests/test_enums.py +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/tests/test_error_map.py +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/tests/test_paging.py +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/tests/test_pipeline.py +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/tests/test_requests_universal.py +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/tests/test_rest_context_manager.py +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/tests/test_rest_headers.py +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/tests/test_rest_http_request.py +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/tests/test_rest_http_response.py +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/tests/test_rest_query.py +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/tests/test_serialization.py +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/tests/test_stream_generator.py +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/tests/test_testserver.py +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/tests/test_universal_pipeline.py +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/tests/test_user_agent_policy.py +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/tests/testserver_tests/coretestserver/coretestserver/__init__.py +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/tests/testserver_tests/coretestserver/coretestserver/test_routes/__init__.py +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/tests/testserver_tests/coretestserver/coretestserver/test_routes/basic.py +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/tests/testserver_tests/coretestserver/coretestserver/test_routes/encoding.py +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/tests/testserver_tests/coretestserver/coretestserver/test_routes/errors.py +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/tests/testserver_tests/coretestserver/coretestserver/test_routes/headers.py +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/tests/testserver_tests/coretestserver/coretestserver/test_routes/structures.py +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/tests/testserver_tests/coretestserver/coretestserver/test_routes/urlencoded.py +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/tests/testserver_tests/coretestserver/coretestserver/test_routes/xml_route.py +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/tests/testserver_tests/coretestserver/setup.py +0 -0
- {corehttp-1.0.0b4 → corehttp-1.0.0b6}/tests/utils.py +0 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# Release History
|
|
2
|
+
|
|
3
|
+
## 1.0.0b6 (2025-03-27)
|
|
4
|
+
|
|
5
|
+
### Features Added
|
|
6
|
+
|
|
7
|
+
- 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)
|
|
8
|
+
- 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)
|
|
9
|
+
- 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)
|
|
10
|
+
- `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)
|
|
11
|
+
- These policies now also check the `refresh_on` attribute when determining if a new token request should be made.
|
|
12
|
+
- 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)
|
|
13
|
+
- Added `auth_flows` support in `BearerTokenCredentialPolicy`. [#40084](https://github.com/Azure/azure-sdk-for-python/pull/40084)
|
|
14
|
+
|
|
15
|
+
### Breaking Changes
|
|
16
|
+
|
|
17
|
+
- 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)
|
|
18
|
+
- The `AccessToken` class has been removed and replaced with a new `AccessTokenInfo` class. [#38346](https://github.com/Azure/azure-sdk-for-python/pull/38346)
|
|
19
|
+
- `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)
|
|
20
|
+
|
|
21
|
+
## 1.0.0b5 (2024-02-29)
|
|
22
|
+
|
|
23
|
+
### Other Changes
|
|
24
|
+
|
|
25
|
+
- Accept float for `retry_after` header.
|
|
26
|
+
|
|
27
|
+
## 1.0.0b4 (2024-02-23)
|
|
28
|
+
|
|
29
|
+
### Other Changes
|
|
30
|
+
|
|
31
|
+
- 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)
|
|
32
|
+
|
|
33
|
+
## 1.0.0b3 (2024-02-01)
|
|
34
|
+
|
|
35
|
+
### Features Added
|
|
36
|
+
|
|
37
|
+
- Support tuple input for `files` values to `corehttp.rest.HttpRequest` #34082
|
|
38
|
+
- Support simultaneous `files` and `data` field entry into `corehttp.rest.HttpRequest` #34082
|
|
39
|
+
|
|
40
|
+
## 1.0.0b2 (2023-11-14)
|
|
41
|
+
|
|
42
|
+
### Features Added
|
|
43
|
+
|
|
44
|
+
- Added the initial implementation of the HTTPX transport. [#32813](https://github.com/Azure/azure-sdk-for-python/pull/32813)
|
|
45
|
+
|
|
46
|
+
### Breaking Changes
|
|
47
|
+
|
|
48
|
+
- 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)
|
|
49
|
+
- Renamed the `aio` extra to `aiohttp`. [#32813](https://github.com/Azure/azure-sdk-for-python/pull/32813)
|
|
50
|
+
|
|
51
|
+
### Bugs Fixed
|
|
52
|
+
|
|
53
|
+
- 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)
|
|
54
|
+
- 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)
|
|
55
|
+
- Fixed an issue with the `aiohttp` transport not using SSL by default. [#33057](https://github.com/Azure/azure-sdk-for-python/pull/33057)
|
|
56
|
+
|
|
57
|
+
### Other Changes
|
|
58
|
+
|
|
59
|
+
- Added extras for `httpx`. [#32813](https://github.com/Azure/azure-sdk-for-python/pull/32813)
|
|
60
|
+
|
|
61
|
+
## 1.0.0b1 (2023-10-18)
|
|
62
|
+
|
|
63
|
+
* Initial Release
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: corehttp
|
|
3
|
-
Version: 1.0.
|
|
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
|
|
@@ -87,6 +87,30 @@ 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
|
+
|
|
108
|
+
## 1.0.0b5 (2024-02-29)
|
|
109
|
+
|
|
110
|
+
### Other Changes
|
|
111
|
+
|
|
112
|
+
- Accept float for `retry_after` header.
|
|
113
|
+
|
|
90
114
|
## 1.0.0b4 (2024-02-23)
|
|
91
115
|
|
|
92
116
|
### Other Changes
|
|
@@ -5,39 +5,71 @@
|
|
|
5
5
|
# -------------------------------------------------------------------------
|
|
6
6
|
from __future__ import annotations
|
|
7
7
|
from types import TracebackType
|
|
8
|
-
from typing import
|
|
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
|
|
13
|
-
"""
|
|
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
|
-
|
|
24
|
-
|
|
25
|
-
|
|
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
|
-
|
|
55
|
+
class TokenCredential(Protocol, ContextManager["TokenCredential"]):
|
|
56
|
+
"""Protocol for classes able to provide OAuth access tokens."""
|
|
31
57
|
|
|
32
|
-
|
|
33
|
-
|
|
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:
|
|
37
|
-
:return: An
|
|
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
|
-
"
|
|
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
|
|
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
|
-
:
|
|
143
|
-
|
|
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
|
|
|
@@ -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"
|
|
@@ -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=
|
|
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
|
|
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
|
|
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)
|
|
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
|
-
|
|
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
|
-
|
|
311
|
-
yield part
|
|
305
|
+
yield from self._stream_download_generator(response=self, pipeline=None, decompress=False)
|
|
312
306
|
self.close()
|
|
@@ -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
|
|
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=
|
|
31
|
-
from requests.structures import CaseInsensitiveDict # pylint: disable=
|
|
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
|
|
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
|
-
|
|
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:
|
|
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
|
|
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
|
-
|
|
16
|
+
|
|
16
17
|
from ...credentials import (
|
|
17
|
-
|
|
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,
|
|
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["
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
120
|
-
except Exception: # pylint:disable=broad-except
|
|
148
|
+
except Exception:
|
|
121
149
|
self.on_exception(request)
|
|
122
150
|
raise
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
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
|
|