py2docfx 0.1.19.dev2175272__py3-none-any.whl → 0.1.19.dev2192444__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/__main__.py +2 -2
- py2docfx/convert_prepare/get_source.py +40 -8
- py2docfx/convert_prepare/git.py +1 -1
- py2docfx/docfx_yaml/logger.py +23 -19
- py2docfx/venv/basevenv/Lib/site-packages/certifi/__init__.py +1 -1
- py2docfx/venv/venv1/Lib/site-packages/certifi/__init__.py +1 -1
- py2docfx/venv/venv1/Lib/site-packages/msal/__main__.py +2 -0
- py2docfx/venv/venv1/Lib/site-packages/msal/application.py +63 -21
- py2docfx/venv/venv1/Lib/site-packages/msal/broker.py +5 -2
- py2docfx/venv/venv1/Lib/site-packages/msal/exceptions.py +19 -5
- py2docfx/venv/venv1/Lib/site-packages/msal/managed_identity.py +50 -10
- py2docfx/venv/venv1/Lib/site-packages/msal/sku.py +1 -1
- py2docfx/venv/venv1/Lib/site-packages/msal/throttled_http_client.py +4 -1
- {py2docfx-0.1.19.dev2175272.dist-info → py2docfx-0.1.19.dev2192444.dist-info}/METADATA +1 -1
- {py2docfx-0.1.19.dev2175272.dist-info → py2docfx-0.1.19.dev2192444.dist-info}/RECORD +17 -17
- {py2docfx-0.1.19.dev2175272.dist-info → py2docfx-0.1.19.dev2192444.dist-info}/WHEEL +0 -0
- {py2docfx-0.1.19.dev2175272.dist-info → py2docfx-0.1.19.dev2192444.dist-info}/top_level.txt +0 -0
py2docfx/__main__.py
CHANGED
@@ -106,8 +106,8 @@ async def main(argv) -> int:
|
|
106
106
|
|
107
107
|
# create log folder and package log folder
|
108
108
|
log_folder = os.path.join(PACKAGE_ROOT, LOG_FOLDER)
|
109
|
-
os.makedirs(log_folder)
|
110
|
-
os.makedirs(os.path.join(log_folder, "package_logs"))
|
109
|
+
os.makedirs(log_folder, exist_ok=True)
|
110
|
+
os.makedirs(os.path.join(log_folder, "package_logs"), exist_ok=True)
|
111
111
|
|
112
112
|
py2docfxLogger.decide_global_log_level(verbose, show_warning)
|
113
113
|
|
@@ -41,10 +41,11 @@ def update_package_info(executable: str, pkg: PackageInfo, source_folder: str):
|
|
41
41
|
|
42
42
|
setattr(pkg, attr, attr_val)
|
43
43
|
else:
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
if
|
44
|
+
# Find .dist-info folders
|
45
|
+
dist_info_folders = [f for f in all_files if path.isdir(f) and f.endswith(".dist-info")]
|
46
|
+
|
47
|
+
if dist_info_folders:
|
48
|
+
folder = dist_info_folders[0] # Take the first one if multiple exist
|
48
49
|
if path.exists(path.join(folder, "METADATA")):
|
49
50
|
with open(
|
50
51
|
path.join(folder, "METADATA"), "r", encoding="utf-8"
|
@@ -97,6 +98,9 @@ async def get_source(executable: str, pkg: PackageInfo, cnt: int, vststoken=None
|
|
97
98
|
sys.path.insert(0, source_folder)
|
98
99
|
elif pkg.install_type == PackageInfo.InstallType.PYPI:
|
99
100
|
full_name = pkg.get_combined_name_version()
|
101
|
+
# Ensure the dist directory exists
|
102
|
+
os.makedirs(dist_dir, exist_ok=True)
|
103
|
+
|
100
104
|
await pip_utils.download(
|
101
105
|
full_name,
|
102
106
|
dist_dir,
|
@@ -104,25 +108,53 @@ async def get_source(executable: str, pkg: PackageInfo, cnt: int, vststoken=None
|
|
104
108
|
prefer_source_distribution=pkg.prefer_source_distribution,
|
105
109
|
)
|
106
110
|
# unpack the downloaded wheel file.
|
107
|
-
|
111
|
+
dist_files = os.listdir(dist_dir)
|
112
|
+
if not dist_files:
|
113
|
+
msg = f"No files downloaded to {dist_dir} for package {pkg.name}"
|
114
|
+
py2docfx_logger.error(msg)
|
115
|
+
raise FileNotFoundError(f"No files found in {dist_dir}")
|
116
|
+
|
117
|
+
downloaded_dist_file = path.join(dist_dir, dist_files[0])
|
108
118
|
await pack.unpack_dist(pkg.name, downloaded_dist_file)
|
109
119
|
os.remove(downloaded_dist_file)
|
120
|
+
dist_files = os.listdir(dist_dir)
|
121
|
+
if not dist_files:
|
122
|
+
msg = f"No files found in {dist_dir} after unpacking for package {pkg.name}"
|
123
|
+
py2docfx_logger.error(msg)
|
124
|
+
raise FileNotFoundError(f"No files found in {dist_dir} after unpacking")
|
125
|
+
|
110
126
|
source_folder = path.join(
|
111
127
|
path.dirname(downloaded_dist_file),
|
112
|
-
|
128
|
+
dist_files[0]
|
113
129
|
)
|
114
130
|
elif pkg.install_type == PackageInfo.InstallType.DIST_FILE:
|
131
|
+
# Ensure the dist directory exists
|
132
|
+
os.makedirs(dist_dir, exist_ok=True)
|
133
|
+
|
115
134
|
await pip_utils.download(pkg.location, dist_dir, prefer_source_distribution=False)
|
116
135
|
# unpack the downloaded dist file.
|
117
|
-
|
136
|
+
dist_files = os.listdir(dist_dir)
|
137
|
+
if not dist_files:
|
138
|
+
msg = f"No files downloaded to {dist_dir} for package {pkg.name}"
|
139
|
+
py2docfx_logger.error(msg)
|
140
|
+
raise FileNotFoundError(f"No files found in {dist_dir}")
|
141
|
+
|
142
|
+
downloaded_dist_file = path.join(dist_dir, dist_files[0])
|
118
143
|
await pack.unpack_dist(pkg.name, downloaded_dist_file)
|
119
144
|
os.remove(downloaded_dist_file)
|
145
|
+
|
146
|
+
# Check again after unpacking
|
147
|
+
dist_files = os.listdir(dist_dir)
|
148
|
+
if not dist_files:
|
149
|
+
msg = f"No files found in {dist_dir} after unpacking for package {pkg.name}"
|
150
|
+
py2docfx_logger.error(msg)
|
151
|
+
raise FileNotFoundError(f"No files found in {dist_dir} after unpacking")
|
120
152
|
if downloaded_dist_file.endswith(".tar.gz"):
|
121
153
|
downloaded_dist_file = downloaded_dist_file.rsplit(".", maxsplit=1)[
|
122
154
|
0]
|
123
155
|
source_folder = path.join(
|
124
156
|
path.dirname(downloaded_dist_file),
|
125
|
-
|
157
|
+
dist_files[0] if dist_files else ""
|
126
158
|
)
|
127
159
|
else:
|
128
160
|
msg = f"Unknown install type: {pkg.install_type}"
|
py2docfx/convert_prepare/git.py
CHANGED
@@ -25,7 +25,7 @@ async def clone(repo_location, branch, folder, extra_token=None):
|
|
25
25
|
raise ValueError(msg)
|
26
26
|
else:
|
27
27
|
# Remove http(s):// from url to record. Further avoid dup-clone.
|
28
|
-
pureURL = re.sub("^\s*https?://", "", repo_location)
|
28
|
+
pureURL = re.sub(r"^\s*https?://", "", repo_location)
|
29
29
|
|
30
30
|
if pureURL not in repoMap:
|
31
31
|
branch = convertBranch(repo_location, branch, extra_token)
|
py2docfx/docfx_yaml/logger.py
CHANGED
@@ -77,16 +77,18 @@ def counts_errors_warnings(log_file_path):
|
|
77
77
|
warning_count += 1
|
78
78
|
return warning_count, error_count
|
79
79
|
|
80
|
-
def get_warning_error_count():
|
81
|
-
main_log_file_path = os.path.join("logs", "log.txt")
|
82
|
-
warning_count, error_count = counts_errors_warnings(main_log_file_path)
|
83
|
-
|
84
|
-
log_folder_path = os.path.join("logs", "package_logs")
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
80
|
+
def get_warning_error_count():
|
81
|
+
main_log_file_path = os.path.join("logs", "log.txt")
|
82
|
+
warning_count, error_count = counts_errors_warnings(main_log_file_path)
|
83
|
+
|
84
|
+
log_folder_path = os.path.join("logs", "package_logs")
|
85
|
+
# Check if the directory exists before trying to list its contents
|
86
|
+
if os.path.exists(log_folder_path) and os.path.isdir(log_folder_path):
|
87
|
+
for log_file in os.listdir(log_folder_path):
|
88
|
+
log_file_path = os.path.join(log_folder_path, log_file)
|
89
|
+
warnings, errors = counts_errors_warnings(log_file_path)
|
90
|
+
warning_count += warnings
|
91
|
+
error_count += errors
|
90
92
|
|
91
93
|
return warning_count, error_count
|
92
94
|
|
@@ -118,15 +120,17 @@ def print_out_log_by_log_level(log_list, log_level):
|
|
118
120
|
if log['level'] >= log_level and log['message'] not in ['', '\n', '\r\n']:
|
119
121
|
print(log['message'])
|
120
122
|
|
121
|
-
def output_log_by_log_level():
|
122
|
-
log_level = get_log_level()
|
123
|
-
main_log_file_path = os.path.join("logs", "log.txt")
|
124
|
-
print_out_log_by_log_level(parse_log(main_log_file_path), log_level)
|
125
|
-
|
126
|
-
package_logs_folder = os.path.join("logs", "package_logs")
|
127
|
-
|
128
|
-
|
129
|
-
|
123
|
+
def output_log_by_log_level():
|
124
|
+
log_level = get_log_level()
|
125
|
+
main_log_file_path = os.path.join("logs", "log.txt")
|
126
|
+
print_out_log_by_log_level(parse_log(main_log_file_path), log_level)
|
127
|
+
|
128
|
+
package_logs_folder = os.path.join("logs", "package_logs")
|
129
|
+
# Check if the directory exists before trying to list its contents
|
130
|
+
if os.path.exists(package_logs_folder) and os.path.isdir(package_logs_folder):
|
131
|
+
for log_file in os.listdir(package_logs_folder):
|
132
|
+
log_file_path = os.path.join(package_logs_folder, log_file)
|
133
|
+
print_out_log_by_log_level(parse_log(log_file_path), log_level)
|
130
134
|
|
131
135
|
async def run_async_subprocess(exe_path, cmd, logger, cwd=None):
|
132
136
|
if cwd is None:
|
@@ -300,6 +300,8 @@ def _main():
|
|
300
300
|
instance_discovery=instance_discovery,
|
301
301
|
enable_broker_on_windows=enable_broker,
|
302
302
|
enable_broker_on_mac=enable_broker,
|
303
|
+
enable_broker_on_linux=enable_broker,
|
304
|
+
enable_broker_on_wsl=enable_broker,
|
303
305
|
enable_pii_log=enable_pii_log,
|
304
306
|
token_cache=global_cache,
|
305
307
|
) if not is_cca else msal.ConfidentialClientApplication(
|
@@ -21,7 +21,7 @@ from .region import _detect_region
|
|
21
21
|
from .throttled_http_client import ThrottledHttpClient
|
22
22
|
from .cloudshell import _is_running_in_cloud_shell
|
23
23
|
from .sku import SKU, __version__
|
24
|
-
|
24
|
+
from .oauth2cli.authcode import is_wsl
|
25
25
|
|
26
26
|
|
27
27
|
logger = logging.getLogger(__name__)
|
@@ -164,6 +164,8 @@ def _preferred_browser():
|
|
164
164
|
pass # We may still proceed
|
165
165
|
return None
|
166
166
|
|
167
|
+
def _is_ssh_cert_or_pop_request(token_type, auth_scheme) -> bool:
|
168
|
+
return token_type == "ssh-cert" or token_type == "pop" or isinstance(auth_scheme, msal.auth_scheme.PopAuthScheme)
|
167
169
|
|
168
170
|
class _ClientWithCcsRoutingInfo(Client):
|
169
171
|
|
@@ -208,6 +210,11 @@ def _msal_extension_check():
|
|
208
210
|
pass # The optional msal_extensions is not installed. Business as usual.
|
209
211
|
except ValueError:
|
210
212
|
logger.exception(f"msal_extensions version {v} not in major.minor.patch format")
|
213
|
+
except:
|
214
|
+
logger.exception(
|
215
|
+
"Unable to import msal_extensions during an optional check. "
|
216
|
+
"This exception can be safely ignored."
|
217
|
+
)
|
211
218
|
|
212
219
|
|
213
220
|
class ClientApplication(object):
|
@@ -329,7 +336,7 @@ class ClientApplication(object):
|
|
329
336
|
"client_assertion": "...a JWT with claims aud, exp, iss, jti, nbf, and sub..."
|
330
337
|
}
|
331
338
|
|
332
|
-
.. admonition:: Supporting reading client
|
339
|
+
.. admonition:: Supporting reading client certificates from PFX files
|
333
340
|
|
334
341
|
*Added in version 1.29.0*:
|
335
342
|
Feed in a dictionary containing the path to a PFX file::
|
@@ -488,10 +495,13 @@ class ClientApplication(object):
|
|
488
495
|
|
489
496
|
If your app is a command-line app (CLI),
|
490
497
|
you would want to persist your http_cache across different CLI runs.
|
498
|
+
The persisted file's format may change due to, but not limited to,
|
499
|
+
`unstable protocol <https://docs.python.org/3/library/pickle.html#data-stream-format>`_,
|
500
|
+
so your implementation shall tolerate unexpected loading errors.
|
491
501
|
The following recipe shows a way to do so::
|
492
502
|
|
493
503
|
# Just add the following lines at the beginning of your CLI script
|
494
|
-
import sys, atexit, pickle
|
504
|
+
import sys, atexit, pickle, logging
|
495
505
|
http_cache_filename = sys.argv[0] + ".http_cache"
|
496
506
|
try:
|
497
507
|
with open(http_cache_filename, "rb") as f:
|
@@ -502,6 +512,9 @@ class ClientApplication(object):
|
|
502
512
|
AttributeError, # Cache created by a different version of MSAL
|
503
513
|
):
|
504
514
|
persisted_http_cache = {} # Recover by starting afresh
|
515
|
+
except: # Unexpected exceptions
|
516
|
+
logging.exception("You may want to debug this")
|
517
|
+
persisted_http_cache = {} # Recover by starting afresh
|
505
518
|
atexit.register(lambda: pickle.dump(
|
506
519
|
# When exit, flush it back to the file.
|
507
520
|
# It may occasionally overwrite another process's concurrent write,
|
@@ -706,7 +719,7 @@ class ClientApplication(object):
|
|
706
719
|
|
707
720
|
def is_pop_supported(self):
|
708
721
|
"""Returns True if this client supports Proof-of-Possession Access Token."""
|
709
|
-
return self._enable_broker
|
722
|
+
return self._enable_broker and sys.platform in ("win32", "darwin")
|
710
723
|
|
711
724
|
def _decorate_scope(
|
712
725
|
self, scopes,
|
@@ -1578,10 +1591,12 @@ The reserved list: {}""".format(list(scope_set), list(reserved_scope)))
|
|
1578
1591
|
raise ValueError("auth_scheme is not supported in Cloud Shell")
|
1579
1592
|
return self._acquire_token_by_cloud_shell(scopes, data=data)
|
1580
1593
|
|
1594
|
+
is_ssh_cert_or_pop_request = _is_ssh_cert_or_pop_request(data.get("token_type"), auth_scheme)
|
1595
|
+
|
1581
1596
|
if self._enable_broker and account and account.get("account_source") in (
|
1582
1597
|
_GRANT_TYPE_BROKER, # Broker successfully established this account previously.
|
1583
1598
|
None, # Unknown data from older MSAL. Broker might still work.
|
1584
|
-
):
|
1599
|
+
) and (sys.platform in ("win32", "darwin") or not is_ssh_cert_or_pop_request):
|
1585
1600
|
from .broker import _acquire_token_silently
|
1586
1601
|
response = _acquire_token_silently(
|
1587
1602
|
"https://{}/{}".format(self.authority.instance, self.authority.tenant),
|
@@ -1828,7 +1843,7 @@ The reserved list: {}""".format(list(scope_set), list(reserved_scope)))
|
|
1828
1843
|
"""
|
1829
1844
|
claims = _merge_claims_challenge_and_capabilities(
|
1830
1845
|
self._client_capabilities, claims_challenge)
|
1831
|
-
if self._enable_broker:
|
1846
|
+
if self._enable_broker and sys.platform in ("win32", "darwin"):
|
1832
1847
|
from .broker import _signin_silently
|
1833
1848
|
response = _signin_silently(
|
1834
1849
|
"https://{}/{}".format(self.authority.instance, self.authority.tenant),
|
@@ -1925,14 +1940,14 @@ class PublicClientApplication(ClientApplication): # browser app or mobile app
|
|
1925
1940
|
*,
|
1926
1941
|
enable_broker_on_windows=None,
|
1927
1942
|
enable_broker_on_mac=None,
|
1943
|
+
enable_broker_on_linux=None,
|
1944
|
+
enable_broker_on_wsl=None,
|
1928
1945
|
**kwargs):
|
1929
1946
|
"""Same as :func:`ClientApplication.__init__`,
|
1930
1947
|
except that ``client_credential`` parameter shall remain ``None``.
|
1931
1948
|
|
1932
1949
|
.. note::
|
1933
1950
|
|
1934
|
-
You may set enable_broker_on_windows and/or enable_broker_on_mac to True.
|
1935
|
-
|
1936
1951
|
**What is a broker, and why use it?**
|
1937
1952
|
|
1938
1953
|
A broker is a component installed on your device.
|
@@ -1950,20 +1965,26 @@ class PublicClientApplication(ClientApplication): # browser app or mobile app
|
|
1950
1965
|
so that your broker-enabled apps (even a CLI)
|
1951
1966
|
could automatically SSO from a previously established signed-in session.
|
1952
1967
|
|
1953
|
-
**
|
1968
|
+
**How to opt in to use broker?**
|
1954
1969
|
|
1955
|
-
1.
|
1956
|
-
and already registered their corresponding redirect_uri
|
1970
|
+
1. You can set any combination of the following opt-in parameters to true:
|
1957
1971
|
|
1958
|
-
|
1959
|
-
|
1960
|
-
|
1961
|
-
|
1972
|
+
+--------------------------+-----------------------------------+------------------------------------------------------------------------------------+
|
1973
|
+
| Opt-in flag | If app will run on | App has registered this as a Desktop platform redirect URI in Azure Portal |
|
1974
|
+
+==========================+===================================+====================================================================================+
|
1975
|
+
| enable_broker_on_windows | Windows 10+ | ms-appx-web://Microsoft.AAD.BrokerPlugin/your_client_id |
|
1976
|
+
+--------------------------+-----------------------------------+------------------------------------------------------------------------------------+
|
1977
|
+
| enable_broker_on_wsl | WSL | ms-appx-web://Microsoft.AAD.BrokerPlugin/your_client_id |
|
1978
|
+
+--------------------------+-----------------------------------+------------------------------------------------------------------------------------+
|
1979
|
+
| enable_broker_on_mac | Mac with Company Portal installed | msauth.com.msauth.unsignedapp://auth |
|
1980
|
+
+--------------------------+-----------------------------------+------------------------------------------------------------------------------------+
|
1981
|
+
| enable_broker_on_linux | Linux with Intune installed | ``https://login.microsoftonline.com/common/oauth2/nativeclient`` (MUST be enabled) |
|
1982
|
+
+--------------------------+-----------------------------------+------------------------------------------------------------------------------------+
|
1962
1983
|
|
1963
|
-
2.
|
1964
|
-
e.g. ``pip install msal[broker]>=1.
|
1984
|
+
2. Install broker dependency,
|
1985
|
+
e.g. ``pip install msal[broker]>=1.33,<2``.
|
1965
1986
|
|
1966
|
-
3.
|
1987
|
+
3. Test with ``acquire_token_interactive()`` and ``acquire_token_silent()``.
|
1967
1988
|
|
1968
1989
|
**The fallback behaviors of MSAL Python's broker support**
|
1969
1990
|
|
@@ -1999,12 +2020,29 @@ class PublicClientApplication(ClientApplication): # browser app or mobile app
|
|
1999
2020
|
This parameter defaults to None, which means MSAL will not utilize a broker.
|
2000
2021
|
|
2001
2022
|
New in MSAL Python 1.31.0.
|
2023
|
+
|
2024
|
+
:param boolean enable_broker_on_linux:
|
2025
|
+
This setting is only effective if your app is running on Linux, including WSL.
|
2026
|
+
This parameter defaults to None, which means MSAL will not utilize a broker.
|
2027
|
+
|
2028
|
+
New in MSAL Python 1.33.0.
|
2029
|
+
|
2030
|
+
:param boolean enable_broker_on_wsl:
|
2031
|
+
This setting is only effective if your app is running on WSL.
|
2032
|
+
This parameter defaults to None, which means MSAL will not utilize a broker.
|
2033
|
+
|
2034
|
+
New in MSAL Python 1.33.0.
|
2002
2035
|
"""
|
2003
2036
|
if client_credential is not None:
|
2004
2037
|
raise ValueError("Public Client should not possess credentials")
|
2038
|
+
|
2005
2039
|
self._enable_broker = bool(
|
2006
2040
|
enable_broker_on_windows and sys.platform == "win32"
|
2007
|
-
or enable_broker_on_mac and sys.platform == "darwin"
|
2041
|
+
or enable_broker_on_mac and sys.platform == "darwin"
|
2042
|
+
or enable_broker_on_linux and sys.platform == "linux"
|
2043
|
+
or enable_broker_on_wsl and is_wsl()
|
2044
|
+
)
|
2045
|
+
|
2008
2046
|
super(PublicClientApplication, self).__init__(
|
2009
2047
|
client_id, client_credential=None, **kwargs)
|
2010
2048
|
|
@@ -2133,6 +2171,8 @@ class PublicClientApplication(ClientApplication): # browser app or mobile app
|
|
2133
2171
|
False
|
2134
2172
|
) and data.get("token_type") != "ssh-cert" # Work around a known issue as of PyMsalRuntime 0.8
|
2135
2173
|
self._validate_ssh_cert_input_data(data)
|
2174
|
+
is_ssh_cert_or_pop_request = _is_ssh_cert_or_pop_request(data.get("token_type"), auth_scheme)
|
2175
|
+
|
2136
2176
|
if not on_before_launching_ui:
|
2137
2177
|
on_before_launching_ui = lambda **kwargs: None
|
2138
2178
|
if _is_running_in_cloud_shell() and prompt == "none":
|
@@ -2141,7 +2181,7 @@ class PublicClientApplication(ClientApplication): # browser app or mobile app
|
|
2141
2181
|
return self._acquire_token_by_cloud_shell(scopes, data=data)
|
2142
2182
|
claims = _merge_claims_challenge_and_capabilities(
|
2143
2183
|
self._client_capabilities, claims_challenge)
|
2144
|
-
if self._enable_broker:
|
2184
|
+
if self._enable_broker and (sys.platform in ("win32", "darwin") or not is_ssh_cert_or_pop_request):
|
2145
2185
|
if parent_window_handle is None:
|
2146
2186
|
raise ValueError(
|
2147
2187
|
"parent_window_handle is required when you opted into using broker. "
|
@@ -2166,7 +2206,9 @@ class PublicClientApplication(ClientApplication): # browser app or mobile app
|
|
2166
2206
|
)
|
2167
2207
|
return self._process_broker_response(response, scopes, data)
|
2168
2208
|
|
2169
|
-
if auth_scheme:
|
2209
|
+
if isinstance(auth_scheme, msal.auth_scheme.PopAuthScheme) and sys.platform == "linux":
|
2210
|
+
raise ValueError("POP is not supported on Linux")
|
2211
|
+
elif auth_scheme:
|
2170
2212
|
raise ValueError(self._AUTH_SCHEME_UNSUPPORTED)
|
2171
2213
|
on_before_launching_ui(ui="browser")
|
2172
2214
|
telemetry_context = self._build_telemetry_context(
|
@@ -27,6 +27,7 @@ except (ImportError, AttributeError): # AttributeError happens when a prior pym
|
|
27
27
|
min_ver = {
|
28
28
|
"win32": "1.20",
|
29
29
|
"darwin": "1.31",
|
30
|
+
"linux": "1.33",
|
30
31
|
}.get(sys.platform)
|
31
32
|
if min_ver:
|
32
33
|
raise ImportError(
|
@@ -59,8 +60,10 @@ def _convert_error(error, client_id):
|
|
59
60
|
or "AADSTS7000218" in context # This "request body must contain ... client_secret" is just a symptom of current app has no WAM redirect_uri
|
60
61
|
):
|
61
62
|
raise RedirectUriError( # This would be seen by either the app developer or end user
|
62
|
-
"MsalRuntime needs the current app to register these redirect_uri
|
63
|
-
|
63
|
+
"""MsalRuntime needs the current app to register these redirect_uri
|
64
|
+
(1) ms-appx-web://Microsoft.AAD.BrokerPlugin/{}
|
65
|
+
(2) {}
|
66
|
+
(3) https://login.microsoftonline.com/common/oauth2/nativeclient""".format(
|
64
67
|
client_id, _redirect_uri_on_mac))
|
65
68
|
# OTOH, AAD would emit other errors when other error handling branch was hit first,
|
66
69
|
# so, the AADSTS50011/RedirectUriError is not guaranteed to happen.
|
@@ -27,12 +27,26 @@
|
|
27
27
|
|
28
28
|
class MsalError(Exception):
|
29
29
|
# Define the template in Unicode to accommodate possible Unicode variables
|
30
|
-
msg = u'An unspecified error'
|
30
|
+
msg = u'An unspecified error' # Keeping for backward compatibility
|
31
31
|
|
32
|
-
def __init__(self, *args, **kwargs):
|
33
|
-
super(MsalError, self).__init__(self.msg.format(**kwargs), *args)
|
34
|
-
self.kwargs = kwargs
|
35
32
|
|
36
33
|
class MsalServiceError(MsalError):
|
37
|
-
msg = u"{error}: {error_description}"
|
34
|
+
msg = u"{error}: {error_description}" # Keeping for backward compatibility
|
35
|
+
def __init__(
|
36
|
+
self,
|
37
|
+
*args,
|
38
|
+
error: str, error_description: str, # Historically required, keeping them for now
|
39
|
+
# 1. We can't simply remove them, or else it will be a breaking change
|
40
|
+
# 2. We may change them to optional without breaking anyone. However,
|
41
|
+
# such a change will be a one-way change, because once being optional,
|
42
|
+
# we will never be able to change them (back) to be required.
|
43
|
+
# 3. Since they were required and already exist anyway,
|
44
|
+
# now we just keep them required "for now",
|
45
|
+
# just in case that we would use them again.
|
46
|
+
# There is no plan to do #1; and we keep option #2 open; we go with #3.
|
47
|
+
**kwargs,
|
48
|
+
):
|
49
|
+
super().__init__(*args, **kwargs)
|
50
|
+
self._error = error
|
51
|
+
self._error_description = error_description
|
38
52
|
|
@@ -2,6 +2,7 @@
|
|
2
2
|
# All rights reserved.
|
3
3
|
#
|
4
4
|
# This code is licensed under the MIT License.
|
5
|
+
import hashlib
|
5
6
|
import json
|
6
7
|
import logging
|
7
8
|
import os
|
@@ -10,7 +11,7 @@ import sys
|
|
10
11
|
import time
|
11
12
|
from urllib.parse import urlparse # Python 3+
|
12
13
|
from collections import UserDict # Python 3+
|
13
|
-
from typing import Optional, Union # Needed in Python 3.7 & 3.8
|
14
|
+
from typing import List, Optional, Union # Needed in Python 3.7 & 3.8
|
14
15
|
from .token_cache import TokenCache
|
15
16
|
from .individual_cache import _IndividualCache as IndividualCache
|
16
17
|
from .throttled_http_client import ThrottledHttpClientBase, RetryAfterParser
|
@@ -162,6 +163,7 @@ class ManagedIdentityClient(object):
|
|
162
163
|
http_client,
|
163
164
|
token_cache=None,
|
164
165
|
http_cache=None,
|
166
|
+
client_capabilities: Optional[List[str]] = None,
|
165
167
|
):
|
166
168
|
"""Create a managed identity client.
|
167
169
|
|
@@ -192,6 +194,17 @@ class ManagedIdentityClient(object):
|
|
192
194
|
Optional. It has the same characteristics as the
|
193
195
|
:paramref:`msal.ClientApplication.http_cache`.
|
194
196
|
|
197
|
+
:param list[str] client_capabilities: (optional)
|
198
|
+
Allows configuration of one or more client capabilities, e.g. ["CP1"].
|
199
|
+
|
200
|
+
Client capability is meant to inform the Microsoft identity platform
|
201
|
+
(STS) what this client is capable for,
|
202
|
+
so STS can decide to turn on certain features.
|
203
|
+
|
204
|
+
Implementation details:
|
205
|
+
Client capability in Managed Identity is relayed as-is
|
206
|
+
via ``xms_cc`` parameter on the wire.
|
207
|
+
|
195
208
|
Recipe 1: Hard code a managed identity for your app::
|
196
209
|
|
197
210
|
import msal, requests
|
@@ -237,6 +250,7 @@ class ManagedIdentityClient(object):
|
|
237
250
|
http_cache=http_cache,
|
238
251
|
)
|
239
252
|
self._token_cache = token_cache or TokenCache()
|
253
|
+
self._client_capabilities = client_capabilities
|
240
254
|
|
241
255
|
def _get_instance(self):
|
242
256
|
if self.__instance is None:
|
@@ -265,8 +279,7 @@ class ManagedIdentityClient(object):
|
|
265
279
|
and then a *claims challenge* will be returned by the target resource,
|
266
280
|
as a `claims_challenge` directive in the `www-authenticate` header,
|
267
281
|
even if the app developer did not opt in for the "CP1" client capability.
|
268
|
-
Upon receiving a `claims_challenge`, MSAL will
|
269
|
-
and will attempt to acquire a new token.
|
282
|
+
Upon receiving a `claims_challenge`, MSAL will attempt to acquire a new token.
|
270
283
|
|
271
284
|
.. note::
|
272
285
|
|
@@ -277,12 +290,14 @@ class ManagedIdentityClient(object):
|
|
277
290
|
This is a service-side behavior that cannot be changed by this library.
|
278
291
|
`Azure VM docs <https://learn.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/how-to-use-vm-token#get-a-token-using-http>`_
|
279
292
|
"""
|
293
|
+
access_token_to_refresh = None # This could become a public parameter in the future
|
280
294
|
access_token_from_cache = None
|
281
295
|
client_id_in_cache = self._managed_identity.get(
|
282
296
|
ManagedIdentity.ID, "SYSTEM_ASSIGNED_MANAGED_IDENTITY")
|
283
297
|
now = time.time()
|
284
|
-
if
|
285
|
-
|
298
|
+
if True: # Attempt cache search even if receiving claims_challenge,
|
299
|
+
# because we want to locate the existing token (if any) and refresh it
|
300
|
+
matches = self._token_cache.search(
|
286
301
|
self._token_cache.CredentialType.ACCESS_TOKEN,
|
287
302
|
target=[resource],
|
288
303
|
query=dict(
|
@@ -296,6 +311,11 @@ class ManagedIdentityClient(object):
|
|
296
311
|
expires_in = int(entry["expires_on"]) - now
|
297
312
|
if expires_in < 5*60: # Then consider it expired
|
298
313
|
continue # Removal is not necessary, it will be overwritten
|
314
|
+
if claims_challenge and not access_token_to_refresh:
|
315
|
+
# Since caller did not pinpoint the token causing claims challenge,
|
316
|
+
# we have to assume it is the first token we found in cache.
|
317
|
+
access_token_to_refresh = entry["secret"]
|
318
|
+
break
|
299
319
|
logger.debug("Cache hit an AT")
|
300
320
|
access_token_from_cache = { # Mimic a real response
|
301
321
|
"access_token": entry["secret"],
|
@@ -309,7 +329,13 @@ class ManagedIdentityClient(object):
|
|
309
329
|
break # With a fallback in hand, we break here to go refresh
|
310
330
|
return access_token_from_cache # It is still good as new
|
311
331
|
try:
|
312
|
-
result = _obtain_token(
|
332
|
+
result = _obtain_token(
|
333
|
+
self._http_client, self._managed_identity, resource,
|
334
|
+
access_token_sha256_to_refresh=hashlib.sha256(
|
335
|
+
access_token_to_refresh.encode("utf-8")).hexdigest()
|
336
|
+
if access_token_to_refresh else None,
|
337
|
+
client_capabilities=self._client_capabilities,
|
338
|
+
)
|
313
339
|
if "access_token" in result:
|
314
340
|
expires_in = result.get("expires_in", 3600)
|
315
341
|
if "refresh_in" not in result and expires_in >= 7200:
|
@@ -384,8 +410,12 @@ def get_managed_identity_source():
|
|
384
410
|
return DEFAULT_TO_VM
|
385
411
|
|
386
412
|
|
387
|
-
def _obtain_token(
|
388
|
-
|
413
|
+
def _obtain_token(
|
414
|
+
http_client, managed_identity, resource,
|
415
|
+
*,
|
416
|
+
access_token_sha256_to_refresh: Optional[str] = None,
|
417
|
+
client_capabilities: Optional[List[str]] = None,
|
418
|
+
):
|
389
419
|
if ("IDENTITY_ENDPOINT" in os.environ and "IDENTITY_HEADER" in os.environ
|
390
420
|
and "IDENTITY_SERVER_THUMBPRINT" in os.environ
|
391
421
|
):
|
@@ -401,6 +431,8 @@ def _obtain_token(http_client, managed_identity, resource):
|
|
401
431
|
os.environ["IDENTITY_HEADER"],
|
402
432
|
os.environ["IDENTITY_SERVER_THUMBPRINT"],
|
403
433
|
resource,
|
434
|
+
access_token_sha256_to_refresh=access_token_sha256_to_refresh,
|
435
|
+
client_capabilities=client_capabilities,
|
404
436
|
)
|
405
437
|
if "IDENTITY_ENDPOINT" in os.environ and "IDENTITY_HEADER" in os.environ:
|
406
438
|
return _obtain_token_on_app_service(
|
@@ -552,6 +584,9 @@ def _obtain_token_on_machine_learning(
|
|
552
584
|
|
553
585
|
def _obtain_token_on_service_fabric(
|
554
586
|
http_client, endpoint, identity_header, server_thumbprint, resource,
|
587
|
+
*,
|
588
|
+
access_token_sha256_to_refresh: str = None,
|
589
|
+
client_capabilities: Optional[List[str]] = None,
|
555
590
|
):
|
556
591
|
"""Obtains token for
|
557
592
|
`Service Fabric <https://learn.microsoft.com/en-us/azure/service-fabric/>`_
|
@@ -562,7 +597,12 @@ def _obtain_token_on_service_fabric(
|
|
562
597
|
logger.debug("Obtaining token via managed identity on Azure Service Fabric")
|
563
598
|
resp = http_client.get(
|
564
599
|
endpoint,
|
565
|
-
params={
|
600
|
+
params={k: v for k, v in {
|
601
|
+
"api-version": "2019-07-01-preview",
|
602
|
+
"resource": resource,
|
603
|
+
"token_sha256_to_refresh": access_token_sha256_to_refresh,
|
604
|
+
"xms_cc": ",".join(client_capabilities) if client_capabilities else None,
|
605
|
+
}.items() if v is not None},
|
566
606
|
headers={"Secret": identity_header},
|
567
607
|
)
|
568
608
|
try:
|
@@ -583,7 +623,7 @@ def _obtain_token_on_service_fabric(
|
|
583
623
|
"ArgumentNullOrEmpty": "invalid_scope",
|
584
624
|
}
|
585
625
|
return {
|
586
|
-
"error": error_mapping.get(
|
626
|
+
"error": error_mapping.get(error.get("code"), "invalid_request"),
|
587
627
|
"error_description": resp.text,
|
588
628
|
}
|
589
629
|
except json.decoder.JSONDecodeError:
|
@@ -66,7 +66,10 @@ class NormalizedResponse(Response):
|
|
66
66
|
# self.raise_for_status = raw_response.raise_for_status
|
67
67
|
def raise_for_status(self):
|
68
68
|
if self.status_code >= 400:
|
69
|
-
raise MsalServiceError(
|
69
|
+
raise MsalServiceError(
|
70
|
+
"HTTP Error: {}".format(self.status_code),
|
71
|
+
error=None, error_description=None, # Historically required, keeping them for now
|
72
|
+
)
|
70
73
|
|
71
74
|
|
72
75
|
class ThrottledHttpClientBase(object):
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: py2docfx
|
3
|
-
Version: 0.1.19.
|
3
|
+
Version: 0.1.19.dev2192444
|
4
4
|
Summary: A package built based on Sphinx which download source code package and generate yaml files supported by docfx.
|
5
5
|
Author: Microsoft Corporation
|
6
6
|
License: MIT License
|
@@ -1,13 +1,13 @@
|
|
1
1
|
py2docfx/__init__.py,sha256=kPRhPGPC1JknDotkksG428c1iIgfFr_4_7Jm-llrowY,72
|
2
|
-
py2docfx/__main__.py,sha256=
|
2
|
+
py2docfx/__main__.py,sha256=NDKRx5RhLJP6Z6zFEdGZJje69jxPaGeHLU_2e5GYUO4,5958
|
3
3
|
py2docfx/convert_prepare/__init__.py,sha256=XxtxrP0kmW3ZBHIAoxsPDEHzcgeC0WSnole8Lk6CjKs,11
|
4
4
|
py2docfx/convert_prepare/arg_parser.py,sha256=Wa1iK8a0Gb3QqaS4X7nUPGvh-7mWhuBS9IVbmnjC770,7606
|
5
5
|
py2docfx/convert_prepare/constants.py,sha256=RC5DqNkqWvx4hb91FrajZ1R9dBFLxcPyoEJ43jdm36E,102
|
6
6
|
py2docfx/convert_prepare/environment.py,sha256=CF8g2hnpwFXsTfvp1O8lwYpR848iCK8bDM2UAWqibEQ,7286
|
7
7
|
py2docfx/convert_prepare/generate_conf.py,sha256=wqs6iyElzJarH-20_qEL9zvZvt5xfBMsGXSXPSZy6wg,2295
|
8
8
|
py2docfx/convert_prepare/generate_document.py,sha256=iTOCMBwkfvZEj5dlEGUq4qynUodaYxJuIrG9R5eGk38,2949
|
9
|
-
py2docfx/convert_prepare/get_source.py,sha256=
|
10
|
-
py2docfx/convert_prepare/git.py,sha256=
|
9
|
+
py2docfx/convert_prepare/get_source.py,sha256=I_-QXXFFraMruDf13xlkwGAs5hDuv-wAjW3w-ylOw2Q,6930
|
10
|
+
py2docfx/convert_prepare/git.py,sha256=Cq76ooxejKlVJiJWWbBhbLZ_JvxqN2ka12L8jkl80b4,6492
|
11
11
|
py2docfx/convert_prepare/install_package.py,sha256=aJxQBwLRPTIKpdtLVl-SaXPaF_OX_H1ZtWmcKD8Zzuk,274
|
12
12
|
py2docfx/convert_prepare/pack.py,sha256=Jjj9ps8ESoKUFmSk6VgNmxOwMhuwirnQ-rhqigH-4VY,1578
|
13
13
|
py2docfx/convert_prepare/package_info.py,sha256=-zrMNeAkHxxzLRjBl1kRehUJy_ugc16yns-xdcAHQIQ,7711
|
@@ -65,7 +65,7 @@ py2docfx/docfx_yaml/convert_enum.py,sha256=HX6qdjDbdbBblx-TH41JXBLIJY3wzL3if-qnL
|
|
65
65
|
py2docfx/docfx_yaml/convert_module.py,sha256=GptO1MRwaQ2Qbu724F0kCDDQQTZe7mWOtrOp3Rzgl-I,2259
|
66
66
|
py2docfx/docfx_yaml/convert_package.py,sha256=Ep7PmvoLInDvY6OU5dveR6iVwyzGRkW3q6lX7yGJ0JE,2109
|
67
67
|
py2docfx/docfx_yaml/directives.py,sha256=zVVuNM_6AU9G6sbqL1UAyHHgPe7bkBWbthXI-PO5ez0,879
|
68
|
-
py2docfx/docfx_yaml/logger.py,sha256=
|
68
|
+
py2docfx/docfx_yaml/logger.py,sha256=V09O17R0YFvLFKKc5-aSXWO4iFufQzpgaxMa6EzNqHM,6817
|
69
69
|
py2docfx/docfx_yaml/miss_reference.py,sha256=NHoQtas0kvFsJXaR4fsk7kHjwV4aJobrr_Q30HaUc_I,2450
|
70
70
|
py2docfx/docfx_yaml/nodes.py,sha256=tBDi35jLJArlobl07DKOkmH2qz7dudXLp_kTUfR_r2w,412
|
71
71
|
py2docfx/docfx_yaml/parameter_utils.py,sha256=04wQCtbS-G2hWM5UGkL22s10LZLUbqbh3RM9rWGOToI,10897
|
@@ -166,7 +166,7 @@ py2docfx/venv/basevenv/Lib/site-packages/babel/messages/mofile.py,sha256=Qf0X-vI
|
|
166
166
|
py2docfx/venv/basevenv/Lib/site-packages/babel/messages/plurals.py,sha256=jsEnofU5b4PZKIloX0MjchYSxD3r1RRZ_GfEVRuETWQ,7495
|
167
167
|
py2docfx/venv/basevenv/Lib/site-packages/babel/messages/pofile.py,sha256=lMllxTXYRBa3m8wVsxXsJsayjCOePKYYZtFSZU5DVF4,25955
|
168
168
|
py2docfx/venv/basevenv/Lib/site-packages/babel/messages/setuptools_frontend.py,sha256=m1l9NHuawj1pSncZeC82cUJfdwxib_C7JSUb_2EhbUM,3485
|
169
|
-
py2docfx/venv/basevenv/Lib/site-packages/certifi/__init__.py,sha256=
|
169
|
+
py2docfx/venv/basevenv/Lib/site-packages/certifi/__init__.py,sha256=0a5ro4KTYep37Oo0Z8TycCPXaDlOEtvuj2pNWZ_1t8Y,94
|
170
170
|
py2docfx/venv/basevenv/Lib/site-packages/certifi/__main__.py,sha256=xBBoj905TUWBLRGANOcf7oi6e-3dMP4cEoG9OyMs11g,243
|
171
171
|
py2docfx/venv/basevenv/Lib/site-packages/certifi/core.py,sha256=XFXycndG5pf37ayeF8N32HUuDafsyhkVMbO4BAPWHa0,3394
|
172
172
|
py2docfx/venv/basevenv/Lib/site-packages/certifi/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -2081,7 +2081,7 @@ py2docfx/venv/venv1/Lib/site-packages/cachetools/__init__.py,sha256=cutUU6fB1bIM
|
|
2081
2081
|
py2docfx/venv/venv1/Lib/site-packages/cachetools/_decorators.py,sha256=4_u0GL89t2BOLGwnK8CueiFtyHKK2zydoHj9aqnsMM4,3832
|
2082
2082
|
py2docfx/venv/venv1/Lib/site-packages/cachetools/func.py,sha256=aOVfSkuNWMRADpkHZGK7LeJ_VZ8wljzbRwIAliOuhAg,3719
|
2083
2083
|
py2docfx/venv/venv1/Lib/site-packages/cachetools/keys.py,sha256=AOgfoi-oioBOnEEk115_9qs0HKISrYnbcV4F0hyZ1yk,1777
|
2084
|
-
py2docfx/venv/venv1/Lib/site-packages/certifi/__init__.py,sha256=
|
2084
|
+
py2docfx/venv/venv1/Lib/site-packages/certifi/__init__.py,sha256=0a5ro4KTYep37Oo0Z8TycCPXaDlOEtvuj2pNWZ_1t8Y,94
|
2085
2085
|
py2docfx/venv/venv1/Lib/site-packages/certifi/__main__.py,sha256=xBBoj905TUWBLRGANOcf7oi6e-3dMP4cEoG9OyMs11g,243
|
2086
2086
|
py2docfx/venv/venv1/Lib/site-packages/certifi/core.py,sha256=XFXycndG5pf37ayeF8N32HUuDafsyhkVMbO4BAPWHa0,3394
|
2087
2087
|
py2docfx/venv/venv1/Lib/site-packages/certifi/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -2553,20 +2553,20 @@ py2docfx/venv/venv1/Lib/site-packages/jwt/types.py,sha256=VnhGv_VFu5a7_mrPoSCB7H
|
|
2553
2553
|
py2docfx/venv/venv1/Lib/site-packages/jwt/utils.py,sha256=hxOjvDBheBYhz-RIPiEz7Q88dSUSTMzEdKE_Ww2VdJw,3640
|
2554
2554
|
py2docfx/venv/venv1/Lib/site-packages/jwt/warnings.py,sha256=50XWOnyNsIaqzUJTk6XHNiIDykiL763GYA92MjTKmok,59
|
2555
2555
|
py2docfx/venv/venv1/Lib/site-packages/msal/__init__.py,sha256=U8y4dCI4xqYgP0iQA19EQsm7ESUqitGR-xySLGX66EA,2089
|
2556
|
-
py2docfx/venv/venv1/Lib/site-packages/msal/__main__.py,sha256
|
2557
|
-
py2docfx/venv/venv1/Lib/site-packages/msal/application.py,sha256=
|
2556
|
+
py2docfx/venv/venv1/Lib/site-packages/msal/__main__.py,sha256=gk_iJRPMl-9Zq8qx-wylPHiT_h1suhIeR0ir1wR9160,16516
|
2557
|
+
py2docfx/venv/venv1/Lib/site-packages/msal/application.py,sha256=snKVtshd4wU5UVERSqB2uKuVRU272YoEoF5qsbok-CM,130378
|
2558
2558
|
py2docfx/venv/venv1/Lib/site-packages/msal/auth_scheme.py,sha256=biI1W2ZEV2u5cQpsF1JK2ykLuyTCKaRZicgOa2kQqaA,1505
|
2559
2559
|
py2docfx/venv/venv1/Lib/site-packages/msal/authority.py,sha256=gT86mPhoxmVQ0aU6hOyOcMnXGKpbxDWKhNRWcPgQXAc,11314
|
2560
|
-
py2docfx/venv/venv1/Lib/site-packages/msal/broker.py,sha256=
|
2560
|
+
py2docfx/venv/venv1/Lib/site-packages/msal/broker.py,sha256=fdcLXhnWAizF3LrJVqJHsnavamTByeGczLjVaJDcXrM,12956
|
2561
2561
|
py2docfx/venv/venv1/Lib/site-packages/msal/cloudshell.py,sha256=KXTRgX5zfRuNqRfVQs_buS8gU9N40sc2C5rBi79bnBk,5319
|
2562
|
-
py2docfx/venv/venv1/Lib/site-packages/msal/exceptions.py,sha256=
|
2562
|
+
py2docfx/venv/venv1/Lib/site-packages/msal/exceptions.py,sha256=UqFHnCfSKXYZVlZEZDHvBCRe3-0b-YoGUS9PilsJcvY,2518
|
2563
2563
|
py2docfx/venv/venv1/Lib/site-packages/msal/individual_cache.py,sha256=K2e72EP3eEoDvGQc9OWY1rvQxJmO4IOqcaG-F7cHuJk,13090
|
2564
|
-
py2docfx/venv/venv1/Lib/site-packages/msal/managed_identity.py,sha256=
|
2564
|
+
py2docfx/venv/venv1/Lib/site-packages/msal/managed_identity.py,sha256=F_Q_MCrO7tx2kQBRJA1UVN9oTmr2XYShExPNRwDzlZk,32212
|
2565
2565
|
py2docfx/venv/venv1/Lib/site-packages/msal/mex.py,sha256=_oub-3zNJUpt1KTRt_XUMxEMTOjHhLZQjzb_VLFHVHc,6455
|
2566
2566
|
py2docfx/venv/venv1/Lib/site-packages/msal/region.py,sha256=N7Z43sbwjnQfoUQC6TBR8xy3v1oY_rI8hH0-AfiXa8g,1738
|
2567
|
-
py2docfx/venv/venv1/Lib/site-packages/msal/sku.py,sha256=
|
2567
|
+
py2docfx/venv/venv1/Lib/site-packages/msal/sku.py,sha256=aPQf6TUIo37-jimfXpnetT7rrJ8vjmyJbbcBefjDQR8,183
|
2568
2568
|
py2docfx/venv/venv1/Lib/site-packages/msal/telemetry.py,sha256=ePllJwgA14s-n70prBndAoyiQAMYy1aVam6VXexU0Ac,3192
|
2569
|
-
py2docfx/venv/venv1/Lib/site-packages/msal/throttled_http_client.py,sha256=
|
2569
|
+
py2docfx/venv/venv1/Lib/site-packages/msal/throttled_http_client.py,sha256=No8Z2zGQhyxBMFi_mum1S1sCyB7_IaN258JM0vHAhIA,9023
|
2570
2570
|
py2docfx/venv/venv1/Lib/site-packages/msal/token_cache.py,sha256=C7wT4_VXQ3dDYxVIEv-Dm_m0Xo2ZJFXWkH21XnUVLcU,20713
|
2571
2571
|
py2docfx/venv/venv1/Lib/site-packages/msal/wstrust_request.py,sha256=2S5eKxmK8fklnirBGewtdhkcA7O8JvE1KhJ8-c9k4yw,6098
|
2572
2572
|
py2docfx/venv/venv1/Lib/site-packages/msal/wstrust_response.py,sha256=QfmdjMEf1vED8vGmtIMWI1UvspUHtFJ8ACjMfecje2g,4599
|
@@ -3913,7 +3913,7 @@ py2docfx/venv/venv1/Lib/site-packages/wheel/_commands/convert.py,sha256=0wSJMU0m
|
|
3913
3913
|
py2docfx/venv/venv1/Lib/site-packages/wheel/_commands/pack.py,sha256=o3iwjfRHl7N9ul-M2kHbewLJZnqBLAWf0tzUCwoiTMw,3078
|
3914
3914
|
py2docfx/venv/venv1/Lib/site-packages/wheel/_commands/tags.py,sha256=Rv2ySVb8-qX3osKp3uJgxcIMXkjt43XUD0-zvC6KvnY,4775
|
3915
3915
|
py2docfx/venv/venv1/Lib/site-packages/wheel/_commands/unpack.py,sha256=Y_J7ynxPSoFFTT7H0fMgbBlVErwyDGcObgme5MBuz58,1021
|
3916
|
-
py2docfx-0.1.19.
|
3917
|
-
py2docfx-0.1.19.
|
3918
|
-
py2docfx-0.1.19.
|
3919
|
-
py2docfx-0.1.19.
|
3916
|
+
py2docfx-0.1.19.dev2192444.dist-info/METADATA,sha256=MCJHbQ0eJXL1aKxUwM6tcI_20MWWar1J5QUqgG5_Hzo,548
|
3917
|
+
py2docfx-0.1.19.dev2192444.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
3918
|
+
py2docfx-0.1.19.dev2192444.dist-info/top_level.txt,sha256=5dH2uP81dczt_qQJ38wiZ-gzoVWasfiJALWRSjdbnYU,9
|
3919
|
+
py2docfx-0.1.19.dev2192444.dist-info/RECORD,,
|
File without changes
|
File without changes
|