diff --git a/README.md b/README.md index ea4d0a3..4db038a 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,21 @@ The Pipedream Python library provides convenient access to the Pipedream APIs from Python. +## Table of Contents + +- [Installation](#installation) +- [Reference](#reference) +- [Usage](#usage) +- [Async Client](#async-client) +- [Exception Handling](#exception-handling) +- [Pagination](#pagination) +- [Advanced](#advanced) + - [Access Raw Response Data](#access-raw-response-data) + - [Retries](#retries) + - [Timeouts](#timeouts) + - [Custom Client](#custom-client) +- [Contributing](#contributing) + ## Installation ```sh @@ -89,14 +104,7 @@ client = Pipedream( client_id="YOUR_CLIENT_ID", client_secret="YOUR_CLIENT_SECRET", ) -response = client.apps.list( - after="after", - before="before", - limit=1, - q="q", - sort_key="name", - sort_direction="asc", -) +response = client.apps.list() for item in response: yield item # alternatively, you can paginate page-by-page diff --git a/poetry.lock b/poetry.lock index fef3795..a19d7e2 100644 --- a/poetry.lock +++ b/poetry.lock @@ -38,13 +38,13 @@ trio = ["trio (>=0.26.1)"] [[package]] name = "certifi" -version = "2025.10.5" +version = "2025.11.12" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.7" files = [ - {file = "certifi-2025.10.5-py3-none-any.whl", hash = "sha256:0f212c2744a9bb6de0c56639a6f68afe01ecd92d91f14ae897c4fe7bbeeef0de"}, - {file = "certifi-2025.10.5.tar.gz", hash = "sha256:47c09d31ccf2acf0be3f701ea53595ee7e0b8fa08801c6624be771df09ae7b43"}, + {file = "certifi-2025.11.12-py3-none-any.whl", hash = "sha256:97de8790030bbd5c2d96b7ec782fc2f7820ef8dba6db909ccf95449f2d062d4b"}, + {file = "certifi-2025.11.12.tar.gz", hash = "sha256:d8ab5478f2ecd78af242878415affce761ca6bc54a22a27e026d7c25357c3316"}, ] [[package]] @@ -60,13 +60,13 @@ files = [ [[package]] name = "exceptiongroup" -version = "1.3.0" +version = "1.3.1" description = "Backport of PEP 654 (exception groups)" optional = false python-versions = ">=3.7" files = [ - {file = "exceptiongroup-1.3.0-py3-none-any.whl", hash = "sha256:4d111e6e0c13d0644cad6ddaa7ed0261a0b36971f6d23e7ec9b4b9097da78a10"}, - {file = "exceptiongroup-1.3.0.tar.gz", hash = "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88"}, + {file = "exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598"}, + {file = "exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219"}, ] [package.dependencies] diff --git a/pyproject.toml b/pyproject.toml index c93c57d..2af2770 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,7 +3,7 @@ name = "pipedream" [tool.poetry] name = "pipedream" -version = "1.0.11" +version = "1.0.12" description = "" readme = "README.md" authors = [] diff --git a/src/pipedream/accounts/client.py b/src/pipedream/accounts/client.py index 84f3fdf..4c97f9d 100644 --- a/src/pipedream/accounts/client.py +++ b/src/pipedream/accounts/client.py @@ -82,15 +82,7 @@ def list( client_id="YOUR_CLIENT_ID", client_secret="YOUR_CLIENT_SECRET", ) - response = client.accounts.list( - external_user_id="external_user_id", - oauth_app_id="oauth_app_id", - after="after", - before="before", - limit=1, - app="app", - include_credentials=True, - ) + response = client.accounts.list() for item in response: yield item # alternatively, you can paginate page-by-page @@ -160,8 +152,6 @@ def create( client_secret="YOUR_CLIENT_SECRET", ) client.accounts.create( - external_user_id="external_user_id", - oauth_app_id="oauth_app_id", app_slug="app_slug", cfmap_json="cfmap_json", connect_token="connect_token", @@ -215,7 +205,6 @@ def retrieve( ) client.accounts.retrieve( account_id="account_id", - include_credentials=True, ) """ _response = self._raw_client.retrieve( @@ -363,15 +352,7 @@ async def list( async def main() -> None: - response = await client.accounts.list( - external_user_id="external_user_id", - oauth_app_id="oauth_app_id", - after="after", - before="before", - limit=1, - app="app", - include_credentials=True, - ) + response = await client.accounts.list() async for item in response: yield item @@ -450,8 +431,6 @@ async def create( async def main() -> None: await client.accounts.create( - external_user_id="external_user_id", - oauth_app_id="oauth_app_id", app_slug="app_slug", cfmap_json="cfmap_json", connect_token="connect_token", @@ -513,7 +492,6 @@ async def retrieve( async def main() -> None: await client.accounts.retrieve( account_id="account_id", - include_credentials=True, ) diff --git a/src/pipedream/actions/__init__.py b/src/pipedream/actions/__init__.py index 5cde020..cb410bc 100644 --- a/src/pipedream/actions/__init__.py +++ b/src/pipedream/actions/__init__.py @@ -2,3 +2,33 @@ # isort: skip_file +import typing +from importlib import import_module + +if typing.TYPE_CHECKING: + from .types import ListActionsRequestRegistry +_dynamic_imports: typing.Dict[str, str] = {"ListActionsRequestRegistry": ".types"} + + +def __getattr__(attr_name: str) -> typing.Any: + module_name = _dynamic_imports.get(attr_name) + if module_name is None: + raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") + try: + module = import_module(module_name, __package__) + if module_name == f".{attr_name}": + return module + else: + return getattr(module, attr_name) + except ImportError as e: + raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e + except AttributeError as e: + raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e + + +def __dir__(): + lazy_attrs = list(_dynamic_imports.keys()) + return sorted(lazy_attrs) + + +__all__ = ["ListActionsRequestRegistry"] diff --git a/src/pipedream/actions/client.py b/src/pipedream/actions/client.py index cebb494..e37449a 100644 --- a/src/pipedream/actions/client.py +++ b/src/pipedream/actions/client.py @@ -12,6 +12,7 @@ from ..types.run_action_opts_stash_id import RunActionOptsStashId from ..types.run_action_response import RunActionResponse from .raw_client import AsyncRawActionsClient, RawActionsClient +from .types.list_actions_request_registry import ListActionsRequestRegistry # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -40,6 +41,7 @@ def list( limit: typing.Optional[int] = None, q: typing.Optional[str] = None, app: typing.Optional[str] = None, + registry: typing.Optional[ListActionsRequestRegistry] = None, request_options: typing.Optional[RequestOptions] = None, ) -> SyncPager[Component]: """ @@ -62,13 +64,16 @@ def list( app : typing.Optional[str] The ID or name slug of the app to filter the actions + registry : typing.Optional[ListActionsRequestRegistry] + The registry to retrieve actions from. Defaults to 'all' ('public', 'private', or 'all') + request_options : typing.Optional[RequestOptions] Request-specific configuration. Returns ------- SyncPager[Component] - actions listed + behaves like registry=all Examples -------- @@ -80,13 +85,7 @@ def list( client_id="YOUR_CLIENT_ID", client_secret="YOUR_CLIENT_SECRET", ) - response = client.actions.list( - after="after", - before="before", - limit=1, - q="q", - app="app", - ) + response = client.actions.list() for item in response: yield item # alternatively, you can paginate page-by-page @@ -94,7 +93,7 @@ def list( yield page """ return self._raw_client.list( - after=after, before=before, limit=limit, q=q, app=app, request_options=request_options + after=after, before=before, limit=limit, q=q, app=app, registry=registry, request_options=request_options ) def retrieve( @@ -386,6 +385,7 @@ async def list( limit: typing.Optional[int] = None, q: typing.Optional[str] = None, app: typing.Optional[str] = None, + registry: typing.Optional[ListActionsRequestRegistry] = None, request_options: typing.Optional[RequestOptions] = None, ) -> AsyncPager[Component]: """ @@ -408,13 +408,16 @@ async def list( app : typing.Optional[str] The ID or name slug of the app to filter the actions + registry : typing.Optional[ListActionsRequestRegistry] + The registry to retrieve actions from. Defaults to 'all' ('public', 'private', or 'all') + request_options : typing.Optional[RequestOptions] Request-specific configuration. Returns ------- AsyncPager[Component] - actions listed + behaves like registry=all Examples -------- @@ -431,13 +434,7 @@ async def list( async def main() -> None: - response = await client.actions.list( - after="after", - before="before", - limit=1, - q="q", - app="app", - ) + response = await client.actions.list() async for item in response: yield item @@ -449,7 +446,7 @@ async def main() -> None: asyncio.run(main()) """ return await self._raw_client.list( - after=after, before=before, limit=limit, q=q, app=app, request_options=request_options + after=after, before=before, limit=limit, q=q, app=app, registry=registry, request_options=request_options ) async def retrieve( diff --git a/src/pipedream/actions/raw_client.py b/src/pipedream/actions/raw_client.py index 1637a43..3db4688 100644 --- a/src/pipedream/actions/raw_client.py +++ b/src/pipedream/actions/raw_client.py @@ -11,15 +11,18 @@ from ..core.pydantic_utilities import parse_obj_as from ..core.request_options import RequestOptions from ..core.serialization import convert_and_respect_annotation_metadata +from ..errors.bad_request_error import BadRequestError from ..errors.too_many_requests_error import TooManyRequestsError from ..types.component import Component from ..types.configure_prop_response import ConfigurePropResponse from ..types.configured_props import ConfiguredProps +from ..types.error_response import ErrorResponse from ..types.get_component_response import GetComponentResponse from ..types.get_components_response import GetComponentsResponse from ..types.reload_props_response import ReloadPropsResponse from ..types.run_action_opts_stash_id import RunActionOptsStashId from ..types.run_action_response import RunActionResponse +from .types.list_actions_request_registry import ListActionsRequestRegistry # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -37,6 +40,7 @@ def list( limit: typing.Optional[int] = None, q: typing.Optional[str] = None, app: typing.Optional[str] = None, + registry: typing.Optional[ListActionsRequestRegistry] = None, request_options: typing.Optional[RequestOptions] = None, ) -> SyncPager[Component]: """ @@ -59,13 +63,16 @@ def list( app : typing.Optional[str] The ID or name slug of the app to filter the actions + registry : typing.Optional[ListActionsRequestRegistry] + The registry to retrieve actions from. Defaults to 'all' ('public', 'private', or 'all') + request_options : typing.Optional[RequestOptions] Request-specific configuration. Returns ------- SyncPager[Component] - actions listed + behaves like registry=all """ _response = self._client_wrapper.httpx_client.request( f"v1/connect/{jsonable_encoder(self._client_wrapper._project_id)}/actions", @@ -76,6 +83,7 @@ def list( "limit": limit, "q": q, "app": app, + "registry": registry, }, request_options=request_options, ) @@ -100,11 +108,23 @@ def list( limit=limit, q=q, app=app, + registry=registry, request_options=request_options, ) return SyncPager( has_next=_has_next, items=_items, get_next=_get_next, response=BaseHttpResponse(response=_response) ) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + ErrorResponse, + parse_obj_as( + type_=ErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 429: raise TooManyRequestsError( headers=dict(_response.headers), @@ -426,7 +446,7 @@ def run( ), "dynamic_props_id": dynamic_props_id, "stash_id": convert_and_respect_annotation_metadata( - object_=stash_id, annotation=RunActionOptsStashId, direction="write" + object_=stash_id, annotation=typing.Optional[RunActionOptsStashId], direction="write" ), }, headers={ @@ -474,6 +494,7 @@ async def list( limit: typing.Optional[int] = None, q: typing.Optional[str] = None, app: typing.Optional[str] = None, + registry: typing.Optional[ListActionsRequestRegistry] = None, request_options: typing.Optional[RequestOptions] = None, ) -> AsyncPager[Component]: """ @@ -496,13 +517,16 @@ async def list( app : typing.Optional[str] The ID or name slug of the app to filter the actions + registry : typing.Optional[ListActionsRequestRegistry] + The registry to retrieve actions from. Defaults to 'all' ('public', 'private', or 'all') + request_options : typing.Optional[RequestOptions] Request-specific configuration. Returns ------- AsyncPager[Component] - actions listed + behaves like registry=all """ _response = await self._client_wrapper.httpx_client.request( f"v1/connect/{jsonable_encoder(self._client_wrapper._project_id)}/actions", @@ -513,6 +537,7 @@ async def list( "limit": limit, "q": q, "app": app, + "registry": registry, }, request_options=request_options, ) @@ -539,12 +564,24 @@ async def _get_next(): limit=limit, q=q, app=app, + registry=registry, request_options=request_options, ) return AsyncPager( has_next=_has_next, items=_items, get_next=_get_next, response=BaseHttpResponse(response=_response) ) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + ErrorResponse, + parse_obj_as( + type_=ErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 429: raise TooManyRequestsError( headers=dict(_response.headers), @@ -866,7 +903,7 @@ async def run( ), "dynamic_props_id": dynamic_props_id, "stash_id": convert_and_respect_annotation_metadata( - object_=stash_id, annotation=RunActionOptsStashId, direction="write" + object_=stash_id, annotation=typing.Optional[RunActionOptsStashId], direction="write" ), }, headers={ diff --git a/src/pipedream/actions/types/__init__.py b/src/pipedream/actions/types/__init__.py new file mode 100644 index 0000000..87d460d --- /dev/null +++ b/src/pipedream/actions/types/__init__.py @@ -0,0 +1,34 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +import typing +from importlib import import_module + +if typing.TYPE_CHECKING: + from .list_actions_request_registry import ListActionsRequestRegistry +_dynamic_imports: typing.Dict[str, str] = {"ListActionsRequestRegistry": ".list_actions_request_registry"} + + +def __getattr__(attr_name: str) -> typing.Any: + module_name = _dynamic_imports.get(attr_name) + if module_name is None: + raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") + try: + module = import_module(module_name, __package__) + if module_name == f".{attr_name}": + return module + else: + return getattr(module, attr_name) + except ImportError as e: + raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e + except AttributeError as e: + raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e + + +def __dir__(): + lazy_attrs = list(_dynamic_imports.keys()) + return sorted(lazy_attrs) + + +__all__ = ["ListActionsRequestRegistry"] diff --git a/src/pipedream/actions/types/list_actions_request_registry.py b/src/pipedream/actions/types/list_actions_request_registry.py new file mode 100644 index 0000000..6a8673d --- /dev/null +++ b/src/pipedream/actions/types/list_actions_request_registry.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +ListActionsRequestRegistry = typing.Union[typing.Literal["public", "private", "all"], typing.Any] diff --git a/src/pipedream/apps/__init__.py b/src/pipedream/apps/__init__.py index 3a7655e..4074914 100644 --- a/src/pipedream/apps/__init__.py +++ b/src/pipedream/apps/__init__.py @@ -6,8 +6,8 @@ from importlib import import_module if typing.TYPE_CHECKING: - from .types import AppsListRequestSortDirection, AppsListRequestSortKey -_dynamic_imports: typing.Dict[str, str] = {"AppsListRequestSortDirection": ".types", "AppsListRequestSortKey": ".types"} + from .types import ListAppsRequestSortDirection, ListAppsRequestSortKey +_dynamic_imports: typing.Dict[str, str] = {"ListAppsRequestSortDirection": ".types", "ListAppsRequestSortKey": ".types"} def __getattr__(attr_name: str) -> typing.Any: @@ -31,4 +31,4 @@ def __dir__(): return sorted(lazy_attrs) -__all__ = ["AppsListRequestSortDirection", "AppsListRequestSortKey"] +__all__ = ["ListAppsRequestSortDirection", "ListAppsRequestSortKey"] diff --git a/src/pipedream/apps/client.py b/src/pipedream/apps/client.py index 512d8df..28ab702 100644 --- a/src/pipedream/apps/client.py +++ b/src/pipedream/apps/client.py @@ -8,8 +8,8 @@ from ..types.app import App from ..types.get_app_response import GetAppResponse from .raw_client import AsyncRawAppsClient, RawAppsClient -from .types.apps_list_request_sort_direction import AppsListRequestSortDirection -from .types.apps_list_request_sort_key import AppsListRequestSortKey +from .types.list_apps_request_sort_direction import ListAppsRequestSortDirection +from .types.list_apps_request_sort_key import ListAppsRequestSortKey class AppsClient: @@ -34,8 +34,8 @@ def list( before: typing.Optional[str] = None, limit: typing.Optional[int] = None, q: typing.Optional[str] = None, - sort_key: typing.Optional[AppsListRequestSortKey] = None, - sort_direction: typing.Optional[AppsListRequestSortDirection] = None, + sort_key: typing.Optional[ListAppsRequestSortKey] = None, + sort_direction: typing.Optional[ListAppsRequestSortDirection] = None, category_ids: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None, request_options: typing.Optional[RequestOptions] = None, ) -> SyncPager[App]: @@ -56,10 +56,10 @@ def list( q : typing.Optional[str] A search query to filter the apps - sort_key : typing.Optional[AppsListRequestSortKey] + sort_key : typing.Optional[ListAppsRequestSortKey] The key to sort the apps by - sort_direction : typing.Optional[AppsListRequestSortDirection] + sort_direction : typing.Optional[ListAppsRequestSortDirection] The direction to sort the apps category_ids : typing.Optional[typing.Union[str, typing.Sequence[str]]] @@ -83,14 +83,7 @@ def list( client_id="YOUR_CLIENT_ID", client_secret="YOUR_CLIENT_SECRET", ) - response = client.apps.list( - after="after", - before="before", - limit=1, - q="q", - sort_key="name", - sort_direction="asc", - ) + response = client.apps.list() for item in response: yield item # alternatively, you can paginate page-by-page @@ -165,8 +158,8 @@ async def list( before: typing.Optional[str] = None, limit: typing.Optional[int] = None, q: typing.Optional[str] = None, - sort_key: typing.Optional[AppsListRequestSortKey] = None, - sort_direction: typing.Optional[AppsListRequestSortDirection] = None, + sort_key: typing.Optional[ListAppsRequestSortKey] = None, + sort_direction: typing.Optional[ListAppsRequestSortDirection] = None, category_ids: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None, request_options: typing.Optional[RequestOptions] = None, ) -> AsyncPager[App]: @@ -187,10 +180,10 @@ async def list( q : typing.Optional[str] A search query to filter the apps - sort_key : typing.Optional[AppsListRequestSortKey] + sort_key : typing.Optional[ListAppsRequestSortKey] The key to sort the apps by - sort_direction : typing.Optional[AppsListRequestSortDirection] + sort_direction : typing.Optional[ListAppsRequestSortDirection] The direction to sort the apps category_ids : typing.Optional[typing.Union[str, typing.Sequence[str]]] @@ -219,14 +212,7 @@ async def list( async def main() -> None: - response = await client.apps.list( - after="after", - before="before", - limit=1, - q="q", - sort_key="name", - sort_direction="asc", - ) + response = await client.apps.list() async for item in response: yield item diff --git a/src/pipedream/apps/raw_client.py b/src/pipedream/apps/raw_client.py index 3bf84a7..c127e01 100644 --- a/src/pipedream/apps/raw_client.py +++ b/src/pipedream/apps/raw_client.py @@ -13,8 +13,8 @@ from ..types.app import App from ..types.get_app_response import GetAppResponse from ..types.list_apps_response import ListAppsResponse -from .types.apps_list_request_sort_direction import AppsListRequestSortDirection -from .types.apps_list_request_sort_key import AppsListRequestSortKey +from .types.list_apps_request_sort_direction import ListAppsRequestSortDirection +from .types.list_apps_request_sort_key import ListAppsRequestSortKey class RawAppsClient: @@ -28,8 +28,8 @@ def list( before: typing.Optional[str] = None, limit: typing.Optional[int] = None, q: typing.Optional[str] = None, - sort_key: typing.Optional[AppsListRequestSortKey] = None, - sort_direction: typing.Optional[AppsListRequestSortDirection] = None, + sort_key: typing.Optional[ListAppsRequestSortKey] = None, + sort_direction: typing.Optional[ListAppsRequestSortDirection] = None, category_ids: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None, request_options: typing.Optional[RequestOptions] = None, ) -> SyncPager[App]: @@ -50,10 +50,10 @@ def list( q : typing.Optional[str] A search query to filter the apps - sort_key : typing.Optional[AppsListRequestSortKey] + sort_key : typing.Optional[ListAppsRequestSortKey] The key to sort the apps by - sort_direction : typing.Optional[AppsListRequestSortDirection] + sort_direction : typing.Optional[ListAppsRequestSortDirection] The direction to sort the apps category_ids : typing.Optional[typing.Union[str, typing.Sequence[str]]] @@ -165,8 +165,8 @@ async def list( before: typing.Optional[str] = None, limit: typing.Optional[int] = None, q: typing.Optional[str] = None, - sort_key: typing.Optional[AppsListRequestSortKey] = None, - sort_direction: typing.Optional[AppsListRequestSortDirection] = None, + sort_key: typing.Optional[ListAppsRequestSortKey] = None, + sort_direction: typing.Optional[ListAppsRequestSortDirection] = None, category_ids: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None, request_options: typing.Optional[RequestOptions] = None, ) -> AsyncPager[App]: @@ -187,10 +187,10 @@ async def list( q : typing.Optional[str] A search query to filter the apps - sort_key : typing.Optional[AppsListRequestSortKey] + sort_key : typing.Optional[ListAppsRequestSortKey] The key to sort the apps by - sort_direction : typing.Optional[AppsListRequestSortDirection] + sort_direction : typing.Optional[ListAppsRequestSortDirection] The direction to sort the apps category_ids : typing.Optional[typing.Union[str, typing.Sequence[str]]] diff --git a/src/pipedream/apps/types/__init__.py b/src/pipedream/apps/types/__init__.py index 08c3a02..526f29a 100644 --- a/src/pipedream/apps/types/__init__.py +++ b/src/pipedream/apps/types/__init__.py @@ -6,11 +6,11 @@ from importlib import import_module if typing.TYPE_CHECKING: - from .apps_list_request_sort_direction import AppsListRequestSortDirection - from .apps_list_request_sort_key import AppsListRequestSortKey + from .list_apps_request_sort_direction import ListAppsRequestSortDirection + from .list_apps_request_sort_key import ListAppsRequestSortKey _dynamic_imports: typing.Dict[str, str] = { - "AppsListRequestSortDirection": ".apps_list_request_sort_direction", - "AppsListRequestSortKey": ".apps_list_request_sort_key", + "ListAppsRequestSortDirection": ".list_apps_request_sort_direction", + "ListAppsRequestSortKey": ".list_apps_request_sort_key", } @@ -35,4 +35,4 @@ def __dir__(): return sorted(lazy_attrs) -__all__ = ["AppsListRequestSortDirection", "AppsListRequestSortKey"] +__all__ = ["ListAppsRequestSortDirection", "ListAppsRequestSortKey"] diff --git a/src/pipedream/apps/types/apps_list_request_sort_direction.py b/src/pipedream/apps/types/list_apps_request_sort_direction.py similarity index 61% rename from src/pipedream/apps/types/apps_list_request_sort_direction.py rename to src/pipedream/apps/types/list_apps_request_sort_direction.py index d841cc9..4d86906 100644 --- a/src/pipedream/apps/types/apps_list_request_sort_direction.py +++ b/src/pipedream/apps/types/list_apps_request_sort_direction.py @@ -2,4 +2,4 @@ import typing -AppsListRequestSortDirection = typing.Union[typing.Literal["asc", "desc"], typing.Any] +ListAppsRequestSortDirection = typing.Union[typing.Literal["asc", "desc"], typing.Any] diff --git a/src/pipedream/apps/types/apps_list_request_sort_key.py b/src/pipedream/apps/types/list_apps_request_sort_key.py similarity index 65% rename from src/pipedream/apps/types/apps_list_request_sort_key.py rename to src/pipedream/apps/types/list_apps_request_sort_key.py index ab4065d..6e9b8e2 100644 --- a/src/pipedream/apps/types/apps_list_request_sort_key.py +++ b/src/pipedream/apps/types/list_apps_request_sort_key.py @@ -2,4 +2,4 @@ import typing -AppsListRequestSortKey = typing.Union[typing.Literal["name", "name_slug", "featured_weight"], typing.Any] +ListAppsRequestSortKey = typing.Union[typing.Literal["name", "name_slug", "featured_weight"], typing.Any] diff --git a/src/pipedream/client.py b/src/pipedream/client.py index 6f4accc..cfb7782 100644 --- a/src/pipedream/client.py +++ b/src/pipedream/client.py @@ -6,7 +6,7 @@ import typing import httpx -from .types.project_environment import ProjectEnvironment +from ._.types.project_environment import ProjectEnvironment from .core.api_error import ApiError from .core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from .core.oauth_token_provider import OAuthTokenProvider diff --git a/src/pipedream/components/__init__.py b/src/pipedream/components/__init__.py index 5cde020..609af6c 100644 --- a/src/pipedream/components/__init__.py +++ b/src/pipedream/components/__init__.py @@ -2,3 +2,33 @@ # isort: skip_file +import typing +from importlib import import_module + +if typing.TYPE_CHECKING: + from .types import ListComponentsRequestRegistry +_dynamic_imports: typing.Dict[str, str] = {"ListComponentsRequestRegistry": ".types"} + + +def __getattr__(attr_name: str) -> typing.Any: + module_name = _dynamic_imports.get(attr_name) + if module_name is None: + raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") + try: + module = import_module(module_name, __package__) + if module_name == f".{attr_name}": + return module + else: + return getattr(module, attr_name) + except ImportError as e: + raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e + except AttributeError as e: + raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e + + +def __dir__(): + lazy_attrs = list(_dynamic_imports.keys()) + return sorted(lazy_attrs) + + +__all__ = ["ListComponentsRequestRegistry"] diff --git a/src/pipedream/components/client.py b/src/pipedream/components/client.py index a68c358..accfced 100644 --- a/src/pipedream/components/client.py +++ b/src/pipedream/components/client.py @@ -11,6 +11,7 @@ from ..types.configured_props import ConfiguredProps from ..types.reload_props_response import ReloadPropsResponse from .raw_client import AsyncRawComponentsClient, RawComponentsClient +from .types.list_components_request_registry import ListComponentsRequestRegistry # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -39,6 +40,7 @@ def list( limit: typing.Optional[int] = None, q: typing.Optional[str] = None, app: typing.Optional[str] = None, + registry: typing.Optional[ListComponentsRequestRegistry] = None, component_type: typing.Optional[ComponentType] = None, request_options: typing.Optional[RequestOptions] = None, ) -> SyncPager[Component]: @@ -62,6 +64,9 @@ def list( app : typing.Optional[str] The ID or name slug of the app to filter the components + registry : typing.Optional[ListComponentsRequestRegistry] + The registry to retrieve components from. Defaults to 'all' ('public', 'private', or 'all') + component_type : typing.Optional[ComponentType] The type of the component to filter the components @@ -71,7 +76,7 @@ def list( Returns ------- SyncPager[Component] - components listed + behaves like registry=all Examples -------- @@ -83,14 +88,7 @@ def list( client_id="YOUR_CLIENT_ID", client_secret="YOUR_CLIENT_SECRET", ) - response = client.components.list( - after="after", - before="before", - limit=1, - q="q", - app="app", - component_type="trigger", - ) + response = client.components.list() for item in response: yield item # alternatively, you can paginate page-by-page @@ -103,6 +101,7 @@ def list( limit=limit, q=q, app=app, + registry=registry, component_type=component_type, request_options=request_options, ) @@ -330,6 +329,7 @@ async def list( limit: typing.Optional[int] = None, q: typing.Optional[str] = None, app: typing.Optional[str] = None, + registry: typing.Optional[ListComponentsRequestRegistry] = None, component_type: typing.Optional[ComponentType] = None, request_options: typing.Optional[RequestOptions] = None, ) -> AsyncPager[Component]: @@ -353,6 +353,9 @@ async def list( app : typing.Optional[str] The ID or name slug of the app to filter the components + registry : typing.Optional[ListComponentsRequestRegistry] + The registry to retrieve components from. Defaults to 'all' ('public', 'private', or 'all') + component_type : typing.Optional[ComponentType] The type of the component to filter the components @@ -362,7 +365,7 @@ async def list( Returns ------- AsyncPager[Component] - components listed + behaves like registry=all Examples -------- @@ -379,14 +382,7 @@ async def list( async def main() -> None: - response = await client.components.list( - after="after", - before="before", - limit=1, - q="q", - app="app", - component_type="trigger", - ) + response = await client.components.list() async for item in response: yield item @@ -403,6 +399,7 @@ async def main() -> None: limit=limit, q=q, app=app, + registry=registry, component_type=component_type, request_options=request_options, ) diff --git a/src/pipedream/components/raw_client.py b/src/pipedream/components/raw_client.py index 3453921..d365942 100644 --- a/src/pipedream/components/raw_client.py +++ b/src/pipedream/components/raw_client.py @@ -11,14 +11,17 @@ from ..core.pydantic_utilities import parse_obj_as from ..core.request_options import RequestOptions from ..core.serialization import convert_and_respect_annotation_metadata +from ..errors.bad_request_error import BadRequestError from ..errors.too_many_requests_error import TooManyRequestsError from ..types.component import Component from ..types.component_type import ComponentType from ..types.configure_prop_response import ConfigurePropResponse from ..types.configured_props import ConfiguredProps +from ..types.error_response import ErrorResponse from ..types.get_component_response import GetComponentResponse from ..types.get_components_response import GetComponentsResponse from ..types.reload_props_response import ReloadPropsResponse +from .types.list_components_request_registry import ListComponentsRequestRegistry # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -36,6 +39,7 @@ def list( limit: typing.Optional[int] = None, q: typing.Optional[str] = None, app: typing.Optional[str] = None, + registry: typing.Optional[ListComponentsRequestRegistry] = None, component_type: typing.Optional[ComponentType] = None, request_options: typing.Optional[RequestOptions] = None, ) -> SyncPager[Component]: @@ -59,6 +63,9 @@ def list( app : typing.Optional[str] The ID or name slug of the app to filter the components + registry : typing.Optional[ListComponentsRequestRegistry] + The registry to retrieve components from. Defaults to 'all' ('public', 'private', or 'all') + component_type : typing.Optional[ComponentType] The type of the component to filter the components @@ -68,7 +75,7 @@ def list( Returns ------- SyncPager[Component] - components listed + behaves like registry=all """ _response = self._client_wrapper.httpx_client.request( f"v1/connect/{jsonable_encoder(self._client_wrapper._project_id)}/components", @@ -79,6 +86,7 @@ def list( "limit": limit, "q": q, "app": app, + "registry": registry, "component_type": component_type, }, request_options=request_options, @@ -104,12 +112,24 @@ def list( limit=limit, q=q, app=app, + registry=registry, component_type=component_type, request_options=request_options, ) return SyncPager( has_next=_has_next, items=_items, get_next=_get_next, response=BaseHttpResponse(response=_response) ) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + ErrorResponse, + parse_obj_as( + type_=ErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 429: raise TooManyRequestsError( headers=dict(_response.headers), @@ -392,6 +412,7 @@ async def list( limit: typing.Optional[int] = None, q: typing.Optional[str] = None, app: typing.Optional[str] = None, + registry: typing.Optional[ListComponentsRequestRegistry] = None, component_type: typing.Optional[ComponentType] = None, request_options: typing.Optional[RequestOptions] = None, ) -> AsyncPager[Component]: @@ -415,6 +436,9 @@ async def list( app : typing.Optional[str] The ID or name slug of the app to filter the components + registry : typing.Optional[ListComponentsRequestRegistry] + The registry to retrieve components from. Defaults to 'all' ('public', 'private', or 'all') + component_type : typing.Optional[ComponentType] The type of the component to filter the components @@ -424,7 +448,7 @@ async def list( Returns ------- AsyncPager[Component] - components listed + behaves like registry=all """ _response = await self._client_wrapper.httpx_client.request( f"v1/connect/{jsonable_encoder(self._client_wrapper._project_id)}/components", @@ -435,6 +459,7 @@ async def list( "limit": limit, "q": q, "app": app, + "registry": registry, "component_type": component_type, }, request_options=request_options, @@ -462,6 +487,7 @@ async def _get_next(): limit=limit, q=q, app=app, + registry=registry, component_type=component_type, request_options=request_options, ) @@ -469,6 +495,17 @@ async def _get_next(): return AsyncPager( has_next=_has_next, items=_items, get_next=_get_next, response=BaseHttpResponse(response=_response) ) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + ErrorResponse, + parse_obj_as( + type_=ErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 429: raise TooManyRequestsError( headers=dict(_response.headers), diff --git a/src/pipedream/components/types/__init__.py b/src/pipedream/components/types/__init__.py new file mode 100644 index 0000000..8af9c8e --- /dev/null +++ b/src/pipedream/components/types/__init__.py @@ -0,0 +1,34 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +import typing +from importlib import import_module + +if typing.TYPE_CHECKING: + from .list_components_request_registry import ListComponentsRequestRegistry +_dynamic_imports: typing.Dict[str, str] = {"ListComponentsRequestRegistry": ".list_components_request_registry"} + + +def __getattr__(attr_name: str) -> typing.Any: + module_name = _dynamic_imports.get(attr_name) + if module_name is None: + raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") + try: + module = import_module(module_name, __package__) + if module_name == f".{attr_name}": + return module + else: + return getattr(module, attr_name) + except ImportError as e: + raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e + except AttributeError as e: + raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e + + +def __dir__(): + lazy_attrs = list(_dynamic_imports.keys()) + return sorted(lazy_attrs) + + +__all__ = ["ListComponentsRequestRegistry"] diff --git a/src/pipedream/components/types/list_components_request_registry.py b/src/pipedream/components/types/list_components_request_registry.py new file mode 100644 index 0000000..0a536ba --- /dev/null +++ b/src/pipedream/components/types/list_components_request_registry.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +ListComponentsRequestRegistry = typing.Union[typing.Literal["public", "private", "all"], typing.Any] diff --git a/src/pipedream/core/client_wrapper.py b/src/pipedream/core/client_wrapper.py index d1cbb05..5792b1c 100644 --- a/src/pipedream/core/client_wrapper.py +++ b/src/pipedream/core/client_wrapper.py @@ -3,7 +3,7 @@ import typing import httpx -from ..types.project_environment import ProjectEnvironment +from .._.types.project_environment import ProjectEnvironment from .http_client import AsyncHttpClient, HttpClient @@ -27,10 +27,10 @@ def __init__( def get_headers(self) -> typing.Dict[str, str]: headers: typing.Dict[str, str] = { - "User-Agent": "pipedream/1.0.11", + "User-Agent": "pipedream/1.0.12", "X-Fern-Language": "Python", "X-Fern-SDK-Name": "pipedream", - "X-Fern-SDK-Version": "1.0.11", + "X-Fern-SDK-Version": "1.0.12", **(self.get_custom_headers() or {}), } if self._project_environment is not None: diff --git a/src/pipedream/deployed_triggers/client.py b/src/pipedream/deployed_triggers/client.py index ea92f4e..d7ae086 100644 --- a/src/pipedream/deployed_triggers/client.py +++ b/src/pipedream/deployed_triggers/client.py @@ -81,11 +81,7 @@ def list( client_secret="YOUR_CLIENT_SECRET", ) response = client.deployed_triggers.list( - after="after", - before="before", - limit=1, external_user_id="external_user_id", - emitter_type="email", ) for item in response: yield item @@ -151,6 +147,7 @@ def update( active: typing.Optional[bool] = OMIT, configured_props: typing.Optional[ConfiguredProps] = OMIT, name: typing.Optional[str] = OMIT, + emit_on_deploy: typing.Optional[bool] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> Emitter: """ @@ -171,6 +168,9 @@ def update( name : typing.Optional[str] The name of the trigger + emit_on_deploy : typing.Optional[bool] + Whether the trigger should emit events during deployment + request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -200,6 +200,7 @@ def update( active=active, configured_props=configured_props, name=name, + emit_on_deploy=emit_on_deploy, request_options=request_options, ) return _response.data @@ -245,7 +246,6 @@ def delete( client.deployed_triggers.delete( trigger_id="trigger_id", external_user_id="external_user_id", - ignore_hook_errors=True, ) """ _response = self._raw_client.delete( @@ -298,7 +298,6 @@ def list_events( client.deployed_triggers.list_events( trigger_id="trigger_id", external_user_id="external_user_id", - n=1, ) """ _response = self._raw_client.list_events( @@ -558,11 +557,7 @@ async def list( async def main() -> None: response = await client.deployed_triggers.list( - after="after", - before="before", - limit=1, external_user_id="external_user_id", - emitter_type="email", ) async for item in response: yield item @@ -640,6 +635,7 @@ async def update( active: typing.Optional[bool] = OMIT, configured_props: typing.Optional[ConfiguredProps] = OMIT, name: typing.Optional[str] = OMIT, + emit_on_deploy: typing.Optional[bool] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> Emitter: """ @@ -660,6 +656,9 @@ async def update( name : typing.Optional[str] The name of the trigger + emit_on_deploy : typing.Optional[bool] + Whether the trigger should emit events during deployment + request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -697,6 +696,7 @@ async def main() -> None: active=active, configured_props=configured_props, name=name, + emit_on_deploy=emit_on_deploy, request_options=request_options, ) return _response.data @@ -747,7 +747,6 @@ async def main() -> None: await client.deployed_triggers.delete( trigger_id="trigger_id", external_user_id="external_user_id", - ignore_hook_errors=True, ) @@ -808,7 +807,6 @@ async def main() -> None: await client.deployed_triggers.list_events( trigger_id="trigger_id", external_user_id="external_user_id", - n=1, ) diff --git a/src/pipedream/deployed_triggers/raw_client.py b/src/pipedream/deployed_triggers/raw_client.py index 4b2e576..dab281a 100644 --- a/src/pipedream/deployed_triggers/raw_client.py +++ b/src/pipedream/deployed_triggers/raw_client.py @@ -186,6 +186,7 @@ def update( active: typing.Optional[bool] = OMIT, configured_props: typing.Optional[ConfiguredProps] = OMIT, name: typing.Optional[str] = OMIT, + emit_on_deploy: typing.Optional[bool] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> HttpResponse[Emitter]: """ @@ -206,6 +207,9 @@ def update( name : typing.Optional[str] The name of the trigger + emit_on_deploy : typing.Optional[bool] + Whether the trigger should emit events during deployment + request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -226,6 +230,7 @@ def update( object_=configured_props, annotation=ConfiguredProps, direction="write" ), "name": name, + "emit_on_deploy": emit_on_deploy, }, headers={ "content-type": "application/json", @@ -795,6 +800,7 @@ async def update( active: typing.Optional[bool] = OMIT, configured_props: typing.Optional[ConfiguredProps] = OMIT, name: typing.Optional[str] = OMIT, + emit_on_deploy: typing.Optional[bool] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> AsyncHttpResponse[Emitter]: """ @@ -815,6 +821,9 @@ async def update( name : typing.Optional[str] The name of the trigger + emit_on_deploy : typing.Optional[bool] + Whether the trigger should emit events during deployment + request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -835,6 +844,7 @@ async def update( object_=configured_props, annotation=ConfiguredProps, direction="write" ), "name": name, + "emit_on_deploy": emit_on_deploy, }, headers={ "content-type": "application/json", diff --git a/src/pipedream/errors/__init__.py b/src/pipedream/errors/__init__.py index a6d06ac..aa63fc1 100644 --- a/src/pipedream/errors/__init__.py +++ b/src/pipedream/errors/__init__.py @@ -6,8 +6,12 @@ from importlib import import_module if typing.TYPE_CHECKING: + from .bad_request_error import BadRequestError from .too_many_requests_error import TooManyRequestsError -_dynamic_imports: typing.Dict[str, str] = {"TooManyRequestsError": ".too_many_requests_error"} +_dynamic_imports: typing.Dict[str, str] = { + "BadRequestError": ".bad_request_error", + "TooManyRequestsError": ".too_many_requests_error", +} def __getattr__(attr_name: str) -> typing.Any: @@ -31,4 +35,4 @@ def __dir__(): return sorted(lazy_attrs) -__all__ = ["TooManyRequestsError"] +__all__ = ["BadRequestError", "TooManyRequestsError"] diff --git a/src/pipedream/errors/bad_request_error.py b/src/pipedream/errors/bad_request_error.py new file mode 100644 index 0000000..9244991 --- /dev/null +++ b/src/pipedream/errors/bad_request_error.py @@ -0,0 +1,11 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +from ..core.api_error import ApiError +from ..types.error_response import ErrorResponse + + +class BadRequestError(ApiError): + def __init__(self, body: ErrorResponse, headers: typing.Optional[typing.Dict[str, str]] = None): + super().__init__(status_code=400, headers=headers, body=body) diff --git a/src/pipedream/proxy/client.py b/src/pipedream/proxy/client.py index bdcb3f2..5c56ef0 100644 --- a/src/pipedream/proxy/client.py +++ b/src/pipedream/proxy/client.py @@ -1,11 +1,9 @@ # This file was auto-generated by Fern from our API Definition. -import base64 import typing from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ..core.request_options import RequestOptions -from ..types.proxy_response import ProxyResponse from .raw_client import AsyncRawProxyClient, RawProxyClient # this is used as the default value for optional parameters @@ -13,15 +11,13 @@ class ProxyClient: - def __init__(self, *, client_wrapper: SyncClientWrapper): self._raw_client = RawProxyClient(client_wrapper=client_wrapper) @property def with_raw_response(self) -> RawProxyClient: """ - Retrieves a raw implementation of this client that returns raw - responses. + Retrieves a raw implementation of this client that returns raw responses. Returns ------- @@ -31,18 +27,19 @@ def with_raw_response(self) -> RawProxyClient: def get( self, - url: str, + url_64: str, *, external_user_id: str, account_id: str, - headers: typing.Optional[typing.Dict[str, typing.Any]] = None, - params: typing.Optional[typing.Dict[str, typing.Any]] = None, - ) -> ProxyResponse: + request_options: typing.Optional[RequestOptions] = None, + ) -> typing.Iterator[bytes]: """ + Forward an authenticated GET request to an external API using an external user's account credentials + Parameters ---------- - url : str - Target URL + url_64 : str + Base64-encoded target URL external_user_id : str The external user ID for the proxy request @@ -50,15 +47,12 @@ def get( account_id : str The account ID to use for authentication - headers : typing.Optional[typing.Dict[str, typing.Any]] - Additional headers to include in the request - - params : typing.Optional[typing.Dict[str, typing.Any]] - Query parameters to include in the request + request_options : typing.Optional[RequestOptions] + Request-specific configuration. You can pass in configuration such as `chunk_size`, and more to customize the request and response. Returns ------- - ProxyResponse + typing.Iterator[bytes] proxy request successful Examples @@ -72,48 +66,32 @@ def get( client_secret="YOUR_CLIENT_SECRET", ) client.proxy.get( - url="https://example.com/api/endpoint", + url_64="url_64", external_user_id="external_user_id", account_id="account_id", - headers={"Extra-Downstream-Header": "some value"} - params={"limit": 10}, ) """ - url_64 = base64.urlsafe_b64encode(url.encode()).decode() - downstream_headers = { - f"x-pd-proxy-{header}": value - for header, value in (headers or {}).items() - } - request_options = RequestOptions( - additional_headers=downstream_headers, - additional_query_parameters=params, - ) - _response = self._raw_client.get( - url_64, - external_user_id=external_user_id, - account_id=account_id, - request_options=request_options, - ) - return _response.data + with self._raw_client.get( + url_64, external_user_id=external_user_id, account_id=account_id, request_options=request_options + ) as r: + yield from r.data def post( self, - url: str, + url_64: str, *, external_user_id: str, account_id: str, - headers: typing.Optional[typing.Dict[str, typing.Any]] = None, - body: typing.Optional[typing.Dict[ - str, - typing.Optional[typing.Any], - ]] = None, - params: typing.Optional[typing.Dict[str, typing.Any]] = None, - ) -> ProxyResponse: + request: typing.Dict[str, typing.Optional[typing.Any]], + request_options: typing.Optional[RequestOptions] = None, + ) -> typing.Iterator[bytes]: """ + Forward an authenticated POST request to an external API using an external user's account credentials + Parameters ---------- - url : str - Target URL + url_64 : str + Base64-encoded target URL external_user_id : str The external user ID for the proxy request @@ -121,18 +99,14 @@ def post( account_id : str The account ID to use for authentication - headers : typing.Optional[typing.Dict[str, typing.Any]] - Additional headers to include in the request - - body : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] - Request body data + request : typing.Dict[str, typing.Optional[typing.Any]] - params : typing.Optional[typing.Dict[str, typing.Any]] - Query parameters to include in the request + request_options : typing.Optional[RequestOptions] + Request-specific configuration. You can pass in configuration such as `chunk_size`, and more to customize the request and response. Returns ------- - ProxyResponse + typing.Iterator[bytes] proxy request successful Examples @@ -146,49 +120,37 @@ def post( client_secret="YOUR_CLIENT_SECRET", ) client.proxy.post( - url="https://example.com/api/endpoint", + url_64="url_64", external_user_id="external_user_id", account_id="account_id", - headers={"Content-Type": "application/json"}, - body={"key": "value"}, + request={"string": {"key": "value"}}, ) """ - url_64 = base64.urlsafe_b64encode(url.encode()).decode() - downstream_headers = { - f"x-pd-proxy-{header}": value - for header, value in (headers or {}).items() - } - request_options = RequestOptions( - additional_headers=downstream_headers, - additional_query_parameters=params, - ) - _response = self._raw_client.post( + with self._raw_client.post( url_64, external_user_id=external_user_id, account_id=account_id, - request=body or {}, + request=request, request_options=request_options, - ) - return _response.data + ) as r: + yield from r.data def put( self, - url: str, + url_64: str, *, external_user_id: str, account_id: str, - headers: typing.Optional[typing.Dict[str, typing.Any]] = None, - body: typing.Optional[typing.Dict[ - str, - typing.Optional[typing.Any], - ]] = None, - params: typing.Optional[typing.Dict[str, typing.Any]] = None, - ) -> ProxyResponse: + request: typing.Dict[str, typing.Optional[typing.Any]], + request_options: typing.Optional[RequestOptions] = None, + ) -> typing.Iterator[bytes]: """ + Forward an authenticated PUT request to an external API using an external user's account credentials + Parameters ---------- - url : str - Target URL + url_64 : str + Base64-encoded target URL external_user_id : str The external user ID for the proxy request @@ -196,18 +158,14 @@ def put( account_id : str The account ID to use for authentication - headers : typing.Optional[typing.Dict[str, typing.Any]] - Additional headers to include in the request + request : typing.Dict[str, typing.Optional[typing.Any]] - body : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] - Request body data - - params : typing.Optional[typing.Dict[str, typing.Any]] - Query parameters to include in the request + request_options : typing.Optional[RequestOptions] + Request-specific configuration. You can pass in configuration such as `chunk_size`, and more to customize the request and response. Returns ------- - ProxyResponse + typing.Iterator[bytes] proxy request successful Examples @@ -221,45 +179,36 @@ def put( client_secret="YOUR_CLIENT_SECRET", ) client.proxy.put( - url="https://example.com/api/endpoint", + url_64="url_64", external_user_id="external_user_id", account_id="account_id", - headers={"Content-Type": "application/json"}, - body={"key": "value"}, + request={"string": {"key": "value"}}, ) """ - url_64 = base64.urlsafe_b64encode(url.encode()).decode() - downstream_headers = { - f"x-pd-proxy-{header}": value - for header, value in (headers or {}).items() - } - request_options = RequestOptions( - additional_headers=downstream_headers, - additional_query_parameters=params, - ) - _response = self._raw_client.put( + with self._raw_client.put( url_64, external_user_id=external_user_id, account_id=account_id, - request=body or {}, + request=request, request_options=request_options, - ) - return _response.data + ) as r: + yield from r.data def delete( self, - url: str, + url_64: str, *, external_user_id: str, account_id: str, - headers: typing.Optional[typing.Dict[str, typing.Any]] = None, - params: typing.Optional[typing.Dict[str, typing.Any]] = None, - ) -> ProxyResponse: + request_options: typing.Optional[RequestOptions] = None, + ) -> typing.Iterator[bytes]: """ + Forward an authenticated DELETE request to an external API using an external user's account credentials + Parameters ---------- - url : str - Target URL + url_64 : str + Base64-encoded target URL external_user_id : str The external user ID for the proxy request @@ -267,15 +216,12 @@ def delete( account_id : str The account ID to use for authentication - headers : typing.Optional[typing.Dict[str, typing.Any]] - Additional headers to include in the request - - params : typing.Optional[typing.Dict[str, typing.Any]] - Query parameters to include in the request + request_options : typing.Optional[RequestOptions] + Request-specific configuration. You can pass in configuration such as `chunk_size`, and more to customize the request and response. Returns ------- - ProxyResponse + typing.Iterator[bytes] proxy request successful Examples @@ -289,47 +235,32 @@ def delete( client_secret="YOUR_CLIENT_SECRET", ) client.proxy.delete( - url="https://example.com/api/endpoint", + url_64="url_64", external_user_id="external_user_id", account_id="account_id", - headers={"Extra-Downstream-Header": "some value"} ) """ - url_64 = base64.urlsafe_b64encode(url.encode()).decode() - downstream_headers = { - f"x-pd-proxy-{header}": value - for header, value in (headers or {}).items() - } - request_options = RequestOptions( - additional_headers=downstream_headers, - additional_query_parameters=params, - ) - _response = self._raw_client.delete( - url_64, - external_user_id=external_user_id, - account_id=account_id, - request_options=request_options, - ) - return _response.data + with self._raw_client.delete( + url_64, external_user_id=external_user_id, account_id=account_id, request_options=request_options + ) as r: + yield from r.data def patch( self, - url: str, + url_64: str, *, external_user_id: str, account_id: str, - headers: typing.Optional[typing.Dict[str, typing.Any]] = None, - body: typing.Optional[typing.Dict[ - str, - typing.Optional[typing.Any], - ]] = None, - params: typing.Optional[typing.Dict[str, typing.Any]] = None, - ) -> ProxyResponse: + request: typing.Dict[str, typing.Optional[typing.Any]], + request_options: typing.Optional[RequestOptions] = None, + ) -> typing.Iterator[bytes]: """ + Forward an authenticated PATCH request to an external API using an external user's account credentials + Parameters ---------- - url : str - Target URL + url_64 : str + Base64-encoded target URL external_user_id : str The external user ID for the proxy request @@ -337,18 +268,14 @@ def patch( account_id : str The account ID to use for authentication - headers : typing.Optional[typing.Dict[str, typing.Any]] - Additional headers to include in the request - - body : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] - Request body data + request : typing.Dict[str, typing.Optional[typing.Any]] - params : typing.Optional[typing.Dict[str, typing.Any]] - Query parameters to include in the request + request_options : typing.Optional[RequestOptions] + Request-specific configuration. You can pass in configuration such as `chunk_size`, and more to customize the request and response. Returns ------- - ProxyResponse + typing.Iterator[bytes] proxy request successful Examples @@ -362,42 +289,30 @@ def patch( client_secret="YOUR_CLIENT_SECRET", ) client.proxy.patch( - url="https://example.com/api/endpoint", + url_64="url_64", external_user_id="external_user_id", account_id="account_id", - headers={"Content-Type": "application/json"}, - body={"key": "value"}, + request={"string": {"key": "value"}}, ) """ - url_64 = base64.urlsafe_b64encode(url.encode()).decode() - downstream_headers = { - f"x-pd-proxy-{header}": value - for header, value in (headers or {}).items() - } - request_options = RequestOptions( - additional_headers=downstream_headers, - additional_query_parameters=params, - ) - _response = self._raw_client.patch( + with self._raw_client.patch( url_64, external_user_id=external_user_id, account_id=account_id, - request=body or {}, + request=request, request_options=request_options, - ) - return _response.data + ) as r: + yield from r.data class AsyncProxyClient: - def __init__(self, *, client_wrapper: AsyncClientWrapper): self._raw_client = AsyncRawProxyClient(client_wrapper=client_wrapper) @property def with_raw_response(self) -> AsyncRawProxyClient: """ - Retrieves a raw implementation of this client that returns raw - responses. + Retrieves a raw implementation of this client that returns raw responses. Returns ------- @@ -407,18 +322,19 @@ def with_raw_response(self) -> AsyncRawProxyClient: async def get( self, - url: str, + url_64: str, *, external_user_id: str, account_id: str, - headers: typing.Optional[typing.Dict[str, typing.Any]] = None, - params: typing.Optional[typing.Dict[str, typing.Any]] = None, - ) -> ProxyResponse: + request_options: typing.Optional[RequestOptions] = None, + ) -> typing.AsyncIterator[bytes]: """ + Forward an authenticated GET request to an external API using an external user's account credentials + Parameters ---------- - url : str - Target URL + url_64 : str + Base64-encoded target URL external_user_id : str The external user ID for the proxy request @@ -426,15 +342,12 @@ async def get( account_id : str The account ID to use for authentication - headers : typing.Optional[typing.Dict[str, typing.Any]] - Additional headers to include in the request - - params : typing.Optional[typing.Dict[str, typing.Any]] - Query parameters to include in the request + request_options : typing.Optional[RequestOptions] + Request-specific configuration. You can pass in configuration such as `chunk_size`, and more to customize the request and response. Returns ------- - ProxyResponse + typing.AsyncIterator[bytes] proxy request successful Examples @@ -453,50 +366,36 @@ async def get( async def main() -> None: await client.proxy.get( - url="https://example.com/api/endpoint", + url_64="url_64", external_user_id="external_user_id", account_id="account_id", - headers={"Extra-Downstream-Header": "some value"} - params={"limit": 10}, ) asyncio.run(main()) """ - url_64 = base64.urlsafe_b64encode(url.encode()).decode() - downstream_headers = { - f"x-pd-proxy-{header}": value - for header, value in (headers or {}).items() - } - request_options = RequestOptions( - additional_headers=downstream_headers, - additional_query_parameters=params, - ) - _response = await self._raw_client.get( - url_64, - external_user_id=external_user_id, - account_id=account_id, - request_options=request_options) - return _response.data + async with self._raw_client.get( + url_64, external_user_id=external_user_id, account_id=account_id, request_options=request_options + ) as r: + async for _chunk in r.data: + yield _chunk async def post( self, - url: str, + url_64: str, *, external_user_id: str, account_id: str, - headers: typing.Optional[typing.Dict[str, typing.Any]] = None, - body: typing.Optional[typing.Dict[ - str, - typing.Optional[typing.Any], - ]] = None, - params: typing.Optional[typing.Dict[str, typing.Any]] = None, - ) -> ProxyResponse: + request: typing.Dict[str, typing.Optional[typing.Any]], + request_options: typing.Optional[RequestOptions] = None, + ) -> typing.AsyncIterator[bytes]: """ + Forward an authenticated POST request to an external API using an external user's account credentials + Parameters ---------- - url : str - Target URL + url_64 : str + Base64-encoded target URL external_user_id : str The external user ID for the proxy request @@ -504,18 +403,14 @@ async def post( account_id : str The account ID to use for authentication - headers : typing.Optional[typing.Dict[str, typing.Any]] - Additional headers to include in the request - - body : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] - Request body data + request : typing.Dict[str, typing.Optional[typing.Any]] - params : typing.Optional[typing.Dict[str, typing.Any]] - Query parameters to include in the request + request_options : typing.Optional[RequestOptions] + Request-specific configuration. You can pass in configuration such as `chunk_size`, and more to customize the request and response. Returns ------- - ProxyResponse + typing.AsyncIterator[bytes] proxy request successful Examples @@ -534,52 +429,41 @@ async def post( async def main() -> None: await client.proxy.post( - url="https://example.com/api/endpoint", + url_64="url_64", external_user_id="external_user_id", account_id="account_id", - headers={"Content-Type": "application/json"}, - body={"key": "value"}, + request={"string": {"key": "value"}}, ) asyncio.run(main()) """ - url_64 = base64.urlsafe_b64encode(url.encode()).decode() - downstream_headers = { - f"x-pd-proxy-{header}": value - for header, value in (headers or {}).items() - } - request_options = RequestOptions( - additional_headers=downstream_headers, - additional_query_parameters=params, - ) - _response = await self._raw_client.post( + async with self._raw_client.post( url_64, external_user_id=external_user_id, account_id=account_id, - request=body or {}, + request=request, request_options=request_options, - ) - return _response.data + ) as r: + async for _chunk in r.data: + yield _chunk async def put( self, - url: str, + url_64: str, *, external_user_id: str, account_id: str, - headers: typing.Optional[typing.Dict[str, typing.Any]] = None, - body: typing.Optional[typing.Dict[ - str, - typing.Optional[typing.Any], - ]] = None, - params: typing.Optional[typing.Dict[str, typing.Any]] = None, - ) -> ProxyResponse: + request: typing.Dict[str, typing.Optional[typing.Any]], + request_options: typing.Optional[RequestOptions] = None, + ) -> typing.AsyncIterator[bytes]: """ + Forward an authenticated PUT request to an external API using an external user's account credentials + Parameters ---------- - url : str - Target URL + url_64 : str + Base64-encoded target URL external_user_id : str The external user ID for the proxy request @@ -587,18 +471,14 @@ async def put( account_id : str The account ID to use for authentication - headers : typing.Optional[typing.Dict[str, typing.Any]] - Additional headers to include in the request + request : typing.Dict[str, typing.Optional[typing.Any]] - body : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] - Request body data - - params : typing.Optional[typing.Dict[str, typing.Any]] - Query parameters to include in the request + request_options : typing.Optional[RequestOptions] + Request-specific configuration. You can pass in configuration such as `chunk_size`, and more to customize the request and response. Returns ------- - ProxyResponse + typing.AsyncIterator[bytes] proxy request successful Examples @@ -617,48 +497,40 @@ async def put( async def main() -> None: await client.proxy.put( - url="https://example.com/api/endpoint", + url_64="url_64", external_user_id="external_user_id", account_id="account_id", - headers={"Content-Type": "application/json"}, - body={"key": "value"}, + request={"string": {"key": "value"}}, ) asyncio.run(main()) """ - url_64 = base64.urlsafe_b64encode(url.encode()).decode() - downstream_headers = { - f"x-pd-proxy-{header}": value - for header, value in (headers or {}).items() - } - request_options = RequestOptions( - additional_headers=downstream_headers, - additional_query_parameters=params, - ) - _response = await self._raw_client.put( + async with self._raw_client.put( url_64, external_user_id=external_user_id, account_id=account_id, - request=body or {}, + request=request, request_options=request_options, - ) - return _response.data + ) as r: + async for _chunk in r.data: + yield _chunk async def delete( self, - url: str, + url_64: str, *, external_user_id: str, account_id: str, - headers: typing.Optional[typing.Dict[str, typing.Any]] = None, - params: typing.Optional[typing.Dict[str, typing.Any]] = None, - ) -> ProxyResponse: + request_options: typing.Optional[RequestOptions] = None, + ) -> typing.AsyncIterator[bytes]: """ + Forward an authenticated DELETE request to an external API using an external user's account credentials + Parameters ---------- - url : str - Target URL + url_64 : str + Base64-encoded target URL external_user_id : str The external user ID for the proxy request @@ -666,15 +538,12 @@ async def delete( account_id : str The account ID to use for authentication - headers : typing.Optional[typing.Dict[str, typing.Any]] - Additional headers to include in the request - - params : typing.Optional[typing.Dict[str, typing.Any]] - Query parameters to include in the request + request_options : typing.Optional[RequestOptions] + Request-specific configuration. You can pass in configuration such as `chunk_size`, and more to customize the request and response. Returns ------- - ProxyResponse + typing.AsyncIterator[bytes] proxy request successful Examples @@ -693,49 +562,36 @@ async def delete( async def main() -> None: await client.proxy.delete( - url="https://example.com/api/endpoint", + url_64="url_64", external_user_id="external_user_id", account_id="account_id", - headers={"Extra-Downstream-Header": "some value"} ) asyncio.run(main()) """ - url_64 = base64.urlsafe_b64encode(url.encode()).decode() - downstream_headers = { - f"x-pd-proxy-{header}": value - for header, value in (headers or {}).items() - } - request_options = RequestOptions( - additional_headers=downstream_headers, - additional_query_parameters=params, - ) - _response = await self._raw_client.delete( - url_64, - external_user_id=external_user_id, - account_id=account_id, - request_options=request_options) - return _response.data + async with self._raw_client.delete( + url_64, external_user_id=external_user_id, account_id=account_id, request_options=request_options + ) as r: + async for _chunk in r.data: + yield _chunk async def patch( self, - url: str, + url_64: str, *, external_user_id: str, account_id: str, - headers: typing.Optional[typing.Dict[str, typing.Any]] = None, - body: typing.Optional[typing.Dict[ - str, - typing.Optional[typing.Any], - ]] = None, - params: typing.Optional[typing.Dict[str, typing.Any]] = None, - ) -> ProxyResponse: + request: typing.Dict[str, typing.Optional[typing.Any]], + request_options: typing.Optional[RequestOptions] = None, + ) -> typing.AsyncIterator[bytes]: """ + Forward an authenticated PATCH request to an external API using an external user's account credentials + Parameters ---------- - url : str - Target URL + url_64 : str + Base64-encoded target URL external_user_id : str The external user ID for the proxy request @@ -743,18 +599,14 @@ async def patch( account_id : str The account ID to use for authentication - headers : typing.Optional[typing.Dict[str, typing.Any]] - Additional headers to include in the request + request : typing.Dict[str, typing.Optional[typing.Any]] - body : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] - Request body data - - params : typing.Optional[typing.Dict[str, typing.Any]] - Query parameters to include in the request + request_options : typing.Optional[RequestOptions] + Request-specific configuration. You can pass in configuration such as `chunk_size`, and more to customize the request and response. Returns ------- - ProxyResponse + typing.AsyncIterator[bytes] proxy request successful Examples @@ -773,30 +625,21 @@ async def patch( async def main() -> None: await client.proxy.patch( - url="https://example.com/api/endpoint", + url_64="url_64", external_user_id="external_user_id", account_id="account_id", - headers={"Content-Type": "application/json"}, - body={"key": "value"}, + request={"string": {"key": "value"}}, ) asyncio.run(main()) """ - url_64 = base64.urlsafe_b64encode(url.encode()).decode() - downstream_headers = { - f"x-pd-proxy-{header}": value - for header, value in (headers or {}).items() - } - request_options = RequestOptions( - additional_headers=downstream_headers, - additional_query_parameters=params, - ) - _response = await self._raw_client.patch( + async with self._raw_client.patch( url_64, external_user_id=external_user_id, account_id=account_id, - request=body or {}, + request=request, request_options=request_options, - ) - return _response.data + ) as r: + async for _chunk in r.data: + yield _chunk diff --git a/src/pipedream/proxy/raw_client.py b/src/pipedream/proxy/raw_client.py index 6825954..7c4d061 100644 --- a/src/pipedream/proxy/raw_client.py +++ b/src/pipedream/proxy/raw_client.py @@ -1,5 +1,6 @@ # This file was auto-generated by Fern from our API Definition. +import contextlib import typing from json.decoder import JSONDecodeError @@ -10,7 +11,6 @@ from ..core.pydantic_utilities import parse_obj_as from ..core.request_options import RequestOptions from ..errors.too_many_requests_error import TooManyRequestsError -from ..types.proxy_response import ProxyResponse # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -20,6 +20,7 @@ class RawProxyClient: def __init__(self, *, client_wrapper: SyncClientWrapper): self._client_wrapper = client_wrapper + @contextlib.contextmanager def get( self, url_64: str, @@ -27,7 +28,7 @@ def get( external_user_id: str, account_id: str, request_options: typing.Optional[RequestOptions] = None, - ) -> HttpResponse[ProxyResponse]: + ) -> typing.Iterator[HttpResponse[typing.Iterator[bytes]]]: """ Forward an authenticated GET request to an external API using an external user's account credentials @@ -43,14 +44,14 @@ def get( The account ID to use for authentication request_options : typing.Optional[RequestOptions] - Request-specific configuration. + Request-specific configuration. You can pass in configuration such as `chunk_size`, and more to customize the request and response. Returns ------- - HttpResponse[ProxyResponse] + typing.Iterator[HttpResponse[typing.Iterator[bytes]]] proxy request successful """ - _response = self._client_wrapper.httpx_client.request( + with self._client_wrapper.httpx_client.stream( f"v1/connect/{jsonable_encoder(self._client_wrapper._project_id)}/proxy/{jsonable_encoder(url_64)}", method="GET", params={ @@ -58,35 +59,37 @@ def get( "account_id": account_id, }, request_options=request_options, - ) - try: - if _response is None or not _response.text.strip(): - return HttpResponse(response=_response, data=None) - if 200 <= _response.status_code < 300: - _data = typing.cast( - ProxyResponse, - parse_obj_as( - type_=ProxyResponse, # type: ignore - object_=_response.json(), - ), - ) - return HttpResponse(response=_response, data=_data) - if _response.status_code == 429: - raise TooManyRequestsError( - headers=dict(_response.headers), - body=typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ), - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) - raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) - + ) as _response: + + def _stream() -> HttpResponse[typing.Iterator[bytes]]: + try: + if 200 <= _response.status_code < 300: + _chunk_size = request_options.get("chunk_size", None) if request_options is not None else None + return HttpResponse( + response=_response, data=(_chunk for _chunk in _response.iter_bytes(chunk_size=_chunk_size)) + ) + _response.read() + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.text + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + yield _stream() + + @contextlib.contextmanager def post( self, url_64: str, @@ -95,7 +98,7 @@ def post( account_id: str, request: typing.Dict[str, typing.Optional[typing.Any]], request_options: typing.Optional[RequestOptions] = None, - ) -> HttpResponse[ProxyResponse]: + ) -> typing.Iterator[HttpResponse[typing.Iterator[bytes]]]: """ Forward an authenticated POST request to an external API using an external user's account credentials @@ -113,14 +116,14 @@ def post( request : typing.Dict[str, typing.Optional[typing.Any]] request_options : typing.Optional[RequestOptions] - Request-specific configuration. + Request-specific configuration. You can pass in configuration such as `chunk_size`, and more to customize the request and response. Returns ------- - HttpResponse[ProxyResponse] + typing.Iterator[HttpResponse[typing.Iterator[bytes]]] proxy request successful """ - _response = self._client_wrapper.httpx_client.request( + with self._client_wrapper.httpx_client.stream( f"v1/connect/{jsonable_encoder(self._client_wrapper._project_id)}/proxy/{jsonable_encoder(url_64)}", method="POST", params={ @@ -133,35 +136,37 @@ def post( }, request_options=request_options, omit=OMIT, - ) - try: - if _response is None or not _response.text.strip(): - return HttpResponse(response=_response, data=None) - if 200 <= _response.status_code < 300: - _data = typing.cast( - ProxyResponse, - parse_obj_as( - type_=ProxyResponse, # type: ignore - object_=_response.json(), - ), - ) - return HttpResponse(response=_response, data=_data) - if _response.status_code == 429: - raise TooManyRequestsError( - headers=dict(_response.headers), - body=typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ), - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) - raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) - + ) as _response: + + def _stream() -> HttpResponse[typing.Iterator[bytes]]: + try: + if 200 <= _response.status_code < 300: + _chunk_size = request_options.get("chunk_size", None) if request_options is not None else None + return HttpResponse( + response=_response, data=(_chunk for _chunk in _response.iter_bytes(chunk_size=_chunk_size)) + ) + _response.read() + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.text + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + yield _stream() + + @contextlib.contextmanager def put( self, url_64: str, @@ -170,7 +175,7 @@ def put( account_id: str, request: typing.Dict[str, typing.Optional[typing.Any]], request_options: typing.Optional[RequestOptions] = None, - ) -> HttpResponse[ProxyResponse]: + ) -> typing.Iterator[HttpResponse[typing.Iterator[bytes]]]: """ Forward an authenticated PUT request to an external API using an external user's account credentials @@ -188,14 +193,14 @@ def put( request : typing.Dict[str, typing.Optional[typing.Any]] request_options : typing.Optional[RequestOptions] - Request-specific configuration. + Request-specific configuration. You can pass in configuration such as `chunk_size`, and more to customize the request and response. Returns ------- - HttpResponse[ProxyResponse] + typing.Iterator[HttpResponse[typing.Iterator[bytes]]] proxy request successful """ - _response = self._client_wrapper.httpx_client.request( + with self._client_wrapper.httpx_client.stream( f"v1/connect/{jsonable_encoder(self._client_wrapper._project_id)}/proxy/{jsonable_encoder(url_64)}", method="PUT", params={ @@ -208,35 +213,37 @@ def put( }, request_options=request_options, omit=OMIT, - ) - try: - if _response is None or not _response.text.strip(): - return HttpResponse(response=_response, data=None) - if 200 <= _response.status_code < 300: - _data = typing.cast( - ProxyResponse, - parse_obj_as( - type_=ProxyResponse, # type: ignore - object_=_response.json(), - ), - ) - return HttpResponse(response=_response, data=_data) - if _response.status_code == 429: - raise TooManyRequestsError( - headers=dict(_response.headers), - body=typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ), - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) - raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) - + ) as _response: + + def _stream() -> HttpResponse[typing.Iterator[bytes]]: + try: + if 200 <= _response.status_code < 300: + _chunk_size = request_options.get("chunk_size", None) if request_options is not None else None + return HttpResponse( + response=_response, data=(_chunk for _chunk in _response.iter_bytes(chunk_size=_chunk_size)) + ) + _response.read() + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.text + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + yield _stream() + + @contextlib.contextmanager def delete( self, url_64: str, @@ -244,7 +251,7 @@ def delete( external_user_id: str, account_id: str, request_options: typing.Optional[RequestOptions] = None, - ) -> HttpResponse[ProxyResponse]: + ) -> typing.Iterator[HttpResponse[typing.Iterator[bytes]]]: """ Forward an authenticated DELETE request to an external API using an external user's account credentials @@ -260,14 +267,14 @@ def delete( The account ID to use for authentication request_options : typing.Optional[RequestOptions] - Request-specific configuration. + Request-specific configuration. You can pass in configuration such as `chunk_size`, and more to customize the request and response. Returns ------- - HttpResponse[ProxyResponse] + typing.Iterator[HttpResponse[typing.Iterator[bytes]]] proxy request successful """ - _response = self._client_wrapper.httpx_client.request( + with self._client_wrapper.httpx_client.stream( f"v1/connect/{jsonable_encoder(self._client_wrapper._project_id)}/proxy/{jsonable_encoder(url_64)}", method="DELETE", params={ @@ -275,35 +282,37 @@ def delete( "account_id": account_id, }, request_options=request_options, - ) - try: - if _response is None or not _response.text.strip(): - return HttpResponse(response=_response, data=None) - if 200 <= _response.status_code < 300: - _data = typing.cast( - ProxyResponse, - parse_obj_as( - type_=ProxyResponse, # type: ignore - object_=_response.json(), - ), - ) - return HttpResponse(response=_response, data=_data) - if _response.status_code == 429: - raise TooManyRequestsError( - headers=dict(_response.headers), - body=typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ), - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) - raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) - + ) as _response: + + def _stream() -> HttpResponse[typing.Iterator[bytes]]: + try: + if 200 <= _response.status_code < 300: + _chunk_size = request_options.get("chunk_size", None) if request_options is not None else None + return HttpResponse( + response=_response, data=(_chunk for _chunk in _response.iter_bytes(chunk_size=_chunk_size)) + ) + _response.read() + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.text + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + yield _stream() + + @contextlib.contextmanager def patch( self, url_64: str, @@ -312,7 +321,7 @@ def patch( account_id: str, request: typing.Dict[str, typing.Optional[typing.Any]], request_options: typing.Optional[RequestOptions] = None, - ) -> HttpResponse[ProxyResponse]: + ) -> typing.Iterator[HttpResponse[typing.Iterator[bytes]]]: """ Forward an authenticated PATCH request to an external API using an external user's account credentials @@ -330,14 +339,14 @@ def patch( request : typing.Dict[str, typing.Optional[typing.Any]] request_options : typing.Optional[RequestOptions] - Request-specific configuration. + Request-specific configuration. You can pass in configuration such as `chunk_size`, and more to customize the request and response. Returns ------- - HttpResponse[ProxyResponse] + typing.Iterator[HttpResponse[typing.Iterator[bytes]]] proxy request successful """ - _response = self._client_wrapper.httpx_client.request( + with self._client_wrapper.httpx_client.stream( f"v1/connect/{jsonable_encoder(self._client_wrapper._project_id)}/proxy/{jsonable_encoder(url_64)}", method="PATCH", params={ @@ -350,40 +359,42 @@ def patch( }, request_options=request_options, omit=OMIT, - ) - try: - if _response is None or not _response.text.strip(): - return HttpResponse(response=_response, data=None) - if 200 <= _response.status_code < 300: - _data = typing.cast( - ProxyResponse, - parse_obj_as( - type_=ProxyResponse, # type: ignore - object_=_response.json(), - ), - ) - return HttpResponse(response=_response, data=_data) - if _response.status_code == 429: - raise TooManyRequestsError( - headers=dict(_response.headers), - body=typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ), - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) - raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + ) as _response: + + def _stream() -> HttpResponse[typing.Iterator[bytes]]: + try: + if 200 <= _response.status_code < 300: + _chunk_size = request_options.get("chunk_size", None) if request_options is not None else None + return HttpResponse( + response=_response, data=(_chunk for _chunk in _response.iter_bytes(chunk_size=_chunk_size)) + ) + _response.read() + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.text + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + yield _stream() class AsyncRawProxyClient: def __init__(self, *, client_wrapper: AsyncClientWrapper): self._client_wrapper = client_wrapper + @contextlib.asynccontextmanager async def get( self, url_64: str, @@ -391,7 +402,7 @@ async def get( external_user_id: str, account_id: str, request_options: typing.Optional[RequestOptions] = None, - ) -> AsyncHttpResponse[ProxyResponse]: + ) -> typing.AsyncIterator[AsyncHttpResponse[typing.AsyncIterator[bytes]]]: """ Forward an authenticated GET request to an external API using an external user's account credentials @@ -407,14 +418,14 @@ async def get( The account ID to use for authentication request_options : typing.Optional[RequestOptions] - Request-specific configuration. + Request-specific configuration. You can pass in configuration such as `chunk_size`, and more to customize the request and response. Returns ------- - AsyncHttpResponse[ProxyResponse] + typing.AsyncIterator[AsyncHttpResponse[typing.AsyncIterator[bytes]]] proxy request successful """ - _response = await self._client_wrapper.httpx_client.request( + async with self._client_wrapper.httpx_client.stream( f"v1/connect/{jsonable_encoder(self._client_wrapper._project_id)}/proxy/{jsonable_encoder(url_64)}", method="GET", params={ @@ -422,35 +433,38 @@ async def get( "account_id": account_id, }, request_options=request_options, - ) - try: - if _response is None or not _response.text.strip(): - return AsyncHttpResponse(response=_response, data=None) - if 200 <= _response.status_code < 300: - _data = typing.cast( - ProxyResponse, - parse_obj_as( - type_=ProxyResponse, # type: ignore - object_=_response.json(), - ), - ) - return AsyncHttpResponse(response=_response, data=_data) - if _response.status_code == 429: - raise TooManyRequestsError( - headers=dict(_response.headers), - body=typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ), - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) - raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) - + ) as _response: + + async def _stream() -> AsyncHttpResponse[typing.AsyncIterator[bytes]]: + try: + if 200 <= _response.status_code < 300: + _chunk_size = request_options.get("chunk_size", None) if request_options is not None else None + return AsyncHttpResponse( + response=_response, + data=(_chunk async for _chunk in _response.aiter_bytes(chunk_size=_chunk_size)), + ) + await _response.aread() + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.text + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + yield await _stream() + + @contextlib.asynccontextmanager async def post( self, url_64: str, @@ -459,7 +473,7 @@ async def post( account_id: str, request: typing.Dict[str, typing.Optional[typing.Any]], request_options: typing.Optional[RequestOptions] = None, - ) -> AsyncHttpResponse[ProxyResponse]: + ) -> typing.AsyncIterator[AsyncHttpResponse[typing.AsyncIterator[bytes]]]: """ Forward an authenticated POST request to an external API using an external user's account credentials @@ -477,14 +491,14 @@ async def post( request : typing.Dict[str, typing.Optional[typing.Any]] request_options : typing.Optional[RequestOptions] - Request-specific configuration. + Request-specific configuration. You can pass in configuration such as `chunk_size`, and more to customize the request and response. Returns ------- - AsyncHttpResponse[ProxyResponse] + typing.AsyncIterator[AsyncHttpResponse[typing.AsyncIterator[bytes]]] proxy request successful """ - _response = await self._client_wrapper.httpx_client.request( + async with self._client_wrapper.httpx_client.stream( f"v1/connect/{jsonable_encoder(self._client_wrapper._project_id)}/proxy/{jsonable_encoder(url_64)}", method="POST", params={ @@ -497,35 +511,38 @@ async def post( }, request_options=request_options, omit=OMIT, - ) - try: - if _response is None or not _response.text.strip(): - return AsyncHttpResponse(response=_response, data=None) - if 200 <= _response.status_code < 300: - _data = typing.cast( - ProxyResponse, - parse_obj_as( - type_=ProxyResponse, # type: ignore - object_=_response.json(), - ), - ) - return AsyncHttpResponse(response=_response, data=_data) - if _response.status_code == 429: - raise TooManyRequestsError( - headers=dict(_response.headers), - body=typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ), - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) - raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) - + ) as _response: + + async def _stream() -> AsyncHttpResponse[typing.AsyncIterator[bytes]]: + try: + if 200 <= _response.status_code < 300: + _chunk_size = request_options.get("chunk_size", None) if request_options is not None else None + return AsyncHttpResponse( + response=_response, + data=(_chunk async for _chunk in _response.aiter_bytes(chunk_size=_chunk_size)), + ) + await _response.aread() + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.text + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + yield await _stream() + + @contextlib.asynccontextmanager async def put( self, url_64: str, @@ -534,7 +551,7 @@ async def put( account_id: str, request: typing.Dict[str, typing.Optional[typing.Any]], request_options: typing.Optional[RequestOptions] = None, - ) -> AsyncHttpResponse[ProxyResponse]: + ) -> typing.AsyncIterator[AsyncHttpResponse[typing.AsyncIterator[bytes]]]: """ Forward an authenticated PUT request to an external API using an external user's account credentials @@ -552,14 +569,14 @@ async def put( request : typing.Dict[str, typing.Optional[typing.Any]] request_options : typing.Optional[RequestOptions] - Request-specific configuration. + Request-specific configuration. You can pass in configuration such as `chunk_size`, and more to customize the request and response. Returns ------- - AsyncHttpResponse[ProxyResponse] + typing.AsyncIterator[AsyncHttpResponse[typing.AsyncIterator[bytes]]] proxy request successful """ - _response = await self._client_wrapper.httpx_client.request( + async with self._client_wrapper.httpx_client.stream( f"v1/connect/{jsonable_encoder(self._client_wrapper._project_id)}/proxy/{jsonable_encoder(url_64)}", method="PUT", params={ @@ -572,35 +589,38 @@ async def put( }, request_options=request_options, omit=OMIT, - ) - try: - if _response is None or not _response.text.strip(): - return AsyncHttpResponse(response=_response, data=None) - if 200 <= _response.status_code < 300: - _data = typing.cast( - ProxyResponse, - parse_obj_as( - type_=ProxyResponse, # type: ignore - object_=_response.json(), - ), - ) - return AsyncHttpResponse(response=_response, data=_data) - if _response.status_code == 429: - raise TooManyRequestsError( - headers=dict(_response.headers), - body=typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ), - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) - raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) - + ) as _response: + + async def _stream() -> AsyncHttpResponse[typing.AsyncIterator[bytes]]: + try: + if 200 <= _response.status_code < 300: + _chunk_size = request_options.get("chunk_size", None) if request_options is not None else None + return AsyncHttpResponse( + response=_response, + data=(_chunk async for _chunk in _response.aiter_bytes(chunk_size=_chunk_size)), + ) + await _response.aread() + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.text + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + yield await _stream() + + @contextlib.asynccontextmanager async def delete( self, url_64: str, @@ -608,7 +628,7 @@ async def delete( external_user_id: str, account_id: str, request_options: typing.Optional[RequestOptions] = None, - ) -> AsyncHttpResponse[ProxyResponse]: + ) -> typing.AsyncIterator[AsyncHttpResponse[typing.AsyncIterator[bytes]]]: """ Forward an authenticated DELETE request to an external API using an external user's account credentials @@ -624,14 +644,14 @@ async def delete( The account ID to use for authentication request_options : typing.Optional[RequestOptions] - Request-specific configuration. + Request-specific configuration. You can pass in configuration such as `chunk_size`, and more to customize the request and response. Returns ------- - AsyncHttpResponse[ProxyResponse] + typing.AsyncIterator[AsyncHttpResponse[typing.AsyncIterator[bytes]]] proxy request successful """ - _response = await self._client_wrapper.httpx_client.request( + async with self._client_wrapper.httpx_client.stream( f"v1/connect/{jsonable_encoder(self._client_wrapper._project_id)}/proxy/{jsonable_encoder(url_64)}", method="DELETE", params={ @@ -639,35 +659,38 @@ async def delete( "account_id": account_id, }, request_options=request_options, - ) - try: - if _response is None or not _response.text.strip(): - return AsyncHttpResponse(response=_response, data=None) - if 200 <= _response.status_code < 300: - _data = typing.cast( - ProxyResponse, - parse_obj_as( - type_=ProxyResponse, # type: ignore - object_=_response.json(), - ), - ) - return AsyncHttpResponse(response=_response, data=_data) - if _response.status_code == 429: - raise TooManyRequestsError( - headers=dict(_response.headers), - body=typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ), - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) - raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) - + ) as _response: + + async def _stream() -> AsyncHttpResponse[typing.AsyncIterator[bytes]]: + try: + if 200 <= _response.status_code < 300: + _chunk_size = request_options.get("chunk_size", None) if request_options is not None else None + return AsyncHttpResponse( + response=_response, + data=(_chunk async for _chunk in _response.aiter_bytes(chunk_size=_chunk_size)), + ) + await _response.aread() + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.text + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + yield await _stream() + + @contextlib.asynccontextmanager async def patch( self, url_64: str, @@ -676,7 +699,7 @@ async def patch( account_id: str, request: typing.Dict[str, typing.Optional[typing.Any]], request_options: typing.Optional[RequestOptions] = None, - ) -> AsyncHttpResponse[ProxyResponse]: + ) -> typing.AsyncIterator[AsyncHttpResponse[typing.AsyncIterator[bytes]]]: """ Forward an authenticated PATCH request to an external API using an external user's account credentials @@ -694,14 +717,14 @@ async def patch( request : typing.Dict[str, typing.Optional[typing.Any]] request_options : typing.Optional[RequestOptions] - Request-specific configuration. + Request-specific configuration. You can pass in configuration such as `chunk_size`, and more to customize the request and response. Returns ------- - AsyncHttpResponse[ProxyResponse] + typing.AsyncIterator[AsyncHttpResponse[typing.AsyncIterator[bytes]]] proxy request successful """ - _response = await self._client_wrapper.httpx_client.request( + async with self._client_wrapper.httpx_client.stream( f"v1/connect/{jsonable_encoder(self._client_wrapper._project_id)}/proxy/{jsonable_encoder(url_64)}", method="PATCH", params={ @@ -714,31 +737,33 @@ async def patch( }, request_options=request_options, omit=OMIT, - ) - try: - if _response is None or not _response.text.strip(): - return AsyncHttpResponse(response=_response, data=None) - if 200 <= _response.status_code < 300: - _data = typing.cast( - ProxyResponse, - parse_obj_as( - type_=ProxyResponse, # type: ignore - object_=_response.json(), - ), - ) - return AsyncHttpResponse(response=_response, data=_data) - if _response.status_code == 429: - raise TooManyRequestsError( - headers=dict(_response.headers), - body=typing.cast( - typing.Optional[typing.Any], - parse_obj_as( - type_=typing.Optional[typing.Any], # type: ignore - object_=_response.json(), - ), - ), - ) - _response_json = _response.json() - except JSONDecodeError: - raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) - raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + ) as _response: + + async def _stream() -> AsyncHttpResponse[typing.AsyncIterator[bytes]]: + try: + if 200 <= _response.status_code < 300: + _chunk_size = request_options.get("chunk_size", None) if request_options is not None else None + return AsyncHttpResponse( + response=_response, + data=(_chunk async for _chunk in _response.aiter_bytes(chunk_size=_chunk_size)), + ) + await _response.aread() + if _response.status_code == 429: + raise TooManyRequestsError( + headers=dict(_response.headers), + body=typing.cast( + typing.Optional[typing.Any], + parse_obj_as( + type_=typing.Optional[typing.Any], # type: ignore + object_=_response.json(), + ), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError( + status_code=_response.status_code, headers=dict(_response.headers), body=_response.text + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + yield await _stream() diff --git a/src/pipedream/tokens/client.py b/src/pipedream/tokens/client.py index f37eccf..cbe1c64 100644 --- a/src/pipedream/tokens/client.py +++ b/src/pipedream/tokens/client.py @@ -132,7 +132,6 @@ def validate( client.tokens.validate( ctok="ctok", app_id="app_id", - oauth_app_id="oauth_app_id", ) """ _response = self._raw_client.validate( @@ -273,7 +272,6 @@ async def main() -> None: await client.tokens.validate( ctok="ctok", app_id="app_id", - oauth_app_id="oauth_app_id", ) diff --git a/src/pipedream/triggers/__init__.py b/src/pipedream/triggers/__init__.py index 5cde020..ae3a5f2 100644 --- a/src/pipedream/triggers/__init__.py +++ b/src/pipedream/triggers/__init__.py @@ -2,3 +2,33 @@ # isort: skip_file +import typing +from importlib import import_module + +if typing.TYPE_CHECKING: + from .types import ListTriggersRequestRegistry +_dynamic_imports: typing.Dict[str, str] = {"ListTriggersRequestRegistry": ".types"} + + +def __getattr__(attr_name: str) -> typing.Any: + module_name = _dynamic_imports.get(attr_name) + if module_name is None: + raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") + try: + module = import_module(module_name, __package__) + if module_name == f".{attr_name}": + return module + else: + return getattr(module, attr_name) + except ImportError as e: + raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e + except AttributeError as e: + raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e + + +def __dir__(): + lazy_attrs = list(_dynamic_imports.keys()) + return sorted(lazy_attrs) + + +__all__ = ["ListTriggersRequestRegistry"] diff --git a/src/pipedream/triggers/client.py b/src/pipedream/triggers/client.py index 85a6646..c6f4524 100644 --- a/src/pipedream/triggers/client.py +++ b/src/pipedream/triggers/client.py @@ -11,6 +11,7 @@ from ..types.emitter import Emitter from ..types.reload_props_response import ReloadPropsResponse from .raw_client import AsyncRawTriggersClient, RawTriggersClient +from .types.list_triggers_request_registry import ListTriggersRequestRegistry # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -39,6 +40,7 @@ def list( limit: typing.Optional[int] = None, q: typing.Optional[str] = None, app: typing.Optional[str] = None, + registry: typing.Optional[ListTriggersRequestRegistry] = None, request_options: typing.Optional[RequestOptions] = None, ) -> SyncPager[Component]: """ @@ -61,13 +63,16 @@ def list( app : typing.Optional[str] The ID or name slug of the app to filter the triggers + registry : typing.Optional[ListTriggersRequestRegistry] + The registry to retrieve triggers from. Defaults to 'all' ('public', 'private', or 'all') + request_options : typing.Optional[RequestOptions] Request-specific configuration. Returns ------- SyncPager[Component] - triggers listed + behaves like registry=all Examples -------- @@ -79,13 +84,7 @@ def list( client_id="YOUR_CLIENT_ID", client_secret="YOUR_CLIENT_SECRET", ) - response = client.triggers.list( - after="after", - before="before", - limit=1, - q="q", - app="app", - ) + response = client.triggers.list() for item in response: yield item # alternatively, you can paginate page-by-page @@ -93,7 +92,7 @@ def list( yield page """ return self._raw_client.list( - after=after, before=before, limit=limit, q=q, app=app, request_options=request_options + after=after, before=before, limit=limit, q=q, app=app, registry=registry, request_options=request_options ) def retrieve( @@ -305,6 +304,7 @@ def deploy( dynamic_props_id: typing.Optional[str] = OMIT, workflow_id: typing.Optional[str] = OMIT, webhook_url: typing.Optional[str] = OMIT, + emit_on_deploy: typing.Optional[bool] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> Emitter: """ @@ -332,6 +332,9 @@ def deploy( webhook_url : typing.Optional[str] Optional webhook URL to receive trigger events + emit_on_deploy : typing.Optional[bool] + Whether the trigger should emit events during the deploy hook execution. Defaults to true if not specified. + request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -363,6 +366,7 @@ def deploy( dynamic_props_id=dynamic_props_id, workflow_id=workflow_id, webhook_url=webhook_url, + emit_on_deploy=emit_on_deploy, request_options=request_options, ) return _response.data @@ -391,6 +395,7 @@ async def list( limit: typing.Optional[int] = None, q: typing.Optional[str] = None, app: typing.Optional[str] = None, + registry: typing.Optional[ListTriggersRequestRegistry] = None, request_options: typing.Optional[RequestOptions] = None, ) -> AsyncPager[Component]: """ @@ -413,13 +418,16 @@ async def list( app : typing.Optional[str] The ID or name slug of the app to filter the triggers + registry : typing.Optional[ListTriggersRequestRegistry] + The registry to retrieve triggers from. Defaults to 'all' ('public', 'private', or 'all') + request_options : typing.Optional[RequestOptions] Request-specific configuration. Returns ------- AsyncPager[Component] - triggers listed + behaves like registry=all Examples -------- @@ -436,13 +444,7 @@ async def list( async def main() -> None: - response = await client.triggers.list( - after="after", - before="before", - limit=1, - q="q", - app="app", - ) + response = await client.triggers.list() async for item in response: yield item @@ -454,7 +456,7 @@ async def main() -> None: asyncio.run(main()) """ return await self._raw_client.list( - after=after, before=before, limit=limit, q=q, app=app, request_options=request_options + after=after, before=before, limit=limit, q=q, app=app, registry=registry, request_options=request_options ) async def retrieve( @@ -690,6 +692,7 @@ async def deploy( dynamic_props_id: typing.Optional[str] = OMIT, workflow_id: typing.Optional[str] = OMIT, webhook_url: typing.Optional[str] = OMIT, + emit_on_deploy: typing.Optional[bool] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> Emitter: """ @@ -717,6 +720,9 @@ async def deploy( webhook_url : typing.Optional[str] Optional webhook URL to receive trigger events + emit_on_deploy : typing.Optional[bool] + Whether the trigger should emit events during the deploy hook execution. Defaults to true if not specified. + request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -756,6 +762,7 @@ async def main() -> None: dynamic_props_id=dynamic_props_id, workflow_id=workflow_id, webhook_url=webhook_url, + emit_on_deploy=emit_on_deploy, request_options=request_options, ) return _response.data diff --git a/src/pipedream/triggers/raw_client.py b/src/pipedream/triggers/raw_client.py index 0d5da95..2c8253a 100644 --- a/src/pipedream/triggers/raw_client.py +++ b/src/pipedream/triggers/raw_client.py @@ -11,15 +11,18 @@ from ..core.pydantic_utilities import parse_obj_as from ..core.request_options import RequestOptions from ..core.serialization import convert_and_respect_annotation_metadata +from ..errors.bad_request_error import BadRequestError from ..errors.too_many_requests_error import TooManyRequestsError from ..types.component import Component from ..types.configure_prop_response import ConfigurePropResponse from ..types.configured_props import ConfiguredProps from ..types.deploy_trigger_response import DeployTriggerResponse from ..types.emitter import Emitter +from ..types.error_response import ErrorResponse from ..types.get_component_response import GetComponentResponse from ..types.get_components_response import GetComponentsResponse from ..types.reload_props_response import ReloadPropsResponse +from .types.list_triggers_request_registry import ListTriggersRequestRegistry # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -37,6 +40,7 @@ def list( limit: typing.Optional[int] = None, q: typing.Optional[str] = None, app: typing.Optional[str] = None, + registry: typing.Optional[ListTriggersRequestRegistry] = None, request_options: typing.Optional[RequestOptions] = None, ) -> SyncPager[Component]: """ @@ -59,13 +63,16 @@ def list( app : typing.Optional[str] The ID or name slug of the app to filter the triggers + registry : typing.Optional[ListTriggersRequestRegistry] + The registry to retrieve triggers from. Defaults to 'all' ('public', 'private', or 'all') + request_options : typing.Optional[RequestOptions] Request-specific configuration. Returns ------- SyncPager[Component] - triggers listed + behaves like registry=all """ _response = self._client_wrapper.httpx_client.request( f"v1/connect/{jsonable_encoder(self._client_wrapper._project_id)}/triggers", @@ -76,6 +83,7 @@ def list( "limit": limit, "q": q, "app": app, + "registry": registry, }, request_options=request_options, ) @@ -100,11 +108,23 @@ def list( limit=limit, q=q, app=app, + registry=registry, request_options=request_options, ) return SyncPager( has_next=_has_next, items=_items, get_next=_get_next, response=BaseHttpResponse(response=_response) ) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + ErrorResponse, + parse_obj_as( + type_=ErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 429: raise TooManyRequestsError( headers=dict(_response.headers), @@ -384,6 +404,7 @@ def deploy( dynamic_props_id: typing.Optional[str] = OMIT, workflow_id: typing.Optional[str] = OMIT, webhook_url: typing.Optional[str] = OMIT, + emit_on_deploy: typing.Optional[bool] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> HttpResponse[Emitter]: """ @@ -411,6 +432,9 @@ def deploy( webhook_url : typing.Optional[str] Optional webhook URL to receive trigger events + emit_on_deploy : typing.Optional[bool] + Whether the trigger should emit events during the deploy hook execution. Defaults to true if not specified. + request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -432,6 +456,7 @@ def deploy( "dynamic_props_id": dynamic_props_id, "workflow_id": workflow_id, "webhook_url": webhook_url, + "emit_on_deploy": emit_on_deploy, }, headers={ "content-type": "application/json", @@ -479,6 +504,7 @@ async def list( limit: typing.Optional[int] = None, q: typing.Optional[str] = None, app: typing.Optional[str] = None, + registry: typing.Optional[ListTriggersRequestRegistry] = None, request_options: typing.Optional[RequestOptions] = None, ) -> AsyncPager[Component]: """ @@ -501,13 +527,16 @@ async def list( app : typing.Optional[str] The ID or name slug of the app to filter the triggers + registry : typing.Optional[ListTriggersRequestRegistry] + The registry to retrieve triggers from. Defaults to 'all' ('public', 'private', or 'all') + request_options : typing.Optional[RequestOptions] Request-specific configuration. Returns ------- AsyncPager[Component] - triggers listed + behaves like registry=all """ _response = await self._client_wrapper.httpx_client.request( f"v1/connect/{jsonable_encoder(self._client_wrapper._project_id)}/triggers", @@ -518,6 +547,7 @@ async def list( "limit": limit, "q": q, "app": app, + "registry": registry, }, request_options=request_options, ) @@ -544,12 +574,24 @@ async def _get_next(): limit=limit, q=q, app=app, + registry=registry, request_options=request_options, ) return AsyncPager( has_next=_has_next, items=_items, get_next=_get_next, response=BaseHttpResponse(response=_response) ) + if _response.status_code == 400: + raise BadRequestError( + headers=dict(_response.headers), + body=typing.cast( + ErrorResponse, + parse_obj_as( + type_=ErrorResponse, # type: ignore + object_=_response.json(), + ), + ), + ) if _response.status_code == 429: raise TooManyRequestsError( headers=dict(_response.headers), @@ -829,6 +871,7 @@ async def deploy( dynamic_props_id: typing.Optional[str] = OMIT, workflow_id: typing.Optional[str] = OMIT, webhook_url: typing.Optional[str] = OMIT, + emit_on_deploy: typing.Optional[bool] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> AsyncHttpResponse[Emitter]: """ @@ -856,6 +899,9 @@ async def deploy( webhook_url : typing.Optional[str] Optional webhook URL to receive trigger events + emit_on_deploy : typing.Optional[bool] + Whether the trigger should emit events during the deploy hook execution. Defaults to true if not specified. + request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -877,6 +923,7 @@ async def deploy( "dynamic_props_id": dynamic_props_id, "workflow_id": workflow_id, "webhook_url": webhook_url, + "emit_on_deploy": emit_on_deploy, }, headers={ "content-type": "application/json", diff --git a/src/pipedream/triggers/types/__init__.py b/src/pipedream/triggers/types/__init__.py new file mode 100644 index 0000000..1024e89 --- /dev/null +++ b/src/pipedream/triggers/types/__init__.py @@ -0,0 +1,34 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +import typing +from importlib import import_module + +if typing.TYPE_CHECKING: + from .list_triggers_request_registry import ListTriggersRequestRegistry +_dynamic_imports: typing.Dict[str, str] = {"ListTriggersRequestRegistry": ".list_triggers_request_registry"} + + +def __getattr__(attr_name: str) -> typing.Any: + module_name = _dynamic_imports.get(attr_name) + if module_name is None: + raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}") + try: + module = import_module(module_name, __package__) + if module_name == f".{attr_name}": + return module + else: + return getattr(module, attr_name) + except ImportError as e: + raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e + except AttributeError as e: + raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e + + +def __dir__(): + lazy_attrs = list(_dynamic_imports.keys()) + return sorted(lazy_attrs) + + +__all__ = ["ListTriggersRequestRegistry"] diff --git a/src/pipedream/triggers/types/list_triggers_request_registry.py b/src/pipedream/triggers/types/list_triggers_request_registry.py new file mode 100644 index 0000000..e6f9d13 --- /dev/null +++ b/src/pipedream/triggers/types/list_triggers_request_registry.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +ListTriggersRequestRegistry = typing.Union[typing.Literal["public", "private", "all"], typing.Any] diff --git a/src/pipedream/types/__init__.py b/src/pipedream/types/__init__.py index 1484a49..6063ee7 100644 --- a/src/pipedream/types/__init__.py +++ b/src/pipedream/types/__init__.py @@ -102,6 +102,7 @@ from .prop_option_nested import PropOptionNested from .prop_option_value import PropOptionValue from .proxy_response import ProxyResponse + from .proxy_response_binary import ProxyResponseBinary from .reload_props_opts import ReloadPropsOpts from .reload_props_response import ReloadPropsResponse from .run_action_opts_stash_id import RunActionOptsStashId @@ -214,6 +215,7 @@ "PropOptionNested": ".prop_option_nested", "PropOptionValue": ".prop_option_value", "ProxyResponse": ".proxy_response", + "ProxyResponseBinary": ".proxy_response_binary", "ReloadPropsOpts": ".reload_props_opts", "ReloadPropsResponse": ".reload_props_response", "RunActionOptsStashId": ".run_action_opts_stash_id", @@ -350,6 +352,7 @@ def __dir__(): "PropOptionNested", "PropOptionValue", "ProxyResponse", + "ProxyResponseBinary", "ReloadPropsOpts", "ReloadPropsResponse", "RunActionOptsStashId", diff --git a/src/pipedream/types/deployed_component.py b/src/pipedream/types/deployed_component.py index 39ba6c2..b628be7 100644 --- a/src/pipedream/types/deployed_component.py +++ b/src/pipedream/types/deployed_component.py @@ -69,6 +69,11 @@ class DeployedComponent(UniversalBaseModel): Callback observations for the deployed component """ + emit_on_deploy: typing.Optional[bool] = pydantic.Field(default=None) + """ + Whether the trigger emits events during the deploy hook execution. When false, the $emit function is disabled during deploy hook execution. Defaults to true. + """ + if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 else: diff --git a/src/pipedream/types/emitter.py b/src/pipedream/types/emitter.py index cd4962f..9f1c407 100644 --- a/src/pipedream/types/emitter.py +++ b/src/pipedream/types/emitter.py @@ -28,6 +28,7 @@ class Emitter_DeployedComponent(UniversalBaseModel): name: str name_slug: str callback_observations: typing.Optional[typing.Optional[typing.Any]] = None + emit_on_deploy: typing.Optional[bool] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/pipedream/types/proxy_response_binary.py b/src/pipedream/types/proxy_response_binary.py new file mode 100644 index 0000000..e799429 --- /dev/null +++ b/src/pipedream/types/proxy_response_binary.py @@ -0,0 +1,3 @@ +# This file was auto-generated by Fern from our API Definition. + +ProxyResponseBinary = str