Skip to content

Commit c7903dc

Browse files
committed
Fixes to the code and improvemnt
1 parent eaf6dd7 commit c7903dc

File tree

7 files changed

+81
-13
lines changed

7 files changed

+81
-13
lines changed

pyatlan/client/aio/client.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -146,10 +146,19 @@ def __init__(self, **kwargs):
146146
self._oauth_token_manager.close()
147147
self._oauth_token_manager = None
148148

149+
final_base_url = self.base_url or os.environ.get(
150+
"ATLAN_BASE_URL", "INTERNAL"
151+
)
152+
final_oauth_client_id = self.oauth_client_id or os.environ.get(
153+
"ATLAN_OAUTH_CLIENT_ID"
154+
)
155+
final_oauth_client_secret = self.oauth_client_secret or os.environ.get(
156+
"ATLAN_OAUTH_CLIENT_SECRET"
157+
)
149158
self._async_oauth_token_manager = AsyncOAuthTokenManager(
150-
base_url=str(self.base_url),
151-
client_id=self.oauth_client_id,
152-
client_secret=self.oauth_client_secret,
159+
base_url=final_base_url,
160+
client_id=final_oauth_client_id,
161+
client_secret=final_oauth_client_secret,
153162
)
154163

155164
# Build proxy/SSL configuration (reuse from sync client)

pyatlan/client/aio/oauth.py

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
import httpx
88
from authlib.oauth2.rfc6749 import OAuth2Token
99

10+
from pyatlan.client.constants import GET_OAUTH_CLIENT
11+
from pyatlan.utils import API
12+
1013

