nextlayer-sdk-python 1.2.0__tar.gz → 1.2.1__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.
- {nextlayer_sdk_python-1.2.0 → nextlayer_sdk_python-1.2.1}/PKG-INFO +1 -1
- {nextlayer_sdk_python-1.2.0 → nextlayer_sdk_python-1.2.1}/pyproject.toml +1 -1
- {nextlayer_sdk_python-1.2.0 → nextlayer_sdk_python-1.2.1}/src/nextlayer/sdk/__init__.py +1 -1
- {nextlayer_sdk_python-1.2.0 → nextlayer_sdk_python-1.2.1}/src/nextlayer/sdk/auth.py +8 -0
- {nextlayer_sdk_python-1.2.0 → nextlayer_sdk_python-1.2.1}/src/nextlayer/sdk/auth_httpx.py +6 -4
- {nextlayer_sdk_python-1.2.0 → nextlayer_sdk_python-1.2.1}/README.md +0 -0
- {nextlayer_sdk_python-1.2.0 → nextlayer_sdk_python-1.2.1}/src/nextlayer/sdk/__init__.pye +0 -0
- {nextlayer_sdk_python-1.2.0 → nextlayer_sdk_python-1.2.1}/src/nextlayer/sdk/auth_code_browser_flow.py +0 -0
- {nextlayer_sdk_python-1.2.0 → nextlayer_sdk_python-1.2.1}/src/nextlayer/sdk/errors.py +0 -0
- {nextlayer_sdk_python-1.2.0 → nextlayer_sdk_python-1.2.1}/src/nextlayer/sdk/utils.py +0 -0
|
@@ -3,7 +3,7 @@ name = "nextlayer-sdk-python"
|
|
|
3
3
|
packages = [
|
|
4
4
|
{ include = "nextlayer", from="src" }
|
|
5
5
|
]
|
|
6
|
-
version = "1.2.
|
|
6
|
+
version = "1.2.1"
|
|
7
7
|
description = "Client utilities to interact with next layer public APIs"
|
|
8
8
|
readme = "README.md"
|
|
9
9
|
authors = ["Wolfgang Powisch <wolfgang.powisch@nextlayer.at>"]
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
# do not edit this version line, it will be updated in CI-Pipeline!
|
|
2
|
-
__version__ = "v1.2.
|
|
2
|
+
__version__ = "v1.2.1"
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
+
import asyncio
|
|
2
3
|
import datetime
|
|
3
4
|
import getpass
|
|
4
5
|
import json
|
|
@@ -160,6 +161,13 @@ class NlAuth(object):
|
|
|
160
161
|
verify=True,
|
|
161
162
|
)
|
|
162
163
|
|
|
164
|
+
# shared by NlHttpxAuth.async_auth_flow() so that multiple async Auth
|
|
165
|
+
# wrappers around the same NlAuth instance (e.g. one per API client,
|
|
166
|
+
# all backed by one shared NlAuth singleton) serialize their
|
|
167
|
+
# get_access_token() calls instead of racing concurrent
|
|
168
|
+
# do_refresh()/do_login() calls against Keycloak.
|
|
169
|
+
self.async_lock = asyncio.Lock()
|
|
170
|
+
|
|
163
171
|
def token_expired(self) -> bool:
|
|
164
172
|
now = int(time.time())
|
|
165
173
|
exp_at = self.store.config.expires_at
|
|
@@ -14,7 +14,6 @@ class NlHttpxAuth(httpx.Auth):
|
|
|
14
14
|
else:
|
|
15
15
|
# pass all arguments to NlAuth constructor and create NlAuth instance internally
|
|
16
16
|
self.nlauth = NlAuth(*args, **kwargs)
|
|
17
|
-
self._lock = asyncio.Lock()
|
|
18
17
|
|
|
19
18
|
def auth_flow(
|
|
20
19
|
self, request: httpx.Request
|
|
@@ -27,9 +26,12 @@ class NlHttpxAuth(httpx.Auth):
|
|
|
27
26
|
) -> AsyncGenerator[httpx.Request, httpx.Response]:
|
|
28
27
|
# NlAuth.get_access_token() does blocking file I/O and, on refresh/login,
|
|
29
28
|
# a blocking HTTP call to Keycloak - offload it so it doesn't stall the
|
|
30
|
-
# event loop. The lock
|
|
31
|
-
#
|
|
32
|
-
|
|
29
|
+
# event loop. The lock lives on the NlAuth instance (not here) so that
|
|
30
|
+
# multiple NlHttpxAuth wrappers sharing one NlAuth (e.g. one per API
|
|
31
|
+
# client, backed by a shared NlAuth singleton) also share the lock -
|
|
32
|
+
# otherwise they could still race concurrent refresh/login calls
|
|
33
|
+
# against Keycloak, which the lock is meant to prevent.
|
|
34
|
+
async with self.nlauth.async_lock:
|
|
33
35
|
access_token = await asyncio.to_thread(self.nlauth.get_access_token)
|
|
34
36
|
request.headers["Authorization"] = "Bearer " + access_token
|
|
35
37
|
yield request
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|