py2docfx 0.1.22.dev2258230__py3-none-any.whl → 0.1.22.dev2270449__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.
- py2docfx/docfx_yaml/process_doctree.py +3 -23
- py2docfx/docfx_yaml/translator.py +6 -35
- py2docfx/docfx_yaml/type_mapping.py +102 -0
- py2docfx/venv/basevenv/Lib/site-packages/certifi/__init__.py +1 -1
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/_credentials/default.py +8 -9
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/_credentials/imds.py +7 -3
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/_credentials/managed_identity.py +7 -1
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/_credentials/shared_cache.py +2 -2
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/_internal/interactive.py +2 -2
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/_internal/msal_managed_identity_client.py +1 -1
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/_version.py +1 -1
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/aio/_credentials/default.py +8 -9
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/aio/_credentials/imds.py +7 -3
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/aio/_credentials/managed_identity.py +7 -1
- py2docfx/venv/venv1/Lib/site-packages/azure/identity/aio/_credentials/shared_cache.py +2 -2
- py2docfx/venv/venv1/Lib/site-packages/cachetools/__init__.py +96 -122
- py2docfx/venv/venv1/Lib/site-packages/cachetools/{_decorators.py → _cached.py} +106 -13
- py2docfx/venv/venv1/Lib/site-packages/cachetools/_cachedmethod.py +128 -0
- py2docfx/venv/venv1/Lib/site-packages/cachetools/func.py +5 -25
- py2docfx/venv/venv1/Lib/site-packages/certifi/__init__.py +1 -1
- py2docfx/venv/venv1/Lib/site-packages/cryptography/__about__.py +1 -1
- py2docfx/venv/venv1/Lib/site-packages/google/api_core/client_options.py +9 -2
- py2docfx/venv/venv1/Lib/site-packages/google/api_core/general_helpers.py +36 -0
- py2docfx/venv/venv1/Lib/site-packages/google/api_core/grpc_helpers.py +10 -7
- py2docfx/venv/venv1/Lib/site-packages/google/api_core/grpc_helpers_async.py +8 -3
- py2docfx/venv/venv1/Lib/site-packages/google/api_core/operations_v1/transports/base.py +13 -7
- py2docfx/venv/venv1/Lib/site-packages/google/api_core/operations_v1/transports/rest.py +19 -12
- py2docfx/venv/venv1/Lib/site-packages/google/api_core/operations_v1/transports/rest_asyncio.py +21 -0
- py2docfx/venv/venv1/Lib/site-packages/google/api_core/version.py +1 -1
- py2docfx/venv/venv1/Lib/site-packages/google/auth/_default.py +66 -12
- py2docfx/venv/venv1/Lib/site-packages/google/auth/_default_async.py +16 -10
- py2docfx/venv/venv1/Lib/site-packages/google/auth/_helpers.py +41 -0
- py2docfx/venv/venv1/Lib/site-packages/google/auth/compute_engine/credentials.py +67 -6
- py2docfx/venv/venv1/Lib/site-packages/google/auth/credentials.py +161 -18
- py2docfx/venv/venv1/Lib/site-packages/google/auth/environment_vars.py +4 -0
- py2docfx/venv/venv1/Lib/site-packages/google/auth/external_account.py +33 -10
- py2docfx/venv/venv1/Lib/site-packages/google/auth/external_account_authorized_user.py +24 -1
- py2docfx/venv/venv1/Lib/site-packages/google/auth/identity_pool.py +25 -1
- py2docfx/venv/venv1/Lib/site-packages/google/auth/impersonated_credentials.py +57 -9
- py2docfx/venv/venv1/Lib/site-packages/google/auth/pluggable.py +25 -1
- py2docfx/venv/venv1/Lib/site-packages/google/auth/version.py +1 -1
- py2docfx/venv/venv1/Lib/site-packages/google/oauth2/_client.py +117 -0
- py2docfx/venv/venv1/Lib/site-packages/google/oauth2/service_account.py +39 -4
- {py2docfx-0.1.22.dev2258230.dist-info → py2docfx-0.1.22.dev2270449.dist-info}/METADATA +1 -1
- {py2docfx-0.1.22.dev2258230.dist-info → py2docfx-0.1.22.dev2270449.dist-info}/RECORD +47 -45
- {py2docfx-0.1.22.dev2258230.dist-info → py2docfx-0.1.22.dev2270449.dist-info}/WHEEL +0 -0
- {py2docfx-0.1.22.dev2258230.dist-info → py2docfx-0.1.22.dev2270449.dist-info}/top_level.txt +0 -0
@@ -12,28 +12,13 @@ from utils import transform_string
|
|
12
12
|
from enum import EnumMeta
|
13
13
|
from importlib import import_module
|
14
14
|
from logger import get_package_logger
|
15
|
+
from type_mapping import map_type_transformations, PACKAGE, METHOD, FUNCTION, DATA, MODULE, CLASS, EXCEPTION, ATTRIBUTE, PROPERTY, PYDANTIC_MODEL, PYDANTIC_FIELD, PYDANTIC_SETTINGS, PYDANTIC_VALIDATOR, PYDANTIC_CONFIG
|
15
16
|
|
16
|
-
PACKAGE = 'package'
|
17
|
-
METHOD = 'method'
|
18
|
-
FUNCTION = 'function'
|
19
|
-
DATA = 'data'
|
20
|
-
MODULE = 'module'
|
21
|
-
CLASS = 'class'
|
22
|
-
EXCEPTION = 'exception'
|
23
|
-
ATTRIBUTE = 'attribute'
|
24
|
-
PROPERTY = 'property'
|
25
17
|
REFMETHOD = 'meth'
|
26
18
|
REFFUNCTION = 'func'
|
27
19
|
REF_PATTERN = ':(py:)?(func|class|meth|mod|ref):`~?[a-zA-Z_\.<> ]*?`'
|
28
20
|
INITPY = '__init__.py'
|
29
21
|
|
30
|
-
#Pydantic specific types
|
31
|
-
PYDANTIC_MODEL = 'pydantic_model'
|
32
|
-
PYDANTIC_FIELD = 'pydantic_field'
|
33
|
-
PYDANTIC_SETTINGS = 'pydantic_settings'
|
34
|
-
PYDANTIC_VALIDATOR = 'pydantic_validator'
|
35
|
-
PYDANTIC_CONFIG = 'pydantic_config'
|
36
|
-
|
37
22
|
def _fullname(obj):
|
38
23
|
"""
|
39
24
|
Get the fullname from a Python object
|
@@ -395,13 +380,8 @@ def process_docstring(app, _type, name, obj, options, lines):
|
|
395
380
|
return PACKAGE
|
396
381
|
return _type
|
397
382
|
|
398
|
-
#
|
399
|
-
|
400
|
-
_type = CLASS
|
401
|
-
elif _type == PROPERTY or _type == PYDANTIC_FIELD:
|
402
|
-
_type = ATTRIBUTE
|
403
|
-
elif _type == PYDANTIC_VALIDATOR:
|
404
|
-
_type = METHOD
|
383
|
+
# Apply type transformations using shared mapping function
|
384
|
+
_type = map_type_transformations(_type)
|
405
385
|
|
406
386
|
_type = check_convert_package_type(obj, _type)
|
407
387
|
cls, module = _get_cls_module(_type, name)
|
@@ -15,35 +15,15 @@ from sphinx.util.docfields import _is_single_paragraph
|
|
15
15
|
from collections import OrderedDict
|
16
16
|
from nodes import remarks
|
17
17
|
from logger import get_package_logger
|
18
|
+
from type_mapping import (
|
19
|
+
translator_type_mapping, CLASS_TYPE, EXCEPTION_TYPE, ATTRIBUTE_TYPE,
|
20
|
+
PYDANTIC_MODEL_TYPE, PYDANTIC_SETTINGS_TYPE, PYDANTIC_FIELD_TYPE, PYDANTIC_CONFIG_TYPE,
|
21
|
+
types_contain_constructor, types_contain_attributes, attribute_types
|
22
|
+
)
|
18
23
|
|
19
24
|
TYPE_SEP_PATTERN = '(\[|\]|, |\(|\))'
|
20
25
|
PARAMETER_NAME = "[*][*](.*?)[*][*]"
|
21
26
|
PARAMETER_TYPE = "[(]((?:.|\n)*)[)]"
|
22
|
-
CLASS_TYPE = 'class'
|
23
|
-
EXCEPTION_TYPE = 'exception'
|
24
|
-
ATTRIBUTE_TYPE = 'attribute'
|
25
|
-
|
26
|
-
# Pydantic specific types
|
27
|
-
PYDANTIC_MODEL_TYPE = "pydantic_model"
|
28
|
-
PYDANTIC_SETTINGS_TYPE = "pydantic_settings"
|
29
|
-
PYDANTIC_FIELD_TYPE = "pydantic_field"
|
30
|
-
PYDANTIC_CONFIG_TYPE = "pydantic_config"
|
31
|
-
|
32
|
-
types_contain_constructor = {
|
33
|
-
CLASS_TYPE,
|
34
|
-
PYDANTIC_MODEL_TYPE,
|
35
|
-
PYDANTIC_SETTINGS_TYPE,
|
36
|
-
EXCEPTION_TYPE,
|
37
|
-
PYDANTIC_CONFIG_TYPE,
|
38
|
-
}
|
39
|
-
types_contain_attributes = {
|
40
|
-
CLASS_TYPE,
|
41
|
-
PYDANTIC_MODEL_TYPE,
|
42
|
-
PYDANTIC_SETTINGS_TYPE,
|
43
|
-
EXCEPTION_TYPE,
|
44
|
-
PYDANTIC_CONFIG_TYPE,
|
45
|
-
}
|
46
|
-
attribute_types = {PYDANTIC_FIELD_TYPE, ATTRIBUTE_TYPE}
|
47
27
|
|
48
28
|
def translator(app, docname, doctree):
|
49
29
|
|
@@ -64,15 +44,6 @@ def translator(app, docname, doctree):
|
|
64
44
|
else:
|
65
45
|
return para_field.astext()
|
66
46
|
|
67
|
-
def type_mapping(type_name):
|
68
|
-
mapping = {
|
69
|
-
"staticmethod": "method",
|
70
|
-
"classmethod": "method",
|
71
|
-
"exception": "class",
|
72
|
-
}
|
73
|
-
|
74
|
-
return mapping[type_name] if type_name in mapping else type_name
|
75
|
-
|
76
47
|
def _get_uid_and_type_from_desc(node):
|
77
48
|
assert node.tagname == 'desc'
|
78
49
|
if node.attributes['domain'] != 'py':
|
@@ -493,7 +464,7 @@ def translator(app, docname, doctree):
|
|
493
464
|
data.update(extract_content(content_child, node_type, module_name))
|
494
465
|
data['content'] = extract_signature(signature_child)
|
495
466
|
|
496
|
-
data['type'] =
|
467
|
+
data['type'] = translator_type_mapping(node_type) if node_type else 'unknown'
|
497
468
|
if _is_property_node(signature_child):
|
498
469
|
data['type'] = ATTRIBUTE_TYPE
|
499
470
|
|
@@ -0,0 +1,102 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
#
|
3
|
+
# ---------------------------------------------------------
|
4
|
+
# Copyright (c) Microsoft Corporation. All rights reserved.
|
5
|
+
# ---------------------------------------------------------
|
6
|
+
|
7
|
+
"""
|
8
|
+
Type mapping utilities for converting various documentation types to standardized forms.
|
9
|
+
"""
|
10
|
+
|
11
|
+
# Standard types
|
12
|
+
PACKAGE = 'package'
|
13
|
+
METHOD = 'method'
|
14
|
+
FUNCTION = 'function'
|
15
|
+
DATA = 'data'
|
16
|
+
MODULE = 'module'
|
17
|
+
CLASS = 'class'
|
18
|
+
EXCEPTION = 'exception'
|
19
|
+
ATTRIBUTE = 'attribute'
|
20
|
+
PROPERTY = 'property'
|
21
|
+
|
22
|
+
# Pydantic specific types
|
23
|
+
PYDANTIC_MODEL = 'pydantic_model'
|
24
|
+
PYDANTIC_FIELD = 'pydantic_field'
|
25
|
+
PYDANTIC_SETTINGS = 'pydantic_settings'
|
26
|
+
PYDANTIC_VALIDATOR = 'pydantic_validator'
|
27
|
+
PYDANTIC_CONFIG = 'pydantic_config'
|
28
|
+
|
29
|
+
# Translator-style constants (for compatibility)
|
30
|
+
CLASS_TYPE = 'class'
|
31
|
+
EXCEPTION_TYPE = 'exception'
|
32
|
+
ATTRIBUTE_TYPE = 'attribute'
|
33
|
+
PYDANTIC_MODEL_TYPE = "pydantic_model"
|
34
|
+
PYDANTIC_SETTINGS_TYPE = "pydantic_settings"
|
35
|
+
PYDANTIC_FIELD_TYPE = "pydantic_field"
|
36
|
+
PYDANTIC_CONFIG_TYPE = "pydantic_config"
|
37
|
+
|
38
|
+
# Type groupings for translator functionality
|
39
|
+
types_contain_constructor = {
|
40
|
+
CLASS_TYPE,
|
41
|
+
PYDANTIC_MODEL_TYPE,
|
42
|
+
PYDANTIC_SETTINGS_TYPE,
|
43
|
+
EXCEPTION_TYPE,
|
44
|
+
PYDANTIC_CONFIG_TYPE,
|
45
|
+
}
|
46
|
+
|
47
|
+
types_contain_attributes = {
|
48
|
+
CLASS_TYPE,
|
49
|
+
PYDANTIC_MODEL_TYPE,
|
50
|
+
PYDANTIC_SETTINGS_TYPE,
|
51
|
+
EXCEPTION_TYPE,
|
52
|
+
PYDANTIC_CONFIG_TYPE,
|
53
|
+
}
|
54
|
+
|
55
|
+
attribute_types = {PYDANTIC_FIELD_TYPE, ATTRIBUTE_TYPE}
|
56
|
+
|
57
|
+
|
58
|
+
def map_type_transformations(type_name):
|
59
|
+
"""
|
60
|
+
Apply type transformations to convert various documentation types to standardized forms.
|
61
|
+
Used by process_doctree.py for initial type processing.
|
62
|
+
|
63
|
+
Args:
|
64
|
+
type_name (str): The original type name
|
65
|
+
|
66
|
+
Returns:
|
67
|
+
str: The transformed type name
|
68
|
+
"""
|
69
|
+
# Type transformations
|
70
|
+
if type_name == EXCEPTION or type_name in {PYDANTIC_MODEL, PYDANTIC_SETTINGS, PYDANTIC_CONFIG}:
|
71
|
+
return CLASS
|
72
|
+
elif type_name == PROPERTY or type_name == PYDANTIC_FIELD:
|
73
|
+
return ATTRIBUTE
|
74
|
+
elif type_name == PYDANTIC_VALIDATOR:
|
75
|
+
return METHOD
|
76
|
+
|
77
|
+
# Return original type if no transformation needed
|
78
|
+
return type_name
|
79
|
+
|
80
|
+
|
81
|
+
def translator_type_mapping(type_name):
|
82
|
+
"""
|
83
|
+
Apply type mapping transformations for translator processing.
|
84
|
+
Used by translator.py for docstring processing.
|
85
|
+
Includes both original translator mappings and process_doctree transformations.
|
86
|
+
|
87
|
+
Args:
|
88
|
+
type_name (str): The original type name
|
89
|
+
|
90
|
+
Returns:
|
91
|
+
str: The mapped type name
|
92
|
+
"""
|
93
|
+
# First apply the process_doctree style transformations
|
94
|
+
transformed_type = map_type_transformations(type_name)
|
95
|
+
|
96
|
+
# Then apply the original translator mappings
|
97
|
+
mapping = {
|
98
|
+
"staticmethod": "method",
|
99
|
+
"classmethod": "method",
|
100
|
+
}
|
101
|
+
|
102
|
+
return mapping[transformed_type] if transformed_type in mapping else transformed_type
|
@@ -172,7 +172,8 @@ class DefaultAzureCredential(ChainedTokenCredential):
|
|
172
172
|
|
173
173
|
process_timeout = kwargs.pop("process_timeout", 10)
|
174
174
|
require_envvar = kwargs.pop("require_envvar", False)
|
175
|
-
|
175
|
+
token_credentials_env = os.environ.get(EnvironmentVariables.AZURE_TOKEN_CREDENTIALS, "").strip().lower()
|
176
|
+
if require_envvar and not token_credentials_env:
|
176
177
|
raise ValueError(
|
177
178
|
"AZURE_TOKEN_CREDENTIALS environment variable is required but is not set or is empty. "
|
178
179
|
"Set it to 'dev', 'prod', or a specific credential name."
|
@@ -274,18 +275,16 @@ class DefaultAzureCredential(ChainedTokenCredential):
|
|
274
275
|
ManagedIdentityCredential(
|
275
276
|
client_id=managed_identity_client_id,
|
276
277
|
_exclude_workload_identity_credential=exclude_workload_identity_credential,
|
278
|
+
_enable_imds_probe=token_credentials_env != "managedidentitycredential",
|
277
279
|
**kwargs,
|
278
280
|
)
|
279
281
|
)
|
280
282
|
if not exclude_shared_token_cache_credential and SharedTokenCacheCredential.supported():
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
credentials.append(shared_cache)
|
287
|
-
except Exception as ex: # pylint:disable=broad-except
|
288
|
-
_LOGGER.info("Shared token cache is unavailable: '%s'", ex)
|
283
|
+
# username and/or tenant_id are only required when the cache contains tokens for multiple identities
|
284
|
+
shared_cache = SharedTokenCacheCredential(
|
285
|
+
username=shared_cache_username, tenant_id=shared_cache_tenant_id, authority=authority, **kwargs
|
286
|
+
)
|
287
|
+
credentials.append(shared_cache)
|
289
288
|
if not exclude_visual_studio_code_credential:
|
290
289
|
credentials.append(VisualStudioCodeCredential(tenant_id=vscode_tenant_id))
|
291
290
|
if not exclude_cli_credential:
|
@@ -82,6 +82,10 @@ def _check_forbidden_response(ex: HttpResponseError) -> None:
|
|
82
82
|
|
83
83
|
class ImdsCredential(MsalManagedIdentityClient):
|
84
84
|
def __init__(self, **kwargs: Any) -> None:
|
85
|
+
# If set to True/False, _enable_imds_probe forces whether or not the credential
|
86
|
+
# probes for the IMDS endpoint before attempting to get a token. If None (the default),
|
87
|
+
# the credential probes only if it's part of a ChainedTokenCredential chain.
|
88
|
+
self._enable_imds_probe = kwargs.pop("_enable_imds_probe", None)
|
85
89
|
super().__init__(retry_policy_class=ImdsRetryPolicy, **dict(PIPELINE_SETTINGS, **kwargs))
|
86
90
|
self._config = kwargs
|
87
91
|
|
@@ -102,9 +106,9 @@ class ImdsCredential(MsalManagedIdentityClient):
|
|
102
106
|
|
103
107
|
def _request_token(self, *scopes: str, **kwargs: Any) -> AccessTokenInfo:
|
104
108
|
|
105
|
-
if
|
106
|
-
|
107
|
-
# is available to avoid hanging for a long time if
|
109
|
+
do_probe = self._enable_imds_probe if self._enable_imds_probe is not None else within_credential_chain.get()
|
110
|
+
if do_probe and not self._endpoint_available:
|
111
|
+
# Probe to see if the IMDS endpoint is available to avoid hanging for a long time if it's not.
|
108
112
|
try:
|
109
113
|
client = ManagedIdentityClient(_get_request, **dict(PIPELINE_SETTINGS, **self._config))
|
110
114
|
client.request_token(*scopes, connection_timeout=1, retry_total=0)
|
@@ -76,6 +76,7 @@ class ManagedIdentityCredential:
|
|
76
76
|
user_identity_info = validate_identity_config(client_id, identity_config)
|
77
77
|
self._credential: Optional[SupportsTokenInfo] = None
|
78
78
|
exclude_workload_identity = kwargs.pop("_exclude_workload_identity_credential", False)
|
79
|
+
self._enable_imds_probe = kwargs.pop("_enable_imds_probe", None)
|
79
80
|
managed_identity_type = None
|
80
81
|
|
81
82
|
if os.environ.get(EnvironmentVariables.IDENTITY_ENDPOINT):
|
@@ -136,7 +137,12 @@ class ManagedIdentityCredential:
|
|
136
137
|
managed_identity_type = "IMDS"
|
137
138
|
from .imds import ImdsCredential
|
138
139
|
|
139
|
-
self._credential = ImdsCredential(
|
140
|
+
self._credential = ImdsCredential(
|
141
|
+
client_id=client_id,
|
142
|
+
identity_config=identity_config,
|
143
|
+
_enable_imds_probe=self._enable_imds_probe,
|
144
|
+
**kwargs,
|
145
|
+
)
|
140
146
|
|
141
147
|
if managed_identity_type:
|
142
148
|
log_msg = f"{self.__class__.__name__} will use {managed_identity_type}"
|
@@ -198,9 +198,9 @@ class _SharedTokenCacheCredential(SharedTokenCacheBase):
|
|
198
198
|
return token
|
199
199
|
except Exception as e: # pylint: disable=broad-except
|
200
200
|
if within_dac.get():
|
201
|
-
raise CredentialUnavailableError(
|
201
|
+
raise CredentialUnavailableError(
|
202
202
|
message=getattr(e, "message", str(e)), response=getattr(e, "response", None)
|
203
|
-
)
|
203
|
+
) from e
|
204
204
|
raise
|
205
205
|
|
206
206
|
raise CredentialUnavailableError(message=NO_TOKEN.format(account.get("username")))
|
@@ -203,7 +203,7 @@ class InteractiveCredential(MsalCredential, ABC):
|
|
203
203
|
return token
|
204
204
|
except Exception as ex: # pylint:disable=broad-except
|
205
205
|
if not (isinstance(ex, AuthenticationRequiredError) and allow_prompt):
|
206
|
-
_LOGGER.warning(
|
206
|
+
_LOGGER.warning( # pylint: disable=do-not-log-raised-errors
|
207
207
|
"%s.%s failed: %s",
|
208
208
|
self.__class__.__name__,
|
209
209
|
base_method_name,
|
@@ -225,7 +225,7 @@ class InteractiveCredential(MsalCredential, ABC):
|
|
225
225
|
# this may be the first authentication, or the user may have authenticated a different identity
|
226
226
|
self._auth_record = _build_auth_record(result)
|
227
227
|
except Exception as ex:
|
228
|
-
_LOGGER.warning(
|
228
|
+
_LOGGER.warning( # pylint: disable=do-not-log-raised-errors
|
229
229
|
"%s.%s failed: %s",
|
230
230
|
self.__class__.__name__,
|
231
231
|
base_method_name,
|
py2docfx/venv/venv1/Lib/site-packages/azure/identity/_internal/msal_managed_identity_client.py
CHANGED
@@ -61,7 +61,7 @@ class MsalManagedIdentityClient(abc.ABC): # pylint:disable=client-accepts-api-v
|
|
61
61
|
)
|
62
62
|
error_desc = ""
|
63
63
|
if result and "error" in result:
|
64
|
-
error_desc =
|
64
|
+
error_desc = f"Token request error: ({result['error']}) {result.get('error_description', '')}"
|
65
65
|
error_message = self.get_unavailable_message(error_desc)
|
66
66
|
raise CredentialUnavailableError(error_message)
|
67
67
|
|
@@ -144,7 +144,8 @@ class DefaultAzureCredential(ChainedTokenCredential):
|
|
144
144
|
|
145
145
|
process_timeout = kwargs.pop("process_timeout", 10)
|
146
146
|
require_envvar = kwargs.pop("require_envvar", False)
|
147
|
-
|
147
|
+
token_credentials_env = os.environ.get(EnvironmentVariables.AZURE_TOKEN_CREDENTIALS, "").strip().lower()
|
148
|
+
if require_envvar and not token_credentials_env:
|
148
149
|
raise ValueError(
|
149
150
|
"AZURE_TOKEN_CREDENTIALS environment variable is required but is not set or is empty. "
|
150
151
|
"Set it to 'dev', 'prod', or a specific credential name."
|
@@ -235,18 +236,16 @@ class DefaultAzureCredential(ChainedTokenCredential):
|
|
235
236
|
ManagedIdentityCredential(
|
236
237
|
client_id=managed_identity_client_id,
|
237
238
|
_exclude_workload_identity_credential=exclude_workload_identity_credential,
|
239
|
+
_enable_imds_probe=token_credentials_env != "managedidentitycredential",
|
238
240
|
**kwargs,
|
239
241
|
)
|
240
242
|
)
|
241
243
|
if not exclude_shared_token_cache_credential and SharedTokenCacheCredential.supported():
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
credentials.append(shared_cache)
|
248
|
-
except Exception as ex: # pylint:disable=broad-except
|
249
|
-
_LOGGER.info("Shared token cache is unavailable: '%s'", ex)
|
244
|
+
# username and/or tenant_id are only required when the cache contains tokens for multiple identities
|
245
|
+
shared_cache = SharedTokenCacheCredential(
|
246
|
+
username=shared_cache_username, tenant_id=shared_cache_tenant_id, authority=authority, **kwargs
|
247
|
+
)
|
248
|
+
credentials.append(shared_cache)
|
250
249
|
if not exclude_visual_studio_code_credential:
|
251
250
|
credentials.append(VisualStudioCodeCredential(tenant_id=vscode_tenant_id))
|
252
251
|
if not exclude_cli_credential:
|
@@ -45,6 +45,10 @@ class ImdsCredential(AsyncContextManager, GetTokenMixin):
|
|
45
45
|
def __init__(self, **kwargs: Any) -> None:
|
46
46
|
super().__init__()
|
47
47
|
|
48
|
+
# If set to True/False, _enable_imds_probe forces whether or not the credential
|
49
|
+
# probes for the IMDS endpoint before attempting to get a token. If None (the default),
|
50
|
+
# the credential probes only if it's part of a ChainedTokenCredential chain.
|
51
|
+
self._enable_imds_probe = kwargs.pop("_enable_imds_probe", None)
|
48
52
|
kwargs["retry_policy_class"] = AsyncImdsRetryPolicy
|
49
53
|
self._client = AsyncManagedIdentityClient(_get_request, **dict(PIPELINE_SETTINGS, **kwargs))
|
50
54
|
if EnvironmentVariables.AZURE_POD_IDENTITY_AUTHORITY_HOST in os.environ:
|
@@ -65,9 +69,9 @@ class ImdsCredential(AsyncContextManager, GetTokenMixin):
|
|
65
69
|
|
66
70
|
async def _request_token(self, *scopes: str, **kwargs: Any) -> AccessTokenInfo:
|
67
71
|
|
68
|
-
if
|
69
|
-
|
70
|
-
# is available to avoid hanging for a long time if
|
72
|
+
do_probe = self._enable_imds_probe if self._enable_imds_probe is not None else within_credential_chain.get()
|
73
|
+
if do_probe and not self._endpoint_available:
|
74
|
+
# Probe to see if the IMDS endpoint is available to avoid hanging for a long time if it's not.
|
71
75
|
try:
|
72
76
|
await self._client.request_token(*scopes, connection_timeout=1, retry_total=0)
|
73
77
|
self._endpoint_available = True
|
@@ -49,6 +49,7 @@ class ManagedIdentityCredential(AsyncContextManager):
|
|
49
49
|
user_identity_info = validate_identity_config(client_id, identity_config)
|
50
50
|
self._credential: Optional[AsyncSupportsTokenInfo] = None
|
51
51
|
exclude_workload_identity = kwargs.pop("_exclude_workload_identity_credential", False)
|
52
|
+
self._enable_imds_probe = kwargs.pop("_enable_imds_probe", None)
|
52
53
|
managed_identity_type = None
|
53
54
|
if os.environ.get(EnvironmentVariables.IDENTITY_ENDPOINT):
|
54
55
|
if os.environ.get(EnvironmentVariables.IDENTITY_HEADER):
|
@@ -108,7 +109,12 @@ class ManagedIdentityCredential(AsyncContextManager):
|
|
108
109
|
managed_identity_type = "IMDS"
|
109
110
|
from .imds import ImdsCredential
|
110
111
|
|
111
|
-
self._credential = ImdsCredential(
|
112
|
+
self._credential = ImdsCredential(
|
113
|
+
client_id=client_id,
|
114
|
+
identity_config=identity_config,
|
115
|
+
_enable_imds_probe=self._enable_imds_probe,
|
116
|
+
**kwargs,
|
117
|
+
)
|
112
118
|
|
113
119
|
if managed_identity_type:
|
114
120
|
log_msg = f"{self.__class__.__name__} will use {managed_identity_type}"
|
@@ -151,9 +151,9 @@ class SharedTokenCacheCredential(SharedTokenCacheBase, AsyncContextManager):
|
|
151
151
|
return token
|
152
152
|
except Exception as e: # pylint: disable=broad-except
|
153
153
|
if within_dac.get():
|
154
|
-
raise CredentialUnavailableError(
|
154
|
+
raise CredentialUnavailableError(
|
155
155
|
message=getattr(e, "message", str(e)), response=getattr(e, "response", None)
|
156
|
-
)
|
156
|
+
) from e
|
157
157
|
raise
|
158
158
|
raise CredentialUnavailableError(message=NO_TOKEN.format(account.get("username")))
|
159
159
|
|