1114
class AsyncOAuthTokenManager:
1215
def __init__(
@@ -16,10 +19,10 @@ def __init__(
1619
client_secret: str,
1720
http_client: Optional[httpx.AsyncClient] = None,
1821
):
19-
self.base_url = base_url.rstrip("/")
22+
self.base_url = base_url
2023
self.client_id = client_id
2124
self.client_secret = client_secret
22-
self.token_url = f"{self.base_url}/api/service/oauth-clients/token"
25+
self.token_url = self._create_path(GET_OAUTH_CLIENT)
2326
self._lock = asyncio.Lock()
2427
self._http_client = http_client or httpx.AsyncClient(timeout=30.0)
2528
self._token: Optional[OAuth2Token] = None
@@ -28,7 +31,7 @@ def __init__(
2831
async def get_token(self) -> str:
2932
async with self._lock:
3033
if self._token and not self._token.is_expired():
31-
return self._token["access_token"]
34+
return str(self._token["access_token"])
3235

3336
response = await self._http_client.post(
3437
self.token_url,
@@ -67,6 +70,16 @@ async def invalidate_token(self):
6770
async with self._lock:
6871
self._token = None
6972

73+
def _create_path(self, api: API):
74+
from urllib.parse import urljoin
75+
76+
if self.base_url == "INTERNAL":
77+
base_with_prefix = urljoin(api.endpoint.service, api.endpoint.prefix)
78+
return urljoin(base_with_prefix, api.path)
79+
else:
80+
base_with_prefix = urljoin(self.base_url, api.endpoint.prefix)
81+
return urljoin(base_with_prefix, api.path)
82+
7083
async def aclose(self):
7184
if self._owns_client:
7285
await self._http_client.aclose()

pyatlan/client/atlan.py

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
from pyatlan.client.file import FileClient
4949
from pyatlan.client.group import GroupClient
5050
from pyatlan.client.impersonate import ImpersonationClient
51+
from pyatlan.client.oauth import OAuthTokenManager
5152
from pyatlan.client.open_lineage import OpenLineageClient
5253
from pyatlan.client.query import QueryClient
5354
from pyatlan.client.role import RoleClient
@@ -177,12 +178,21 @@ def __init__(self, **data):
177178
super().__init__(**data)
178179

179180
if self.oauth_client_id and self.oauth_client_secret and self.api_key is None:
180-
from pyatlan.client.oauth import OAuthTokenManager
181+
LOGGER.debug("API KEY not provided. Using OAuth flow for authentication")
181182

183+
final_base_url = self.base_url or os.environ.get(
184+
"ATLAN_BASE_URL", "INTERNAL"
185+
)
186+
final_oauth_client_id = self.oauth_client_id or os.environ.get(
187+
"ATLAN_OAUTH_CLIENT_ID"
188+
)
189+
final_oauth_client_secret = self.oauth_client_secret or os.environ.get(
190+
"ATLAN_OAUTH_CLIENT_SECRET"
191+
)
182192
self._oauth_token_manager = OAuthTokenManager(
183-
base_url=str(self.base_url),
184-
client_id=self.oauth_client_id,
185-
client_secret=self.oauth_client_secret,
193+
base_url=final_base_url,
194+
client_id=final_oauth_client_id,
195+
client_secret=final_oauth_client_secret,
186196
)
187197
self._request_params = {"headers": {}}
188198
else:

pyatlan/client/constants.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,14 @@
8888
GET_WHOAMI_USER = API(
8989
WHOAMI_API, HTTPMethod.GET, HTTPStatus.OK, endpoint=EndPoint.HERACLES
9090
)
91+
92+
# oauth client authentinatication
93+
GET_OAUTH_CLIENT = API(
94+
"oauth-clients/token",
95+
HTTPMethod.POST,
96+
HTTPStatus.OK,
97+
endpoint=EndPoint.HERACLES,
98+
)
9199
# SQL parsing APIs
92100
PARSE_QUERY = API(
93101
f"{QUERY_API}/parse", HTTPMethod.POST, HTTPStatus.OK, endpoint=EndPoint.HEKA

pyatlan/client/oauth.py

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
import httpx
88
from authlib.oauth2.rfc6749 import OAuth2Token
99

10+
from pyatlan.client.constants import GET_OAUTH_CLIENT
11+
from pyatlan.utils import API
12+
1013

1114
class OAuthTokenManager:
1215
def __init__(
@@ -16,10 +19,10 @@ def __init__(
1619
client_secret: str,
1720
http_client: Optional[httpx.Client] = None,
1821
):
19-
self.base_url = base_url.rstrip("/")
22+
self.base_url = base_url
2023
self.client_id = client_id
2124
self.client_secret = client_secret
22-
self.token_url = f"{self.base_url}/api/service/oauth-clients/token"
25+
self.token_url = self._create_path(GET_OAUTH_CLIENT)
2326
self._lock = threading.Lock()
2427
self._http_client = http_client or httpx.Client(timeout=30.0)
2528
self._token: Optional[OAuth2Token] = None
@@ -28,7 +31,7 @@ def __init__(
2831
def get_token(self) -> str:
2932
with self._lock:
3033
if self._token and not self._token.is_expired():
31-
return self._token["access_token"]
34+
return str(self._token["access_token"])
3235

3336
response = self._http_client.post(
3437
self.token_url,
@@ -67,6 +70,16 @@ def invalidate_token(self):
6770
with self._lock:
6871
self._token = None
6972

73+
def _create_path(self, api: API):
74+
from urllib.parse import urljoin
75+
76+
if self.base_url == "INTERNAL":
77+
base_with_prefix = urljoin(api.endpoint.service, api.endpoint.prefix)
78+
return urljoin(base_with_prefix, api.path)
79+
else:
80+
base_with_prefix = urljoin(self.base_url, api.endpoint.prefix)
81+
return urljoin(base_with_prefix, api.path)
82+
7083
def close(self):
7184
if self._owns_client:
7285
self._http_client.close()

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ dev = [
5151
"mypy~=1.18.0",
5252
"ruff~=0.14.0",
5353
"types-setuptools~=80.9.0.20250822",
54+
"types-Authlib",
5455
"pytest~=8.4.2",
5556
"pytest-vcr~=1.0.2",
5657
"vcrpy~=7.0.0",

uv.lock

Lines changed: 14 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)