Skip to content

Commit ffee571

Browse files
committed
Fixes done
1 parent 6dab7aa commit ffee571

File tree

3 files changed

+24
-3
lines changed

3 files changed

+24
-3
lines changed

pyatlan/client/aio/client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
from contextlib import _AsyncGeneratorContextManager
1717
from http import HTTPStatus
1818
from types import SimpleNamespace
19-
from typing import Optional
19+
from typing import Any, Optional
2020

2121
import httpx
2222
from httpx_retries.retry import Retry

pyatlan/client/atlan.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,12 @@ def __init__(self, **data):
192192
else {"headers": {}}
193193
)
194194

195+
# Build proxy/SSL configuration with environment variable fallback
195196
transport_kwargs = self._build_transport_proxy_config(data)
197+
198+
# Configure httpx client with custom transport that supports retry and proxy
199+
# Note: We pass proxy/SSL config to the transport, not the client,
200+
# so that retry logic properly respects these settings
196201
self._session = httpx.Client(
197202
transport=PyatlanSyncTransport(retry=self.retry, **transport_kwargs),
198203
headers={
@@ -832,6 +837,9 @@ def _create_params(
832837
params["params"] = query_params
833838
if request_obj is not None:
834839
if isinstance(request_obj, AtlanObject):
840+
# Always use AtlanRequest, which accepts a Pydantic model instance and the client
841+
# Behind the scenes, it handles retranslation tasks—such as converting
842+
# human-readable Atlan tag names back into hashed IDs as required by the backend
835843
params["data"] = AtlanRequest(instance=request_obj, client=self).json()
836844
elif api.consumes == APPLICATION_ENCODED_FORM:
837845
params["data"] = request_obj
@@ -848,6 +856,13 @@ def _handle_401_token_refresh(
848856
download_file_path=None,
849857
text_response=False,
850858
):
859+
"""
860+
Handles token refresh and retries the API request upon a 401 Unauthorized response.
861+
1. Impersonates the user (if a user ID is available) to fetch a new token.
862+
2. Updates the authorization header with the refreshed token.
863+
3. Retries the API request with the new token.
864+
returns: HTTP response received after retrying the request with the refreshed token
865+
"""
851866
if self._oauth_token_manager:
852867
self._oauth_token_manager.invalidate_token()
853868
token = self._oauth_token_manager.get_token()
@@ -878,6 +893,11 @@ def _handle_401_token_refresh(
878893
self._request_params["headers"]["authorization"] = f"Bearer {self.api_key}"
879894
LOGGER.debug("Successfully completed 401 automatic token refresh.")
880895

896+
# Added a retry loop to ensure a token is active before retrying original request
897+
# This helps ensure that when we fetch typedefs using the new token,
898+
# the backend has fully recognized the token as valid.
899+
# Without this delay, we occasionally get an empty response `[]` from the API,
900+
# likely because the backend hasn’t fully propagated token validity yet.
881901
import time
882902

883903
retry_count = 1
@@ -891,9 +911,10 @@ def _handle_401_token_refresh(
891911
"Retrying to get typedefs (to ensure token is active) after token refresh failed: %s",
892912
e,
893913
)
894-
time.sleep(retry_count)
914+
time.sleep(retry_count) # Linear backoff
895915
retry_count += 1
896916

917+
# Retry the API call with the new token
897918
return self._call_api_internal(
898919
api,
899920
path,

pyatlan/client/oauth.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ def get_token(self) -> str:
4343
data = response.json()
4444
access_token = data.get("accessToken") or data.get("access_token")
4545
expires_in = data.get("expiresIn") or data.get("expires_in", 600)
46-
print(data.get("expiresIn"))
46+
4747
self._token = OAuth2Token(
4848
{
4949
"access_token": access_token,

0 commit comments

Comments
 (0)