nextlayer-sdk-python 1.1.0__py3-none-any.whl → 1.2.1__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.
nextlayer/sdk/__init__.py CHANGED
@@ -1,2 +1,2 @@
1
1
  # do not edit this version line, it will be updated in CI-Pipeline!
2
- __version__ = "v1.1.0"
2
+ __version__ = "v1.2.1"
nextlayer/sdk/auth.py CHANGED
@@ -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
@@ -1,4 +1,5 @@
1
- from typing import Generator
1
+ import asyncio
2
+ from typing import AsyncGenerator, Generator
2
3
 
3
4
  import httpx
4
5
 
@@ -19,3 +20,18 @@ class NlHttpxAuth(httpx.Auth):
19
20
  ) -> Generator[httpx.Request, httpx.Response, None]:
20
21
  request.headers["Authorization"] = "Bearer " + self.nlauth.get_access_token()
21
22
  yield request
23
+
24
+ async def async_auth_flow(
25
+ self, request: httpx.Request
26
+ ) -> AsyncGenerator[httpx.Request, httpx.Response]:
27
+ # NlAuth.get_access_token() does blocking file I/O and, on refresh/login,
28
+ # a blocking HTTP call to Keycloak - offload it so it doesn't stall the
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:
35
+ access_token = await asyncio.to_thread(self.nlauth.get_access_token)
36
+ request.headers["Authorization"] = "Bearer " + access_token
37
+ yield request
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nextlayer-sdk-python
3
- Version: 1.1.0
3
+ Version: 1.2.1
4
4
  Summary: Client utilities to interact with next layer public APIs
5
5
  Author: Wolfgang Powisch
6
6
  Author-email: wolfgang.powisch@nextlayer.at
@@ -0,0 +1,11 @@
1
+ nextlayer/sdk/__init__.py,sha256=sWOPCd1Jr15QBJpoy9twf0dTxxMeX6ZmRaiOBHmOCCA,91
2
+ nextlayer/sdk/__init__.pye,sha256=fIfxryYAp41WbubhUjhitrpwoi6wXFQCZL40RdI4tHA,90
3
+ nextlayer/sdk/auth.py,sha256=GLqENjPmzq_jVH3xwAtlYcp2NrFq6HTVUf7_cUo08UM,14314
4
+ nextlayer/sdk/auth_code_browser_flow.py,sha256=luPScN2WFJtBzUc-6jEGx1zx3cjfgsl1UQweikD3y90,4648
5
+ nextlayer/sdk/auth_httpx.py,sha256=aAd3cABajn7vH9ZGgh_zQVwQos-cpHHFuieu2Xgeasc,1594
6
+ nextlayer/sdk/errors.py,sha256=ZylQSsiFOulLaFwIeBHK0ZWo2Vn6AjML8PoNGIDdx8c,430
7
+ nextlayer/sdk/utils.py,sha256=JPkPuy1bU4jBOf0NunYWMqwrwKmNa2OKNTGPv_UaH6s,583
8
+ nextlayer_sdk_python-1.2.1.dist-info/METADATA,sha256=4OKFCpgICe_MXLKWFHM4DosAQ7CzKZpmbkyuytapBAc,2906
9
+ nextlayer_sdk_python-1.2.1.dist-info/WHEEL,sha256=EGEvSphFYqXKs23-kQBeyNoJP1nrT8ZJKQoi5p5DYL8,88
10
+ nextlayer_sdk_python-1.2.1.dist-info/entry_points.txt,sha256=d2f4hShiG0Z_TDG72fCWJdOUZkXPfmPBUIieDXh94d0,58
11
+ nextlayer_sdk_python-1.2.1.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 2.2.1
2
+ Generator: poetry-core 2.4.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -1,11 +0,0 @@
1
- nextlayer/sdk/__init__.py,sha256=NxlAYeesZK2o7oYu_DI8iFduo5smKVKK5zaWPX5VNdg,91
2
- nextlayer/sdk/__init__.pye,sha256=fIfxryYAp41WbubhUjhitrpwoi6wXFQCZL40RdI4tHA,90
3
- nextlayer/sdk/auth.py,sha256=i89o0NmSgR9gwntoihfQ_CqyH7iT_FS-w9vCqLMJV5k,13911
4
- nextlayer/sdk/auth_code_browser_flow.py,sha256=luPScN2WFJtBzUc-6jEGx1zx3cjfgsl1UQweikD3y90,4648
5
- nextlayer/sdk/auth_httpx.py,sha256=g04GqH_lbr2UNA5rGzk_G0VvN9Um1xezqVuWz8WaAyU,692
6
- nextlayer/sdk/errors.py,sha256=ZylQSsiFOulLaFwIeBHK0ZWo2Vn6AjML8PoNGIDdx8c,430
7
- nextlayer/sdk/utils.py,sha256=JPkPuy1bU4jBOf0NunYWMqwrwKmNa2OKNTGPv_UaH6s,583
8
- nextlayer_sdk_python-1.1.0.dist-info/METADATA,sha256=JkhVMxKu3GgjgFkNk8-UcI1p7dz6xMvcw6ZCG9isKio,2906
9
- nextlayer_sdk_python-1.1.0.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
10
- nextlayer_sdk_python-1.1.0.dist-info/entry_points.txt,sha256=d2f4hShiG0Z_TDG72fCWJdOUZkXPfmPBUIieDXh94d0,58
11
- nextlayer_sdk_python-1.1.0.dist-info/RECORD,,