From e73f6ec6e98ddfd9aae8d999c5dee5cdcdc5b6ba Mon Sep 17 00:00:00 2001 From: fern-api <115122769+fern-api[bot]@users.noreply.github.com> Date: Tue, 26 May 2026 22:40:58 +0000 Subject: [PATCH 1/2] [fern-generated] Update SDK Generated by Fern CLI Version: unknown Generators: - fernapi/fern-python-sdk: 5.12.11 --- .fern/metadata.json | 13 +- .github/workflows/ci.yml | 13 +- poetry.lock | 78 ++- pyproject.toml | 2 +- reference.md | 894 +++++++++++-------------- src/pipedream/__init__.py | 14 +- src/pipedream/actions/raw_client.py | 12 - src/pipedream/components/raw_client.py | 12 - src/pipedream/core/client_wrapper.py | 4 +- src/pipedream/pipedream.py | 143 ++-- src/pipedream/proxy/client.py | 741 +++++++++++++------- src/pipedream/proxy/raw_client.py | 782 ++++++++++++++++----- src/pipedream/triggers/raw_client.py | 12 - src/pipedream/workflows/__init__.py | 5 - src/pipedream/workflows/client.py | 271 -------- 15 files changed, 1633 insertions(+), 1363 deletions(-) delete mode 100644 src/pipedream/workflows/__init__.py delete mode 100644 src/pipedream/workflows/client.py diff --git a/.fern/metadata.json b/.fern/metadata.json index e96d3f9..1b82d35 100644 --- a/.fern/metadata.json +++ b/.fern/metadata.json @@ -1,7 +1,7 @@ { - "cliVersion": "5.17.0", + "cliVersion": "5.37.12", "generatorName": "fernapi/fern-python-sdk", - "generatorVersion": "5.12.1", + "generatorVersion": "5.12.11", "generatorConfig": { "client": { "class_name": "Client", @@ -10,9 +10,8 @@ "exported_filename": "pipedream.py" } }, - "originGitCommit": "fa2fad94474bee68b5a4c87f25775ff6701a0fe6", - "originGitCommitIsDirty": false, - "invokedBy": "ci", - "ciProvider": "github", - "sdkVersion": "2.0.4" + "originGitCommit": "320eac6d2809f95097ec1bb8cdb630cf13316b22", + "originGitCommitIsDirty": true, + "invokedBy": "manual", + "sdkVersion": "2.0.5" } \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7fd6ffd..9ab0a27 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,8 +50,6 @@ jobs: needs: [compile, test] if: github.event_name == 'push' && contains(github.ref, 'refs/tags/') runs-on: ubuntu-latest - permissions: - id-token: write steps: - name: Checkout repo uses: actions/checkout@v4 @@ -64,7 +62,10 @@ jobs: curl -sSL https://install.python-poetry.org | python - -y --version 1.5.1 - name: Install dependencies run: poetry install - - name: Build package - run: poetry --no-interaction -v build - - name: Publish package - uses: pypa/gh-action-pypi-publish@release/v1 + - name: Publish to pypi + run: | + poetry config repositories.remote https://upload.pypi.org/legacy/ + poetry --no-interaction -v publish --build --repository remote --username "$PYPI_USERNAME" --password "$PYPI_PASSWORD" + env: + PYPI_USERNAME: ${{ secrets.PYPI_USERNAME }} + PYPI_PASSWORD: ${{ secrets.PYPI_PASSWORD }} diff --git a/poetry.lock b/poetry.lock index 4111119..4d94723 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.5 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.4.1 and should not be changed by hand. [[package]] name = "aiohappyeyeballs" @@ -6,6 +6,8 @@ version = "2.6.2" description = "Happy Eyeballs for asyncio" optional = true python-versions = ">=3.10" +groups = ["main"] +markers = "extra == \"aiohttp\"" files = [ {file = "aiohappyeyeballs-2.6.2-py3-none-any.whl", hash = "sha256:4708045e2d7a6c6bdf8aafa8ed39649eaf926a4543b54560659129e3365953c4"}, {file = "aiohappyeyeballs-2.6.2.tar.gz", hash = "sha256:e202810ee718bd01fc6ef49e8ea53d023d5cb6b581076d7925aa499fa55dbe64"}, @@ -17,6 +19,8 @@ version = "3.13.5" description = "Async http client/server framework (asyncio)" optional = true python-versions = ">=3.9" +groups = ["main"] +markers = "extra == \"aiohttp\"" files = [ {file = "aiohttp-3.13.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:02222e7e233295f40e011c1b00e3b0bd451f22cf853a0304c3595633ee47da4b"}, {file = "aiohttp-3.13.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bace460460ed20614fa6bc8cb09966c0b8517b8c58ad8046828c6078d25333b5"}, @@ -151,7 +155,7 @@ propcache = ">=0.2.0" yarl = ">=1.17.0,<2.0" [package.extras] -speedups = ["Brotli (>=1.2)", "aiodns (>=3.3.0)", "backports.zstd", "brotlicffi (>=1.2)"] +speedups = ["Brotli (>=1.2) ; platform_python_implementation == \"CPython\"", "aiodns (>=3.3.0)", "backports.zstd ; platform_python_implementation == \"CPython\" and python_version < \"3.14\"", "brotlicffi (>=1.2) ; platform_python_implementation != \"CPython\""] [[package]] name = "aiosignal" @@ -159,6 +163,8 @@ version = "1.4.0" description = "aiosignal: a list of registered asynchronous callbacks" optional = true python-versions = ">=3.9" +groups = ["main"] +markers = "extra == \"aiohttp\"" files = [ {file = "aiosignal-1.4.0-py3-none-any.whl", hash = "sha256:053243f8b92b990551949e63930a839ff0cf0b0ebbe0597b0f3fb19e1a0fe82e"}, {file = "aiosignal-1.4.0.tar.gz", hash = "sha256:f47eecd9468083c2029cc99945502cb7708b082c232f9aca65da147157b251c7"}, @@ -174,6 +180,7 @@ version = "0.7.0" description = "Reusable constraint types to use with typing.Annotated" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, @@ -185,6 +192,7 @@ version = "4.13.0" description = "High-level concurrency and networking framework on top of asyncio or Trio" optional = false python-versions = ">=3.10" +groups = ["main"] files = [ {file = "anyio-4.13.0-py3-none-any.whl", hash = "sha256:08b310f9e24a9594186fd75b4f73f4a4152069e3853f1ed8bfbf58369f4ad708"}, {file = "anyio-4.13.0.tar.gz", hash = "sha256:334b70e641fd2221c1505b3890c69882fe4a2df910cba14d97019b90b24439dc"}, @@ -204,6 +212,8 @@ version = "5.0.1" description = "Timeout context manager for asyncio programs" optional = true python-versions = ">=3.8" +groups = ["main"] +markers = "extra == \"aiohttp\" and python_version == \"3.10\"" files = [ {file = "async_timeout-5.0.1-py3-none-any.whl", hash = "sha256:39e3809566ff85354557ec2398b55e096c8364bacac9405a7a1fa429e77fe76c"}, {file = "async_timeout-5.0.1.tar.gz", hash = "sha256:d9321a7a3d5a6a5e187e824d2fa0793ce379a202935782d555d6e9d2735677d3"}, @@ -215,6 +225,8 @@ version = "26.1.0" description = "Classes Without Boilerplate" optional = true python-versions = ">=3.9" +groups = ["main"] +markers = "extra == \"aiohttp\"" files = [ {file = "attrs-26.1.0-py3-none-any.whl", hash = "sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309"}, {file = "attrs-26.1.0.tar.gz", hash = "sha256:d03ceb89cb322a8fd706d4fb91940737b6642aa36998fe130a9bc96c985eff32"}, @@ -226,6 +238,8 @@ version = "1.2.0" description = "Backport of asyncio.Runner, a context manager that controls event loop life cycle." optional = false python-versions = "<3.11,>=3.8" +groups = ["dev"] +markers = "python_version == \"3.10\"" files = [ {file = "backports_asyncio_runner-1.2.0-py3-none-any.whl", hash = "sha256:0da0a936a8aeb554eccb426dc55af3ba63bcdc69fa1a600b5bb305413a4477b5"}, {file = "backports_asyncio_runner-1.2.0.tar.gz", hash = "sha256:a5aa7b2b7d8f8bfcaa2b57313f70792df84e32a2a746f585213373f900b42162"}, @@ -237,6 +251,7 @@ version = "2026.5.20" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "certifi-2026.5.20-py3-none-any.whl", hash = "sha256:3c52e209ba0a4ad7aebe60436a4ab349c39e1e602e8c134221e546902ad25897"}, {file = "certifi-2026.5.20.tar.gz", hash = "sha256:69dea482ab64caa7b9f6aba1c6bf48bb6a5448d1c0f1b17ab42ad8c763a5344d"}, @@ -248,6 +263,8 @@ version = "0.4.6" description = "Cross-platform colored terminal text." optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +groups = ["dev"] +markers = "sys_platform == \"win32\"" files = [ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, @@ -259,6 +276,8 @@ version = "1.3.1" description = "Backport of PEP 654 (exception groups)" optional = false python-versions = ">=3.7" +groups = ["main", "dev"] +markers = "python_version == \"3.10\"" files = [ {file = "exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598"}, {file = "exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219"}, @@ -276,6 +295,7 @@ version = "2.1.2" description = "execnet: rapid multi-Python deployment" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "execnet-2.1.2-py3-none-any.whl", hash = "sha256:67fba928dd5a544b783f6056f449e5e3931a5c378b128bc18501f7ea79e296ec"}, {file = "execnet-2.1.2.tar.gz", hash = "sha256:63d83bfdd9a23e35b9c6a3261412324f964c2ec8dcd8d3c6916ee9373e0befcd"}, @@ -290,6 +310,8 @@ version = "1.8.0" description = "A list-like structure which implements collections.abc.MutableSequence" optional = true python-versions = ">=3.9" +groups = ["main"] +markers = "extra == \"aiohttp\"" files = [ {file = "frozenlist-1.8.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:b37f6d31b3dcea7deb5e9696e529a6aa4a898adc33db82da12e4c60a7c4d2011"}, {file = "frozenlist-1.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ef2b7b394f208233e471abc541cc6991f907ffd47dc72584acee3147899d6565"}, @@ -429,6 +451,7 @@ version = "0.16.0" description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86"}, {file = "h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1"}, @@ -440,6 +463,7 @@ version = "1.0.9" description = "A minimal low-level HTTP client." optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55"}, {file = "httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8"}, @@ -461,6 +485,7 @@ version = "0.28.1" description = "The next generation HTTP client." optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad"}, {file = "httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc"}, @@ -473,7 +498,7 @@ httpcore = "==1.*" idna = "*" [package.extras] -brotli = ["brotli", "brotlicffi"] +brotli = ["brotli ; platform_python_implementation == \"CPython\"", "brotlicffi ; platform_python_implementation != \"CPython\""] cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"] http2 = ["h2 (>=3,<5)"] socks = ["socksio (==1.*)"] @@ -485,6 +510,8 @@ version = "0.1.8" description = "Aiohttp transport for HTTPX" optional = true python-versions = ">=3.8" +groups = ["main"] +markers = "extra == \"aiohttp\"" files = [ {file = "httpx_aiohttp-0.1.8-py3-none-any.whl", hash = "sha256:b7bd958d1331f3759a38a0ba22ad29832cb63ca69498c17735228055bf78fa7e"}, {file = "httpx_aiohttp-0.1.8.tar.gz", hash = "sha256:756c5e74cdb568c3248ba63fe82bfe8bbe64b928728720f7eaac64b3cf46f308"}, @@ -500,6 +527,7 @@ version = "3.16" description = "Internationalized Domain Names in Applications (IDNA)" optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {file = "idna-3.16-py3-none-any.whl", hash = "sha256:cc246e3a3f89580c3a951b5ad298ca4638078b2cdd4f115654332b5c26daded5"}, {file = "idna-3.16.tar.gz", hash = "sha256:d7a6da03db833450fca25d2358ac9ff06cd624577a4aea3a596d5c0f77b8e03d"}, @@ -514,6 +542,7 @@ version = "2.3.0" description = "brain-dead simple config-ini parsing" optional = false python-versions = ">=3.10" +groups = ["dev"] files = [ {file = "iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12"}, {file = "iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730"}, @@ -525,6 +554,8 @@ version = "6.7.1" description = "multidict implementation" optional = true python-versions = ">=3.9" +groups = ["main"] +markers = "extra == \"aiohttp\"" files = [ {file = "multidict-6.7.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:c93c3db7ea657dd4637d57e74ab73de31bccefe144d3d4ce370052035bc85fb5"}, {file = "multidict-6.7.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:974e72a2474600827abaeda71af0c53d9ebbc3c2eb7da37b37d7829ae31232d8"}, @@ -683,6 +714,7 @@ version = "1.13.0" description = "Optional static typing for Python" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "mypy-1.13.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6607e0f1dd1fb7f0aca14d936d13fd19eba5e17e1cd2a14f808fa5f8f6d8f60a"}, {file = "mypy-1.13.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8a21be69bd26fa81b1f80a61ee7ab05b076c674d9b18fb56239d72e21d9f4c80"}, @@ -736,6 +768,7 @@ version = "1.1.0" description = "Type system extensions for programs checked with the mypy type checker." optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505"}, {file = "mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558"}, @@ -747,6 +780,7 @@ version = "26.2" description = "Core utilities for Python packages" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "packaging-26.2-py3-none-any.whl", hash = "sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e"}, {file = "packaging-26.2.tar.gz", hash = "sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661"}, @@ -758,6 +792,7 @@ version = "1.6.0" description = "plugin and hook calling mechanisms for python" optional = false python-versions = ">=3.9" +groups = ["dev"] files = [ {file = "pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746"}, {file = "pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3"}, @@ -773,6 +808,8 @@ version = "0.5.2" description = "Accelerated property cache" optional = true python-versions = ">=3.10" +groups = ["main"] +markers = "extra == \"aiohttp\"" files = [ {file = "propcache-0.5.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d5a81be28596d6559f6131ef33e10200de6e17643b3c74ce03f9eb103be6ae8b"}, {file = "propcache-0.5.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:29cbaac5ea0212663e6845e04b5e188d5a6ae6dd919810ac835bf1d3b42c3f4c"}, @@ -903,6 +940,7 @@ version = "2.13.4" description = "Data validation using Python type hints" optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {file = "pydantic-2.13.4-py3-none-any.whl", hash = "sha256:45a282cde31d808236fd7ea9d919b128653c8b38b393d1c4ab335c62924d9aba"}, {file = "pydantic-2.13.4.tar.gz", hash = "sha256:c40756b57adaa8b1efeeced5c196f3f3b7c435f90e84ea7f443901bec8099ef6"}, @@ -916,7 +954,7 @@ typing-inspection = ">=0.4.2" [package.extras] email = ["email-validator (>=2.0.0)"] -timezone = ["tzdata"] +timezone = ["tzdata ; python_version >= \"3.9\" and platform_system == \"Windows\""] [[package]] name = "pydantic-core" @@ -924,6 +962,7 @@ version = "2.46.4" description = "Core functionality for Pydantic validation and serialization" optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {file = "pydantic_core-2.46.4-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:a396dcc17e5a0b164dbe026896245a4fa9ff402edca1dff0be3d53a517f74de4"}, {file = "pydantic_core-2.46.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:da4b951fe36dc7c3a1ccb4e3cd1747c3542b8c9ceede8fc86cae054e764485f5"}, @@ -1056,6 +1095,7 @@ version = "2.20.0" description = "Pygments is a syntax highlighting package written in Python." optional = false python-versions = ">=3.9" +groups = ["dev"] files = [ {file = "pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176"}, {file = "pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f"}, @@ -1070,6 +1110,7 @@ version = "9.0.3" description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.10" +groups = ["dev"] files = [ {file = "pytest-9.0.3-py3-none-any.whl", hash = "sha256:2c5efc453d45394fdd706ade797c0a81091eccd1d6e4bccfcd476e2b8e0ab5d9"}, {file = "pytest-9.0.3.tar.gz", hash = "sha256:b86ada508af81d19edeb213c681b1d48246c1a91d304c6c81a427674c17eb91c"}, @@ -1089,22 +1130,23 @@ dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "requests [[package]] name = "pytest-asyncio" -version = "1.3.0" +version = "1.4.0" description = "Pytest support for asyncio" optional = false python-versions = ">=3.10" +groups = ["dev"] files = [ - {file = "pytest_asyncio-1.3.0-py3-none-any.whl", hash = "sha256:611e26147c7f77640e6d0a92a38ed17c3e9848063698d5c93d5aa7aa11cebff5"}, - {file = "pytest_asyncio-1.3.0.tar.gz", hash = "sha256:d7f52f36d231b80ee124cd216ffb19369aa168fc10095013c6b014a34d3ee9e5"}, + {file = "pytest_asyncio-1.4.0-py3-none-any.whl", hash = "sha256:933ca923a23075a87fb7070c0ec272a6848489824d887c85c812670932835aa1"}, + {file = "pytest_asyncio-1.4.0.tar.gz", hash = "sha256:c6c0d2259945122819f171a32ecea2c349ead889ee28176caaf492143424be42"}, ] [package.dependencies] backports-asyncio-runner = {version = ">=1.1,<2", markers = "python_version < \"3.11\""} -pytest = ">=8.2,<10" +pytest = ">=8.4,<10" typing-extensions = {version = ">=4.12", markers = "python_version < \"3.13\""} [package.extras] -docs = ["sphinx (>=5.3)", "sphinx-rtd-theme (>=1)"] +docs = ["sphinx (>=5.3)", "sphinx-rtd-theme (>=1)", "sphinx-tabs (>=3.5)"] testing = ["coverage (>=6.2)", "hypothesis (>=5.7.1)"] [[package]] @@ -1113,6 +1155,7 @@ version = "3.8.0" description = "pytest xdist plugin for distributed testing, most importantly across multiple CPUs" optional = false python-versions = ">=3.9" +groups = ["dev"] files = [ {file = "pytest_xdist-3.8.0-py3-none-any.whl", hash = "sha256:202ca578cfeb7370784a8c33d6d05bc6e13b4f25b5053c30a152269fd10f0b88"}, {file = "pytest_xdist-3.8.0.tar.gz", hash = "sha256:7e578125ec9bc6050861aa93f2d59f1d8d085595d6551c2c90b6f4fad8d3a9f1"}, @@ -1133,6 +1176,7 @@ version = "2.9.0.post0" description = "Extensions to the standard Python datetime module" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +groups = ["dev"] files = [ {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, @@ -1147,6 +1191,7 @@ version = "0.11.5" description = "An extremely fast Python linter and code formatter, written in Rust." optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ {file = "ruff-0.11.5-py3-none-linux_armv6l.whl", hash = "sha256:2561294e108eb648e50f210671cc56aee590fb6167b594144401532138c66c7b"}, {file = "ruff-0.11.5-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:ac12884b9e005c12d0bd121f56ccf8033e1614f736f766c118ad60780882a077"}, @@ -1174,6 +1219,7 @@ version = "1.17.0" description = "Python 2 and 3 compatibility utilities" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +groups = ["dev"] files = [ {file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"}, {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"}, @@ -1185,6 +1231,8 @@ version = "2.4.1" description = "A lil' TOML parser" optional = false python-versions = ">=3.8" +groups = ["dev"] +markers = "python_version == \"3.10\"" files = [ {file = "tomli-2.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f8f0fc26ec2cc2b965b7a3b87cd19c5c6b8c5e5f436b984e85f486d652285c30"}, {file = "tomli-2.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4ab97e64ccda8756376892c53a72bd1f964e519c77236368527f758fbc36a53a"}, @@ -1241,6 +1289,7 @@ version = "2.9.0.20260518" description = "Typing stubs for python-dateutil" optional = false python-versions = ">=3.10" +groups = ["dev"] files = [ {file = "types_python_dateutil-2.9.0.20260518-py3-none-any.whl", hash = "sha256:d6a9c5bd0de61460c8fdef8ab2b400f956a1a1075cce08d4e2b4434e478c50b8"}, {file = "types_python_dateutil-2.9.0.20260518.tar.gz", hash = "sha256:51f02dc03b61c7f6a07df45797d4dfe8a1aa47f0b7db9ad89f6fd3a1a70e1b51"}, @@ -1252,6 +1301,7 @@ version = "4.15.0" description = "Backported and Experimental Type Hints for Python 3.9+" optional = false python-versions = ">=3.9" +groups = ["main", "dev"] files = [ {file = "typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548"}, {file = "typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466"}, @@ -1263,6 +1313,7 @@ version = "0.4.2" description = "Runtime typing introspection tools" optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {file = "typing_inspection-0.4.2-py3-none-any.whl", hash = "sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7"}, {file = "typing_inspection-0.4.2.tar.gz", hash = "sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464"}, @@ -1277,16 +1328,17 @@ version = "2.7.0" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false python-versions = ">=3.10" +groups = ["dev"] files = [ {file = "urllib3-2.7.0-py3-none-any.whl", hash = "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897"}, {file = "urllib3-2.7.0.tar.gz", hash = "sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c"}, ] [package.extras] -brotli = ["brotli (>=1.2.0)", "brotlicffi (>=1.2.0.0)"] +brotli = ["brotli (>=1.2.0) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=1.2.0.0) ; platform_python_implementation != \"CPython\""] h2 = ["h2 (>=4,<5)"] socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] -zstd = ["backports-zstd (>=1.0.0)"] +zstd = ["backports-zstd (>=1.0.0) ; python_version < \"3.14\""] [[package]] name = "yarl" @@ -1294,6 +1346,8 @@ version = "1.24.2" description = "Yet another URL library" optional = true python-versions = ">=3.10" +groups = ["main"] +markers = "extra == \"aiohttp\"" files = [ {file = "yarl-1.24.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:5249a113065c2b7a958bc699759e359cd61cfc81e3069662208f48f191b7ed12"}, {file = "yarl-1.24.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7f4425fa244fbf530b006d0c5f79ce920114cfff5b4f5f6056e669f8e160fdc0"}, @@ -1410,6 +1464,6 @@ propcache = ">=0.2.1" aiohttp = ["aiohttp", "httpx-aiohttp"] [metadata] -lock-version = "2.0" +lock-version = "2.1" python-versions = "^3.10" content-hash = "747cf6806d0d2a32dda32c0f4beb23d48047dee5fab394a6dbe55935c60b949a" diff --git a/pyproject.toml b/pyproject.toml index c3be54d..7e5b9a9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ dynamic = ["version"] [tool.poetry] name = "pipedream" -version = "2.0.4" +version = "2.0.5" description = "" readme = "README.md" authors = [] diff --git a/reference.md b/reference.md index 12e322c..4aa17e2 100644 --- a/reference.md +++ b/reference.md @@ -53,7 +53,7 @@ client.app_categories.list()
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -119,7 +119,7 @@ client.app_categories.retrieve(
**id:** `str` — The ID of the app category to retrieve - +
@@ -127,7 +127,7 @@ client.app_categories.retrieve(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -205,7 +205,7 @@ client.apps.list(
**after:** `typing.Optional[str]` — The cursor to start from for pagination - +
@@ -213,7 +213,7 @@ client.apps.list(
**before:** `typing.Optional[str]` — The cursor to end before for pagination - +
@@ -221,7 +221,7 @@ client.apps.list(
**limit:** `typing.Optional[int]` — The maximum number of results to return - +
@@ -229,7 +229,7 @@ client.apps.list(
**q:** `typing.Optional[str]` — A search query to filter the apps - +
@@ -237,7 +237,7 @@ client.apps.list(
**sort_key:** `typing.Optional[AppsListRequestSortKey]` — The key to sort the apps by - +
@@ -245,7 +245,7 @@ client.apps.list(
**sort_direction:** `typing.Optional[AppsListRequestSortDirection]` — The direction to sort the apps - +
@@ -253,7 +253,7 @@ client.apps.list(
**category_ids:** `typing.Optional[typing.Union[str, typing.Sequence[str]]]` — Only return apps in these categories - +
@@ -261,7 +261,7 @@ client.apps.list(
**has_components:** `typing.Optional[bool]` — Only return apps that have components (actions or triggers) - +
@@ -269,7 +269,7 @@ client.apps.list(
**has_actions:** `typing.Optional[bool]` — Only return apps that have actions - +
@@ -277,7 +277,7 @@ client.apps.list(
**has_triggers:** `typing.Optional[bool]` — Only return apps that have triggers - +
@@ -285,7 +285,7 @@ client.apps.list(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -351,7 +351,7 @@ client.apps.retrieve(
**app_id:** `str` — The name slug or ID of the app (e.g., 'slack', 'github') - +
@@ -359,7 +359,7 @@ client.apps.retrieve(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -432,15 +432,15 @@ client.accounts.list(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
-**external_user_id:** `typing.Optional[str]` - +**external_user_id:** `typing.Optional[str]` +
@@ -448,7 +448,7 @@ client.accounts.list(
**oauth_app_id:** `typing.Optional[str]` — The OAuth app ID to filter by, if applicable - +
@@ -456,7 +456,7 @@ client.accounts.list(
**after:** `typing.Optional[str]` — The cursor to start from for pagination - +
@@ -464,7 +464,7 @@ client.accounts.list(
**before:** `typing.Optional[str]` — The cursor to end before for pagination - +
@@ -472,7 +472,7 @@ client.accounts.list(
**limit:** `typing.Optional[int]` — The maximum number of results to return - +
@@ -480,7 +480,7 @@ client.accounts.list(
**app:** `typing.Optional[str]` — The app slug or ID to filter accounts by. - +
@@ -488,7 +488,7 @@ client.accounts.list(
**include_credentials:** `typing.Optional[bool]` — Whether to retrieve the account's credentials or not - +
@@ -496,7 +496,7 @@ client.accounts.list(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -566,7 +566,7 @@ client.accounts.create(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
@@ -574,7 +574,7 @@ client.accounts.create(
**app_slug:** `str` — The app slug for the account - +
@@ -582,7 +582,7 @@ client.accounts.create(
**cfmap_json:** `str` — JSON string containing the custom fields mapping - +
@@ -590,15 +590,15 @@ client.accounts.create(
**connect_token:** `str` — The connect token for authentication - +
-**external_user_id:** `typing.Optional[str]` - +**external_user_id:** `typing.Optional[str]` +
@@ -606,7 +606,7 @@ client.accounts.create(
**oauth_app_id:** `typing.Optional[str]` — The OAuth app ID to filter by, if applicable - +
@@ -614,7 +614,7 @@ client.accounts.create(
**name:** `typing.Optional[str]` — Optional name for the account - +
@@ -622,7 +622,7 @@ client.accounts.create(
**account_id:** `typing.Optional[str]` — An existing account ID to reconnect. When provided, the account's credentials are updated instead of creating a new account. Must belong to the same external user and project environment as the connect token, and match the app identified by app_slug. - +
@@ -630,7 +630,7 @@ client.accounts.create(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -697,15 +697,15 @@ client.accounts.retrieve(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
-**account_id:** `str` - +**account_id:** `str` +
@@ -713,7 +713,7 @@ client.accounts.retrieve(
**include_credentials:** `typing.Optional[bool]` — Whether to retrieve the account's credentials or not - +
@@ -721,7 +721,7 @@ client.accounts.retrieve(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -787,15 +787,15 @@ client.accounts.delete(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
-**account_id:** `str` - +**account_id:** `str` +
@@ -803,7 +803,7 @@ client.accounts.delete(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -869,23 +869,123 @@ client.accounts.delete_by_app(
**project_id:** `str` — The project ID, which starts with `proj_`. + +
+ + +
+
+**app_id:** `str` +
-**app_id:** `str` +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+ + + + +
client.accounts.list_by_external_user(...) -> typing.List[Account]
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. +#### 📝 Description + +
+
+ +
+
+ +List all connected accounts for a specific external user. Equivalent to GET /accounts with external_user_id filter but uses path-based routing. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from pipedream import Pipedream +from pipedream.environment import PipedreamEnvironment + +client = Pipedream( + client_id="", + client_secret="", + environment=PipedreamEnvironment.PROD, +) + +client.accounts.list_by_external_user( + external_user_id="external_user_id", + include_credentials=True, + app="app", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**project_id:** `str` — The project ID, which starts with `proj_`. + +
+
+ +
+
+ +**external_user_id:** `str` + +
+
+ +
+
+ +**include_credentials:** `typing.Optional[bool]` + +
+
+ +
+
+ +**app:** `typing.Optional[str]` + +
+
+ +
+
+**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. +
@@ -952,15 +1052,15 @@ client.users.delete_external_user(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
-**external_user_id:** `str` - +**external_user_id:** `str` +
@@ -968,7 +1068,7 @@ client.users.delete_external_user(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -1037,7 +1137,7 @@ client.users.list(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
@@ -1045,7 +1145,7 @@ client.users.list(
**after:** `typing.Optional[str]` — The cursor to start from for pagination - +
@@ -1053,7 +1153,7 @@ client.users.list(
**before:** `typing.Optional[str]` — The cursor to end before for pagination - +
@@ -1061,7 +1161,7 @@ client.users.list(
**limit:** `typing.Optional[int]` — The maximum number of results to return - +
@@ -1069,7 +1169,7 @@ client.users.list(
**q:** `typing.Optional[str]` — Filter users by external_id (partial match) - +
@@ -1077,7 +1177,7 @@ client.users.list(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -1150,7 +1250,7 @@ client.components.list(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
@@ -1158,7 +1258,7 @@ client.components.list(
**after:** `typing.Optional[str]` — The cursor to start from for pagination - +
@@ -1166,7 +1266,7 @@ client.components.list(
**before:** `typing.Optional[str]` — The cursor to end before for pagination - +
@@ -1174,7 +1274,7 @@ client.components.list(
**limit:** `typing.Optional[int]` — The maximum number of results to return - +
@@ -1182,7 +1282,7 @@ client.components.list(
**q:** `typing.Optional[str]` — A search query to filter the components - +
@@ -1190,7 +1290,7 @@ client.components.list(
**app:** `typing.Optional[str]` — The ID or name slug of the app to filter the components - +
@@ -1198,7 +1298,7 @@ client.components.list(
**registry:** `typing.Optional[ComponentsListRequestRegistry]` — The registry to retrieve components from. Defaults to 'all' ('public', 'private', or 'all') - +
@@ -1206,7 +1306,7 @@ client.components.list(
**component_type:** `typing.Optional[ComponentType]` — The type of the component to filter the components - +
@@ -1214,7 +1314,7 @@ client.components.list(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -1281,7 +1381,7 @@ client.components.retrieve(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
@@ -1289,7 +1389,7 @@ client.components.retrieve(
**component_id:** `str` — The key that uniquely identifies the component (e.g., 'slack-send-message') - +
@@ -1297,7 +1397,7 @@ client.components.retrieve(
**version:** `typing.Optional[str]` — Optional semantic version of the component to retrieve (for example '1.0.0') - +
@@ -1305,7 +1405,7 @@ client.components.retrieve(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -1373,15 +1473,15 @@ client.components.configure_prop(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
-**request:** `ConfigurePropOpts` - +**request:** `ConfigurePropOpts` +
@@ -1389,7 +1489,7 @@ client.components.configure_prop(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -1456,15 +1556,15 @@ client.components.reload_props(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
-**request:** `ReloadPropsOpts` - +**request:** `ReloadPropsOpts` +
@@ -1472,7 +1572,7 @@ client.components.reload_props(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -1544,7 +1644,7 @@ client.actions.list(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
@@ -1552,7 +1652,7 @@ client.actions.list(
**after:** `typing.Optional[str]` — The cursor to start from for pagination - +
@@ -1560,7 +1660,7 @@ client.actions.list(
**before:** `typing.Optional[str]` — The cursor to end before for pagination - +
@@ -1568,7 +1668,7 @@ client.actions.list(
**limit:** `typing.Optional[int]` — The maximum number of results to return - +
@@ -1576,7 +1676,7 @@ client.actions.list(
**q:** `typing.Optional[str]` — A search query to filter the actions - +
@@ -1584,7 +1684,7 @@ client.actions.list(
**app:** `typing.Optional[str]` — The ID or name slug of the app to filter the actions - +
@@ -1592,7 +1692,7 @@ client.actions.list(
**registry:** `typing.Optional[ActionsListRequestRegistry]` — The registry to retrieve actions from. Defaults to 'all' ('public', 'private', or 'all') - +
@@ -1600,7 +1700,7 @@ client.actions.list(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -1667,7 +1767,7 @@ client.actions.retrieve(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
@@ -1675,7 +1775,7 @@ client.actions.retrieve(
**component_id:** `str` — The key that uniquely identifies the component (e.g., 'slack-send-message') - +
@@ -1683,7 +1783,7 @@ client.actions.retrieve(
**version:** `typing.Optional[str]` — Optional semantic version of the component to retrieve (for example '1.0.0') - +
@@ -1691,7 +1791,7 @@ client.actions.retrieve(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -1759,15 +1859,15 @@ client.actions.configure_prop(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
-**request:** `ConfigurePropOpts` - +**request:** `ConfigurePropOpts` +
@@ -1775,7 +1875,7 @@ client.actions.configure_prop(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -1842,15 +1942,15 @@ client.actions.reload_props(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
-**request:** `ReloadPropsOpts` - +**request:** `ReloadPropsOpts` +
@@ -1858,7 +1958,7 @@ client.actions.reload_props(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -1925,7 +2025,7 @@ client.actions.run(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
@@ -1933,7 +2033,7 @@ client.actions.run(
**id:** `str` — The action component ID - +
@@ -1941,7 +2041,7 @@ client.actions.run(
**external_user_id:** `str` — The external user ID - +
@@ -1949,15 +2049,15 @@ client.actions.run(
**version:** `typing.Optional[str]` — Optional action component version (in SemVer format, for example '1.0.0'), defaults to latest - +
-**configured_props:** `typing.Optional[ConfiguredProps]` - +**configured_props:** `typing.Optional[ConfiguredProps]` +
@@ -1965,15 +2065,15 @@ client.actions.run(
**dynamic_props_id:** `typing.Optional[str]` — The ID for dynamic props - +
-**stash_id:** `typing.Optional[RunActionOptsStashId]` - +**stash_id:** `typing.Optional[RunActionOptsStashId]` +
@@ -1981,7 +2081,7 @@ client.actions.run(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -2053,7 +2153,7 @@ client.triggers.list(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
@@ -2061,7 +2161,7 @@ client.triggers.list(
**after:** `typing.Optional[str]` — The cursor to start from for pagination - +
@@ -2069,7 +2169,7 @@ client.triggers.list(
**before:** `typing.Optional[str]` — The cursor to end before for pagination - +
@@ -2077,7 +2177,7 @@ client.triggers.list(
**limit:** `typing.Optional[int]` — The maximum number of results to return - +
@@ -2085,7 +2185,7 @@ client.triggers.list(
**q:** `typing.Optional[str]` — A search query to filter the triggers - +
@@ -2093,7 +2193,7 @@ client.triggers.list(
**app:** `typing.Optional[str]` — The ID or name slug of the app to filter the triggers - +
@@ -2101,7 +2201,7 @@ client.triggers.list(
**registry:** `typing.Optional[TriggersListRequestRegistry]` — The registry to retrieve triggers from. Defaults to 'all' ('public', 'private', or 'all') - +
@@ -2109,7 +2209,7 @@ client.triggers.list(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -2176,7 +2276,7 @@ client.triggers.retrieve(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
@@ -2184,7 +2284,7 @@ client.triggers.retrieve(
**component_id:** `str` — The key that uniquely identifies the component (e.g., 'slack-send-message') - +
@@ -2192,7 +2292,7 @@ client.triggers.retrieve(
**version:** `typing.Optional[str]` — Optional semantic version of the component to retrieve (for example '1.0.0') - +
@@ -2200,7 +2300,7 @@ client.triggers.retrieve(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -2268,15 +2368,15 @@ client.triggers.configure_prop(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
-**request:** `ConfigurePropOpts` - +**request:** `ConfigurePropOpts` +
@@ -2284,7 +2384,7 @@ client.triggers.configure_prop(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -2351,15 +2451,15 @@ client.triggers.reload_props(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
-**request:** `ReloadPropsOpts` - +**request:** `ReloadPropsOpts` +
@@ -2367,7 +2467,7 @@ client.triggers.reload_props(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -2434,7 +2534,7 @@ client.triggers.deploy(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
@@ -2442,7 +2542,7 @@ client.triggers.deploy(
**id:** `str` — The trigger component ID - +
@@ -2450,7 +2550,7 @@ client.triggers.deploy(
**external_user_id:** `str` — The external user ID - +
@@ -2458,15 +2558,15 @@ client.triggers.deploy(
**version:** `typing.Optional[str]` — Optional trigger component version (in SemVer format, for example '1.0.0'), defaults to latest - +
-**configured_props:** `typing.Optional[ConfiguredProps]` - +**configured_props:** `typing.Optional[ConfiguredProps]` +
@@ -2474,7 +2574,7 @@ client.triggers.deploy(
**dynamic_props_id:** `typing.Optional[str]` — The ID for dynamic props - +
@@ -2482,7 +2582,7 @@ client.triggers.deploy(
**workflow_id:** `typing.Optional[str]` — Optional ID of a workflow to receive trigger events - +
@@ -2490,7 +2590,7 @@ client.triggers.deploy(
**webhook_url:** `typing.Optional[str]` — Optional webhook URL to receive trigger events - +
@@ -2498,7 +2598,7 @@ client.triggers.deploy(
**emit_on_deploy:** `typing.Optional[bool]` — Whether the trigger should emit events during the deploy hook execution. Defaults to true if not specified. - +
@@ -2506,7 +2606,7 @@ client.triggers.deploy(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -2577,7 +2677,7 @@ client.deployed_triggers.list(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
@@ -2585,7 +2685,7 @@ client.deployed_triggers.list(
**external_user_id:** `str` — Your end user ID, for whom you deployed the trigger - +
@@ -2593,7 +2693,7 @@ client.deployed_triggers.list(
**after:** `typing.Optional[str]` — The cursor to start from for pagination - +
@@ -2601,7 +2701,7 @@ client.deployed_triggers.list(
**before:** `typing.Optional[str]` — The cursor to end before for pagination - +
@@ -2609,7 +2709,7 @@ client.deployed_triggers.list(
**limit:** `typing.Optional[int]` — The maximum number of results to return - +
@@ -2617,7 +2717,7 @@ client.deployed_triggers.list(
**emitter_type:** `typing.Optional[EmitterType]` — Filter deployed triggers by emitter type (defaults to 'source' if not provided) - +
@@ -2625,7 +2725,7 @@ client.deployed_triggers.list(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -2692,15 +2792,15 @@ client.deployed_triggers.retrieve(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
-**trigger_id:** `str` - +**trigger_id:** `str` +
@@ -2708,7 +2808,7 @@ client.deployed_triggers.retrieve(
**external_user_id:** `str` — Your end user ID, for whom you deployed the trigger - +
@@ -2716,7 +2816,7 @@ client.deployed_triggers.retrieve(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -2783,15 +2883,15 @@ client.deployed_triggers.update(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
-**trigger_id:** `str` - +**trigger_id:** `str` +
@@ -2799,7 +2899,7 @@ client.deployed_triggers.update(
**external_user_id:** `str` — The external user ID who owns the trigger - +
@@ -2807,15 +2907,15 @@ client.deployed_triggers.update(
**active:** `typing.Optional[bool]` — Whether the trigger should be active - +
-**configured_props:** `typing.Optional[ConfiguredProps]` - +**configured_props:** `typing.Optional[ConfiguredProps]` +
@@ -2823,7 +2923,7 @@ client.deployed_triggers.update(
**name:** `typing.Optional[str]` — The name of the trigger - +
@@ -2831,7 +2931,7 @@ client.deployed_triggers.update(
**emit_on_deploy:** `typing.Optional[bool]` — Whether the trigger should emit events during deployment - +
@@ -2839,7 +2939,7 @@ client.deployed_triggers.update(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -2907,15 +3007,15 @@ client.deployed_triggers.delete(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
-**trigger_id:** `str` - +**trigger_id:** `str` +
@@ -2923,7 +3023,7 @@ client.deployed_triggers.delete(
**external_user_id:** `str` — The external user ID who owns the trigger - +
@@ -2931,7 +3031,7 @@ client.deployed_triggers.delete(
**ignore_hook_errors:** `typing.Optional[bool]` — Whether to ignore errors during deactivation hook - +
@@ -2939,7 +3039,7 @@ client.deployed_triggers.delete(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -3007,15 +3107,15 @@ client.deployed_triggers.list_events(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
-**trigger_id:** `str` - +**trigger_id:** `str` +
@@ -3023,7 +3123,7 @@ client.deployed_triggers.list_events(
**external_user_id:** `str` — Your end user ID, for whom you deployed the trigger - +
@@ -3031,7 +3131,7 @@ client.deployed_triggers.list_events(
**n:** `typing.Optional[int]` — The number of events to retrieve (defaults to 20 if not provided) - +
@@ -3039,7 +3139,7 @@ client.deployed_triggers.list_events(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -3106,15 +3206,15 @@ client.deployed_triggers.list_workflows(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
-**trigger_id:** `str` - +**trigger_id:** `str` +
@@ -3122,7 +3222,7 @@ client.deployed_triggers.list_workflows(
**external_user_id:** `str` — The external user ID who owns the trigger - +
@@ -3130,7 +3230,7 @@ client.deployed_triggers.list_workflows(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -3200,15 +3300,15 @@ client.deployed_triggers.update_workflows(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
-**trigger_id:** `str` - +**trigger_id:** `str` +
@@ -3216,7 +3316,7 @@ client.deployed_triggers.update_workflows(
**external_user_id:** `str` — The external user ID who owns the trigger - +
@@ -3224,7 +3324,7 @@ client.deployed_triggers.update_workflows(
**workflow_ids:** `typing.List[str]` — Array of workflow IDs to set - +
@@ -3232,7 +3332,7 @@ client.deployed_triggers.update_workflows(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -3299,15 +3399,15 @@ client.deployed_triggers.list_webhooks(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
-**trigger_id:** `str` - +**trigger_id:** `str` +
@@ -3315,7 +3415,7 @@ client.deployed_triggers.list_webhooks(
**external_user_id:** `str` — The external user ID who owns the trigger - +
@@ -3323,7 +3423,7 @@ client.deployed_triggers.list_webhooks(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -3393,15 +3493,15 @@ client.deployed_triggers.update_webhooks(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
-**trigger_id:** `str` - +**trigger_id:** `str` +
@@ -3409,7 +3509,7 @@ client.deployed_triggers.update_webhooks(
**external_user_id:** `str` — The external user ID who owns the trigger - +
@@ -3417,7 +3517,7 @@ client.deployed_triggers.update_webhooks(
**webhook_urls:** `typing.List[str]` — Array of webhook URLs to set - +
@@ -3425,7 +3525,7 @@ client.deployed_triggers.update_webhooks(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -3493,23 +3593,23 @@ client.deployed_triggers.retrieve_webhook(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
-**trigger_id:** `str` - +**trigger_id:** `str` +
-**webhook_id:** `str` - +**webhook_id:** `str` +
@@ -3517,7 +3617,7 @@ client.deployed_triggers.retrieve_webhook(
**external_user_id:** `str` — The external user ID who owns the trigger - +
@@ -3525,7 +3625,7 @@ client.deployed_triggers.retrieve_webhook(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -3593,23 +3693,23 @@ client.deployed_triggers.regenerate_webhook_signing_key(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
-**trigger_id:** `str` - +**trigger_id:** `str` +
-**webhook_id:** `str` - +**webhook_id:** `str` +
@@ -3617,7 +3717,7 @@ client.deployed_triggers.regenerate_webhook_signing_key(
**external_user_id:** `str` — The external user ID who owns the trigger - +
@@ -3625,7 +3725,7 @@ client.deployed_triggers.regenerate_webhook_signing_key(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -3690,7 +3790,7 @@ client.project_environment.retrieve_webhook()
**project_id:** `str` — The project ID, which starts with `proj_`. - +
@@ -3698,7 +3798,7 @@ client.project_environment.retrieve_webhook()
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -3764,7 +3864,7 @@ client.project_environment.update_webhook(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
@@ -3772,7 +3872,7 @@ client.project_environment.update_webhook(
**url:** `str` — The webhook URL to set - +
@@ -3780,7 +3880,7 @@ client.project_environment.update_webhook(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -3844,7 +3944,7 @@ client.project_environment.delete_webhook()
**project_id:** `str` — The project ID, which starts with `proj_`. - +
@@ -3852,7 +3952,7 @@ client.project_environment.delete_webhook()
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -3916,7 +4016,7 @@ client.project_environment.regenerate_webhook_signing_key()
**project_id:** `str` — The project ID, which starts with `proj_`. - +
@@ -3924,7 +4024,7 @@ client.project_environment.regenerate_webhook_signing_key()
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -3994,7 +4094,7 @@ client.projects.list(
**after:** `typing.Optional[str]` — The cursor to start from for pagination - +
@@ -4002,7 +4102,7 @@ client.projects.list(
**before:** `typing.Optional[str]` — The cursor to end before for pagination - +
@@ -4010,7 +4110,7 @@ client.projects.list(
**limit:** `typing.Optional[int]` — The maximum number of results to return - +
@@ -4018,7 +4118,7 @@ client.projects.list(
**q:** `typing.Optional[str]` — A search query to filter the projects - +
@@ -4026,7 +4126,7 @@ client.projects.list(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -4092,7 +4192,7 @@ client.projects.create(
**name:** `str` — Name of the project - +
@@ -4100,7 +4200,7 @@ client.projects.create(
**app_name:** `typing.Optional[str]` — Display name for the Connect application - +
@@ -4108,7 +4208,7 @@ client.projects.create(
**support_email:** `typing.Optional[str]` — Support email displayed to end users - +
@@ -4116,7 +4216,7 @@ client.projects.create(
**connect_require_key_auth_test:** `typing.Optional[bool]` — Send a test request to the upstream API when adding Connect accounts for key-based apps - +
@@ -4124,7 +4224,7 @@ client.projects.create(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -4190,7 +4290,7 @@ client.projects.retrieve(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
@@ -4198,7 +4298,7 @@ client.projects.retrieve(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -4264,7 +4364,7 @@ client.projects.delete(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
@@ -4272,7 +4372,7 @@ client.projects.delete(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -4338,7 +4438,7 @@ client.projects.update(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
@@ -4346,7 +4446,7 @@ client.projects.update(
**name:** `typing.Optional[str]` — Name of the project - +
@@ -4354,7 +4454,7 @@ client.projects.update(
**app_name:** `typing.Optional[str]` — Display name for the Connect application - +
@@ -4362,7 +4462,7 @@ client.projects.update(
**support_email:** `typing.Optional[str]` — Support email displayed to end users - +
@@ -4370,7 +4470,7 @@ client.projects.update(
**connect_require_key_auth_test:** `typing.Optional[bool]` — Send a test request to the upstream API when adding Connect accounts for key-based apps - +
@@ -4378,7 +4478,7 @@ client.projects.update(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -4445,7 +4545,7 @@ client.projects.update_logo(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
@@ -4453,7 +4553,7 @@ client.projects.update_logo(
**logo:** `str` — Data URI containing the new Base64 encoded image - +
@@ -4461,7 +4561,7 @@ client.projects.update_logo(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -4525,7 +4625,7 @@ client.projects.retrieve_info()
**project_id:** `str` — The project ID, which starts with `proj_`. - +
@@ -4533,7 +4633,7 @@ client.projects.retrieve_info()
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -4600,15 +4700,15 @@ client.file_stash.download_file(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
-**s_3_key:** `str` - +**s_3_key:** `str` +
@@ -4616,7 +4716,7 @@ client.file_stash.download_file(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -4685,7 +4785,7 @@ client.proxy.get(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
@@ -4693,7 +4793,7 @@ client.proxy.get(
**url_64:** `str` — Base64-encoded target URL - +
@@ -4701,7 +4801,7 @@ client.proxy.get(
**external_user_id:** `str` — The external user ID for the proxy request - +
@@ -4709,7 +4809,7 @@ client.proxy.get(
**account_id:** `str` — The account ID to use for authentication - +
@@ -4717,7 +4817,7 @@ client.proxy.get(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -4788,7 +4888,7 @@ client.proxy.post(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
@@ -4796,7 +4896,7 @@ client.proxy.post(
**url_64:** `str` — Base64-encoded target URL - +
@@ -4804,7 +4904,7 @@ client.proxy.post(
**external_user_id:** `str` — The external user ID for the proxy request - +
@@ -4812,7 +4912,7 @@ client.proxy.post(
**account_id:** `str` — The account ID to use for authentication - +
@@ -4820,7 +4920,7 @@ client.proxy.post(
**request:** `typing.Dict[str, typing.Any]` — Request body to forward to the target API - +
@@ -4828,7 +4928,7 @@ client.proxy.post(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -4899,7 +4999,7 @@ client.proxy.put(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
@@ -4907,7 +5007,7 @@ client.proxy.put(
**url_64:** `str` — Base64-encoded target URL - +
@@ -4915,7 +5015,7 @@ client.proxy.put(
**external_user_id:** `str` — The external user ID for the proxy request - +
@@ -4923,7 +5023,7 @@ client.proxy.put(
**account_id:** `str` — The account ID to use for authentication - +
@@ -4931,7 +5031,7 @@ client.proxy.put(
**request:** `typing.Dict[str, typing.Any]` — Request body to forward to the target API - +
@@ -4939,7 +5039,7 @@ client.proxy.put(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -5007,7 +5107,7 @@ client.proxy.delete(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
@@ -5015,7 +5115,7 @@ client.proxy.delete(
**url_64:** `str` — Base64-encoded target URL - +
@@ -5023,7 +5123,7 @@ client.proxy.delete(
**external_user_id:** `str` — The external user ID for the proxy request - +
@@ -5031,7 +5131,7 @@ client.proxy.delete(
**account_id:** `str` — The account ID to use for authentication - +
@@ -5039,7 +5139,7 @@ client.proxy.delete(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -5110,7 +5210,7 @@ client.proxy.patch(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
@@ -5118,7 +5218,7 @@ client.proxy.patch(
**url_64:** `str` — Base64-encoded target URL - +
@@ -5126,7 +5226,7 @@ client.proxy.patch(
**external_user_id:** `str` — The external user ID for the proxy request - +
@@ -5134,7 +5234,7 @@ client.proxy.patch(
**account_id:** `str` — The account ID to use for authentication - +
@@ -5142,7 +5242,7 @@ client.proxy.patch(
**request:** `typing.Dict[str, typing.Any]` — Request body to forward to the target API - +
@@ -5150,7 +5250,7 @@ client.proxy.patch(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -5217,7 +5317,7 @@ client.tokens.create(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
@@ -5225,7 +5325,7 @@ client.tokens.create(
**external_user_id:** `str` — Your end user ID, for whom you're creating the token - +
@@ -5233,7 +5333,7 @@ client.tokens.create(
**allowed_origins:** `typing.Optional[typing.List[str]]` — List of allowed origins for CORS - +
@@ -5241,7 +5341,7 @@ client.tokens.create(
**error_redirect_uri:** `typing.Optional[str]` — URI to redirect to on error - +
@@ -5249,7 +5349,7 @@ client.tokens.create(
**expires_in:** `typing.Optional[int]` — Token TTL in seconds (max 14400 = 4 hours). Defaults to 4 hours if not specified. - +
@@ -5257,7 +5357,7 @@ client.tokens.create(
**scope:** `typing.Optional[str]` — Space-separated scopes to restrict token permissions. Defaults to 'connect:*' if not specified. See https://pipedream.com/docs/connect/api-reference/authentication#connect-token-scopes for more information. - +
@@ -5265,7 +5365,7 @@ client.tokens.create(
**success_redirect_uri:** `typing.Optional[str]` — URI to redirect to on success - +
@@ -5273,7 +5373,7 @@ client.tokens.create(
**webhook_uri:** `typing.Optional[str]` — Webhook URI for notifications - +
@@ -5281,7 +5381,7 @@ client.tokens.create(
**allow_progressive_scopes:** `typing.Optional[bool]` — When true, end users may authorize a subset of the app's OAuth scopes; only the app's functional scopes (needed for the post-OAuth test request) are enforced. Defaults to false. - +
@@ -5289,7 +5389,7 @@ client.tokens.create(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -5357,8 +5457,8 @@ client.tokens.validate(
-**ctok:** `ConnectToken` - +**ctok:** `ConnectToken` +
@@ -5366,7 +5466,7 @@ client.tokens.validate(
**app_id:** `str` — The app ID to validate against - +
@@ -5374,7 +5474,7 @@ client.tokens.validate(
**account_id:** `typing.Optional[str]` — An existing account ID to reconnect. Must belong to the app identified by app_id. - +
@@ -5382,7 +5482,7 @@ client.tokens.validate(
**oauth_app_id:** `typing.Optional[str]` — The OAuth app ID to validate against (if the token is for an OAuth app) - +
@@ -5390,7 +5490,7 @@ client.tokens.validate(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -5458,7 +5558,7 @@ client.usage.list(
**start_ts:** `int` — Usage window start timestamp (seconds) - +
@@ -5466,7 +5566,7 @@ client.usage.list(
**end_ts:** `int` — Usage window end timestamp (seconds) - +
@@ -5474,7 +5574,7 @@ client.usage.list(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -5541,24 +5641,24 @@ client.oauth_tokens.create(
-**grant_type:** `typing.Literal` - +**grant_type:** `typing.Literal` +
-**client_id:** `str` - +**client_id:** `str` +
-**client_secret:** `str` - +**client_secret:** `str` +
@@ -5566,104 +5666,7 @@ client.oauth_tokens.create(
**scope:** `typing.Optional[str]` — Optional space-separated scopes for the access token. Defaults to `*`. - -
- - -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
- - - - - - -
- - -## Workflows -
client.workflows.invoke(...) -
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from pipedream import Pipedream, PipedreamEnvironment -from pipedream.workflows.client import HTTPAuthType - -client = Pipedream( - client_id="", - client_secret="", - environment=PipedreamEnvironment.PROD, -) -response = client.workflows.invoke( - url_or_endpoint="https://your-workflow.m.pipedream.net", - method="POST", - body={"key": "value"}, - headers={"Content-Type": "application/json"}, - auth_type=HTTPAuthType.NONE, -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**url_or_endpoint:** `str` — The URL of the workflow's HTTP interface or the ID of the endpoint - -
-
- -
-
- -**method:** `str` — HTTP method to use (default: "POST") - -
-
- -
-
- -**body:** `typing.Optional[typing.Any]` — Request body data - -
-
- -
-
- -**headers:** `typing.Optional[typing.Dict[str, str]]` — HTTP headers to include - -
-
- -
-
- -**auth_type:** `HTTPAuthType` — Type of authorization (default: HTTPAuthType.NONE) - +
@@ -5671,7 +5674,7 @@ response = client.workflows.invoke(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -5682,96 +5685,3 @@ response = client.workflows.invoke(
-
client.workflows.invoke_for_external_user(...) -
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from pipedream import Pipedream, PipedreamEnvironment - -client = Pipedream( - client_id="", - client_secret="", - environment=PipedreamEnvironment.PROD, -) -response = client.workflows.invoke_for_external_user( - url_or_endpoint="en2r1n8a98np7", - external_user_id="user_123", - method="POST", - body={"message": "Hello from external user"}, - headers={"Content-Type": "application/json"}, -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**url_or_endpoint:** `str` — The URL of the workflow's HTTP interface or the ID of the endpoint - -
-
- -
-
- -**external_user_id:** `str` — The external user ID for whom the workflow is being invoked - -
-
- -
-
- -**method:** `str` — HTTP method to use (default: "POST") - -
-
- -
-
- -**body:** `typing.Optional[typing.Any]` — Request body data - -
-
- -
-
- -**headers:** `typing.Optional[typing.Dict[str, str]]` — HTTP headers to include - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
-
-
- - -
-
-
diff --git a/src/pipedream/__init__.py b/src/pipedream/__init__.py index 8b5a7ee..9e9e73e 100644 --- a/src/pipedream/__init__.py +++ b/src/pipedream/__init__.py @@ -13,6 +13,8 @@ App, AppAuthType, AppCategory, + AppScopeProfilesItem, + AppScopeProfilesItemName, BackendClientOpts, ClientOpts, Component, @@ -160,7 +162,6 @@ triggers, usage, users, - workflows, ) from ._default_clients import DefaultAioHttpClient, DefaultAsyncHttpxClient from .actions import ActionsListRequestRegistry @@ -170,7 +171,6 @@ from .pipedream import AsyncPipedream, Pipedream from .triggers import TriggersListRequestRegistry from .version import __version__ - from .workflows.client import AsyncWorkflowsClient, WorkflowsClient _dynamic_imports: typing.Dict[str, str] = { "Account": ".types", "AccountCredentials": ".types", @@ -179,10 +179,11 @@ "App": ".types", "AppAuthType": ".types", "AppCategory": ".types", + "AppScopeProfilesItem": ".types", + "AppScopeProfilesItemName": ".types", "AppsListRequestSortDirection": ".apps", "AppsListRequestSortKey": ".apps", "AsyncPipedream": ".pipedream", - "AsyncWorkflowsClient": ".workflows.client", "BackendClientOpts": ".types", "BadRequestError": ".errors", "ClientOpts": ".types", @@ -321,7 +322,6 @@ "Webhook": ".types", "WebhookWithOptionalSigningKey": ".types", "WebhookWithSigningKey": ".types", - "WorkflowsClient": ".workflows.client", "__version__": ".version", "accounts": ".accounts", "actions": ".actions", @@ -338,7 +338,6 @@ "triggers": ".triggers", "usage": ".usage", "users": ".users", - "workflows": ".workflows", } @@ -371,10 +370,11 @@ def __dir__(): "App", "AppAuthType", "AppCategory", + "AppScopeProfilesItem", + "AppScopeProfilesItemName", "AppsListRequestSortDirection", "AppsListRequestSortKey", "AsyncPipedream", - "AsyncWorkflowsClient", "BackendClientOpts", "BadRequestError", "ClientOpts", @@ -513,7 +513,6 @@ def __dir__(): "Webhook", "WebhookWithOptionalSigningKey", "WebhookWithSigningKey", - "WorkflowsClient", "__version__", "accounts", "actions", @@ -530,5 +529,4 @@ def __dir__(): "triggers", "usage", "users", - "workflows", ] diff --git a/src/pipedream/actions/raw_client.py b/src/pipedream/actions/raw_client.py index 5de5c34..e9bcf94 100644 --- a/src/pipedream/actions/raw_client.py +++ b/src/pipedream/actions/raw_client.py @@ -283,9 +283,6 @@ def configure_prop( "prev_context": prev_context, "query": query, }, - headers={ - "content-type": "application/json", - }, request_options=request_options, omit=OMIT, ) @@ -373,9 +370,6 @@ def reload_props( ), "dynamic_props_id": dynamic_props_id, }, - headers={ - "content-type": "application/json", - }, request_options=request_options, omit=OMIT, ) @@ -758,9 +752,6 @@ async def configure_prop( "prev_context": prev_context, "query": query, }, - headers={ - "content-type": "application/json", - }, request_options=request_options, omit=OMIT, ) @@ -848,9 +839,6 @@ async def reload_props( ), "dynamic_props_id": dynamic_props_id, }, - headers={ - "content-type": "application/json", - }, request_options=request_options, omit=OMIT, ) diff --git a/src/pipedream/components/raw_client.py b/src/pipedream/components/raw_client.py index d9a7bc2..e122c9f 100644 --- a/src/pipedream/components/raw_client.py +++ b/src/pipedream/components/raw_client.py @@ -288,9 +288,6 @@ def configure_prop( "prev_context": prev_context, "query": query, }, - headers={ - "content-type": "application/json", - }, request_options=request_options, omit=OMIT, ) @@ -378,9 +375,6 @@ def reload_props( ), "dynamic_props_id": dynamic_props_id, }, - headers={ - "content-type": "application/json", - }, request_options=request_options, omit=OMIT, ) @@ -678,9 +672,6 @@ async def configure_prop( "prev_context": prev_context, "query": query, }, - headers={ - "content-type": "application/json", - }, request_options=request_options, omit=OMIT, ) @@ -768,9 +759,6 @@ async def reload_props( ), "dynamic_props_id": dynamic_props_id, }, - headers={ - "content-type": "application/json", - }, request_options=request_options, omit=OMIT, ) diff --git a/src/pipedream/core/client_wrapper.py b/src/pipedream/core/client_wrapper.py index 4bf948c..f4b8b8a 100644 --- a/src/pipedream/core/client_wrapper.py +++ b/src/pipedream/core/client_wrapper.py @@ -34,12 +34,12 @@ def get_headers(self) -> typing.Dict[str, str]: import platform headers: typing.Dict[str, str] = { - "User-Agent": "pipedream/2.0.4", + "User-Agent": "pipedream/2.0.5", "X-Fern-Language": "Python", "X-Fern-Runtime": f"python/{platform.python_version()}", "X-Fern-Platform": f"{platform.system().lower()}/{platform.release()}", "X-Fern-SDK-Name": "pipedream", - "X-Fern-SDK-Version": "2.0.4", + "X-Fern-SDK-Version": "2.0.5", **(self.get_custom_headers() or {}), } if self._project_environment is not None: diff --git a/src/pipedream/pipedream.py b/src/pipedream/pipedream.py index 53f491d..ed51914 100644 --- a/src/pipedream/pipedream.py +++ b/src/pipedream/pipedream.py @@ -1,131 +1,86 @@ +# This file was auto-generated by Fern from our API Definition. + import os import typing import httpx - from .client import AsyncClient, Client from .core.logging import LogConfig, Logger +from .environment import PipedreamEnvironment from .types.project_environment import ProjectEnvironment -from .workflows.client import AsyncWorkflowsClient, WorkflowsClient - -_PROD_BASE_URL = "https://api.pipedream.com" class Pipedream(Client): - + @typing.overload def __init__( self, *, - access_token: typing.Optional[str] = os.getenv("PIPEDREAM_ACCESS_TOKEN"), + base_url: typing.Optional[str] = None, + environment: PipedreamEnvironment = PipedreamEnvironment.PROD, + project_id: str, + project_environment: typing.Optional[ProjectEnvironment] = os.getenv("PIPEDREAM_PROJECT_ENVIRONMENT"), + headers: typing.Optional[typing.Dict[str, str]] = None, + timeout: typing.Optional[float] = None, + max_retries: typing.Optional[int] = None, + follow_redirects: typing.Optional[bool] = True, + httpx_client: typing.Optional[httpx.Client] = None, + logging: typing.Optional[typing.Union[LogConfig, Logger]] = None, client_id: typing.Optional[str] = os.getenv("PIPEDREAM_CLIENT_ID"), client_secret: typing.Optional[str] = os.getenv("PIPEDREAM_CLIENT_SECRET"), - project_id: typing.Optional[str] = os.getenv("PIPEDREAM_PROJECT_ID"), - project_environment: typing.Optional[ProjectEnvironment] = os.getenv( - "PIPEDREAM_PROJECT_ENVIRONMENT", - "production", - ), + ): ... + @typing.overload + def __init__( + self, + *, base_url: typing.Optional[str] = None, - workflow_domain: typing.Optional[str] = None, + environment: PipedreamEnvironment = PipedreamEnvironment.PROD, + project_id: str, + project_environment: typing.Optional[ProjectEnvironment] = os.getenv("PIPEDREAM_PROJECT_ENVIRONMENT"), headers: typing.Optional[typing.Dict[str, str]] = None, timeout: typing.Optional[float] = None, max_retries: typing.Optional[int] = None, follow_redirects: typing.Optional[bool] = True, httpx_client: typing.Optional[httpx.Client] = None, logging: typing.Optional[typing.Union[LogConfig, Logger]] = None, - ): - if not project_id: - raise ValueError("Project ID is required") - - resolved_base_url = base_url or os.environ.get("PIPEDREAM_BASE_URL") or _PROD_BASE_URL - resolved_workflow_domain = ( - workflow_domain or os.environ.get("PIPEDREAM_WORKFLOW_DOMAIN") or "m.pipedream.net" - ) - - common_kwargs: typing.Dict[str, typing.Any] = dict( - base_url=resolved_base_url, - project_id=project_id, - project_environment=project_environment, - headers=headers, - timeout=timeout, - max_retries=max_retries, - follow_redirects=follow_redirects, - httpx_client=httpx_client, - logging=logging, - ) - - if access_token: - super().__init__(token=(lambda: access_token), **common_kwargs) - else: - super().__init__(client_id=client_id, client_secret=client_secret, **common_kwargs) - - self.workflows = WorkflowsClient( - client_wrapper=self._client_wrapper, - workflow_domain=resolved_workflow_domain, - ) - - @property - def raw_access_token(self) -> typing.Optional[str]: - """ - Returns an access token that can be used to authenticate API requests - """ - return self._client_wrapper._get_token() + token: typing.Callable[[], str], + ): ... + def __init__(self, **kwargs: typing.Any): + super().__init__(**kwargs) class AsyncPipedream(AsyncClient): - + @typing.overload def __init__( self, *, - access_token: typing.Optional[str] = os.getenv("PIPEDREAM_ACCESS_TOKEN"), + base_url: typing.Optional[str] = None, + environment: PipedreamEnvironment = PipedreamEnvironment.PROD, + project_id: str, + project_environment: typing.Optional[ProjectEnvironment] = os.getenv("PIPEDREAM_PROJECT_ENVIRONMENT"), + headers: typing.Optional[typing.Dict[str, str]] = None, + timeout: typing.Optional[float] = None, + max_retries: typing.Optional[int] = None, + follow_redirects: typing.Optional[bool] = True, + httpx_client: typing.Optional[httpx.AsyncClient] = None, + logging: typing.Optional[typing.Union[LogConfig, Logger]] = None, client_id: typing.Optional[str] = os.getenv("PIPEDREAM_CLIENT_ID"), client_secret: typing.Optional[str] = os.getenv("PIPEDREAM_CLIENT_SECRET"), - project_id: typing.Optional[str] = os.getenv("PIPEDREAM_PROJECT_ID"), - project_environment: typing.Optional[ProjectEnvironment] = os.getenv( - "PIPEDREAM_PROJECT_ENVIRONMENT", - "production", - ), + ): ... + @typing.overload + def __init__( + self, + *, base_url: typing.Optional[str] = None, - workflow_domain: typing.Optional[str] = None, + environment: PipedreamEnvironment = PipedreamEnvironment.PROD, + project_id: str, + project_environment: typing.Optional[ProjectEnvironment] = os.getenv("PIPEDREAM_PROJECT_ENVIRONMENT"), headers: typing.Optional[typing.Dict[str, str]] = None, timeout: typing.Optional[float] = None, max_retries: typing.Optional[int] = None, follow_redirects: typing.Optional[bool] = True, httpx_client: typing.Optional[httpx.AsyncClient] = None, logging: typing.Optional[typing.Union[LogConfig, Logger]] = None, - ): - if not project_id: - raise ValueError("Project ID is required") - - resolved_base_url = base_url or os.environ.get("PIPEDREAM_BASE_URL") or _PROD_BASE_URL - resolved_workflow_domain = ( - workflow_domain or os.environ.get("PIPEDREAM_WORKFLOW_DOMAIN") or "m.pipedream.net" - ) - - common_kwargs: typing.Dict[str, typing.Any] = dict( - base_url=resolved_base_url, - project_id=project_id, - project_environment=project_environment, - headers=headers, - timeout=timeout, - max_retries=max_retries, - follow_redirects=follow_redirects, - httpx_client=httpx_client, - logging=logging, - ) - - if access_token: - super().__init__(token=(lambda: access_token), **common_kwargs) - else: - super().__init__(client_id=client_id, client_secret=client_secret, **common_kwargs) - - self.workflows = AsyncWorkflowsClient( - client_wrapper=self._client_wrapper, - workflow_domain=resolved_workflow_domain, - ) - - @property - def raw_access_token(self) -> typing.Optional[str]: - """ - Returns an access token that can be used to authenticate API requests - """ - return self._client_wrapper._get_token() + token: typing.Callable[[], str], + ): ... + def __init__(self, **kwargs: typing.Any): + super().__init__(**kwargs) diff --git a/src/pipedream/proxy/client.py b/src/pipedream/proxy/client.py index 1bff6ce..38bbf5c 100644 --- a/src/pipedream/proxy/client.py +++ b/src/pipedream/proxy/client.py @@ -1,85 +1,14 @@ -import base64 +# This file was auto-generated by Fern from our API Definition. + import typing -from collections.abc import AsyncIterator, Iterator -from urllib.parse import parse_qs, urlencode, urlparse, urlunparse 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 OMIT = typing.cast(typing.Any, ...) -_SyncResult = typing.Union[ProxyResponse, typing.Iterator[bytes], None] -_AsyncResult = typing.Union[ProxyResponse, typing.AsyncIterator[bytes], None] - - -def _add_params_to_url(url: str, params: typing.Dict[str, typing.Any]) -> str: - parsed = urlparse(url) - existing_params = parse_qs(parsed.query) - for key, value in params.items(): - existing_params[key] = value if isinstance(value, list) else [value] - new_query = urlencode(existing_params, doseq=True) - return urlunparse(parsed._replace(query=new_query)) - - -def _prepare_request( - url: str, - *, - headers: typing.Optional[typing.Dict[str, typing.Any]], - params: typing.Optional[typing.Dict[str, typing.Any]], -) -> typing.Tuple[str, RequestOptions]: - if params: - url = _add_params_to_url(url, params) - url_64 = base64.urlsafe_b64encode(url.encode()).decode() - downstream_headers = { - f"x-pd-proxy-{name}": value for name, value in (headers or {}).items() - } - return url_64, RequestOptions(additional_headers=downstream_headers) - - -def _consume_sync(ctx: typing.ContextManager) -> _SyncResult: - """ - Open the raw proxy context, peek at the response payload, and either - return the parsed ProxyResponse (fully-buffered JSON) or a generator that - streams the binary body and closes the underlying response when exhausted. - """ - raw = ctx.__enter__() - data = raw.data - if not isinstance(data, Iterator): - ctx.__exit__(None, None, None) - return data - - def _stream() -> typing.Iterator[bytes]: - try: - yield from data - finally: - ctx.__exit__(None, None, None) - - return _stream() - - -async def _consume_async(ctx: typing.AsyncContextManager) -> _AsyncResult: - """ - Async counterpart of `_consume_sync` — returns either a parsed - ProxyResponse or an async generator that streams the binary body. - """ - raw = await ctx.__aenter__() - data = raw.data - if not isinstance(data, AsyncIterator): - await ctx.__aexit__(None, None, None) - return data - - async def _stream() -> typing.AsyncIterator[bytes]: - try: - async for chunk in data: - yield chunk - finally: - await ctx.__aexit__(None, None, None) - - return _stream() - class ProxyClient: def __init__(self, *, client_wrapper: SyncClientWrapper): @@ -98,20 +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, - ) -> _SyncResult: + 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. + 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 @@ -119,137 +47,257 @@ 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 ------- - typing.Union[ProxyResponse, typing.Iterator[bytes], None] - ProxyResponse for JSON content, Iterator[bytes] for binary content, None for empty bodies. + typing.Iterator[bytes] + proxy request successful Examples -------- - from pipedream import Pipedream, PipedreamEnvironment + from pipedream import Pipedream client = Pipedream( - client_id="", - client_secret="", - environment=PipedreamEnvironment.PROD, + project_id="YOUR_PROJECT_ID", + client_id="YOUR_CLIENT_ID", + 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, request_options = _prepare_request(url, headers=headers, params=params) - return _consume_sync( - self._raw_client.get( - url_64, - external_user_id=external_user_id, - account_id=account_id, - request_options=request_options, - ) - ) + 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, - ) -> _SyncResult: - """ - Forward an authenticated POST request to an external API using an external user's account credentials. + request: typing.Dict[str, typing.Any], + request_options: typing.Optional[RequestOptions] = None, + ) -> typing.Iterator[bytes]: """ - url_64, request_options = _prepare_request(url, headers=headers, params=params) - return _consume_sync( - self._raw_client.post( - url_64, - external_user_id=external_user_id, - account_id=account_id, - request=body or {}, - request_options=request_options, - ) + Forward an authenticated POST request to an external API using an external user's account credentials + + Parameters + ---------- + url_64 : str + Base64-encoded target URL + + external_user_id : str + The external user ID for the proxy request + + account_id : str + The account ID to use for authentication + + request : typing.Dict[str, typing.Any] + + 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 + ------- + typing.Iterator[bytes] + proxy request successful + + Examples + -------- + from pipedream import Pipedream + + client = Pipedream( + project_id="YOUR_PROJECT_ID", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", ) + client.proxy.post( + url_64="url_64", + external_user_id="external_user_id", + account_id="account_id", + request={"string": {"key": "value"}}, + ) + """ + with self._raw_client.post( + url_64, + external_user_id=external_user_id, + account_id=account_id, + request=request, + request_options=request_options, + ) 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, - ) -> _SyncResult: - """ - Forward an authenticated PUT request to an external API using an external user's account credentials. + request: typing.Dict[str, typing.Any], + request_options: typing.Optional[RequestOptions] = None, + ) -> typing.Iterator[bytes]: """ - url_64, request_options = _prepare_request(url, headers=headers, params=params) - return _consume_sync( - self._raw_client.put( - url_64, - external_user_id=external_user_id, - account_id=account_id, - request=body or {}, - request_options=request_options, - ) + Forward an authenticated PUT request to an external API using an external user's account credentials + + Parameters + ---------- + url_64 : str + Base64-encoded target URL + + external_user_id : str + The external user ID for the proxy request + + account_id : str + The account ID to use for authentication + + request : typing.Dict[str, typing.Any] + + 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 + ------- + typing.Iterator[bytes] + proxy request successful + + Examples + -------- + from pipedream import Pipedream + + client = Pipedream( + project_id="YOUR_PROJECT_ID", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", ) + client.proxy.put( + url_64="url_64", + external_user_id="external_user_id", + account_id="account_id", + request={"string": {"key": "value"}}, + ) + """ + with self._raw_client.put( + url_64, + external_user_id=external_user_id, + account_id=account_id, + request=request, + request_options=request_options, + ) as r: + yield from r.data - def patch( + def delete( 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, - ) -> _SyncResult: + 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. - """ - url_64, request_options = _prepare_request(url, headers=headers, params=params) - return _consume_sync( - self._raw_client.patch( - url_64, - external_user_id=external_user_id, - account_id=account_id, - request=body or {}, - request_options=request_options, - ) + Forward an authenticated DELETE request to an external API using an external user's account credentials + + Parameters + ---------- + url_64 : str + Base64-encoded target URL + + external_user_id : str + The external user ID for the proxy request + + account_id : str + The account ID to use for authentication + + 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 + ------- + typing.Iterator[bytes] + proxy request successful + + Examples + -------- + from pipedream import Pipedream + + client = Pipedream( + project_id="YOUR_PROJECT_ID", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", ) + client.proxy.delete( + url_64="url_64", + external_user_id="external_user_id", + account_id="account_id", + ) + """ + 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 delete( + def patch( 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, - ) -> _SyncResult: - """ - Forward an authenticated DELETE request to an external API using an external user's account credentials. + request: typing.Dict[str, typing.Any], + request_options: typing.Optional[RequestOptions] = None, + ) -> typing.Iterator[bytes]: """ - url_64, request_options = _prepare_request(url, headers=headers, params=params) - return _consume_sync( - self._raw_client.delete( - url_64, - external_user_id=external_user_id, - account_id=account_id, - request_options=request_options, - ) + Forward an authenticated PATCH request to an external API using an external user's account credentials + + Parameters + ---------- + url_64 : str + Base64-encoded target URL + + external_user_id : str + The external user ID for the proxy request + + account_id : str + The account ID to use for authentication + + request : typing.Dict[str, typing.Any] + + 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 + ------- + typing.Iterator[bytes] + proxy request successful + + Examples + -------- + from pipedream import Pipedream + + client = Pipedream( + project_id="YOUR_PROJECT_ID", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", ) + client.proxy.patch( + url_64="url_64", + external_user_id="external_user_id", + account_id="account_id", + request={"string": {"key": "value"}}, + ) + """ + with self._raw_client.patch( + url_64, + external_user_id=external_user_id, + account_id=account_id, + request=request, + request_options=request_options, + ) as r: + yield from r.data class AsyncProxyClient: @@ -269,116 +317,319 @@ 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, - ) -> _AsyncResult: + 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. - """ - url_64, request_options = _prepare_request(url, headers=headers, params=params) - return await _consume_async( - self._raw_client.get( - url_64, - external_user_id=external_user_id, - account_id=account_id, - request_options=request_options, - ) + Forward an authenticated GET request to an external API using an external user's account credentials + + Parameters + ---------- + url_64 : str + Base64-encoded target URL + + external_user_id : str + The external user ID for the proxy request + + account_id : str + The account ID to use for authentication + + 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 + ------- + typing.AsyncIterator[bytes] + proxy request successful + + Examples + -------- + import asyncio + + from pipedream import AsyncPipedream + + client = AsyncPipedream( + project_id="YOUR_PROJECT_ID", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", ) + + async def main() -> None: + await client.proxy.get( + url_64="url_64", + external_user_id="external_user_id", + account_id="account_id", + ) + + + asyncio.run(main()) + """ + 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, - ) -> _AsyncResult: - """ - Forward an authenticated POST request to an external API using an external user's account credentials. + request: typing.Dict[str, typing.Any], + request_options: typing.Optional[RequestOptions] = None, + ) -> typing.AsyncIterator[bytes]: """ - url_64, request_options = _prepare_request(url, headers=headers, params=params) - return await _consume_async( - self._raw_client.post( - url_64, - external_user_id=external_user_id, - account_id=account_id, - request=body or {}, - request_options=request_options, - ) + Forward an authenticated POST request to an external API using an external user's account credentials + + Parameters + ---------- + url_64 : str + Base64-encoded target URL + + external_user_id : str + The external user ID for the proxy request + + account_id : str + The account ID to use for authentication + + request : typing.Dict[str, typing.Any] + + 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 + ------- + typing.AsyncIterator[bytes] + proxy request successful + + Examples + -------- + import asyncio + + from pipedream import AsyncPipedream + + client = AsyncPipedream( + project_id="YOUR_PROJECT_ID", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", ) + + async def main() -> None: + await client.proxy.post( + url_64="url_64", + external_user_id="external_user_id", + account_id="account_id", + request={"string": {"key": "value"}}, + ) + + + asyncio.run(main()) + """ + async with self._raw_client.post( + url_64, + external_user_id=external_user_id, + account_id=account_id, + request=request, + request_options=request_options, + ) 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, - ) -> _AsyncResult: - """ - Forward an authenticated PUT request to an external API using an external user's account credentials. + request: typing.Dict[str, typing.Any], + request_options: typing.Optional[RequestOptions] = None, + ) -> typing.AsyncIterator[bytes]: """ - url_64, request_options = _prepare_request(url, headers=headers, params=params) - return await _consume_async( - self._raw_client.put( - url_64, - external_user_id=external_user_id, - account_id=account_id, - request=body or {}, - request_options=request_options, - ) + Forward an authenticated PUT request to an external API using an external user's account credentials + + Parameters + ---------- + url_64 : str + Base64-encoded target URL + + external_user_id : str + The external user ID for the proxy request + + account_id : str + The account ID to use for authentication + + request : typing.Dict[str, typing.Any] + + 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 + ------- + typing.AsyncIterator[bytes] + proxy request successful + + Examples + -------- + import asyncio + + from pipedream import AsyncPipedream + + client = AsyncPipedream( + project_id="YOUR_PROJECT_ID", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", ) - async def patch( + + async def main() -> None: + await client.proxy.put( + url_64="url_64", + external_user_id="external_user_id", + account_id="account_id", + request={"string": {"key": "value"}}, + ) + + + asyncio.run(main()) + """ + async with self._raw_client.put( + url_64, + external_user_id=external_user_id, + account_id=account_id, + request=request, + request_options=request_options, + ) 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, - body: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = None, - params: typing.Optional[typing.Dict[str, typing.Any]] = None, - ) -> _AsyncResult: + 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. - """ - url_64, request_options = _prepare_request(url, headers=headers, params=params) - return await _consume_async( - self._raw_client.patch( - url_64, - external_user_id=external_user_id, - account_id=account_id, - request=body or {}, - request_options=request_options, - ) + Forward an authenticated DELETE request to an external API using an external user's account credentials + + Parameters + ---------- + url_64 : str + Base64-encoded target URL + + external_user_id : str + The external user ID for the proxy request + + account_id : str + The account ID to use for authentication + + 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 + ------- + typing.AsyncIterator[bytes] + proxy request successful + + Examples + -------- + import asyncio + + from pipedream import AsyncPipedream + + client = AsyncPipedream( + project_id="YOUR_PROJECT_ID", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", ) - async def delete( + + async def main() -> None: + await client.proxy.delete( + url_64="url_64", + external_user_id="external_user_id", + account_id="account_id", + ) + + + asyncio.run(main()) + """ + 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, - params: typing.Optional[typing.Dict[str, typing.Any]] = None, - ) -> _AsyncResult: - """ - Forward an authenticated DELETE request to an external API using an external user's account credentials. + request: typing.Dict[str, typing.Any], + request_options: typing.Optional[RequestOptions] = None, + ) -> typing.AsyncIterator[bytes]: """ - url_64, request_options = _prepare_request(url, headers=headers, params=params) - return await _consume_async( - self._raw_client.delete( - url_64, - external_user_id=external_user_id, - account_id=account_id, - request_options=request_options, - ) + Forward an authenticated PATCH request to an external API using an external user's account credentials + + Parameters + ---------- + url_64 : str + Base64-encoded target URL + + external_user_id : str + The external user ID for the proxy request + + account_id : str + The account ID to use for authentication + + request : typing.Dict[str, typing.Any] + + 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 + ------- + typing.AsyncIterator[bytes] + proxy request successful + + Examples + -------- + import asyncio + + from pipedream import AsyncPipedream + + client = AsyncPipedream( + project_id="YOUR_PROJECT_ID", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", ) + + + async def main() -> None: + await client.proxy.patch( + url_64="url_64", + external_user_id="external_user_id", + account_id="account_id", + request={"string": {"key": "value"}}, + ) + + + asyncio.run(main()) + """ + async with self._raw_client.patch( + url_64, + external_user_id=external_user_id, + account_id=account_id, + request=request, + request_options=request_options, + ) 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 d9fc875..1af958d 100644 --- a/src/pipedream/proxy/raw_client.py +++ b/src/pipedream/proxy/raw_client.py @@ -1,9 +1,9 @@ +# This file was auto-generated by Fern from our API Definition. + import contextlib import typing from json.decoder import JSONDecodeError -from pydantic import ValidationError - from ..core.api_error import ApiError from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ..core.http_response import AsyncHttpResponse, HttpResponse @@ -12,25 +12,11 @@ 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 +from pydantic import ValidationError # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) -_ProxyData = typing.Optional[typing.Union[ProxyResponse, typing.Iterator[bytes]]] -_AsyncProxyData = typing.Optional[typing.Union[ProxyResponse, typing.AsyncIterator[bytes]]] - - -def _is_json_content_type(content_type: str) -> bool: - return "application/json" in content_type or not content_type - - -def _decode_error_body(_response: typing.Any) -> typing.Any: - error_content_type = _response.headers.get("content-type", "").lower() - if "application/json" in error_content_type: - return _response.json() - return _response.text - class RawProxyClient: def __init__(self, *, client_wrapper: SyncClientWrapper): @@ -44,9 +30,9 @@ def get( external_user_id: str, account_id: str, request_options: typing.Optional[RequestOptions] = None, - ) -> typing.Iterator[HttpResponse[_ProxyData]]: + ) -> typing.Iterator[HttpResponse[typing.Iterator[bytes]]]: """ - Forward an authenticated GET request to an external API using an external user's account credentials. + Forward an authenticated GET request to an external API using an external user's account credentials Parameters ---------- @@ -64,7 +50,7 @@ def get( Returns ------- - typing.Iterator[HttpResponse[typing.Optional[typing.Union[ProxyResponse, typing.Iterator[bytes]]]]] + typing.Iterator[HttpResponse[typing.Iterator[bytes]]] proxy request successful """ with self._client_wrapper.httpx_client.stream( @@ -76,7 +62,41 @@ def get( }, request_options=request_options, ) as _response: - yield _handle_sync_response(_response, request_options) + + 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.Any, + parse_obj_as( + type_=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 + ) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, + headers=dict(_response.headers), + body=_response.json(), + cause=e, + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + yield _stream() @contextlib.contextmanager def post( @@ -85,11 +105,32 @@ def post( *, external_user_id: str, account_id: str, - request: typing.Dict[str, typing.Optional[typing.Any]], + request: typing.Dict[str, typing.Any], request_options: typing.Optional[RequestOptions] = None, - ) -> typing.Iterator[HttpResponse[_ProxyData]]: + ) -> typing.Iterator[HttpResponse[typing.Iterator[bytes]]]: """ - Forward an authenticated POST request to an external API using an external user's account credentials. + Forward an authenticated POST request to an external API using an external user's account credentials + + Parameters + ---------- + url_64 : str + Base64-encoded target URL + + external_user_id : str + The external user ID for the proxy request + + account_id : str + The account ID to use for authentication + + request : typing.Dict[str, typing.Any] + + 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 + ------- + typing.Iterator[HttpResponse[typing.Iterator[bytes]]] + proxy request successful """ with self._client_wrapper.httpx_client.stream( f"v1/connect/{encode_path_param(self._client_wrapper._project_id)}/proxy/{encode_path_param(url_64)}", @@ -99,11 +140,47 @@ def post( "account_id": account_id, }, json=request, - headers={"content-type": "application/json"}, + headers={ + "content-type": "application/json", + }, request_options=request_options, omit=OMIT, ) as _response: - yield _handle_sync_response(_response, request_options) + + 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.Any, + parse_obj_as( + type_=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 + ) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, + headers=dict(_response.headers), + body=_response.json(), + cause=e, + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + yield _stream() @contextlib.contextmanager def put( @@ -112,11 +189,32 @@ def put( *, external_user_id: str, account_id: str, - request: typing.Dict[str, typing.Optional[typing.Any]], + request: typing.Dict[str, typing.Any], request_options: typing.Optional[RequestOptions] = None, - ) -> typing.Iterator[HttpResponse[_ProxyData]]: + ) -> typing.Iterator[HttpResponse[typing.Iterator[bytes]]]: """ - Forward an authenticated PUT request to an external API using an external user's account credentials. + Forward an authenticated PUT request to an external API using an external user's account credentials + + Parameters + ---------- + url_64 : str + Base64-encoded target URL + + external_user_id : str + The external user ID for the proxy request + + account_id : str + The account ID to use for authentication + + request : typing.Dict[str, typing.Any] + + 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 + ------- + typing.Iterator[HttpResponse[typing.Iterator[bytes]]] + proxy request successful """ with self._client_wrapper.httpx_client.stream( f"v1/connect/{encode_path_param(self._client_wrapper._project_id)}/proxy/{encode_path_param(url_64)}", @@ -126,61 +224,207 @@ def put( "account_id": account_id, }, json=request, - headers={"content-type": "application/json"}, + headers={ + "content-type": "application/json", + }, request_options=request_options, omit=OMIT, ) as _response: - yield _handle_sync_response(_response, request_options) + + 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.Any, + parse_obj_as( + type_=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 + ) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, + headers=dict(_response.headers), + body=_response.json(), + cause=e, + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + yield _stream() @contextlib.contextmanager - def patch( + def delete( self, url_64: str, *, external_user_id: str, account_id: str, - request: typing.Dict[str, typing.Optional[typing.Any]], request_options: typing.Optional[RequestOptions] = None, - ) -> typing.Iterator[HttpResponse[_ProxyData]]: + ) -> typing.Iterator[HttpResponse[typing.Iterator[bytes]]]: """ - Forward an authenticated PATCH request to an external API using an external user's account credentials. + Forward an authenticated DELETE request to an external API using an external user's account credentials + + Parameters + ---------- + url_64 : str + Base64-encoded target URL + + external_user_id : str + The external user ID for the proxy request + + account_id : str + The account ID to use for authentication + + 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 + ------- + typing.Iterator[HttpResponse[typing.Iterator[bytes]]] + proxy request successful """ with self._client_wrapper.httpx_client.stream( f"v1/connect/{encode_path_param(self._client_wrapper._project_id)}/proxy/{encode_path_param(url_64)}", - method="PATCH", + method="DELETE", params={ "external_user_id": external_user_id, "account_id": account_id, }, - json=request, - headers={"content-type": "application/json"}, request_options=request_options, - omit=OMIT, ) as _response: - yield _handle_sync_response(_response, request_options) + + 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.Any, + parse_obj_as( + type_=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 + ) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, + headers=dict(_response.headers), + body=_response.json(), + cause=e, + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + yield _stream() @contextlib.contextmanager - def delete( + def patch( self, url_64: str, *, external_user_id: str, account_id: str, + request: typing.Dict[str, typing.Any], request_options: typing.Optional[RequestOptions] = None, - ) -> typing.Iterator[HttpResponse[_ProxyData]]: + ) -> typing.Iterator[HttpResponse[typing.Iterator[bytes]]]: """ - Forward an authenticated DELETE request to an external API using an external user's account credentials. + Forward an authenticated PATCH request to an external API using an external user's account credentials + + Parameters + ---------- + url_64 : str + Base64-encoded target URL + + external_user_id : str + The external user ID for the proxy request + + account_id : str + The account ID to use for authentication + + request : typing.Dict[str, typing.Any] + + 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 + ------- + typing.Iterator[HttpResponse[typing.Iterator[bytes]]] + proxy request successful """ with self._client_wrapper.httpx_client.stream( f"v1/connect/{encode_path_param(self._client_wrapper._project_id)}/proxy/{encode_path_param(url_64)}", - method="DELETE", + method="PATCH", params={ "external_user_id": external_user_id, "account_id": account_id, }, + json=request, + headers={ + "content-type": "application/json", + }, request_options=request_options, + omit=OMIT, ) as _response: - yield _handle_sync_response(_response, request_options) + + 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.Any, + parse_obj_as( + type_=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 + ) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, + headers=dict(_response.headers), + body=_response.json(), + cause=e, + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + yield _stream() class AsyncRawProxyClient: @@ -195,9 +439,28 @@ async def get( external_user_id: str, account_id: str, request_options: typing.Optional[RequestOptions] = None, - ) -> typing.AsyncIterator[AsyncHttpResponse[_AsyncProxyData]]: + ) -> typing.AsyncIterator[AsyncHttpResponse[typing.AsyncIterator[bytes]]]: """ - Forward an authenticated GET request to an external API using an external user's account credentials. + Forward an authenticated GET request to an external API using an external user's account credentials + + Parameters + ---------- + url_64 : str + Base64-encoded target URL + + external_user_id : str + The external user ID for the proxy request + + account_id : str + The account ID to use for authentication + + 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 + ------- + typing.AsyncIterator[AsyncHttpResponse[typing.AsyncIterator[bytes]]] + proxy request successful """ async with self._client_wrapper.httpx_client.stream( f"v1/connect/{encode_path_param(self._client_wrapper._project_id)}/proxy/{encode_path_param(url_64)}", @@ -208,7 +471,42 @@ async def get( }, request_options=request_options, ) as _response: - yield await _handle_async_response(_response, request_options) + + 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.Any, + parse_obj_as( + type_=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 + ) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, + headers=dict(_response.headers), + body=_response.json(), + cause=e, + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + yield await _stream() @contextlib.asynccontextmanager async def post( @@ -217,11 +515,32 @@ async def post( *, external_user_id: str, account_id: str, - request: typing.Dict[str, typing.Optional[typing.Any]], + request: typing.Dict[str, typing.Any], request_options: typing.Optional[RequestOptions] = None, - ) -> typing.AsyncIterator[AsyncHttpResponse[_AsyncProxyData]]: + ) -> typing.AsyncIterator[AsyncHttpResponse[typing.AsyncIterator[bytes]]]: """ - Forward an authenticated POST request to an external API using an external user's account credentials. + Forward an authenticated POST request to an external API using an external user's account credentials + + Parameters + ---------- + url_64 : str + Base64-encoded target URL + + external_user_id : str + The external user ID for the proxy request + + account_id : str + The account ID to use for authentication + + request : typing.Dict[str, typing.Any] + + 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 + ------- + typing.AsyncIterator[AsyncHttpResponse[typing.AsyncIterator[bytes]]] + proxy request successful """ async with self._client_wrapper.httpx_client.stream( f"v1/connect/{encode_path_param(self._client_wrapper._project_id)}/proxy/{encode_path_param(url_64)}", @@ -231,11 +550,48 @@ async def post( "account_id": account_id, }, json=request, - headers={"content-type": "application/json"}, + headers={ + "content-type": "application/json", + }, request_options=request_options, omit=OMIT, ) as _response: - yield await _handle_async_response(_response, request_options) + + 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.Any, + parse_obj_as( + type_=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 + ) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, + headers=dict(_response.headers), + body=_response.json(), + cause=e, + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + yield await _stream() @contextlib.asynccontextmanager async def put( @@ -244,11 +600,32 @@ async def put( *, external_user_id: str, account_id: str, - request: typing.Dict[str, typing.Optional[typing.Any]], + request: typing.Dict[str, typing.Any], request_options: typing.Optional[RequestOptions] = None, - ) -> typing.AsyncIterator[AsyncHttpResponse[_AsyncProxyData]]: + ) -> typing.AsyncIterator[AsyncHttpResponse[typing.AsyncIterator[bytes]]]: """ - Forward an authenticated PUT request to an external API using an external user's account credentials. + Forward an authenticated PUT request to an external API using an external user's account credentials + + Parameters + ---------- + url_64 : str + Base64-encoded target URL + + external_user_id : str + The external user ID for the proxy request + + account_id : str + The account ID to use for authentication + + request : typing.Dict[str, typing.Any] + + 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 + ------- + typing.AsyncIterator[AsyncHttpResponse[typing.AsyncIterator[bytes]]] + proxy request successful """ async with self._client_wrapper.httpx_client.stream( f"v1/connect/{encode_path_param(self._client_wrapper._project_id)}/proxy/{encode_path_param(url_64)}", @@ -258,170 +635,207 @@ async def put( "account_id": account_id, }, json=request, - headers={"content-type": "application/json"}, + headers={ + "content-type": "application/json", + }, request_options=request_options, omit=OMIT, ) as _response: - yield await _handle_async_response(_response, request_options) + + 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.Any, + parse_obj_as( + type_=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 + ) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, + headers=dict(_response.headers), + body=_response.json(), + cause=e, + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + yield await _stream() @contextlib.asynccontextmanager - async def patch( + async def delete( self, url_64: str, *, external_user_id: str, account_id: str, - request: typing.Dict[str, typing.Optional[typing.Any]], request_options: typing.Optional[RequestOptions] = None, - ) -> typing.AsyncIterator[AsyncHttpResponse[_AsyncProxyData]]: + ) -> typing.AsyncIterator[AsyncHttpResponse[typing.AsyncIterator[bytes]]]: """ - Forward an authenticated PATCH request to an external API using an external user's account credentials. + Forward an authenticated DELETE request to an external API using an external user's account credentials + + Parameters + ---------- + url_64 : str + Base64-encoded target URL + + external_user_id : str + The external user ID for the proxy request + + account_id : str + The account ID to use for authentication + + 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 + ------- + typing.AsyncIterator[AsyncHttpResponse[typing.AsyncIterator[bytes]]] + proxy request successful """ async with self._client_wrapper.httpx_client.stream( f"v1/connect/{encode_path_param(self._client_wrapper._project_id)}/proxy/{encode_path_param(url_64)}", - method="PATCH", + method="DELETE", params={ "external_user_id": external_user_id, "account_id": account_id, }, - json=request, - headers={"content-type": "application/json"}, request_options=request_options, - omit=OMIT, ) as _response: - yield await _handle_async_response(_response, request_options) + + 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.Any, + parse_obj_as( + type_=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 + ) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, + headers=dict(_response.headers), + body=_response.json(), + cause=e, + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + yield await _stream() @contextlib.asynccontextmanager - async def delete( + async def patch( self, url_64: str, *, external_user_id: str, account_id: str, + request: typing.Dict[str, typing.Any], request_options: typing.Optional[RequestOptions] = None, - ) -> typing.AsyncIterator[AsyncHttpResponse[_AsyncProxyData]]: + ) -> typing.AsyncIterator[AsyncHttpResponse[typing.AsyncIterator[bytes]]]: """ - Forward an authenticated DELETE request to an external API using an external user's account credentials. + Forward an authenticated PATCH request to an external API using an external user's account credentials + + Parameters + ---------- + url_64 : str + Base64-encoded target URL + + external_user_id : str + The external user ID for the proxy request + + account_id : str + The account ID to use for authentication + + request : typing.Dict[str, typing.Any] + + 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 + ------- + typing.AsyncIterator[AsyncHttpResponse[typing.AsyncIterator[bytes]]] + proxy request successful """ async with self._client_wrapper.httpx_client.stream( f"v1/connect/{encode_path_param(self._client_wrapper._project_id)}/proxy/{encode_path_param(url_64)}", - method="DELETE", + method="PATCH", params={ "external_user_id": external_user_id, "account_id": account_id, }, + json=request, + headers={ + "content-type": "application/json", + }, request_options=request_options, + omit=OMIT, ) as _response: - yield await _handle_async_response(_response, request_options) - - -def _handle_sync_response( - _response: typing.Any, request_options: typing.Optional[RequestOptions] -) -> HttpResponse[_ProxyData]: - try: - if 200 <= _response.status_code < 300: - content_type = _response.headers.get("content-type", "").lower() - if _is_json_content_type(content_type): - _response.read() - if not _response.text.strip(): - return HttpResponse(response=_response, data=None) - _data = typing.cast( - ProxyResponse, - parse_obj_as( - type_=ProxyResponse, # type: ignore - object_=_response.json(), - ), - ) - return HttpResponse(response=_response, data=_data) - _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_=_decode_error_body(_response), - ), - ), - ) - _response_body = _decode_error_body(_response) - except JSONDecodeError: - raise ApiError( - status_code=_response.status_code, - headers=dict(_response.headers), - body=_response.text, - ) - except ValidationError as e: - raise ParsingError( - status_code=_response.status_code, - headers=dict(_response.headers), - body=_response.json(), - cause=e, - ) - raise ApiError( - status_code=_response.status_code, - headers=dict(_response.headers), - body=_response_body, - ) - - -async def _handle_async_response( - _response: typing.Any, request_options: typing.Optional[RequestOptions] -) -> AsyncHttpResponse[_AsyncProxyData]: - try: - if 200 <= _response.status_code < 300: - content_type = _response.headers.get("content-type", "").lower() - if _is_json_content_type(content_type): - await _response.aread() - if not _response.text.strip(): - return AsyncHttpResponse(response=_response, data=None) - _data = typing.cast( - ProxyResponse, - parse_obj_as( - type_=ProxyResponse, # type: ignore - object_=_response.json(), - ), - ) - return AsyncHttpResponse(response=_response, data=_data) - _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_=_decode_error_body(_response), - ), - ), - ) - _response_body = _decode_error_body(_response) - except JSONDecodeError: - raise ApiError( - status_code=_response.status_code, - headers=dict(_response.headers), - body=_response.text, - ) - except ValidationError as e: - raise ParsingError( - status_code=_response.status_code, - headers=dict(_response.headers), - body=_response.json(), - cause=e, - ) - raise ApiError( - status_code=_response.status_code, - headers=dict(_response.headers), - body=_response_body, - ) + + 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.Any, + parse_obj_as( + type_=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 + ) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, + headers=dict(_response.headers), + body=_response.json(), + cause=e, + ) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + yield await _stream() diff --git a/src/pipedream/triggers/raw_client.py b/src/pipedream/triggers/raw_client.py index 5e0ebd3..7b26a45 100644 --- a/src/pipedream/triggers/raw_client.py +++ b/src/pipedream/triggers/raw_client.py @@ -283,9 +283,6 @@ def configure_prop( "prev_context": prev_context, "query": query, }, - headers={ - "content-type": "application/json", - }, request_options=request_options, omit=OMIT, ) @@ -373,9 +370,6 @@ def reload_props( ), "dynamic_props_id": dynamic_props_id, }, - headers={ - "content-type": "application/json", - }, request_options=request_options, omit=OMIT, ) @@ -768,9 +762,6 @@ async def configure_prop( "prev_context": prev_context, "query": query, }, - headers={ - "content-type": "application/json", - }, request_options=request_options, omit=OMIT, ) @@ -858,9 +849,6 @@ async def reload_props( ), "dynamic_props_id": dynamic_props_id, }, - headers={ - "content-type": "application/json", - }, request_options=request_options, omit=OMIT, ) diff --git a/src/pipedream/workflows/__init__.py b/src/pipedream/workflows/__init__.py deleted file mode 100644 index 395047f..0000000 --- a/src/pipedream/workflows/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -# This file was auto-generated by Fern from our API Definition. - -from .client import AsyncWorkflowsClient, WorkflowsClient - -__all__ = ["AsyncWorkflowsClient", "WorkflowsClient"] \ No newline at end of file diff --git a/src/pipedream/workflows/client.py b/src/pipedream/workflows/client.py deleted file mode 100644 index 1f31604..0000000 --- a/src/pipedream/workflows/client.py +++ /dev/null @@ -1,271 +0,0 @@ -import enum -import re -import typing - -import httpx - -from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper -from ..core.request_options import RequestOptions - -# this is used as the default value for optional parameters -OMIT = typing.cast(typing.Any, ...) - -_DEFAULT_WORKFLOW_DOMAIN = "m.pipedream.net" -_ENDPOINT_ID_RE = re.compile(r"^e(n|o)[a-z0-9-]+$") - - -class HTTPAuthType(enum.Enum): - """Authentication types for workflow invocation.""" - - NONE = "none" - STATIC_BEARER = "static_bearer_token" - OAUTH = "oauth" - - -def _is_endpoint_id(url_or_endpoint: str) -> bool: - return bool(_ENDPOINT_ID_RE.match(url_or_endpoint)) - - -def _build_workflow_url(url_or_endpoint: str, *, workflow_domain: str) -> str: - if not url_or_endpoint: - raise ValueError("URL or endpoint ID is required") - - if url_or_endpoint.startswith(("http://", "https://")): - return url_or_endpoint - - if "." in url_or_endpoint and not _is_endpoint_id(url_or_endpoint): - return f"https://{url_or_endpoint}" - - if not _is_endpoint_id(url_or_endpoint): - raise ValueError(f"Invalid endpoint ID format: {url_or_endpoint}") - - return f"https://{url_or_endpoint}.{workflow_domain}" - - -def _prepare_headers( - headers: typing.Optional[typing.Dict[str, str]], - auth_type: HTTPAuthType, -) -> typing.Dict[str, str]: - request_headers = dict(headers) if headers else {} - if auth_type == HTTPAuthType.NONE: - # Suppress the default bearer token added by the client wrapper. - request_headers["Authorization"] = "" - return request_headers - - -def _add_external_user_id_header( - headers: typing.Optional[typing.Dict[str, str]], - external_user_id: str, -) -> typing.Dict[str, str]: - if not external_user_id: - raise ValueError("external_user_id is required") - request_headers = dict(headers) if headers else {} - request_headers["X-PD-External-User-ID"] = external_user_id - return request_headers - - -class WorkflowsClient: - def __init__( - self, - *, - client_wrapper: SyncClientWrapper, - workflow_domain: str = _DEFAULT_WORKFLOW_DOMAIN, - ): - self._client_wrapper = client_wrapper - self._workflow_domain = workflow_domain - - def invoke( - self, - url_or_endpoint: str, - *, - method: str = "POST", - body: typing.Optional[typing.Any] = None, - headers: typing.Optional[typing.Dict[str, str]] = None, - auth_type: HTTPAuthType = HTTPAuthType.NONE, - request_options: typing.Optional[RequestOptions] = None, - ) -> httpx.Response: - """ - Invoke a workflow via its HTTP interface URL or endpoint ID. - - Parameters - ---------- - url_or_endpoint : str - The full URL of the workflow's HTTP interface or the endpoint ID. - - method : str - HTTP method to use (default: "POST"). - - body : typing.Optional[typing.Any] - Request body. Dict/list values are serialized as JSON; other types are sent as raw form data. - - headers : typing.Optional[typing.Dict[str, str]] - Additional HTTP headers to include. - - auth_type : HTTPAuthType - Authentication mode (default: HTTPAuthType.NONE). - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - httpx.Response - Response returned by the invoked workflow. - - Examples - -------- - from pipedream import Pipedream, PipedreamEnvironment - from pipedream.workflows.client import HTTPAuthType - - client = Pipedream( - client_id="", - client_secret="", - environment=PipedreamEnvironment.PROD, - ) - response = client.workflows.invoke( - url_or_endpoint="https://your-workflow.m.pipedream.net", - method="POST", - body={"key": "value"}, - headers={"Content-Type": "application/json"}, - auth_type=HTTPAuthType.NONE, - ) - """ - workflow_url = _build_workflow_url(url_or_endpoint, workflow_domain=self._workflow_domain) - request_headers = _prepare_headers(headers, auth_type) - - response = self._client_wrapper.httpx_client.request( - workflow_url, - method=method, - data=body, - json=body, - headers=request_headers, - request_options=request_options, - ) - response.raise_for_status() - return response - - def invoke_for_external_user( - self, - url_or_endpoint: str, - *, - external_user_id: str, - method: str = "POST", - body: typing.Optional[typing.Any] = None, - headers: typing.Optional[typing.Dict[str, str]] = None, - request_options: typing.Optional[RequestOptions] = None, - ) -> httpx.Response: - """ - Invoke a workflow on behalf of a Pipedream Connect end-user. - - Forces OAuth authentication and adds the `X-PD-External-User-ID` header. - - Parameters - ---------- - url_or_endpoint : str - The full URL of the workflow's HTTP interface or the endpoint ID. - - external_user_id : str - The external user ID for whom the workflow is being invoked. - - method : str - HTTP method to use (default: "POST"). - - body : typing.Optional[typing.Any] - Request body. Dict/list values are serialized as JSON; other types are sent as raw form data. - - headers : typing.Optional[typing.Dict[str, str]] - Additional HTTP headers to include. - - request_options : typing.Optional[RequestOptions] - Request-specific configuration. - - Returns - ------- - httpx.Response - Response returned by the invoked workflow. - - Examples - -------- - from pipedream import Pipedream, PipedreamEnvironment - - client = Pipedream( - client_id="", - client_secret="", - environment=PipedreamEnvironment.PROD, - ) - response = client.workflows.invoke_for_external_user( - url_or_endpoint="en2r1n8a98np7", - external_user_id="user_123", - method="POST", - body={"message": "Hello from external user"}, - headers={"Content-Type": "application/json"}, - ) - """ - return self.invoke( - url_or_endpoint, - method=method, - body=body, - headers=_add_external_user_id_header(headers, external_user_id), - auth_type=HTTPAuthType.OAUTH, - request_options=request_options, - ) - - -class AsyncWorkflowsClient: - def __init__( - self, - *, - client_wrapper: AsyncClientWrapper, - workflow_domain: str = _DEFAULT_WORKFLOW_DOMAIN, - ): - self._client_wrapper = client_wrapper - self._workflow_domain = workflow_domain - - async def invoke( - self, - url_or_endpoint: str, - *, - method: str = "POST", - body: typing.Optional[typing.Any] = None, - headers: typing.Optional[typing.Dict[str, str]] = None, - auth_type: HTTPAuthType = HTTPAuthType.NONE, - request_options: typing.Optional[RequestOptions] = None, - ) -> httpx.Response: - """ - Async counterpart of `WorkflowsClient.invoke`. - """ - workflow_url = _build_workflow_url(url_or_endpoint, workflow_domain=self._workflow_domain) - request_headers = _prepare_headers(headers, auth_type) - - response = await self._client_wrapper.httpx_client.request( - workflow_url, - method=method, - data=body, - json=body, - headers=request_headers, - request_options=request_options, - ) - response.raise_for_status() - return response - - async def invoke_for_external_user( - self, - url_or_endpoint: str, - *, - external_user_id: str, - method: str = "POST", - body: typing.Optional[typing.Any] = None, - headers: typing.Optional[typing.Dict[str, str]] = None, - request_options: typing.Optional[RequestOptions] = None, - ) -> httpx.Response: - """ - Async counterpart of `WorkflowsClient.invoke_for_external_user`. - """ - return await self.invoke( - url_or_endpoint, - method=method, - body=body, - headers=_add_external_user_id_header(headers, external_user_id), - auth_type=HTTPAuthType.OAUTH, - request_options=request_options, - ) From 83158b9e678d2ca5bfb721de31ea46bc0bb340e4 Mon Sep 17 00:00:00 2001 From: Jay Vercellone Date: Tue, 26 May 2026 15:55:20 -0700 Subject: [PATCH 2/2] Custom changes --- .github/workflows/ci.yml | 13 +- reference.md | 894 +++++++++++++++------------- src/pipedream/__init__.py | 8 + src/pipedream/pipedream.py | 143 +++-- src/pipedream/proxy/client.py | 741 ++++++++--------------- src/pipedream/proxy/raw_client.py | 782 ++++++------------------ src/pipedream/workflows/__init__.py | 5 + src/pipedream/workflows/client.py | 271 +++++++++ 8 files changed, 1305 insertions(+), 1552 deletions(-) create mode 100644 src/pipedream/workflows/__init__.py create mode 100644 src/pipedream/workflows/client.py diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9ab0a27..7fd6ffd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,6 +50,8 @@ jobs: needs: [compile, test] if: github.event_name == 'push' && contains(github.ref, 'refs/tags/') runs-on: ubuntu-latest + permissions: + id-token: write steps: - name: Checkout repo uses: actions/checkout@v4 @@ -62,10 +64,7 @@ jobs: curl -sSL https://install.python-poetry.org | python - -y --version 1.5.1 - name: Install dependencies run: poetry install - - name: Publish to pypi - run: | - poetry config repositories.remote https://upload.pypi.org/legacy/ - poetry --no-interaction -v publish --build --repository remote --username "$PYPI_USERNAME" --password "$PYPI_PASSWORD" - env: - PYPI_USERNAME: ${{ secrets.PYPI_USERNAME }} - PYPI_PASSWORD: ${{ secrets.PYPI_PASSWORD }} + - name: Build package + run: poetry --no-interaction -v build + - name: Publish package + uses: pypa/gh-action-pypi-publish@release/v1 diff --git a/reference.md b/reference.md index 4aa17e2..12e322c 100644 --- a/reference.md +++ b/reference.md @@ -53,7 +53,7 @@ client.app_categories.list()
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -119,7 +119,7 @@ client.app_categories.retrieve(
**id:** `str` — The ID of the app category to retrieve - +
@@ -127,7 +127,7 @@ client.app_categories.retrieve(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -205,7 +205,7 @@ client.apps.list(
**after:** `typing.Optional[str]` — The cursor to start from for pagination - +
@@ -213,7 +213,7 @@ client.apps.list(
**before:** `typing.Optional[str]` — The cursor to end before for pagination - +
@@ -221,7 +221,7 @@ client.apps.list(
**limit:** `typing.Optional[int]` — The maximum number of results to return - +
@@ -229,7 +229,7 @@ client.apps.list(
**q:** `typing.Optional[str]` — A search query to filter the apps - +
@@ -237,7 +237,7 @@ client.apps.list(
**sort_key:** `typing.Optional[AppsListRequestSortKey]` — The key to sort the apps by - +
@@ -245,7 +245,7 @@ client.apps.list(
**sort_direction:** `typing.Optional[AppsListRequestSortDirection]` — The direction to sort the apps - +
@@ -253,7 +253,7 @@ client.apps.list(
**category_ids:** `typing.Optional[typing.Union[str, typing.Sequence[str]]]` — Only return apps in these categories - +
@@ -261,7 +261,7 @@ client.apps.list(
**has_components:** `typing.Optional[bool]` — Only return apps that have components (actions or triggers) - +
@@ -269,7 +269,7 @@ client.apps.list(
**has_actions:** `typing.Optional[bool]` — Only return apps that have actions - +
@@ -277,7 +277,7 @@ client.apps.list(
**has_triggers:** `typing.Optional[bool]` — Only return apps that have triggers - +
@@ -285,7 +285,7 @@ client.apps.list(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -351,7 +351,7 @@ client.apps.retrieve(
**app_id:** `str` — The name slug or ID of the app (e.g., 'slack', 'github') - +
@@ -359,7 +359,7 @@ client.apps.retrieve(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -432,15 +432,15 @@ client.accounts.list(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
-**external_user_id:** `typing.Optional[str]` - +**external_user_id:** `typing.Optional[str]` +
@@ -448,7 +448,7 @@ client.accounts.list(
**oauth_app_id:** `typing.Optional[str]` — The OAuth app ID to filter by, if applicable - +
@@ -456,7 +456,7 @@ client.accounts.list(
**after:** `typing.Optional[str]` — The cursor to start from for pagination - +
@@ -464,7 +464,7 @@ client.accounts.list(
**before:** `typing.Optional[str]` — The cursor to end before for pagination - +
@@ -472,7 +472,7 @@ client.accounts.list(
**limit:** `typing.Optional[int]` — The maximum number of results to return - +
@@ -480,7 +480,7 @@ client.accounts.list(
**app:** `typing.Optional[str]` — The app slug or ID to filter accounts by. - +
@@ -488,7 +488,7 @@ client.accounts.list(
**include_credentials:** `typing.Optional[bool]` — Whether to retrieve the account's credentials or not - +
@@ -496,7 +496,7 @@ client.accounts.list(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -566,7 +566,7 @@ client.accounts.create(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
@@ -574,7 +574,7 @@ client.accounts.create(
**app_slug:** `str` — The app slug for the account - +
@@ -582,7 +582,7 @@ client.accounts.create(
**cfmap_json:** `str` — JSON string containing the custom fields mapping - +
@@ -590,15 +590,15 @@ client.accounts.create(
**connect_token:** `str` — The connect token for authentication - +
-**external_user_id:** `typing.Optional[str]` - +**external_user_id:** `typing.Optional[str]` +
@@ -606,7 +606,7 @@ client.accounts.create(
**oauth_app_id:** `typing.Optional[str]` — The OAuth app ID to filter by, if applicable - +
@@ -614,7 +614,7 @@ client.accounts.create(
**name:** `typing.Optional[str]` — Optional name for the account - +
@@ -622,7 +622,7 @@ client.accounts.create(
**account_id:** `typing.Optional[str]` — An existing account ID to reconnect. When provided, the account's credentials are updated instead of creating a new account. Must belong to the same external user and project environment as the connect token, and match the app identified by app_slug. - +
@@ -630,7 +630,7 @@ client.accounts.create(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -697,15 +697,15 @@ client.accounts.retrieve(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
-**account_id:** `str` - +**account_id:** `str` +
@@ -713,7 +713,7 @@ client.accounts.retrieve(
**include_credentials:** `typing.Optional[bool]` — Whether to retrieve the account's credentials or not - +
@@ -721,7 +721,7 @@ client.accounts.retrieve(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -787,15 +787,15 @@ client.accounts.delete(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
-**account_id:** `str` - +**account_id:** `str` +
@@ -803,7 +803,7 @@ client.accounts.delete(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -869,115 +869,15 @@ client.accounts.delete_by_app(
**project_id:** `str` — The project ID, which starts with `proj_`. - -
- - -
-
- -**app_id:** `str` - -
-
- -
-
- -**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - -
-
- - - - - - - - -
client.accounts.list_by_external_user(...) -> typing.List[Account] -
-
- -#### 📝 Description - -
-
- -
-
- -List all connected accounts for a specific external user. Equivalent to GET /accounts with external_user_id filter but uses path-based routing. -
-
-
-
- -#### 🔌 Usage - -
-
- -
-
- -```python -from pipedream import Pipedream -from pipedream.environment import PipedreamEnvironment - -client = Pipedream( - client_id="", - client_secret="", - environment=PipedreamEnvironment.PROD, -) - -client.accounts.list_by_external_user( - external_user_id="external_user_id", - include_credentials=True, - app="app", -) - -``` -
-
-
-
- -#### ⚙️ Parameters - -
-
- -
-
- -**project_id:** `str` — The project ID, which starts with `proj_`. - -
-
-
-
- -**external_user_id:** `str` -
-**include_credentials:** `typing.Optional[bool]` - -
-
- -
-
+**app_id:** `str` -**app:** `typing.Optional[str]` -
@@ -985,7 +885,7 @@ client.accounts.list_by_external_user(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -1052,15 +952,15 @@ client.users.delete_external_user(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
-**external_user_id:** `str` - +**external_user_id:** `str` +
@@ -1068,7 +968,7 @@ client.users.delete_external_user(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -1137,7 +1037,7 @@ client.users.list(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
@@ -1145,7 +1045,7 @@ client.users.list(
**after:** `typing.Optional[str]` — The cursor to start from for pagination - +
@@ -1153,7 +1053,7 @@ client.users.list(
**before:** `typing.Optional[str]` — The cursor to end before for pagination - +
@@ -1161,7 +1061,7 @@ client.users.list(
**limit:** `typing.Optional[int]` — The maximum number of results to return - +
@@ -1169,7 +1069,7 @@ client.users.list(
**q:** `typing.Optional[str]` — Filter users by external_id (partial match) - +
@@ -1177,7 +1077,7 @@ client.users.list(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -1250,7 +1150,7 @@ client.components.list(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
@@ -1258,7 +1158,7 @@ client.components.list(
**after:** `typing.Optional[str]` — The cursor to start from for pagination - +
@@ -1266,7 +1166,7 @@ client.components.list(
**before:** `typing.Optional[str]` — The cursor to end before for pagination - +
@@ -1274,7 +1174,7 @@ client.components.list(
**limit:** `typing.Optional[int]` — The maximum number of results to return - +
@@ -1282,7 +1182,7 @@ client.components.list(
**q:** `typing.Optional[str]` — A search query to filter the components - +
@@ -1290,7 +1190,7 @@ client.components.list(
**app:** `typing.Optional[str]` — The ID or name slug of the app to filter the components - +
@@ -1298,7 +1198,7 @@ client.components.list(
**registry:** `typing.Optional[ComponentsListRequestRegistry]` — The registry to retrieve components from. Defaults to 'all' ('public', 'private', or 'all') - +
@@ -1306,7 +1206,7 @@ client.components.list(
**component_type:** `typing.Optional[ComponentType]` — The type of the component to filter the components - +
@@ -1314,7 +1214,7 @@ client.components.list(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -1381,7 +1281,7 @@ client.components.retrieve(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
@@ -1389,7 +1289,7 @@ client.components.retrieve(
**component_id:** `str` — The key that uniquely identifies the component (e.g., 'slack-send-message') - +
@@ -1397,7 +1297,7 @@ client.components.retrieve(
**version:** `typing.Optional[str]` — Optional semantic version of the component to retrieve (for example '1.0.0') - +
@@ -1405,7 +1305,7 @@ client.components.retrieve(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -1473,15 +1373,15 @@ client.components.configure_prop(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
-**request:** `ConfigurePropOpts` - +**request:** `ConfigurePropOpts` +
@@ -1489,7 +1389,7 @@ client.components.configure_prop(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -1556,15 +1456,15 @@ client.components.reload_props(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
-**request:** `ReloadPropsOpts` - +**request:** `ReloadPropsOpts` +
@@ -1572,7 +1472,7 @@ client.components.reload_props(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -1644,7 +1544,7 @@ client.actions.list(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
@@ -1652,7 +1552,7 @@ client.actions.list(
**after:** `typing.Optional[str]` — The cursor to start from for pagination - +
@@ -1660,7 +1560,7 @@ client.actions.list(
**before:** `typing.Optional[str]` — The cursor to end before for pagination - +
@@ -1668,7 +1568,7 @@ client.actions.list(
**limit:** `typing.Optional[int]` — The maximum number of results to return - +
@@ -1676,7 +1576,7 @@ client.actions.list(
**q:** `typing.Optional[str]` — A search query to filter the actions - +
@@ -1684,7 +1584,7 @@ client.actions.list(
**app:** `typing.Optional[str]` — The ID or name slug of the app to filter the actions - +
@@ -1692,7 +1592,7 @@ client.actions.list(
**registry:** `typing.Optional[ActionsListRequestRegistry]` — The registry to retrieve actions from. Defaults to 'all' ('public', 'private', or 'all') - +
@@ -1700,7 +1600,7 @@ client.actions.list(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -1767,7 +1667,7 @@ client.actions.retrieve(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
@@ -1775,7 +1675,7 @@ client.actions.retrieve(
**component_id:** `str` — The key that uniquely identifies the component (e.g., 'slack-send-message') - +
@@ -1783,7 +1683,7 @@ client.actions.retrieve(
**version:** `typing.Optional[str]` — Optional semantic version of the component to retrieve (for example '1.0.0') - +
@@ -1791,7 +1691,7 @@ client.actions.retrieve(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -1859,15 +1759,15 @@ client.actions.configure_prop(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
-**request:** `ConfigurePropOpts` - +**request:** `ConfigurePropOpts` +
@@ -1875,7 +1775,7 @@ client.actions.configure_prop(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -1942,15 +1842,15 @@ client.actions.reload_props(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
-**request:** `ReloadPropsOpts` - +**request:** `ReloadPropsOpts` +
@@ -1958,7 +1858,7 @@ client.actions.reload_props(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -2025,7 +1925,7 @@ client.actions.run(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
@@ -2033,7 +1933,7 @@ client.actions.run(
**id:** `str` — The action component ID - +
@@ -2041,7 +1941,7 @@ client.actions.run(
**external_user_id:** `str` — The external user ID - +
@@ -2049,15 +1949,15 @@ client.actions.run(
**version:** `typing.Optional[str]` — Optional action component version (in SemVer format, for example '1.0.0'), defaults to latest - +
-**configured_props:** `typing.Optional[ConfiguredProps]` - +**configured_props:** `typing.Optional[ConfiguredProps]` +
@@ -2065,15 +1965,15 @@ client.actions.run(
**dynamic_props_id:** `typing.Optional[str]` — The ID for dynamic props - +
-**stash_id:** `typing.Optional[RunActionOptsStashId]` - +**stash_id:** `typing.Optional[RunActionOptsStashId]` +
@@ -2081,7 +1981,7 @@ client.actions.run(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -2153,7 +2053,7 @@ client.triggers.list(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
@@ -2161,7 +2061,7 @@ client.triggers.list(
**after:** `typing.Optional[str]` — The cursor to start from for pagination - +
@@ -2169,7 +2069,7 @@ client.triggers.list(
**before:** `typing.Optional[str]` — The cursor to end before for pagination - +
@@ -2177,7 +2077,7 @@ client.triggers.list(
**limit:** `typing.Optional[int]` — The maximum number of results to return - +
@@ -2185,7 +2085,7 @@ client.triggers.list(
**q:** `typing.Optional[str]` — A search query to filter the triggers - +
@@ -2193,7 +2093,7 @@ client.triggers.list(
**app:** `typing.Optional[str]` — The ID or name slug of the app to filter the triggers - +
@@ -2201,7 +2101,7 @@ client.triggers.list(
**registry:** `typing.Optional[TriggersListRequestRegistry]` — The registry to retrieve triggers from. Defaults to 'all' ('public', 'private', or 'all') - +
@@ -2209,7 +2109,7 @@ client.triggers.list(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -2276,7 +2176,7 @@ client.triggers.retrieve(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
@@ -2284,7 +2184,7 @@ client.triggers.retrieve(
**component_id:** `str` — The key that uniquely identifies the component (e.g., 'slack-send-message') - +
@@ -2292,7 +2192,7 @@ client.triggers.retrieve(
**version:** `typing.Optional[str]` — Optional semantic version of the component to retrieve (for example '1.0.0') - +
@@ -2300,7 +2200,7 @@ client.triggers.retrieve(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -2368,15 +2268,15 @@ client.triggers.configure_prop(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
-**request:** `ConfigurePropOpts` - +**request:** `ConfigurePropOpts` +
@@ -2384,7 +2284,7 @@ client.triggers.configure_prop(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -2451,15 +2351,15 @@ client.triggers.reload_props(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
-**request:** `ReloadPropsOpts` - +**request:** `ReloadPropsOpts` +
@@ -2467,7 +2367,7 @@ client.triggers.reload_props(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -2534,7 +2434,7 @@ client.triggers.deploy(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
@@ -2542,7 +2442,7 @@ client.triggers.deploy(
**id:** `str` — The trigger component ID - +
@@ -2550,7 +2450,7 @@ client.triggers.deploy(
**external_user_id:** `str` — The external user ID - +
@@ -2558,15 +2458,15 @@ client.triggers.deploy(
**version:** `typing.Optional[str]` — Optional trigger component version (in SemVer format, for example '1.0.0'), defaults to latest - +
-**configured_props:** `typing.Optional[ConfiguredProps]` - +**configured_props:** `typing.Optional[ConfiguredProps]` +
@@ -2574,7 +2474,7 @@ client.triggers.deploy(
**dynamic_props_id:** `typing.Optional[str]` — The ID for dynamic props - +
@@ -2582,7 +2482,7 @@ client.triggers.deploy(
**workflow_id:** `typing.Optional[str]` — Optional ID of a workflow to receive trigger events - +
@@ -2590,7 +2490,7 @@ client.triggers.deploy(
**webhook_url:** `typing.Optional[str]` — Optional webhook URL to receive trigger events - +
@@ -2598,7 +2498,7 @@ client.triggers.deploy(
**emit_on_deploy:** `typing.Optional[bool]` — Whether the trigger should emit events during the deploy hook execution. Defaults to true if not specified. - +
@@ -2606,7 +2506,7 @@ client.triggers.deploy(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -2677,7 +2577,7 @@ client.deployed_triggers.list(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
@@ -2685,7 +2585,7 @@ client.deployed_triggers.list(
**external_user_id:** `str` — Your end user ID, for whom you deployed the trigger - +
@@ -2693,7 +2593,7 @@ client.deployed_triggers.list(
**after:** `typing.Optional[str]` — The cursor to start from for pagination - +
@@ -2701,7 +2601,7 @@ client.deployed_triggers.list(
**before:** `typing.Optional[str]` — The cursor to end before for pagination - +
@@ -2709,7 +2609,7 @@ client.deployed_triggers.list(
**limit:** `typing.Optional[int]` — The maximum number of results to return - +
@@ -2717,7 +2617,7 @@ client.deployed_triggers.list(
**emitter_type:** `typing.Optional[EmitterType]` — Filter deployed triggers by emitter type (defaults to 'source' if not provided) - +
@@ -2725,7 +2625,7 @@ client.deployed_triggers.list(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -2792,15 +2692,15 @@ client.deployed_triggers.retrieve(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
-**trigger_id:** `str` - +**trigger_id:** `str` +
@@ -2808,7 +2708,7 @@ client.deployed_triggers.retrieve(
**external_user_id:** `str` — Your end user ID, for whom you deployed the trigger - +
@@ -2816,7 +2716,7 @@ client.deployed_triggers.retrieve(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -2883,15 +2783,15 @@ client.deployed_triggers.update(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
-**trigger_id:** `str` - +**trigger_id:** `str` +
@@ -2899,7 +2799,7 @@ client.deployed_triggers.update(
**external_user_id:** `str` — The external user ID who owns the trigger - +
@@ -2907,15 +2807,15 @@ client.deployed_triggers.update(
**active:** `typing.Optional[bool]` — Whether the trigger should be active - +
-**configured_props:** `typing.Optional[ConfiguredProps]` - +**configured_props:** `typing.Optional[ConfiguredProps]` +
@@ -2923,7 +2823,7 @@ client.deployed_triggers.update(
**name:** `typing.Optional[str]` — The name of the trigger - +
@@ -2931,7 +2831,7 @@ client.deployed_triggers.update(
**emit_on_deploy:** `typing.Optional[bool]` — Whether the trigger should emit events during deployment - +
@@ -2939,7 +2839,7 @@ client.deployed_triggers.update(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -3007,15 +2907,15 @@ client.deployed_triggers.delete(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
-**trigger_id:** `str` - +**trigger_id:** `str` +
@@ -3023,7 +2923,7 @@ client.deployed_triggers.delete(
**external_user_id:** `str` — The external user ID who owns the trigger - +
@@ -3031,7 +2931,7 @@ client.deployed_triggers.delete(
**ignore_hook_errors:** `typing.Optional[bool]` — Whether to ignore errors during deactivation hook - +
@@ -3039,7 +2939,7 @@ client.deployed_triggers.delete(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -3107,15 +3007,15 @@ client.deployed_triggers.list_events(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
-**trigger_id:** `str` - +**trigger_id:** `str` +
@@ -3123,7 +3023,7 @@ client.deployed_triggers.list_events(
**external_user_id:** `str` — Your end user ID, for whom you deployed the trigger - +
@@ -3131,7 +3031,7 @@ client.deployed_triggers.list_events(
**n:** `typing.Optional[int]` — The number of events to retrieve (defaults to 20 if not provided) - +
@@ -3139,7 +3039,7 @@ client.deployed_triggers.list_events(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -3206,15 +3106,15 @@ client.deployed_triggers.list_workflows(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
-**trigger_id:** `str` - +**trigger_id:** `str` +
@@ -3222,7 +3122,7 @@ client.deployed_triggers.list_workflows(
**external_user_id:** `str` — The external user ID who owns the trigger - +
@@ -3230,7 +3130,7 @@ client.deployed_triggers.list_workflows(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -3300,15 +3200,15 @@ client.deployed_triggers.update_workflows(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
-**trigger_id:** `str` - +**trigger_id:** `str` +
@@ -3316,7 +3216,7 @@ client.deployed_triggers.update_workflows(
**external_user_id:** `str` — The external user ID who owns the trigger - +
@@ -3324,7 +3224,7 @@ client.deployed_triggers.update_workflows(
**workflow_ids:** `typing.List[str]` — Array of workflow IDs to set - +
@@ -3332,7 +3232,7 @@ client.deployed_triggers.update_workflows(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -3399,15 +3299,15 @@ client.deployed_triggers.list_webhooks(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
-**trigger_id:** `str` - +**trigger_id:** `str` +
@@ -3415,7 +3315,7 @@ client.deployed_triggers.list_webhooks(
**external_user_id:** `str` — The external user ID who owns the trigger - +
@@ -3423,7 +3323,7 @@ client.deployed_triggers.list_webhooks(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -3493,15 +3393,15 @@ client.deployed_triggers.update_webhooks(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
-**trigger_id:** `str` - +**trigger_id:** `str` +
@@ -3509,7 +3409,7 @@ client.deployed_triggers.update_webhooks(
**external_user_id:** `str` — The external user ID who owns the trigger - +
@@ -3517,7 +3417,7 @@ client.deployed_triggers.update_webhooks(
**webhook_urls:** `typing.List[str]` — Array of webhook URLs to set - +
@@ -3525,7 +3425,7 @@ client.deployed_triggers.update_webhooks(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -3593,23 +3493,23 @@ client.deployed_triggers.retrieve_webhook(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
-**trigger_id:** `str` - +**trigger_id:** `str` +
-**webhook_id:** `str` - +**webhook_id:** `str` +
@@ -3617,7 +3517,7 @@ client.deployed_triggers.retrieve_webhook(
**external_user_id:** `str` — The external user ID who owns the trigger - +
@@ -3625,7 +3525,7 @@ client.deployed_triggers.retrieve_webhook(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -3693,23 +3593,23 @@ client.deployed_triggers.regenerate_webhook_signing_key(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
-**trigger_id:** `str` - +**trigger_id:** `str` +
-**webhook_id:** `str` - +**webhook_id:** `str` +
@@ -3717,7 +3617,7 @@ client.deployed_triggers.regenerate_webhook_signing_key(
**external_user_id:** `str` — The external user ID who owns the trigger - +
@@ -3725,7 +3625,7 @@ client.deployed_triggers.regenerate_webhook_signing_key(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -3790,7 +3690,7 @@ client.project_environment.retrieve_webhook()
**project_id:** `str` — The project ID, which starts with `proj_`. - +
@@ -3798,7 +3698,7 @@ client.project_environment.retrieve_webhook()
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -3864,7 +3764,7 @@ client.project_environment.update_webhook(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
@@ -3872,7 +3772,7 @@ client.project_environment.update_webhook(
**url:** `str` — The webhook URL to set - +
@@ -3880,7 +3780,7 @@ client.project_environment.update_webhook(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -3944,7 +3844,7 @@ client.project_environment.delete_webhook()
**project_id:** `str` — The project ID, which starts with `proj_`. - +
@@ -3952,7 +3852,7 @@ client.project_environment.delete_webhook()
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -4016,7 +3916,7 @@ client.project_environment.regenerate_webhook_signing_key()
**project_id:** `str` — The project ID, which starts with `proj_`. - +
@@ -4024,7 +3924,7 @@ client.project_environment.regenerate_webhook_signing_key()
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -4094,7 +3994,7 @@ client.projects.list(
**after:** `typing.Optional[str]` — The cursor to start from for pagination - +
@@ -4102,7 +4002,7 @@ client.projects.list(
**before:** `typing.Optional[str]` — The cursor to end before for pagination - +
@@ -4110,7 +4010,7 @@ client.projects.list(
**limit:** `typing.Optional[int]` — The maximum number of results to return - +
@@ -4118,7 +4018,7 @@ client.projects.list(
**q:** `typing.Optional[str]` — A search query to filter the projects - +
@@ -4126,7 +4026,7 @@ client.projects.list(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -4192,7 +4092,7 @@ client.projects.create(
**name:** `str` — Name of the project - +
@@ -4200,7 +4100,7 @@ client.projects.create(
**app_name:** `typing.Optional[str]` — Display name for the Connect application - +
@@ -4208,7 +4108,7 @@ client.projects.create(
**support_email:** `typing.Optional[str]` — Support email displayed to end users - +
@@ -4216,7 +4116,7 @@ client.projects.create(
**connect_require_key_auth_test:** `typing.Optional[bool]` — Send a test request to the upstream API when adding Connect accounts for key-based apps - +
@@ -4224,7 +4124,7 @@ client.projects.create(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -4290,7 +4190,7 @@ client.projects.retrieve(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
@@ -4298,7 +4198,7 @@ client.projects.retrieve(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -4364,7 +4264,7 @@ client.projects.delete(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
@@ -4372,7 +4272,7 @@ client.projects.delete(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -4438,7 +4338,7 @@ client.projects.update(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
@@ -4446,7 +4346,7 @@ client.projects.update(
**name:** `typing.Optional[str]` — Name of the project - +
@@ -4454,7 +4354,7 @@ client.projects.update(
**app_name:** `typing.Optional[str]` — Display name for the Connect application - +
@@ -4462,7 +4362,7 @@ client.projects.update(
**support_email:** `typing.Optional[str]` — Support email displayed to end users - +
@@ -4470,7 +4370,7 @@ client.projects.update(
**connect_require_key_auth_test:** `typing.Optional[bool]` — Send a test request to the upstream API when adding Connect accounts for key-based apps - +
@@ -4478,7 +4378,7 @@ client.projects.update(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -4545,7 +4445,7 @@ client.projects.update_logo(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
@@ -4553,7 +4453,7 @@ client.projects.update_logo(
**logo:** `str` — Data URI containing the new Base64 encoded image - +
@@ -4561,7 +4461,7 @@ client.projects.update_logo(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -4625,7 +4525,7 @@ client.projects.retrieve_info()
**project_id:** `str` — The project ID, which starts with `proj_`. - +
@@ -4633,7 +4533,7 @@ client.projects.retrieve_info()
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -4700,15 +4600,15 @@ client.file_stash.download_file(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
-**s_3_key:** `str` - +**s_3_key:** `str` +
@@ -4716,7 +4616,7 @@ client.file_stash.download_file(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -4785,7 +4685,7 @@ client.proxy.get(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
@@ -4793,7 +4693,7 @@ client.proxy.get(
**url_64:** `str` — Base64-encoded target URL - +
@@ -4801,7 +4701,7 @@ client.proxy.get(
**external_user_id:** `str` — The external user ID for the proxy request - +
@@ -4809,7 +4709,7 @@ client.proxy.get(
**account_id:** `str` — The account ID to use for authentication - +
@@ -4817,7 +4717,7 @@ client.proxy.get(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -4888,7 +4788,7 @@ client.proxy.post(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
@@ -4896,7 +4796,7 @@ client.proxy.post(
**url_64:** `str` — Base64-encoded target URL - +
@@ -4904,7 +4804,7 @@ client.proxy.post(
**external_user_id:** `str` — The external user ID for the proxy request - +
@@ -4912,7 +4812,7 @@ client.proxy.post(
**account_id:** `str` — The account ID to use for authentication - +
@@ -4920,7 +4820,7 @@ client.proxy.post(
**request:** `typing.Dict[str, typing.Any]` — Request body to forward to the target API - +
@@ -4928,7 +4828,7 @@ client.proxy.post(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -4999,7 +4899,7 @@ client.proxy.put(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
@@ -5007,7 +4907,7 @@ client.proxy.put(
**url_64:** `str` — Base64-encoded target URL - +
@@ -5015,7 +4915,7 @@ client.proxy.put(
**external_user_id:** `str` — The external user ID for the proxy request - +
@@ -5023,7 +4923,7 @@ client.proxy.put(
**account_id:** `str` — The account ID to use for authentication - +
@@ -5031,7 +4931,7 @@ client.proxy.put(
**request:** `typing.Dict[str, typing.Any]` — Request body to forward to the target API - +
@@ -5039,7 +4939,7 @@ client.proxy.put(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -5107,7 +5007,7 @@ client.proxy.delete(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
@@ -5115,7 +5015,7 @@ client.proxy.delete(
**url_64:** `str` — Base64-encoded target URL - +
@@ -5123,7 +5023,7 @@ client.proxy.delete(
**external_user_id:** `str` — The external user ID for the proxy request - +
@@ -5131,7 +5031,7 @@ client.proxy.delete(
**account_id:** `str` — The account ID to use for authentication - +
@@ -5139,7 +5039,7 @@ client.proxy.delete(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -5210,7 +5110,7 @@ client.proxy.patch(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
@@ -5218,7 +5118,7 @@ client.proxy.patch(
**url_64:** `str` — Base64-encoded target URL - +
@@ -5226,7 +5126,7 @@ client.proxy.patch(
**external_user_id:** `str` — The external user ID for the proxy request - +
@@ -5234,7 +5134,7 @@ client.proxy.patch(
**account_id:** `str` — The account ID to use for authentication - +
@@ -5242,7 +5142,7 @@ client.proxy.patch(
**request:** `typing.Dict[str, typing.Any]` — Request body to forward to the target API - +
@@ -5250,7 +5150,7 @@ client.proxy.patch(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -5317,7 +5217,7 @@ client.tokens.create(
**project_id:** `str` — The project ID, which starts with `proj_`. - +
@@ -5325,7 +5225,7 @@ client.tokens.create(
**external_user_id:** `str` — Your end user ID, for whom you're creating the token - +
@@ -5333,7 +5233,7 @@ client.tokens.create(
**allowed_origins:** `typing.Optional[typing.List[str]]` — List of allowed origins for CORS - +
@@ -5341,7 +5241,7 @@ client.tokens.create(
**error_redirect_uri:** `typing.Optional[str]` — URI to redirect to on error - +
@@ -5349,7 +5249,7 @@ client.tokens.create(
**expires_in:** `typing.Optional[int]` — Token TTL in seconds (max 14400 = 4 hours). Defaults to 4 hours if not specified. - +
@@ -5357,7 +5257,7 @@ client.tokens.create(
**scope:** `typing.Optional[str]` — Space-separated scopes to restrict token permissions. Defaults to 'connect:*' if not specified. See https://pipedream.com/docs/connect/api-reference/authentication#connect-token-scopes for more information. - +
@@ -5365,7 +5265,7 @@ client.tokens.create(
**success_redirect_uri:** `typing.Optional[str]` — URI to redirect to on success - +
@@ -5373,7 +5273,7 @@ client.tokens.create(
**webhook_uri:** `typing.Optional[str]` — Webhook URI for notifications - +
@@ -5381,7 +5281,7 @@ client.tokens.create(
**allow_progressive_scopes:** `typing.Optional[bool]` — When true, end users may authorize a subset of the app's OAuth scopes; only the app's functional scopes (needed for the post-OAuth test request) are enforced. Defaults to false. - +
@@ -5389,7 +5289,7 @@ client.tokens.create(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -5457,8 +5357,8 @@ client.tokens.validate(
-**ctok:** `ConnectToken` - +**ctok:** `ConnectToken` +
@@ -5466,7 +5366,7 @@ client.tokens.validate(
**app_id:** `str` — The app ID to validate against - +
@@ -5474,7 +5374,7 @@ client.tokens.validate(
**account_id:** `typing.Optional[str]` — An existing account ID to reconnect. Must belong to the app identified by app_id. - +
@@ -5482,7 +5382,7 @@ client.tokens.validate(
**oauth_app_id:** `typing.Optional[str]` — The OAuth app ID to validate against (if the token is for an OAuth app) - +
@@ -5490,7 +5390,7 @@ client.tokens.validate(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -5558,7 +5458,7 @@ client.usage.list(
**start_ts:** `int` — Usage window start timestamp (seconds) - +
@@ -5566,7 +5466,7 @@ client.usage.list(
**end_ts:** `int` — Usage window end timestamp (seconds) - +
@@ -5574,7 +5474,7 @@ client.usage.list(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -5641,24 +5541,24 @@ client.oauth_tokens.create(
-**grant_type:** `typing.Literal` - +**grant_type:** `typing.Literal` +
-**client_id:** `str` - +**client_id:** `str` +
-**client_secret:** `str` - +**client_secret:** `str` +
@@ -5666,7 +5566,104 @@ client.oauth_tokens.create(
**scope:** `typing.Optional[str]` — Optional space-separated scopes for the access token. Defaults to `*`. - + +
+ + +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+ + + + + + +
+ + +## Workflows +
client.workflows.invoke(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from pipedream import Pipedream, PipedreamEnvironment +from pipedream.workflows.client import HTTPAuthType + +client = Pipedream( + client_id="", + client_secret="", + environment=PipedreamEnvironment.PROD, +) +response = client.workflows.invoke( + url_or_endpoint="https://your-workflow.m.pipedream.net", + method="POST", + body={"key": "value"}, + headers={"Content-Type": "application/json"}, + auth_type=HTTPAuthType.NONE, +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**url_or_endpoint:** `str` — The URL of the workflow's HTTP interface or the ID of the endpoint + +
+
+ +
+
+ +**method:** `str` — HTTP method to use (default: "POST") + +
+
+ +
+
+ +**body:** `typing.Optional[typing.Any]` — Request body data + +
+
+ +
+
+ +**headers:** `typing.Optional[typing.Dict[str, str]]` — HTTP headers to include + +
+
+ +
+
+ +**auth_type:** `HTTPAuthType` — Type of authorization (default: HTTPAuthType.NONE) +
@@ -5674,7 +5671,7 @@ client.oauth_tokens.create(
**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. - +
@@ -5685,3 +5682,96 @@ client.oauth_tokens.create(
+
client.workflows.invoke_for_external_user(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from pipedream import Pipedream, PipedreamEnvironment + +client = Pipedream( + client_id="", + client_secret="", + environment=PipedreamEnvironment.PROD, +) +response = client.workflows.invoke_for_external_user( + url_or_endpoint="en2r1n8a98np7", + external_user_id="user_123", + method="POST", + body={"message": "Hello from external user"}, + headers={"Content-Type": "application/json"}, +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**url_or_endpoint:** `str` — The URL of the workflow's HTTP interface or the ID of the endpoint + +
+
+ +
+
+ +**external_user_id:** `str` — The external user ID for whom the workflow is being invoked + +
+
+ +
+
+ +**method:** `str` — HTTP method to use (default: "POST") + +
+
+ +
+
+ +**body:** `typing.Optional[typing.Any]` — Request body data + +
+
+ +
+
+ +**headers:** `typing.Optional[typing.Dict[str, str]]` — HTTP headers to include + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
diff --git a/src/pipedream/__init__.py b/src/pipedream/__init__.py index 9e9e73e..090033e 100644 --- a/src/pipedream/__init__.py +++ b/src/pipedream/__init__.py @@ -162,6 +162,7 @@ triggers, usage, users, + workflows, ) from ._default_clients import DefaultAioHttpClient, DefaultAsyncHttpxClient from .actions import ActionsListRequestRegistry @@ -171,6 +172,7 @@ from .pipedream import AsyncPipedream, Pipedream from .triggers import TriggersListRequestRegistry from .version import __version__ + from .workflows.client import AsyncWorkflowsClient, WorkflowsClient _dynamic_imports: typing.Dict[str, str] = { "Account": ".types", "AccountCredentials": ".types", @@ -184,6 +186,7 @@ "AppsListRequestSortDirection": ".apps", "AppsListRequestSortKey": ".apps", "AsyncPipedream": ".pipedream", + "AsyncWorkflowsClient": ".workflows.client", "BackendClientOpts": ".types", "BadRequestError": ".errors", "ClientOpts": ".types", @@ -322,6 +325,7 @@ "Webhook": ".types", "WebhookWithOptionalSigningKey": ".types", "WebhookWithSigningKey": ".types", + "WorkflowsClient": ".workflows.client", "__version__": ".version", "accounts": ".accounts", "actions": ".actions", @@ -338,6 +342,7 @@ "triggers": ".triggers", "usage": ".usage", "users": ".users", + "workflows": ".workflows", } @@ -375,6 +380,7 @@ def __dir__(): "AppsListRequestSortDirection", "AppsListRequestSortKey", "AsyncPipedream", + "AsyncWorkflowsClient", "BackendClientOpts", "BadRequestError", "ClientOpts", @@ -513,6 +519,7 @@ def __dir__(): "Webhook", "WebhookWithOptionalSigningKey", "WebhookWithSigningKey", + "WorkflowsClient", "__version__", "accounts", "actions", @@ -529,4 +536,5 @@ def __dir__(): "triggers", "usage", "users", + "workflows", ] diff --git a/src/pipedream/pipedream.py b/src/pipedream/pipedream.py index ed51914..53f491d 100644 --- a/src/pipedream/pipedream.py +++ b/src/pipedream/pipedream.py @@ -1,86 +1,131 @@ -# This file was auto-generated by Fern from our API Definition. - import os import typing import httpx + from .client import AsyncClient, Client from .core.logging import LogConfig, Logger -from .environment import PipedreamEnvironment from .types.project_environment import ProjectEnvironment +from .workflows.client import AsyncWorkflowsClient, WorkflowsClient + +_PROD_BASE_URL = "https://api.pipedream.com" class Pipedream(Client): - @typing.overload + def __init__( self, *, - base_url: typing.Optional[str] = None, - environment: PipedreamEnvironment = PipedreamEnvironment.PROD, - project_id: str, - project_environment: typing.Optional[ProjectEnvironment] = os.getenv("PIPEDREAM_PROJECT_ENVIRONMENT"), - headers: typing.Optional[typing.Dict[str, str]] = None, - timeout: typing.Optional[float] = None, - max_retries: typing.Optional[int] = None, - follow_redirects: typing.Optional[bool] = True, - httpx_client: typing.Optional[httpx.Client] = None, - logging: typing.Optional[typing.Union[LogConfig, Logger]] = None, + access_token: typing.Optional[str] = os.getenv("PIPEDREAM_ACCESS_TOKEN"), client_id: typing.Optional[str] = os.getenv("PIPEDREAM_CLIENT_ID"), client_secret: typing.Optional[str] = os.getenv("PIPEDREAM_CLIENT_SECRET"), - ): ... - @typing.overload - def __init__( - self, - *, + project_id: typing.Optional[str] = os.getenv("PIPEDREAM_PROJECT_ID"), + project_environment: typing.Optional[ProjectEnvironment] = os.getenv( + "PIPEDREAM_PROJECT_ENVIRONMENT", + "production", + ), base_url: typing.Optional[str] = None, - environment: PipedreamEnvironment = PipedreamEnvironment.PROD, - project_id: str, - project_environment: typing.Optional[ProjectEnvironment] = os.getenv("PIPEDREAM_PROJECT_ENVIRONMENT"), + workflow_domain: typing.Optional[str] = None, headers: typing.Optional[typing.Dict[str, str]] = None, timeout: typing.Optional[float] = None, max_retries: typing.Optional[int] = None, follow_redirects: typing.Optional[bool] = True, httpx_client: typing.Optional[httpx.Client] = None, logging: typing.Optional[typing.Union[LogConfig, Logger]] = None, - token: typing.Callable[[], str], - ): ... - def __init__(self, **kwargs: typing.Any): - super().__init__(**kwargs) + ): + if not project_id: + raise ValueError("Project ID is required") + + resolved_base_url = base_url or os.environ.get("PIPEDREAM_BASE_URL") or _PROD_BASE_URL + resolved_workflow_domain = ( + workflow_domain or os.environ.get("PIPEDREAM_WORKFLOW_DOMAIN") or "m.pipedream.net" + ) + + common_kwargs: typing.Dict[str, typing.Any] = dict( + base_url=resolved_base_url, + project_id=project_id, + project_environment=project_environment, + headers=headers, + timeout=timeout, + max_retries=max_retries, + follow_redirects=follow_redirects, + httpx_client=httpx_client, + logging=logging, + ) + + if access_token: + super().__init__(token=(lambda: access_token), **common_kwargs) + else: + super().__init__(client_id=client_id, client_secret=client_secret, **common_kwargs) + + self.workflows = WorkflowsClient( + client_wrapper=self._client_wrapper, + workflow_domain=resolved_workflow_domain, + ) + + @property + def raw_access_token(self) -> typing.Optional[str]: + """ + Returns an access token that can be used to authenticate API requests + """ + return self._client_wrapper._get_token() class AsyncPipedream(AsyncClient): - @typing.overload + def __init__( self, *, - base_url: typing.Optional[str] = None, - environment: PipedreamEnvironment = PipedreamEnvironment.PROD, - project_id: str, - project_environment: typing.Optional[ProjectEnvironment] = os.getenv("PIPEDREAM_PROJECT_ENVIRONMENT"), - headers: typing.Optional[typing.Dict[str, str]] = None, - timeout: typing.Optional[float] = None, - max_retries: typing.Optional[int] = None, - follow_redirects: typing.Optional[bool] = True, - httpx_client: typing.Optional[httpx.AsyncClient] = None, - logging: typing.Optional[typing.Union[LogConfig, Logger]] = None, + access_token: typing.Optional[str] = os.getenv("PIPEDREAM_ACCESS_TOKEN"), client_id: typing.Optional[str] = os.getenv("PIPEDREAM_CLIENT_ID"), client_secret: typing.Optional[str] = os.getenv("PIPEDREAM_CLIENT_SECRET"), - ): ... - @typing.overload - def __init__( - self, - *, + project_id: typing.Optional[str] = os.getenv("PIPEDREAM_PROJECT_ID"), + project_environment: typing.Optional[ProjectEnvironment] = os.getenv( + "PIPEDREAM_PROJECT_ENVIRONMENT", + "production", + ), base_url: typing.Optional[str] = None, - environment: PipedreamEnvironment = PipedreamEnvironment.PROD, - project_id: str, - project_environment: typing.Optional[ProjectEnvironment] = os.getenv("PIPEDREAM_PROJECT_ENVIRONMENT"), + workflow_domain: typing.Optional[str] = None, headers: typing.Optional[typing.Dict[str, str]] = None, timeout: typing.Optional[float] = None, max_retries: typing.Optional[int] = None, follow_redirects: typing.Optional[bool] = True, httpx_client: typing.Optional[httpx.AsyncClient] = None, logging: typing.Optional[typing.Union[LogConfig, Logger]] = None, - token: typing.Callable[[], str], - ): ... - def __init__(self, **kwargs: typing.Any): - super().__init__(**kwargs) + ): + if not project_id: + raise ValueError("Project ID is required") + + resolved_base_url = base_url or os.environ.get("PIPEDREAM_BASE_URL") or _PROD_BASE_URL + resolved_workflow_domain = ( + workflow_domain or os.environ.get("PIPEDREAM_WORKFLOW_DOMAIN") or "m.pipedream.net" + ) + + common_kwargs: typing.Dict[str, typing.Any] = dict( + base_url=resolved_base_url, + project_id=project_id, + project_environment=project_environment, + headers=headers, + timeout=timeout, + max_retries=max_retries, + follow_redirects=follow_redirects, + httpx_client=httpx_client, + logging=logging, + ) + + if access_token: + super().__init__(token=(lambda: access_token), **common_kwargs) + else: + super().__init__(client_id=client_id, client_secret=client_secret, **common_kwargs) + + self.workflows = AsyncWorkflowsClient( + client_wrapper=self._client_wrapper, + workflow_domain=resolved_workflow_domain, + ) + + @property + def raw_access_token(self) -> typing.Optional[str]: + """ + Returns an access token that can be used to authenticate API requests + """ + return self._client_wrapper._get_token() diff --git a/src/pipedream/proxy/client.py b/src/pipedream/proxy/client.py index 38bbf5c..1bff6ce 100644 --- a/src/pipedream/proxy/client.py +++ b/src/pipedream/proxy/client.py @@ -1,14 +1,85 @@ -# This file was auto-generated by Fern from our API Definition. - +import base64 import typing +from collections.abc import AsyncIterator, Iterator +from urllib.parse import parse_qs, urlencode, urlparse, urlunparse 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 OMIT = typing.cast(typing.Any, ...) +_SyncResult = typing.Union[ProxyResponse, typing.Iterator[bytes], None] +_AsyncResult = typing.Union[ProxyResponse, typing.AsyncIterator[bytes], None] + + +def _add_params_to_url(url: str, params: typing.Dict[str, typing.Any]) -> str: + parsed = urlparse(url) + existing_params = parse_qs(parsed.query) + for key, value in params.items(): + existing_params[key] = value if isinstance(value, list) else [value] + new_query = urlencode(existing_params, doseq=True) + return urlunparse(parsed._replace(query=new_query)) + + +def _prepare_request( + url: str, + *, + headers: typing.Optional[typing.Dict[str, typing.Any]], + params: typing.Optional[typing.Dict[str, typing.Any]], +) -> typing.Tuple[str, RequestOptions]: + if params: + url = _add_params_to_url(url, params) + url_64 = base64.urlsafe_b64encode(url.encode()).decode() + downstream_headers = { + f"x-pd-proxy-{name}": value for name, value in (headers or {}).items() + } + return url_64, RequestOptions(additional_headers=downstream_headers) + + +def _consume_sync(ctx: typing.ContextManager) -> _SyncResult: + """ + Open the raw proxy context, peek at the response payload, and either + return the parsed ProxyResponse (fully-buffered JSON) or a generator that + streams the binary body and closes the underlying response when exhausted. + """ + raw = ctx.__enter__() + data = raw.data + if not isinstance(data, Iterator): + ctx.__exit__(None, None, None) + return data + + def _stream() -> typing.Iterator[bytes]: + try: + yield from data + finally: + ctx.__exit__(None, None, None) + + return _stream() + + +async def _consume_async(ctx: typing.AsyncContextManager) -> _AsyncResult: + """ + Async counterpart of `_consume_sync` — returns either a parsed + ProxyResponse or an async generator that streams the binary body. + """ + raw = await ctx.__aenter__() + data = raw.data + if not isinstance(data, AsyncIterator): + await ctx.__aexit__(None, None, None) + return data + + async def _stream() -> typing.AsyncIterator[bytes]: + try: + async for chunk in data: + yield chunk + finally: + await ctx.__aexit__(None, None, None) + + return _stream() + class ProxyClient: def __init__(self, *, client_wrapper: SyncClientWrapper): @@ -27,19 +98,20 @@ def with_raw_response(self) -> RawProxyClient: def get( self, - url_64: str, + url: str, *, external_user_id: str, account_id: str, - request_options: typing.Optional[RequestOptions] = None, - ) -> typing.Iterator[bytes]: + headers: typing.Optional[typing.Dict[str, typing.Any]] = None, + params: typing.Optional[typing.Dict[str, typing.Any]] = None, + ) -> _SyncResult: """ - Forward an authenticated GET request to an external API using an external user's account credentials + Forward an authenticated GET request to an external API using an external user's account credentials. Parameters ---------- - url_64 : str - Base64-encoded target URL + url : str + Target URL external_user_id : str The external user ID for the proxy request @@ -47,257 +119,137 @@ def get( account_id : str The account ID to use for authentication - 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. + 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 Returns ------- - typing.Iterator[bytes] - proxy request successful + typing.Union[ProxyResponse, typing.Iterator[bytes], None] + ProxyResponse for JSON content, Iterator[bytes] for binary content, None for empty bodies. Examples -------- - from pipedream import Pipedream + from pipedream import Pipedream, PipedreamEnvironment client = Pipedream( - project_id="YOUR_PROJECT_ID", - client_id="YOUR_CLIENT_ID", - client_secret="YOUR_CLIENT_SECRET", + client_id="", + client_secret="", + environment=PipedreamEnvironment.PROD, ) client.proxy.get( - url_64="url_64", + url="https://example.com/api/endpoint", external_user_id="external_user_id", account_id="account_id", + headers={"Extra-Downstream-Header": "some value"}, + params={"limit": 10}, ) """ - 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 + url_64, request_options = _prepare_request(url, headers=headers, params=params) + return _consume_sync( + self._raw_client.get( + url_64, + external_user_id=external_user_id, + account_id=account_id, + request_options=request_options, + ) + ) def post( self, - url_64: str, + url: str, *, external_user_id: str, account_id: str, - request: typing.Dict[str, typing.Any], - request_options: typing.Optional[RequestOptions] = None, - ) -> typing.Iterator[bytes]: + 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, + ) -> _SyncResult: """ - Forward an authenticated POST request to an external API using an external user's account credentials - - Parameters - ---------- - url_64 : str - Base64-encoded target URL - - external_user_id : str - The external user ID for the proxy request - - account_id : str - The account ID to use for authentication - - request : typing.Dict[str, typing.Any] - - 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 - ------- - typing.Iterator[bytes] - proxy request successful - - Examples - -------- - from pipedream import Pipedream - - client = Pipedream( - project_id="YOUR_PROJECT_ID", - client_id="YOUR_CLIENT_ID", - client_secret="YOUR_CLIENT_SECRET", - ) - client.proxy.post( - url_64="url_64", - external_user_id="external_user_id", - account_id="account_id", - request={"string": {"key": "value"}}, - ) + Forward an authenticated POST request to an external API using an external user's account credentials. """ - with self._raw_client.post( - url_64, - external_user_id=external_user_id, - account_id=account_id, - request=request, - request_options=request_options, - ) as r: - yield from r.data + url_64, request_options = _prepare_request(url, headers=headers, params=params) + return _consume_sync( + self._raw_client.post( + url_64, + external_user_id=external_user_id, + account_id=account_id, + request=body or {}, + request_options=request_options, + ) + ) def put( self, - url_64: str, + url: str, *, external_user_id: str, account_id: str, - request: typing.Dict[str, typing.Any], - request_options: typing.Optional[RequestOptions] = None, - ) -> typing.Iterator[bytes]: + 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, + ) -> _SyncResult: """ - Forward an authenticated PUT request to an external API using an external user's account credentials - - Parameters - ---------- - url_64 : str - Base64-encoded target URL - - external_user_id : str - The external user ID for the proxy request - - account_id : str - The account ID to use for authentication - - request : typing.Dict[str, typing.Any] - - 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 - ------- - typing.Iterator[bytes] - proxy request successful - - Examples - -------- - from pipedream import Pipedream - - client = Pipedream( - project_id="YOUR_PROJECT_ID", - client_id="YOUR_CLIENT_ID", - client_secret="YOUR_CLIENT_SECRET", - ) - client.proxy.put( - url_64="url_64", - external_user_id="external_user_id", - account_id="account_id", - request={"string": {"key": "value"}}, - ) + Forward an authenticated PUT request to an external API using an external user's account credentials. """ - with self._raw_client.put( - url_64, - external_user_id=external_user_id, - account_id=account_id, - request=request, - request_options=request_options, - ) as r: - yield from r.data + url_64, request_options = _prepare_request(url, headers=headers, params=params) + return _consume_sync( + self._raw_client.put( + url_64, + external_user_id=external_user_id, + account_id=account_id, + request=body or {}, + request_options=request_options, + ) + ) - def delete( + def patch( self, - url_64: str, + url: str, *, external_user_id: str, account_id: str, - request_options: typing.Optional[RequestOptions] = None, - ) -> typing.Iterator[bytes]: + 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, + ) -> _SyncResult: """ - Forward an authenticated DELETE request to an external API using an external user's account credentials - - Parameters - ---------- - url_64 : str - Base64-encoded target URL - - external_user_id : str - The external user ID for the proxy request - - account_id : str - The account ID to use for authentication - - 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 - ------- - typing.Iterator[bytes] - proxy request successful - - Examples - -------- - from pipedream import Pipedream - - client = Pipedream( - project_id="YOUR_PROJECT_ID", - client_id="YOUR_CLIENT_ID", - client_secret="YOUR_CLIENT_SECRET", - ) - client.proxy.delete( - url_64="url_64", - external_user_id="external_user_id", - account_id="account_id", - ) + Forward an authenticated PATCH request to an external API using an external user's account credentials. """ - 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 + url_64, request_options = _prepare_request(url, headers=headers, params=params) + return _consume_sync( + self._raw_client.patch( + url_64, + external_user_id=external_user_id, + account_id=account_id, + request=body or {}, + request_options=request_options, + ) + ) - def patch( + def delete( self, - url_64: str, + url: str, *, external_user_id: str, account_id: str, - request: typing.Dict[str, typing.Any], - request_options: typing.Optional[RequestOptions] = None, - ) -> typing.Iterator[bytes]: + headers: typing.Optional[typing.Dict[str, typing.Any]] = None, + params: typing.Optional[typing.Dict[str, typing.Any]] = None, + ) -> _SyncResult: """ - Forward an authenticated PATCH request to an external API using an external user's account credentials - - Parameters - ---------- - url_64 : str - Base64-encoded target URL - - external_user_id : str - The external user ID for the proxy request - - account_id : str - The account ID to use for authentication - - request : typing.Dict[str, typing.Any] - - 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 - ------- - typing.Iterator[bytes] - proxy request successful - - Examples - -------- - from pipedream import Pipedream - - client = Pipedream( - project_id="YOUR_PROJECT_ID", - client_id="YOUR_CLIENT_ID", - client_secret="YOUR_CLIENT_SECRET", - ) - client.proxy.patch( - url_64="url_64", - external_user_id="external_user_id", - account_id="account_id", - request={"string": {"key": "value"}}, - ) + Forward an authenticated DELETE request to an external API using an external user's account credentials. """ - with self._raw_client.patch( - url_64, - external_user_id=external_user_id, - account_id=account_id, - request=request, - request_options=request_options, - ) as r: - yield from r.data + url_64, request_options = _prepare_request(url, headers=headers, params=params) + return _consume_sync( + self._raw_client.delete( + url_64, + external_user_id=external_user_id, + account_id=account_id, + request_options=request_options, + ) + ) class AsyncProxyClient: @@ -317,319 +269,116 @@ def with_raw_response(self) -> AsyncRawProxyClient: async def get( self, - url_64: str, + url: str, *, external_user_id: str, account_id: str, - request_options: typing.Optional[RequestOptions] = None, - ) -> typing.AsyncIterator[bytes]: + headers: typing.Optional[typing.Dict[str, typing.Any]] = None, + params: typing.Optional[typing.Dict[str, typing.Any]] = None, + ) -> _AsyncResult: """ - Forward an authenticated GET request to an external API using an external user's account credentials - - Parameters - ---------- - url_64 : str - Base64-encoded target URL - - external_user_id : str - The external user ID for the proxy request - - account_id : str - The account ID to use for authentication - - 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 - ------- - typing.AsyncIterator[bytes] - proxy request successful - - Examples - -------- - import asyncio - - from pipedream import AsyncPipedream - - client = AsyncPipedream( - project_id="YOUR_PROJECT_ID", - client_id="YOUR_CLIENT_ID", - client_secret="YOUR_CLIENT_SECRET", - ) - - - async def main() -> None: - await client.proxy.get( - url_64="url_64", - external_user_id="external_user_id", - account_id="account_id", - ) - - - asyncio.run(main()) + Forward an authenticated GET request to an external API using an external user's account credentials. """ - 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 + url_64, request_options = _prepare_request(url, headers=headers, params=params) + return await _consume_async( + self._raw_client.get( + url_64, + external_user_id=external_user_id, + account_id=account_id, + request_options=request_options, + ) + ) async def post( self, - url_64: str, + url: str, *, external_user_id: str, account_id: str, - request: typing.Dict[str, typing.Any], - request_options: typing.Optional[RequestOptions] = None, - ) -> typing.AsyncIterator[bytes]: + 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, + ) -> _AsyncResult: """ - Forward an authenticated POST request to an external API using an external user's account credentials - - Parameters - ---------- - url_64 : str - Base64-encoded target URL - - external_user_id : str - The external user ID for the proxy request - - account_id : str - The account ID to use for authentication - - request : typing.Dict[str, typing.Any] - - 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 - ------- - typing.AsyncIterator[bytes] - proxy request successful - - Examples - -------- - import asyncio - - from pipedream import AsyncPipedream - - client = AsyncPipedream( - project_id="YOUR_PROJECT_ID", - client_id="YOUR_CLIENT_ID", - client_secret="YOUR_CLIENT_SECRET", - ) - - - async def main() -> None: - await client.proxy.post( - url_64="url_64", - external_user_id="external_user_id", - account_id="account_id", - request={"string": {"key": "value"}}, - ) - - - asyncio.run(main()) + Forward an authenticated POST request to an external API using an external user's account credentials. """ - async with self._raw_client.post( - url_64, - external_user_id=external_user_id, - account_id=account_id, - request=request, - request_options=request_options, - ) as r: - async for _chunk in r.data: - yield _chunk + url_64, request_options = _prepare_request(url, headers=headers, params=params) + return await _consume_async( + self._raw_client.post( + url_64, + external_user_id=external_user_id, + account_id=account_id, + request=body or {}, + request_options=request_options, + ) + ) async def put( self, - url_64: str, + url: str, *, external_user_id: str, account_id: str, - request: typing.Dict[str, typing.Any], - request_options: typing.Optional[RequestOptions] = None, - ) -> typing.AsyncIterator[bytes]: + 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, + ) -> _AsyncResult: """ - Forward an authenticated PUT request to an external API using an external user's account credentials - - Parameters - ---------- - url_64 : str - Base64-encoded target URL - - external_user_id : str - The external user ID for the proxy request - - account_id : str - The account ID to use for authentication - - request : typing.Dict[str, typing.Any] - - 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 - ------- - typing.AsyncIterator[bytes] - proxy request successful - - Examples - -------- - import asyncio - - from pipedream import AsyncPipedream - - client = AsyncPipedream( - project_id="YOUR_PROJECT_ID", - client_id="YOUR_CLIENT_ID", - client_secret="YOUR_CLIENT_SECRET", - ) - - - async def main() -> None: - await client.proxy.put( - url_64="url_64", - external_user_id="external_user_id", - account_id="account_id", - request={"string": {"key": "value"}}, - ) - - - asyncio.run(main()) + Forward an authenticated PUT request to an external API using an external user's account credentials. """ - async with self._raw_client.put( - url_64, - external_user_id=external_user_id, - account_id=account_id, - request=request, - request_options=request_options, - ) as r: - async for _chunk in r.data: - yield _chunk + url_64, request_options = _prepare_request(url, headers=headers, params=params) + return await _consume_async( + self._raw_client.put( + url_64, + external_user_id=external_user_id, + account_id=account_id, + request=body or {}, + request_options=request_options, + ) + ) - async def delete( + async def patch( self, - url_64: str, + url: str, *, external_user_id: str, account_id: str, - request_options: typing.Optional[RequestOptions] = None, - ) -> typing.AsyncIterator[bytes]: + 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, + ) -> _AsyncResult: """ - Forward an authenticated DELETE request to an external API using an external user's account credentials - - Parameters - ---------- - url_64 : str - Base64-encoded target URL - - external_user_id : str - The external user ID for the proxy request - - account_id : str - The account ID to use for authentication - - 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 - ------- - typing.AsyncIterator[bytes] - proxy request successful - - Examples - -------- - import asyncio - - from pipedream import AsyncPipedream - - client = AsyncPipedream( - project_id="YOUR_PROJECT_ID", - client_id="YOUR_CLIENT_ID", - client_secret="YOUR_CLIENT_SECRET", - ) - - - async def main() -> None: - await client.proxy.delete( - url_64="url_64", - external_user_id="external_user_id", - account_id="account_id", - ) - - - asyncio.run(main()) + Forward an authenticated PATCH request to an external API using an external user's account credentials. """ - 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 + url_64, request_options = _prepare_request(url, headers=headers, params=params) + return await _consume_async( + self._raw_client.patch( + url_64, + external_user_id=external_user_id, + account_id=account_id, + request=body or {}, + request_options=request_options, + ) + ) - async def patch( + async def delete( self, - url_64: str, + url: str, *, external_user_id: str, account_id: str, - request: typing.Dict[str, typing.Any], - request_options: typing.Optional[RequestOptions] = None, - ) -> typing.AsyncIterator[bytes]: + headers: typing.Optional[typing.Dict[str, typing.Any]] = None, + params: typing.Optional[typing.Dict[str, typing.Any]] = None, + ) -> _AsyncResult: """ - Forward an authenticated PATCH request to an external API using an external user's account credentials - - Parameters - ---------- - url_64 : str - Base64-encoded target URL - - external_user_id : str - The external user ID for the proxy request - - account_id : str - The account ID to use for authentication - - request : typing.Dict[str, typing.Any] - - 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 - ------- - typing.AsyncIterator[bytes] - proxy request successful - - Examples - -------- - import asyncio - - from pipedream import AsyncPipedream - - client = AsyncPipedream( - project_id="YOUR_PROJECT_ID", - client_id="YOUR_CLIENT_ID", - client_secret="YOUR_CLIENT_SECRET", - ) - - - async def main() -> None: - await client.proxy.patch( - url_64="url_64", - external_user_id="external_user_id", - account_id="account_id", - request={"string": {"key": "value"}}, - ) - - - asyncio.run(main()) + Forward an authenticated DELETE request to an external API using an external user's account credentials. """ - async with self._raw_client.patch( - url_64, - external_user_id=external_user_id, - account_id=account_id, - request=request, - request_options=request_options, - ) as r: - async for _chunk in r.data: - yield _chunk + url_64, request_options = _prepare_request(url, headers=headers, params=params) + return await _consume_async( + self._raw_client.delete( + url_64, + external_user_id=external_user_id, + account_id=account_id, + request_options=request_options, + ) + ) diff --git a/src/pipedream/proxy/raw_client.py b/src/pipedream/proxy/raw_client.py index 1af958d..d9fc875 100644 --- a/src/pipedream/proxy/raw_client.py +++ b/src/pipedream/proxy/raw_client.py @@ -1,9 +1,9 @@ -# This file was auto-generated by Fern from our API Definition. - import contextlib import typing from json.decoder import JSONDecodeError +from pydantic import ValidationError + from ..core.api_error import ApiError from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ..core.http_response import AsyncHttpResponse, HttpResponse @@ -12,11 +12,25 @@ from ..core.pydantic_utilities import parse_obj_as from ..core.request_options import RequestOptions from ..errors.too_many_requests_error import TooManyRequestsError -from pydantic import ValidationError +from ..types.proxy_response import ProxyResponse # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) +_ProxyData = typing.Optional[typing.Union[ProxyResponse, typing.Iterator[bytes]]] +_AsyncProxyData = typing.Optional[typing.Union[ProxyResponse, typing.AsyncIterator[bytes]]] + + +def _is_json_content_type(content_type: str) -> bool: + return "application/json" in content_type or not content_type + + +def _decode_error_body(_response: typing.Any) -> typing.Any: + error_content_type = _response.headers.get("content-type", "").lower() + if "application/json" in error_content_type: + return _response.json() + return _response.text + class RawProxyClient: def __init__(self, *, client_wrapper: SyncClientWrapper): @@ -30,9 +44,9 @@ def get( external_user_id: str, account_id: str, request_options: typing.Optional[RequestOptions] = None, - ) -> typing.Iterator[HttpResponse[typing.Iterator[bytes]]]: + ) -> typing.Iterator[HttpResponse[_ProxyData]]: """ - Forward an authenticated GET request to an external API using an external user's account credentials + Forward an authenticated GET request to an external API using an external user's account credentials. Parameters ---------- @@ -50,7 +64,7 @@ def get( Returns ------- - typing.Iterator[HttpResponse[typing.Iterator[bytes]]] + typing.Iterator[HttpResponse[typing.Optional[typing.Union[ProxyResponse, typing.Iterator[bytes]]]]] proxy request successful """ with self._client_wrapper.httpx_client.stream( @@ -62,41 +76,7 @@ def get( }, request_options=request_options, ) 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.Any, - parse_obj_as( - type_=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 - ) - except ValidationError as e: - raise ParsingError( - status_code=_response.status_code, - headers=dict(_response.headers), - body=_response.json(), - cause=e, - ) - raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) - - yield _stream() + yield _handle_sync_response(_response, request_options) @contextlib.contextmanager def post( @@ -105,32 +85,11 @@ def post( *, external_user_id: str, account_id: str, - request: typing.Dict[str, typing.Any], + request: typing.Dict[str, typing.Optional[typing.Any]], request_options: typing.Optional[RequestOptions] = None, - ) -> typing.Iterator[HttpResponse[typing.Iterator[bytes]]]: + ) -> typing.Iterator[HttpResponse[_ProxyData]]: """ - Forward an authenticated POST request to an external API using an external user's account credentials - - Parameters - ---------- - url_64 : str - Base64-encoded target URL - - external_user_id : str - The external user ID for the proxy request - - account_id : str - The account ID to use for authentication - - request : typing.Dict[str, typing.Any] - - 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 - ------- - typing.Iterator[HttpResponse[typing.Iterator[bytes]]] - proxy request successful + Forward an authenticated POST request to an external API using an external user's account credentials. """ with self._client_wrapper.httpx_client.stream( f"v1/connect/{encode_path_param(self._client_wrapper._project_id)}/proxy/{encode_path_param(url_64)}", @@ -140,47 +99,11 @@ def post( "account_id": account_id, }, json=request, - headers={ - "content-type": "application/json", - }, + headers={"content-type": "application/json"}, request_options=request_options, omit=OMIT, ) 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.Any, - parse_obj_as( - type_=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 - ) - except ValidationError as e: - raise ParsingError( - status_code=_response.status_code, - headers=dict(_response.headers), - body=_response.json(), - cause=e, - ) - raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) - - yield _stream() + yield _handle_sync_response(_response, request_options) @contextlib.contextmanager def put( @@ -189,32 +112,11 @@ def put( *, external_user_id: str, account_id: str, - request: typing.Dict[str, typing.Any], + request: typing.Dict[str, typing.Optional[typing.Any]], request_options: typing.Optional[RequestOptions] = None, - ) -> typing.Iterator[HttpResponse[typing.Iterator[bytes]]]: + ) -> typing.Iterator[HttpResponse[_ProxyData]]: """ - Forward an authenticated PUT request to an external API using an external user's account credentials - - Parameters - ---------- - url_64 : str - Base64-encoded target URL - - external_user_id : str - The external user ID for the proxy request - - account_id : str - The account ID to use for authentication - - request : typing.Dict[str, typing.Any] - - 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 - ------- - typing.Iterator[HttpResponse[typing.Iterator[bytes]]] - proxy request successful + Forward an authenticated PUT request to an external API using an external user's account credentials. """ with self._client_wrapper.httpx_client.stream( f"v1/connect/{encode_path_param(self._client_wrapper._project_id)}/proxy/{encode_path_param(url_64)}", @@ -224,207 +126,61 @@ def put( "account_id": account_id, }, json=request, - headers={ - "content-type": "application/json", - }, + headers={"content-type": "application/json"}, request_options=request_options, omit=OMIT, ) 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.Any, - parse_obj_as( - type_=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 - ) - except ValidationError as e: - raise ParsingError( - status_code=_response.status_code, - headers=dict(_response.headers), - body=_response.json(), - cause=e, - ) - raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) - - yield _stream() + yield _handle_sync_response(_response, request_options) @contextlib.contextmanager - def delete( + def patch( self, url_64: str, *, external_user_id: str, account_id: str, + request: typing.Dict[str, typing.Optional[typing.Any]], request_options: typing.Optional[RequestOptions] = None, - ) -> typing.Iterator[HttpResponse[typing.Iterator[bytes]]]: + ) -> typing.Iterator[HttpResponse[_ProxyData]]: """ - Forward an authenticated DELETE request to an external API using an external user's account credentials - - Parameters - ---------- - url_64 : str - Base64-encoded target URL - - external_user_id : str - The external user ID for the proxy request - - account_id : str - The account ID to use for authentication - - 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 - ------- - typing.Iterator[HttpResponse[typing.Iterator[bytes]]] - proxy request successful + Forward an authenticated PATCH request to an external API using an external user's account credentials. """ with self._client_wrapper.httpx_client.stream( f"v1/connect/{encode_path_param(self._client_wrapper._project_id)}/proxy/{encode_path_param(url_64)}", - method="DELETE", + method="PATCH", params={ "external_user_id": external_user_id, "account_id": account_id, }, + json=request, + headers={"content-type": "application/json"}, request_options=request_options, + omit=OMIT, ) 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.Any, - parse_obj_as( - type_=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 - ) - except ValidationError as e: - raise ParsingError( - status_code=_response.status_code, - headers=dict(_response.headers), - body=_response.json(), - cause=e, - ) - raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) - - yield _stream() + yield _handle_sync_response(_response, request_options) @contextlib.contextmanager - def patch( + def delete( self, url_64: str, *, external_user_id: str, account_id: str, - request: typing.Dict[str, typing.Any], request_options: typing.Optional[RequestOptions] = None, - ) -> typing.Iterator[HttpResponse[typing.Iterator[bytes]]]: + ) -> typing.Iterator[HttpResponse[_ProxyData]]: """ - Forward an authenticated PATCH request to an external API using an external user's account credentials - - Parameters - ---------- - url_64 : str - Base64-encoded target URL - - external_user_id : str - The external user ID for the proxy request - - account_id : str - The account ID to use for authentication - - request : typing.Dict[str, typing.Any] - - 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 - ------- - typing.Iterator[HttpResponse[typing.Iterator[bytes]]] - proxy request successful + Forward an authenticated DELETE request to an external API using an external user's account credentials. """ with self._client_wrapper.httpx_client.stream( f"v1/connect/{encode_path_param(self._client_wrapper._project_id)}/proxy/{encode_path_param(url_64)}", - method="PATCH", + method="DELETE", params={ "external_user_id": external_user_id, "account_id": account_id, }, - json=request, - headers={ - "content-type": "application/json", - }, request_options=request_options, - omit=OMIT, ) 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.Any, - parse_obj_as( - type_=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 - ) - except ValidationError as e: - raise ParsingError( - status_code=_response.status_code, - headers=dict(_response.headers), - body=_response.json(), - cause=e, - ) - raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) - - yield _stream() + yield _handle_sync_response(_response, request_options) class AsyncRawProxyClient: @@ -439,28 +195,9 @@ async def get( external_user_id: str, account_id: str, request_options: typing.Optional[RequestOptions] = None, - ) -> typing.AsyncIterator[AsyncHttpResponse[typing.AsyncIterator[bytes]]]: + ) -> typing.AsyncIterator[AsyncHttpResponse[_AsyncProxyData]]: """ - Forward an authenticated GET request to an external API using an external user's account credentials - - Parameters - ---------- - url_64 : str - Base64-encoded target URL - - external_user_id : str - The external user ID for the proxy request - - account_id : str - The account ID to use for authentication - - 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 - ------- - typing.AsyncIterator[AsyncHttpResponse[typing.AsyncIterator[bytes]]] - proxy request successful + Forward an authenticated GET request to an external API using an external user's account credentials. """ async with self._client_wrapper.httpx_client.stream( f"v1/connect/{encode_path_param(self._client_wrapper._project_id)}/proxy/{encode_path_param(url_64)}", @@ -471,42 +208,7 @@ async def get( }, request_options=request_options, ) 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.Any, - parse_obj_as( - type_=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 - ) - except ValidationError as e: - raise ParsingError( - status_code=_response.status_code, - headers=dict(_response.headers), - body=_response.json(), - cause=e, - ) - raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) - - yield await _stream() + yield await _handle_async_response(_response, request_options) @contextlib.asynccontextmanager async def post( @@ -515,32 +217,11 @@ async def post( *, external_user_id: str, account_id: str, - request: typing.Dict[str, typing.Any], + request: typing.Dict[str, typing.Optional[typing.Any]], request_options: typing.Optional[RequestOptions] = None, - ) -> typing.AsyncIterator[AsyncHttpResponse[typing.AsyncIterator[bytes]]]: + ) -> typing.AsyncIterator[AsyncHttpResponse[_AsyncProxyData]]: """ - Forward an authenticated POST request to an external API using an external user's account credentials - - Parameters - ---------- - url_64 : str - Base64-encoded target URL - - external_user_id : str - The external user ID for the proxy request - - account_id : str - The account ID to use for authentication - - request : typing.Dict[str, typing.Any] - - 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 - ------- - typing.AsyncIterator[AsyncHttpResponse[typing.AsyncIterator[bytes]]] - proxy request successful + Forward an authenticated POST request to an external API using an external user's account credentials. """ async with self._client_wrapper.httpx_client.stream( f"v1/connect/{encode_path_param(self._client_wrapper._project_id)}/proxy/{encode_path_param(url_64)}", @@ -550,48 +231,11 @@ async def post( "account_id": account_id, }, json=request, - headers={ - "content-type": "application/json", - }, + headers={"content-type": "application/json"}, request_options=request_options, omit=OMIT, ) 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.Any, - parse_obj_as( - type_=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 - ) - except ValidationError as e: - raise ParsingError( - status_code=_response.status_code, - headers=dict(_response.headers), - body=_response.json(), - cause=e, - ) - raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) - - yield await _stream() + yield await _handle_async_response(_response, request_options) @contextlib.asynccontextmanager async def put( @@ -600,32 +244,11 @@ async def put( *, external_user_id: str, account_id: str, - request: typing.Dict[str, typing.Any], + request: typing.Dict[str, typing.Optional[typing.Any]], request_options: typing.Optional[RequestOptions] = None, - ) -> typing.AsyncIterator[AsyncHttpResponse[typing.AsyncIterator[bytes]]]: + ) -> typing.AsyncIterator[AsyncHttpResponse[_AsyncProxyData]]: """ - Forward an authenticated PUT request to an external API using an external user's account credentials - - Parameters - ---------- - url_64 : str - Base64-encoded target URL - - external_user_id : str - The external user ID for the proxy request - - account_id : str - The account ID to use for authentication - - request : typing.Dict[str, typing.Any] - - 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 - ------- - typing.AsyncIterator[AsyncHttpResponse[typing.AsyncIterator[bytes]]] - proxy request successful + Forward an authenticated PUT request to an external API using an external user's account credentials. """ async with self._client_wrapper.httpx_client.stream( f"v1/connect/{encode_path_param(self._client_wrapper._project_id)}/proxy/{encode_path_param(url_64)}", @@ -635,207 +258,170 @@ async def put( "account_id": account_id, }, json=request, - headers={ - "content-type": "application/json", - }, + headers={"content-type": "application/json"}, request_options=request_options, omit=OMIT, ) 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.Any, - parse_obj_as( - type_=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 - ) - except ValidationError as e: - raise ParsingError( - status_code=_response.status_code, - headers=dict(_response.headers), - body=_response.json(), - cause=e, - ) - raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) - - yield await _stream() + yield await _handle_async_response(_response, request_options) @contextlib.asynccontextmanager - async def delete( + async def patch( self, url_64: str, *, external_user_id: str, account_id: str, + request: typing.Dict[str, typing.Optional[typing.Any]], request_options: typing.Optional[RequestOptions] = None, - ) -> typing.AsyncIterator[AsyncHttpResponse[typing.AsyncIterator[bytes]]]: + ) -> typing.AsyncIterator[AsyncHttpResponse[_AsyncProxyData]]: """ - Forward an authenticated DELETE request to an external API using an external user's account credentials - - Parameters - ---------- - url_64 : str - Base64-encoded target URL - - external_user_id : str - The external user ID for the proxy request - - account_id : str - The account ID to use for authentication - - 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 - ------- - typing.AsyncIterator[AsyncHttpResponse[typing.AsyncIterator[bytes]]] - proxy request successful + Forward an authenticated PATCH request to an external API using an external user's account credentials. """ async with self._client_wrapper.httpx_client.stream( f"v1/connect/{encode_path_param(self._client_wrapper._project_id)}/proxy/{encode_path_param(url_64)}", - method="DELETE", + method="PATCH", params={ "external_user_id": external_user_id, "account_id": account_id, }, + json=request, + headers={"content-type": "application/json"}, request_options=request_options, + omit=OMIT, ) 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.Any, - parse_obj_as( - type_=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 - ) - except ValidationError as e: - raise ParsingError( - status_code=_response.status_code, - headers=dict(_response.headers), - body=_response.json(), - cause=e, - ) - raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) - - yield await _stream() + yield await _handle_async_response(_response, request_options) @contextlib.asynccontextmanager - async def patch( + async def delete( self, url_64: str, *, external_user_id: str, account_id: str, - request: typing.Dict[str, typing.Any], request_options: typing.Optional[RequestOptions] = None, - ) -> typing.AsyncIterator[AsyncHttpResponse[typing.AsyncIterator[bytes]]]: + ) -> typing.AsyncIterator[AsyncHttpResponse[_AsyncProxyData]]: """ - Forward an authenticated PATCH request to an external API using an external user's account credentials - - Parameters - ---------- - url_64 : str - Base64-encoded target URL - - external_user_id : str - The external user ID for the proxy request - - account_id : str - The account ID to use for authentication - - request : typing.Dict[str, typing.Any] - - 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 - ------- - typing.AsyncIterator[AsyncHttpResponse[typing.AsyncIterator[bytes]]] - proxy request successful + Forward an authenticated DELETE request to an external API using an external user's account credentials. """ async with self._client_wrapper.httpx_client.stream( f"v1/connect/{encode_path_param(self._client_wrapper._project_id)}/proxy/{encode_path_param(url_64)}", - method="PATCH", + method="DELETE", params={ "external_user_id": external_user_id, "account_id": account_id, }, - json=request, - headers={ - "content-type": "application/json", - }, request_options=request_options, - omit=OMIT, ) 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.Any, - parse_obj_as( - type_=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 - ) - except ValidationError as e: - raise ParsingError( - status_code=_response.status_code, - headers=dict(_response.headers), - body=_response.json(), - cause=e, - ) - raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) - - yield await _stream() + yield await _handle_async_response(_response, request_options) + + +def _handle_sync_response( + _response: typing.Any, request_options: typing.Optional[RequestOptions] +) -> HttpResponse[_ProxyData]: + try: + if 200 <= _response.status_code < 300: + content_type = _response.headers.get("content-type", "").lower() + if _is_json_content_type(content_type): + _response.read() + if not _response.text.strip(): + return HttpResponse(response=_response, data=None) + _data = typing.cast( + ProxyResponse, + parse_obj_as( + type_=ProxyResponse, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _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_=_decode_error_body(_response), + ), + ), + ) + _response_body = _decode_error_body(_response) + except JSONDecodeError: + raise ApiError( + status_code=_response.status_code, + headers=dict(_response.headers), + body=_response.text, + ) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, + headers=dict(_response.headers), + body=_response.json(), + cause=e, + ) + raise ApiError( + status_code=_response.status_code, + headers=dict(_response.headers), + body=_response_body, + ) + + +async def _handle_async_response( + _response: typing.Any, request_options: typing.Optional[RequestOptions] +) -> AsyncHttpResponse[_AsyncProxyData]: + try: + if 200 <= _response.status_code < 300: + content_type = _response.headers.get("content-type", "").lower() + if _is_json_content_type(content_type): + await _response.aread() + if not _response.text.strip(): + return AsyncHttpResponse(response=_response, data=None) + _data = typing.cast( + ProxyResponse, + parse_obj_as( + type_=ProxyResponse, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _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_=_decode_error_body(_response), + ), + ), + ) + _response_body = _decode_error_body(_response) + except JSONDecodeError: + raise ApiError( + status_code=_response.status_code, + headers=dict(_response.headers), + body=_response.text, + ) + except ValidationError as e: + raise ParsingError( + status_code=_response.status_code, + headers=dict(_response.headers), + body=_response.json(), + cause=e, + ) + raise ApiError( + status_code=_response.status_code, + headers=dict(_response.headers), + body=_response_body, + ) diff --git a/src/pipedream/workflows/__init__.py b/src/pipedream/workflows/__init__.py new file mode 100644 index 0000000..395047f --- /dev/null +++ b/src/pipedream/workflows/__init__.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +from .client import AsyncWorkflowsClient, WorkflowsClient + +__all__ = ["AsyncWorkflowsClient", "WorkflowsClient"] \ No newline at end of file diff --git a/src/pipedream/workflows/client.py b/src/pipedream/workflows/client.py new file mode 100644 index 0000000..1f31604 --- /dev/null +++ b/src/pipedream/workflows/client.py @@ -0,0 +1,271 @@ +import enum +import re +import typing + +import httpx + +from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ..core.request_options import RequestOptions + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + +_DEFAULT_WORKFLOW_DOMAIN = "m.pipedream.net" +_ENDPOINT_ID_RE = re.compile(r"^e(n|o)[a-z0-9-]+$") + + +class HTTPAuthType(enum.Enum): + """Authentication types for workflow invocation.""" + + NONE = "none" + STATIC_BEARER = "static_bearer_token" + OAUTH = "oauth" + + +def _is_endpoint_id(url_or_endpoint: str) -> bool: + return bool(_ENDPOINT_ID_RE.match(url_or_endpoint)) + + +def _build_workflow_url(url_or_endpoint: str, *, workflow_domain: str) -> str: + if not url_or_endpoint: + raise ValueError("URL or endpoint ID is required") + + if url_or_endpoint.startswith(("http://", "https://")): + return url_or_endpoint + + if "." in url_or_endpoint and not _is_endpoint_id(url_or_endpoint): + return f"https://{url_or_endpoint}" + + if not _is_endpoint_id(url_or_endpoint): + raise ValueError(f"Invalid endpoint ID format: {url_or_endpoint}") + + return f"https://{url_or_endpoint}.{workflow_domain}" + + +def _prepare_headers( + headers: typing.Optional[typing.Dict[str, str]], + auth_type: HTTPAuthType, +) -> typing.Dict[str, str]: + request_headers = dict(headers) if headers else {} + if auth_type == HTTPAuthType.NONE: + # Suppress the default bearer token added by the client wrapper. + request_headers["Authorization"] = "" + return request_headers + + +def _add_external_user_id_header( + headers: typing.Optional[typing.Dict[str, str]], + external_user_id: str, +) -> typing.Dict[str, str]: + if not external_user_id: + raise ValueError("external_user_id is required") + request_headers = dict(headers) if headers else {} + request_headers["X-PD-External-User-ID"] = external_user_id + return request_headers + + +class WorkflowsClient: + def __init__( + self, + *, + client_wrapper: SyncClientWrapper, + workflow_domain: str = _DEFAULT_WORKFLOW_DOMAIN, + ): + self._client_wrapper = client_wrapper + self._workflow_domain = workflow_domain + + def invoke( + self, + url_or_endpoint: str, + *, + method: str = "POST", + body: typing.Optional[typing.Any] = None, + headers: typing.Optional[typing.Dict[str, str]] = None, + auth_type: HTTPAuthType = HTTPAuthType.NONE, + request_options: typing.Optional[RequestOptions] = None, + ) -> httpx.Response: + """ + Invoke a workflow via its HTTP interface URL or endpoint ID. + + Parameters + ---------- + url_or_endpoint : str + The full URL of the workflow's HTTP interface or the endpoint ID. + + method : str + HTTP method to use (default: "POST"). + + body : typing.Optional[typing.Any] + Request body. Dict/list values are serialized as JSON; other types are sent as raw form data. + + headers : typing.Optional[typing.Dict[str, str]] + Additional HTTP headers to include. + + auth_type : HTTPAuthType + Authentication mode (default: HTTPAuthType.NONE). + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + httpx.Response + Response returned by the invoked workflow. + + Examples + -------- + from pipedream import Pipedream, PipedreamEnvironment + from pipedream.workflows.client import HTTPAuthType + + client = Pipedream( + client_id="", + client_secret="", + environment=PipedreamEnvironment.PROD, + ) + response = client.workflows.invoke( + url_or_endpoint="https://your-workflow.m.pipedream.net", + method="POST", + body={"key": "value"}, + headers={"Content-Type": "application/json"}, + auth_type=HTTPAuthType.NONE, + ) + """ + workflow_url = _build_workflow_url(url_or_endpoint, workflow_domain=self._workflow_domain) + request_headers = _prepare_headers(headers, auth_type) + + response = self._client_wrapper.httpx_client.request( + workflow_url, + method=method, + data=body, + json=body, + headers=request_headers, + request_options=request_options, + ) + response.raise_for_status() + return response + + def invoke_for_external_user( + self, + url_or_endpoint: str, + *, + external_user_id: str, + method: str = "POST", + body: typing.Optional[typing.Any] = None, + headers: typing.Optional[typing.Dict[str, str]] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> httpx.Response: + """ + Invoke a workflow on behalf of a Pipedream Connect end-user. + + Forces OAuth authentication and adds the `X-PD-External-User-ID` header. + + Parameters + ---------- + url_or_endpoint : str + The full URL of the workflow's HTTP interface or the endpoint ID. + + external_user_id : str + The external user ID for whom the workflow is being invoked. + + method : str + HTTP method to use (default: "POST"). + + body : typing.Optional[typing.Any] + Request body. Dict/list values are serialized as JSON; other types are sent as raw form data. + + headers : typing.Optional[typing.Dict[str, str]] + Additional HTTP headers to include. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + httpx.Response + Response returned by the invoked workflow. + + Examples + -------- + from pipedream import Pipedream, PipedreamEnvironment + + client = Pipedream( + client_id="", + client_secret="", + environment=PipedreamEnvironment.PROD, + ) + response = client.workflows.invoke_for_external_user( + url_or_endpoint="en2r1n8a98np7", + external_user_id="user_123", + method="POST", + body={"message": "Hello from external user"}, + headers={"Content-Type": "application/json"}, + ) + """ + return self.invoke( + url_or_endpoint, + method=method, + body=body, + headers=_add_external_user_id_header(headers, external_user_id), + auth_type=HTTPAuthType.OAUTH, + request_options=request_options, + ) + + +class AsyncWorkflowsClient: + def __init__( + self, + *, + client_wrapper: AsyncClientWrapper, + workflow_domain: str = _DEFAULT_WORKFLOW_DOMAIN, + ): + self._client_wrapper = client_wrapper + self._workflow_domain = workflow_domain + + async def invoke( + self, + url_or_endpoint: str, + *, + method: str = "POST", + body: typing.Optional[typing.Any] = None, + headers: typing.Optional[typing.Dict[str, str]] = None, + auth_type: HTTPAuthType = HTTPAuthType.NONE, + request_options: typing.Optional[RequestOptions] = None, + ) -> httpx.Response: + """ + Async counterpart of `WorkflowsClient.invoke`. + """ + workflow_url = _build_workflow_url(url_or_endpoint, workflow_domain=self._workflow_domain) + request_headers = _prepare_headers(headers, auth_type) + + response = await self._client_wrapper.httpx_client.request( + workflow_url, + method=method, + data=body, + json=body, + headers=request_headers, + request_options=request_options, + ) + response.raise_for_status() + return response + + async def invoke_for_external_user( + self, + url_or_endpoint: str, + *, + external_user_id: str, + method: str = "POST", + body: typing.Optional[typing.Any] = None, + headers: typing.Optional[typing.Dict[str, str]] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> httpx.Response: + """ + Async counterpart of `WorkflowsClient.invoke_for_external_user`. + """ + return await self.invoke( + url_or_endpoint, + method=method, + body=body, + headers=_add_external_user_id_header(headers, external_user_id), + auth_type=HTTPAuthType.OAUTH, + request_options=request_options, + )