From aa4f32e311eff38e9ef7361d4edc87ec0dc2331f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 12 Dec 2025 22:33:03 +0000 Subject: [PATCH 1/4] Initial plan From 76400c2efc8c96c39e05d67a14d042cc45c0f340 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 12 Dec 2025 22:38:08 +0000 Subject: [PATCH 2/4] Add async get_raw_access_token() method to AsyncPipedream for non-blocking OAuth token fetching Co-authored-by: jverce <5479513+jverce@users.noreply.github.com> --- src/pipedream/core/client_wrapper.py | 5 ++++ src/pipedream/pipedream.py | 15 +++++++++- tests/custom/test_client.py | 42 ++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 1 deletion(-) diff --git a/src/pipedream/core/client_wrapper.py b/src/pipedream/core/client_wrapper.py index e76f5e3..a0f922d 100644 --- a/src/pipedream/core/client_wrapper.py +++ b/src/pipedream/core/client_wrapper.py @@ -120,3 +120,8 @@ async def async_get_headers(self) -> typing.Dict[str, str]: token = await self._async_token() headers["Authorization"] = f"Bearer {token}" return headers + + async def _async_get_token(self) -> typing.Optional[str]: + if self._async_token is not None: + return await self._async_token() + return self._get_token() diff --git a/src/pipedream/pipedream.py b/src/pipedream/pipedream.py index 327b9ea..90a2ed1 100644 --- a/src/pipedream/pipedream.py +++ b/src/pipedream/pipedream.py @@ -110,10 +110,23 @@ def __init__( @property def raw_access_token(self) -> Optional[str]: """ - Returns an access token that can be used to authenticate API requests + Returns an access token that can be used to authenticate API requests. + + Note: When using OAuth authentication (client_id/client_secret), this property + may perform blocking network operations. For async applications, prefer using + the async method `get_raw_access_token()` instead. """ return self._client_wrapper._get_token() + async def get_raw_access_token(self) -> Optional[str]: + """ + Asynchronously returns an access token that can be used to authenticate API requests. + + This method is non-blocking and safe to use in async contexts such as FastAPI, + Django ASGI, or any other asyncio-based application. + """ + return await self._client_wrapper._async_get_token() + def _get_base_url(environment: PipedreamEnvironment) -> str: """ diff --git a/tests/custom/test_client.py b/tests/custom/test_client.py index ab04ce6..5b9afed 100644 --- a/tests/custom/test_client.py +++ b/tests/custom/test_client.py @@ -1,7 +1,49 @@ +from unittest.mock import AsyncMock + import pytest +from pipedream import AsyncPipedream, Pipedream + # Get started with writing tests with pytest at https://docs.pytest.org @pytest.mark.skip(reason="Unimplemented") def test_client() -> None: assert True + + +def test_sync_pipedream_raw_access_token() -> None: + """Test synchronous Pipedream client raw_access_token property.""" + client = Pipedream(access_token="test-token", project_id="test-project") + assert client.raw_access_token == "test-token" + + +def test_async_pipedream_raw_access_token() -> None: + """Test AsyncPipedream client raw_access_token property with access_token.""" + client = AsyncPipedream(access_token="test-token", project_id="test-project") + assert client.raw_access_token == "test-token" + + +async def test_async_pipedream_get_raw_access_token() -> None: + """Test AsyncPipedream async method get_raw_access_token() with access_token.""" + client = AsyncPipedream(access_token="test-token", project_id="test-project") + token = await client.get_raw_access_token() + assert token == "test-token" + + +async def test_async_pipedream_get_raw_access_token_with_oauth() -> None: + """Test AsyncPipedream async method with OAuth flow.""" + client = AsyncPipedream( + client_id="test-client-id", + client_secret="test-client-secret", + project_id="test-project", + ) + + # The client should have _async_token set when using OAuth + assert client._client_wrapper._async_token is not None + + # Mock the async token provider + client._client_wrapper._async_token = AsyncMock(return_value="mocked-oauth-token") + + # Test the async method + token = await client.get_raw_access_token() + assert token == "mocked-oauth-token" From 29355bb3033caff27a104a3cc2bd33ac7e7396a3 Mon Sep 17 00:00:00 2001 From: Jay Vercellone Date: Fri, 12 Dec 2025 19:58:32 -0300 Subject: [PATCH 3/4] Avoid changes in core module --- src/pipedream/core/client_wrapper.py | 5 ----- src/pipedream/pipedream.py | 21 +++++++++++++-------- tests/custom/test_client.py | 10 +++++----- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/pipedream/core/client_wrapper.py b/src/pipedream/core/client_wrapper.py index a0f922d..e76f5e3 100644 --- a/src/pipedream/core/client_wrapper.py +++ b/src/pipedream/core/client_wrapper.py @@ -120,8 +120,3 @@ async def async_get_headers(self) -> typing.Dict[str, str]: token = await self._async_token() headers["Authorization"] = f"Bearer {token}" return headers - - async def _async_get_token(self) -> typing.Optional[str]: - if self._async_token is not None: - return await self._async_token() - return self._get_token() diff --git a/src/pipedream/pipedream.py b/src/pipedream/pipedream.py index 90a2ed1..b1d86c9 100644 --- a/src/pipedream/pipedream.py +++ b/src/pipedream/pipedream.py @@ -112,20 +112,25 @@ def raw_access_token(self) -> Optional[str]: """ Returns an access token that can be used to authenticate API requests. - Note: When using OAuth authentication (client_id/client_secret), this property - may perform blocking network operations. For async applications, prefer using - the async method `get_raw_access_token()` instead. + Note: When using OAuth authentication (`client_id`/`client_secret`), + this property may perform blocking network operations. For async + applications, prefer using the async property `async_raw_access_token` + instead. """ return self._client_wrapper._get_token() - async def get_raw_access_token(self) -> Optional[str]: + @property + async def async_raw_access_token(self) -> Optional[str]: """ - Asynchronously returns an access token that can be used to authenticate API requests. + Asynchronously returns an access token that can be used to authenticate + API requests. - This method is non-blocking and safe to use in async contexts such as FastAPI, - Django ASGI, or any other asyncio-based application. + This method is non-blocking and safe to use in async contexts such as + FastAPI, Django ASGI, or any other asyncio-based application. """ - return await self._client_wrapper._async_get_token() + if self._client_wrapper._async_token is not None: + return await self._client_wrapper._async_token() + return self.raw_access_token def _get_base_url(environment: PipedreamEnvironment) -> str: diff --git a/tests/custom/test_client.py b/tests/custom/test_client.py index 5b9afed..56f588a 100644 --- a/tests/custom/test_client.py +++ b/tests/custom/test_client.py @@ -23,14 +23,14 @@ def test_async_pipedream_raw_access_token() -> None: assert client.raw_access_token == "test-token" -async def test_async_pipedream_get_raw_access_token() -> None: - """Test AsyncPipedream async method get_raw_access_token() with access_token.""" +async def test_async_pipedream_async_raw_access_token() -> None: + """Test AsyncPipedream async method async_raw_access_token() with access_token.""" client = AsyncPipedream(access_token="test-token", project_id="test-project") - token = await client.get_raw_access_token() + token = await client.async_raw_access_token assert token == "test-token" -async def test_async_pipedream_get_raw_access_token_with_oauth() -> None: +async def test_async_pipedream_async_raw_access_token_with_oauth() -> None: """Test AsyncPipedream async method with OAuth flow.""" client = AsyncPipedream( client_id="test-client-id", @@ -45,5 +45,5 @@ async def test_async_pipedream_get_raw_access_token_with_oauth() -> None: client._client_wrapper._async_token = AsyncMock(return_value="mocked-oauth-token") # Test the async method - token = await client.get_raw_access_token() + token = await client.async_raw_access_token assert token == "mocked-oauth-token" From 3fb7102e54206381e60a4b9010083d97b65e1eb5 Mon Sep 17 00:00:00 2001 From: Jay Vercellone Date: Fri, 12 Dec 2025 20:05:01 -0300 Subject: [PATCH 4/4] CodeRabbit feedback --- tests/custom/test_client.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/custom/test_client.py b/tests/custom/test_client.py index 56f588a..01c560a 100644 --- a/tests/custom/test_client.py +++ b/tests/custom/test_client.py @@ -38,9 +38,6 @@ async def test_async_pipedream_async_raw_access_token_with_oauth() -> None: project_id="test-project", ) - # The client should have _async_token set when using OAuth - assert client._client_wrapper._async_token is not None - # Mock the async token provider client._client_wrapper._async_token = AsyncMock(return_value="mocked-oauth-token")