diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..9818c03 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,61 @@ +name: ci + +on: [push] +jobs: + compile: + runs-on: ubuntu-latest + steps: + - name: Checkout repo + uses: actions/checkout@v4 + - name: Set up python + uses: actions/setup-python@v4 + with: + python-version: 3.8 + - name: Bootstrap poetry + run: | + curl -sSL https://install.python-poetry.org | python - -y --version 1.5.1 + - name: Install dependencies + run: poetry install + - name: Compile + run: poetry run mypy . + test: + runs-on: ubuntu-latest + steps: + - name: Checkout repo + uses: actions/checkout@v4 + - name: Set up python + uses: actions/setup-python@v4 + with: + python-version: 3.8 + - name: Bootstrap poetry + run: | + curl -sSL https://install.python-poetry.org | python - -y --version 1.5.1 + - name: Install dependencies + run: poetry install + + - name: Test + run: poetry run pytest -rP . + + publish: + needs: [compile, test] + if: github.event_name == 'push' && contains(github.ref, 'refs/tags/') + runs-on: ubuntu-latest + steps: + - name: Checkout repo + uses: actions/checkout@v4 + - name: Set up python + uses: actions/setup-python@v4 + with: + python-version: 3.8 + - name: Bootstrap poetry + run: | + 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 }} diff --git a/.gitignore b/.gitignore index 7b004e5..d2e4ca8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,194 +1,5 @@ -# Byte-compiled / optimized / DLL files -__pycache__/ -*.py[cod] -*$py.class - -# C extensions -*.so - -# Distribution / packaging -.Python -build/ -develop-eggs/ -dist/ -downloads/ -eggs/ -.eggs/ -lib/ -lib64/ -parts/ -sdist/ -var/ -wheels/ -share/python-wheels/ -*.egg-info/ -.installed.cfg -*.egg -MANIFEST - -# PyInstaller -# Usually these files are written by a python script from a template -# before PyInstaller builds the exe, so as to inject date/other infos into it. -*.manifest -*.spec - -# Installer logs -pip-log.txt -pip-delete-this-directory.txt - -# Unit test / coverage reports -htmlcov/ -.tox/ -.nox/ -.coverage -.coverage.* -.cache -nosetests.xml -coverage.xml -*.cover -*.py,cover -.hypothesis/ -.pytest_cache/ -cover/ - -# Translations -*.mo -*.pot - -# Django stuff: -*.log -local_settings.py -db.sqlite3 -db.sqlite3-journal - -# Flask stuff: -instance/ -.webassets-cache - -# Scrapy stuff: -.scrapy - -# Sphinx documentation -docs/_build/ - -# PyBuilder -.pybuilder/ -target/ - -# Jupyter Notebook -.ipynb_checkpoints - -# IPython -profile_default/ -ipython_config.py - -# pyenv -# For a library or package, you might want to ignore these files since the code is -# intended to run in multiple environments; otherwise, check them in: -# .python-version - -# pipenv -# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. -# However, in case of collaboration, if having platform-specific dependencies or dependencies -# having no cross-platform support, pipenv may install dependencies that don't work, or not -# install all needed dependencies. -#Pipfile.lock - -# UV -# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control. -# This is especially recommended for binary packages to ensure reproducibility, and is more -# commonly ignored for libraries. -#uv.lock - -# poetry -# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. -# This is especially recommended for binary packages to ensure reproducibility, and is more -# commonly ignored for libraries. -# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control -#poetry.lock - -# pdm -# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. -#pdm.lock -# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it -# in version control. -# https://pdm.fming.dev/latest/usage/project/#working-with-version-control -.pdm.toml -.pdm-python -.pdm-build/ - -# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm -__pypackages__/ - -# Celery stuff -celerybeat-schedule -celerybeat.pid - -# SageMath parsed files -*.sage.py - -# Environments -.env -.venv -env/ -venv/ -ENV/ -env.bak/ -venv.bak/ - -# Spyder project settings -.spyderproject -.spyproject - -# Rope project settings -.ropeproject - -# mkdocs documentation -/site - -# mypy .mypy_cache/ -.dmypy.json -dmypy.json - -# Pyre type checker -.pyre/ - -# pytype static type analyzer -.pytype/ - -# Cython debug symbols -cython_debug/ - -# PyCharm -# JetBrains specific template is maintained in a separate JetBrains.gitignore that can -# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore -# and can be added to the global gitignore or merged into this file. For a more nuclear -# option (not recommended) you can uncomment the following to ignore the entire idea folder. -#.idea/ - -# Abstra -# Abstra is an AI-powered process automation framework. -# Ignore directories containing user credentials, local state, and settings. -# Learn more at https://abstra.io/docs -.abstra/ - -# Visual Studio Code -# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore -# that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore -# and can be added to the global gitignore or merged into this file. However, if you prefer, -# you could uncomment the following to ignore the enitre vscode folder -# .vscode/ - -# Ruff stuff: .ruff_cache/ - -# PyPI configuration file -.pypirc - -# Cursor -# Cursor is an AI-powered code editor. `.cursorignore` specifies files/directories to -# exclude from AI features like autocomplete and code analysis. Recommended for sensitive data -# refer to https://docs.cursor.com/context/ignore-files -.cursorignore -.cursorindexingignore \ No newline at end of file +__pycache__/ +dist/ +poetry.toml diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 16feac0..0000000 --- a/LICENSE +++ /dev/null @@ -1,123 +0,0 @@ -Pipedream Source Available License Version 1.0 - -This Pipedream Source Available License Agreement Version 1.0 (this -“Agreement”) sets forth the terms on which Pipedream, Inc., a Delaware -corporation (“Pipedream”) makes available certain software (the -“Software”). By installing, downloading, accessing, using or -distributing the Software, you agree to the terms of this -Agreement. If you do not agree to such terms, you must not use the -Software. If you are receiving the Software on behalf of a legal -entity, you represent and warrant that you have the actual authority -to agree to the terms and conditions of this Agreement on behalf of -such entity. “Licensee” means you, an individual, or the entity on -whose behalf you are receiving the Software. - -LICENSE GRANT AND CONDITIONS. - -1.1 License. Subject to the terms and conditions of this Agreement, -Pipedream hereby grants to Licensee a non-exclusive, royalty-free, -worldwide, non-transferable, non-sublicenseable license during the -term of this Agreement to use, prepare modifications and derivative -works, distribute (including without limitation in source code or -object code form) and reproduce copies of the Software (the -“License”). Licensee is not granted the right to, and Licensee shall -not, exercise the License for an Excluded Purpose. For purposes of -this Agreement, “Excluded Purpose” means any commercial use of the -software including, but not limited to, making available any -software-as-a-service, platform-as-a-service, -infrastructure-as-a-service or other online service that competes with -the Software or any other Pipedream products or services. - -1.2 Conditions. In consideration of the License, Licensee’s -distribution of the Software is subject to the following conditions: - -a. Licensee must cause any Software modified by Licensee to carry -prominent notices stating that Licensee modified the Software. - -b. On each Software copy, Licensee shall reproduce and not remove or -alter all Pipedream or third party copyright or other proprietary -notices contained in the Software, and Licensee must provide this with -each copy: “This software is made available by Pipedream, Inc., under -the terms of the Pipedream Source Available License, Version 1.0 -located at -https://github.com/PipedreamHQ/pipedream/blob/master/LICENSE. By -installing, downloading, accessing, using or distributing the -Software, you agree to the terms of such License Agreement.” - -1.3 Modifications. Licensee may add its own copyright notices to -modifications made by Licensee and may provide additional or different -license terms and conditions for use, reproduction, or distribution of -Licensee’s modifications. While redistributing the Software or -modifications thereof, Licensee may choose to offer, for a fee or free -of charge, support, warranty, indemnity, or other -obligations. Licensee, and not Pipedream, will be responsible for any -such obligations. - -1.4 No Sublicensing. The License does not include the right to -sublicense the Software; provided, however, that any recipient to -which Licensee provides the Software may exercise the License so long -as such recipient agrees to the terms and conditions of this -Agreement. - -TERM AND TERMINATION. - -This Agreement will continue unless and until earlier terminated as -set forth herein. If Licensee breaches any of its conditions or -obligations under this Agreement, this Agreement will terminate -automatically and the License will terminate automatically and -permanently. - -INTELLECTUAL PROPERTY. - -As between the parties, Pipedream retains all right, title, and -interest in the Software, and all intellectual property rights -therein. Pipedream hereby reserves all rights not expressly granted to -Licensee in this Agreement. Pipedream reserves all rights in its -trademarks and service marks, and no licenses thereto are granted by -this Agreement. - -DISCLAIMER. - -PIPEDREAM HEREBY DISCLAIMS ANY AND ALL WARRANTIES AND CONDITIONS, -EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, AND SPECIFICALLY DISCLAIMS -ANY WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, -WITH RESPECT TO THE SOFTWARE. - -LIMITATION OF LIABILITY. - -PIPEDREAM WILL NOT BE LIABLE FOR ANY DAMAGES OF ANY KIND, INCLUDING -BUT NOT LIMITED TO, LOST PROFITS OR ANY CONSEQUENTIAL, SPECIAL, -INCIDENTAL, INDIRECT, OR DIRECT DAMAGES, HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, ARISING OUT OF THIS AGREEMENT. THE FOREGOING -SHALL APPLY TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW. - -GENERAL. - -6.1 Governing Law. This Agreement will be governed by and interpreted -in accordance with the laws of the state of California, without -reference to its conflict of laws principles. If Licensee is located -outside of the United States, any dispute, controversy or claim -arising out of or relating to this Agreement will be referred to and -finally determined by arbitration in accordance with the JAMS -International Arbitration Rules. The tribunal will consist of one -arbitrator. Judgment upon the award rendered by the arbitrator may be -entered in any court having jurisdiction thereof. All disputes -including arbitrations shall take place in Santa Clara County, -California. The language to be used in any such proceedings shall be -English. - -6.2. Assignment. Licensee is not authorized to assign its rights -under this Agreement to any third party. Pipedream may freely assign -its rights under this Agreement to any third party. - -6.3. Other. This Agreement is the entire agreement between the -parties regarding the subject matter hereof. No amendment or -modification of this Agreement will be valid or binding upon the -parties unless made in writing and signed by the duly authorized -representatives of both parties. In the event that any provision, -including without limitation any condition, of this Agreement is held -to be unenforceable, this Agreement and all licenses and rights -granted hereunder will immediately terminate. Waiver by Pipedream of a -breach of any provision of this Agreement or the failure by Pipedream -to exercise any right hereunder will not be construed as a waiver of -any subsequent breach of that right or as a waiver of any other right. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..9c5abb7 --- /dev/null +++ b/README.md @@ -0,0 +1,193 @@ +# Pipedream Python Library + +[![fern shield](https://img.shields.io/badge/%F0%9F%8C%BF-Built%20with%20Fern-brightgreen)](https://buildwithfern.com?utm_source=github&utm_medium=github&utm_campaign=readme&utm_source=https%3A%2F%2Fgithub.com%2FPipedreamHQ%2Fpipedream-sdk-python) +[![pypi](https://img.shields.io/pypi/v/pipedream)](https://pypi.python.org/pypi/pipedream) + +The Pipedream Python library provides convenient access to the Pipedream API from Python. + +## Installation + +```sh +pip install pipedream +``` + +## Reference + +A full reference for this library is available [here](https://github.com/PipedreamHQ/pipedream-sdk-python/blob/HEAD/./reference.md). + +## Usage + +Instantiate and use the client with the following: + +```python +from pipedream import Pipedream + +client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", +) +client.accounts.create( + project_id="project_id", + app_slug="app_slug", + cfmap_json="cfmap_json", + connect_token="connect_token", +) +``` + +## Async Client + +The SDK also exports an `async` client so that you can make non-blocking calls to our API. + +```python +import asyncio + +from pipedream import AsyncPipedream + +client = AsyncPipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", +) + + +async def main() -> None: + await client.accounts.create( + project_id="project_id", + app_slug="app_slug", + cfmap_json="cfmap_json", + connect_token="connect_token", + ) + + +asyncio.run(main()) +``` + +## Exception Handling + +When the API returns a non-success status code (4xx or 5xx response), a subclass of the following error +will be thrown. + +```python +from pipedream.core.api_error import ApiError + +try: + client.accounts.create(...) +except ApiError as e: + print(e.status_code) + print(e.body) +``` + +## Pagination + +Paginated requests will return a `SyncPager` or `AsyncPager`, which can be used as generators for the underlying object. + +```python +from pipedream import Pipedream + +client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", +) +response = client.apps.list() +for item in response: + yield item +# alternatively, you can paginate page-by-page +for page in response.iter_pages(): + yield page +``` + +## Advanced + +### Access Raw Response Data + +The SDK provides access to raw response data, including headers, through the `.with_raw_response` property. +The `.with_raw_response` property returns a "raw" client that can be used to access the `.headers` and `.data` attributes. + +```python +from pipedream import Pipedream + +client = Pipedream( + ..., +) +response = client.accounts.with_raw_response.create(...) +print(response.headers) # access the response headers +print(response.data) # access the underlying object +pager = client.apps.list(...) +print(pager.response.headers) # access the response headers for the first page +for item in pager: + print(item) # access the underlying object(s) +for page in pager.iter_pages(): + print(page.response.headers) # access the response headers for each page + for item in page: + print(item) # access the underlying object(s) +``` + +### Retries + +The SDK is instrumented with automatic retries with exponential backoff. A request will be retried as long +as the request is deemed retryable and the number of retry attempts has not grown larger than the configured +retry limit (default: 2). + +A request is deemed retryable when any of the following HTTP status codes is returned: + +- [408](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/408) (Timeout) +- [429](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/429) (Too Many Requests) +- [5XX](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/500) (Internal Server Errors) + +Use the `max_retries` request option to configure this behavior. + +```python +client.accounts.create(..., request_options={ + "max_retries": 1 +}) +``` + +### Timeouts + +The SDK defaults to a 60 second timeout. You can configure this with a timeout option at the client or request level. + +```python + +from pipedream import Pipedream + +client = Pipedream( + ..., + timeout=20.0, +) + + +# Override timeout for a specific method +client.accounts.create(..., request_options={ + "timeout_in_seconds": 1 +}) +``` + +### Custom Client + +You can override the `httpx` client to customize it for your use-case. Some common use-cases include support for proxies +and transports. + +```python +import httpx +from pipedream import Pipedream + +client = Pipedream( + ..., + httpx_client=httpx.Client( + proxies="http://my.test.proxy.example.com", + transport=httpx.HTTPTransport(local_address="0.0.0.0"), + ), +) +``` + +## Contributing + +While we value open-source contributions to this SDK, this library is generated programmatically. +Additions made directly to this library would have to be moved over to our generation code, +otherwise they would be overwritten upon the next generated release. Feel free to open a PR as +a proof of concept, but know that we will not be able to merge it as-is. We suggest opening +an issue first to discuss with us! + +On the other hand, contributions to the README are always very welcome! diff --git a/poetry.lock b/poetry.lock new file mode 100644 index 0000000..3ddef64 --- /dev/null +++ b/poetry.lock @@ -0,0 +1,550 @@ +# This file is automatically @generated by Poetry 1.8.5 and should not be changed by hand. + +[[package]] +name = "annotated-types" +version = "0.7.0" +description = "Reusable constraint types to use with typing.Annotated" +optional = false +python-versions = ">=3.8" +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"}, +] + +[package.dependencies] +typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.9\""} + +[[package]] +name = "anyio" +version = "4.5.2" +description = "High level compatibility layer for multiple asynchronous event loop implementations" +optional = false +python-versions = ">=3.8" +files = [ + {file = "anyio-4.5.2-py3-none-any.whl", hash = "sha256:c011ee36bc1e8ba40e5a81cb9df91925c218fe9b778554e0b56a21e1b5d4716f"}, + {file = "anyio-4.5.2.tar.gz", hash = "sha256:23009af4ed04ce05991845451e11ef02fc7c5ed29179ac9a420e5ad0ac7ddc5b"}, +] + +[package.dependencies] +exceptiongroup = {version = ">=1.0.2", markers = "python_version < \"3.11\""} +idna = ">=2.8" +sniffio = ">=1.1" +typing-extensions = {version = ">=4.1", markers = "python_version < \"3.11\""} + +[package.extras] +doc = ["Sphinx (>=7.4,<8.0)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"] +test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "truststore (>=0.9.1)", "uvloop (>=0.21.0b1)"] +trio = ["trio (>=0.26.1)"] + +[[package]] +name = "certifi" +version = "2025.6.15" +description = "Python package for providing Mozilla's CA Bundle." +optional = false +python-versions = ">=3.7" +files = [ + {file = "certifi-2025.6.15-py3-none-any.whl", hash = "sha256:2e0c7ce7cb5d8f8634ca55d2ba7e6ec2689a2fd6537d8dec1296a477a4910057"}, + {file = "certifi-2025.6.15.tar.gz", hash = "sha256:d747aa5a8b9bbbb1bb8c22bb13e22bd1f18e9796defa16bab421f7f7a317323b"}, +] + +[[package]] +name = "colorama" +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" +files = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] + +[[package]] +name = "exceptiongroup" +version = "1.3.0" +description = "Backport of PEP 654 (exception groups)" +optional = false +python-versions = ">=3.7" +files = [ + {file = "exceptiongroup-1.3.0-py3-none-any.whl", hash = "sha256:4d111e6e0c13d0644cad6ddaa7ed0261a0b36971f6d23e7ec9b4b9097da78a10"}, + {file = "exceptiongroup-1.3.0.tar.gz", hash = "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88"}, +] + +[package.dependencies] +typing-extensions = {version = ">=4.6.0", markers = "python_version < \"3.13\""} + +[package.extras] +test = ["pytest (>=6)"] + +[[package]] +name = "h11" +version = "0.16.0" +description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" +optional = false +python-versions = ">=3.8" +files = [ + {file = "h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86"}, + {file = "h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1"}, +] + +[[package]] +name = "httpcore" +version = "1.0.9" +description = "A minimal low-level HTTP client." +optional = false +python-versions = ">=3.8" +files = [ + {file = "httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55"}, + {file = "httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8"}, +] + +[package.dependencies] +certifi = "*" +h11 = ">=0.16" + +[package.extras] +asyncio = ["anyio (>=4.0,<5.0)"] +http2 = ["h2 (>=3,<5)"] +socks = ["socksio (==1.*)"] +trio = ["trio (>=0.22.0,<1.0)"] + +[[package]] +name = "httpx" +version = "0.28.1" +description = "The next generation HTTP client." +optional = false +python-versions = ">=3.8" +files = [ + {file = "httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad"}, + {file = "httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc"}, +] + +[package.dependencies] +anyio = "*" +certifi = "*" +httpcore = "==1.*" +idna = "*" + +[package.extras] +brotli = ["brotli", "brotlicffi"] +cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"] +http2 = ["h2 (>=3,<5)"] +socks = ["socksio (==1.*)"] +zstd = ["zstandard (>=0.18.0)"] + +[[package]] +name = "idna" +version = "3.10" +description = "Internationalized Domain Names in Applications (IDNA)" +optional = false +python-versions = ">=3.6" +files = [ + {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, + {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, +] + +[package.extras] +all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] + +[[package]] +name = "iniconfig" +version = "2.1.0" +description = "brain-dead simple config-ini parsing" +optional = false +python-versions = ">=3.8" +files = [ + {file = "iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760"}, + {file = "iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7"}, +] + +[[package]] +name = "mypy" +version = "1.13.0" +description = "Optional static typing for Python" +optional = false +python-versions = ">=3.8" +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"}, + {file = "mypy-1.13.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7b2353a44d2179846a096e25691d54d59904559f4232519d420d64da6828a3a7"}, + {file = "mypy-1.13.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0730d1c6a2739d4511dc4253f8274cdd140c55c32dfb0a4cf8b7a43f40abfa6f"}, + {file = "mypy-1.13.0-cp310-cp310-win_amd64.whl", hash = "sha256:c5fc54dbb712ff5e5a0fca797e6e0aa25726c7e72c6a5850cfd2adbc1eb0a372"}, + {file = "mypy-1.13.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:581665e6f3a8a9078f28d5502f4c334c0c8d802ef55ea0e7276a6e409bc0d82d"}, + {file = "mypy-1.13.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3ddb5b9bf82e05cc9a627e84707b528e5c7caaa1c55c69e175abb15a761cec2d"}, + {file = "mypy-1.13.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:20c7ee0bc0d5a9595c46f38beb04201f2620065a93755704e141fcac9f59db2b"}, + {file = "mypy-1.13.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3790ded76f0b34bc9c8ba4def8f919dd6a46db0f5a6610fb994fe8efdd447f73"}, + {file = "mypy-1.13.0-cp311-cp311-win_amd64.whl", hash = "sha256:51f869f4b6b538229c1d1bcc1dd7d119817206e2bc54e8e374b3dfa202defcca"}, + {file = "mypy-1.13.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:5c7051a3461ae84dfb5dd15eff5094640c61c5f22257c8b766794e6dd85e72d5"}, + {file = "mypy-1.13.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:39bb21c69a5d6342f4ce526e4584bc5c197fd20a60d14a8624d8743fffb9472e"}, + {file = "mypy-1.13.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:164f28cb9d6367439031f4c81e84d3ccaa1e19232d9d05d37cb0bd880d3f93c2"}, + {file = "mypy-1.13.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a4c1bfcdbce96ff5d96fc9b08e3831acb30dc44ab02671eca5953eadad07d6d0"}, + {file = "mypy-1.13.0-cp312-cp312-win_amd64.whl", hash = "sha256:a0affb3a79a256b4183ba09811e3577c5163ed06685e4d4b46429a271ba174d2"}, + {file = "mypy-1.13.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a7b44178c9760ce1a43f544e595d35ed61ac2c3de306599fa59b38a6048e1aa7"}, + {file = "mypy-1.13.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5d5092efb8516d08440e36626f0153b5006d4088c1d663d88bf79625af3d1d62"}, + {file = "mypy-1.13.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:de2904956dac40ced10931ac967ae63c5089bd498542194b436eb097a9f77bc8"}, + {file = "mypy-1.13.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:7bfd8836970d33c2105562650656b6846149374dc8ed77d98424b40b09340ba7"}, + {file = "mypy-1.13.0-cp313-cp313-win_amd64.whl", hash = "sha256:9f73dba9ec77acb86457a8fc04b5239822df0c14a082564737833d2963677dbc"}, + {file = "mypy-1.13.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:100fac22ce82925f676a734af0db922ecfea991e1d7ec0ceb1e115ebe501301a"}, + {file = "mypy-1.13.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7bcb0bb7f42a978bb323a7c88f1081d1b5dee77ca86f4100735a6f541299d8fb"}, + {file = "mypy-1.13.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bde31fc887c213e223bbfc34328070996061b0833b0a4cfec53745ed61f3519b"}, + {file = "mypy-1.13.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:07de989f89786f62b937851295ed62e51774722e5444a27cecca993fc3f9cd74"}, + {file = "mypy-1.13.0-cp38-cp38-win_amd64.whl", hash = "sha256:4bde84334fbe19bad704b3f5b78c4abd35ff1026f8ba72b29de70dda0916beb6"}, + {file = "mypy-1.13.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0246bcb1b5de7f08f2826451abd947bf656945209b140d16ed317f65a17dc7dc"}, + {file = "mypy-1.13.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:7f5b7deae912cf8b77e990b9280f170381fdfbddf61b4ef80927edd813163732"}, + {file = "mypy-1.13.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7029881ec6ffb8bc233a4fa364736789582c738217b133f1b55967115288a2bc"}, + {file = "mypy-1.13.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:3e38b980e5681f28f033f3be86b099a247b13c491f14bb8b1e1e134d23bb599d"}, + {file = "mypy-1.13.0-cp39-cp39-win_amd64.whl", hash = "sha256:a6789be98a2017c912ae6ccb77ea553bbaf13d27605d2ca20a76dfbced631b24"}, + {file = "mypy-1.13.0-py3-none-any.whl", hash = "sha256:9c250883f9fd81d212e0952c92dbfcc96fc237f4b7c92f56ac81fd48460b3e5a"}, + {file = "mypy-1.13.0.tar.gz", hash = "sha256:0291a61b6fbf3e6673e3405cfcc0e7650bebc7939659fdca2702958038bd835e"}, +] + +[package.dependencies] +mypy-extensions = ">=1.0.0" +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} +typing-extensions = ">=4.6.0" + +[package.extras] +dmypy = ["psutil (>=4.0)"] +faster-cache = ["orjson"] +install-types = ["pip"] +mypyc = ["setuptools (>=50)"] +reports = ["lxml"] + +[[package]] +name = "mypy-extensions" +version = "1.1.0" +description = "Type system extensions for programs checked with the mypy type checker." +optional = false +python-versions = ">=3.8" +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"}, +] + +[[package]] +name = "packaging" +version = "25.0" +description = "Core utilities for Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484"}, + {file = "packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f"}, +] + +[[package]] +name = "pluggy" +version = "1.5.0" +description = "plugin and hook calling mechanisms for python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, + {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, +] + +[package.extras] +dev = ["pre-commit", "tox"] +testing = ["pytest", "pytest-benchmark"] + +[[package]] +name = "pydantic" +version = "2.10.6" +description = "Data validation using Python type hints" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pydantic-2.10.6-py3-none-any.whl", hash = "sha256:427d664bf0b8a2b34ff5dd0f5a18df00591adcee7198fbd71981054cef37b584"}, + {file = "pydantic-2.10.6.tar.gz", hash = "sha256:ca5daa827cce33de7a42be142548b0096bf05a7e7b365aebfa5f8eeec7128236"}, +] + +[package.dependencies] +annotated-types = ">=0.6.0" +pydantic-core = "2.27.2" +typing-extensions = ">=4.12.2" + +[package.extras] +email = ["email-validator (>=2.0.0)"] +timezone = ["tzdata"] + +[[package]] +name = "pydantic-core" +version = "2.27.2" +description = "Core functionality for Pydantic validation and serialization" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pydantic_core-2.27.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2d367ca20b2f14095a8f4fa1210f5a7b78b8a20009ecced6b12818f455b1e9fa"}, + {file = "pydantic_core-2.27.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:491a2b73db93fab69731eaee494f320faa4e093dbed776be1a829c2eb222c34c"}, + {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7969e133a6f183be60e9f6f56bfae753585680f3b7307a8e555a948d443cc05a"}, + {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3de9961f2a346257caf0aa508a4da705467f53778e9ef6fe744c038119737ef5"}, + {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e2bb4d3e5873c37bb3dd58714d4cd0b0e6238cebc4177ac8fe878f8b3aa8e74c"}, + {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:280d219beebb0752699480fe8f1dc61ab6615c2046d76b7ab7ee38858de0a4e7"}, + {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47956ae78b6422cbd46f772f1746799cbb862de838fd8d1fbd34a82e05b0983a"}, + {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:14d4a5c49d2f009d62a2a7140d3064f686d17a5d1a268bc641954ba181880236"}, + {file = "pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:337b443af21d488716f8d0b6164de833e788aa6bd7e3a39c005febc1284f4962"}, + {file = "pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:03d0f86ea3184a12f41a2d23f7ccb79cdb5a18e06993f8a45baa8dfec746f0e9"}, + {file = "pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7041c36f5680c6e0f08d922aed302e98b3745d97fe1589db0a3eebf6624523af"}, + {file = "pydantic_core-2.27.2-cp310-cp310-win32.whl", hash = "sha256:50a68f3e3819077be2c98110c1f9dcb3817e93f267ba80a2c05bb4f8799e2ff4"}, + {file = "pydantic_core-2.27.2-cp310-cp310-win_amd64.whl", hash = "sha256:e0fd26b16394ead34a424eecf8a31a1f5137094cabe84a1bcb10fa6ba39d3d31"}, + {file = "pydantic_core-2.27.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:8e10c99ef58cfdf2a66fc15d66b16c4a04f62bca39db589ae8cba08bc55331bc"}, + {file = "pydantic_core-2.27.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:26f32e0adf166a84d0cb63be85c562ca8a6fa8de28e5f0d92250c6b7e9e2aff7"}, + {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c19d1ea0673cd13cc2f872f6c9ab42acc4e4f492a7ca9d3795ce2b112dd7e15"}, + {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5e68c4446fe0810e959cdff46ab0a41ce2f2c86d227d96dc3847af0ba7def306"}, + {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d9640b0059ff4f14d1f37321b94061c6db164fbe49b334b31643e0528d100d99"}, + {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:40d02e7d45c9f8af700f3452f329ead92da4c5f4317ca9b896de7ce7199ea459"}, + {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1c1fd185014191700554795c99b347d64f2bb637966c4cfc16998a0ca700d048"}, + {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d81d2068e1c1228a565af076598f9e7451712700b673de8f502f0334f281387d"}, + {file = "pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:1a4207639fb02ec2dbb76227d7c751a20b1a6b4bc52850568e52260cae64ca3b"}, + {file = "pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:3de3ce3c9ddc8bbd88f6e0e304dea0e66d843ec9de1b0042b0911c1663ffd474"}, + {file = "pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:30c5f68ded0c36466acede341551106821043e9afaad516adfb6e8fa80a4e6a6"}, + {file = "pydantic_core-2.27.2-cp311-cp311-win32.whl", hash = "sha256:c70c26d2c99f78b125a3459f8afe1aed4d9687c24fd677c6a4436bc042e50d6c"}, + {file = "pydantic_core-2.27.2-cp311-cp311-win_amd64.whl", hash = "sha256:08e125dbdc505fa69ca7d9c499639ab6407cfa909214d500897d02afb816e7cc"}, + {file = "pydantic_core-2.27.2-cp311-cp311-win_arm64.whl", hash = "sha256:26f0d68d4b235a2bae0c3fc585c585b4ecc51382db0e3ba402a22cbc440915e4"}, + {file = "pydantic_core-2.27.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:9e0c8cfefa0ef83b4da9588448b6d8d2a2bf1a53c3f1ae5fca39eb3061e2f0b0"}, + {file = "pydantic_core-2.27.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:83097677b8e3bd7eaa6775720ec8e0405f1575015a463285a92bfdfe254529ef"}, + {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:172fce187655fece0c90d90a678424b013f8fbb0ca8b036ac266749c09438cb7"}, + {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:519f29f5213271eeeeb3093f662ba2fd512b91c5f188f3bb7b27bc5973816934"}, + {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:05e3a55d124407fffba0dd6b0c0cd056d10e983ceb4e5dbd10dda135c31071d6"}, + {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9c3ed807c7b91de05e63930188f19e921d1fe90de6b4f5cd43ee7fcc3525cb8c"}, + {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fb4aadc0b9a0c063206846d603b92030eb6f03069151a625667f982887153e2"}, + {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:28ccb213807e037460326424ceb8b5245acb88f32f3d2777427476e1b32c48c4"}, + {file = "pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:de3cd1899e2c279b140adde9357c4495ed9d47131b4a4eaff9052f23398076b3"}, + {file = "pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:220f892729375e2d736b97d0e51466252ad84c51857d4d15f5e9692f9ef12be4"}, + {file = "pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a0fcd29cd6b4e74fe8ddd2c90330fd8edf2e30cb52acda47f06dd615ae72da57"}, + {file = "pydantic_core-2.27.2-cp312-cp312-win32.whl", hash = "sha256:1e2cb691ed9834cd6a8be61228471d0a503731abfb42f82458ff27be7b2186fc"}, + {file = "pydantic_core-2.27.2-cp312-cp312-win_amd64.whl", hash = "sha256:cc3f1a99a4f4f9dd1de4fe0312c114e740b5ddead65bb4102884b384c15d8bc9"}, + {file = "pydantic_core-2.27.2-cp312-cp312-win_arm64.whl", hash = "sha256:3911ac9284cd8a1792d3cb26a2da18f3ca26c6908cc434a18f730dc0db7bfa3b"}, + {file = "pydantic_core-2.27.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:7d14bd329640e63852364c306f4d23eb744e0f8193148d4044dd3dacdaacbd8b"}, + {file = "pydantic_core-2.27.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:82f91663004eb8ed30ff478d77c4d1179b3563df6cdb15c0817cd1cdaf34d154"}, + {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:71b24c7d61131bb83df10cc7e687433609963a944ccf45190cfc21e0887b08c9"}, + {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fa8e459d4954f608fa26116118bb67f56b93b209c39b008277ace29937453dc9"}, + {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce8918cbebc8da707ba805b7fd0b382816858728ae7fe19a942080c24e5b7cd1"}, + {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eda3f5c2a021bbc5d976107bb302e0131351c2ba54343f8a496dc8783d3d3a6a"}, + {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd8086fa684c4775c27f03f062cbb9eaa6e17f064307e86b21b9e0abc9c0f02e"}, + {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8d9b3388db186ba0c099a6d20f0604a44eabdeef1777ddd94786cdae158729e4"}, + {file = "pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:7a66efda2387de898c8f38c0cf7f14fca0b51a8ef0b24bfea5849f1b3c95af27"}, + {file = "pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:18a101c168e4e092ab40dbc2503bdc0f62010e95d292b27827871dc85450d7ee"}, + {file = "pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ba5dd002f88b78a4215ed2f8ddbdf85e8513382820ba15ad5ad8955ce0ca19a1"}, + {file = "pydantic_core-2.27.2-cp313-cp313-win32.whl", hash = "sha256:1ebaf1d0481914d004a573394f4be3a7616334be70261007e47c2a6fe7e50130"}, + {file = "pydantic_core-2.27.2-cp313-cp313-win_amd64.whl", hash = "sha256:953101387ecf2f5652883208769a79e48db18c6df442568a0b5ccd8c2723abee"}, + {file = "pydantic_core-2.27.2-cp313-cp313-win_arm64.whl", hash = "sha256:ac4dbfd1691affb8f48c2c13241a2e3b60ff23247cbcf981759c768b6633cf8b"}, + {file = "pydantic_core-2.27.2-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:d3e8d504bdd3f10835468f29008d72fc8359d95c9c415ce6e767203db6127506"}, + {file = "pydantic_core-2.27.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:521eb9b7f036c9b6187f0b47318ab0d7ca14bd87f776240b90b21c1f4f149320"}, + {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85210c4d99a0114f5a9481b44560d7d1e35e32cc5634c656bc48e590b669b145"}, + {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d716e2e30c6f140d7560ef1538953a5cd1a87264c737643d481f2779fc247fe1"}, + {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f66d89ba397d92f840f8654756196d93804278457b5fbede59598a1f9f90b228"}, + {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:669e193c1c576a58f132e3158f9dfa9662969edb1a250c54d8fa52590045f046"}, + {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fdbe7629b996647b99c01b37f11170a57ae675375b14b8c13b8518b8320ced5"}, + {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d262606bf386a5ba0b0af3b97f37c83d7011439e3dc1a9298f21efb292e42f1a"}, + {file = "pydantic_core-2.27.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:cabb9bcb7e0d97f74df8646f34fc76fbf793b7f6dc2438517d7a9e50eee4f14d"}, + {file = "pydantic_core-2.27.2-cp38-cp38-musllinux_1_1_armv7l.whl", hash = "sha256:d2d63f1215638d28221f664596b1ccb3944f6e25dd18cd3b86b0a4c408d5ebb9"}, + {file = "pydantic_core-2.27.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:bca101c00bff0adb45a833f8451b9105d9df18accb8743b08107d7ada14bd7da"}, + {file = "pydantic_core-2.27.2-cp38-cp38-win32.whl", hash = "sha256:f6f8e111843bbb0dee4cb6594cdc73e79b3329b526037ec242a3e49012495b3b"}, + {file = "pydantic_core-2.27.2-cp38-cp38-win_amd64.whl", hash = "sha256:fd1aea04935a508f62e0d0ef1f5ae968774a32afc306fb8545e06f5ff5cdf3ad"}, + {file = "pydantic_core-2.27.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:c10eb4f1659290b523af58fa7cffb452a61ad6ae5613404519aee4bfbf1df993"}, + {file = "pydantic_core-2.27.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ef592d4bad47296fb11f96cd7dc898b92e795032b4894dfb4076cfccd43a9308"}, + {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c61709a844acc6bf0b7dce7daae75195a10aac96a596ea1b776996414791ede4"}, + {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:42c5f762659e47fdb7b16956c71598292f60a03aa92f8b6351504359dbdba6cf"}, + {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4c9775e339e42e79ec99c441d9730fccf07414af63eac2f0e48e08fd38a64d76"}, + {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:57762139821c31847cfb2df63c12f725788bd9f04bc2fb392790959b8f70f118"}, + {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d1e85068e818c73e048fe28cfc769040bb1f475524f4745a5dc621f75ac7630"}, + {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:097830ed52fd9e427942ff3b9bc17fab52913b2f50f2880dc4a5611446606a54"}, + {file = "pydantic_core-2.27.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:044a50963a614ecfae59bb1eaf7ea7efc4bc62f49ed594e18fa1e5d953c40e9f"}, + {file = "pydantic_core-2.27.2-cp39-cp39-musllinux_1_1_armv7l.whl", hash = "sha256:4e0b4220ba5b40d727c7f879eac379b822eee5d8fff418e9d3381ee45b3b0362"}, + {file = "pydantic_core-2.27.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5e4f4bb20d75e9325cc9696c6802657b58bc1dbbe3022f32cc2b2b632c3fbb96"}, + {file = "pydantic_core-2.27.2-cp39-cp39-win32.whl", hash = "sha256:cca63613e90d001b9f2f9a9ceb276c308bfa2a43fafb75c8031c4f66039e8c6e"}, + {file = "pydantic_core-2.27.2-cp39-cp39-win_amd64.whl", hash = "sha256:77d1bca19b0f7021b3a982e6f903dcd5b2b06076def36a652e3907f596e29f67"}, + {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:2bf14caea37e91198329b828eae1618c068dfb8ef17bb33287a7ad4b61ac314e"}, + {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:b0cb791f5b45307caae8810c2023a184c74605ec3bcbb67d13846c28ff731ff8"}, + {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:688d3fd9fcb71f41c4c015c023d12a79d1c4c0732ec9eb35d96e3388a120dcf3"}, + {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d591580c34f4d731592f0e9fe40f9cc1b430d297eecc70b962e93c5c668f15f"}, + {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:82f986faf4e644ffc189a7f1aafc86e46ef70372bb153e7001e8afccc6e54133"}, + {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:bec317a27290e2537f922639cafd54990551725fc844249e64c523301d0822fc"}, + {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:0296abcb83a797db256b773f45773da397da75a08f5fcaef41f2044adec05f50"}, + {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:0d75070718e369e452075a6017fbf187f788e17ed67a3abd47fa934d001863d9"}, + {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:7e17b560be3c98a8e3aa66ce828bdebb9e9ac6ad5466fba92eb74c4c95cb1151"}, + {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:c33939a82924da9ed65dab5a65d427205a73181d8098e79b6b426bdf8ad4e656"}, + {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:00bad2484fa6bda1e216e7345a798bd37c68fb2d97558edd584942aa41b7d278"}, + {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c817e2b40aba42bac6f457498dacabc568c3b7a986fc9ba7c8d9d260b71485fb"}, + {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:251136cdad0cb722e93732cb45ca5299fb56e1344a833640bf93b2803f8d1bfd"}, + {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d2088237af596f0a524d3afc39ab3b036e8adb054ee57cbb1dcf8e09da5b29cc"}, + {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:d4041c0b966a84b4ae7a09832eb691a35aec90910cd2dbe7a208de59be77965b"}, + {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:8083d4e875ebe0b864ffef72a4304827015cff328a1be6e22cc850753bfb122b"}, + {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f141ee28a0ad2123b6611b6ceff018039df17f32ada8b534e6aa039545a3efb2"}, + {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7d0c8399fcc1848491f00e0314bd59fb34a9c008761bcb422a057670c3f65e35"}, + {file = "pydantic_core-2.27.2.tar.gz", hash = "sha256:eb026e5a4c1fee05726072337ff51d1efb6f59090b7da90d30ea58625b1ffb39"}, +] + +[package.dependencies] +typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" + +[[package]] +name = "pytest" +version = "7.4.4" +description = "pytest: simple powerful testing with Python" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pytest-7.4.4-py3-none-any.whl", hash = "sha256:b090cdf5ed60bf4c45261be03239c2c1c22df034fbffe691abe93cd80cea01d8"}, + {file = "pytest-7.4.4.tar.gz", hash = "sha256:2cf0005922c6ace4a3e2ec8b4080eb0d9753fdc93107415332f50ce9e7994280"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "sys_platform == \"win32\""} +exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} +iniconfig = "*" +packaging = "*" +pluggy = ">=0.12,<2.0" +tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} + +[package.extras] +testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] + +[[package]] +name = "pytest-asyncio" +version = "0.23.8" +description = "Pytest support for asyncio" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pytest_asyncio-0.23.8-py3-none-any.whl", hash = "sha256:50265d892689a5faefb84df80819d1ecef566eb3549cf915dfb33569359d1ce2"}, + {file = "pytest_asyncio-0.23.8.tar.gz", hash = "sha256:759b10b33a6dc61cce40a8bd5205e302978bbbcc00e279a8b61d9a6a3c82e4d3"}, +] + +[package.dependencies] +pytest = ">=7.0.0,<9" + +[package.extras] +docs = ["sphinx (>=5.3)", "sphinx-rtd-theme (>=1.0)"] +testing = ["coverage (>=6.2)", "hypothesis (>=5.7.1)"] + +[[package]] +name = "python-dateutil" +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" +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"}, +] + +[package.dependencies] +six = ">=1.5" + +[[package]] +name = "ruff" +version = "0.11.5" +description = "An extremely fast Python linter and code formatter, written in Rust." +optional = false +python-versions = ">=3.7" +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"}, + {file = "ruff-0.11.5-py3-none-macosx_11_0_arm64.whl", hash = "sha256:4bfd80a6ec559a5eeb96c33f832418bf0fb96752de0539905cf7b0cc1d31d779"}, + {file = "ruff-0.11.5-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0947c0a1afa75dcb5db4b34b070ec2bccee869d40e6cc8ab25aca11a7d527794"}, + {file = "ruff-0.11.5-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ad871ff74b5ec9caa66cb725b85d4ef89b53f8170f47c3406e32ef040400b038"}, + {file = "ruff-0.11.5-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e6cf918390cfe46d240732d4d72fa6e18e528ca1f60e318a10835cf2fa3dc19f"}, + {file = "ruff-0.11.5-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:56145ee1478582f61c08f21076dc59153310d606ad663acc00ea3ab5b2125f82"}, + {file = "ruff-0.11.5-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e5f66f8f1e8c9fc594cbd66fbc5f246a8d91f916cb9667e80208663ec3728304"}, + {file = "ruff-0.11.5-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:80b4df4d335a80315ab9afc81ed1cff62be112bd165e162b5eed8ac55bfc8470"}, + {file = "ruff-0.11.5-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3068befab73620b8a0cc2431bd46b3cd619bc17d6f7695a3e1bb166b652c382a"}, + {file = "ruff-0.11.5-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:f5da2e710a9641828e09aa98b92c9ebbc60518fdf3921241326ca3e8f8e55b8b"}, + {file = "ruff-0.11.5-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:ef39f19cb8ec98cbc762344921e216f3857a06c47412030374fffd413fb8fd3a"}, + {file = "ruff-0.11.5-py3-none-musllinux_1_2_i686.whl", hash = "sha256:b2a7cedf47244f431fd11aa5a7e2806dda2e0c365873bda7834e8f7d785ae159"}, + {file = "ruff-0.11.5-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:81be52e7519f3d1a0beadcf8e974715b2dfc808ae8ec729ecfc79bddf8dbb783"}, + {file = "ruff-0.11.5-py3-none-win32.whl", hash = "sha256:e268da7b40f56e3eca571508a7e567e794f9bfcc0f412c4b607931d3af9c4afe"}, + {file = "ruff-0.11.5-py3-none-win_amd64.whl", hash = "sha256:6c6dc38af3cfe2863213ea25b6dc616d679205732dc0fb673356c2d69608f800"}, + {file = "ruff-0.11.5-py3-none-win_arm64.whl", hash = "sha256:67e241b4314f4eacf14a601d586026a962f4002a475aa702c69980a38087aa4e"}, + {file = "ruff-0.11.5.tar.gz", hash = "sha256:cae2e2439cb88853e421901ec040a758960b576126dab520fa08e9de431d1bef"}, +] + +[[package]] +name = "six" +version = "1.17.0" +description = "Python 2 and 3 compatibility utilities" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +files = [ + {file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"}, + {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"}, +] + +[[package]] +name = "sniffio" +version = "1.3.1" +description = "Sniff out which async library your code is running under" +optional = false +python-versions = ">=3.7" +files = [ + {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, + {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, +] + +[[package]] +name = "tomli" +version = "2.2.1" +description = "A lil' TOML parser" +optional = false +python-versions = ">=3.8" +files = [ + {file = "tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249"}, + {file = "tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6"}, + {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a"}, + {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee"}, + {file = "tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e"}, + {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4"}, + {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106"}, + {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8"}, + {file = "tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff"}, + {file = "tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b"}, + {file = "tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea"}, + {file = "tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8"}, + {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192"}, + {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222"}, + {file = "tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77"}, + {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6"}, + {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd"}, + {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e"}, + {file = "tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98"}, + {file = "tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4"}, + {file = "tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7"}, + {file = "tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c"}, + {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13"}, + {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281"}, + {file = "tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272"}, + {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140"}, + {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2"}, + {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744"}, + {file = "tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec"}, + {file = "tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69"}, + {file = "tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc"}, + {file = "tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff"}, +] + +[[package]] +name = "types-python-dateutil" +version = "2.9.0.20241206" +description = "Typing stubs for python-dateutil" +optional = false +python-versions = ">=3.8" +files = [ + {file = "types_python_dateutil-2.9.0.20241206-py3-none-any.whl", hash = "sha256:e248a4bc70a486d3e3ec84d0dc30eec3a5f979d6e7ee4123ae043eedbb987f53"}, + {file = "types_python_dateutil-2.9.0.20241206.tar.gz", hash = "sha256:18f493414c26ffba692a72369fea7a154c502646301ebfe3d56a04b3767284cb"}, +] + +[[package]] +name = "typing-extensions" +version = "4.13.2" +description = "Backported and Experimental Type Hints for Python 3.8+" +optional = false +python-versions = ">=3.8" +files = [ + {file = "typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c"}, + {file = "typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef"}, +] + +[metadata] +lock-version = "2.0" +python-versions = "^3.8" +content-hash = "8551b871abee465e23fb0966d51f2c155fd257b55bdcb0c02d095de19f92f358" diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..820197e --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,84 @@ +[project] +name = "pipedream" + +[tool.poetry] +name = "pipedream" +version = "0.3.1" +description = "" +readme = "README.md" +authors = [] +keywords = [] + +classifiers = [ + "Intended Audience :: Developers", + "Programming Language :: Python", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Operating System :: OS Independent", + "Operating System :: POSIX", + "Operating System :: MacOS", + "Operating System :: POSIX :: Linux", + "Operating System :: Microsoft :: Windows", + "Topic :: Software Development :: Libraries :: Python Modules", + "Typing :: Typed" +] +packages = [ + { include = "pipedream", from = "src"} +] + +[project.urls] +Repository = 'https://github.com/PipedreamHQ/pipedream-sdk-python' + +[tool.poetry.dependencies] +python = "^3.8" +httpx = ">=0.21.2" +pydantic = ">= 1.9.2" +pydantic-core = ">=2.18.2" +typing_extensions = ">= 4.0.0" + +[tool.poetry.group.dev.dependencies] +mypy = "==1.13.0" +pytest = "^7.4.0" +pytest-asyncio = "^0.23.5" +python-dateutil = "^2.9.0" +types-python-dateutil = "^2.9.0.20240316" +ruff = "==0.11.5" + +[tool.pytest.ini_options] +testpaths = [ "tests" ] +asyncio_mode = "auto" + +[tool.mypy] +plugins = ["pydantic.mypy"] + +[tool.ruff] +line-length = 120 + +[tool.ruff.lint] +select = [ + "E", # pycodestyle errors + "F", # pyflakes + "I", # isort +] +ignore = [ + "E402", # Module level import not at top of file + "E501", # Line too long + "E711", # Comparison to `None` should be `cond is not None` + "E712", # Avoid equality comparisons to `True`; use `if ...:` checks + "E721", # Use `is` and `is not` for type comparisons, or `isinstance()` for insinstance checks + "E722", # Do not use bare `except` + "E731", # Do not assign a `lambda` expression, use a `def` + "F821", # Undefined name + "F841" # Local variable ... is assigned to but never used +] + +[tool.ruff.lint.isort] +section-order = ["future", "standard-library", "third-party", "first-party"] + +[build-system] +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api" diff --git a/reference.md b/reference.md new file mode 100644 index 0000000..26909eb --- /dev/null +++ b/reference.md @@ -0,0 +1,3807 @@ +# Reference +## AppCategories +
client.app_categories.list() +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from pipedream import Pipedream + +client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", +) +client.app_categories.list() + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.app_categories.retrieve(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from pipedream import Pipedream + +client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", +) +client.app_categories.retrieve( + id="id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**id:** `str` — The ID of the app category to retrieve + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## Apps +
client.apps.list(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from pipedream import Pipedream + +client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", +) +response = client.apps.list() +for item in response: + yield item +# alternatively, you can paginate page-by-page +for page in response.iter_pages(): + yield page + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**after:** `typing.Optional[str]` — The cursor to start from for pagination + +
+
+ +
+
+ +**before:** `typing.Optional[str]` — The cursor to end before for pagination + +
+
+ +
+
+ +**limit:** `typing.Optional[int]` — The maximum number of results to return + +
+
+ +
+
+ +**q:** `typing.Optional[str]` — A search query to filter the apps + +
+
+ +
+
+ +**sort_key:** `typing.Optional[AppsListRequestSortKey]` — The key to sort the apps by + +
+
+ +
+
+ +**sort_direction:** `typing.Optional[AppsListRequestSortDirection]` — The direction to sort the apps + +
+
+ +
+
+ +**category_ids:** `typing.Optional[typing.Union[str, typing.Sequence[str]]]` — Only return apps in these categories + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.apps.retrieve(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from pipedream import Pipedream + +client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", +) +client.apps.retrieve( + app_id="app_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**app_id:** `str` — The name slug or ID of the app (e.g., 'slack', 'github') + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## Accounts +
client.accounts.list(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from pipedream import Pipedream + +client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", +) +response = client.accounts.list( + project_id="project_id", +) +for item in response: + yield item +# alternatively, you can paginate page-by-page +for page in response.iter_pages(): + yield page + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**project_id:** `str` — The project ID, which starts with 'proj_'. + +
+
+ +
+
+ +**app_id:** `typing.Optional[str]` — The app slug or ID to filter accounts by. + +
+
+ +
+
+ +**external_user_id:** `typing.Optional[str]` + +
+
+ +
+
+ +**oauth_app_id:** `typing.Optional[str]` — The OAuth app ID to filter by, if applicable + +
+
+ +
+
+ +**after:** `typing.Optional[str]` — The cursor to start from for pagination + +
+
+ +
+
+ +**before:** `typing.Optional[str]` — The cursor to end before for pagination + +
+
+ +
+
+ +**limit:** `typing.Optional[int]` — The maximum number of results to return + +
+
+ +
+
+ +**include_credentials:** `typing.Optional[bool]` — Whether to retrieve the account's credentials or not + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.accounts.create(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from pipedream import Pipedream + +client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", +) +client.accounts.create( + project_id="project_id", + app_slug="app_slug", + cfmap_json="cfmap_json", + connect_token="connect_token", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**project_id:** `str` — The project ID, which starts with 'proj_'. + +
+
+ +
+
+ +**app_slug:** `str` — The app slug for the account + +
+
+ +
+
+ +**cfmap_json:** `str` — JSON string containing the custom fields mapping + +
+
+ +
+
+ +**connect_token:** `str` — The connect token for authentication + +
+
+ +
+
+ +**app_id:** `typing.Optional[str]` — The app slug or ID to filter accounts by. + +
+
+ +
+
+ +**external_user_id:** `typing.Optional[str]` + +
+
+ +
+
+ +**oauth_app_id:** `typing.Optional[str]` — The OAuth app ID to filter by, if applicable + +
+
+ +
+
+ +**name:** `typing.Optional[str]` — Optional name for the account + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.accounts.retrieve(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from pipedream import Pipedream + +client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", +) +client.accounts.retrieve( + project_id="project_id", + account_id="account_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**project_id:** `str` — The project ID, which starts with 'proj_'. + +
+
+ +
+
+ +**account_id:** `str` + +
+
+ +
+
+ +**include_credentials:** `typing.Optional[bool]` — Whether to retrieve the account's credentials or not + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.accounts.delete(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from pipedream import Pipedream + +client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", +) +client.accounts.delete( + project_id="project_id", + account_id="account_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**project_id:** `str` — The project ID, which starts with 'proj_'. + +
+
+ +
+
+ +**account_id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.accounts.delete_by_app(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from pipedream import Pipedream + +client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", +) +client.accounts.delete_by_app( + project_id="project_id", + app_id="app_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**project_id:** `str` — The project ID, which starts with 'proj_'. + +
+
+ +
+
+ +**app_id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## Users +
client.users.delete_external_user(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from pipedream import Pipedream + +client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", +) +client.users.delete_external_user( + project_id="project_id", + external_user_id="external_user_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**project_id:** `str` — The project ID, which starts with 'proj_'. + +
+
+ +
+
+ +**external_user_id:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## Components +
client.components.list(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from pipedream import Pipedream + +client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", +) +response = client.components.list( + project_id="project_id", +) +for item in response: + yield item +# alternatively, you can paginate page-by-page +for page in response.iter_pages(): + yield page + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**project_id:** `str` — The project ID, which starts with 'proj_'. + +
+
+ +
+
+ +**after:** `typing.Optional[str]` — The cursor to start from for pagination + +
+
+ +
+
+ +**before:** `typing.Optional[str]` — The cursor to end before for pagination + +
+
+ +
+
+ +**limit:** `typing.Optional[int]` — The maximum number of results to return + +
+
+ +
+
+ +**q:** `typing.Optional[str]` — A search query to filter the components + +
+
+ +
+
+ +**app:** `typing.Optional[str]` — The ID or name slug of the app to filter the components + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.components.retrieve(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from pipedream import Pipedream + +client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", +) +client.components.retrieve( + project_id="project_id", + component_id="component_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**project_id:** `str` — The project ID, which starts with 'proj_'. + +
+
+ +
+
+ +**component_id:** `str` — The key that uniquely identifies the component (e.g., 'slack-send-message') + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.components.configure_prop(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from pipedream import Pipedream + +client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", +) +client.components.configure_prop( + project_id="project_id", + id="id", + external_user_id="external_user_id", + prop_name="prop_name", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**project_id:** `str` — The project ID, which starts with 'proj_'. + +
+
+ +
+
+ +**id:** `str` — The component ID + +
+
+ +
+
+ +**external_user_id:** `str` — The external user ID + +
+
+ +
+
+ +**prop_name:** `str` — The name of the prop to configure + +
+
+ +
+
+ +**async_handle:** `typing.Optional[str]` + +
+
+ +
+
+ +**blocking:** `typing.Optional[bool]` — Whether this operation should block until completion + +
+
+ +
+
+ +**configured_props:** `typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]` — The configured properties for the component + +
+
+ +
+
+ +**dynamic_props_id:** `typing.Optional[str]` — The ID for dynamic props + +
+
+ +
+
+ +**configure_prop_opts_async_handle:** `typing.Optional[str]` — Handle for async operations + +
+
+ +
+
+ +**page:** `typing.Optional[float]` — Page number for paginated results + +
+
+ +
+
+ +**prev_context:** `typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]` — Previous context for pagination + +
+
+ +
+
+ +**query:** `typing.Optional[str]` — Search query for filtering options + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.components.reload_props(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from pipedream import Pipedream + +client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", +) +client.components.reload_props( + project_id="project_id", + id="id", + external_user_id="external_user_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**project_id:** `str` — The project ID, which starts with 'proj_'. + +
+
+ +
+
+ +**id:** `str` — The component ID + +
+
+ +
+
+ +**external_user_id:** `str` — The external user ID + +
+
+ +
+
+ +**async_handle:** `typing.Optional[str]` + +
+
+ +
+
+ +**blocking:** `typing.Optional[bool]` — Whether this operation should block until completion + +
+
+ +
+
+ +**configured_props:** `typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]` — The configured properties for the component + +
+
+ +
+
+ +**dynamic_props_id:** `typing.Optional[str]` — The ID for dynamic props + +
+
+ +
+
+ +**reload_props_opts_async_handle:** `typing.Optional[str]` — Handle for async operations + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## Actions +
client.actions.list(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from pipedream import Pipedream + +client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", +) +response = client.actions.list( + project_id="project_id", +) +for item in response: + yield item +# alternatively, you can paginate page-by-page +for page in response.iter_pages(): + yield page + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**project_id:** `str` — The project ID, which starts with 'proj_'. + +
+
+ +
+
+ +**after:** `typing.Optional[str]` — The cursor to start from for pagination + +
+
+ +
+
+ +**before:** `typing.Optional[str]` — The cursor to end before for pagination + +
+
+ +
+
+ +**limit:** `typing.Optional[int]` — The maximum number of results to return + +
+
+ +
+
+ +**q:** `typing.Optional[str]` — A search query to filter the actions + +
+
+ +
+
+ +**app:** `typing.Optional[str]` — The ID or name slug of the app to filter the actions + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.actions.retrieve(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from pipedream import Pipedream + +client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", +) +client.actions.retrieve( + project_id="project_id", + component_id="component_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**project_id:** `str` — The project ID, which starts with 'proj_'. + +
+
+ +
+
+ +**component_id:** `str` — The key that uniquely identifies the component (e.g., 'slack-send-message') + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.actions.configure_prop(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from pipedream import Pipedream + +client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", +) +client.actions.configure_prop( + project_id="project_id", + id="id", + external_user_id="external_user_id", + prop_name="prop_name", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**project_id:** `str` — The project ID, which starts with 'proj_'. + +
+
+ +
+
+ +**id:** `str` — The component ID + +
+
+ +
+
+ +**external_user_id:** `str` — The external user ID + +
+
+ +
+
+ +**prop_name:** `str` — The name of the prop to configure + +
+
+ +
+
+ +**async_handle:** `typing.Optional[str]` + +
+
+ +
+
+ +**blocking:** `typing.Optional[bool]` — Whether this operation should block until completion + +
+
+ +
+
+ +**configured_props:** `typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]` — The configured properties for the component + +
+
+ +
+
+ +**dynamic_props_id:** `typing.Optional[str]` — The ID for dynamic props + +
+
+ +
+
+ +**configure_prop_opts_async_handle:** `typing.Optional[str]` — Handle for async operations + +
+
+ +
+
+ +**page:** `typing.Optional[float]` — Page number for paginated results + +
+
+ +
+
+ +**prev_context:** `typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]` — Previous context for pagination + +
+
+ +
+
+ +**query:** `typing.Optional[str]` — Search query for filtering options + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.actions.reload_props(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from pipedream import Pipedream + +client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", +) +client.actions.reload_props( + project_id="project_id", + id="id", + external_user_id="external_user_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**project_id:** `str` — The project ID, which starts with 'proj_'. + +
+
+ +
+
+ +**id:** `str` — The component ID + +
+
+ +
+
+ +**external_user_id:** `str` — The external user ID + +
+
+ +
+
+ +**async_handle:** `typing.Optional[str]` + +
+
+ +
+
+ +**blocking:** `typing.Optional[bool]` — Whether this operation should block until completion + +
+
+ +
+
+ +**configured_props:** `typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]` — The configured properties for the component + +
+
+ +
+
+ +**dynamic_props_id:** `typing.Optional[str]` — The ID for dynamic props + +
+
+ +
+
+ +**reload_props_opts_async_handle:** `typing.Optional[str]` — Handle for async operations + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.actions.run(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from pipedream import Pipedream + +client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", +) +client.actions.run( + project_id="project_id", + id="id", + external_user_id="external_user_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**project_id:** `str` — The project ID, which starts with 'proj_'. + +
+
+ +
+
+ +**id:** `str` — The action component ID + +
+
+ +
+
+ +**external_user_id:** `str` — The external user ID + +
+
+ +
+
+ +**async_handle:** `typing.Optional[str]` + +
+
+ +
+
+ +**configured_props:** `typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]` — The configured properties for the action + +
+
+ +
+
+ +**dynamic_props_id:** `typing.Optional[str]` — The ID for dynamic props + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## Triggers +
client.triggers.list(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from pipedream import Pipedream + +client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", +) +response = client.triggers.list( + project_id="project_id", +) +for item in response: + yield item +# alternatively, you can paginate page-by-page +for page in response.iter_pages(): + yield page + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**project_id:** `str` — The project ID, which starts with 'proj_'. + +
+
+ +
+
+ +**after:** `typing.Optional[str]` — The cursor to start from for pagination + +
+
+ +
+
+ +**before:** `typing.Optional[str]` — The cursor to end before for pagination + +
+
+ +
+
+ +**limit:** `typing.Optional[int]` — The maximum number of results to return + +
+
+ +
+
+ +**q:** `typing.Optional[str]` — A search query to filter the triggers + +
+
+ +
+
+ +**app:** `typing.Optional[str]` — The ID or name slug of the app to filter the triggers + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.triggers.retrieve(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from pipedream import Pipedream + +client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", +) +client.triggers.retrieve( + project_id="project_id", + component_id="component_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**project_id:** `str` — The project ID, which starts with 'proj_'. + +
+
+ +
+
+ +**component_id:** `str` — The key that uniquely identifies the component (e.g., 'slack-send-message') + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.triggers.configure_prop(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from pipedream import Pipedream + +client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", +) +client.triggers.configure_prop( + project_id="project_id", + id="id", + external_user_id="external_user_id", + prop_name="prop_name", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**project_id:** `str` — The project ID, which starts with 'proj_'. + +
+
+ +
+
+ +**id:** `str` — The component ID + +
+
+ +
+
+ +**external_user_id:** `str` — The external user ID + +
+
+ +
+
+ +**prop_name:** `str` — The name of the prop to configure + +
+
+ +
+
+ +**async_handle:** `typing.Optional[str]` + +
+
+ +
+
+ +**blocking:** `typing.Optional[bool]` — Whether this operation should block until completion + +
+
+ +
+
+ +**configured_props:** `typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]` — The configured properties for the component + +
+
+ +
+
+ +**dynamic_props_id:** `typing.Optional[str]` — The ID for dynamic props + +
+
+ +
+
+ +**configure_prop_opts_async_handle:** `typing.Optional[str]` — Handle for async operations + +
+
+ +
+
+ +**page:** `typing.Optional[float]` — Page number for paginated results + +
+
+ +
+
+ +**prev_context:** `typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]` — Previous context for pagination + +
+
+ +
+
+ +**query:** `typing.Optional[str]` — Search query for filtering options + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.triggers.reload_props(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from pipedream import Pipedream + +client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", +) +client.triggers.reload_props( + project_id="project_id", + id="id", + external_user_id="external_user_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**project_id:** `str` — The project ID, which starts with 'proj_'. + +
+
+ +
+
+ +**id:** `str` — The component ID + +
+
+ +
+
+ +**external_user_id:** `str` — The external user ID + +
+
+ +
+
+ +**async_handle:** `typing.Optional[str]` + +
+
+ +
+
+ +**blocking:** `typing.Optional[bool]` — Whether this operation should block until completion + +
+
+ +
+
+ +**configured_props:** `typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]` — The configured properties for the component + +
+
+ +
+
+ +**dynamic_props_id:** `typing.Optional[str]` — The ID for dynamic props + +
+
+ +
+
+ +**reload_props_opts_async_handle:** `typing.Optional[str]` — Handle for async operations + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.triggers.deploy(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from pipedream import Pipedream + +client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", +) +client.triggers.deploy( + project_id="project_id", + id="id", + external_user_id="external_user_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**project_id:** `str` — The project ID, which starts with 'proj_'. + +
+
+ +
+
+ +**id:** `str` — The trigger component ID + +
+
+ +
+
+ +**external_user_id:** `str` — The external user ID + +
+
+ +
+
+ +**configured_props:** `typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]` — The configured properties for the trigger + +
+
+ +
+
+ +**dynamic_props_id:** `typing.Optional[str]` — The ID for dynamic props + +
+
+ +
+
+ +**webhook_url:** `typing.Optional[str]` — Optional webhook URL to receive trigger events + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## DeployedTriggers +
client.deployed_triggers.list(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from pipedream import Pipedream + +client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", +) +response = client.deployed_triggers.list( + project_id="project_id", + external_user_id="external_user_id", +) +for item in response: + yield item +# alternatively, you can paginate page-by-page +for page in response.iter_pages(): + yield page + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**project_id:** `str` — The project ID, which starts with 'proj_'. + +
+
+ +
+
+ +**external_user_id:** `str` — Your end user ID, for whom you deployed the trigger + +
+
+ +
+
+ +**after:** `typing.Optional[str]` — The cursor to start from for pagination + +
+
+ +
+
+ +**before:** `typing.Optional[str]` — The cursor to end before for pagination + +
+
+ +
+
+ +**limit:** `typing.Optional[int]` — The maximum number of results to return + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.deployed_triggers.retrieve(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from pipedream import Pipedream + +client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", +) +client.deployed_triggers.retrieve( + project_id="project_id", + trigger_id="trigger_id", + external_user_id="external_user_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**project_id:** `str` — The project ID, which starts with 'proj_'. + +
+
+ +
+
+ +**trigger_id:** `str` + +
+
+ +
+
+ +**external_user_id:** `str` — Your end user ID, for whom you deployed the trigger + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.deployed_triggers.update(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from pipedream import Pipedream + +client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", +) +client.deployed_triggers.update( + project_id="project_id", + trigger_id="trigger_id", + external_user_id="external_user_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**project_id:** `str` — The project ID, which starts with 'proj_'. + +
+
+ +
+
+ +**trigger_id:** `str` + +
+
+ +
+
+ +**external_user_id:** `str` — The external user ID who owns the trigger + +
+
+ +
+
+ +**active:** `typing.Optional[bool]` — Whether the trigger should be active + +
+
+ +
+
+ +**configured_props:** `typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]` — The configured properties for the trigger + +
+
+ +
+
+ +**name:** `typing.Optional[str]` — The name of the trigger + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.deployed_triggers.delete(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from pipedream import Pipedream + +client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", +) +client.deployed_triggers.delete( + project_id="project_id", + trigger_id="trigger_id", + external_user_id="external_user_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**project_id:** `str` — The project ID, which starts with 'proj_'. + +
+
+ +
+
+ +**trigger_id:** `str` + +
+
+ +
+
+ +**external_user_id:** `str` — The external user ID who owns the trigger + +
+
+ +
+
+ +**ignore_hook_errors:** `typing.Optional[bool]` — Whether to ignore errors during deactivation hook + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.deployed_triggers.list_events(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from pipedream import Pipedream + +client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", +) +client.deployed_triggers.list_events( + project_id="project_id", + trigger_id="trigger_id", + external_user_id="external_user_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**project_id:** `str` — The project ID, which starts with 'proj_'. + +
+
+ +
+
+ +**trigger_id:** `str` + +
+
+ +
+
+ +**external_user_id:** `str` — Your end user ID, for whom you deployed the trigger + +
+
+ +
+
+ +**n:** `typing.Optional[int]` — The number of events to retrieve (defaults to 20 if not provided) + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.deployed_triggers.list_workflows(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from pipedream import Pipedream + +client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", +) +client.deployed_triggers.list_workflows( + project_id="project_id", + trigger_id="trigger_id", + external_user_id="external_user_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**project_id:** `str` — The project ID, which starts with 'proj_'. + +
+
+ +
+
+ +**trigger_id:** `str` + +
+
+ +
+
+ +**external_user_id:** `str` — The external user ID who owns the trigger + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.deployed_triggers.update_workflows(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from pipedream import Pipedream + +client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", +) +client.deployed_triggers.update_workflows( + project_id="project_id", + trigger_id="trigger_id", + external_user_id="external_user_id", + workflow_ids=["workflow_ids"], +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**project_id:** `str` — The project ID, which starts with 'proj_'. + +
+
+ +
+
+ +**trigger_id:** `str` + +
+
+ +
+
+ +**external_user_id:** `str` — The external user ID who owns the trigger + +
+
+ +
+
+ +**workflow_ids:** `typing.Sequence[str]` — Array of workflow IDs to set + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.deployed_triggers.list_webhooks(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from pipedream import Pipedream + +client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", +) +client.deployed_triggers.list_webhooks( + project_id="project_id", + trigger_id="trigger_id", + external_user_id="external_user_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**project_id:** `str` — The project ID, which starts with 'proj_'. + +
+
+ +
+
+ +**trigger_id:** `str` + +
+
+ +
+
+ +**external_user_id:** `str` — The external user ID who owns the trigger + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.deployed_triggers.update_webhooks(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from pipedream import Pipedream + +client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", +) +client.deployed_triggers.update_webhooks( + project_id="project_id", + trigger_id="trigger_id", + external_user_id="external_user_id", + webhook_urls=["webhook_urls"], +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**project_id:** `str` — The project ID, which starts with 'proj_'. + +
+
+ +
+
+ +**trigger_id:** `str` + +
+
+ +
+
+ +**external_user_id:** `str` — The external user ID who owns the trigger + +
+
+ +
+
+ +**webhook_urls:** `typing.Sequence[str]` — Array of webhook URLs to set + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## Projects +
client.projects.retrieve_info(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from pipedream import Pipedream + +client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", +) +client.projects.retrieve_info( + project_id="project_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**project_id:** `str` — The project ID, which starts with 'proj_'. + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## Proxy +
client.proxy.get(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from pipedream import Pipedream + +client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", +) +client.proxy.get( + project_id="project_id", + url_64="url_64", + external_user_id="external_user_id", + account_id="account_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**project_id:** `str` — The project ID, which starts with 'proj_'. + +
+
+ +
+
+ +**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. + +
+
+
+
+ + +
+
+
+ +
client.proxy.post(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from pipedream import Pipedream + +client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", +) +client.proxy.post( + project_id="project_id", + url_64="url_64", + external_user_id="external_user_id", + account_id="account_id", + request={"key": "value"}, +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**project_id:** `str` — The project ID, which starts with 'proj_'. + +
+
+ +
+
+ +**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.Optional[typing.Any]]` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.proxy.put(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from pipedream import Pipedream + +client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", +) +client.proxy.put( + project_id="project_id", + url_64="url_64", + external_user_id="external_user_id", + account_id="account_id", + request={"key": "value"}, +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**project_id:** `str` — The project ID, which starts with 'proj_'. + +
+
+ +
+
+ +**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.Optional[typing.Any]]` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.proxy.delete(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from pipedream import Pipedream + +client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", +) +client.proxy.delete( + project_id="project_id", + url_64="url_64", + external_user_id="external_user_id", + account_id="account_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**project_id:** `str` — The project ID, which starts with 'proj_'. + +
+
+ +
+
+ +**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. + +
+
+
+
+ + +
+
+
+ +
client.proxy.patch(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from pipedream import Pipedream + +client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", +) +client.proxy.patch( + project_id="project_id", + url_64="url_64", + external_user_id="external_user_id", + account_id="account_id", + request={"key": "value"}, +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**project_id:** `str` — The project ID, which starts with 'proj_'. + +
+
+ +
+
+ +**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.Optional[typing.Any]]` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## Tokens +
client.tokens.create(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from pipedream import Pipedream + +client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", +) +client.tokens.create( + external_user_id="external_user_id", + project_id="project_id", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**external_user_id:** `str` — Your end user ID, for whom you're creating the token + +
+
+ +
+
+ +**project_id:** `str` — The ID of the project + +
+
+ +
+
+ +**allowed_origins:** `typing.Optional[typing.Sequence[str]]` — List of allowed origins for CORS + +
+
+ +
+
+ +**error_redirect_uri:** `typing.Optional[str]` — URI to redirect to on error + +
+
+ +
+
+ +**success_redirect_uri:** `typing.Optional[str]` — URI to redirect to on success + +
+
+ +
+
+ +**webhook_uri:** `typing.Optional[str]` — Webhook URI for notifications + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.tokens.validate(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from pipedream import Pipedream + +client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", +) +client.tokens.validate( + ctok="ctok", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**ctok:** `str` + +
+
+ +
+
+ +**params:** `typing.Optional[ValidateTokenParams]` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +## OauthTokens +
client.oauth_tokens.create(...) +
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from pipedream import Pipedream + +client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", +) +client.oauth_tokens.create( + client_id="client_id", + client_secret="client_secret", +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**client_id:** `str` + +
+
+ +
+
+ +**client_secret:** `str` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..e80f640 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +httpx>=0.21.2 +pydantic>= 1.9.2 +pydantic-core>=2.18.2 +typing_extensions>= 4.0.0 diff --git a/src/pipedream/__init__.py b/src/pipedream/__init__.py new file mode 100644 index 0000000..09b017c --- /dev/null +++ b/src/pipedream/__init__.py @@ -0,0 +1,157 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +from .types import ( + Account, + App, + AppAuthType, + AppCategory, + BackendClientOpts, + ClientOpts, + Component, + ComponentStash, + ConfigurableProp, + ConfigurablePropAlert, + ConfigurablePropAlertAlertType, + ConfigurablePropAny, + ConfigurablePropApp, + ConfigurablePropBoolean, + ConfigurablePropDiscord, + ConfigurablePropInteger, + ConfigurablePropObject, + ConfigurablePropString, + ConfigurablePropStringArray, + ConfigurePropOpts, + ConfigurePropResponse, + ConnectTokenCreateOpts, + ConnectTokenResponse, + CreateBrowserClientOpts, + CreateOAuthTokenResponse, + CreateTokenResponse, + DeleteTriggerOpts, + DeployTriggerResponse, + DeployedComponent, + EmittedEvent, + ErrorResponse, + GetAccountsResponse, + GetAppCategoryResponse, + GetAppResponse, + GetAppsResponse, + GetComponentResponse, + GetComponentsResponse, + GetTriggerEventsResponse, + GetTriggerResponse, + GetTriggerWebhooksResponse, + GetTriggerWorkflowsResponse, + GetTriggersResponse, + ListAccountsResponse, + ListAppCategoriesResponse, + ListAppsResponse, + PageInfo, + ProjectInfoResponse, + ProjectInfoResponseAppsItem, + PropOption, + ProxyResponse, + ReloadPropsOpts, + ReloadPropsResponse, + RunActionResponse, + StartConnectOpts, + ValidateTokenParams, + ValidateTokenResponse, +) +from . import ( + accounts, + actions, + app_categories, + apps, + components, + deployed_triggers, + oauth_tokens, + projects, + proxy, + tokens, + triggers, + users, +) +from .apps import AppsListRequestSortDirection, AppsListRequestSortKey +from .environment import PipedreamEnvironment +from .pipedream import AsyncPipedream, Pipedream +from .version import __version__ + +__all__ = [ + "Account", + "App", + "AppAuthType", + "AppCategory", + "AppsListRequestSortDirection", + "AppsListRequestSortKey", + "AsyncPipedream", + "BackendClientOpts", + "ClientOpts", + "Component", + "ComponentStash", + "ConfigurableProp", + "ConfigurablePropAlert", + "ConfigurablePropAlertAlertType", + "ConfigurablePropAny", + "ConfigurablePropApp", + "ConfigurablePropBoolean", + "ConfigurablePropDiscord", + "ConfigurablePropInteger", + "ConfigurablePropObject", + "ConfigurablePropString", + "ConfigurablePropStringArray", + "ConfigurePropOpts", + "ConfigurePropResponse", + "ConnectTokenCreateOpts", + "ConnectTokenResponse", + "CreateBrowserClientOpts", + "CreateOAuthTokenResponse", + "CreateTokenResponse", + "DeleteTriggerOpts", + "DeployTriggerResponse", + "DeployedComponent", + "EmittedEvent", + "ErrorResponse", + "GetAccountsResponse", + "GetAppCategoryResponse", + "GetAppResponse", + "GetAppsResponse", + "GetComponentResponse", + "GetComponentsResponse", + "GetTriggerEventsResponse", + "GetTriggerResponse", + "GetTriggerWebhooksResponse", + "GetTriggerWorkflowsResponse", + "GetTriggersResponse", + "ListAccountsResponse", + "ListAppCategoriesResponse", + "ListAppsResponse", + "PageInfo", + "Pipedream", + "PipedreamEnvironment", + "ProjectInfoResponse", + "ProjectInfoResponseAppsItem", + "PropOption", + "ProxyResponse", + "ReloadPropsOpts", + "ReloadPropsResponse", + "RunActionResponse", + "StartConnectOpts", + "ValidateTokenParams", + "ValidateTokenResponse", + "__version__", + "accounts", + "actions", + "app_categories", + "apps", + "components", + "deployed_triggers", + "oauth_tokens", + "projects", + "proxy", + "tokens", + "triggers", + "users", +] diff --git a/src/pipedream/accounts/__init__.py b/src/pipedream/accounts/__init__.py new file mode 100644 index 0000000..5cde020 --- /dev/null +++ b/src/pipedream/accounts/__init__.py @@ -0,0 +1,4 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + diff --git a/src/pipedream/accounts/client.py b/src/pipedream/accounts/client.py new file mode 100644 index 0000000..bce7562 --- /dev/null +++ b/src/pipedream/accounts/client.py @@ -0,0 +1,623 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ..core.pagination import AsyncPager, SyncPager +from ..core.request_options import RequestOptions +from ..types.account import Account +from .raw_client import AsyncRawAccountsClient, RawAccountsClient + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class AccountsClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._raw_client = RawAccountsClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawAccountsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawAccountsClient + """ + return self._raw_client + + def list( + self, + project_id: str, + *, + app_id: typing.Optional[str] = None, + external_user_id: typing.Optional[str] = None, + oauth_app_id: typing.Optional[str] = None, + after: typing.Optional[str] = None, + before: typing.Optional[str] = None, + limit: typing.Optional[int] = None, + include_credentials: typing.Optional[bool] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> SyncPager[Account]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + app_id : typing.Optional[str] + The app slug or ID to filter accounts by. + + external_user_id : typing.Optional[str] + + oauth_app_id : typing.Optional[str] + The OAuth app ID to filter by, if applicable + + after : typing.Optional[str] + The cursor to start from for pagination + + before : typing.Optional[str] + The cursor to end before for pagination + + limit : typing.Optional[int] + The maximum number of results to return + + include_credentials : typing.Optional[bool] + Whether to retrieve the account's credentials or not + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + SyncPager[Account] + accounts listed + + Examples + -------- + from pipedream import Pipedream + + client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + response = client.accounts.list( + project_id="project_id", + ) + for item in response: + yield item + # alternatively, you can paginate page-by-page + for page in response.iter_pages(): + yield page + """ + return self._raw_client.list( + project_id, + app_id=app_id, + external_user_id=external_user_id, + oauth_app_id=oauth_app_id, + after=after, + before=before, + limit=limit, + include_credentials=include_credentials, + request_options=request_options, + ) + + def create( + self, + project_id: str, + *, + app_slug: str, + cfmap_json: str, + connect_token: str, + app_id: typing.Optional[str] = None, + external_user_id: typing.Optional[str] = None, + oauth_app_id: typing.Optional[str] = None, + name: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> Account: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + app_slug : str + The app slug for the account + + cfmap_json : str + JSON string containing the custom fields mapping + + connect_token : str + The connect token for authentication + + app_id : typing.Optional[str] + The app slug or ID to filter accounts by. + + external_user_id : typing.Optional[str] + + oauth_app_id : typing.Optional[str] + The OAuth app ID to filter by, if applicable + + name : typing.Optional[str] + Optional name for the account + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Account + account created + + Examples + -------- + from pipedream import Pipedream + + client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + client.accounts.create( + project_id="project_id", + app_slug="app_slug", + cfmap_json="cfmap_json", + connect_token="connect_token", + ) + """ + _response = self._raw_client.create( + project_id, + app_slug=app_slug, + cfmap_json=cfmap_json, + connect_token=connect_token, + app_id=app_id, + external_user_id=external_user_id, + oauth_app_id=oauth_app_id, + name=name, + request_options=request_options, + ) + return _response.data + + def retrieve( + self, + project_id: str, + account_id: str, + *, + include_credentials: typing.Optional[bool] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> Account: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + account_id : str + + include_credentials : typing.Optional[bool] + Whether to retrieve the account's credentials or not + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Account + account retrieved + + Examples + -------- + from pipedream import Pipedream + + client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + client.accounts.retrieve( + project_id="project_id", + account_id="account_id", + ) + """ + _response = self._raw_client.retrieve( + project_id, account_id, include_credentials=include_credentials, request_options=request_options + ) + return _response.data + + def delete( + self, project_id: str, account_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> None: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + account_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + None + + Examples + -------- + from pipedream import Pipedream + + client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + client.accounts.delete( + project_id="project_id", + account_id="account_id", + ) + """ + _response = self._raw_client.delete(project_id, account_id, request_options=request_options) + return _response.data + + def delete_by_app( + self, project_id: str, app_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> None: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + app_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + None + + Examples + -------- + from pipedream import Pipedream + + client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + client.accounts.delete_by_app( + project_id="project_id", + app_id="app_id", + ) + """ + _response = self._raw_client.delete_by_app(project_id, app_id, request_options=request_options) + return _response.data + + +class AsyncAccountsClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._raw_client = AsyncRawAccountsClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawAccountsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawAccountsClient + """ + return self._raw_client + + async def list( + self, + project_id: str, + *, + app_id: typing.Optional[str] = None, + external_user_id: typing.Optional[str] = None, + oauth_app_id: typing.Optional[str] = None, + after: typing.Optional[str] = None, + before: typing.Optional[str] = None, + limit: typing.Optional[int] = None, + include_credentials: typing.Optional[bool] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncPager[Account]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + app_id : typing.Optional[str] + The app slug or ID to filter accounts by. + + external_user_id : typing.Optional[str] + + oauth_app_id : typing.Optional[str] + The OAuth app ID to filter by, if applicable + + after : typing.Optional[str] + The cursor to start from for pagination + + before : typing.Optional[str] + The cursor to end before for pagination + + limit : typing.Optional[int] + The maximum number of results to return + + include_credentials : typing.Optional[bool] + Whether to retrieve the account's credentials or not + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncPager[Account] + accounts listed + + Examples + -------- + import asyncio + + from pipedream import AsyncPipedream + + client = AsyncPipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + + + async def main() -> None: + response = await client.accounts.list( + project_id="project_id", + ) + async for item in response: + yield item + + # alternatively, you can paginate page-by-page + async for page in response.iter_pages(): + yield page + + + asyncio.run(main()) + """ + return await self._raw_client.list( + project_id, + app_id=app_id, + external_user_id=external_user_id, + oauth_app_id=oauth_app_id, + after=after, + before=before, + limit=limit, + include_credentials=include_credentials, + request_options=request_options, + ) + + async def create( + self, + project_id: str, + *, + app_slug: str, + cfmap_json: str, + connect_token: str, + app_id: typing.Optional[str] = None, + external_user_id: typing.Optional[str] = None, + oauth_app_id: typing.Optional[str] = None, + name: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> Account: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + app_slug : str + The app slug for the account + + cfmap_json : str + JSON string containing the custom fields mapping + + connect_token : str + The connect token for authentication + + app_id : typing.Optional[str] + The app slug or ID to filter accounts by. + + external_user_id : typing.Optional[str] + + oauth_app_id : typing.Optional[str] + The OAuth app ID to filter by, if applicable + + name : typing.Optional[str] + Optional name for the account + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Account + account created + + Examples + -------- + import asyncio + + from pipedream import AsyncPipedream + + client = AsyncPipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + + + async def main() -> None: + await client.accounts.create( + project_id="project_id", + app_slug="app_slug", + cfmap_json="cfmap_json", + connect_token="connect_token", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.create( + project_id, + app_slug=app_slug, + cfmap_json=cfmap_json, + connect_token=connect_token, + app_id=app_id, + external_user_id=external_user_id, + oauth_app_id=oauth_app_id, + name=name, + request_options=request_options, + ) + return _response.data + + async def retrieve( + self, + project_id: str, + account_id: str, + *, + include_credentials: typing.Optional[bool] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> Account: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + account_id : str + + include_credentials : typing.Optional[bool] + Whether to retrieve the account's credentials or not + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Account + account retrieved + + Examples + -------- + import asyncio + + from pipedream import AsyncPipedream + + client = AsyncPipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + + + async def main() -> None: + await client.accounts.retrieve( + project_id="project_id", + account_id="account_id", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.retrieve( + project_id, account_id, include_credentials=include_credentials, request_options=request_options + ) + return _response.data + + async def delete( + self, project_id: str, account_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> None: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + account_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + None + + Examples + -------- + import asyncio + + from pipedream import AsyncPipedream + + client = AsyncPipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + + + async def main() -> None: + await client.accounts.delete( + project_id="project_id", + account_id="account_id", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.delete(project_id, account_id, request_options=request_options) + return _response.data + + async def delete_by_app( + self, project_id: str, app_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> None: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + app_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + None + + Examples + -------- + import asyncio + + from pipedream import AsyncPipedream + + client = AsyncPipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + + + async def main() -> None: + await client.accounts.delete_by_app( + project_id="project_id", + app_id="app_id", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.delete_by_app(project_id, app_id, request_options=request_options) + return _response.data diff --git a/src/pipedream/accounts/raw_client.py b/src/pipedream/accounts/raw_client.py new file mode 100644 index 0000000..8f5b61f --- /dev/null +++ b/src/pipedream/accounts/raw_client.py @@ -0,0 +1,608 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from json.decoder import JSONDecodeError + +from ..core.api_error import ApiError +from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ..core.http_response import AsyncHttpResponse, HttpResponse +from ..core.jsonable_encoder import jsonable_encoder +from ..core.pagination import AsyncPager, BaseHttpResponse, SyncPager +from ..core.pydantic_utilities import parse_obj_as +from ..core.request_options import RequestOptions +from ..types.account import Account +from ..types.list_accounts_response import ListAccountsResponse + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class RawAccountsClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def list( + self, + project_id: str, + *, + app_id: typing.Optional[str] = None, + external_user_id: typing.Optional[str] = None, + oauth_app_id: typing.Optional[str] = None, + after: typing.Optional[str] = None, + before: typing.Optional[str] = None, + limit: typing.Optional[int] = None, + include_credentials: typing.Optional[bool] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> SyncPager[Account]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + app_id : typing.Optional[str] + The app slug or ID to filter accounts by. + + external_user_id : typing.Optional[str] + + oauth_app_id : typing.Optional[str] + The OAuth app ID to filter by, if applicable + + after : typing.Optional[str] + The cursor to start from for pagination + + before : typing.Optional[str] + The cursor to end before for pagination + + limit : typing.Optional[int] + The maximum number of results to return + + include_credentials : typing.Optional[bool] + Whether to retrieve the account's credentials or not + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + SyncPager[Account] + accounts listed + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/accounts", + method="GET", + params={ + "app_id": app_id, + "external_user_id": external_user_id, + "oauth_app_id": oauth_app_id, + "after": after, + "before": before, + "limit": limit, + "include_credentials": include_credentials, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _parsed_response = typing.cast( + ListAccountsResponse, + parse_obj_as( + type_=ListAccountsResponse, # type: ignore + object_=_response.json(), + ), + ) + _items = _parsed_response.data + _has_next = False + _get_next = None + if _parsed_response.page_info is not None: + _parsed_next = _parsed_response.page_info.end_cursor + _has_next = _parsed_next is not None and _parsed_next != "" + _get_next = lambda: self.list( + project_id, + app_id=app_id, + external_user_id=external_user_id, + oauth_app_id=oauth_app_id, + after=_parsed_next, + before=before, + limit=limit, + include_credentials=include_credentials, + request_options=request_options, + ) + return SyncPager( + has_next=_has_next, items=_items, get_next=_get_next, response=BaseHttpResponse(response=_response) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def create( + self, + project_id: str, + *, + app_slug: str, + cfmap_json: str, + connect_token: str, + app_id: typing.Optional[str] = None, + external_user_id: typing.Optional[str] = None, + oauth_app_id: typing.Optional[str] = None, + name: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[Account]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + app_slug : str + The app slug for the account + + cfmap_json : str + JSON string containing the custom fields mapping + + connect_token : str + The connect token for authentication + + app_id : typing.Optional[str] + The app slug or ID to filter accounts by. + + external_user_id : typing.Optional[str] + + oauth_app_id : typing.Optional[str] + The OAuth app ID to filter by, if applicable + + name : typing.Optional[str] + Optional name for the account + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[Account] + account created + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/accounts", + method="POST", + params={ + "app_id": app_id, + "external_user_id": external_user_id, + "oauth_app_id": oauth_app_id, + }, + json={ + "app_slug": app_slug, + "cfmap_json": cfmap_json, + "connect_token": connect_token, + "name": name, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Account, + parse_obj_as( + type_=Account, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def retrieve( + self, + project_id: str, + account_id: str, + *, + include_credentials: typing.Optional[bool] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[Account]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + account_id : str + + include_credentials : typing.Optional[bool] + Whether to retrieve the account's credentials or not + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[Account] + account retrieved + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/accounts/{jsonable_encoder(account_id)}", + method="GET", + params={ + "include_credentials": include_credentials, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Account, + parse_obj_as( + type_=Account, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def delete( + self, project_id: str, account_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[None]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + account_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[None] + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/accounts/{jsonable_encoder(account_id)}", + method="DELETE", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return HttpResponse(response=_response, data=None) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def delete_by_app( + self, project_id: str, app_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[None]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + app_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[None] + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/apps/{jsonable_encoder(app_id)}/accounts", + method="DELETE", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return HttpResponse(response=_response, data=None) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + +class AsyncRawAccountsClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def list( + self, + project_id: str, + *, + app_id: typing.Optional[str] = None, + external_user_id: typing.Optional[str] = None, + oauth_app_id: typing.Optional[str] = None, + after: typing.Optional[str] = None, + before: typing.Optional[str] = None, + limit: typing.Optional[int] = None, + include_credentials: typing.Optional[bool] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncPager[Account]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + app_id : typing.Optional[str] + The app slug or ID to filter accounts by. + + external_user_id : typing.Optional[str] + + oauth_app_id : typing.Optional[str] + The OAuth app ID to filter by, if applicable + + after : typing.Optional[str] + The cursor to start from for pagination + + before : typing.Optional[str] + The cursor to end before for pagination + + limit : typing.Optional[int] + The maximum number of results to return + + include_credentials : typing.Optional[bool] + Whether to retrieve the account's credentials or not + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncPager[Account] + accounts listed + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/accounts", + method="GET", + params={ + "app_id": app_id, + "external_user_id": external_user_id, + "oauth_app_id": oauth_app_id, + "after": after, + "before": before, + "limit": limit, + "include_credentials": include_credentials, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _parsed_response = typing.cast( + ListAccountsResponse, + parse_obj_as( + type_=ListAccountsResponse, # type: ignore + object_=_response.json(), + ), + ) + _items = _parsed_response.data + _has_next = False + _get_next = None + if _parsed_response.page_info is not None: + _parsed_next = _parsed_response.page_info.end_cursor + _has_next = _parsed_next is not None and _parsed_next != "" + + async def _get_next(): + return await self.list( + project_id, + app_id=app_id, + external_user_id=external_user_id, + oauth_app_id=oauth_app_id, + after=_parsed_next, + before=before, + limit=limit, + include_credentials=include_credentials, + request_options=request_options, + ) + + return AsyncPager( + has_next=_has_next, items=_items, get_next=_get_next, response=BaseHttpResponse(response=_response) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def create( + self, + project_id: str, + *, + app_slug: str, + cfmap_json: str, + connect_token: str, + app_id: typing.Optional[str] = None, + external_user_id: typing.Optional[str] = None, + oauth_app_id: typing.Optional[str] = None, + name: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[Account]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + app_slug : str + The app slug for the account + + cfmap_json : str + JSON string containing the custom fields mapping + + connect_token : str + The connect token for authentication + + app_id : typing.Optional[str] + The app slug or ID to filter accounts by. + + external_user_id : typing.Optional[str] + + oauth_app_id : typing.Optional[str] + The OAuth app ID to filter by, if applicable + + name : typing.Optional[str] + Optional name for the account + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[Account] + account created + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/accounts", + method="POST", + params={ + "app_id": app_id, + "external_user_id": external_user_id, + "oauth_app_id": oauth_app_id, + }, + json={ + "app_slug": app_slug, + "cfmap_json": cfmap_json, + "connect_token": connect_token, + "name": name, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Account, + parse_obj_as( + type_=Account, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def retrieve( + self, + project_id: str, + account_id: str, + *, + include_credentials: typing.Optional[bool] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[Account]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + account_id : str + + include_credentials : typing.Optional[bool] + Whether to retrieve the account's credentials or not + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[Account] + account retrieved + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/accounts/{jsonable_encoder(account_id)}", + method="GET", + params={ + "include_credentials": include_credentials, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + Account, + parse_obj_as( + type_=Account, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def delete( + self, project_id: str, account_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[None]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + account_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[None] + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/accounts/{jsonable_encoder(account_id)}", + method="DELETE", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return AsyncHttpResponse(response=_response, data=None) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def delete_by_app( + self, project_id: str, app_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[None]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + app_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[None] + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/apps/{jsonable_encoder(app_id)}/accounts", + method="DELETE", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return AsyncHttpResponse(response=_response, data=None) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/pipedream/actions/__init__.py b/src/pipedream/actions/__init__.py new file mode 100644 index 0000000..5cde020 --- /dev/null +++ b/src/pipedream/actions/__init__.py @@ -0,0 +1,4 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + diff --git a/src/pipedream/actions/client.py b/src/pipedream/actions/client.py new file mode 100644 index 0000000..55f4d68 --- /dev/null +++ b/src/pipedream/actions/client.py @@ -0,0 +1,758 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ..core.pagination import AsyncPager, SyncPager +from ..core.request_options import RequestOptions +from ..types.component import Component +from ..types.configure_prop_response import ConfigurePropResponse +from ..types.reload_props_response import ReloadPropsResponse +from ..types.run_action_response import RunActionResponse +from .raw_client import AsyncRawActionsClient, RawActionsClient + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class ActionsClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._raw_client = RawActionsClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawActionsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawActionsClient + """ + return self._raw_client + + def list( + self, + project_id: str, + *, + after: typing.Optional[str] = None, + before: typing.Optional[str] = None, + limit: typing.Optional[int] = None, + q: typing.Optional[str] = None, + app: typing.Optional[str] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> SyncPager[Component]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + after : typing.Optional[str] + The cursor to start from for pagination + + before : typing.Optional[str] + The cursor to end before for pagination + + limit : typing.Optional[int] + The maximum number of results to return + + q : typing.Optional[str] + A search query to filter the actions + + app : typing.Optional[str] + The ID or name slug of the app to filter the actions + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + SyncPager[Component] + actions listed + + Examples + -------- + from pipedream import Pipedream + + client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + response = client.actions.list( + project_id="project_id", + ) + for item in response: + yield item + # alternatively, you can paginate page-by-page + for page in response.iter_pages(): + yield page + """ + return self._raw_client.list( + project_id, after=after, before=before, limit=limit, q=q, app=app, request_options=request_options + ) + + def retrieve( + self, project_id: str, component_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> Component: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + component_id : str + The key that uniquely identifies the component (e.g., 'slack-send-message') + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Component + action retrieved + + Examples + -------- + from pipedream import Pipedream + + client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + client.actions.retrieve( + project_id="project_id", + component_id="component_id", + ) + """ + _response = self._raw_client.retrieve(project_id, component_id, request_options=request_options) + return _response.data + + def configure_prop( + self, + project_id: str, + *, + id: str, + external_user_id: str, + prop_name: str, + async_handle: typing.Optional[str] = None, + blocking: typing.Optional[bool] = OMIT, + configured_props: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, + dynamic_props_id: typing.Optional[str] = OMIT, + configure_prop_opts_async_handle: typing.Optional[str] = OMIT, + page: typing.Optional[float] = OMIT, + prev_context: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, + query: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> ConfigurePropResponse: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + id : str + The component ID + + external_user_id : str + The external user ID + + prop_name : str + The name of the prop to configure + + async_handle : typing.Optional[str] + + blocking : typing.Optional[bool] + Whether this operation should block until completion + + configured_props : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] + The configured properties for the component + + dynamic_props_id : typing.Optional[str] + The ID for dynamic props + + configure_prop_opts_async_handle : typing.Optional[str] + Handle for async operations + + page : typing.Optional[float] + Page number for paginated results + + prev_context : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] + Previous context for pagination + + query : typing.Optional[str] + Search query for filtering options + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ConfigurePropResponse + action configuration started + + Examples + -------- + from pipedream import Pipedream + + client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + client.actions.configure_prop( + project_id="project_id", + id="id", + external_user_id="external_user_id", + prop_name="prop_name", + ) + """ + _response = self._raw_client.configure_prop( + project_id, + id=id, + external_user_id=external_user_id, + prop_name=prop_name, + async_handle=async_handle, + blocking=blocking, + configured_props=configured_props, + dynamic_props_id=dynamic_props_id, + configure_prop_opts_async_handle=configure_prop_opts_async_handle, + page=page, + prev_context=prev_context, + query=query, + request_options=request_options, + ) + return _response.data + + def reload_props( + self, + project_id: str, + *, + id: str, + external_user_id: str, + async_handle: typing.Optional[str] = None, + blocking: typing.Optional[bool] = OMIT, + configured_props: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, + dynamic_props_id: typing.Optional[str] = OMIT, + reload_props_opts_async_handle: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> ReloadPropsResponse: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + id : str + The component ID + + external_user_id : str + The external user ID + + async_handle : typing.Optional[str] + + blocking : typing.Optional[bool] + Whether this operation should block until completion + + configured_props : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] + The configured properties for the component + + dynamic_props_id : typing.Optional[str] + The ID for dynamic props + + reload_props_opts_async_handle : typing.Optional[str] + Handle for async operations + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ReloadPropsResponse + action props reloaded + + Examples + -------- + from pipedream import Pipedream + + client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + client.actions.reload_props( + project_id="project_id", + id="id", + external_user_id="external_user_id", + ) + """ + _response = self._raw_client.reload_props( + project_id, + id=id, + external_user_id=external_user_id, + async_handle=async_handle, + blocking=blocking, + configured_props=configured_props, + dynamic_props_id=dynamic_props_id, + reload_props_opts_async_handle=reload_props_opts_async_handle, + request_options=request_options, + ) + return _response.data + + def run( + self, + project_id: str, + *, + id: str, + external_user_id: str, + async_handle: typing.Optional[str] = None, + configured_props: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, + dynamic_props_id: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> RunActionResponse: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + id : str + The action component ID + + external_user_id : str + The external user ID + + async_handle : typing.Optional[str] + + configured_props : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] + The configured properties for the action + + dynamic_props_id : typing.Optional[str] + The ID for dynamic props + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + RunActionResponse + action ran + + Examples + -------- + from pipedream import Pipedream + + client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + client.actions.run( + project_id="project_id", + id="id", + external_user_id="external_user_id", + ) + """ + _response = self._raw_client.run( + project_id, + id=id, + external_user_id=external_user_id, + async_handle=async_handle, + configured_props=configured_props, + dynamic_props_id=dynamic_props_id, + request_options=request_options, + ) + return _response.data + + +class AsyncActionsClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._raw_client = AsyncRawActionsClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawActionsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawActionsClient + """ + return self._raw_client + + async def list( + self, + project_id: str, + *, + after: typing.Optional[str] = None, + before: typing.Optional[str] = None, + limit: typing.Optional[int] = None, + q: typing.Optional[str] = None, + app: typing.Optional[str] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncPager[Component]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + after : typing.Optional[str] + The cursor to start from for pagination + + before : typing.Optional[str] + The cursor to end before for pagination + + limit : typing.Optional[int] + The maximum number of results to return + + q : typing.Optional[str] + A search query to filter the actions + + app : typing.Optional[str] + The ID or name slug of the app to filter the actions + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncPager[Component] + actions listed + + Examples + -------- + import asyncio + + from pipedream import AsyncPipedream + + client = AsyncPipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + + + async def main() -> None: + response = await client.actions.list( + project_id="project_id", + ) + async for item in response: + yield item + + # alternatively, you can paginate page-by-page + async for page in response.iter_pages(): + yield page + + + asyncio.run(main()) + """ + return await self._raw_client.list( + project_id, after=after, before=before, limit=limit, q=q, app=app, request_options=request_options + ) + + async def retrieve( + self, project_id: str, component_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> Component: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + component_id : str + The key that uniquely identifies the component (e.g., 'slack-send-message') + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Component + action retrieved + + Examples + -------- + import asyncio + + from pipedream import AsyncPipedream + + client = AsyncPipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + + + async def main() -> None: + await client.actions.retrieve( + project_id="project_id", + component_id="component_id", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.retrieve(project_id, component_id, request_options=request_options) + return _response.data + + async def configure_prop( + self, + project_id: str, + *, + id: str, + external_user_id: str, + prop_name: str, + async_handle: typing.Optional[str] = None, + blocking: typing.Optional[bool] = OMIT, + configured_props: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, + dynamic_props_id: typing.Optional[str] = OMIT, + configure_prop_opts_async_handle: typing.Optional[str] = OMIT, + page: typing.Optional[float] = OMIT, + prev_context: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, + query: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> ConfigurePropResponse: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + id : str + The component ID + + external_user_id : str + The external user ID + + prop_name : str + The name of the prop to configure + + async_handle : typing.Optional[str] + + blocking : typing.Optional[bool] + Whether this operation should block until completion + + configured_props : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] + The configured properties for the component + + dynamic_props_id : typing.Optional[str] + The ID for dynamic props + + configure_prop_opts_async_handle : typing.Optional[str] + Handle for async operations + + page : typing.Optional[float] + Page number for paginated results + + prev_context : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] + Previous context for pagination + + query : typing.Optional[str] + Search query for filtering options + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ConfigurePropResponse + action configuration started + + Examples + -------- + import asyncio + + from pipedream import AsyncPipedream + + client = AsyncPipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + + + async def main() -> None: + await client.actions.configure_prop( + project_id="project_id", + id="id", + external_user_id="external_user_id", + prop_name="prop_name", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.configure_prop( + project_id, + id=id, + external_user_id=external_user_id, + prop_name=prop_name, + async_handle=async_handle, + blocking=blocking, + configured_props=configured_props, + dynamic_props_id=dynamic_props_id, + configure_prop_opts_async_handle=configure_prop_opts_async_handle, + page=page, + prev_context=prev_context, + query=query, + request_options=request_options, + ) + return _response.data + + async def reload_props( + self, + project_id: str, + *, + id: str, + external_user_id: str, + async_handle: typing.Optional[str] = None, + blocking: typing.Optional[bool] = OMIT, + configured_props: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, + dynamic_props_id: typing.Optional[str] = OMIT, + reload_props_opts_async_handle: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> ReloadPropsResponse: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + id : str + The component ID + + external_user_id : str + The external user ID + + async_handle : typing.Optional[str] + + blocking : typing.Optional[bool] + Whether this operation should block until completion + + configured_props : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] + The configured properties for the component + + dynamic_props_id : typing.Optional[str] + The ID for dynamic props + + reload_props_opts_async_handle : typing.Optional[str] + Handle for async operations + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ReloadPropsResponse + action props reloaded + + Examples + -------- + import asyncio + + from pipedream import AsyncPipedream + + client = AsyncPipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + + + async def main() -> None: + await client.actions.reload_props( + project_id="project_id", + id="id", + external_user_id="external_user_id", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.reload_props( + project_id, + id=id, + external_user_id=external_user_id, + async_handle=async_handle, + blocking=blocking, + configured_props=configured_props, + dynamic_props_id=dynamic_props_id, + reload_props_opts_async_handle=reload_props_opts_async_handle, + request_options=request_options, + ) + return _response.data + + async def run( + self, + project_id: str, + *, + id: str, + external_user_id: str, + async_handle: typing.Optional[str] = None, + configured_props: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, + dynamic_props_id: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> RunActionResponse: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + id : str + The action component ID + + external_user_id : str + The external user ID + + async_handle : typing.Optional[str] + + configured_props : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] + The configured properties for the action + + dynamic_props_id : typing.Optional[str] + The ID for dynamic props + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + RunActionResponse + action ran + + Examples + -------- + import asyncio + + from pipedream import AsyncPipedream + + client = AsyncPipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + + + async def main() -> None: + await client.actions.run( + project_id="project_id", + id="id", + external_user_id="external_user_id", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.run( + project_id, + id=id, + external_user_id=external_user_id, + async_handle=async_handle, + configured_props=configured_props, + dynamic_props_id=dynamic_props_id, + request_options=request_options, + ) + return _response.data diff --git a/src/pipedream/actions/raw_client.py b/src/pipedream/actions/raw_client.py new file mode 100644 index 0000000..5da94c5 --- /dev/null +++ b/src/pipedream/actions/raw_client.py @@ -0,0 +1,784 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from json.decoder import JSONDecodeError + +from ..core.api_error import ApiError +from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ..core.http_response import AsyncHttpResponse, HttpResponse +from ..core.jsonable_encoder import jsonable_encoder +from ..core.pagination import AsyncPager, BaseHttpResponse, SyncPager +from ..core.pydantic_utilities import parse_obj_as +from ..core.request_options import RequestOptions +from ..types.component import Component +from ..types.configure_prop_response import ConfigurePropResponse +from ..types.get_component_response import GetComponentResponse +from ..types.get_components_response import GetComponentsResponse +from ..types.reload_props_response import ReloadPropsResponse +from ..types.run_action_response import RunActionResponse + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class RawActionsClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def list( + self, + project_id: str, + *, + after: typing.Optional[str] = None, + before: typing.Optional[str] = None, + limit: typing.Optional[int] = None, + q: typing.Optional[str] = None, + app: typing.Optional[str] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> SyncPager[Component]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + after : typing.Optional[str] + The cursor to start from for pagination + + before : typing.Optional[str] + The cursor to end before for pagination + + limit : typing.Optional[int] + The maximum number of results to return + + q : typing.Optional[str] + A search query to filter the actions + + app : typing.Optional[str] + The ID or name slug of the app to filter the actions + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + SyncPager[Component] + actions listed + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/actions", + method="GET", + params={ + "after": after, + "before": before, + "limit": limit, + "q": q, + "app": app, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _parsed_response = typing.cast( + GetComponentsResponse, + parse_obj_as( + type_=GetComponentsResponse, # type: ignore + object_=_response.json(), + ), + ) + _items = _parsed_response.data + _has_next = False + _get_next = None + if _parsed_response.page_info is not None: + _parsed_next = _parsed_response.page_info.end_cursor + _has_next = _parsed_next is not None and _parsed_next != "" + _get_next = lambda: self.list( + project_id, + after=_parsed_next, + before=before, + limit=limit, + q=q, + app=app, + request_options=request_options, + ) + return SyncPager( + has_next=_has_next, items=_items, get_next=_get_next, response=BaseHttpResponse(response=_response) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def retrieve( + self, project_id: str, component_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[Component]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + component_id : str + The key that uniquely identifies the component (e.g., 'slack-send-message') + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[Component] + action retrieved + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/actions/{jsonable_encoder(component_id)}", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _parsed_response = typing.cast( + GetComponentResponse, + parse_obj_as( + type_=GetComponentResponse, # type: ignore + object_=_response.json(), + ), + ) + _data = _parsed_response.data + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def configure_prop( + self, + project_id: str, + *, + id: str, + external_user_id: str, + prop_name: str, + async_handle: typing.Optional[str] = None, + blocking: typing.Optional[bool] = OMIT, + configured_props: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, + dynamic_props_id: typing.Optional[str] = OMIT, + configure_prop_opts_async_handle: typing.Optional[str] = OMIT, + page: typing.Optional[float] = OMIT, + prev_context: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, + query: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[ConfigurePropResponse]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + id : str + The component ID + + external_user_id : str + The external user ID + + prop_name : str + The name of the prop to configure + + async_handle : typing.Optional[str] + + blocking : typing.Optional[bool] + Whether this operation should block until completion + + configured_props : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] + The configured properties for the component + + dynamic_props_id : typing.Optional[str] + The ID for dynamic props + + configure_prop_opts_async_handle : typing.Optional[str] + Handle for async operations + + page : typing.Optional[float] + Page number for paginated results + + prev_context : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] + Previous context for pagination + + query : typing.Optional[str] + Search query for filtering options + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[ConfigurePropResponse] + action configuration started + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/actions/configure", + method="POST", + json={ + "id": id, + "external_user_id": external_user_id, + "prop_name": prop_name, + "blocking": blocking, + "configured_props": configured_props, + "dynamic_props_id": dynamic_props_id, + "async_handle": async_handle, + "page": page, + "prev_context": prev_context, + "query": query, + }, + headers={ + "content-type": "application/json", + "x-async-handle": str(async_handle) if async_handle is not None else None, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ConfigurePropResponse, + parse_obj_as( + type_=ConfigurePropResponse, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def reload_props( + self, + project_id: str, + *, + id: str, + external_user_id: str, + async_handle: typing.Optional[str] = None, + blocking: typing.Optional[bool] = OMIT, + configured_props: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, + dynamic_props_id: typing.Optional[str] = OMIT, + reload_props_opts_async_handle: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[ReloadPropsResponse]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + id : str + The component ID + + external_user_id : str + The external user ID + + async_handle : typing.Optional[str] + + blocking : typing.Optional[bool] + Whether this operation should block until completion + + configured_props : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] + The configured properties for the component + + dynamic_props_id : typing.Optional[str] + The ID for dynamic props + + reload_props_opts_async_handle : typing.Optional[str] + Handle for async operations + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[ReloadPropsResponse] + action props reloaded + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/actions/props", + method="POST", + json={ + "id": id, + "external_user_id": external_user_id, + "blocking": blocking, + "configured_props": configured_props, + "dynamic_props_id": dynamic_props_id, + "async_handle": async_handle, + }, + headers={ + "content-type": "application/json", + "x-async-handle": str(async_handle) if async_handle is not None else None, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ReloadPropsResponse, + parse_obj_as( + type_=ReloadPropsResponse, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def run( + self, + project_id: str, + *, + id: str, + external_user_id: str, + async_handle: typing.Optional[str] = None, + configured_props: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, + dynamic_props_id: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[RunActionResponse]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + id : str + The action component ID + + external_user_id : str + The external user ID + + async_handle : typing.Optional[str] + + configured_props : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] + The configured properties for the action + + dynamic_props_id : typing.Optional[str] + The ID for dynamic props + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[RunActionResponse] + action ran + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/actions/run", + method="POST", + json={ + "id": id, + "external_user_id": external_user_id, + "configured_props": configured_props, + "dynamic_props_id": dynamic_props_id, + }, + headers={ + "content-type": "application/json", + "x-async-handle": str(async_handle) if async_handle is not None else None, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + RunActionResponse, + parse_obj_as( + type_=RunActionResponse, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + +class AsyncRawActionsClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def list( + self, + project_id: str, + *, + after: typing.Optional[str] = None, + before: typing.Optional[str] = None, + limit: typing.Optional[int] = None, + q: typing.Optional[str] = None, + app: typing.Optional[str] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncPager[Component]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + after : typing.Optional[str] + The cursor to start from for pagination + + before : typing.Optional[str] + The cursor to end before for pagination + + limit : typing.Optional[int] + The maximum number of results to return + + q : typing.Optional[str] + A search query to filter the actions + + app : typing.Optional[str] + The ID or name slug of the app to filter the actions + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncPager[Component] + actions listed + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/actions", + method="GET", + params={ + "after": after, + "before": before, + "limit": limit, + "q": q, + "app": app, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _parsed_response = typing.cast( + GetComponentsResponse, + parse_obj_as( + type_=GetComponentsResponse, # type: ignore + object_=_response.json(), + ), + ) + _items = _parsed_response.data + _has_next = False + _get_next = None + if _parsed_response.page_info is not None: + _parsed_next = _parsed_response.page_info.end_cursor + _has_next = _parsed_next is not None and _parsed_next != "" + + async def _get_next(): + return await self.list( + project_id, + after=_parsed_next, + before=before, + limit=limit, + q=q, + app=app, + request_options=request_options, + ) + + return AsyncPager( + has_next=_has_next, items=_items, get_next=_get_next, response=BaseHttpResponse(response=_response) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def retrieve( + self, project_id: str, component_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[Component]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + component_id : str + The key that uniquely identifies the component (e.g., 'slack-send-message') + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[Component] + action retrieved + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/actions/{jsonable_encoder(component_id)}", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _parsed_response = typing.cast( + GetComponentResponse, + parse_obj_as( + type_=GetComponentResponse, # type: ignore + object_=_response.json(), + ), + ) + _data = _parsed_response.data + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def configure_prop( + self, + project_id: str, + *, + id: str, + external_user_id: str, + prop_name: str, + async_handle: typing.Optional[str] = None, + blocking: typing.Optional[bool] = OMIT, + configured_props: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, + dynamic_props_id: typing.Optional[str] = OMIT, + configure_prop_opts_async_handle: typing.Optional[str] = OMIT, + page: typing.Optional[float] = OMIT, + prev_context: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, + query: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[ConfigurePropResponse]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + id : str + The component ID + + external_user_id : str + The external user ID + + prop_name : str + The name of the prop to configure + + async_handle : typing.Optional[str] + + blocking : typing.Optional[bool] + Whether this operation should block until completion + + configured_props : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] + The configured properties for the component + + dynamic_props_id : typing.Optional[str] + The ID for dynamic props + + configure_prop_opts_async_handle : typing.Optional[str] + Handle for async operations + + page : typing.Optional[float] + Page number for paginated results + + prev_context : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] + Previous context for pagination + + query : typing.Optional[str] + Search query for filtering options + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[ConfigurePropResponse] + action configuration started + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/actions/configure", + method="POST", + json={ + "id": id, + "external_user_id": external_user_id, + "prop_name": prop_name, + "blocking": blocking, + "configured_props": configured_props, + "dynamic_props_id": dynamic_props_id, + "async_handle": async_handle, + "page": page, + "prev_context": prev_context, + "query": query, + }, + headers={ + "content-type": "application/json", + "x-async-handle": str(async_handle) if async_handle is not None else None, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ConfigurePropResponse, + parse_obj_as( + type_=ConfigurePropResponse, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def reload_props( + self, + project_id: str, + *, + id: str, + external_user_id: str, + async_handle: typing.Optional[str] = None, + blocking: typing.Optional[bool] = OMIT, + configured_props: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, + dynamic_props_id: typing.Optional[str] = OMIT, + reload_props_opts_async_handle: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[ReloadPropsResponse]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + id : str + The component ID + + external_user_id : str + The external user ID + + async_handle : typing.Optional[str] + + blocking : typing.Optional[bool] + Whether this operation should block until completion + + configured_props : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] + The configured properties for the component + + dynamic_props_id : typing.Optional[str] + The ID for dynamic props + + reload_props_opts_async_handle : typing.Optional[str] + Handle for async operations + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[ReloadPropsResponse] + action props reloaded + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/actions/props", + method="POST", + json={ + "id": id, + "external_user_id": external_user_id, + "blocking": blocking, + "configured_props": configured_props, + "dynamic_props_id": dynamic_props_id, + "async_handle": async_handle, + }, + headers={ + "content-type": "application/json", + "x-async-handle": str(async_handle) if async_handle is not None else None, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ReloadPropsResponse, + parse_obj_as( + type_=ReloadPropsResponse, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def run( + self, + project_id: str, + *, + id: str, + external_user_id: str, + async_handle: typing.Optional[str] = None, + configured_props: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, + dynamic_props_id: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[RunActionResponse]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + id : str + The action component ID + + external_user_id : str + The external user ID + + async_handle : typing.Optional[str] + + configured_props : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] + The configured properties for the action + + dynamic_props_id : typing.Optional[str] + The ID for dynamic props + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[RunActionResponse] + action ran + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/actions/run", + method="POST", + json={ + "id": id, + "external_user_id": external_user_id, + "configured_props": configured_props, + "dynamic_props_id": dynamic_props_id, + }, + headers={ + "content-type": "application/json", + "x-async-handle": str(async_handle) if async_handle is not None else None, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + RunActionResponse, + parse_obj_as( + type_=RunActionResponse, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/pipedream/app_categories/__init__.py b/src/pipedream/app_categories/__init__.py new file mode 100644 index 0000000..5cde020 --- /dev/null +++ b/src/pipedream/app_categories/__init__.py @@ -0,0 +1,4 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + diff --git a/src/pipedream/app_categories/client.py b/src/pipedream/app_categories/client.py new file mode 100644 index 0000000..7079f95 --- /dev/null +++ b/src/pipedream/app_categories/client.py @@ -0,0 +1,173 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ..core.request_options import RequestOptions +from ..types.get_app_category_response import GetAppCategoryResponse +from ..types.list_app_categories_response import ListAppCategoriesResponse +from .raw_client import AsyncRawAppCategoriesClient, RawAppCategoriesClient + + +class AppCategoriesClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._raw_client = RawAppCategoriesClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawAppCategoriesClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawAppCategoriesClient + """ + return self._raw_client + + def list(self, *, request_options: typing.Optional[RequestOptions] = None) -> ListAppCategoriesResponse: + """ + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ListAppCategoriesResponse + apps listed + + Examples + -------- + from pipedream import Pipedream + + client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + client.app_categories.list() + """ + _response = self._raw_client.list(request_options=request_options) + return _response.data + + def retrieve(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> GetAppCategoryResponse: + """ + Parameters + ---------- + id : str + The ID of the app category to retrieve + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + GetAppCategoryResponse + app retrieved + + Examples + -------- + from pipedream import Pipedream + + client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + client.app_categories.retrieve( + id="id", + ) + """ + _response = self._raw_client.retrieve(id, request_options=request_options) + return _response.data + + +class AsyncAppCategoriesClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._raw_client = AsyncRawAppCategoriesClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawAppCategoriesClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawAppCategoriesClient + """ + return self._raw_client + + async def list(self, *, request_options: typing.Optional[RequestOptions] = None) -> ListAppCategoriesResponse: + """ + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ListAppCategoriesResponse + apps listed + + Examples + -------- + import asyncio + + from pipedream import AsyncPipedream + + client = AsyncPipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + + + async def main() -> None: + await client.app_categories.list() + + + asyncio.run(main()) + """ + _response = await self._raw_client.list(request_options=request_options) + return _response.data + + async def retrieve( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> GetAppCategoryResponse: + """ + Parameters + ---------- + id : str + The ID of the app category to retrieve + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + GetAppCategoryResponse + app retrieved + + Examples + -------- + import asyncio + + from pipedream import AsyncPipedream + + client = AsyncPipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + + + async def main() -> None: + await client.app_categories.retrieve( + id="id", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.retrieve(id, request_options=request_options) + return _response.data diff --git a/src/pipedream/app_categories/raw_client.py b/src/pipedream/app_categories/raw_client.py new file mode 100644 index 0000000..28fdbdb --- /dev/null +++ b/src/pipedream/app_categories/raw_client.py @@ -0,0 +1,165 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from json.decoder import JSONDecodeError + +from ..core.api_error import ApiError +from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ..core.http_response import AsyncHttpResponse, HttpResponse +from ..core.jsonable_encoder import jsonable_encoder +from ..core.pydantic_utilities import parse_obj_as +from ..core.request_options import RequestOptions +from ..types.get_app_category_response import GetAppCategoryResponse +from ..types.list_app_categories_response import ListAppCategoriesResponse + + +class RawAppCategoriesClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def list( + self, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[ListAppCategoriesResponse]: + """ + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[ListAppCategoriesResponse] + apps listed + """ + _response = self._client_wrapper.httpx_client.request( + "v1/connect/app_categories", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ListAppCategoriesResponse, + parse_obj_as( + type_=ListAppCategoriesResponse, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def retrieve( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[GetAppCategoryResponse]: + """ + Parameters + ---------- + id : str + The ID of the app category to retrieve + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[GetAppCategoryResponse] + app retrieved + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/connect/app_categories/{jsonable_encoder(id)}", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + GetAppCategoryResponse, + parse_obj_as( + type_=GetAppCategoryResponse, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + +class AsyncRawAppCategoriesClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def list( + self, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[ListAppCategoriesResponse]: + """ + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[ListAppCategoriesResponse] + apps listed + """ + _response = await self._client_wrapper.httpx_client.request( + "v1/connect/app_categories", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ListAppCategoriesResponse, + parse_obj_as( + type_=ListAppCategoriesResponse, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def retrieve( + self, id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[GetAppCategoryResponse]: + """ + Parameters + ---------- + id : str + The ID of the app category to retrieve + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[GetAppCategoryResponse] + app retrieved + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/connect/app_categories/{jsonable_encoder(id)}", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + GetAppCategoryResponse, + parse_obj_as( + type_=GetAppCategoryResponse, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/pipedream/apps/__init__.py b/src/pipedream/apps/__init__.py new file mode 100644 index 0000000..66417f3 --- /dev/null +++ b/src/pipedream/apps/__init__.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +from .types import AppsListRequestSortDirection, AppsListRequestSortKey + +__all__ = ["AppsListRequestSortDirection", "AppsListRequestSortKey"] diff --git a/src/pipedream/apps/client.py b/src/pipedream/apps/client.py new file mode 100644 index 0000000..7b0556a --- /dev/null +++ b/src/pipedream/apps/client.py @@ -0,0 +1,265 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ..core.pagination import AsyncPager, SyncPager +from ..core.request_options import RequestOptions +from ..types.app import App +from ..types.get_app_response import GetAppResponse +from .raw_client import AsyncRawAppsClient, RawAppsClient +from .types.apps_list_request_sort_direction import AppsListRequestSortDirection +from .types.apps_list_request_sort_key import AppsListRequestSortKey + + +class AppsClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._raw_client = RawAppsClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawAppsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawAppsClient + """ + return self._raw_client + + def list( + self, + *, + after: typing.Optional[str] = None, + before: typing.Optional[str] = None, + limit: typing.Optional[int] = None, + q: typing.Optional[str] = None, + sort_key: typing.Optional[AppsListRequestSortKey] = None, + sort_direction: typing.Optional[AppsListRequestSortDirection] = None, + category_ids: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> SyncPager[App]: + """ + Parameters + ---------- + after : typing.Optional[str] + The cursor to start from for pagination + + before : typing.Optional[str] + The cursor to end before for pagination + + limit : typing.Optional[int] + The maximum number of results to return + + q : typing.Optional[str] + A search query to filter the apps + + sort_key : typing.Optional[AppsListRequestSortKey] + The key to sort the apps by + + sort_direction : typing.Optional[AppsListRequestSortDirection] + The direction to sort the apps + + category_ids : typing.Optional[typing.Union[str, typing.Sequence[str]]] + Only return apps in these categories + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + SyncPager[App] + apps listed + + Examples + -------- + from pipedream import Pipedream + + client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + response = client.apps.list() + for item in response: + yield item + # alternatively, you can paginate page-by-page + for page in response.iter_pages(): + yield page + """ + return self._raw_client.list( + after=after, + before=before, + limit=limit, + q=q, + sort_key=sort_key, + sort_direction=sort_direction, + category_ids=category_ids, + request_options=request_options, + ) + + def retrieve(self, app_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> GetAppResponse: + """ + Parameters + ---------- + app_id : str + The name slug or ID of the app (e.g., 'slack', 'github') + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + GetAppResponse + app retrieved + + Examples + -------- + from pipedream import Pipedream + + client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + client.apps.retrieve( + app_id="app_id", + ) + """ + _response = self._raw_client.retrieve(app_id, request_options=request_options) + return _response.data + + +class AsyncAppsClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._raw_client = AsyncRawAppsClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawAppsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawAppsClient + """ + return self._raw_client + + async def list( + self, + *, + after: typing.Optional[str] = None, + before: typing.Optional[str] = None, + limit: typing.Optional[int] = None, + q: typing.Optional[str] = None, + sort_key: typing.Optional[AppsListRequestSortKey] = None, + sort_direction: typing.Optional[AppsListRequestSortDirection] = None, + category_ids: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncPager[App]: + """ + Parameters + ---------- + after : typing.Optional[str] + The cursor to start from for pagination + + before : typing.Optional[str] + The cursor to end before for pagination + + limit : typing.Optional[int] + The maximum number of results to return + + q : typing.Optional[str] + A search query to filter the apps + + sort_key : typing.Optional[AppsListRequestSortKey] + The key to sort the apps by + + sort_direction : typing.Optional[AppsListRequestSortDirection] + The direction to sort the apps + + category_ids : typing.Optional[typing.Union[str, typing.Sequence[str]]] + Only return apps in these categories + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncPager[App] + apps listed + + Examples + -------- + import asyncio + + from pipedream import AsyncPipedream + + client = AsyncPipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + + + async def main() -> None: + response = await client.apps.list() + async for item in response: + yield item + + # alternatively, you can paginate page-by-page + async for page in response.iter_pages(): + yield page + + + asyncio.run(main()) + """ + return await self._raw_client.list( + after=after, + before=before, + limit=limit, + q=q, + sort_key=sort_key, + sort_direction=sort_direction, + category_ids=category_ids, + request_options=request_options, + ) + + async def retrieve(self, app_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> GetAppResponse: + """ + Parameters + ---------- + app_id : str + The name slug or ID of the app (e.g., 'slack', 'github') + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + GetAppResponse + app retrieved + + Examples + -------- + import asyncio + + from pipedream import AsyncPipedream + + client = AsyncPipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + + + async def main() -> None: + await client.apps.retrieve( + app_id="app_id", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.retrieve(app_id, request_options=request_options) + return _response.data diff --git a/src/pipedream/apps/raw_client.py b/src/pipedream/apps/raw_client.py new file mode 100644 index 0000000..d850825 --- /dev/null +++ b/src/pipedream/apps/raw_client.py @@ -0,0 +1,286 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from json.decoder import JSONDecodeError + +from ..core.api_error import ApiError +from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ..core.http_response import AsyncHttpResponse, HttpResponse +from ..core.jsonable_encoder import jsonable_encoder +from ..core.pagination import AsyncPager, BaseHttpResponse, SyncPager +from ..core.pydantic_utilities import parse_obj_as +from ..core.request_options import RequestOptions +from ..types.app import App +from ..types.get_app_response import GetAppResponse +from ..types.list_apps_response import ListAppsResponse +from .types.apps_list_request_sort_direction import AppsListRequestSortDirection +from .types.apps_list_request_sort_key import AppsListRequestSortKey + + +class RawAppsClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def list( + self, + *, + after: typing.Optional[str] = None, + before: typing.Optional[str] = None, + limit: typing.Optional[int] = None, + q: typing.Optional[str] = None, + sort_key: typing.Optional[AppsListRequestSortKey] = None, + sort_direction: typing.Optional[AppsListRequestSortDirection] = None, + category_ids: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> SyncPager[App]: + """ + Parameters + ---------- + after : typing.Optional[str] + The cursor to start from for pagination + + before : typing.Optional[str] + The cursor to end before for pagination + + limit : typing.Optional[int] + The maximum number of results to return + + q : typing.Optional[str] + A search query to filter the apps + + sort_key : typing.Optional[AppsListRequestSortKey] + The key to sort the apps by + + sort_direction : typing.Optional[AppsListRequestSortDirection] + The direction to sort the apps + + category_ids : typing.Optional[typing.Union[str, typing.Sequence[str]]] + Only return apps in these categories + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + SyncPager[App] + apps listed + """ + _response = self._client_wrapper.httpx_client.request( + "v1/connect/apps", + method="GET", + params={ + "after": after, + "before": before, + "limit": limit, + "q": q, + "sort_key": sort_key, + "sort_direction": sort_direction, + "category_ids": category_ids, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _parsed_response = typing.cast( + ListAppsResponse, + parse_obj_as( + type_=ListAppsResponse, # type: ignore + object_=_response.json(), + ), + ) + _items = _parsed_response.data + _has_next = False + _get_next = None + if _parsed_response.page_info is not None: + _parsed_next = _parsed_response.page_info.end_cursor + _has_next = _parsed_next is not None and _parsed_next != "" + _get_next = lambda: self.list( + after=_parsed_next, + before=before, + limit=limit, + q=q, + sort_key=sort_key, + sort_direction=sort_direction, + category_ids=category_ids, + request_options=request_options, + ) + return SyncPager( + has_next=_has_next, items=_items, get_next=_get_next, response=BaseHttpResponse(response=_response) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def retrieve( + self, app_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[GetAppResponse]: + """ + Parameters + ---------- + app_id : str + The name slug or ID of the app (e.g., 'slack', 'github') + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[GetAppResponse] + app retrieved + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/connect/apps/{jsonable_encoder(app_id)}", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + GetAppResponse, + parse_obj_as( + type_=GetAppResponse, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + +class AsyncRawAppsClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def list( + self, + *, + after: typing.Optional[str] = None, + before: typing.Optional[str] = None, + limit: typing.Optional[int] = None, + q: typing.Optional[str] = None, + sort_key: typing.Optional[AppsListRequestSortKey] = None, + sort_direction: typing.Optional[AppsListRequestSortDirection] = None, + category_ids: typing.Optional[typing.Union[str, typing.Sequence[str]]] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncPager[App]: + """ + Parameters + ---------- + after : typing.Optional[str] + The cursor to start from for pagination + + before : typing.Optional[str] + The cursor to end before for pagination + + limit : typing.Optional[int] + The maximum number of results to return + + q : typing.Optional[str] + A search query to filter the apps + + sort_key : typing.Optional[AppsListRequestSortKey] + The key to sort the apps by + + sort_direction : typing.Optional[AppsListRequestSortDirection] + The direction to sort the apps + + category_ids : typing.Optional[typing.Union[str, typing.Sequence[str]]] + Only return apps in these categories + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncPager[App] + apps listed + """ + _response = await self._client_wrapper.httpx_client.request( + "v1/connect/apps", + method="GET", + params={ + "after": after, + "before": before, + "limit": limit, + "q": q, + "sort_key": sort_key, + "sort_direction": sort_direction, + "category_ids": category_ids, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _parsed_response = typing.cast( + ListAppsResponse, + parse_obj_as( + type_=ListAppsResponse, # type: ignore + object_=_response.json(), + ), + ) + _items = _parsed_response.data + _has_next = False + _get_next = None + if _parsed_response.page_info is not None: + _parsed_next = _parsed_response.page_info.end_cursor + _has_next = _parsed_next is not None and _parsed_next != "" + + async def _get_next(): + return await self.list( + after=_parsed_next, + before=before, + limit=limit, + q=q, + sort_key=sort_key, + sort_direction=sort_direction, + category_ids=category_ids, + request_options=request_options, + ) + + return AsyncPager( + has_next=_has_next, items=_items, get_next=_get_next, response=BaseHttpResponse(response=_response) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def retrieve( + self, app_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[GetAppResponse]: + """ + Parameters + ---------- + app_id : str + The name slug or ID of the app (e.g., 'slack', 'github') + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[GetAppResponse] + app retrieved + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/connect/apps/{jsonable_encoder(app_id)}", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + GetAppResponse, + parse_obj_as( + type_=GetAppResponse, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/pipedream/apps/types/__init__.py b/src/pipedream/apps/types/__init__.py new file mode 100644 index 0000000..87ed3b2 --- /dev/null +++ b/src/pipedream/apps/types/__init__.py @@ -0,0 +1,8 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +from .apps_list_request_sort_direction import AppsListRequestSortDirection +from .apps_list_request_sort_key import AppsListRequestSortKey + +__all__ = ["AppsListRequestSortDirection", "AppsListRequestSortKey"] diff --git a/src/pipedream/apps/types/apps_list_request_sort_direction.py b/src/pipedream/apps/types/apps_list_request_sort_direction.py new file mode 100644 index 0000000..d841cc9 --- /dev/null +++ b/src/pipedream/apps/types/apps_list_request_sort_direction.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +AppsListRequestSortDirection = typing.Union[typing.Literal["asc", "desc"], typing.Any] diff --git a/src/pipedream/apps/types/apps_list_request_sort_key.py b/src/pipedream/apps/types/apps_list_request_sort_key.py new file mode 100644 index 0000000..ab4065d --- /dev/null +++ b/src/pipedream/apps/types/apps_list_request_sort_key.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +AppsListRequestSortKey = typing.Union[typing.Literal["name", "name_slug", "featured_weight"], typing.Any] diff --git a/src/pipedream/client.py b/src/pipedream/client.py new file mode 100644 index 0000000..8ba6924 --- /dev/null +++ b/src/pipedream/client.py @@ -0,0 +1,219 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import httpx +from .accounts.client import AccountsClient, AsyncAccountsClient +from .actions.client import ActionsClient, AsyncActionsClient +from .app_categories.client import AppCategoriesClient, AsyncAppCategoriesClient +from .apps.client import AppsClient, AsyncAppsClient +from .components.client import AsyncComponentsClient, ComponentsClient +from .core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from .core.oauth_token_provider import OAuthTokenProvider +from .deployed_triggers.client import AsyncDeployedTriggersClient, DeployedTriggersClient +from .environment import PipedreamEnvironment +from .oauth_tokens.client import AsyncOauthTokensClient, OauthTokensClient +from .projects.client import AsyncProjectsClient, ProjectsClient +from .proxy.client import AsyncProxyClient, ProxyClient +from .tokens.client import AsyncTokensClient, TokensClient +from .triggers.client import AsyncTriggersClient, TriggersClient +from .users.client import AsyncUsersClient, UsersClient + + +class Client: + """ + Use this class to access the different functions within the SDK. You can instantiate any number of clients with different configuration that will propagate to these functions. + + Parameters + ---------- + base_url : typing.Optional[str] + The base url to use for requests from the client. + + environment : PipedreamEnvironment + The environment to use for requests from the client. from .environment import PipedreamEnvironment + + + + Defaults to PipedreamEnvironment.PROD + + + + x_pd_environment : typing.Optional[str] + client_id : str + client_secret : str + _token_getter_override : typing.Optional[typing.Callable[[], str]] + timeout : typing.Optional[float] + The timeout to be used, in seconds, for requests. By default the timeout is 60 seconds, unless a custom httpx client is used, in which case this default is not enforced. + + follow_redirects : typing.Optional[bool] + Whether the default httpx client follows redirects or not, this is irrelevant if a custom httpx client is passed in. + + httpx_client : typing.Optional[httpx.Client] + The httpx client to use for making requests, a preconfigured client is used by default, however this is useful should you want to pass in any custom httpx configuration. + + Examples + -------- + from pipedream import Pipedream + + client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + """ + + def __init__( + self, + *, + base_url: typing.Optional[str] = None, + environment: PipedreamEnvironment = PipedreamEnvironment.PROD, + x_pd_environment: typing.Optional[str] = None, + client_id: str, + client_secret: str, + _token_getter_override: typing.Optional[typing.Callable[[], str]] = None, + timeout: typing.Optional[float] = None, + follow_redirects: typing.Optional[bool] = True, + httpx_client: typing.Optional[httpx.Client] = None, + ): + _defaulted_timeout = ( + timeout if timeout is not None else 60 if httpx_client is None else httpx_client.timeout.read + ) + oauth_token_provider = OAuthTokenProvider( + client_id=client_id, + client_secret=client_secret, + client_wrapper=SyncClientWrapper( + base_url=_get_base_url(base_url=base_url, environment=environment), + x_pd_environment=x_pd_environment, + httpx_client=httpx.Client(timeout=_defaulted_timeout, follow_redirects=follow_redirects) + if follow_redirects is not None + else httpx.Client(timeout=_defaulted_timeout), + timeout=_defaulted_timeout, + ), + ) + self._client_wrapper = SyncClientWrapper( + base_url=_get_base_url(base_url=base_url, environment=environment), + x_pd_environment=x_pd_environment, + token=_token_getter_override if _token_getter_override is not None else oauth_token_provider.get_token, + httpx_client=httpx_client + if httpx_client is not None + else httpx.Client(timeout=_defaulted_timeout, follow_redirects=follow_redirects) + if follow_redirects is not None + else httpx.Client(timeout=_defaulted_timeout), + timeout=_defaulted_timeout, + ) + self.app_categories = AppCategoriesClient(client_wrapper=self._client_wrapper) + self.apps = AppsClient(client_wrapper=self._client_wrapper) + self.accounts = AccountsClient(client_wrapper=self._client_wrapper) + self.users = UsersClient(client_wrapper=self._client_wrapper) + self.components = ComponentsClient(client_wrapper=self._client_wrapper) + self.actions = ActionsClient(client_wrapper=self._client_wrapper) + self.triggers = TriggersClient(client_wrapper=self._client_wrapper) + self.deployed_triggers = DeployedTriggersClient(client_wrapper=self._client_wrapper) + self.projects = ProjectsClient(client_wrapper=self._client_wrapper) + self.proxy = ProxyClient(client_wrapper=self._client_wrapper) + self.tokens = TokensClient(client_wrapper=self._client_wrapper) + self.oauth_tokens = OauthTokensClient(client_wrapper=self._client_wrapper) + + +class AsyncClient: + """ + Use this class to access the different functions within the SDK. You can instantiate any number of clients with different configuration that will propagate to these functions. + + Parameters + ---------- + base_url : typing.Optional[str] + The base url to use for requests from the client. + + environment : PipedreamEnvironment + The environment to use for requests from the client. from .environment import PipedreamEnvironment + + + + Defaults to PipedreamEnvironment.PROD + + + + x_pd_environment : typing.Optional[str] + client_id : str + client_secret : str + _token_getter_override : typing.Optional[typing.Callable[[], str]] + timeout : typing.Optional[float] + The timeout to be used, in seconds, for requests. By default the timeout is 60 seconds, unless a custom httpx client is used, in which case this default is not enforced. + + follow_redirects : typing.Optional[bool] + Whether the default httpx client follows redirects or not, this is irrelevant if a custom httpx client is passed in. + + httpx_client : typing.Optional[httpx.AsyncClient] + The httpx client to use for making requests, a preconfigured client is used by default, however this is useful should you want to pass in any custom httpx configuration. + + Examples + -------- + from pipedream import AsyncPipedream + + client = AsyncPipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + """ + + def __init__( + self, + *, + base_url: typing.Optional[str] = None, + environment: PipedreamEnvironment = PipedreamEnvironment.PROD, + x_pd_environment: typing.Optional[str] = None, + client_id: str, + client_secret: str, + _token_getter_override: typing.Optional[typing.Callable[[], str]] = None, + timeout: typing.Optional[float] = None, + follow_redirects: typing.Optional[bool] = True, + httpx_client: typing.Optional[httpx.AsyncClient] = None, + ): + _defaulted_timeout = ( + timeout if timeout is not None else 60 if httpx_client is None else httpx_client.timeout.read + ) + oauth_token_provider = OAuthTokenProvider( + client_id=client_id, + client_secret=client_secret, + client_wrapper=SyncClientWrapper( + base_url=_get_base_url(base_url=base_url, environment=environment), + x_pd_environment=x_pd_environment, + httpx_client=httpx.Client(timeout=_defaulted_timeout, follow_redirects=follow_redirects) + if follow_redirects is not None + else httpx.Client(timeout=_defaulted_timeout), + timeout=_defaulted_timeout, + ), + ) + self._client_wrapper = AsyncClientWrapper( + base_url=_get_base_url(base_url=base_url, environment=environment), + x_pd_environment=x_pd_environment, + token=_token_getter_override if _token_getter_override is not None else oauth_token_provider.get_token, + httpx_client=httpx_client + if httpx_client is not None + else httpx.AsyncClient(timeout=_defaulted_timeout, follow_redirects=follow_redirects) + if follow_redirects is not None + else httpx.AsyncClient(timeout=_defaulted_timeout), + timeout=_defaulted_timeout, + ) + self.app_categories = AsyncAppCategoriesClient(client_wrapper=self._client_wrapper) + self.apps = AsyncAppsClient(client_wrapper=self._client_wrapper) + self.accounts = AsyncAccountsClient(client_wrapper=self._client_wrapper) + self.users = AsyncUsersClient(client_wrapper=self._client_wrapper) + self.components = AsyncComponentsClient(client_wrapper=self._client_wrapper) + self.actions = AsyncActionsClient(client_wrapper=self._client_wrapper) + self.triggers = AsyncTriggersClient(client_wrapper=self._client_wrapper) + self.deployed_triggers = AsyncDeployedTriggersClient(client_wrapper=self._client_wrapper) + self.projects = AsyncProjectsClient(client_wrapper=self._client_wrapper) + self.proxy = AsyncProxyClient(client_wrapper=self._client_wrapper) + self.tokens = AsyncTokensClient(client_wrapper=self._client_wrapper) + self.oauth_tokens = AsyncOauthTokensClient(client_wrapper=self._client_wrapper) + + +def _get_base_url(*, base_url: typing.Optional[str] = None, environment: PipedreamEnvironment) -> str: + if base_url is not None: + return base_url + elif environment is not None: + return environment.value + else: + raise Exception("Please pass in either base_url or environment to construct the client") diff --git a/src/pipedream/components/__init__.py b/src/pipedream/components/__init__.py new file mode 100644 index 0000000..5cde020 --- /dev/null +++ b/src/pipedream/components/__init__.py @@ -0,0 +1,4 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + diff --git a/src/pipedream/components/client.py b/src/pipedream/components/client.py new file mode 100644 index 0000000..56ab9c7 --- /dev/null +++ b/src/pipedream/components/client.py @@ -0,0 +1,619 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ..core.pagination import AsyncPager, SyncPager +from ..core.request_options import RequestOptions +from ..types.component import Component +from ..types.configure_prop_response import ConfigurePropResponse +from ..types.reload_props_response import ReloadPropsResponse +from .raw_client import AsyncRawComponentsClient, RawComponentsClient + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class ComponentsClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._raw_client = RawComponentsClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawComponentsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawComponentsClient + """ + return self._raw_client + + def list( + self, + project_id: str, + *, + after: typing.Optional[str] = None, + before: typing.Optional[str] = None, + limit: typing.Optional[int] = None, + q: typing.Optional[str] = None, + app: typing.Optional[str] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> SyncPager[Component]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + after : typing.Optional[str] + The cursor to start from for pagination + + before : typing.Optional[str] + The cursor to end before for pagination + + limit : typing.Optional[int] + The maximum number of results to return + + q : typing.Optional[str] + A search query to filter the components + + app : typing.Optional[str] + The ID or name slug of the app to filter the components + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + SyncPager[Component] + components listed + + Examples + -------- + from pipedream import Pipedream + + client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + response = client.components.list( + project_id="project_id", + ) + for item in response: + yield item + # alternatively, you can paginate page-by-page + for page in response.iter_pages(): + yield page + """ + return self._raw_client.list( + project_id, after=after, before=before, limit=limit, q=q, app=app, request_options=request_options + ) + + def retrieve( + self, project_id: str, component_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> Component: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + component_id : str + The key that uniquely identifies the component (e.g., 'slack-send-message') + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Component + component retrieved + + Examples + -------- + from pipedream import Pipedream + + client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + client.components.retrieve( + project_id="project_id", + component_id="component_id", + ) + """ + _response = self._raw_client.retrieve(project_id, component_id, request_options=request_options) + return _response.data + + def configure_prop( + self, + project_id: str, + *, + id: str, + external_user_id: str, + prop_name: str, + async_handle: typing.Optional[str] = None, + blocking: typing.Optional[bool] = OMIT, + configured_props: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, + dynamic_props_id: typing.Optional[str] = OMIT, + configure_prop_opts_async_handle: typing.Optional[str] = OMIT, + page: typing.Optional[float] = OMIT, + prev_context: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, + query: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> ConfigurePropResponse: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + id : str + The component ID + + external_user_id : str + The external user ID + + prop_name : str + The name of the prop to configure + + async_handle : typing.Optional[str] + + blocking : typing.Optional[bool] + Whether this operation should block until completion + + configured_props : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] + The configured properties for the component + + dynamic_props_id : typing.Optional[str] + The ID for dynamic props + + configure_prop_opts_async_handle : typing.Optional[str] + Handle for async operations + + page : typing.Optional[float] + Page number for paginated results + + prev_context : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] + Previous context for pagination + + query : typing.Optional[str] + Search query for filtering options + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ConfigurePropResponse + component configuration started + + Examples + -------- + from pipedream import Pipedream + + client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + client.components.configure_prop( + project_id="project_id", + id="id", + external_user_id="external_user_id", + prop_name="prop_name", + ) + """ + _response = self._raw_client.configure_prop( + project_id, + id=id, + external_user_id=external_user_id, + prop_name=prop_name, + async_handle=async_handle, + blocking=blocking, + configured_props=configured_props, + dynamic_props_id=dynamic_props_id, + configure_prop_opts_async_handle=configure_prop_opts_async_handle, + page=page, + prev_context=prev_context, + query=query, + request_options=request_options, + ) + return _response.data + + def reload_props( + self, + project_id: str, + *, + id: str, + external_user_id: str, + async_handle: typing.Optional[str] = None, + blocking: typing.Optional[bool] = OMIT, + configured_props: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, + dynamic_props_id: typing.Optional[str] = OMIT, + reload_props_opts_async_handle: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> ReloadPropsResponse: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + id : str + The component ID + + external_user_id : str + The external user ID + + async_handle : typing.Optional[str] + + blocking : typing.Optional[bool] + Whether this operation should block until completion + + configured_props : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] + The configured properties for the component + + dynamic_props_id : typing.Optional[str] + The ID for dynamic props + + reload_props_opts_async_handle : typing.Optional[str] + Handle for async operations + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ReloadPropsResponse + component props reloaded + + Examples + -------- + from pipedream import Pipedream + + client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + client.components.reload_props( + project_id="project_id", + id="id", + external_user_id="external_user_id", + ) + """ + _response = self._raw_client.reload_props( + project_id, + id=id, + external_user_id=external_user_id, + async_handle=async_handle, + blocking=blocking, + configured_props=configured_props, + dynamic_props_id=dynamic_props_id, + reload_props_opts_async_handle=reload_props_opts_async_handle, + request_options=request_options, + ) + return _response.data + + +class AsyncComponentsClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._raw_client = AsyncRawComponentsClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawComponentsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawComponentsClient + """ + return self._raw_client + + async def list( + self, + project_id: str, + *, + after: typing.Optional[str] = None, + before: typing.Optional[str] = None, + limit: typing.Optional[int] = None, + q: typing.Optional[str] = None, + app: typing.Optional[str] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncPager[Component]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + after : typing.Optional[str] + The cursor to start from for pagination + + before : typing.Optional[str] + The cursor to end before for pagination + + limit : typing.Optional[int] + The maximum number of results to return + + q : typing.Optional[str] + A search query to filter the components + + app : typing.Optional[str] + The ID or name slug of the app to filter the components + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncPager[Component] + components listed + + Examples + -------- + import asyncio + + from pipedream import AsyncPipedream + + client = AsyncPipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + + + async def main() -> None: + response = await client.components.list( + project_id="project_id", + ) + async for item in response: + yield item + + # alternatively, you can paginate page-by-page + async for page in response.iter_pages(): + yield page + + + asyncio.run(main()) + """ + return await self._raw_client.list( + project_id, after=after, before=before, limit=limit, q=q, app=app, request_options=request_options + ) + + async def retrieve( + self, project_id: str, component_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> Component: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + component_id : str + The key that uniquely identifies the component (e.g., 'slack-send-message') + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Component + component retrieved + + Examples + -------- + import asyncio + + from pipedream import AsyncPipedream + + client = AsyncPipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + + + async def main() -> None: + await client.components.retrieve( + project_id="project_id", + component_id="component_id", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.retrieve(project_id, component_id, request_options=request_options) + return _response.data + + async def configure_prop( + self, + project_id: str, + *, + id: str, + external_user_id: str, + prop_name: str, + async_handle: typing.Optional[str] = None, + blocking: typing.Optional[bool] = OMIT, + configured_props: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, + dynamic_props_id: typing.Optional[str] = OMIT, + configure_prop_opts_async_handle: typing.Optional[str] = OMIT, + page: typing.Optional[float] = OMIT, + prev_context: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, + query: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> ConfigurePropResponse: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + id : str + The component ID + + external_user_id : str + The external user ID + + prop_name : str + The name of the prop to configure + + async_handle : typing.Optional[str] + + blocking : typing.Optional[bool] + Whether this operation should block until completion + + configured_props : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] + The configured properties for the component + + dynamic_props_id : typing.Optional[str] + The ID for dynamic props + + configure_prop_opts_async_handle : typing.Optional[str] + Handle for async operations + + page : typing.Optional[float] + Page number for paginated results + + prev_context : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] + Previous context for pagination + + query : typing.Optional[str] + Search query for filtering options + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ConfigurePropResponse + component configuration started + + Examples + -------- + import asyncio + + from pipedream import AsyncPipedream + + client = AsyncPipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + + + async def main() -> None: + await client.components.configure_prop( + project_id="project_id", + id="id", + external_user_id="external_user_id", + prop_name="prop_name", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.configure_prop( + project_id, + id=id, + external_user_id=external_user_id, + prop_name=prop_name, + async_handle=async_handle, + blocking=blocking, + configured_props=configured_props, + dynamic_props_id=dynamic_props_id, + configure_prop_opts_async_handle=configure_prop_opts_async_handle, + page=page, + prev_context=prev_context, + query=query, + request_options=request_options, + ) + return _response.data + + async def reload_props( + self, + project_id: str, + *, + id: str, + external_user_id: str, + async_handle: typing.Optional[str] = None, + blocking: typing.Optional[bool] = OMIT, + configured_props: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, + dynamic_props_id: typing.Optional[str] = OMIT, + reload_props_opts_async_handle: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> ReloadPropsResponse: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + id : str + The component ID + + external_user_id : str + The external user ID + + async_handle : typing.Optional[str] + + blocking : typing.Optional[bool] + Whether this operation should block until completion + + configured_props : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] + The configured properties for the component + + dynamic_props_id : typing.Optional[str] + The ID for dynamic props + + reload_props_opts_async_handle : typing.Optional[str] + Handle for async operations + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ReloadPropsResponse + component props reloaded + + Examples + -------- + import asyncio + + from pipedream import AsyncPipedream + + client = AsyncPipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + + + async def main() -> None: + await client.components.reload_props( + project_id="project_id", + id="id", + external_user_id="external_user_id", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.reload_props( + project_id, + id=id, + external_user_id=external_user_id, + async_handle=async_handle, + blocking=blocking, + configured_props=configured_props, + dynamic_props_id=dynamic_props_id, + reload_props_opts_async_handle=reload_props_opts_async_handle, + request_options=request_options, + ) + return _response.data diff --git a/src/pipedream/components/raw_client.py b/src/pipedream/components/raw_client.py new file mode 100644 index 0000000..0179903 --- /dev/null +++ b/src/pipedream/components/raw_client.py @@ -0,0 +1,643 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from json.decoder import JSONDecodeError + +from ..core.api_error import ApiError +from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ..core.http_response import AsyncHttpResponse, HttpResponse +from ..core.jsonable_encoder import jsonable_encoder +from ..core.pagination import AsyncPager, BaseHttpResponse, SyncPager +from ..core.pydantic_utilities import parse_obj_as +from ..core.request_options import RequestOptions +from ..types.component import Component +from ..types.configure_prop_response import ConfigurePropResponse +from ..types.get_component_response import GetComponentResponse +from ..types.get_components_response import GetComponentsResponse +from ..types.reload_props_response import ReloadPropsResponse + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class RawComponentsClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def list( + self, + project_id: str, + *, + after: typing.Optional[str] = None, + before: typing.Optional[str] = None, + limit: typing.Optional[int] = None, + q: typing.Optional[str] = None, + app: typing.Optional[str] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> SyncPager[Component]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + after : typing.Optional[str] + The cursor to start from for pagination + + before : typing.Optional[str] + The cursor to end before for pagination + + limit : typing.Optional[int] + The maximum number of results to return + + q : typing.Optional[str] + A search query to filter the components + + app : typing.Optional[str] + The ID or name slug of the app to filter the components + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + SyncPager[Component] + components listed + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/components", + method="GET", + params={ + "after": after, + "before": before, + "limit": limit, + "q": q, + "app": app, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _parsed_response = typing.cast( + GetComponentsResponse, + parse_obj_as( + type_=GetComponentsResponse, # type: ignore + object_=_response.json(), + ), + ) + _items = _parsed_response.data + _has_next = False + _get_next = None + if _parsed_response.page_info is not None: + _parsed_next = _parsed_response.page_info.end_cursor + _has_next = _parsed_next is not None and _parsed_next != "" + _get_next = lambda: self.list( + project_id, + after=_parsed_next, + before=before, + limit=limit, + q=q, + app=app, + request_options=request_options, + ) + return SyncPager( + has_next=_has_next, items=_items, get_next=_get_next, response=BaseHttpResponse(response=_response) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def retrieve( + self, project_id: str, component_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[Component]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + component_id : str + The key that uniquely identifies the component (e.g., 'slack-send-message') + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[Component] + component retrieved + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/components/{jsonable_encoder(component_id)}", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _parsed_response = typing.cast( + GetComponentResponse, + parse_obj_as( + type_=GetComponentResponse, # type: ignore + object_=_response.json(), + ), + ) + _data = _parsed_response.data + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def configure_prop( + self, + project_id: str, + *, + id: str, + external_user_id: str, + prop_name: str, + async_handle: typing.Optional[str] = None, + blocking: typing.Optional[bool] = OMIT, + configured_props: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, + dynamic_props_id: typing.Optional[str] = OMIT, + configure_prop_opts_async_handle: typing.Optional[str] = OMIT, + page: typing.Optional[float] = OMIT, + prev_context: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, + query: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[ConfigurePropResponse]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + id : str + The component ID + + external_user_id : str + The external user ID + + prop_name : str + The name of the prop to configure + + async_handle : typing.Optional[str] + + blocking : typing.Optional[bool] + Whether this operation should block until completion + + configured_props : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] + The configured properties for the component + + dynamic_props_id : typing.Optional[str] + The ID for dynamic props + + configure_prop_opts_async_handle : typing.Optional[str] + Handle for async operations + + page : typing.Optional[float] + Page number for paginated results + + prev_context : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] + Previous context for pagination + + query : typing.Optional[str] + Search query for filtering options + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[ConfigurePropResponse] + component configuration started + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/components/configure", + method="POST", + json={ + "id": id, + "external_user_id": external_user_id, + "prop_name": prop_name, + "blocking": blocking, + "configured_props": configured_props, + "dynamic_props_id": dynamic_props_id, + "async_handle": async_handle, + "page": page, + "prev_context": prev_context, + "query": query, + }, + headers={ + "content-type": "application/json", + "x-async-handle": str(async_handle) if async_handle is not None else None, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ConfigurePropResponse, + parse_obj_as( + type_=ConfigurePropResponse, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def reload_props( + self, + project_id: str, + *, + id: str, + external_user_id: str, + async_handle: typing.Optional[str] = None, + blocking: typing.Optional[bool] = OMIT, + configured_props: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, + dynamic_props_id: typing.Optional[str] = OMIT, + reload_props_opts_async_handle: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[ReloadPropsResponse]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + id : str + The component ID + + external_user_id : str + The external user ID + + async_handle : typing.Optional[str] + + blocking : typing.Optional[bool] + Whether this operation should block until completion + + configured_props : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] + The configured properties for the component + + dynamic_props_id : typing.Optional[str] + The ID for dynamic props + + reload_props_opts_async_handle : typing.Optional[str] + Handle for async operations + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[ReloadPropsResponse] + component props reloaded + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/components/props", + method="POST", + json={ + "id": id, + "external_user_id": external_user_id, + "blocking": blocking, + "configured_props": configured_props, + "dynamic_props_id": dynamic_props_id, + "async_handle": async_handle, + }, + headers={ + "content-type": "application/json", + "x-async-handle": str(async_handle) if async_handle is not None else None, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ReloadPropsResponse, + parse_obj_as( + type_=ReloadPropsResponse, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + +class AsyncRawComponentsClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def list( + self, + project_id: str, + *, + after: typing.Optional[str] = None, + before: typing.Optional[str] = None, + limit: typing.Optional[int] = None, + q: typing.Optional[str] = None, + app: typing.Optional[str] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncPager[Component]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + after : typing.Optional[str] + The cursor to start from for pagination + + before : typing.Optional[str] + The cursor to end before for pagination + + limit : typing.Optional[int] + The maximum number of results to return + + q : typing.Optional[str] + A search query to filter the components + + app : typing.Optional[str] + The ID or name slug of the app to filter the components + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncPager[Component] + components listed + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/components", + method="GET", + params={ + "after": after, + "before": before, + "limit": limit, + "q": q, + "app": app, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _parsed_response = typing.cast( + GetComponentsResponse, + parse_obj_as( + type_=GetComponentsResponse, # type: ignore + object_=_response.json(), + ), + ) + _items = _parsed_response.data + _has_next = False + _get_next = None + if _parsed_response.page_info is not None: + _parsed_next = _parsed_response.page_info.end_cursor + _has_next = _parsed_next is not None and _parsed_next != "" + + async def _get_next(): + return await self.list( + project_id, + after=_parsed_next, + before=before, + limit=limit, + q=q, + app=app, + request_options=request_options, + ) + + return AsyncPager( + has_next=_has_next, items=_items, get_next=_get_next, response=BaseHttpResponse(response=_response) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def retrieve( + self, project_id: str, component_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[Component]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + component_id : str + The key that uniquely identifies the component (e.g., 'slack-send-message') + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[Component] + component retrieved + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/components/{jsonable_encoder(component_id)}", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _parsed_response = typing.cast( + GetComponentResponse, + parse_obj_as( + type_=GetComponentResponse, # type: ignore + object_=_response.json(), + ), + ) + _data = _parsed_response.data + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def configure_prop( + self, + project_id: str, + *, + id: str, + external_user_id: str, + prop_name: str, + async_handle: typing.Optional[str] = None, + blocking: typing.Optional[bool] = OMIT, + configured_props: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, + dynamic_props_id: typing.Optional[str] = OMIT, + configure_prop_opts_async_handle: typing.Optional[str] = OMIT, + page: typing.Optional[float] = OMIT, + prev_context: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, + query: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[ConfigurePropResponse]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + id : str + The component ID + + external_user_id : str + The external user ID + + prop_name : str + The name of the prop to configure + + async_handle : typing.Optional[str] + + blocking : typing.Optional[bool] + Whether this operation should block until completion + + configured_props : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] + The configured properties for the component + + dynamic_props_id : typing.Optional[str] + The ID for dynamic props + + configure_prop_opts_async_handle : typing.Optional[str] + Handle for async operations + + page : typing.Optional[float] + Page number for paginated results + + prev_context : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] + Previous context for pagination + + query : typing.Optional[str] + Search query for filtering options + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[ConfigurePropResponse] + component configuration started + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/components/configure", + method="POST", + json={ + "id": id, + "external_user_id": external_user_id, + "prop_name": prop_name, + "blocking": blocking, + "configured_props": configured_props, + "dynamic_props_id": dynamic_props_id, + "async_handle": async_handle, + "page": page, + "prev_context": prev_context, + "query": query, + }, + headers={ + "content-type": "application/json", + "x-async-handle": str(async_handle) if async_handle is not None else None, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ConfigurePropResponse, + parse_obj_as( + type_=ConfigurePropResponse, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def reload_props( + self, + project_id: str, + *, + id: str, + external_user_id: str, + async_handle: typing.Optional[str] = None, + blocking: typing.Optional[bool] = OMIT, + configured_props: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, + dynamic_props_id: typing.Optional[str] = OMIT, + reload_props_opts_async_handle: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[ReloadPropsResponse]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + id : str + The component ID + + external_user_id : str + The external user ID + + async_handle : typing.Optional[str] + + blocking : typing.Optional[bool] + Whether this operation should block until completion + + configured_props : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] + The configured properties for the component + + dynamic_props_id : typing.Optional[str] + The ID for dynamic props + + reload_props_opts_async_handle : typing.Optional[str] + Handle for async operations + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[ReloadPropsResponse] + component props reloaded + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/components/props", + method="POST", + json={ + "id": id, + "external_user_id": external_user_id, + "blocking": blocking, + "configured_props": configured_props, + "dynamic_props_id": dynamic_props_id, + "async_handle": async_handle, + }, + headers={ + "content-type": "application/json", + "x-async-handle": str(async_handle) if async_handle is not None else None, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ReloadPropsResponse, + parse_obj_as( + type_=ReloadPropsResponse, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/pipedream/core/__init__.py b/src/pipedream/core/__init__.py new file mode 100644 index 0000000..d1461de --- /dev/null +++ b/src/pipedream/core/__init__.py @@ -0,0 +1,55 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +from .api_error import ApiError +from .client_wrapper import AsyncClientWrapper, BaseClientWrapper, SyncClientWrapper +from .datetime_utils import serialize_datetime +from .file import File, convert_file_dict_to_httpx_tuples, with_content_type +from .http_client import AsyncHttpClient, HttpClient +from .http_response import AsyncHttpResponse, HttpResponse +from .jsonable_encoder import jsonable_encoder +from .pagination import AsyncPager, SyncPager +from .pydantic_utilities import ( + IS_PYDANTIC_V2, + UniversalBaseModel, + UniversalRootModel, + parse_obj_as, + universal_field_validator, + universal_root_validator, + update_forward_refs, +) +from .query_encoder import encode_query +from .remove_none_from_dict import remove_none_from_dict +from .request_options import RequestOptions +from .serialization import FieldMetadata, convert_and_respect_annotation_metadata + +__all__ = [ + "ApiError", + "AsyncClientWrapper", + "AsyncHttpClient", + "AsyncHttpResponse", + "AsyncPager", + "BaseClientWrapper", + "FieldMetadata", + "File", + "HttpClient", + "HttpResponse", + "IS_PYDANTIC_V2", + "RequestOptions", + "SyncClientWrapper", + "SyncPager", + "UniversalBaseModel", + "UniversalRootModel", + "convert_and_respect_annotation_metadata", + "convert_file_dict_to_httpx_tuples", + "encode_query", + "jsonable_encoder", + "parse_obj_as", + "remove_none_from_dict", + "serialize_datetime", + "universal_field_validator", + "universal_root_validator", + "update_forward_refs", + "with_content_type", +] diff --git a/src/pipedream/core/api_error.py b/src/pipedream/core/api_error.py new file mode 100644 index 0000000..6f850a6 --- /dev/null +++ b/src/pipedream/core/api_error.py @@ -0,0 +1,23 @@ +# This file was auto-generated by Fern from our API Definition. + +from typing import Any, Dict, Optional + + +class ApiError(Exception): + headers: Optional[Dict[str, str]] + status_code: Optional[int] + body: Any + + def __init__( + self, + *, + headers: Optional[Dict[str, str]] = None, + status_code: Optional[int] = None, + body: Any = None, + ) -> None: + self.headers = headers + self.status_code = status_code + self.body = body + + def __str__(self) -> str: + return f"headers: {self.headers}, status_code: {self.status_code}, body: {self.body}" diff --git a/src/pipedream/core/client_wrapper.py b/src/pipedream/core/client_wrapper.py new file mode 100644 index 0000000..4a6c2b8 --- /dev/null +++ b/src/pipedream/core/client_wrapper.py @@ -0,0 +1,97 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import httpx +from .http_client import AsyncHttpClient, HttpClient + + +class BaseClientWrapper: + def __init__( + self, + *, + x_pd_environment: typing.Optional[str] = None, + token: typing.Optional[typing.Union[str, typing.Callable[[], str]]] = None, + headers: typing.Optional[typing.Dict[str, str]] = None, + base_url: str, + timeout: typing.Optional[float] = None, + ): + self._x_pd_environment = x_pd_environment + self._token = token + self._headers = headers + self._base_url = base_url + self._timeout = timeout + + def get_headers(self) -> typing.Dict[str, str]: + headers: typing.Dict[str, str] = { + "User-Agent": "pipedream/0.3.1", + "X-Fern-Language": "Python", + "X-Fern-SDK-Name": "pipedream", + "X-Fern-SDK-Version": "0.3.1", + **(self.get_custom_headers() or {}), + } + if self._x_pd_environment is not None: + headers["x-pd-environment"] = self._x_pd_environment + token = self._get_token() + if token is not None: + headers["Authorization"] = f"Bearer {token}" + return headers + + def _get_token(self) -> typing.Optional[str]: + if isinstance(self._token, str) or self._token is None: + return self._token + else: + return self._token() + + def get_custom_headers(self) -> typing.Optional[typing.Dict[str, str]]: + return self._headers + + def get_base_url(self) -> str: + return self._base_url + + def get_timeout(self) -> typing.Optional[float]: + return self._timeout + + +class SyncClientWrapper(BaseClientWrapper): + def __init__( + self, + *, + x_pd_environment: typing.Optional[str] = None, + token: typing.Optional[typing.Union[str, typing.Callable[[], str]]] = None, + headers: typing.Optional[typing.Dict[str, str]] = None, + base_url: str, + timeout: typing.Optional[float] = None, + httpx_client: httpx.Client, + ): + super().__init__( + x_pd_environment=x_pd_environment, token=token, headers=headers, base_url=base_url, timeout=timeout + ) + self.httpx_client = HttpClient( + httpx_client=httpx_client, + base_headers=self.get_headers, + base_timeout=self.get_timeout, + base_url=self.get_base_url, + ) + + +class AsyncClientWrapper(BaseClientWrapper): + def __init__( + self, + *, + x_pd_environment: typing.Optional[str] = None, + token: typing.Optional[typing.Union[str, typing.Callable[[], str]]] = None, + headers: typing.Optional[typing.Dict[str, str]] = None, + base_url: str, + timeout: typing.Optional[float] = None, + httpx_client: httpx.AsyncClient, + ): + super().__init__( + x_pd_environment=x_pd_environment, token=token, headers=headers, base_url=base_url, timeout=timeout + ) + self.httpx_client = AsyncHttpClient( + httpx_client=httpx_client, + base_headers=self.get_headers, + base_timeout=self.get_timeout, + base_url=self.get_base_url, + ) diff --git a/src/pipedream/core/datetime_utils.py b/src/pipedream/core/datetime_utils.py new file mode 100644 index 0000000..7c9864a --- /dev/null +++ b/src/pipedream/core/datetime_utils.py @@ -0,0 +1,28 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt + + +def serialize_datetime(v: dt.datetime) -> str: + """ + Serialize a datetime including timezone info. + + Uses the timezone info provided if present, otherwise uses the current runtime's timezone info. + + UTC datetimes end in "Z" while all other timezones are represented as offset from UTC, e.g. +05:00. + """ + + def _serialize_zoned_datetime(v: dt.datetime) -> str: + if v.tzinfo is not None and v.tzinfo.tzname(None) == dt.timezone.utc.tzname(None): + # UTC is a special case where we use "Z" at the end instead of "+00:00" + return v.isoformat().replace("+00:00", "Z") + else: + # Delegate to the typical +/- offset format + return v.isoformat() + + if v.tzinfo is not None: + return _serialize_zoned_datetime(v) + else: + local_tz = dt.datetime.now().astimezone().tzinfo + localized_dt = v.replace(tzinfo=local_tz) + return _serialize_zoned_datetime(localized_dt) diff --git a/src/pipedream/core/file.py b/src/pipedream/core/file.py new file mode 100644 index 0000000..44b0d27 --- /dev/null +++ b/src/pipedream/core/file.py @@ -0,0 +1,67 @@ +# This file was auto-generated by Fern from our API Definition. + +from typing import IO, Dict, List, Mapping, Optional, Tuple, Union, cast + +# File typing inspired by the flexibility of types within the httpx library +# https://github.com/encode/httpx/blob/master/httpx/_types.py +FileContent = Union[IO[bytes], bytes, str] +File = Union[ + # file (or bytes) + FileContent, + # (filename, file (or bytes)) + Tuple[Optional[str], FileContent], + # (filename, file (or bytes), content_type) + Tuple[Optional[str], FileContent, Optional[str]], + # (filename, file (or bytes), content_type, headers) + Tuple[ + Optional[str], + FileContent, + Optional[str], + Mapping[str, str], + ], +] + + +def convert_file_dict_to_httpx_tuples( + d: Dict[str, Union[File, List[File]]], +) -> List[Tuple[str, File]]: + """ + The format we use is a list of tuples, where the first element is the + name of the file and the second is the file object. Typically HTTPX wants + a dict, but to be able to send lists of files, you have to use the list + approach (which also works for non-lists) + https://github.com/encode/httpx/pull/1032 + """ + + httpx_tuples = [] + for key, file_like in d.items(): + if isinstance(file_like, list): + for file_like_item in file_like: + httpx_tuples.append((key, file_like_item)) + else: + httpx_tuples.append((key, file_like)) + return httpx_tuples + + +def with_content_type(*, file: File, default_content_type: str) -> File: + """ + This function resolves to the file's content type, if provided, and defaults + to the default_content_type value if not. + """ + if isinstance(file, tuple): + if len(file) == 2: + filename, content = cast(Tuple[Optional[str], FileContent], file) # type: ignore + return (filename, content, default_content_type) + elif len(file) == 3: + filename, content, file_content_type = cast(Tuple[Optional[str], FileContent, Optional[str]], file) # type: ignore + out_content_type = file_content_type or default_content_type + return (filename, content, out_content_type) + elif len(file) == 4: + filename, content, file_content_type, headers = cast( # type: ignore + Tuple[Optional[str], FileContent, Optional[str], Mapping[str, str]], file + ) + out_content_type = file_content_type or default_content_type + return (filename, content, out_content_type, headers) + else: + raise ValueError(f"Unexpected tuple length: {len(file)}") + return (None, file, default_content_type) diff --git a/src/pipedream/core/force_multipart.py b/src/pipedream/core/force_multipart.py new file mode 100644 index 0000000..ae24ccf --- /dev/null +++ b/src/pipedream/core/force_multipart.py @@ -0,0 +1,16 @@ +# This file was auto-generated by Fern from our API Definition. + + +class ForceMultipartDict(dict): + """ + A dictionary subclass that always evaluates to True in boolean contexts. + + This is used to force multipart/form-data encoding in HTTP requests even when + the dictionary is empty, which would normally evaluate to False. + """ + + def __bool__(self): + return True + + +FORCE_MULTIPART = ForceMultipartDict() diff --git a/src/pipedream/core/http_client.py b/src/pipedream/core/http_client.py new file mode 100644 index 0000000..e4173f9 --- /dev/null +++ b/src/pipedream/core/http_client.py @@ -0,0 +1,543 @@ +# This file was auto-generated by Fern from our API Definition. + +import asyncio +import email.utils +import re +import time +import typing +import urllib.parse +from contextlib import asynccontextmanager, contextmanager +from random import random + +import httpx +from .file import File, convert_file_dict_to_httpx_tuples +from .force_multipart import FORCE_MULTIPART +from .jsonable_encoder import jsonable_encoder +from .query_encoder import encode_query +from .remove_none_from_dict import remove_none_from_dict +from .request_options import RequestOptions +from httpx._types import RequestFiles + +INITIAL_RETRY_DELAY_SECONDS = 0.5 +MAX_RETRY_DELAY_SECONDS = 10 +MAX_RETRY_DELAY_SECONDS_FROM_HEADER = 30 + + +def _parse_retry_after(response_headers: httpx.Headers) -> typing.Optional[float]: + """ + This function parses the `Retry-After` header in a HTTP response and returns the number of seconds to wait. + + Inspired by the urllib3 retry implementation. + """ + retry_after_ms = response_headers.get("retry-after-ms") + if retry_after_ms is not None: + try: + return int(retry_after_ms) / 1000 if retry_after_ms > 0 else 0 + except Exception: + pass + + retry_after = response_headers.get("retry-after") + if retry_after is None: + return None + + # Attempt to parse the header as an int. + if re.match(r"^\s*[0-9]+\s*$", retry_after): + seconds = float(retry_after) + # Fallback to parsing it as a date. + else: + retry_date_tuple = email.utils.parsedate_tz(retry_after) + if retry_date_tuple is None: + return None + if retry_date_tuple[9] is None: # Python 2 + # Assume UTC if no timezone was specified + # On Python2.7, parsedate_tz returns None for a timezone offset + # instead of 0 if no timezone is given, where mktime_tz treats + # a None timezone offset as local time. + retry_date_tuple = retry_date_tuple[:9] + (0,) + retry_date_tuple[10:] + + retry_date = email.utils.mktime_tz(retry_date_tuple) + seconds = retry_date - time.time() + + if seconds < 0: + seconds = 0 + + return seconds + + +def _retry_timeout(response: httpx.Response, retries: int) -> float: + """ + Determine the amount of time to wait before retrying a request. + This function begins by trying to parse a retry-after header from the response, and then proceeds to use exponential backoff + with a jitter to determine the number of seconds to wait. + """ + + # If the API asks us to wait a certain amount of time (and it's a reasonable amount), just do what it says. + retry_after = _parse_retry_after(response.headers) + if retry_after is not None and retry_after <= MAX_RETRY_DELAY_SECONDS_FROM_HEADER: + return retry_after + + # Apply exponential backoff, capped at MAX_RETRY_DELAY_SECONDS. + retry_delay = min(INITIAL_RETRY_DELAY_SECONDS * pow(2.0, retries), MAX_RETRY_DELAY_SECONDS) + + # Add a randomness / jitter to the retry delay to avoid overwhelming the server with retries. + timeout = retry_delay * (1 - 0.25 * random()) + return timeout if timeout >= 0 else 0 + + +def _should_retry(response: httpx.Response) -> bool: + retryable_400s = [429, 408, 409] + return response.status_code >= 500 or response.status_code in retryable_400s + + +def remove_omit_from_dict( + original: typing.Dict[str, typing.Optional[typing.Any]], + omit: typing.Optional[typing.Any], +) -> typing.Dict[str, typing.Any]: + if omit is None: + return original + new: typing.Dict[str, typing.Any] = {} + for key, value in original.items(): + if value is not omit: + new[key] = value + return new + + +def maybe_filter_request_body( + data: typing.Optional[typing.Any], + request_options: typing.Optional[RequestOptions], + omit: typing.Optional[typing.Any], +) -> typing.Optional[typing.Any]: + if data is None: + return ( + jsonable_encoder(request_options.get("additional_body_parameters", {})) or {} + if request_options is not None + else None + ) + elif not isinstance(data, typing.Mapping): + data_content = jsonable_encoder(data) + else: + data_content = { + **(jsonable_encoder(remove_omit_from_dict(data, omit))), # type: ignore + **( + jsonable_encoder(request_options.get("additional_body_parameters", {})) or {} + if request_options is not None + else {} + ), + } + return data_content + + +# Abstracted out for testing purposes +def get_request_body( + *, + json: typing.Optional[typing.Any], + data: typing.Optional[typing.Any], + request_options: typing.Optional[RequestOptions], + omit: typing.Optional[typing.Any], +) -> typing.Tuple[typing.Optional[typing.Any], typing.Optional[typing.Any]]: + json_body = None + data_body = None + if data is not None: + data_body = maybe_filter_request_body(data, request_options, omit) + else: + # If both data and json are None, we send json data in the event extra properties are specified + json_body = maybe_filter_request_body(json, request_options, omit) + + # If you have an empty JSON body, you should just send None + return (json_body if json_body != {} else None), data_body if data_body != {} else None + + +class HttpClient: + def __init__( + self, + *, + httpx_client: httpx.Client, + base_timeout: typing.Callable[[], typing.Optional[float]], + base_headers: typing.Callable[[], typing.Dict[str, str]], + base_url: typing.Optional[typing.Callable[[], str]] = None, + ): + self.base_url = base_url + self.base_timeout = base_timeout + self.base_headers = base_headers + self.httpx_client = httpx_client + + def get_base_url(self, maybe_base_url: typing.Optional[str]) -> str: + base_url = maybe_base_url + if self.base_url is not None and base_url is None: + base_url = self.base_url() + + if base_url is None: + raise ValueError("A base_url is required to make this request, please provide one and try again.") + return base_url + + def request( + self, + path: typing.Optional[str] = None, + *, + method: str, + base_url: typing.Optional[str] = None, + params: typing.Optional[typing.Dict[str, typing.Any]] = None, + json: typing.Optional[typing.Any] = None, + data: typing.Optional[typing.Any] = None, + content: typing.Optional[typing.Union[bytes, typing.Iterator[bytes], typing.AsyncIterator[bytes]]] = None, + files: typing.Optional[ + typing.Union[ + typing.Dict[str, typing.Optional[typing.Union[File, typing.List[File]]]], + typing.List[typing.Tuple[str, File]], + ] + ] = None, + headers: typing.Optional[typing.Dict[str, typing.Any]] = None, + request_options: typing.Optional[RequestOptions] = None, + retries: int = 2, + omit: typing.Optional[typing.Any] = None, + force_multipart: typing.Optional[bool] = None, + ) -> httpx.Response: + base_url = self.get_base_url(base_url) + timeout = ( + request_options.get("timeout_in_seconds") + if request_options is not None and request_options.get("timeout_in_seconds") is not None + else self.base_timeout() + ) + + json_body, data_body = get_request_body(json=json, data=data, request_options=request_options, omit=omit) + + request_files: typing.Optional[RequestFiles] = ( + convert_file_dict_to_httpx_tuples(remove_omit_from_dict(remove_none_from_dict(files), omit)) + if (files is not None and files is not omit and isinstance(files, dict)) + else None + ) + + if (request_files is None or len(request_files) == 0) and force_multipart: + request_files = FORCE_MULTIPART + + response = self.httpx_client.request( + method=method, + url=urllib.parse.urljoin(f"{base_url}/", path), + headers=jsonable_encoder( + remove_none_from_dict( + { + **self.base_headers(), + **(headers if headers is not None else {}), + **(request_options.get("additional_headers", {}) or {} if request_options is not None else {}), + } + ) + ), + params=encode_query( + jsonable_encoder( + remove_none_from_dict( + remove_omit_from_dict( + { + **(params if params is not None else {}), + **( + request_options.get("additional_query_parameters", {}) or {} + if request_options is not None + else {} + ), + }, + omit, + ) + ) + ) + ), + json=json_body, + data=data_body, + content=content, + files=request_files, + timeout=timeout, + ) + + max_retries: int = request_options.get("max_retries", 0) if request_options is not None else 0 + if _should_retry(response=response): + if max_retries > retries: + time.sleep(_retry_timeout(response=response, retries=retries)) + return self.request( + path=path, + method=method, + base_url=base_url, + params=params, + json=json, + content=content, + files=files, + headers=headers, + request_options=request_options, + retries=retries + 1, + omit=omit, + ) + + return response + + @contextmanager + def stream( + self, + path: typing.Optional[str] = None, + *, + method: str, + base_url: typing.Optional[str] = None, + params: typing.Optional[typing.Dict[str, typing.Any]] = None, + json: typing.Optional[typing.Any] = None, + data: typing.Optional[typing.Any] = None, + content: typing.Optional[typing.Union[bytes, typing.Iterator[bytes], typing.AsyncIterator[bytes]]] = None, + files: typing.Optional[ + typing.Union[ + typing.Dict[str, typing.Optional[typing.Union[File, typing.List[File]]]], + typing.List[typing.Tuple[str, File]], + ] + ] = None, + headers: typing.Optional[typing.Dict[str, typing.Any]] = None, + request_options: typing.Optional[RequestOptions] = None, + retries: int = 2, + omit: typing.Optional[typing.Any] = None, + force_multipart: typing.Optional[bool] = None, + ) -> typing.Iterator[httpx.Response]: + base_url = self.get_base_url(base_url) + timeout = ( + request_options.get("timeout_in_seconds") + if request_options is not None and request_options.get("timeout_in_seconds") is not None + else self.base_timeout() + ) + + request_files: typing.Optional[RequestFiles] = ( + convert_file_dict_to_httpx_tuples(remove_omit_from_dict(remove_none_from_dict(files), omit)) + if (files is not None and files is not omit and isinstance(files, dict)) + else None + ) + + if (request_files is None or len(request_files) == 0) and force_multipart: + request_files = FORCE_MULTIPART + + json_body, data_body = get_request_body(json=json, data=data, request_options=request_options, omit=omit) + + with self.httpx_client.stream( + method=method, + url=urllib.parse.urljoin(f"{base_url}/", path), + headers=jsonable_encoder( + remove_none_from_dict( + { + **self.base_headers(), + **(headers if headers is not None else {}), + **(request_options.get("additional_headers", {}) if request_options is not None else {}), + } + ) + ), + params=encode_query( + jsonable_encoder( + remove_none_from_dict( + remove_omit_from_dict( + { + **(params if params is not None else {}), + **( + request_options.get("additional_query_parameters", {}) + if request_options is not None + else {} + ), + }, + omit, + ) + ) + ) + ), + json=json_body, + data=data_body, + content=content, + files=request_files, + timeout=timeout, + ) as stream: + yield stream + + +class AsyncHttpClient: + def __init__( + self, + *, + httpx_client: httpx.AsyncClient, + base_timeout: typing.Callable[[], typing.Optional[float]], + base_headers: typing.Callable[[], typing.Dict[str, str]], + base_url: typing.Optional[typing.Callable[[], str]] = None, + ): + self.base_url = base_url + self.base_timeout = base_timeout + self.base_headers = base_headers + self.httpx_client = httpx_client + + def get_base_url(self, maybe_base_url: typing.Optional[str]) -> str: + base_url = maybe_base_url + if self.base_url is not None and base_url is None: + base_url = self.base_url() + + if base_url is None: + raise ValueError("A base_url is required to make this request, please provide one and try again.") + return base_url + + async def request( + self, + path: typing.Optional[str] = None, + *, + method: str, + base_url: typing.Optional[str] = None, + params: typing.Optional[typing.Dict[str, typing.Any]] = None, + json: typing.Optional[typing.Any] = None, + data: typing.Optional[typing.Any] = None, + content: typing.Optional[typing.Union[bytes, typing.Iterator[bytes], typing.AsyncIterator[bytes]]] = None, + files: typing.Optional[ + typing.Union[ + typing.Dict[str, typing.Optional[typing.Union[File, typing.List[File]]]], + typing.List[typing.Tuple[str, File]], + ] + ] = None, + headers: typing.Optional[typing.Dict[str, typing.Any]] = None, + request_options: typing.Optional[RequestOptions] = None, + retries: int = 2, + omit: typing.Optional[typing.Any] = None, + force_multipart: typing.Optional[bool] = None, + ) -> httpx.Response: + base_url = self.get_base_url(base_url) + timeout = ( + request_options.get("timeout_in_seconds") + if request_options is not None and request_options.get("timeout_in_seconds") is not None + else self.base_timeout() + ) + + request_files: typing.Optional[RequestFiles] = ( + convert_file_dict_to_httpx_tuples(remove_omit_from_dict(remove_none_from_dict(files), omit)) + if (files is not None and files is not omit and isinstance(files, dict)) + else None + ) + + if (request_files is None or len(request_files) == 0) and force_multipart: + request_files = FORCE_MULTIPART + + json_body, data_body = get_request_body(json=json, data=data, request_options=request_options, omit=omit) + + # Add the input to each of these and do None-safety checks + response = await self.httpx_client.request( + method=method, + url=urllib.parse.urljoin(f"{base_url}/", path), + headers=jsonable_encoder( + remove_none_from_dict( + { + **self.base_headers(), + **(headers if headers is not None else {}), + **(request_options.get("additional_headers", {}) or {} if request_options is not None else {}), + } + ) + ), + params=encode_query( + jsonable_encoder( + remove_none_from_dict( + remove_omit_from_dict( + { + **(params if params is not None else {}), + **( + request_options.get("additional_query_parameters", {}) or {} + if request_options is not None + else {} + ), + }, + omit, + ) + ) + ) + ), + json=json_body, + data=data_body, + content=content, + files=request_files, + timeout=timeout, + ) + + max_retries: int = request_options.get("max_retries", 0) if request_options is not None else 0 + if _should_retry(response=response): + if max_retries > retries: + await asyncio.sleep(_retry_timeout(response=response, retries=retries)) + return await self.request( + path=path, + method=method, + base_url=base_url, + params=params, + json=json, + content=content, + files=files, + headers=headers, + request_options=request_options, + retries=retries + 1, + omit=omit, + ) + return response + + @asynccontextmanager + async def stream( + self, + path: typing.Optional[str] = None, + *, + method: str, + base_url: typing.Optional[str] = None, + params: typing.Optional[typing.Dict[str, typing.Any]] = None, + json: typing.Optional[typing.Any] = None, + data: typing.Optional[typing.Any] = None, + content: typing.Optional[typing.Union[bytes, typing.Iterator[bytes], typing.AsyncIterator[bytes]]] = None, + files: typing.Optional[ + typing.Union[ + typing.Dict[str, typing.Optional[typing.Union[File, typing.List[File]]]], + typing.List[typing.Tuple[str, File]], + ] + ] = None, + headers: typing.Optional[typing.Dict[str, typing.Any]] = None, + request_options: typing.Optional[RequestOptions] = None, + retries: int = 2, + omit: typing.Optional[typing.Any] = None, + force_multipart: typing.Optional[bool] = None, + ) -> typing.AsyncIterator[httpx.Response]: + base_url = self.get_base_url(base_url) + timeout = ( + request_options.get("timeout_in_seconds") + if request_options is not None and request_options.get("timeout_in_seconds") is not None + else self.base_timeout() + ) + + request_files: typing.Optional[RequestFiles] = ( + convert_file_dict_to_httpx_tuples(remove_omit_from_dict(remove_none_from_dict(files), omit)) + if (files is not None and files is not omit and isinstance(files, dict)) + else None + ) + + if (request_files is None or len(request_files) == 0) and force_multipart: + request_files = FORCE_MULTIPART + + json_body, data_body = get_request_body(json=json, data=data, request_options=request_options, omit=omit) + + async with self.httpx_client.stream( + method=method, + url=urllib.parse.urljoin(f"{base_url}/", path), + headers=jsonable_encoder( + remove_none_from_dict( + { + **self.base_headers(), + **(headers if headers is not None else {}), + **(request_options.get("additional_headers", {}) if request_options is not None else {}), + } + ) + ), + params=encode_query( + jsonable_encoder( + remove_none_from_dict( + remove_omit_from_dict( + { + **(params if params is not None else {}), + **( + request_options.get("additional_query_parameters", {}) + if request_options is not None + else {} + ), + }, + omit=omit, + ) + ) + ) + ), + json=json_body, + data=data_body, + content=content, + files=request_files, + timeout=timeout, + ) as stream: + yield stream diff --git a/src/pipedream/core/http_response.py b/src/pipedream/core/http_response.py new file mode 100644 index 0000000..48a1798 --- /dev/null +++ b/src/pipedream/core/http_response.py @@ -0,0 +1,55 @@ +# This file was auto-generated by Fern from our API Definition. + +from typing import Dict, Generic, TypeVar + +import httpx + +T = TypeVar("T") +"""Generic to represent the underlying type of the data wrapped by the HTTP response.""" + + +class BaseHttpResponse: + """Minimalist HTTP response wrapper that exposes response headers.""" + + _response: httpx.Response + + def __init__(self, response: httpx.Response): + self._response = response + + @property + def headers(self) -> Dict[str, str]: + return dict(self._response.headers) + + +class HttpResponse(Generic[T], BaseHttpResponse): + """HTTP response wrapper that exposes response headers and data.""" + + _data: T + + def __init__(self, response: httpx.Response, data: T): + super().__init__(response) + self._data = data + + @property + def data(self) -> T: + return self._data + + def close(self) -> None: + self._response.close() + + +class AsyncHttpResponse(Generic[T], BaseHttpResponse): + """HTTP response wrapper that exposes response headers and data.""" + + _data: T + + def __init__(self, response: httpx.Response, data: T): + super().__init__(response) + self._data = data + + @property + def data(self) -> T: + return self._data + + async def close(self) -> None: + await self._response.aclose() diff --git a/src/pipedream/core/jsonable_encoder.py b/src/pipedream/core/jsonable_encoder.py new file mode 100644 index 0000000..afee366 --- /dev/null +++ b/src/pipedream/core/jsonable_encoder.py @@ -0,0 +1,100 @@ +# This file was auto-generated by Fern from our API Definition. + +""" +jsonable_encoder converts a Python object to a JSON-friendly dict +(e.g. datetimes to strings, Pydantic models to dicts). + +Taken from FastAPI, and made a bit simpler +https://github.com/tiangolo/fastapi/blob/master/fastapi/encoders.py +""" + +import base64 +import dataclasses +import datetime as dt +from enum import Enum +from pathlib import PurePath +from types import GeneratorType +from typing import Any, Callable, Dict, List, Optional, Set, Union + +import pydantic +from .datetime_utils import serialize_datetime +from .pydantic_utilities import ( + IS_PYDANTIC_V2, + encode_by_type, + to_jsonable_with_fallback, +) + +SetIntStr = Set[Union[int, str]] +DictIntStrAny = Dict[Union[int, str], Any] + + +def jsonable_encoder(obj: Any, custom_encoder: Optional[Dict[Any, Callable[[Any], Any]]] = None) -> Any: + custom_encoder = custom_encoder or {} + if custom_encoder: + if type(obj) in custom_encoder: + return custom_encoder[type(obj)](obj) + else: + for encoder_type, encoder_instance in custom_encoder.items(): + if isinstance(obj, encoder_type): + return encoder_instance(obj) + if isinstance(obj, pydantic.BaseModel): + if IS_PYDANTIC_V2: + encoder = getattr(obj.model_config, "json_encoders", {}) # type: ignore # Pydantic v2 + else: + encoder = getattr(obj.__config__, "json_encoders", {}) # type: ignore # Pydantic v1 + if custom_encoder: + encoder.update(custom_encoder) + obj_dict = obj.dict(by_alias=True) + if "__root__" in obj_dict: + obj_dict = obj_dict["__root__"] + if "root" in obj_dict: + obj_dict = obj_dict["root"] + return jsonable_encoder(obj_dict, custom_encoder=encoder) + if dataclasses.is_dataclass(obj): + obj_dict = dataclasses.asdict(obj) # type: ignore + return jsonable_encoder(obj_dict, custom_encoder=custom_encoder) + if isinstance(obj, bytes): + return base64.b64encode(obj).decode("utf-8") + if isinstance(obj, Enum): + return obj.value + if isinstance(obj, PurePath): + return str(obj) + if isinstance(obj, (str, int, float, type(None))): + return obj + if isinstance(obj, dt.datetime): + return serialize_datetime(obj) + if isinstance(obj, dt.date): + return str(obj) + if isinstance(obj, dict): + encoded_dict = {} + allowed_keys = set(obj.keys()) + for key, value in obj.items(): + if key in allowed_keys: + encoded_key = jsonable_encoder(key, custom_encoder=custom_encoder) + encoded_value = jsonable_encoder(value, custom_encoder=custom_encoder) + encoded_dict[encoded_key] = encoded_value + return encoded_dict + if isinstance(obj, (list, set, frozenset, GeneratorType, tuple)): + encoded_list = [] + for item in obj: + encoded_list.append(jsonable_encoder(item, custom_encoder=custom_encoder)) + return encoded_list + + def fallback_serializer(o: Any) -> Any: + attempt_encode = encode_by_type(o) + if attempt_encode is not None: + return attempt_encode + + try: + data = dict(o) + except Exception as e: + errors: List[Exception] = [] + errors.append(e) + try: + data = vars(o) + except Exception as e: + errors.append(e) + raise ValueError(errors) from e + return jsonable_encoder(data, custom_encoder=custom_encoder) + + return to_jsonable_with_fallback(obj, fallback_serializer) diff --git a/src/pipedream/core/oauth_token_provider.py b/src/pipedream/core/oauth_token_provider.py new file mode 100644 index 0000000..c158e70 --- /dev/null +++ b/src/pipedream/core/oauth_token_provider.py @@ -0,0 +1,34 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +from ..oauth_tokens.client import OauthTokensClient +from .client_wrapper import SyncClientWrapper + + +class OAuthTokenProvider: + BUFFER_IN_MINUTES = 2 + + def __init__(self, *, client_id: str, client_secret: str, client_wrapper: SyncClientWrapper): + self._client_id = client_id + self._client_secret = client_secret + self._access_token: typing.Optional[str] = None + self._expires_at: dt.datetime = dt.datetime.now() + self._auth_client = OauthTokensClient(client_wrapper=client_wrapper) + + def get_token(self) -> str: + if self._access_token and self._expires_at > dt.datetime.now(): + return self._access_token + return self._refresh() + + def _refresh(self) -> str: + token_response = self._auth_client.create(client_id=self._client_id, client_secret=self._client_secret) + self._access_token = token_response.access_token + self._expires_at = self._get_expires_at( + expires_in_seconds=token_response.expires_in, buffer_in_minutes=self.BUFFER_IN_MINUTES + ) + return self._access_token + + def _get_expires_at(self, *, expires_in_seconds: int, buffer_in_minutes: int): + return dt.datetime.now() + dt.timedelta(seconds=expires_in_seconds) - dt.timedelta(minutes=buffer_in_minutes) diff --git a/src/pipedream/core/pagination.py b/src/pipedream/core/pagination.py new file mode 100644 index 0000000..209a1ff --- /dev/null +++ b/src/pipedream/core/pagination.py @@ -0,0 +1,82 @@ +# This file was auto-generated by Fern from our API Definition. + +from __future__ import annotations + +from dataclasses import dataclass +from typing import AsyncIterator, Awaitable, Callable, Generic, Iterator, List, Optional, TypeVar + +from .http_response import BaseHttpResponse + +T = TypeVar("T") +"""Generic to represent the underlying type of the results within a page""" + + +# SDKs implement a Page ABC per-pagination request, the endpoint then returns a pager that wraps this type +# for example, an endpoint will return SyncPager[UserPage] where UserPage implements the Page ABC. ex: +# +# SyncPager( +# has_next=response.list_metadata.after is not None, +# items=response.data, +# # This should be the outer function that returns the SyncPager again +# get_next=lambda: list(..., cursor: response.cursor) (or list(..., offset: offset + 1)) +# ) + + +@dataclass(frozen=True) +class SyncPager(Generic[T]): + get_next: Optional[Callable[[], Optional[SyncPager[T]]]] + has_next: bool + items: Optional[List[T]] + response: Optional[BaseHttpResponse] + + # Here we type ignore the iterator to avoid a mypy error + # caused by the type conflict with Pydanitc's __iter__ method + # brought in by extending the base model + def __iter__(self) -> Iterator[T]: # type: ignore[override] + for page in self.iter_pages(): + if page.items is not None: + yield from page.items + + def iter_pages(self) -> Iterator[SyncPager[T]]: + page: Optional[SyncPager[T]] = self + while page is not None: + yield page + + if not page.has_next or page.get_next is None: + return + + page = page.get_next() + if page is None or page.items is None or len(page.items) == 0: + return + + def next_page(self) -> Optional[SyncPager[T]]: + return self.get_next() if self.get_next is not None else None + + +@dataclass(frozen=True) +class AsyncPager(Generic[T]): + get_next: Optional[Callable[[], Awaitable[Optional[AsyncPager[T]]]]] + has_next: bool + items: Optional[List[T]] + response: Optional[BaseHttpResponse] + + async def __aiter__(self) -> AsyncIterator[T]: + async for page in self.iter_pages(): + if page.items is not None: + for item in page.items: + yield item + + async def iter_pages(self) -> AsyncIterator[AsyncPager[T]]: + page: Optional[AsyncPager[T]] = self + while page is not None: + yield page + + if not page.has_next or page.get_next is None: + return + + page = await page.get_next() + if page is None or page.items is None or len(page.items) == 0: + return + + async def next_page(self) -> Optional[AsyncPager[T]]: + return await self.get_next() if self.get_next is not None else None diff --git a/src/pipedream/core/pydantic_utilities.py b/src/pipedream/core/pydantic_utilities.py new file mode 100644 index 0000000..7db2950 --- /dev/null +++ b/src/pipedream/core/pydantic_utilities.py @@ -0,0 +1,255 @@ +# This file was auto-generated by Fern from our API Definition. + +# nopycln: file +import datetime as dt +from collections import defaultdict +from typing import Any, Callable, ClassVar, Dict, List, Mapping, Optional, Set, Tuple, Type, TypeVar, Union, cast + +import pydantic + +IS_PYDANTIC_V2 = pydantic.VERSION.startswith("2.") + +if IS_PYDANTIC_V2: + from pydantic.v1.datetime_parse import parse_date as parse_date + from pydantic.v1.datetime_parse import parse_datetime as parse_datetime + from pydantic.v1.fields import ModelField as ModelField + from pydantic.v1.json import ENCODERS_BY_TYPE as encoders_by_type # type: ignore[attr-defined] + from pydantic.v1.typing import get_args as get_args + from pydantic.v1.typing import get_origin as get_origin + from pydantic.v1.typing import is_literal_type as is_literal_type + from pydantic.v1.typing import is_union as is_union +else: + from pydantic.datetime_parse import parse_date as parse_date # type: ignore[no-redef] + from pydantic.datetime_parse import parse_datetime as parse_datetime # type: ignore[no-redef] + from pydantic.fields import ModelField as ModelField # type: ignore[attr-defined, no-redef] + from pydantic.json import ENCODERS_BY_TYPE as encoders_by_type # type: ignore[no-redef] + from pydantic.typing import get_args as get_args # type: ignore[no-redef] + from pydantic.typing import get_origin as get_origin # type: ignore[no-redef] + from pydantic.typing import is_literal_type as is_literal_type # type: ignore[no-redef] + from pydantic.typing import is_union as is_union # type: ignore[no-redef] + +from .datetime_utils import serialize_datetime +from .serialization import convert_and_respect_annotation_metadata +from typing_extensions import TypeAlias + +T = TypeVar("T") +Model = TypeVar("Model", bound=pydantic.BaseModel) + + +def parse_obj_as(type_: Type[T], object_: Any) -> T: + dealiased_object = convert_and_respect_annotation_metadata(object_=object_, annotation=type_, direction="read") + if IS_PYDANTIC_V2: + adapter = pydantic.TypeAdapter(type_) # type: ignore[attr-defined] + return adapter.validate_python(dealiased_object) + return pydantic.parse_obj_as(type_, dealiased_object) + + +def to_jsonable_with_fallback(obj: Any, fallback_serializer: Callable[[Any], Any]) -> Any: + if IS_PYDANTIC_V2: + from pydantic_core import to_jsonable_python + + return to_jsonable_python(obj, fallback=fallback_serializer) + return fallback_serializer(obj) + + +class UniversalBaseModel(pydantic.BaseModel): + if IS_PYDANTIC_V2: + model_config: ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict( # type: ignore[typeddict-unknown-key] + # Allow fields beginning with `model_` to be used in the model + protected_namespaces=(), + ) + + @pydantic.model_serializer(mode="plain", when_used="json") # type: ignore[attr-defined] + def serialize_model(self) -> Any: # type: ignore[name-defined] + serialized = self.model_dump() + data = {k: serialize_datetime(v) if isinstance(v, dt.datetime) else v for k, v in serialized.items()} + return data + + else: + + class Config: + smart_union = True + json_encoders = {dt.datetime: serialize_datetime} + + @classmethod + def model_construct(cls: Type["Model"], _fields_set: Optional[Set[str]] = None, **values: Any) -> "Model": + dealiased_object = convert_and_respect_annotation_metadata(object_=values, annotation=cls, direction="read") + return cls.construct(_fields_set, **dealiased_object) + + @classmethod + def construct(cls: Type["Model"], _fields_set: Optional[Set[str]] = None, **values: Any) -> "Model": + dealiased_object = convert_and_respect_annotation_metadata(object_=values, annotation=cls, direction="read") + if IS_PYDANTIC_V2: + return super().model_construct(_fields_set, **dealiased_object) # type: ignore[misc] + return super().construct(_fields_set, **dealiased_object) + + def json(self, **kwargs: Any) -> str: + kwargs_with_defaults = { + "by_alias": True, + "exclude_unset": True, + **kwargs, + } + if IS_PYDANTIC_V2: + return super().model_dump_json(**kwargs_with_defaults) # type: ignore[misc] + return super().json(**kwargs_with_defaults) + + def dict(self, **kwargs: Any) -> Dict[str, Any]: + """ + Override the default dict method to `exclude_unset` by default. This function patches + `exclude_unset` to work include fields within non-None default values. + """ + # Note: the logic here is multiplexed given the levers exposed in Pydantic V1 vs V2 + # Pydantic V1's .dict can be extremely slow, so we do not want to call it twice. + # + # We'd ideally do the same for Pydantic V2, but it shells out to a library to serialize models + # that we have less control over, and this is less intrusive than custom serializers for now. + if IS_PYDANTIC_V2: + kwargs_with_defaults_exclude_unset = { + **kwargs, + "by_alias": True, + "exclude_unset": True, + "exclude_none": False, + } + kwargs_with_defaults_exclude_none = { + **kwargs, + "by_alias": True, + "exclude_none": True, + "exclude_unset": False, + } + dict_dump = deep_union_pydantic_dicts( + super().model_dump(**kwargs_with_defaults_exclude_unset), # type: ignore[misc] + super().model_dump(**kwargs_with_defaults_exclude_none), # type: ignore[misc] + ) + + else: + _fields_set = self.__fields_set__.copy() + + fields = _get_model_fields(self.__class__) + for name, field in fields.items(): + if name not in _fields_set: + default = _get_field_default(field) + + # If the default values are non-null act like they've been set + # This effectively allows exclude_unset to work like exclude_none where + # the latter passes through intentionally set none values. + if default is not None or ("exclude_unset" in kwargs and not kwargs["exclude_unset"]): + _fields_set.add(name) + + if default is not None: + self.__fields_set__.add(name) + + kwargs_with_defaults_exclude_unset_include_fields = { + "by_alias": True, + "exclude_unset": True, + "include": _fields_set, + **kwargs, + } + + dict_dump = super().dict(**kwargs_with_defaults_exclude_unset_include_fields) + + return convert_and_respect_annotation_metadata(object_=dict_dump, annotation=self.__class__, direction="write") + + +def _union_list_of_pydantic_dicts(source: List[Any], destination: List[Any]) -> List[Any]: + converted_list: List[Any] = [] + for i, item in enumerate(source): + destination_value = destination[i] + if isinstance(item, dict): + converted_list.append(deep_union_pydantic_dicts(item, destination_value)) + elif isinstance(item, list): + converted_list.append(_union_list_of_pydantic_dicts(item, destination_value)) + else: + converted_list.append(item) + return converted_list + + +def deep_union_pydantic_dicts(source: Dict[str, Any], destination: Dict[str, Any]) -> Dict[str, Any]: + for key, value in source.items(): + node = destination.setdefault(key, {}) + if isinstance(value, dict): + deep_union_pydantic_dicts(value, node) + # Note: we do not do this same processing for sets given we do not have sets of models + # and given the sets are unordered, the processing of the set and matching objects would + # be non-trivial. + elif isinstance(value, list): + destination[key] = _union_list_of_pydantic_dicts(value, node) + else: + destination[key] = value + + return destination + + +if IS_PYDANTIC_V2: + + class V2RootModel(UniversalBaseModel, pydantic.RootModel): # type: ignore[misc, name-defined, type-arg] + pass + + UniversalRootModel: TypeAlias = V2RootModel # type: ignore[misc] +else: + UniversalRootModel: TypeAlias = UniversalBaseModel # type: ignore[misc, no-redef] + + +def encode_by_type(o: Any) -> Any: + encoders_by_class_tuples: Dict[Callable[[Any], Any], Tuple[Any, ...]] = defaultdict(tuple) + for type_, encoder in encoders_by_type.items(): + encoders_by_class_tuples[encoder] += (type_,) + + if type(o) in encoders_by_type: + return encoders_by_type[type(o)](o) + for encoder, classes_tuple in encoders_by_class_tuples.items(): + if isinstance(o, classes_tuple): + return encoder(o) + + +def update_forward_refs(model: Type["Model"], **localns: Any) -> None: + if IS_PYDANTIC_V2: + model.model_rebuild(raise_errors=False) # type: ignore[attr-defined] + else: + model.update_forward_refs(**localns) + + +# Mirrors Pydantic's internal typing +AnyCallable = Callable[..., Any] + + +def universal_root_validator( + pre: bool = False, +) -> Callable[[AnyCallable], AnyCallable]: + def decorator(func: AnyCallable) -> AnyCallable: + if IS_PYDANTIC_V2: + return cast(AnyCallable, pydantic.model_validator(mode="before" if pre else "after")(func)) # type: ignore[attr-defined] + return cast(AnyCallable, pydantic.root_validator(pre=pre)(func)) # type: ignore[call-overload] + + return decorator + + +def universal_field_validator(field_name: str, pre: bool = False) -> Callable[[AnyCallable], AnyCallable]: + def decorator(func: AnyCallable) -> AnyCallable: + if IS_PYDANTIC_V2: + return cast(AnyCallable, pydantic.field_validator(field_name, mode="before" if pre else "after")(func)) # type: ignore[attr-defined] + return cast(AnyCallable, pydantic.validator(field_name, pre=pre)(func)) + + return decorator + + +PydanticField = Union[ModelField, pydantic.fields.FieldInfo] + + +def _get_model_fields(model: Type["Model"]) -> Mapping[str, PydanticField]: + if IS_PYDANTIC_V2: + return cast(Mapping[str, PydanticField], model.model_fields) # type: ignore[attr-defined] + return cast(Mapping[str, PydanticField], model.__fields__) + + +def _get_field_default(field: PydanticField) -> Any: + try: + value = field.get_default() # type: ignore[union-attr] + except: + value = field.default + if IS_PYDANTIC_V2: + from pydantic_core import PydanticUndefined + + if value == PydanticUndefined: + return None + return value + return value diff --git a/src/pipedream/core/query_encoder.py b/src/pipedream/core/query_encoder.py new file mode 100644 index 0000000..3183001 --- /dev/null +++ b/src/pipedream/core/query_encoder.py @@ -0,0 +1,58 @@ +# This file was auto-generated by Fern from our API Definition. + +from typing import Any, Dict, List, Optional, Tuple + +import pydantic + + +# Flattens dicts to be of the form {"key[subkey][subkey2]": value} where value is not a dict +def traverse_query_dict(dict_flat: Dict[str, Any], key_prefix: Optional[str] = None) -> List[Tuple[str, Any]]: + result = [] + for k, v in dict_flat.items(): + key = f"{key_prefix}[{k}]" if key_prefix is not None else k + if isinstance(v, dict): + result.extend(traverse_query_dict(v, key)) + elif isinstance(v, list): + for arr_v in v: + if isinstance(arr_v, dict): + result.extend(traverse_query_dict(arr_v, key)) + else: + result.append((key, arr_v)) + else: + result.append((key, v)) + return result + + +def single_query_encoder(query_key: str, query_value: Any) -> List[Tuple[str, Any]]: + if isinstance(query_value, pydantic.BaseModel) or isinstance(query_value, dict): + if isinstance(query_value, pydantic.BaseModel): + obj_dict = query_value.dict(by_alias=True) + else: + obj_dict = query_value + return traverse_query_dict(obj_dict, query_key) + elif isinstance(query_value, list): + encoded_values: List[Tuple[str, Any]] = [] + for value in query_value: + if isinstance(value, pydantic.BaseModel) or isinstance(value, dict): + if isinstance(value, pydantic.BaseModel): + obj_dict = value.dict(by_alias=True) + elif isinstance(value, dict): + obj_dict = value + + encoded_values.extend(single_query_encoder(query_key, obj_dict)) + else: + encoded_values.append((query_key, value)) + + return encoded_values + + return [(query_key, query_value)] + + +def encode_query(query: Optional[Dict[str, Any]]) -> Optional[List[Tuple[str, Any]]]: + if query is None: + return None + + encoded_query = [] + for k, v in query.items(): + encoded_query.extend(single_query_encoder(k, v)) + return encoded_query diff --git a/src/pipedream/core/remove_none_from_dict.py b/src/pipedream/core/remove_none_from_dict.py new file mode 100644 index 0000000..c229814 --- /dev/null +++ b/src/pipedream/core/remove_none_from_dict.py @@ -0,0 +1,11 @@ +# This file was auto-generated by Fern from our API Definition. + +from typing import Any, Dict, Mapping, Optional + + +def remove_none_from_dict(original: Mapping[str, Optional[Any]]) -> Dict[str, Any]: + new: Dict[str, Any] = {} + for key, value in original.items(): + if value is not None: + new[key] = value + return new diff --git a/src/pipedream/core/request_options.py b/src/pipedream/core/request_options.py new file mode 100644 index 0000000..1b38804 --- /dev/null +++ b/src/pipedream/core/request_options.py @@ -0,0 +1,35 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +try: + from typing import NotRequired # type: ignore +except ImportError: + from typing_extensions import NotRequired + + +class RequestOptions(typing.TypedDict, total=False): + """ + Additional options for request-specific configuration when calling APIs via the SDK. + This is used primarily as an optional final parameter for service functions. + + Attributes: + - timeout_in_seconds: int. The number of seconds to await an API call before timing out. + + - max_retries: int. The max number of retries to attempt if the API call fails. + + - additional_headers: typing.Dict[str, typing.Any]. A dictionary containing additional parameters to spread into the request's header dict + + - additional_query_parameters: typing.Dict[str, typing.Any]. A dictionary containing additional parameters to spread into the request's query parameters dict + + - additional_body_parameters: typing.Dict[str, typing.Any]. A dictionary containing additional parameters to spread into the request's body parameters dict + + - chunk_size: int. The size, in bytes, to process each chunk of data being streamed back within the response. This equates to leveraging `chunk_size` within `requests` or `httpx`, and is only leveraged for file downloads. + """ + + timeout_in_seconds: NotRequired[int] + max_retries: NotRequired[int] + additional_headers: NotRequired[typing.Dict[str, typing.Any]] + additional_query_parameters: NotRequired[typing.Dict[str, typing.Any]] + additional_body_parameters: NotRequired[typing.Dict[str, typing.Any]] + chunk_size: NotRequired[int] diff --git a/src/pipedream/core/serialization.py b/src/pipedream/core/serialization.py new file mode 100644 index 0000000..c36e865 --- /dev/null +++ b/src/pipedream/core/serialization.py @@ -0,0 +1,276 @@ +# This file was auto-generated by Fern from our API Definition. + +import collections +import inspect +import typing + +import pydantic +import typing_extensions + + +class FieldMetadata: + """ + Metadata class used to annotate fields to provide additional information. + + Example: + class MyDict(TypedDict): + field: typing.Annotated[str, FieldMetadata(alias="field_name")] + + Will serialize: `{"field": "value"}` + To: `{"field_name": "value"}` + """ + + alias: str + + def __init__(self, *, alias: str) -> None: + self.alias = alias + + +def convert_and_respect_annotation_metadata( + *, + object_: typing.Any, + annotation: typing.Any, + inner_type: typing.Optional[typing.Any] = None, + direction: typing.Literal["read", "write"], +) -> typing.Any: + """ + Respect the metadata annotations on a field, such as aliasing. This function effectively + manipulates the dict-form of an object to respect the metadata annotations. This is primarily used for + TypedDicts, which cannot support aliasing out of the box, and can be extended for additional + utilities, such as defaults. + + Parameters + ---------- + object_ : typing.Any + + annotation : type + The type we're looking to apply typing annotations from + + inner_type : typing.Optional[type] + + Returns + ------- + typing.Any + """ + + if object_ is None: + return None + if inner_type is None: + inner_type = annotation + + clean_type = _remove_annotations(inner_type) + # Pydantic models + if ( + inspect.isclass(clean_type) + and issubclass(clean_type, pydantic.BaseModel) + and isinstance(object_, typing.Mapping) + ): + return _convert_mapping(object_, clean_type, direction) + # TypedDicts + if typing_extensions.is_typeddict(clean_type) and isinstance(object_, typing.Mapping): + return _convert_mapping(object_, clean_type, direction) + + if ( + typing_extensions.get_origin(clean_type) == typing.Dict + or typing_extensions.get_origin(clean_type) == dict + or clean_type == typing.Dict + ) and isinstance(object_, typing.Dict): + key_type = typing_extensions.get_args(clean_type)[0] + value_type = typing_extensions.get_args(clean_type)[1] + + return { + key: convert_and_respect_annotation_metadata( + object_=value, + annotation=annotation, + inner_type=value_type, + direction=direction, + ) + for key, value in object_.items() + } + + # If you're iterating on a string, do not bother to coerce it to a sequence. + if not isinstance(object_, str): + if ( + typing_extensions.get_origin(clean_type) == typing.Set + or typing_extensions.get_origin(clean_type) == set + or clean_type == typing.Set + ) and isinstance(object_, typing.Set): + inner_type = typing_extensions.get_args(clean_type)[0] + return { + convert_and_respect_annotation_metadata( + object_=item, + annotation=annotation, + inner_type=inner_type, + direction=direction, + ) + for item in object_ + } + elif ( + ( + typing_extensions.get_origin(clean_type) == typing.List + or typing_extensions.get_origin(clean_type) == list + or clean_type == typing.List + ) + and isinstance(object_, typing.List) + ) or ( + ( + typing_extensions.get_origin(clean_type) == typing.Sequence + or typing_extensions.get_origin(clean_type) == collections.abc.Sequence + or clean_type == typing.Sequence + ) + and isinstance(object_, typing.Sequence) + ): + inner_type = typing_extensions.get_args(clean_type)[0] + return [ + convert_and_respect_annotation_metadata( + object_=item, + annotation=annotation, + inner_type=inner_type, + direction=direction, + ) + for item in object_ + ] + + if typing_extensions.get_origin(clean_type) == typing.Union: + # We should be able to ~relatively~ safely try to convert keys against all + # member types in the union, the edge case here is if one member aliases a field + # of the same name to a different name from another member + # Or if another member aliases a field of the same name that another member does not. + for member in typing_extensions.get_args(clean_type): + object_ = convert_and_respect_annotation_metadata( + object_=object_, + annotation=annotation, + inner_type=member, + direction=direction, + ) + return object_ + + annotated_type = _get_annotation(annotation) + if annotated_type is None: + return object_ + + # If the object is not a TypedDict, a Union, or other container (list, set, sequence, etc.) + # Then we can safely call it on the recursive conversion. + return object_ + + +def _convert_mapping( + object_: typing.Mapping[str, object], + expected_type: typing.Any, + direction: typing.Literal["read", "write"], +) -> typing.Mapping[str, object]: + converted_object: typing.Dict[str, object] = {} + try: + annotations = typing_extensions.get_type_hints(expected_type, include_extras=True) + except NameError: + # The TypedDict contains a circular reference, so + # we use the __annotations__ attribute directly. + annotations = getattr(expected_type, "__annotations__", {}) + aliases_to_field_names = _get_alias_to_field_name(annotations) + for key, value in object_.items(): + if direction == "read" and key in aliases_to_field_names: + dealiased_key = aliases_to_field_names.get(key) + if dealiased_key is not None: + type_ = annotations.get(dealiased_key) + else: + type_ = annotations.get(key) + # Note you can't get the annotation by the field name if you're in read mode, so you must check the aliases map + # + # So this is effectively saying if we're in write mode, and we don't have a type, or if we're in read mode and we don't have an alias + # then we can just pass the value through as is + if type_ is None: + converted_object[key] = value + elif direction == "read" and key not in aliases_to_field_names: + converted_object[key] = convert_and_respect_annotation_metadata( + object_=value, annotation=type_, direction=direction + ) + else: + converted_object[_alias_key(key, type_, direction, aliases_to_field_names)] = ( + convert_and_respect_annotation_metadata(object_=value, annotation=type_, direction=direction) + ) + return converted_object + + +def _get_annotation(type_: typing.Any) -> typing.Optional[typing.Any]: + maybe_annotated_type = typing_extensions.get_origin(type_) + if maybe_annotated_type is None: + return None + + if maybe_annotated_type == typing_extensions.NotRequired: + type_ = typing_extensions.get_args(type_)[0] + maybe_annotated_type = typing_extensions.get_origin(type_) + + if maybe_annotated_type == typing_extensions.Annotated: + return type_ + + return None + + +def _remove_annotations(type_: typing.Any) -> typing.Any: + maybe_annotated_type = typing_extensions.get_origin(type_) + if maybe_annotated_type is None: + return type_ + + if maybe_annotated_type == typing_extensions.NotRequired: + return _remove_annotations(typing_extensions.get_args(type_)[0]) + + if maybe_annotated_type == typing_extensions.Annotated: + return _remove_annotations(typing_extensions.get_args(type_)[0]) + + return type_ + + +def get_alias_to_field_mapping(type_: typing.Any) -> typing.Dict[str, str]: + annotations = typing_extensions.get_type_hints(type_, include_extras=True) + return _get_alias_to_field_name(annotations) + + +def get_field_to_alias_mapping(type_: typing.Any) -> typing.Dict[str, str]: + annotations = typing_extensions.get_type_hints(type_, include_extras=True) + return _get_field_to_alias_name(annotations) + + +def _get_alias_to_field_name( + field_to_hint: typing.Dict[str, typing.Any], +) -> typing.Dict[str, str]: + aliases = {} + for field, hint in field_to_hint.items(): + maybe_alias = _get_alias_from_type(hint) + if maybe_alias is not None: + aliases[maybe_alias] = field + return aliases + + +def _get_field_to_alias_name( + field_to_hint: typing.Dict[str, typing.Any], +) -> typing.Dict[str, str]: + aliases = {} + for field, hint in field_to_hint.items(): + maybe_alias = _get_alias_from_type(hint) + if maybe_alias is not None: + aliases[field] = maybe_alias + return aliases + + +def _get_alias_from_type(type_: typing.Any) -> typing.Optional[str]: + maybe_annotated_type = _get_annotation(type_) + + if maybe_annotated_type is not None: + # The actual annotations are 1 onward, the first is the annotated type + annotations = typing_extensions.get_args(maybe_annotated_type)[1:] + + for annotation in annotations: + if isinstance(annotation, FieldMetadata) and annotation.alias is not None: + return annotation.alias + return None + + +def _alias_key( + key: str, + type_: typing.Any, + direction: typing.Literal["read", "write"], + aliases_to_field_names: typing.Dict[str, str], +) -> str: + if direction == "read": + return aliases_to_field_names.get(key, key) + return _get_alias_from_type(type_=type_) or key diff --git a/src/pipedream/deployed_triggers/__init__.py b/src/pipedream/deployed_triggers/__init__.py new file mode 100644 index 0000000..5cde020 --- /dev/null +++ b/src/pipedream/deployed_triggers/__init__.py @@ -0,0 +1,4 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + diff --git a/src/pipedream/deployed_triggers/client.py b/src/pipedream/deployed_triggers/client.py new file mode 100644 index 0000000..0535ef7 --- /dev/null +++ b/src/pipedream/deployed_triggers/client.py @@ -0,0 +1,1094 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ..core.pagination import AsyncPager, SyncPager +from ..core.request_options import RequestOptions +from ..types.deployed_component import DeployedComponent +from ..types.emitted_event import EmittedEvent +from ..types.get_trigger_webhooks_response import GetTriggerWebhooksResponse +from ..types.get_trigger_workflows_response import GetTriggerWorkflowsResponse +from .raw_client import AsyncRawDeployedTriggersClient, RawDeployedTriggersClient + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class DeployedTriggersClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._raw_client = RawDeployedTriggersClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawDeployedTriggersClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawDeployedTriggersClient + """ + return self._raw_client + + def list( + self, + project_id: str, + *, + external_user_id: str, + after: typing.Optional[str] = None, + before: typing.Optional[str] = None, + limit: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> SyncPager[DeployedComponent]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + external_user_id : str + Your end user ID, for whom you deployed the trigger + + after : typing.Optional[str] + The cursor to start from for pagination + + before : typing.Optional[str] + The cursor to end before for pagination + + limit : typing.Optional[int] + The maximum number of results to return + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + SyncPager[DeployedComponent] + deployed triggers listed + + Examples + -------- + from pipedream import Pipedream + + client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + response = client.deployed_triggers.list( + project_id="project_id", + external_user_id="external_user_id", + ) + for item in response: + yield item + # alternatively, you can paginate page-by-page + for page in response.iter_pages(): + yield page + """ + return self._raw_client.list( + project_id, + external_user_id=external_user_id, + after=after, + before=before, + limit=limit, + request_options=request_options, + ) + + def retrieve( + self, + project_id: str, + trigger_id: str, + *, + external_user_id: str, + request_options: typing.Optional[RequestOptions] = None, + ) -> DeployedComponent: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + trigger_id : str + + external_user_id : str + Your end user ID, for whom you deployed the trigger + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + DeployedComponent + deployed trigger retrieved + + Examples + -------- + from pipedream import Pipedream + + client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + client.deployed_triggers.retrieve( + project_id="project_id", + trigger_id="trigger_id", + external_user_id="external_user_id", + ) + """ + _response = self._raw_client.retrieve( + project_id, trigger_id, external_user_id=external_user_id, request_options=request_options + ) + return _response.data + + def update( + self, + project_id: str, + trigger_id: str, + *, + external_user_id: str, + active: typing.Optional[bool] = OMIT, + configured_props: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, + name: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> DeployedComponent: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + trigger_id : str + + external_user_id : str + The external user ID who owns the trigger + + active : typing.Optional[bool] + Whether the trigger should be active + + configured_props : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] + The configured properties for the trigger + + name : typing.Optional[str] + The name of the trigger + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + DeployedComponent + deployed trigger updated + + Examples + -------- + from pipedream import Pipedream + + client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + client.deployed_triggers.update( + project_id="project_id", + trigger_id="trigger_id", + external_user_id="external_user_id", + ) + """ + _response = self._raw_client.update( + project_id, + trigger_id, + external_user_id=external_user_id, + active=active, + configured_props=configured_props, + name=name, + request_options=request_options, + ) + return _response.data + + def delete( + self, + project_id: str, + trigger_id: str, + *, + external_user_id: str, + ignore_hook_errors: typing.Optional[bool] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> None: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + trigger_id : str + + external_user_id : str + The external user ID who owns the trigger + + ignore_hook_errors : typing.Optional[bool] + Whether to ignore errors during deactivation hook + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + None + + Examples + -------- + from pipedream import Pipedream + + client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + client.deployed_triggers.delete( + project_id="project_id", + trigger_id="trigger_id", + external_user_id="external_user_id", + ) + """ + _response = self._raw_client.delete( + project_id, + trigger_id, + external_user_id=external_user_id, + ignore_hook_errors=ignore_hook_errors, + request_options=request_options, + ) + return _response.data + + def list_events( + self, + project_id: str, + trigger_id: str, + *, + external_user_id: str, + n: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> typing.List[EmittedEvent]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + trigger_id : str + + external_user_id : str + Your end user ID, for whom you deployed the trigger + + n : typing.Optional[int] + The number of events to retrieve (defaults to 20 if not provided) + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.List[EmittedEvent] + trigger events retrieved + + Examples + -------- + from pipedream import Pipedream + + client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + client.deployed_triggers.list_events( + project_id="project_id", + trigger_id="trigger_id", + external_user_id="external_user_id", + ) + """ + _response = self._raw_client.list_events( + project_id, trigger_id, external_user_id=external_user_id, n=n, request_options=request_options + ) + return _response.data + + def list_workflows( + self, + project_id: str, + trigger_id: str, + *, + external_user_id: str, + request_options: typing.Optional[RequestOptions] = None, + ) -> GetTriggerWorkflowsResponse: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + trigger_id : str + + external_user_id : str + The external user ID who owns the trigger + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + GetTriggerWorkflowsResponse + trigger workflows retrieved + + Examples + -------- + from pipedream import Pipedream + + client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + client.deployed_triggers.list_workflows( + project_id="project_id", + trigger_id="trigger_id", + external_user_id="external_user_id", + ) + """ + _response = self._raw_client.list_workflows( + project_id, trigger_id, external_user_id=external_user_id, request_options=request_options + ) + return _response.data + + def update_workflows( + self, + project_id: str, + trigger_id: str, + *, + external_user_id: str, + workflow_ids: typing.Sequence[str], + request_options: typing.Optional[RequestOptions] = None, + ) -> GetTriggerWorkflowsResponse: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + trigger_id : str + + external_user_id : str + The external user ID who owns the trigger + + workflow_ids : typing.Sequence[str] + Array of workflow IDs to set + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + GetTriggerWorkflowsResponse + trigger workflows updated + + Examples + -------- + from pipedream import Pipedream + + client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + client.deployed_triggers.update_workflows( + project_id="project_id", + trigger_id="trigger_id", + external_user_id="external_user_id", + workflow_ids=["workflow_ids"], + ) + """ + _response = self._raw_client.update_workflows( + project_id, + trigger_id, + external_user_id=external_user_id, + workflow_ids=workflow_ids, + request_options=request_options, + ) + return _response.data + + def list_webhooks( + self, + project_id: str, + trigger_id: str, + *, + external_user_id: str, + request_options: typing.Optional[RequestOptions] = None, + ) -> GetTriggerWebhooksResponse: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + trigger_id : str + + external_user_id : str + The external user ID who owns the trigger + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + GetTriggerWebhooksResponse + trigger webhooks retrieved + + Examples + -------- + from pipedream import Pipedream + + client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + client.deployed_triggers.list_webhooks( + project_id="project_id", + trigger_id="trigger_id", + external_user_id="external_user_id", + ) + """ + _response = self._raw_client.list_webhooks( + project_id, trigger_id, external_user_id=external_user_id, request_options=request_options + ) + return _response.data + + def update_webhooks( + self, + project_id: str, + trigger_id: str, + *, + external_user_id: str, + webhook_urls: typing.Sequence[str], + request_options: typing.Optional[RequestOptions] = None, + ) -> GetTriggerWebhooksResponse: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + trigger_id : str + + external_user_id : str + The external user ID who owns the trigger + + webhook_urls : typing.Sequence[str] + Array of webhook URLs to set + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + GetTriggerWebhooksResponse + trigger webhooks updated + + Examples + -------- + from pipedream import Pipedream + + client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + client.deployed_triggers.update_webhooks( + project_id="project_id", + trigger_id="trigger_id", + external_user_id="external_user_id", + webhook_urls=["webhook_urls"], + ) + """ + _response = self._raw_client.update_webhooks( + project_id, + trigger_id, + external_user_id=external_user_id, + webhook_urls=webhook_urls, + request_options=request_options, + ) + return _response.data + + +class AsyncDeployedTriggersClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._raw_client = AsyncRawDeployedTriggersClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawDeployedTriggersClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawDeployedTriggersClient + """ + return self._raw_client + + async def list( + self, + project_id: str, + *, + external_user_id: str, + after: typing.Optional[str] = None, + before: typing.Optional[str] = None, + limit: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncPager[DeployedComponent]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + external_user_id : str + Your end user ID, for whom you deployed the trigger + + after : typing.Optional[str] + The cursor to start from for pagination + + before : typing.Optional[str] + The cursor to end before for pagination + + limit : typing.Optional[int] + The maximum number of results to return + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncPager[DeployedComponent] + deployed triggers listed + + Examples + -------- + import asyncio + + from pipedream import AsyncPipedream + + client = AsyncPipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + + + async def main() -> None: + response = await client.deployed_triggers.list( + project_id="project_id", + external_user_id="external_user_id", + ) + async for item in response: + yield item + + # alternatively, you can paginate page-by-page + async for page in response.iter_pages(): + yield page + + + asyncio.run(main()) + """ + return await self._raw_client.list( + project_id, + external_user_id=external_user_id, + after=after, + before=before, + limit=limit, + request_options=request_options, + ) + + async def retrieve( + self, + project_id: str, + trigger_id: str, + *, + external_user_id: str, + request_options: typing.Optional[RequestOptions] = None, + ) -> DeployedComponent: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + trigger_id : str + + external_user_id : str + Your end user ID, for whom you deployed the trigger + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + DeployedComponent + deployed trigger retrieved + + Examples + -------- + import asyncio + + from pipedream import AsyncPipedream + + client = AsyncPipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + + + async def main() -> None: + await client.deployed_triggers.retrieve( + project_id="project_id", + trigger_id="trigger_id", + external_user_id="external_user_id", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.retrieve( + project_id, trigger_id, external_user_id=external_user_id, request_options=request_options + ) + return _response.data + + async def update( + self, + project_id: str, + trigger_id: str, + *, + external_user_id: str, + active: typing.Optional[bool] = OMIT, + configured_props: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, + name: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> DeployedComponent: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + trigger_id : str + + external_user_id : str + The external user ID who owns the trigger + + active : typing.Optional[bool] + Whether the trigger should be active + + configured_props : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] + The configured properties for the trigger + + name : typing.Optional[str] + The name of the trigger + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + DeployedComponent + deployed trigger updated + + Examples + -------- + import asyncio + + from pipedream import AsyncPipedream + + client = AsyncPipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + + + async def main() -> None: + await client.deployed_triggers.update( + project_id="project_id", + trigger_id="trigger_id", + external_user_id="external_user_id", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.update( + project_id, + trigger_id, + external_user_id=external_user_id, + active=active, + configured_props=configured_props, + name=name, + request_options=request_options, + ) + return _response.data + + async def delete( + self, + project_id: str, + trigger_id: str, + *, + external_user_id: str, + ignore_hook_errors: typing.Optional[bool] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> None: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + trigger_id : str + + external_user_id : str + The external user ID who owns the trigger + + ignore_hook_errors : typing.Optional[bool] + Whether to ignore errors during deactivation hook + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + None + + Examples + -------- + import asyncio + + from pipedream import AsyncPipedream + + client = AsyncPipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + + + async def main() -> None: + await client.deployed_triggers.delete( + project_id="project_id", + trigger_id="trigger_id", + external_user_id="external_user_id", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.delete( + project_id, + trigger_id, + external_user_id=external_user_id, + ignore_hook_errors=ignore_hook_errors, + request_options=request_options, + ) + return _response.data + + async def list_events( + self, + project_id: str, + trigger_id: str, + *, + external_user_id: str, + n: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> typing.List[EmittedEvent]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + trigger_id : str + + external_user_id : str + Your end user ID, for whom you deployed the trigger + + n : typing.Optional[int] + The number of events to retrieve (defaults to 20 if not provided) + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.List[EmittedEvent] + trigger events retrieved + + Examples + -------- + import asyncio + + from pipedream import AsyncPipedream + + client = AsyncPipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + + + async def main() -> None: + await client.deployed_triggers.list_events( + project_id="project_id", + trigger_id="trigger_id", + external_user_id="external_user_id", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.list_events( + project_id, trigger_id, external_user_id=external_user_id, n=n, request_options=request_options + ) + return _response.data + + async def list_workflows( + self, + project_id: str, + trigger_id: str, + *, + external_user_id: str, + request_options: typing.Optional[RequestOptions] = None, + ) -> GetTriggerWorkflowsResponse: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + trigger_id : str + + external_user_id : str + The external user ID who owns the trigger + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + GetTriggerWorkflowsResponse + trigger workflows retrieved + + Examples + -------- + import asyncio + + from pipedream import AsyncPipedream + + client = AsyncPipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + + + async def main() -> None: + await client.deployed_triggers.list_workflows( + project_id="project_id", + trigger_id="trigger_id", + external_user_id="external_user_id", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.list_workflows( + project_id, trigger_id, external_user_id=external_user_id, request_options=request_options + ) + return _response.data + + async def update_workflows( + self, + project_id: str, + trigger_id: str, + *, + external_user_id: str, + workflow_ids: typing.Sequence[str], + request_options: typing.Optional[RequestOptions] = None, + ) -> GetTriggerWorkflowsResponse: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + trigger_id : str + + external_user_id : str + The external user ID who owns the trigger + + workflow_ids : typing.Sequence[str] + Array of workflow IDs to set + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + GetTriggerWorkflowsResponse + trigger workflows updated + + Examples + -------- + import asyncio + + from pipedream import AsyncPipedream + + client = AsyncPipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + + + async def main() -> None: + await client.deployed_triggers.update_workflows( + project_id="project_id", + trigger_id="trigger_id", + external_user_id="external_user_id", + workflow_ids=["workflow_ids"], + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.update_workflows( + project_id, + trigger_id, + external_user_id=external_user_id, + workflow_ids=workflow_ids, + request_options=request_options, + ) + return _response.data + + async def list_webhooks( + self, + project_id: str, + trigger_id: str, + *, + external_user_id: str, + request_options: typing.Optional[RequestOptions] = None, + ) -> GetTriggerWebhooksResponse: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + trigger_id : str + + external_user_id : str + The external user ID who owns the trigger + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + GetTriggerWebhooksResponse + trigger webhooks retrieved + + Examples + -------- + import asyncio + + from pipedream import AsyncPipedream + + client = AsyncPipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + + + async def main() -> None: + await client.deployed_triggers.list_webhooks( + project_id="project_id", + trigger_id="trigger_id", + external_user_id="external_user_id", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.list_webhooks( + project_id, trigger_id, external_user_id=external_user_id, request_options=request_options + ) + return _response.data + + async def update_webhooks( + self, + project_id: str, + trigger_id: str, + *, + external_user_id: str, + webhook_urls: typing.Sequence[str], + request_options: typing.Optional[RequestOptions] = None, + ) -> GetTriggerWebhooksResponse: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + trigger_id : str + + external_user_id : str + The external user ID who owns the trigger + + webhook_urls : typing.Sequence[str] + Array of webhook URLs to set + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + GetTriggerWebhooksResponse + trigger webhooks updated + + Examples + -------- + import asyncio + + from pipedream import AsyncPipedream + + client = AsyncPipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + + + async def main() -> None: + await client.deployed_triggers.update_webhooks( + project_id="project_id", + trigger_id="trigger_id", + external_user_id="external_user_id", + webhook_urls=["webhook_urls"], + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.update_webhooks( + project_id, + trigger_id, + external_user_id=external_user_id, + webhook_urls=webhook_urls, + request_options=request_options, + ) + return _response.data diff --git a/src/pipedream/deployed_triggers/raw_client.py b/src/pipedream/deployed_triggers/raw_client.py new file mode 100644 index 0000000..a5c37f2 --- /dev/null +++ b/src/pipedream/deployed_triggers/raw_client.py @@ -0,0 +1,1087 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from json.decoder import JSONDecodeError + +from ..core.api_error import ApiError +from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ..core.http_response import AsyncHttpResponse, HttpResponse +from ..core.jsonable_encoder import jsonable_encoder +from ..core.pagination import AsyncPager, BaseHttpResponse, SyncPager +from ..core.pydantic_utilities import parse_obj_as +from ..core.request_options import RequestOptions +from ..types.deployed_component import DeployedComponent +from ..types.emitted_event import EmittedEvent +from ..types.get_trigger_events_response import GetTriggerEventsResponse +from ..types.get_trigger_response import GetTriggerResponse +from ..types.get_trigger_webhooks_response import GetTriggerWebhooksResponse +from ..types.get_trigger_workflows_response import GetTriggerWorkflowsResponse +from ..types.get_triggers_response import GetTriggersResponse + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class RawDeployedTriggersClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def list( + self, + project_id: str, + *, + external_user_id: str, + after: typing.Optional[str] = None, + before: typing.Optional[str] = None, + limit: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> SyncPager[DeployedComponent]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + external_user_id : str + Your end user ID, for whom you deployed the trigger + + after : typing.Optional[str] + The cursor to start from for pagination + + before : typing.Optional[str] + The cursor to end before for pagination + + limit : typing.Optional[int] + The maximum number of results to return + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + SyncPager[DeployedComponent] + deployed triggers listed + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/deployed-triggers", + method="GET", + params={ + "after": after, + "before": before, + "limit": limit, + "external_user_id": external_user_id, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _parsed_response = typing.cast( + GetTriggersResponse, + parse_obj_as( + type_=GetTriggersResponse, # type: ignore + object_=_response.json(), + ), + ) + _items = _parsed_response.data + _has_next = False + _get_next = None + if _parsed_response.page_info is not None: + _parsed_next = _parsed_response.page_info.end_cursor + _has_next = _parsed_next is not None and _parsed_next != "" + _get_next = lambda: self.list( + project_id, + external_user_id=external_user_id, + after=_parsed_next, + before=before, + limit=limit, + request_options=request_options, + ) + return SyncPager( + has_next=_has_next, items=_items, get_next=_get_next, response=BaseHttpResponse(response=_response) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def retrieve( + self, + project_id: str, + trigger_id: str, + *, + external_user_id: str, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[DeployedComponent]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + trigger_id : str + + external_user_id : str + Your end user ID, for whom you deployed the trigger + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[DeployedComponent] + deployed trigger retrieved + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/deployed-triggers/{jsonable_encoder(trigger_id)}", + method="GET", + params={ + "external_user_id": external_user_id, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _parsed_response = typing.cast( + GetTriggerResponse, + parse_obj_as( + type_=GetTriggerResponse, # type: ignore + object_=_response.json(), + ), + ) + _data = _parsed_response.data + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def update( + self, + project_id: str, + trigger_id: str, + *, + external_user_id: str, + active: typing.Optional[bool] = OMIT, + configured_props: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, + name: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[DeployedComponent]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + trigger_id : str + + external_user_id : str + The external user ID who owns the trigger + + active : typing.Optional[bool] + Whether the trigger should be active + + configured_props : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] + The configured properties for the trigger + + name : typing.Optional[str] + The name of the trigger + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[DeployedComponent] + deployed trigger updated + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/deployed-triggers/{jsonable_encoder(trigger_id)}", + method="PUT", + params={ + "external_user_id": external_user_id, + }, + json={ + "active": active, + "configured_props": configured_props, + "name": name, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _parsed_response = typing.cast( + GetTriggerResponse, + parse_obj_as( + type_=GetTriggerResponse, # type: ignore + object_=_response.json(), + ), + ) + _data = _parsed_response.data + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def delete( + self, + project_id: str, + trigger_id: str, + *, + external_user_id: str, + ignore_hook_errors: typing.Optional[bool] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[None]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + trigger_id : str + + external_user_id : str + The external user ID who owns the trigger + + ignore_hook_errors : typing.Optional[bool] + Whether to ignore errors during deactivation hook + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[None] + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/deployed-triggers/{jsonable_encoder(trigger_id)}", + method="DELETE", + params={ + "external_user_id": external_user_id, + "ignore_hook_errors": ignore_hook_errors, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return HttpResponse(response=_response, data=None) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def list_events( + self, + project_id: str, + trigger_id: str, + *, + external_user_id: str, + n: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[typing.List[EmittedEvent]]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + trigger_id : str + + external_user_id : str + Your end user ID, for whom you deployed the trigger + + n : typing.Optional[int] + The number of events to retrieve (defaults to 20 if not provided) + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.List[EmittedEvent]] + trigger events retrieved + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/deployed-triggers/{jsonable_encoder(trigger_id)}/events", + method="GET", + params={ + "external_user_id": external_user_id, + "n": n, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _parsed_response = typing.cast( + GetTriggerEventsResponse, + parse_obj_as( + type_=GetTriggerEventsResponse, # type: ignore + object_=_response.json(), + ), + ) + _data = _parsed_response.data + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def list_workflows( + self, + project_id: str, + trigger_id: str, + *, + external_user_id: str, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[GetTriggerWorkflowsResponse]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + trigger_id : str + + external_user_id : str + The external user ID who owns the trigger + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[GetTriggerWorkflowsResponse] + trigger workflows retrieved + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/deployed-triggers/{jsonable_encoder(trigger_id)}/pipelines", + method="GET", + params={ + "external_user_id": external_user_id, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + GetTriggerWorkflowsResponse, + parse_obj_as( + type_=GetTriggerWorkflowsResponse, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def update_workflows( + self, + project_id: str, + trigger_id: str, + *, + external_user_id: str, + workflow_ids: typing.Sequence[str], + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[GetTriggerWorkflowsResponse]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + trigger_id : str + + external_user_id : str + The external user ID who owns the trigger + + workflow_ids : typing.Sequence[str] + Array of workflow IDs to set + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[GetTriggerWorkflowsResponse] + trigger workflows updated + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/deployed-triggers/{jsonable_encoder(trigger_id)}/pipelines", + method="PUT", + params={ + "external_user_id": external_user_id, + }, + json={ + "workflow_ids": workflow_ids, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + GetTriggerWorkflowsResponse, + parse_obj_as( + type_=GetTriggerWorkflowsResponse, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def list_webhooks( + self, + project_id: str, + trigger_id: str, + *, + external_user_id: str, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[GetTriggerWebhooksResponse]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + trigger_id : str + + external_user_id : str + The external user ID who owns the trigger + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[GetTriggerWebhooksResponse] + trigger webhooks retrieved + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/deployed-triggers/{jsonable_encoder(trigger_id)}/webhooks", + method="GET", + params={ + "external_user_id": external_user_id, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + GetTriggerWebhooksResponse, + parse_obj_as( + type_=GetTriggerWebhooksResponse, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def update_webhooks( + self, + project_id: str, + trigger_id: str, + *, + external_user_id: str, + webhook_urls: typing.Sequence[str], + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[GetTriggerWebhooksResponse]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + trigger_id : str + + external_user_id : str + The external user ID who owns the trigger + + webhook_urls : typing.Sequence[str] + Array of webhook URLs to set + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[GetTriggerWebhooksResponse] + trigger webhooks updated + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/deployed-triggers/{jsonable_encoder(trigger_id)}/webhooks", + method="PUT", + params={ + "external_user_id": external_user_id, + }, + json={ + "webhook_urls": webhook_urls, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + GetTriggerWebhooksResponse, + parse_obj_as( + type_=GetTriggerWebhooksResponse, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + +class AsyncRawDeployedTriggersClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def list( + self, + project_id: str, + *, + external_user_id: str, + after: typing.Optional[str] = None, + before: typing.Optional[str] = None, + limit: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncPager[DeployedComponent]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + external_user_id : str + Your end user ID, for whom you deployed the trigger + + after : typing.Optional[str] + The cursor to start from for pagination + + before : typing.Optional[str] + The cursor to end before for pagination + + limit : typing.Optional[int] + The maximum number of results to return + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncPager[DeployedComponent] + deployed triggers listed + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/deployed-triggers", + method="GET", + params={ + "after": after, + "before": before, + "limit": limit, + "external_user_id": external_user_id, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _parsed_response = typing.cast( + GetTriggersResponse, + parse_obj_as( + type_=GetTriggersResponse, # type: ignore + object_=_response.json(), + ), + ) + _items = _parsed_response.data + _has_next = False + _get_next = None + if _parsed_response.page_info is not None: + _parsed_next = _parsed_response.page_info.end_cursor + _has_next = _parsed_next is not None and _parsed_next != "" + + async def _get_next(): + return await self.list( + project_id, + external_user_id=external_user_id, + after=_parsed_next, + before=before, + limit=limit, + request_options=request_options, + ) + + return AsyncPager( + has_next=_has_next, items=_items, get_next=_get_next, response=BaseHttpResponse(response=_response) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def retrieve( + self, + project_id: str, + trigger_id: str, + *, + external_user_id: str, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[DeployedComponent]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + trigger_id : str + + external_user_id : str + Your end user ID, for whom you deployed the trigger + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[DeployedComponent] + deployed trigger retrieved + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/deployed-triggers/{jsonable_encoder(trigger_id)}", + method="GET", + params={ + "external_user_id": external_user_id, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _parsed_response = typing.cast( + GetTriggerResponse, + parse_obj_as( + type_=GetTriggerResponse, # type: ignore + object_=_response.json(), + ), + ) + _data = _parsed_response.data + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def update( + self, + project_id: str, + trigger_id: str, + *, + external_user_id: str, + active: typing.Optional[bool] = OMIT, + configured_props: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, + name: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[DeployedComponent]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + trigger_id : str + + external_user_id : str + The external user ID who owns the trigger + + active : typing.Optional[bool] + Whether the trigger should be active + + configured_props : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] + The configured properties for the trigger + + name : typing.Optional[str] + The name of the trigger + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[DeployedComponent] + deployed trigger updated + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/deployed-triggers/{jsonable_encoder(trigger_id)}", + method="PUT", + params={ + "external_user_id": external_user_id, + }, + json={ + "active": active, + "configured_props": configured_props, + "name": name, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _parsed_response = typing.cast( + GetTriggerResponse, + parse_obj_as( + type_=GetTriggerResponse, # type: ignore + object_=_response.json(), + ), + ) + _data = _parsed_response.data + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def delete( + self, + project_id: str, + trigger_id: str, + *, + external_user_id: str, + ignore_hook_errors: typing.Optional[bool] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[None]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + trigger_id : str + + external_user_id : str + The external user ID who owns the trigger + + ignore_hook_errors : typing.Optional[bool] + Whether to ignore errors during deactivation hook + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[None] + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/deployed-triggers/{jsonable_encoder(trigger_id)}", + method="DELETE", + params={ + "external_user_id": external_user_id, + "ignore_hook_errors": ignore_hook_errors, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return AsyncHttpResponse(response=_response, data=None) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def list_events( + self, + project_id: str, + trigger_id: str, + *, + external_user_id: str, + n: typing.Optional[int] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[typing.List[EmittedEvent]]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + trigger_id : str + + external_user_id : str + Your end user ID, for whom you deployed the trigger + + n : typing.Optional[int] + The number of events to retrieve (defaults to 20 if not provided) + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.List[EmittedEvent]] + trigger events retrieved + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/deployed-triggers/{jsonable_encoder(trigger_id)}/events", + method="GET", + params={ + "external_user_id": external_user_id, + "n": n, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _parsed_response = typing.cast( + GetTriggerEventsResponse, + parse_obj_as( + type_=GetTriggerEventsResponse, # type: ignore + object_=_response.json(), + ), + ) + _data = _parsed_response.data + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def list_workflows( + self, + project_id: str, + trigger_id: str, + *, + external_user_id: str, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[GetTriggerWorkflowsResponse]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + trigger_id : str + + external_user_id : str + The external user ID who owns the trigger + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[GetTriggerWorkflowsResponse] + trigger workflows retrieved + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/deployed-triggers/{jsonable_encoder(trigger_id)}/pipelines", + method="GET", + params={ + "external_user_id": external_user_id, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + GetTriggerWorkflowsResponse, + parse_obj_as( + type_=GetTriggerWorkflowsResponse, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def update_workflows( + self, + project_id: str, + trigger_id: str, + *, + external_user_id: str, + workflow_ids: typing.Sequence[str], + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[GetTriggerWorkflowsResponse]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + trigger_id : str + + external_user_id : str + The external user ID who owns the trigger + + workflow_ids : typing.Sequence[str] + Array of workflow IDs to set + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[GetTriggerWorkflowsResponse] + trigger workflows updated + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/deployed-triggers/{jsonable_encoder(trigger_id)}/pipelines", + method="PUT", + params={ + "external_user_id": external_user_id, + }, + json={ + "workflow_ids": workflow_ids, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + GetTriggerWorkflowsResponse, + parse_obj_as( + type_=GetTriggerWorkflowsResponse, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def list_webhooks( + self, + project_id: str, + trigger_id: str, + *, + external_user_id: str, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[GetTriggerWebhooksResponse]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + trigger_id : str + + external_user_id : str + The external user ID who owns the trigger + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[GetTriggerWebhooksResponse] + trigger webhooks retrieved + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/deployed-triggers/{jsonable_encoder(trigger_id)}/webhooks", + method="GET", + params={ + "external_user_id": external_user_id, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + GetTriggerWebhooksResponse, + parse_obj_as( + type_=GetTriggerWebhooksResponse, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def update_webhooks( + self, + project_id: str, + trigger_id: str, + *, + external_user_id: str, + webhook_urls: typing.Sequence[str], + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[GetTriggerWebhooksResponse]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + trigger_id : str + + external_user_id : str + The external user ID who owns the trigger + + webhook_urls : typing.Sequence[str] + Array of webhook URLs to set + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[GetTriggerWebhooksResponse] + trigger webhooks updated + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/deployed-triggers/{jsonable_encoder(trigger_id)}/webhooks", + method="PUT", + params={ + "external_user_id": external_user_id, + }, + json={ + "webhook_urls": webhook_urls, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + GetTriggerWebhooksResponse, + parse_obj_as( + type_=GetTriggerWebhooksResponse, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/pipedream/environment.py b/src/pipedream/environment.py new file mode 100644 index 0000000..cbafba5 --- /dev/null +++ b/src/pipedream/environment.py @@ -0,0 +1,9 @@ +# This file was auto-generated by Fern from our API Definition. + +import enum + + +class PipedreamEnvironment(enum.Enum): + CANARY = "https://api2.pipedream.com" + DEV = "https://api.${DEV_NAMESPACE}.gkes.pipedream.net" + PROD = "https://api.pipedream.com" diff --git a/src/pipedream/oauth_tokens/__init__.py b/src/pipedream/oauth_tokens/__init__.py new file mode 100644 index 0000000..5cde020 --- /dev/null +++ b/src/pipedream/oauth_tokens/__init__.py @@ -0,0 +1,4 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + diff --git a/src/pipedream/oauth_tokens/client.py b/src/pipedream/oauth_tokens/client.py new file mode 100644 index 0000000..8342b20 --- /dev/null +++ b/src/pipedream/oauth_tokens/client.py @@ -0,0 +1,125 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ..core.request_options import RequestOptions +from ..types.create_o_auth_token_response import CreateOAuthTokenResponse +from .raw_client import AsyncRawOauthTokensClient, RawOauthTokensClient + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class OauthTokensClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._raw_client = RawOauthTokensClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawOauthTokensClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawOauthTokensClient + """ + return self._raw_client + + def create( + self, *, client_id: str, client_secret: str, request_options: typing.Optional[RequestOptions] = None + ) -> CreateOAuthTokenResponse: + """ + Parameters + ---------- + client_id : str + + client_secret : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + CreateOAuthTokenResponse + token created + + Examples + -------- + from pipedream import Pipedream + + client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + client.oauth_tokens.create( + client_id="client_id", + client_secret="client_secret", + ) + """ + _response = self._raw_client.create( + client_id=client_id, client_secret=client_secret, request_options=request_options + ) + return _response.data + + +class AsyncOauthTokensClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._raw_client = AsyncRawOauthTokensClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawOauthTokensClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawOauthTokensClient + """ + return self._raw_client + + async def create( + self, *, client_id: str, client_secret: str, request_options: typing.Optional[RequestOptions] = None + ) -> CreateOAuthTokenResponse: + """ + Parameters + ---------- + client_id : str + + client_secret : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + CreateOAuthTokenResponse + token created + + Examples + -------- + import asyncio + + from pipedream import AsyncPipedream + + client = AsyncPipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + + + async def main() -> None: + await client.oauth_tokens.create( + client_id="client_id", + client_secret="client_secret", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.create( + client_id=client_id, client_secret=client_secret, request_options=request_options + ) + return _response.data diff --git a/src/pipedream/oauth_tokens/raw_client.py b/src/pipedream/oauth_tokens/raw_client.py new file mode 100644 index 0000000..7ce3d55 --- /dev/null +++ b/src/pipedream/oauth_tokens/raw_client.py @@ -0,0 +1,118 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from json.decoder import JSONDecodeError + +from ..core.api_error import ApiError +from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ..core.http_response import AsyncHttpResponse, HttpResponse +from ..core.pydantic_utilities import parse_obj_as +from ..core.request_options import RequestOptions +from ..types.create_o_auth_token_response import CreateOAuthTokenResponse + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class RawOauthTokensClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def create( + self, *, client_id: str, client_secret: str, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[CreateOAuthTokenResponse]: + """ + Parameters + ---------- + client_id : str + + client_secret : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[CreateOAuthTokenResponse] + token created + """ + _response = self._client_wrapper.httpx_client.request( + "v1/oauth/token", + method="POST", + json={ + "client_id": client_id, + "client_secret": client_secret, + "grant_type": "client_credentials", + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + CreateOAuthTokenResponse, + parse_obj_as( + type_=CreateOAuthTokenResponse, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + +class AsyncRawOauthTokensClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def create( + self, *, client_id: str, client_secret: str, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[CreateOAuthTokenResponse]: + """ + Parameters + ---------- + client_id : str + + client_secret : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[CreateOAuthTokenResponse] + token created + """ + _response = await self._client_wrapper.httpx_client.request( + "v1/oauth/token", + method="POST", + json={ + "client_id": client_id, + "client_secret": client_secret, + "grant_type": "client_credentials", + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + CreateOAuthTokenResponse, + parse_obj_as( + type_=CreateOAuthTokenResponse, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/pipedream/projects/__init__.py b/src/pipedream/projects/__init__.py new file mode 100644 index 0000000..5cde020 --- /dev/null +++ b/src/pipedream/projects/__init__.py @@ -0,0 +1,4 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + diff --git a/src/pipedream/projects/client.py b/src/pipedream/projects/client.py new file mode 100644 index 0000000..510cfa6 --- /dev/null +++ b/src/pipedream/projects/client.py @@ -0,0 +1,114 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ..core.request_options import RequestOptions +from ..types.project_info_response import ProjectInfoResponse +from .raw_client import AsyncRawProjectsClient, RawProjectsClient + + +class ProjectsClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._raw_client = RawProjectsClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawProjectsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawProjectsClient + """ + return self._raw_client + + def retrieve_info( + self, project_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> ProjectInfoResponse: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ProjectInfoResponse + project info retrieved + + Examples + -------- + from pipedream import Pipedream + + client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + client.projects.retrieve_info( + project_id="project_id", + ) + """ + _response = self._raw_client.retrieve_info(project_id, request_options=request_options) + return _response.data + + +class AsyncProjectsClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._raw_client = AsyncRawProjectsClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawProjectsClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawProjectsClient + """ + return self._raw_client + + async def retrieve_info( + self, project_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> ProjectInfoResponse: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ProjectInfoResponse + project info retrieved + + Examples + -------- + import asyncio + + from pipedream import AsyncPipedream + + client = AsyncPipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + + + async def main() -> None: + await client.projects.retrieve_info( + project_id="project_id", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.retrieve_info(project_id, request_options=request_options) + return _response.data diff --git a/src/pipedream/projects/raw_client.py b/src/pipedream/projects/raw_client.py new file mode 100644 index 0000000..c4e468b --- /dev/null +++ b/src/pipedream/projects/raw_client.py @@ -0,0 +1,96 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from json.decoder import JSONDecodeError + +from ..core.api_error import ApiError +from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ..core.http_response import AsyncHttpResponse, HttpResponse +from ..core.jsonable_encoder import jsonable_encoder +from ..core.pydantic_utilities import parse_obj_as +from ..core.request_options import RequestOptions +from ..types.project_info_response import ProjectInfoResponse + + +class RawProjectsClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def retrieve_info( + self, project_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[ProjectInfoResponse]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[ProjectInfoResponse] + project info retrieved + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/projects/info", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ProjectInfoResponse, + parse_obj_as( + type_=ProjectInfoResponse, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + +class AsyncRawProjectsClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def retrieve_info( + self, project_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[ProjectInfoResponse]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[ProjectInfoResponse] + project info retrieved + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/projects/info", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ProjectInfoResponse, + parse_obj_as( + type_=ProjectInfoResponse, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/pipedream/proxy/__init__.py b/src/pipedream/proxy/__init__.py new file mode 100644 index 0000000..5cde020 --- /dev/null +++ b/src/pipedream/proxy/__init__.py @@ -0,0 +1,4 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + diff --git a/src/pipedream/proxy/client.py b/src/pipedream/proxy/client.py new file mode 100644 index 0000000..0050c22 --- /dev/null +++ b/src/pipedream/proxy/client.py @@ -0,0 +1,682 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ..core.request_options import RequestOptions +from .raw_client import AsyncRawProxyClient, RawProxyClient + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class ProxyClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._raw_client = RawProxyClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawProxyClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawProxyClient + """ + return self._raw_client + + def get( + self, + project_id: str, + url_64: str, + *, + external_user_id: str, + account_id: str, + request_options: typing.Optional[RequestOptions] = None, + ) -> typing.Dict[str, typing.Optional[typing.Any]]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + 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. + + Returns + ------- + typing.Dict[str, typing.Optional[typing.Any]] + proxy request successful + + Examples + -------- + from pipedream import Pipedream + + client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + client.proxy.get( + project_id="project_id", + url_64="url_64", + external_user_id="external_user_id", + account_id="account_id", + ) + """ + _response = self._raw_client.get( + project_id, + url_64, + external_user_id=external_user_id, + account_id=account_id, + request_options=request_options, + ) + return _response.data + + def post( + self, + project_id: str, + 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.Dict[str, typing.Optional[typing.Any]]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + 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.Optional[typing.Any]] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Optional[typing.Any]] + proxy request successful + + Examples + -------- + from pipedream import Pipedream + + client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + client.proxy.post( + project_id="project_id", + url_64="url_64", + external_user_id="external_user_id", + account_id="account_id", + request={"key": "value"}, + ) + """ + _response = self._raw_client.post( + project_id, + url_64, + external_user_id=external_user_id, + account_id=account_id, + request=request, + request_options=request_options, + ) + return _response.data + + def put( + self, + project_id: str, + 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.Dict[str, typing.Optional[typing.Any]]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + 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.Optional[typing.Any]] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Optional[typing.Any]] + proxy request successful + + Examples + -------- + from pipedream import Pipedream + + client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + client.proxy.put( + project_id="project_id", + url_64="url_64", + external_user_id="external_user_id", + account_id="account_id", + request={"key": "value"}, + ) + """ + _response = self._raw_client.put( + project_id, + url_64, + external_user_id=external_user_id, + account_id=account_id, + request=request, + request_options=request_options, + ) + return _response.data + + def delete( + self, + project_id: str, + url_64: str, + *, + external_user_id: str, + account_id: str, + request_options: typing.Optional[RequestOptions] = None, + ) -> typing.Dict[str, typing.Optional[typing.Any]]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + 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. + + Returns + ------- + typing.Dict[str, typing.Optional[typing.Any]] + proxy request successful + + Examples + -------- + from pipedream import Pipedream + + client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + client.proxy.delete( + project_id="project_id", + url_64="url_64", + external_user_id="external_user_id", + account_id="account_id", + ) + """ + _response = self._raw_client.delete( + project_id, + url_64, + external_user_id=external_user_id, + account_id=account_id, + request_options=request_options, + ) + return _response.data + + def patch( + self, + project_id: str, + 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.Dict[str, typing.Optional[typing.Any]]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + 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.Optional[typing.Any]] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Optional[typing.Any]] + proxy request successful + + Examples + -------- + from pipedream import Pipedream + + client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + client.proxy.patch( + project_id="project_id", + url_64="url_64", + external_user_id="external_user_id", + account_id="account_id", + request={"key": "value"}, + ) + """ + _response = self._raw_client.patch( + project_id, + url_64, + external_user_id=external_user_id, + account_id=account_id, + request=request, + request_options=request_options, + ) + return _response.data + + +class AsyncProxyClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._raw_client = AsyncRawProxyClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawProxyClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawProxyClient + """ + return self._raw_client + + async def get( + self, + project_id: str, + url_64: str, + *, + external_user_id: str, + account_id: str, + request_options: typing.Optional[RequestOptions] = None, + ) -> typing.Dict[str, typing.Optional[typing.Any]]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + 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. + + Returns + ------- + typing.Dict[str, typing.Optional[typing.Any]] + proxy request successful + + Examples + -------- + import asyncio + + from pipedream import AsyncPipedream + + client = AsyncPipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + + + async def main() -> None: + await client.proxy.get( + project_id="project_id", + url_64="url_64", + external_user_id="external_user_id", + account_id="account_id", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.get( + project_id, + url_64, + external_user_id=external_user_id, + account_id=account_id, + request_options=request_options, + ) + return _response.data + + async def post( + self, + project_id: str, + 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.Dict[str, typing.Optional[typing.Any]]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + 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.Optional[typing.Any]] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Optional[typing.Any]] + proxy request successful + + Examples + -------- + import asyncio + + from pipedream import AsyncPipedream + + client = AsyncPipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + + + async def main() -> None: + await client.proxy.post( + project_id="project_id", + url_64="url_64", + external_user_id="external_user_id", + account_id="account_id", + request={"key": "value"}, + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.post( + project_id, + url_64, + external_user_id=external_user_id, + account_id=account_id, + request=request, + request_options=request_options, + ) + return _response.data + + async def put( + self, + project_id: str, + 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.Dict[str, typing.Optional[typing.Any]]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + 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.Optional[typing.Any]] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Optional[typing.Any]] + proxy request successful + + Examples + -------- + import asyncio + + from pipedream import AsyncPipedream + + client = AsyncPipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + + + async def main() -> None: + await client.proxy.put( + project_id="project_id", + url_64="url_64", + external_user_id="external_user_id", + account_id="account_id", + request={"key": "value"}, + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.put( + project_id, + url_64, + external_user_id=external_user_id, + account_id=account_id, + request=request, + request_options=request_options, + ) + return _response.data + + async def delete( + self, + project_id: str, + url_64: str, + *, + external_user_id: str, + account_id: str, + request_options: typing.Optional[RequestOptions] = None, + ) -> typing.Dict[str, typing.Optional[typing.Any]]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + 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. + + Returns + ------- + typing.Dict[str, typing.Optional[typing.Any]] + proxy request successful + + Examples + -------- + import asyncio + + from pipedream import AsyncPipedream + + client = AsyncPipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + + + async def main() -> None: + await client.proxy.delete( + project_id="project_id", + url_64="url_64", + external_user_id="external_user_id", + account_id="account_id", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.delete( + project_id, + url_64, + external_user_id=external_user_id, + account_id=account_id, + request_options=request_options, + ) + return _response.data + + async def patch( + self, + project_id: str, + 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.Dict[str, typing.Optional[typing.Any]]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + 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.Optional[typing.Any]] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + typing.Dict[str, typing.Optional[typing.Any]] + proxy request successful + + Examples + -------- + import asyncio + + from pipedream import AsyncPipedream + + client = AsyncPipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + + + async def main() -> None: + await client.proxy.patch( + project_id="project_id", + url_64="url_64", + external_user_id="external_user_id", + account_id="account_id", + request={"key": "value"}, + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.patch( + project_id, + url_64, + external_user_id=external_user_id, + account_id=account_id, + request=request, + request_options=request_options, + ) + return _response.data diff --git a/src/pipedream/proxy/raw_client.py b/src/pipedream/proxy/raw_client.py new file mode 100644 index 0000000..f82002a --- /dev/null +++ b/src/pipedream/proxy/raw_client.py @@ -0,0 +1,632 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from json.decoder import JSONDecodeError + +from ..core.api_error import ApiError +from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ..core.http_response import AsyncHttpResponse, HttpResponse +from ..core.jsonable_encoder import jsonable_encoder +from ..core.pydantic_utilities import parse_obj_as +from ..core.request_options import RequestOptions + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class RawProxyClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def get( + self, + project_id: str, + url_64: str, + *, + external_user_id: str, + account_id: str, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[typing.Dict[str, typing.Optional[typing.Any]]]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + 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. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Optional[typing.Any]]] + proxy request successful + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/proxy/{jsonable_encoder(url_64)}", + method="GET", + params={ + "external_user_id": external_user_id, + "account_id": account_id, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Optional[typing.Any]], + parse_obj_as( + type_=typing.Dict[str, typing.Optional[typing.Any]], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def post( + self, + project_id: str, + url_64: str, + *, + external_user_id: str, + account_id: str, + request: typing.Dict[str, typing.Optional[typing.Any]], + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[typing.Dict[str, typing.Optional[typing.Any]]]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + 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.Optional[typing.Any]] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Optional[typing.Any]]] + proxy request successful + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/proxy/{jsonable_encoder(url_64)}", + method="POST", + params={ + "external_user_id": external_user_id, + "account_id": account_id, + }, + json=request, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Optional[typing.Any]], + parse_obj_as( + type_=typing.Dict[str, typing.Optional[typing.Any]], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def put( + self, + project_id: str, + url_64: str, + *, + external_user_id: str, + account_id: str, + request: typing.Dict[str, typing.Optional[typing.Any]], + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[typing.Dict[str, typing.Optional[typing.Any]]]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + 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.Optional[typing.Any]] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Optional[typing.Any]]] + proxy request successful + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/proxy/{jsonable_encoder(url_64)}", + method="PUT", + params={ + "external_user_id": external_user_id, + "account_id": account_id, + }, + json=request, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Optional[typing.Any]], + parse_obj_as( + type_=typing.Dict[str, typing.Optional[typing.Any]], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def delete( + self, + project_id: str, + url_64: str, + *, + external_user_id: str, + account_id: str, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[typing.Dict[str, typing.Optional[typing.Any]]]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + 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. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Optional[typing.Any]]] + proxy request successful + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/proxy/{jsonable_encoder(url_64)}", + method="DELETE", + params={ + "external_user_id": external_user_id, + "account_id": account_id, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Optional[typing.Any]], + parse_obj_as( + type_=typing.Dict[str, typing.Optional[typing.Any]], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def patch( + self, + project_id: str, + url_64: str, + *, + external_user_id: str, + account_id: str, + request: typing.Dict[str, typing.Optional[typing.Any]], + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[typing.Dict[str, typing.Optional[typing.Any]]]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + 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.Optional[typing.Any]] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[typing.Dict[str, typing.Optional[typing.Any]]] + proxy request successful + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/proxy/{jsonable_encoder(url_64)}", + 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, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Optional[typing.Any]], + parse_obj_as( + type_=typing.Dict[str, typing.Optional[typing.Any]], # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + +class AsyncRawProxyClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def get( + self, + project_id: str, + url_64: str, + *, + external_user_id: str, + account_id: str, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[typing.Dict[str, typing.Optional[typing.Any]]]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + 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. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Optional[typing.Any]]] + proxy request successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/proxy/{jsonable_encoder(url_64)}", + method="GET", + params={ + "external_user_id": external_user_id, + "account_id": account_id, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Optional[typing.Any]], + parse_obj_as( + type_=typing.Dict[str, typing.Optional[typing.Any]], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def post( + self, + project_id: str, + url_64: str, + *, + external_user_id: str, + account_id: str, + request: typing.Dict[str, typing.Optional[typing.Any]], + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[typing.Dict[str, typing.Optional[typing.Any]]]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + 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.Optional[typing.Any]] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Optional[typing.Any]]] + proxy request successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/proxy/{jsonable_encoder(url_64)}", + method="POST", + params={ + "external_user_id": external_user_id, + "account_id": account_id, + }, + json=request, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Optional[typing.Any]], + parse_obj_as( + type_=typing.Dict[str, typing.Optional[typing.Any]], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def put( + self, + project_id: str, + url_64: str, + *, + external_user_id: str, + account_id: str, + request: typing.Dict[str, typing.Optional[typing.Any]], + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[typing.Dict[str, typing.Optional[typing.Any]]]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + 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.Optional[typing.Any]] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Optional[typing.Any]]] + proxy request successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/proxy/{jsonable_encoder(url_64)}", + method="PUT", + params={ + "external_user_id": external_user_id, + "account_id": account_id, + }, + json=request, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Optional[typing.Any]], + parse_obj_as( + type_=typing.Dict[str, typing.Optional[typing.Any]], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def delete( + self, + project_id: str, + url_64: str, + *, + external_user_id: str, + account_id: str, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[typing.Dict[str, typing.Optional[typing.Any]]]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + 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. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Optional[typing.Any]]] + proxy request successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/proxy/{jsonable_encoder(url_64)}", + method="DELETE", + params={ + "external_user_id": external_user_id, + "account_id": account_id, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Optional[typing.Any]], + parse_obj_as( + type_=typing.Dict[str, typing.Optional[typing.Any]], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def patch( + self, + project_id: str, + url_64: str, + *, + external_user_id: str, + account_id: str, + request: typing.Dict[str, typing.Optional[typing.Any]], + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[typing.Dict[str, typing.Optional[typing.Any]]]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + 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.Optional[typing.Any]] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[typing.Dict[str, typing.Optional[typing.Any]]] + proxy request successful + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/proxy/{jsonable_encoder(url_64)}", + 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, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + typing.Dict[str, typing.Optional[typing.Any]], + parse_obj_as( + type_=typing.Dict[str, typing.Optional[typing.Any]], # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/pipedream/py.typed b/src/pipedream/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/src/pipedream/tokens/__init__.py b/src/pipedream/tokens/__init__.py new file mode 100644 index 0000000..5cde020 --- /dev/null +++ b/src/pipedream/tokens/__init__.py @@ -0,0 +1,4 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + diff --git a/src/pipedream/tokens/client.py b/src/pipedream/tokens/client.py new file mode 100644 index 0000000..badcc92 --- /dev/null +++ b/src/pipedream/tokens/client.py @@ -0,0 +1,267 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ..core.request_options import RequestOptions +from ..types.create_token_response import CreateTokenResponse +from ..types.validate_token_params import ValidateTokenParams +from ..types.validate_token_response import ValidateTokenResponse +from .raw_client import AsyncRawTokensClient, RawTokensClient + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class TokensClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._raw_client = RawTokensClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawTokensClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawTokensClient + """ + return self._raw_client + + def create( + self, + *, + external_user_id: str, + project_id: str, + allowed_origins: typing.Optional[typing.Sequence[str]] = OMIT, + error_redirect_uri: typing.Optional[str] = OMIT, + success_redirect_uri: typing.Optional[str] = OMIT, + webhook_uri: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> CreateTokenResponse: + """ + Parameters + ---------- + external_user_id : str + Your end user ID, for whom you're creating the token + + project_id : str + The ID of the project + + allowed_origins : typing.Optional[typing.Sequence[str]] + List of allowed origins for CORS + + error_redirect_uri : typing.Optional[str] + URI to redirect to on error + + success_redirect_uri : typing.Optional[str] + URI to redirect to on success + + webhook_uri : typing.Optional[str] + Webhook URI for notifications + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + CreateTokenResponse + connect token created + + Examples + -------- + from pipedream import Pipedream + + client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + client.tokens.create( + external_user_id="external_user_id", + project_id="project_id", + ) + """ + _response = self._raw_client.create( + external_user_id=external_user_id, + project_id=project_id, + allowed_origins=allowed_origins, + error_redirect_uri=error_redirect_uri, + success_redirect_uri=success_redirect_uri, + webhook_uri=webhook_uri, + request_options=request_options, + ) + return _response.data + + def validate( + self, + ctok: str, + *, + params: typing.Optional[ValidateTokenParams] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> ValidateTokenResponse: + """ + Parameters + ---------- + ctok : str + + params : typing.Optional[ValidateTokenParams] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ValidateTokenResponse + connect token validated + + Examples + -------- + from pipedream import Pipedream + + client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + client.tokens.validate( + ctok="ctok", + ) + """ + _response = self._raw_client.validate(ctok, params=params, request_options=request_options) + return _response.data + + +class AsyncTokensClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._raw_client = AsyncRawTokensClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawTokensClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawTokensClient + """ + return self._raw_client + + async def create( + self, + *, + external_user_id: str, + project_id: str, + allowed_origins: typing.Optional[typing.Sequence[str]] = OMIT, + error_redirect_uri: typing.Optional[str] = OMIT, + success_redirect_uri: typing.Optional[str] = OMIT, + webhook_uri: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> CreateTokenResponse: + """ + Parameters + ---------- + external_user_id : str + Your end user ID, for whom you're creating the token + + project_id : str + The ID of the project + + allowed_origins : typing.Optional[typing.Sequence[str]] + List of allowed origins for CORS + + error_redirect_uri : typing.Optional[str] + URI to redirect to on error + + success_redirect_uri : typing.Optional[str] + URI to redirect to on success + + webhook_uri : typing.Optional[str] + Webhook URI for notifications + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + CreateTokenResponse + connect token created + + Examples + -------- + import asyncio + + from pipedream import AsyncPipedream + + client = AsyncPipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + + + async def main() -> None: + await client.tokens.create( + external_user_id="external_user_id", + project_id="project_id", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.create( + external_user_id=external_user_id, + project_id=project_id, + allowed_origins=allowed_origins, + error_redirect_uri=error_redirect_uri, + success_redirect_uri=success_redirect_uri, + webhook_uri=webhook_uri, + request_options=request_options, + ) + return _response.data + + async def validate( + self, + ctok: str, + *, + params: typing.Optional[ValidateTokenParams] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> ValidateTokenResponse: + """ + Parameters + ---------- + ctok : str + + params : typing.Optional[ValidateTokenParams] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ValidateTokenResponse + connect token validated + + Examples + -------- + import asyncio + + from pipedream import AsyncPipedream + + client = AsyncPipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + + + async def main() -> None: + await client.tokens.validate( + ctok="ctok", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.validate(ctok, params=params, request_options=request_options) + return _response.data diff --git a/src/pipedream/tokens/raw_client.py b/src/pipedream/tokens/raw_client.py new file mode 100644 index 0000000..747b454 --- /dev/null +++ b/src/pipedream/tokens/raw_client.py @@ -0,0 +1,266 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from json.decoder import JSONDecodeError + +from ..core.api_error import ApiError +from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ..core.http_response import AsyncHttpResponse, HttpResponse +from ..core.jsonable_encoder import jsonable_encoder +from ..core.pydantic_utilities import parse_obj_as +from ..core.request_options import RequestOptions +from ..core.serialization import convert_and_respect_annotation_metadata +from ..types.create_token_response import CreateTokenResponse +from ..types.validate_token_params import ValidateTokenParams +from ..types.validate_token_response import ValidateTokenResponse + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class RawTokensClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def create( + self, + *, + external_user_id: str, + project_id: str, + allowed_origins: typing.Optional[typing.Sequence[str]] = OMIT, + error_redirect_uri: typing.Optional[str] = OMIT, + success_redirect_uri: typing.Optional[str] = OMIT, + webhook_uri: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[CreateTokenResponse]: + """ + Parameters + ---------- + external_user_id : str + Your end user ID, for whom you're creating the token + + project_id : str + The ID of the project + + allowed_origins : typing.Optional[typing.Sequence[str]] + List of allowed origins for CORS + + error_redirect_uri : typing.Optional[str] + URI to redirect to on error + + success_redirect_uri : typing.Optional[str] + URI to redirect to on success + + webhook_uri : typing.Optional[str] + Webhook URI for notifications + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[CreateTokenResponse] + connect token created + """ + _response = self._client_wrapper.httpx_client.request( + "v1/connect/tokens", + method="POST", + json={ + "allowed_origins": allowed_origins, + "error_redirect_uri": error_redirect_uri, + "external_user_id": external_user_id, + "project_id": project_id, + "success_redirect_uri": success_redirect_uri, + "webhook_uri": webhook_uri, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + CreateTokenResponse, + parse_obj_as( + type_=CreateTokenResponse, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def validate( + self, + ctok: str, + *, + params: typing.Optional[ValidateTokenParams] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[ValidateTokenResponse]: + """ + Parameters + ---------- + ctok : str + + params : typing.Optional[ValidateTokenParams] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[ValidateTokenResponse] + connect token validated + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/connect/tokens/{jsonable_encoder(ctok)}/validate", + method="GET", + params={ + "params": convert_and_respect_annotation_metadata( + object_=params, annotation=ValidateTokenParams, direction="write" + ), + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ValidateTokenResponse, + parse_obj_as( + type_=ValidateTokenResponse, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + +class AsyncRawTokensClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def create( + self, + *, + external_user_id: str, + project_id: str, + allowed_origins: typing.Optional[typing.Sequence[str]] = OMIT, + error_redirect_uri: typing.Optional[str] = OMIT, + success_redirect_uri: typing.Optional[str] = OMIT, + webhook_uri: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[CreateTokenResponse]: + """ + Parameters + ---------- + external_user_id : str + Your end user ID, for whom you're creating the token + + project_id : str + The ID of the project + + allowed_origins : typing.Optional[typing.Sequence[str]] + List of allowed origins for CORS + + error_redirect_uri : typing.Optional[str] + URI to redirect to on error + + success_redirect_uri : typing.Optional[str] + URI to redirect to on success + + webhook_uri : typing.Optional[str] + Webhook URI for notifications + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[CreateTokenResponse] + connect token created + """ + _response = await self._client_wrapper.httpx_client.request( + "v1/connect/tokens", + method="POST", + json={ + "allowed_origins": allowed_origins, + "error_redirect_uri": error_redirect_uri, + "external_user_id": external_user_id, + "project_id": project_id, + "success_redirect_uri": success_redirect_uri, + "webhook_uri": webhook_uri, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + CreateTokenResponse, + parse_obj_as( + type_=CreateTokenResponse, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def validate( + self, + ctok: str, + *, + params: typing.Optional[ValidateTokenParams] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[ValidateTokenResponse]: + """ + Parameters + ---------- + ctok : str + + params : typing.Optional[ValidateTokenParams] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[ValidateTokenResponse] + connect token validated + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/connect/tokens/{jsonable_encoder(ctok)}/validate", + method="GET", + params={ + "params": convert_and_respect_annotation_metadata( + object_=params, annotation=ValidateTokenParams, direction="write" + ), + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ValidateTokenResponse, + parse_obj_as( + type_=ValidateTokenResponse, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/pipedream/triggers/__init__.py b/src/pipedream/triggers/__init__.py new file mode 100644 index 0000000..5cde020 --- /dev/null +++ b/src/pipedream/triggers/__init__.py @@ -0,0 +1,4 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + diff --git a/src/pipedream/triggers/client.py b/src/pipedream/triggers/client.py new file mode 100644 index 0000000..9b9d5b4 --- /dev/null +++ b/src/pipedream/triggers/client.py @@ -0,0 +1,760 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ..core.pagination import AsyncPager, SyncPager +from ..core.request_options import RequestOptions +from ..types.component import Component +from ..types.configure_prop_response import ConfigurePropResponse +from ..types.deployed_component import DeployedComponent +from ..types.reload_props_response import ReloadPropsResponse +from .raw_client import AsyncRawTriggersClient, RawTriggersClient + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class TriggersClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._raw_client = RawTriggersClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawTriggersClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawTriggersClient + """ + return self._raw_client + + def list( + self, + project_id: str, + *, + after: typing.Optional[str] = None, + before: typing.Optional[str] = None, + limit: typing.Optional[int] = None, + q: typing.Optional[str] = None, + app: typing.Optional[str] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> SyncPager[Component]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + after : typing.Optional[str] + The cursor to start from for pagination + + before : typing.Optional[str] + The cursor to end before for pagination + + limit : typing.Optional[int] + The maximum number of results to return + + q : typing.Optional[str] + A search query to filter the triggers + + app : typing.Optional[str] + The ID or name slug of the app to filter the triggers + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + SyncPager[Component] + triggers listed + + Examples + -------- + from pipedream import Pipedream + + client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + response = client.triggers.list( + project_id="project_id", + ) + for item in response: + yield item + # alternatively, you can paginate page-by-page + for page in response.iter_pages(): + yield page + """ + return self._raw_client.list( + project_id, after=after, before=before, limit=limit, q=q, app=app, request_options=request_options + ) + + def retrieve( + self, project_id: str, component_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> Component: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + component_id : str + The key that uniquely identifies the component (e.g., 'slack-send-message') + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Component + trigger retrieved + + Examples + -------- + from pipedream import Pipedream + + client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + client.triggers.retrieve( + project_id="project_id", + component_id="component_id", + ) + """ + _response = self._raw_client.retrieve(project_id, component_id, request_options=request_options) + return _response.data + + def configure_prop( + self, + project_id: str, + *, + id: str, + external_user_id: str, + prop_name: str, + async_handle: typing.Optional[str] = None, + blocking: typing.Optional[bool] = OMIT, + configured_props: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, + dynamic_props_id: typing.Optional[str] = OMIT, + configure_prop_opts_async_handle: typing.Optional[str] = OMIT, + page: typing.Optional[float] = OMIT, + prev_context: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, + query: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> ConfigurePropResponse: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + id : str + The component ID + + external_user_id : str + The external user ID + + prop_name : str + The name of the prop to configure + + async_handle : typing.Optional[str] + + blocking : typing.Optional[bool] + Whether this operation should block until completion + + configured_props : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] + The configured properties for the component + + dynamic_props_id : typing.Optional[str] + The ID for dynamic props + + configure_prop_opts_async_handle : typing.Optional[str] + Handle for async operations + + page : typing.Optional[float] + Page number for paginated results + + prev_context : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] + Previous context for pagination + + query : typing.Optional[str] + Search query for filtering options + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ConfigurePropResponse + trigger configuration started + + Examples + -------- + from pipedream import Pipedream + + client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + client.triggers.configure_prop( + project_id="project_id", + id="id", + external_user_id="external_user_id", + prop_name="prop_name", + ) + """ + _response = self._raw_client.configure_prop( + project_id, + id=id, + external_user_id=external_user_id, + prop_name=prop_name, + async_handle=async_handle, + blocking=blocking, + configured_props=configured_props, + dynamic_props_id=dynamic_props_id, + configure_prop_opts_async_handle=configure_prop_opts_async_handle, + page=page, + prev_context=prev_context, + query=query, + request_options=request_options, + ) + return _response.data + + def reload_props( + self, + project_id: str, + *, + id: str, + external_user_id: str, + async_handle: typing.Optional[str] = None, + blocking: typing.Optional[bool] = OMIT, + configured_props: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, + dynamic_props_id: typing.Optional[str] = OMIT, + reload_props_opts_async_handle: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> ReloadPropsResponse: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + id : str + The component ID + + external_user_id : str + The external user ID + + async_handle : typing.Optional[str] + + blocking : typing.Optional[bool] + Whether this operation should block until completion + + configured_props : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] + The configured properties for the component + + dynamic_props_id : typing.Optional[str] + The ID for dynamic props + + reload_props_opts_async_handle : typing.Optional[str] + Handle for async operations + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ReloadPropsResponse + trigger props reloaded + + Examples + -------- + from pipedream import Pipedream + + client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + client.triggers.reload_props( + project_id="project_id", + id="id", + external_user_id="external_user_id", + ) + """ + _response = self._raw_client.reload_props( + project_id, + id=id, + external_user_id=external_user_id, + async_handle=async_handle, + blocking=blocking, + configured_props=configured_props, + dynamic_props_id=dynamic_props_id, + reload_props_opts_async_handle=reload_props_opts_async_handle, + request_options=request_options, + ) + return _response.data + + def deploy( + self, + project_id: str, + *, + id: str, + external_user_id: str, + configured_props: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, + dynamic_props_id: typing.Optional[str] = OMIT, + webhook_url: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> DeployedComponent: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + id : str + The trigger component ID + + external_user_id : str + The external user ID + + configured_props : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] + The configured properties for the trigger + + dynamic_props_id : typing.Optional[str] + The ID for dynamic props + + webhook_url : typing.Optional[str] + Optional webhook URL to receive trigger events + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + DeployedComponent + trigger deployed + + Examples + -------- + from pipedream import Pipedream + + client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + client.triggers.deploy( + project_id="project_id", + id="id", + external_user_id="external_user_id", + ) + """ + _response = self._raw_client.deploy( + project_id, + id=id, + external_user_id=external_user_id, + configured_props=configured_props, + dynamic_props_id=dynamic_props_id, + webhook_url=webhook_url, + request_options=request_options, + ) + return _response.data + + +class AsyncTriggersClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._raw_client = AsyncRawTriggersClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawTriggersClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawTriggersClient + """ + return self._raw_client + + async def list( + self, + project_id: str, + *, + after: typing.Optional[str] = None, + before: typing.Optional[str] = None, + limit: typing.Optional[int] = None, + q: typing.Optional[str] = None, + app: typing.Optional[str] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncPager[Component]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + after : typing.Optional[str] + The cursor to start from for pagination + + before : typing.Optional[str] + The cursor to end before for pagination + + limit : typing.Optional[int] + The maximum number of results to return + + q : typing.Optional[str] + A search query to filter the triggers + + app : typing.Optional[str] + The ID or name slug of the app to filter the triggers + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncPager[Component] + triggers listed + + Examples + -------- + import asyncio + + from pipedream import AsyncPipedream + + client = AsyncPipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + + + async def main() -> None: + response = await client.triggers.list( + project_id="project_id", + ) + async for item in response: + yield item + + # alternatively, you can paginate page-by-page + async for page in response.iter_pages(): + yield page + + + asyncio.run(main()) + """ + return await self._raw_client.list( + project_id, after=after, before=before, limit=limit, q=q, app=app, request_options=request_options + ) + + async def retrieve( + self, project_id: str, component_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> Component: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + component_id : str + The key that uniquely identifies the component (e.g., 'slack-send-message') + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + Component + trigger retrieved + + Examples + -------- + import asyncio + + from pipedream import AsyncPipedream + + client = AsyncPipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + + + async def main() -> None: + await client.triggers.retrieve( + project_id="project_id", + component_id="component_id", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.retrieve(project_id, component_id, request_options=request_options) + return _response.data + + async def configure_prop( + self, + project_id: str, + *, + id: str, + external_user_id: str, + prop_name: str, + async_handle: typing.Optional[str] = None, + blocking: typing.Optional[bool] = OMIT, + configured_props: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, + dynamic_props_id: typing.Optional[str] = OMIT, + configure_prop_opts_async_handle: typing.Optional[str] = OMIT, + page: typing.Optional[float] = OMIT, + prev_context: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, + query: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> ConfigurePropResponse: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + id : str + The component ID + + external_user_id : str + The external user ID + + prop_name : str + The name of the prop to configure + + async_handle : typing.Optional[str] + + blocking : typing.Optional[bool] + Whether this operation should block until completion + + configured_props : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] + The configured properties for the component + + dynamic_props_id : typing.Optional[str] + The ID for dynamic props + + configure_prop_opts_async_handle : typing.Optional[str] + Handle for async operations + + page : typing.Optional[float] + Page number for paginated results + + prev_context : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] + Previous context for pagination + + query : typing.Optional[str] + Search query for filtering options + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ConfigurePropResponse + trigger configuration started + + Examples + -------- + import asyncio + + from pipedream import AsyncPipedream + + client = AsyncPipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + + + async def main() -> None: + await client.triggers.configure_prop( + project_id="project_id", + id="id", + external_user_id="external_user_id", + prop_name="prop_name", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.configure_prop( + project_id, + id=id, + external_user_id=external_user_id, + prop_name=prop_name, + async_handle=async_handle, + blocking=blocking, + configured_props=configured_props, + dynamic_props_id=dynamic_props_id, + configure_prop_opts_async_handle=configure_prop_opts_async_handle, + page=page, + prev_context=prev_context, + query=query, + request_options=request_options, + ) + return _response.data + + async def reload_props( + self, + project_id: str, + *, + id: str, + external_user_id: str, + async_handle: typing.Optional[str] = None, + blocking: typing.Optional[bool] = OMIT, + configured_props: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, + dynamic_props_id: typing.Optional[str] = OMIT, + reload_props_opts_async_handle: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> ReloadPropsResponse: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + id : str + The component ID + + external_user_id : str + The external user ID + + async_handle : typing.Optional[str] + + blocking : typing.Optional[bool] + Whether this operation should block until completion + + configured_props : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] + The configured properties for the component + + dynamic_props_id : typing.Optional[str] + The ID for dynamic props + + reload_props_opts_async_handle : typing.Optional[str] + Handle for async operations + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + ReloadPropsResponse + trigger props reloaded + + Examples + -------- + import asyncio + + from pipedream import AsyncPipedream + + client = AsyncPipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + + + async def main() -> None: + await client.triggers.reload_props( + project_id="project_id", + id="id", + external_user_id="external_user_id", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.reload_props( + project_id, + id=id, + external_user_id=external_user_id, + async_handle=async_handle, + blocking=blocking, + configured_props=configured_props, + dynamic_props_id=dynamic_props_id, + reload_props_opts_async_handle=reload_props_opts_async_handle, + request_options=request_options, + ) + return _response.data + + async def deploy( + self, + project_id: str, + *, + id: str, + external_user_id: str, + configured_props: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, + dynamic_props_id: typing.Optional[str] = OMIT, + webhook_url: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> DeployedComponent: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + id : str + The trigger component ID + + external_user_id : str + The external user ID + + configured_props : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] + The configured properties for the trigger + + dynamic_props_id : typing.Optional[str] + The ID for dynamic props + + webhook_url : typing.Optional[str] + Optional webhook URL to receive trigger events + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + DeployedComponent + trigger deployed + + Examples + -------- + import asyncio + + from pipedream import AsyncPipedream + + client = AsyncPipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + + + async def main() -> None: + await client.triggers.deploy( + project_id="project_id", + id="id", + external_user_id="external_user_id", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.deploy( + project_id, + id=id, + external_user_id=external_user_id, + configured_props=configured_props, + dynamic_props_id=dynamic_props_id, + webhook_url=webhook_url, + request_options=request_options, + ) + return _response.data diff --git a/src/pipedream/triggers/raw_client.py b/src/pipedream/triggers/raw_client.py new file mode 100644 index 0000000..2e62b98 --- /dev/null +++ b/src/pipedream/triggers/raw_client.py @@ -0,0 +1,789 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from json.decoder import JSONDecodeError + +from ..core.api_error import ApiError +from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ..core.http_response import AsyncHttpResponse, HttpResponse +from ..core.jsonable_encoder import jsonable_encoder +from ..core.pagination import AsyncPager, BaseHttpResponse, SyncPager +from ..core.pydantic_utilities import parse_obj_as +from ..core.request_options import RequestOptions +from ..types.component import Component +from ..types.configure_prop_response import ConfigurePropResponse +from ..types.deploy_trigger_response import DeployTriggerResponse +from ..types.deployed_component import DeployedComponent +from ..types.get_component_response import GetComponentResponse +from ..types.get_components_response import GetComponentsResponse +from ..types.reload_props_response import ReloadPropsResponse + +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + + +class RawTriggersClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def list( + self, + project_id: str, + *, + after: typing.Optional[str] = None, + before: typing.Optional[str] = None, + limit: typing.Optional[int] = None, + q: typing.Optional[str] = None, + app: typing.Optional[str] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> SyncPager[Component]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + after : typing.Optional[str] + The cursor to start from for pagination + + before : typing.Optional[str] + The cursor to end before for pagination + + limit : typing.Optional[int] + The maximum number of results to return + + q : typing.Optional[str] + A search query to filter the triggers + + app : typing.Optional[str] + The ID or name slug of the app to filter the triggers + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + SyncPager[Component] + triggers listed + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/triggers", + method="GET", + params={ + "after": after, + "before": before, + "limit": limit, + "q": q, + "app": app, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _parsed_response = typing.cast( + GetComponentsResponse, + parse_obj_as( + type_=GetComponentsResponse, # type: ignore + object_=_response.json(), + ), + ) + _items = _parsed_response.data + _has_next = False + _get_next = None + if _parsed_response.page_info is not None: + _parsed_next = _parsed_response.page_info.end_cursor + _has_next = _parsed_next is not None and _parsed_next != "" + _get_next = lambda: self.list( + project_id, + after=_parsed_next, + before=before, + limit=limit, + q=q, + app=app, + request_options=request_options, + ) + return SyncPager( + has_next=_has_next, items=_items, get_next=_get_next, response=BaseHttpResponse(response=_response) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def retrieve( + self, project_id: str, component_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[Component]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + component_id : str + The key that uniquely identifies the component (e.g., 'slack-send-message') + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[Component] + trigger retrieved + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/triggers/{jsonable_encoder(component_id)}", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _parsed_response = typing.cast( + GetComponentResponse, + parse_obj_as( + type_=GetComponentResponse, # type: ignore + object_=_response.json(), + ), + ) + _data = _parsed_response.data + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def configure_prop( + self, + project_id: str, + *, + id: str, + external_user_id: str, + prop_name: str, + async_handle: typing.Optional[str] = None, + blocking: typing.Optional[bool] = OMIT, + configured_props: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, + dynamic_props_id: typing.Optional[str] = OMIT, + configure_prop_opts_async_handle: typing.Optional[str] = OMIT, + page: typing.Optional[float] = OMIT, + prev_context: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, + query: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[ConfigurePropResponse]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + id : str + The component ID + + external_user_id : str + The external user ID + + prop_name : str + The name of the prop to configure + + async_handle : typing.Optional[str] + + blocking : typing.Optional[bool] + Whether this operation should block until completion + + configured_props : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] + The configured properties for the component + + dynamic_props_id : typing.Optional[str] + The ID for dynamic props + + configure_prop_opts_async_handle : typing.Optional[str] + Handle for async operations + + page : typing.Optional[float] + Page number for paginated results + + prev_context : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] + Previous context for pagination + + query : typing.Optional[str] + Search query for filtering options + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[ConfigurePropResponse] + trigger configuration started + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/triggers/configure", + method="POST", + json={ + "id": id, + "external_user_id": external_user_id, + "prop_name": prop_name, + "blocking": blocking, + "configured_props": configured_props, + "dynamic_props_id": dynamic_props_id, + "async_handle": async_handle, + "page": page, + "prev_context": prev_context, + "query": query, + }, + headers={ + "content-type": "application/json", + "x-async-handle": str(async_handle) if async_handle is not None else None, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ConfigurePropResponse, + parse_obj_as( + type_=ConfigurePropResponse, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def reload_props( + self, + project_id: str, + *, + id: str, + external_user_id: str, + async_handle: typing.Optional[str] = None, + blocking: typing.Optional[bool] = OMIT, + configured_props: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, + dynamic_props_id: typing.Optional[str] = OMIT, + reload_props_opts_async_handle: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[ReloadPropsResponse]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + id : str + The component ID + + external_user_id : str + The external user ID + + async_handle : typing.Optional[str] + + blocking : typing.Optional[bool] + Whether this operation should block until completion + + configured_props : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] + The configured properties for the component + + dynamic_props_id : typing.Optional[str] + The ID for dynamic props + + reload_props_opts_async_handle : typing.Optional[str] + Handle for async operations + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[ReloadPropsResponse] + trigger props reloaded + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/triggers/props", + method="POST", + json={ + "id": id, + "external_user_id": external_user_id, + "blocking": blocking, + "configured_props": configured_props, + "dynamic_props_id": dynamic_props_id, + "async_handle": async_handle, + }, + headers={ + "content-type": "application/json", + "x-async-handle": str(async_handle) if async_handle is not None else None, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ReloadPropsResponse, + parse_obj_as( + type_=ReloadPropsResponse, # type: ignore + object_=_response.json(), + ), + ) + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + def deploy( + self, + project_id: str, + *, + id: str, + external_user_id: str, + configured_props: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, + dynamic_props_id: typing.Optional[str] = OMIT, + webhook_url: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> HttpResponse[DeployedComponent]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + id : str + The trigger component ID + + external_user_id : str + The external user ID + + configured_props : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] + The configured properties for the trigger + + dynamic_props_id : typing.Optional[str] + The ID for dynamic props + + webhook_url : typing.Optional[str] + Optional webhook URL to receive trigger events + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[DeployedComponent] + trigger deployed + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/triggers/deploy", + method="POST", + json={ + "id": id, + "external_user_id": external_user_id, + "configured_props": configured_props, + "dynamic_props_id": dynamic_props_id, + "webhook_url": webhook_url, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _parsed_response = typing.cast( + DeployTriggerResponse, + parse_obj_as( + type_=DeployTriggerResponse, # type: ignore + object_=_response.json(), + ), + ) + _data = _parsed_response.data + return HttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + +class AsyncRawTriggersClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def list( + self, + project_id: str, + *, + after: typing.Optional[str] = None, + before: typing.Optional[str] = None, + limit: typing.Optional[int] = None, + q: typing.Optional[str] = None, + app: typing.Optional[str] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncPager[Component]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + after : typing.Optional[str] + The cursor to start from for pagination + + before : typing.Optional[str] + The cursor to end before for pagination + + limit : typing.Optional[int] + The maximum number of results to return + + q : typing.Optional[str] + A search query to filter the triggers + + app : typing.Optional[str] + The ID or name slug of the app to filter the triggers + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncPager[Component] + triggers listed + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/triggers", + method="GET", + params={ + "after": after, + "before": before, + "limit": limit, + "q": q, + "app": app, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _parsed_response = typing.cast( + GetComponentsResponse, + parse_obj_as( + type_=GetComponentsResponse, # type: ignore + object_=_response.json(), + ), + ) + _items = _parsed_response.data + _has_next = False + _get_next = None + if _parsed_response.page_info is not None: + _parsed_next = _parsed_response.page_info.end_cursor + _has_next = _parsed_next is not None and _parsed_next != "" + + async def _get_next(): + return await self.list( + project_id, + after=_parsed_next, + before=before, + limit=limit, + q=q, + app=app, + request_options=request_options, + ) + + return AsyncPager( + has_next=_has_next, items=_items, get_next=_get_next, response=BaseHttpResponse(response=_response) + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def retrieve( + self, project_id: str, component_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[Component]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + component_id : str + The key that uniquely identifies the component (e.g., 'slack-send-message') + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[Component] + trigger retrieved + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/triggers/{jsonable_encoder(component_id)}", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + _parsed_response = typing.cast( + GetComponentResponse, + parse_obj_as( + type_=GetComponentResponse, # type: ignore + object_=_response.json(), + ), + ) + _data = _parsed_response.data + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def configure_prop( + self, + project_id: str, + *, + id: str, + external_user_id: str, + prop_name: str, + async_handle: typing.Optional[str] = None, + blocking: typing.Optional[bool] = OMIT, + configured_props: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, + dynamic_props_id: typing.Optional[str] = OMIT, + configure_prop_opts_async_handle: typing.Optional[str] = OMIT, + page: typing.Optional[float] = OMIT, + prev_context: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, + query: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[ConfigurePropResponse]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + id : str + The component ID + + external_user_id : str + The external user ID + + prop_name : str + The name of the prop to configure + + async_handle : typing.Optional[str] + + blocking : typing.Optional[bool] + Whether this operation should block until completion + + configured_props : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] + The configured properties for the component + + dynamic_props_id : typing.Optional[str] + The ID for dynamic props + + configure_prop_opts_async_handle : typing.Optional[str] + Handle for async operations + + page : typing.Optional[float] + Page number for paginated results + + prev_context : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] + Previous context for pagination + + query : typing.Optional[str] + Search query for filtering options + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[ConfigurePropResponse] + trigger configuration started + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/triggers/configure", + method="POST", + json={ + "id": id, + "external_user_id": external_user_id, + "prop_name": prop_name, + "blocking": blocking, + "configured_props": configured_props, + "dynamic_props_id": dynamic_props_id, + "async_handle": async_handle, + "page": page, + "prev_context": prev_context, + "query": query, + }, + headers={ + "content-type": "application/json", + "x-async-handle": str(async_handle) if async_handle is not None else None, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ConfigurePropResponse, + parse_obj_as( + type_=ConfigurePropResponse, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def reload_props( + self, + project_id: str, + *, + id: str, + external_user_id: str, + async_handle: typing.Optional[str] = None, + blocking: typing.Optional[bool] = OMIT, + configured_props: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, + dynamic_props_id: typing.Optional[str] = OMIT, + reload_props_opts_async_handle: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[ReloadPropsResponse]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + id : str + The component ID + + external_user_id : str + The external user ID + + async_handle : typing.Optional[str] + + blocking : typing.Optional[bool] + Whether this operation should block until completion + + configured_props : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] + The configured properties for the component + + dynamic_props_id : typing.Optional[str] + The ID for dynamic props + + reload_props_opts_async_handle : typing.Optional[str] + Handle for async operations + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[ReloadPropsResponse] + trigger props reloaded + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/triggers/props", + method="POST", + json={ + "id": id, + "external_user_id": external_user_id, + "blocking": blocking, + "configured_props": configured_props, + "dynamic_props_id": dynamic_props_id, + "async_handle": async_handle, + }, + headers={ + "content-type": "application/json", + "x-async-handle": str(async_handle) if async_handle is not None else None, + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _data = typing.cast( + ReloadPropsResponse, + parse_obj_as( + type_=ReloadPropsResponse, # type: ignore + object_=_response.json(), + ), + ) + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + async def deploy( + self, + project_id: str, + *, + id: str, + external_user_id: str, + configured_props: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT, + dynamic_props_id: typing.Optional[str] = OMIT, + webhook_url: typing.Optional[str] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> AsyncHttpResponse[DeployedComponent]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + id : str + The trigger component ID + + external_user_id : str + The external user ID + + configured_props : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] + The configured properties for the trigger + + dynamic_props_id : typing.Optional[str] + The ID for dynamic props + + webhook_url : typing.Optional[str] + Optional webhook URL to receive trigger events + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[DeployedComponent] + trigger deployed + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/triggers/deploy", + method="POST", + json={ + "id": id, + "external_user_id": external_user_id, + "configured_props": configured_props, + "dynamic_props_id": dynamic_props_id, + "webhook_url": webhook_url, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + _parsed_response = typing.cast( + DeployTriggerResponse, + parse_obj_as( + type_=DeployTriggerResponse, # type: ignore + object_=_response.json(), + ), + ) + _data = _parsed_response.data + return AsyncHttpResponse(response=_response, data=_data) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/pipedream/types/__init__.py b/src/pipedream/types/__init__.py new file mode 100644 index 0000000..c0604e5 --- /dev/null +++ b/src/pipedream/types/__init__.py @@ -0,0 +1,119 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + +from .account import Account +from .app import App +from .app_auth_type import AppAuthType +from .app_category import AppCategory +from .backend_client_opts import BackendClientOpts +from .client_opts import ClientOpts +from .component import Component +from .component_stash import ComponentStash +from .configurable_prop import ConfigurableProp +from .configurable_prop_alert import ConfigurablePropAlert +from .configurable_prop_alert_alert_type import ConfigurablePropAlertAlertType +from .configurable_prop_any import ConfigurablePropAny +from .configurable_prop_app import ConfigurablePropApp +from .configurable_prop_boolean import ConfigurablePropBoolean +from .configurable_prop_discord import ConfigurablePropDiscord +from .configurable_prop_integer import ConfigurablePropInteger +from .configurable_prop_object import ConfigurablePropObject +from .configurable_prop_string import ConfigurablePropString +from .configurable_prop_string_array import ConfigurablePropStringArray +from .configure_prop_opts import ConfigurePropOpts +from .configure_prop_response import ConfigurePropResponse +from .connect_token_create_opts import ConnectTokenCreateOpts +from .connect_token_response import ConnectTokenResponse +from .create_browser_client_opts import CreateBrowserClientOpts +from .create_o_auth_token_response import CreateOAuthTokenResponse +from .create_token_response import CreateTokenResponse +from .delete_trigger_opts import DeleteTriggerOpts +from .deploy_trigger_response import DeployTriggerResponse +from .deployed_component import DeployedComponent +from .emitted_event import EmittedEvent +from .error_response import ErrorResponse +from .get_accounts_response import GetAccountsResponse +from .get_app_category_response import GetAppCategoryResponse +from .get_app_response import GetAppResponse +from .get_apps_response import GetAppsResponse +from .get_component_response import GetComponentResponse +from .get_components_response import GetComponentsResponse +from .get_trigger_events_response import GetTriggerEventsResponse +from .get_trigger_response import GetTriggerResponse +from .get_trigger_webhooks_response import GetTriggerWebhooksResponse +from .get_trigger_workflows_response import GetTriggerWorkflowsResponse +from .get_triggers_response import GetTriggersResponse +from .list_accounts_response import ListAccountsResponse +from .list_app_categories_response import ListAppCategoriesResponse +from .list_apps_response import ListAppsResponse +from .page_info import PageInfo +from .project_info_response import ProjectInfoResponse +from .project_info_response_apps_item import ProjectInfoResponseAppsItem +from .prop_option import PropOption +from .proxy_response import ProxyResponse +from .reload_props_opts import ReloadPropsOpts +from .reload_props_response import ReloadPropsResponse +from .run_action_response import RunActionResponse +from .start_connect_opts import StartConnectOpts +from .validate_token_params import ValidateTokenParams +from .validate_token_response import ValidateTokenResponse + +__all__ = [ + "Account", + "App", + "AppAuthType", + "AppCategory", + "BackendClientOpts", + "ClientOpts", + "Component", + "ComponentStash", + "ConfigurableProp", + "ConfigurablePropAlert", + "ConfigurablePropAlertAlertType", + "ConfigurablePropAny", + "ConfigurablePropApp", + "ConfigurablePropBoolean", + "ConfigurablePropDiscord", + "ConfigurablePropInteger", + "ConfigurablePropObject", + "ConfigurablePropString", + "ConfigurablePropStringArray", + "ConfigurePropOpts", + "ConfigurePropResponse", + "ConnectTokenCreateOpts", + "ConnectTokenResponse", + "CreateBrowserClientOpts", + "CreateOAuthTokenResponse", + "CreateTokenResponse", + "DeleteTriggerOpts", + "DeployTriggerResponse", + "DeployedComponent", + "EmittedEvent", + "ErrorResponse", + "GetAccountsResponse", + "GetAppCategoryResponse", + "GetAppResponse", + "GetAppsResponse", + "GetComponentResponse", + "GetComponentsResponse", + "GetTriggerEventsResponse", + "GetTriggerResponse", + "GetTriggerWebhooksResponse", + "GetTriggerWorkflowsResponse", + "GetTriggersResponse", + "ListAccountsResponse", + "ListAppCategoriesResponse", + "ListAppsResponse", + "PageInfo", + "ProjectInfoResponse", + "ProjectInfoResponseAppsItem", + "PropOption", + "ProxyResponse", + "ReloadPropsOpts", + "ReloadPropsResponse", + "RunActionResponse", + "StartConnectOpts", + "ValidateTokenParams", + "ValidateTokenResponse", +] diff --git a/src/pipedream/types/account.py b/src/pipedream/types/account.py new file mode 100644 index 0000000..ce024d3 --- /dev/null +++ b/src/pipedream/types/account.py @@ -0,0 +1,84 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from .app import App + + +class Account(UniversalBaseModel): + """ + End user account data, returned from the API. + """ + + id: typing.Optional[str] = pydantic.Field(default=None) + """ + The unique ID of the account. + """ + + name: typing.Optional[str] = pydantic.Field(default=None) + """ + The custom name of the account if set. + """ + + external_id: typing.Optional[str] = pydantic.Field(default=None) + """ + The external ID associated with the account. + """ + + healthy: typing.Optional[bool] = pydantic.Field(default=None) + """ + Indicates if the account is healthy. Pipedream will periodically retry token refresh and test requests for unhealthy accounts + """ + + dead: typing.Optional[bool] = pydantic.Field(default=None) + """ + Indicates if the account is no longer active + """ + + app: typing.Optional[App] = None + created_at: typing.Optional[dt.datetime] = pydantic.Field(default=None) + """ + The date and time the account was created, an ISO 8601 formatted string + """ + + updated_at: typing.Optional[dt.datetime] = pydantic.Field(default=None) + """ + The date and time the account was last updated, an ISO 8601 formatted string + """ + + credentials: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = pydantic.Field(default=None) + """ + The credentials associated with the account, if the `include_credentials` parameter was set to true in the request + """ + + expires_at: typing.Optional[dt.datetime] = pydantic.Field(default=None) + """ + The date and time the account's credentials expiration, an ISO 8601 formatted string + """ + + error: typing.Optional[str] = pydantic.Field(default=None) + """ + The error message if the account is unhealthy or dead, null otherwise + """ + + last_refreshed_at: typing.Optional[dt.datetime] = pydantic.Field(default=None) + """ + The date and time the account was last refreshed, an ISO 8601 formatted string + """ + + next_refresh_at: typing.Optional[dt.datetime] = pydantic.Field(default=None) + """ + The date and time the account will next be refreshed, an ISO 8601 formatted string + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/pipedream/types/app.py b/src/pipedream/types/app.py new file mode 100644 index 0000000..9389fe4 --- /dev/null +++ b/src/pipedream/types/app.py @@ -0,0 +1,67 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from .app_auth_type import AppAuthType + + +class App(UniversalBaseModel): + """ + Response object for a Pipedream app's metadata + """ + + id: typing.Optional[str] = pydantic.Field(default=None) + """ + ID of the app. Only applies for OAuth apps. + """ + + name_slug: str = pydantic.Field() + """ + The name slug of the target app (see https://pipedream.com/docs/connect/quickstart#find-your-apps-name-slug) + """ + + name: str = pydantic.Field() + """ + The human-readable name of the app + """ + + auth_type: typing.Optional[AppAuthType] = pydantic.Field(default=None) + """ + The authentication type used by the app + """ + + description: typing.Optional[str] = pydantic.Field(default=None) + """ + A short description of the app + """ + + img_src: str = pydantic.Field() + """ + The URL to the app's logo + """ + + custom_fields_json: typing.Optional[str] = pydantic.Field(default=None) + """ + A JSON string representing the custom fields for the app + """ + + categories: typing.List[str] = pydantic.Field() + """ + Categories associated with the app + """ + + featured_weight: float = pydantic.Field() + """ + A rough directional ordering of app popularity, subject to changes by Pipedream + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/pipedream/types/app_auth_type.py b/src/pipedream/types/app_auth_type.py new file mode 100644 index 0000000..44a2cc6 --- /dev/null +++ b/src/pipedream/types/app_auth_type.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +AppAuthType = typing.Union[typing.Literal["keys", "oauth", "none"], typing.Any] diff --git a/src/pipedream/types/app_category.py b/src/pipedream/types/app_category.py new file mode 100644 index 0000000..2df2f2c --- /dev/null +++ b/src/pipedream/types/app_category.py @@ -0,0 +1,36 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel + + +class AppCategory(UniversalBaseModel): + """ + Response object for a Pipedream app category + """ + + id: typing.Optional[str] = pydantic.Field(default=None) + """ + ID of the app category + """ + + name: typing.Optional[str] = pydantic.Field(default=None) + """ + The human-readable name of the app category + """ + + description: typing.Optional[str] = pydantic.Field(default=None) + """ + A short description of the app category + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/pipedream/types/backend_client_opts.py b/src/pipedream/types/backend_client_opts.py new file mode 100644 index 0000000..9ed37b8 --- /dev/null +++ b/src/pipedream/types/backend_client_opts.py @@ -0,0 +1,36 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel + + +class BackendClientOpts(UniversalBaseModel): + """ + Options for creating a server-side client + """ + + client_id: typing.Optional[str] = pydantic.Field(default=None) + """ + The client ID for authentication + """ + + client_secret: typing.Optional[str] = pydantic.Field(default=None) + """ + The client secret for authentication + """ + + api_url: typing.Optional[str] = pydantic.Field(default=None) + """ + The API URL to use + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/pipedream/types/client_opts.py b/src/pipedream/types/client_opts.py new file mode 100644 index 0000000..5f57615 --- /dev/null +++ b/src/pipedream/types/client_opts.py @@ -0,0 +1,36 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel + + +class ClientOpts(UniversalBaseModel): + """ + Options for creating a server-side client + """ + + client_id: typing.Optional[str] = pydantic.Field(default=None) + """ + The client ID for authentication + """ + + client_secret: typing.Optional[str] = pydantic.Field(default=None) + """ + The client secret for authentication + """ + + api_url: typing.Optional[str] = pydantic.Field(default=None) + """ + The API URL to use (defaults to https://api.pipedream.com/) + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/pipedream/types/component.py b/src/pipedream/types/component.py new file mode 100644 index 0000000..5d27cbd --- /dev/null +++ b/src/pipedream/types/component.py @@ -0,0 +1,50 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from .component_stash import ComponentStash +from .configurable_prop import ConfigurableProp + + +class Component(UniversalBaseModel): + key: str = pydantic.Field() + """ + The key that uniquely identifies the component. + """ + + name: str = pydantic.Field() + """ + The human-readable name of the component, e.g. 'GitLab: List Commits' + """ + + version: str = pydantic.Field() + """ + The latest version of the component, in SemVer format. + """ + + configurable_props: typing.List[ConfigurableProp] + description: typing.Optional[str] = pydantic.Field(default=None) + """ + A description of the component + """ + + component_type: typing.Optional[str] = pydantic.Field(default=None) + """ + The type of component (trigger or action) + """ + + stash: typing.Optional[ComponentStash] = pydantic.Field(default=None) + """ + Indicates if a File Stash ID is optional or required to run the component + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/pipedream/types/component_stash.py b/src/pipedream/types/component_stash.py new file mode 100644 index 0000000..e6269c8 --- /dev/null +++ b/src/pipedream/types/component_stash.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +ComponentStash = typing.Union[typing.Literal["optional", "required"], typing.Any] diff --git a/src/pipedream/types/configurable_prop.py b/src/pipedream/types/configurable_prop.py new file mode 100644 index 0000000..df64dc0 --- /dev/null +++ b/src/pipedream/types/configurable_prop.py @@ -0,0 +1,82 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.serialization import FieldMetadata + + +class ConfigurableProp(UniversalBaseModel): + """ + A configuration or input field for a component. + """ + + name: typing.Optional[str] = pydantic.Field(default=None) + """ + When building `configuredProps`, make sure to use this field as the key when setting the prop value + """ + + type: typing.Optional[str] = None + label: typing.Optional[str] = pydantic.Field(default=None) + """ + Value to use as an input label. In cases where `type` is "app", should load the app via `getApp`, etc. and show `app.name` instead. + """ + + description: typing.Optional[str] = pydantic.Field(default=None) + """ + A description of the prop, shown to the user when configuring the component. + """ + + optional: typing.Optional[bool] = pydantic.Field(default=None) + """ + If true, this prop does not need to be specified. + """ + + disabled: typing.Optional[bool] = pydantic.Field(default=None) + """ + If true, this prop will be ignored. + """ + + hidden: typing.Optional[bool] = pydantic.Field(default=None) + """ + If true, should not expose this prop to the user + """ + + remote_options: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="remoteOptions")] = ( + pydantic.Field(default=None) + ) + """ + If true, call `configureComponent` for this prop to load remote options. It is safe, and preferred, given a returned list of { label: string; value: any } objects to set the prop value to { __lv: { label: string; value: any } }. This way, on load, you can access label for the value without necessarily reloading these options + """ + + use_query: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="useQuery")] = pydantic.Field( + default=None + ) + """ + If true, calls to `configureComponent` for this prop support receiving a `query` parameter to filter remote options + """ + + reload_props: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="reloadProps")] = ( + pydantic.Field(default=None) + ) + """ + If true, after setting a value for this prop, a call to `reloadComponentProps` is required as the component has dynamic configurable props dependent on this one + """ + + with_label: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="withLabel")] = pydantic.Field( + default=None + ) + """ + If true, you must save the configured prop value as a "label-value" object which should look like: { __lv: { label: string; value: any } } because the execution needs to access the label + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/pipedream/types/configurable_prop_alert.py b/src/pipedream/types/configurable_prop_alert.py new file mode 100644 index 0000000..c6d0c1b --- /dev/null +++ b/src/pipedream/types/configurable_prop_alert.py @@ -0,0 +1,91 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.serialization import FieldMetadata +from .configurable_prop_alert_alert_type import ConfigurablePropAlertAlertType + + +class ConfigurablePropAlert(UniversalBaseModel): + type: typing.Optional[typing.Literal["alert"]] = None + alert_type: typing_extensions.Annotated[ + typing.Optional[ConfigurablePropAlertAlertType], FieldMetadata(alias="alertType") + ] = pydantic.Field(default=None) + """ + The severity level of the alert. + """ + + content: typing.Optional[str] = pydantic.Field(default=None) + """ + The content of the alert, which can include HTML or plain text. + """ + + name: typing.Optional[str] = pydantic.Field(default=None) + """ + When building `configuredProps`, make sure to use this field as the key when setting the prop value + """ + + label: typing.Optional[str] = pydantic.Field(default=None) + """ + Value to use as an input label. In cases where `type` is "app", should load the app via `getApp`, etc. and show `app.name` instead. + """ + + description: typing.Optional[str] = pydantic.Field(default=None) + """ + A description of the prop, shown to the user when configuring the component. + """ + + optional: typing.Optional[bool] = pydantic.Field(default=None) + """ + If true, this prop does not need to be specified. + """ + + disabled: typing.Optional[bool] = pydantic.Field(default=None) + """ + If true, this prop will be ignored. + """ + + hidden: typing.Optional[bool] = pydantic.Field(default=None) + """ + If true, should not expose this prop to the user + """ + + remote_options: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="remoteOptions")] = ( + pydantic.Field(default=None) + ) + """ + If true, call `configureComponent` for this prop to load remote options. It is safe, and preferred, given a returned list of { label: string; value: any } objects to set the prop value to { __lv: { label: string; value: any } }. This way, on load, you can access label for the value without necessarily reloading these options + """ + + use_query: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="useQuery")] = pydantic.Field( + default=None + ) + """ + If true, calls to `configureComponent` for this prop support receiving a `query` parameter to filter remote options + """ + + reload_props: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="reloadProps")] = ( + pydantic.Field(default=None) + ) + """ + If true, after setting a value for this prop, a call to `reloadComponentProps` is required as the component has dynamic configurable props dependent on this one + """ + + with_label: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="withLabel")] = pydantic.Field( + default=None + ) + """ + If true, you must save the configured prop value as a "label-value" object which should look like: { __lv: { label: string; value: any } } because the execution needs to access the label + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/pipedream/types/configurable_prop_alert_alert_type.py b/src/pipedream/types/configurable_prop_alert_alert_type.py new file mode 100644 index 0000000..2fd84e6 --- /dev/null +++ b/src/pipedream/types/configurable_prop_alert_alert_type.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +ConfigurablePropAlertAlertType = typing.Union[typing.Literal["info", "neutral", "warning", "error"], typing.Any] diff --git a/src/pipedream/types/configurable_prop_any.py b/src/pipedream/types/configurable_prop_any.py new file mode 100644 index 0000000..88db652 --- /dev/null +++ b/src/pipedream/types/configurable_prop_any.py @@ -0,0 +1,78 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.serialization import FieldMetadata + + +class ConfigurablePropAny(UniversalBaseModel): + type: typing.Optional[typing.Literal["any"]] = None + name: typing.Optional[str] = pydantic.Field(default=None) + """ + When building `configuredProps`, make sure to use this field as the key when setting the prop value + """ + + label: typing.Optional[str] = pydantic.Field(default=None) + """ + Value to use as an input label. In cases where `type` is "app", should load the app via `getApp`, etc. and show `app.name` instead. + """ + + description: typing.Optional[str] = pydantic.Field(default=None) + """ + A description of the prop, shown to the user when configuring the component. + """ + + optional: typing.Optional[bool] = pydantic.Field(default=None) + """ + If true, this prop does not need to be specified. + """ + + disabled: typing.Optional[bool] = pydantic.Field(default=None) + """ + If true, this prop will be ignored. + """ + + hidden: typing.Optional[bool] = pydantic.Field(default=None) + """ + If true, should not expose this prop to the user + """ + + remote_options: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="remoteOptions")] = ( + pydantic.Field(default=None) + ) + """ + If true, call `configureComponent` for this prop to load remote options. It is safe, and preferred, given a returned list of { label: string; value: any } objects to set the prop value to { __lv: { label: string; value: any } }. This way, on load, you can access label for the value without necessarily reloading these options + """ + + use_query: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="useQuery")] = pydantic.Field( + default=None + ) + """ + If true, calls to `configureComponent` for this prop support receiving a `query` parameter to filter remote options + """ + + reload_props: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="reloadProps")] = ( + pydantic.Field(default=None) + ) + """ + If true, after setting a value for this prop, a call to `reloadComponentProps` is required as the component has dynamic configurable props dependent on this one + """ + + with_label: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="withLabel")] = pydantic.Field( + default=None + ) + """ + If true, you must save the configured prop value as a "label-value" object which should look like: { __lv: { label: string; value: any } } because the execution needs to access the label + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/pipedream/types/configurable_prop_app.py b/src/pipedream/types/configurable_prop_app.py new file mode 100644 index 0000000..7053f8f --- /dev/null +++ b/src/pipedream/types/configurable_prop_app.py @@ -0,0 +1,83 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.serialization import FieldMetadata + + +class ConfigurablePropApp(UniversalBaseModel): + type: typing.Optional[typing.Literal["app"]] = None + app: typing.Optional[str] = pydantic.Field(default=None) + """ + The name slug of the app, e.g. 'github', 'slack', etc. This is used to identify the app for which the account is being configured. + """ + + name: typing.Optional[str] = pydantic.Field(default=None) + """ + When building `configuredProps`, make sure to use this field as the key when setting the prop value + """ + + label: typing.Optional[str] = pydantic.Field(default=None) + """ + Value to use as an input label. In cases where `type` is "app", should load the app via `getApp`, etc. and show `app.name` instead. + """ + + description: typing.Optional[str] = pydantic.Field(default=None) + """ + A description of the prop, shown to the user when configuring the component. + """ + + optional: typing.Optional[bool] = pydantic.Field(default=None) + """ + If true, this prop does not need to be specified. + """ + + disabled: typing.Optional[bool] = pydantic.Field(default=None) + """ + If true, this prop will be ignored. + """ + + hidden: typing.Optional[bool] = pydantic.Field(default=None) + """ + If true, should not expose this prop to the user + """ + + remote_options: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="remoteOptions")] = ( + pydantic.Field(default=None) + ) + """ + If true, call `configureComponent` for this prop to load remote options. It is safe, and preferred, given a returned list of { label: string; value: any } objects to set the prop value to { __lv: { label: string; value: any } }. This way, on load, you can access label for the value without necessarily reloading these options + """ + + use_query: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="useQuery")] = pydantic.Field( + default=None + ) + """ + If true, calls to `configureComponent` for this prop support receiving a `query` parameter to filter remote options + """ + + reload_props: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="reloadProps")] = ( + pydantic.Field(default=None) + ) + """ + If true, after setting a value for this prop, a call to `reloadComponentProps` is required as the component has dynamic configurable props dependent on this one + """ + + with_label: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="withLabel")] = pydantic.Field( + default=None + ) + """ + If true, you must save the configured prop value as a "label-value" object which should look like: { __lv: { label: string; value: any } } because the execution needs to access the label + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/pipedream/types/configurable_prop_boolean.py b/src/pipedream/types/configurable_prop_boolean.py new file mode 100644 index 0000000..5209bea --- /dev/null +++ b/src/pipedream/types/configurable_prop_boolean.py @@ -0,0 +1,78 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.serialization import FieldMetadata + + +class ConfigurablePropBoolean(UniversalBaseModel): + type: typing.Optional[typing.Literal["boolean"]] = None + name: typing.Optional[str] = pydantic.Field(default=None) + """ + When building `configuredProps`, make sure to use this field as the key when setting the prop value + """ + + label: typing.Optional[str] = pydantic.Field(default=None) + """ + Value to use as an input label. In cases where `type` is "app", should load the app via `getApp`, etc. and show `app.name` instead. + """ + + description: typing.Optional[str] = pydantic.Field(default=None) + """ + A description of the prop, shown to the user when configuring the component. + """ + + optional: typing.Optional[bool] = pydantic.Field(default=None) + """ + If true, this prop does not need to be specified. + """ + + disabled: typing.Optional[bool] = pydantic.Field(default=None) + """ + If true, this prop will be ignored. + """ + + hidden: typing.Optional[bool] = pydantic.Field(default=None) + """ + If true, should not expose this prop to the user + """ + + remote_options: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="remoteOptions")] = ( + pydantic.Field(default=None) + ) + """ + If true, call `configureComponent` for this prop to load remote options. It is safe, and preferred, given a returned list of { label: string; value: any } objects to set the prop value to { __lv: { label: string; value: any } }. This way, on load, you can access label for the value without necessarily reloading these options + """ + + use_query: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="useQuery")] = pydantic.Field( + default=None + ) + """ + If true, calls to `configureComponent` for this prop support receiving a `query` parameter to filter remote options + """ + + reload_props: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="reloadProps")] = ( + pydantic.Field(default=None) + ) + """ + If true, after setting a value for this prop, a call to `reloadComponentProps` is required as the component has dynamic configurable props dependent on this one + """ + + with_label: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="withLabel")] = pydantic.Field( + default=None + ) + """ + If true, you must save the configured prop value as a "label-value" object which should look like: { __lv: { label: string; value: any } } because the execution needs to access the label + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/pipedream/types/configurable_prop_discord.py b/src/pipedream/types/configurable_prop_discord.py new file mode 100644 index 0000000..2a93554 --- /dev/null +++ b/src/pipedream/types/configurable_prop_discord.py @@ -0,0 +1,78 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.serialization import FieldMetadata + + +class ConfigurablePropDiscord(UniversalBaseModel): + type: typing.Optional[typing.Literal["$.discord.channel"]] = None + name: typing.Optional[str] = pydantic.Field(default=None) + """ + When building `configuredProps`, make sure to use this field as the key when setting the prop value + """ + + label: typing.Optional[str] = pydantic.Field(default=None) + """ + Value to use as an input label. In cases where `type` is "app", should load the app via `getApp`, etc. and show `app.name` instead. + """ + + description: typing.Optional[str] = pydantic.Field(default=None) + """ + A description of the prop, shown to the user when configuring the component. + """ + + optional: typing.Optional[bool] = pydantic.Field(default=None) + """ + If true, this prop does not need to be specified. + """ + + disabled: typing.Optional[bool] = pydantic.Field(default=None) + """ + If true, this prop will be ignored. + """ + + hidden: typing.Optional[bool] = pydantic.Field(default=None) + """ + If true, should not expose this prop to the user + """ + + remote_options: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="remoteOptions")] = ( + pydantic.Field(default=None) + ) + """ + If true, call `configureComponent` for this prop to load remote options. It is safe, and preferred, given a returned list of { label: string; value: any } objects to set the prop value to { __lv: { label: string; value: any } }. This way, on load, you can access label for the value without necessarily reloading these options + """ + + use_query: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="useQuery")] = pydantic.Field( + default=None + ) + """ + If true, calls to `configureComponent` for this prop support receiving a `query` parameter to filter remote options + """ + + reload_props: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="reloadProps")] = ( + pydantic.Field(default=None) + ) + """ + If true, after setting a value for this prop, a call to `reloadComponentProps` is required as the component has dynamic configurable props dependent on this one + """ + + with_label: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="withLabel")] = pydantic.Field( + default=None + ) + """ + If true, you must save the configured prop value as a "label-value" object which should look like: { __lv: { label: string; value: any } } because the execution needs to access the label + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/pipedream/types/configurable_prop_integer.py b/src/pipedream/types/configurable_prop_integer.py new file mode 100644 index 0000000..ed4d01c --- /dev/null +++ b/src/pipedream/types/configurable_prop_integer.py @@ -0,0 +1,88 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.serialization import FieldMetadata + + +class ConfigurablePropInteger(UniversalBaseModel): + type: typing.Optional[typing.Literal["integer"]] = None + min: typing.Optional[int] = pydantic.Field(default=None) + """ + The minimum value for this integer prop. + """ + + max: typing.Optional[int] = pydantic.Field(default=None) + """ + The maximum value for this integer prop. + """ + + name: typing.Optional[str] = pydantic.Field(default=None) + """ + When building `configuredProps`, make sure to use this field as the key when setting the prop value + """ + + label: typing.Optional[str] = pydantic.Field(default=None) + """ + Value to use as an input label. In cases where `type` is "app", should load the app via `getApp`, etc. and show `app.name` instead. + """ + + description: typing.Optional[str] = pydantic.Field(default=None) + """ + A description of the prop, shown to the user when configuring the component. + """ + + optional: typing.Optional[bool] = pydantic.Field(default=None) + """ + If true, this prop does not need to be specified. + """ + + disabled: typing.Optional[bool] = pydantic.Field(default=None) + """ + If true, this prop will be ignored. + """ + + hidden: typing.Optional[bool] = pydantic.Field(default=None) + """ + If true, should not expose this prop to the user + """ + + remote_options: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="remoteOptions")] = ( + pydantic.Field(default=None) + ) + """ + If true, call `configureComponent` for this prop to load remote options. It is safe, and preferred, given a returned list of { label: string; value: any } objects to set the prop value to { __lv: { label: string; value: any } }. This way, on load, you can access label for the value without necessarily reloading these options + """ + + use_query: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="useQuery")] = pydantic.Field( + default=None + ) + """ + If true, calls to `configureComponent` for this prop support receiving a `query` parameter to filter remote options + """ + + reload_props: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="reloadProps")] = ( + pydantic.Field(default=None) + ) + """ + If true, after setting a value for this prop, a call to `reloadComponentProps` is required as the component has dynamic configurable props dependent on this one + """ + + with_label: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="withLabel")] = pydantic.Field( + default=None + ) + """ + If true, you must save the configured prop value as a "label-value" object which should look like: { __lv: { label: string; value: any } } because the execution needs to access the label + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/pipedream/types/configurable_prop_object.py b/src/pipedream/types/configurable_prop_object.py new file mode 100644 index 0000000..f77c16b --- /dev/null +++ b/src/pipedream/types/configurable_prop_object.py @@ -0,0 +1,78 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.serialization import FieldMetadata + + +class ConfigurablePropObject(UniversalBaseModel): + type: typing.Optional[typing.Literal["object"]] = None + name: typing.Optional[str] = pydantic.Field(default=None) + """ + When building `configuredProps`, make sure to use this field as the key when setting the prop value + """ + + label: typing.Optional[str] = pydantic.Field(default=None) + """ + Value to use as an input label. In cases where `type` is "app", should load the app via `getApp`, etc. and show `app.name` instead. + """ + + description: typing.Optional[str] = pydantic.Field(default=None) + """ + A description of the prop, shown to the user when configuring the component. + """ + + optional: typing.Optional[bool] = pydantic.Field(default=None) + """ + If true, this prop does not need to be specified. + """ + + disabled: typing.Optional[bool] = pydantic.Field(default=None) + """ + If true, this prop will be ignored. + """ + + hidden: typing.Optional[bool] = pydantic.Field(default=None) + """ + If true, should not expose this prop to the user + """ + + remote_options: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="remoteOptions")] = ( + pydantic.Field(default=None) + ) + """ + If true, call `configureComponent` for this prop to load remote options. It is safe, and preferred, given a returned list of { label: string; value: any } objects to set the prop value to { __lv: { label: string; value: any } }. This way, on load, you can access label for the value without necessarily reloading these options + """ + + use_query: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="useQuery")] = pydantic.Field( + default=None + ) + """ + If true, calls to `configureComponent` for this prop support receiving a `query` parameter to filter remote options + """ + + reload_props: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="reloadProps")] = ( + pydantic.Field(default=None) + ) + """ + If true, after setting a value for this prop, a call to `reloadComponentProps` is required as the component has dynamic configurable props dependent on this one + """ + + with_label: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="withLabel")] = pydantic.Field( + default=None + ) + """ + If true, you must save the configured prop value as a "label-value" object which should look like: { __lv: { label: string; value: any } } because the execution needs to access the label + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/pipedream/types/configurable_prop_string.py b/src/pipedream/types/configurable_prop_string.py new file mode 100644 index 0000000..6f993ac --- /dev/null +++ b/src/pipedream/types/configurable_prop_string.py @@ -0,0 +1,83 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.serialization import FieldMetadata + + +class ConfigurablePropString(UniversalBaseModel): + type: typing.Optional[typing.Literal["string"]] = None + secret: typing.Optional[bool] = pydantic.Field(default=None) + """ + If true, this prop is a secret and should not be displayed in plain text. + """ + + name: typing.Optional[str] = pydantic.Field(default=None) + """ + When building `configuredProps`, make sure to use this field as the key when setting the prop value + """ + + label: typing.Optional[str] = pydantic.Field(default=None) + """ + Value to use as an input label. In cases where `type` is "app", should load the app via `getApp`, etc. and show `app.name` instead. + """ + + description: typing.Optional[str] = pydantic.Field(default=None) + """ + A description of the prop, shown to the user when configuring the component. + """ + + optional: typing.Optional[bool] = pydantic.Field(default=None) + """ + If true, this prop does not need to be specified. + """ + + disabled: typing.Optional[bool] = pydantic.Field(default=None) + """ + If true, this prop will be ignored. + """ + + hidden: typing.Optional[bool] = pydantic.Field(default=None) + """ + If true, should not expose this prop to the user + """ + + remote_options: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="remoteOptions")] = ( + pydantic.Field(default=None) + ) + """ + If true, call `configureComponent` for this prop to load remote options. It is safe, and preferred, given a returned list of { label: string; value: any } objects to set the prop value to { __lv: { label: string; value: any } }. This way, on load, you can access label for the value without necessarily reloading these options + """ + + use_query: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="useQuery")] = pydantic.Field( + default=None + ) + """ + If true, calls to `configureComponent` for this prop support receiving a `query` parameter to filter remote options + """ + + reload_props: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="reloadProps")] = ( + pydantic.Field(default=None) + ) + """ + If true, after setting a value for this prop, a call to `reloadComponentProps` is required as the component has dynamic configurable props dependent on this one + """ + + with_label: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="withLabel")] = pydantic.Field( + default=None + ) + """ + If true, you must save the configured prop value as a "label-value" object which should look like: { __lv: { label: string; value: any } } because the execution needs to access the label + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/pipedream/types/configurable_prop_string_array.py b/src/pipedream/types/configurable_prop_string_array.py new file mode 100644 index 0000000..1e74b7b --- /dev/null +++ b/src/pipedream/types/configurable_prop_string_array.py @@ -0,0 +1,83 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ..core.serialization import FieldMetadata + + +class ConfigurablePropStringArray(UniversalBaseModel): + type: typing.Optional[typing.Literal["string[]"]] = None + secret: typing.Optional[bool] = pydantic.Field(default=None) + """ + If true, this prop is a secret and should not be displayed in plain text. + """ + + name: typing.Optional[str] = pydantic.Field(default=None) + """ + When building `configuredProps`, make sure to use this field as the key when setting the prop value + """ + + label: typing.Optional[str] = pydantic.Field(default=None) + """ + Value to use as an input label. In cases where `type` is "app", should load the app via `getApp`, etc. and show `app.name` instead. + """ + + description: typing.Optional[str] = pydantic.Field(default=None) + """ + A description of the prop, shown to the user when configuring the component. + """ + + optional: typing.Optional[bool] = pydantic.Field(default=None) + """ + If true, this prop does not need to be specified. + """ + + disabled: typing.Optional[bool] = pydantic.Field(default=None) + """ + If true, this prop will be ignored. + """ + + hidden: typing.Optional[bool] = pydantic.Field(default=None) + """ + If true, should not expose this prop to the user + """ + + remote_options: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="remoteOptions")] = ( + pydantic.Field(default=None) + ) + """ + If true, call `configureComponent` for this prop to load remote options. It is safe, and preferred, given a returned list of { label: string; value: any } objects to set the prop value to { __lv: { label: string; value: any } }. This way, on load, you can access label for the value without necessarily reloading these options + """ + + use_query: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="useQuery")] = pydantic.Field( + default=None + ) + """ + If true, calls to `configureComponent` for this prop support receiving a `query` parameter to filter remote options + """ + + reload_props: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="reloadProps")] = ( + pydantic.Field(default=None) + ) + """ + If true, after setting a value for this prop, a call to `reloadComponentProps` is required as the component has dynamic configurable props dependent on this one + """ + + with_label: typing_extensions.Annotated[typing.Optional[bool], FieldMetadata(alias="withLabel")] = pydantic.Field( + default=None + ) + """ + If true, you must save the configured prop value as a "label-value" object which should look like: { __lv: { label: string; value: any } } because the execution needs to access the label + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/pipedream/types/configure_prop_opts.py b/src/pipedream/types/configure_prop_opts.py new file mode 100644 index 0000000..5811a46 --- /dev/null +++ b/src/pipedream/types/configure_prop_opts.py @@ -0,0 +1,71 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel + + +class ConfigurePropOpts(UniversalBaseModel): + """ + Request options for configuring a component's prop + """ + + id: str = pydantic.Field() + """ + The component ID + """ + + external_user_id: str = pydantic.Field() + """ + The external user ID + """ + + prop_name: str = pydantic.Field() + """ + The name of the prop to configure + """ + + blocking: typing.Optional[bool] = pydantic.Field(default=None) + """ + Whether this operation should block until completion + """ + + configured_props: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = pydantic.Field(default=None) + """ + The configured properties for the component + """ + + dynamic_props_id: typing.Optional[str] = pydantic.Field(default=None) + """ + The ID for dynamic props + """ + + async_handle: typing.Optional[str] = pydantic.Field(default=None) + """ + Handle for async operations + """ + + page: typing.Optional[float] = pydantic.Field(default=None) + """ + Page number for paginated results + """ + + prev_context: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = pydantic.Field(default=None) + """ + Previous context for pagination + """ + + query: typing.Optional[str] = pydantic.Field(default=None) + """ + Search query for filtering options + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/pipedream/types/configure_prop_response.py b/src/pipedream/types/configure_prop_response.py new file mode 100644 index 0000000..44f7086 --- /dev/null +++ b/src/pipedream/types/configure_prop_response.py @@ -0,0 +1,32 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from .prop_option import PropOption + + +class ConfigurePropResponse(UniversalBaseModel): + """ + Response received after configuring a component's prop + """ + + options: typing.Optional[typing.List[PropOption]] = pydantic.Field(default=None) + """ + Available options for the configured prop + """ + + errors: typing.Optional[typing.List[str]] = pydantic.Field(default=None) + """ + Any errors that occurred during configuration + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/pipedream/types/connect_token_create_opts.py b/src/pipedream/types/connect_token_create_opts.py new file mode 100644 index 0000000..dc16143 --- /dev/null +++ b/src/pipedream/types/connect_token_create_opts.py @@ -0,0 +1,51 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel + + +class ConnectTokenCreateOpts(UniversalBaseModel): + """ + Options for creating a Connect token + """ + + external_user_id: str = pydantic.Field() + """ + Your end user ID, for whom you're creating the token + """ + + project_id: str = pydantic.Field() + """ + The ID of the project + """ + + allowed_origins: typing.Optional[typing.List[str]] = pydantic.Field(default=None) + """ + List of allowed origins for CORS + """ + + error_redirect_uri: typing.Optional[str] = pydantic.Field(default=None) + """ + URI to redirect to on error + """ + + success_redirect_uri: typing.Optional[str] = pydantic.Field(default=None) + """ + URI to redirect to on success + """ + + webhook_uri: typing.Optional[str] = pydantic.Field(default=None) + """ + Webhook URI for notifications + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/pipedream/types/connect_token_response.py b/src/pipedream/types/connect_token_response.py new file mode 100644 index 0000000..c0f4cea --- /dev/null +++ b/src/pipedream/types/connect_token_response.py @@ -0,0 +1,37 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel + + +class ConnectTokenResponse(UniversalBaseModel): + """ + Response received after creating a connect token + """ + + connect_link_url: str = pydantic.Field() + """ + The Connect Link URL + """ + + expires_at: dt.datetime = pydantic.Field() + """ + The expiration time of the token in ISO 8601 format + """ + + token: str = pydantic.Field() + """ + The generated token + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/pipedream/types/create_browser_client_opts.py b/src/pipedream/types/create_browser_client_opts.py new file mode 100644 index 0000000..50400a4 --- /dev/null +++ b/src/pipedream/types/create_browser_client_opts.py @@ -0,0 +1,26 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel + + +class CreateBrowserClientOpts(UniversalBaseModel): + """ + Options for creating a browser-side client + """ + + api_url: typing.Optional[str] = pydantic.Field(default=None) + """ + The API URL to use + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/pipedream/types/create_o_auth_token_response.py b/src/pipedream/types/create_o_auth_token_response.py new file mode 100644 index 0000000..2545673 --- /dev/null +++ b/src/pipedream/types/create_o_auth_token_response.py @@ -0,0 +1,25 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel + + +class CreateOAuthTokenResponse(UniversalBaseModel): + """ + Response object for creating an OAuth token + """ + + access_token: str + token_type: str + expires_in: int + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/pipedream/types/create_token_response.py b/src/pipedream/types/create_token_response.py new file mode 100644 index 0000000..738ce83 --- /dev/null +++ b/src/pipedream/types/create_token_response.py @@ -0,0 +1,37 @@ +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel + + +class CreateTokenResponse(UniversalBaseModel): + """ + Response received after creating a connect token + """ + + connect_link_url: str = pydantic.Field() + """ + The Connect Link URL + """ + + expires_at: dt.datetime = pydantic.Field() + """ + The expiration time of the token in ISO 8601 format + """ + + token: str = pydantic.Field() + """ + The generated token + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/pipedream/types/delete_trigger_opts.py b/src/pipedream/types/delete_trigger_opts.py new file mode 100644 index 0000000..58c5e47 --- /dev/null +++ b/src/pipedream/types/delete_trigger_opts.py @@ -0,0 +1,26 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel + + +class DeleteTriggerOpts(UniversalBaseModel): + """ + Request options for deleting a deployed trigger + """ + + ignore_hook_errors: typing.Optional[bool] = pydantic.Field(default=None) + """ + Whether to ignore errors during deactivation hook + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/pipedream/types/deploy_trigger_response.py b/src/pipedream/types/deploy_trigger_response.py new file mode 100644 index 0000000..bdb7143 --- /dev/null +++ b/src/pipedream/types/deploy_trigger_response.py @@ -0,0 +1,24 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from .deployed_component import DeployedComponent + + +class DeployTriggerResponse(UniversalBaseModel): + """ + Response received after deploying a trigger + """ + + data: DeployedComponent + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/pipedream/types/deployed_component.py b/src/pipedream/types/deployed_component.py new file mode 100644 index 0000000..7413f3f --- /dev/null +++ b/src/pipedream/types/deployed_component.py @@ -0,0 +1,74 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from .configurable_prop import ConfigurableProp + + +class DeployedComponent(UniversalBaseModel): + """ + A deployed component instance + """ + + id: str = pydantic.Field() + """ + The unique ID of the deployed component + """ + + owner_id: str = pydantic.Field() + """ + The ID of the owner + """ + + component_id: str = pydantic.Field() + """ + The ID of the component that was deployed + """ + + configurable_props: typing.List[ConfigurableProp] = pydantic.Field() + """ + The configurable properties of the component + """ + + configured_props: typing.Dict[str, typing.Optional[typing.Any]] = pydantic.Field() + """ + The configured properties of the component + """ + + active: bool = pydantic.Field() + """ + Whether the deployed component is active + """ + + created_at: int = pydantic.Field() + """ + The timestamp when the component was deployed (epoch milliseconds) + """ + + updated_at: int = pydantic.Field() + """ + The timestamp when the component was last updated (epoch milliseconds) + """ + + name: str = pydantic.Field() + """ + The name of the deployed component + """ + + name_slug: str = pydantic.Field() + """ + The name slug of the deployed component + """ + + callback_observations: typing.Optional[typing.Optional[typing.Any]] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/pipedream/types/emitted_event.py b/src/pipedream/types/emitted_event.py new file mode 100644 index 0000000..633bbeb --- /dev/null +++ b/src/pipedream/types/emitted_event.py @@ -0,0 +1,41 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel + + +class EmittedEvent(UniversalBaseModel): + """ + An event emitted by a trigger + """ + + e: typing.Dict[str, typing.Optional[typing.Any]] = pydantic.Field() + """ + The event's payload + """ + + k: str = pydantic.Field() + """ + The event's type (set to 'emit' currently) + """ + + ts: int = pydantic.Field() + """ + The event's timestamp in epoch milliseconds + """ + + id: str = pydantic.Field() + """ + The event's unique ID + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/pipedream/types/error_response.py b/src/pipedream/types/error_response.py new file mode 100644 index 0000000..ce5a708 --- /dev/null +++ b/src/pipedream/types/error_response.py @@ -0,0 +1,36 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel + + +class ErrorResponse(UniversalBaseModel): + """ + Error response returned by the API in case of an error + """ + + error: str = pydantic.Field() + """ + The error message + """ + + code: typing.Optional[str] = pydantic.Field(default=None) + """ + The error code + """ + + details: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = pydantic.Field(default=None) + """ + Additional error details + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/pipedream/types/get_accounts_response.py b/src/pipedream/types/get_accounts_response.py new file mode 100644 index 0000000..7579943 --- /dev/null +++ b/src/pipedream/types/get_accounts_response.py @@ -0,0 +1,26 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from .account import Account +from .page_info import PageInfo + + +class GetAccountsResponse(UniversalBaseModel): + """ + Response received when retrieving a list of accounts + """ + + data: typing.List[Account] + page_info: PageInfo + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/pipedream/types/get_app_category_response.py b/src/pipedream/types/get_app_category_response.py new file mode 100644 index 0000000..ceacf51 --- /dev/null +++ b/src/pipedream/types/get_app_category_response.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +from .app_category import AppCategory + +GetAppCategoryResponse = AppCategory diff --git a/src/pipedream/types/get_app_response.py b/src/pipedream/types/get_app_response.py new file mode 100644 index 0000000..59a1020 --- /dev/null +++ b/src/pipedream/types/get_app_response.py @@ -0,0 +1,24 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from .app import App + + +class GetAppResponse(UniversalBaseModel): + """ + Response received when retrieving a single app + """ + + data: App + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/pipedream/types/get_apps_response.py b/src/pipedream/types/get_apps_response.py new file mode 100644 index 0000000..d0b98f6 --- /dev/null +++ b/src/pipedream/types/get_apps_response.py @@ -0,0 +1,26 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from .app import App +from .page_info import PageInfo + + +class GetAppsResponse(UniversalBaseModel): + """ + Response received when retrieving a list of apps + """ + + data: typing.List[App] + page_info: PageInfo + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/pipedream/types/get_component_response.py b/src/pipedream/types/get_component_response.py new file mode 100644 index 0000000..456b2d9 --- /dev/null +++ b/src/pipedream/types/get_component_response.py @@ -0,0 +1,24 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from .component import Component + + +class GetComponentResponse(UniversalBaseModel): + """ + Response received when retrieving a specific component + """ + + data: Component + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/pipedream/types/get_components_response.py b/src/pipedream/types/get_components_response.py new file mode 100644 index 0000000..e4d4883 --- /dev/null +++ b/src/pipedream/types/get_components_response.py @@ -0,0 +1,26 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from .component import Component +from .page_info import PageInfo + + +class GetComponentsResponse(UniversalBaseModel): + """ + Response received when retrieving a list of components + """ + + data: typing.List[Component] + page_info: PageInfo + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/pipedream/types/get_trigger_events_response.py b/src/pipedream/types/get_trigger_events_response.py new file mode 100644 index 0000000..4f84810 --- /dev/null +++ b/src/pipedream/types/get_trigger_events_response.py @@ -0,0 +1,24 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from .emitted_event import EmittedEvent + + +class GetTriggerEventsResponse(UniversalBaseModel): + """ + Response received when retrieving trigger events + """ + + data: typing.List[EmittedEvent] + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/pipedream/types/get_trigger_response.py b/src/pipedream/types/get_trigger_response.py new file mode 100644 index 0000000..d97f5e3 --- /dev/null +++ b/src/pipedream/types/get_trigger_response.py @@ -0,0 +1,24 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from .deployed_component import DeployedComponent + + +class GetTriggerResponse(UniversalBaseModel): + """ + Response received when retrieving a deployed trigger + """ + + data: DeployedComponent + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/pipedream/types/get_trigger_webhooks_response.py b/src/pipedream/types/get_trigger_webhooks_response.py new file mode 100644 index 0000000..1cd7254 --- /dev/null +++ b/src/pipedream/types/get_trigger_webhooks_response.py @@ -0,0 +1,23 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel + + +class GetTriggerWebhooksResponse(UniversalBaseModel): + """ + Response received when retrieving trigger webhooks + """ + + webhook_urls: typing.List[str] + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/pipedream/types/get_trigger_workflows_response.py b/src/pipedream/types/get_trigger_workflows_response.py new file mode 100644 index 0000000..b69afc4 --- /dev/null +++ b/src/pipedream/types/get_trigger_workflows_response.py @@ -0,0 +1,23 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel + + +class GetTriggerWorkflowsResponse(UniversalBaseModel): + """ + Response received when retrieving trigger workflows + """ + + workflow_ids: typing.List[str] + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/pipedream/types/get_triggers_response.py b/src/pipedream/types/get_triggers_response.py new file mode 100644 index 0000000..19d13ab --- /dev/null +++ b/src/pipedream/types/get_triggers_response.py @@ -0,0 +1,26 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from .deployed_component import DeployedComponent +from .page_info import PageInfo + + +class GetTriggersResponse(UniversalBaseModel): + """ + Response received when listing deployed triggers + """ + + data: typing.List[DeployedComponent] + page_info: PageInfo + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/pipedream/types/list_accounts_response.py b/src/pipedream/types/list_accounts_response.py new file mode 100644 index 0000000..19db243 --- /dev/null +++ b/src/pipedream/types/list_accounts_response.py @@ -0,0 +1,26 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from .account import Account +from .page_info import PageInfo + + +class ListAccountsResponse(UniversalBaseModel): + """ + Response received when listing accounts + """ + + data: typing.List[Account] + page_info: PageInfo + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/pipedream/types/list_app_categories_response.py b/src/pipedream/types/list_app_categories_response.py new file mode 100644 index 0000000..0bde20d --- /dev/null +++ b/src/pipedream/types/list_app_categories_response.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +from .app_category import AppCategory + +ListAppCategoriesResponse = typing.List[AppCategory] diff --git a/src/pipedream/types/list_apps_response.py b/src/pipedream/types/list_apps_response.py new file mode 100644 index 0000000..bb719ed --- /dev/null +++ b/src/pipedream/types/list_apps_response.py @@ -0,0 +1,26 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from .app import App +from .page_info import PageInfo + + +class ListAppsResponse(UniversalBaseModel): + """ + Response received when listing apps + """ + + data: typing.List[App] + page_info: PageInfo + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/pipedream/types/page_info.py b/src/pipedream/types/page_info.py new file mode 100644 index 0000000..3cd0148 --- /dev/null +++ b/src/pipedream/types/page_info.py @@ -0,0 +1,22 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel + + +class PageInfo(UniversalBaseModel): + count: typing.Optional[int] = None + total_count: typing.Optional[int] = None + start_cursor: typing.Optional[str] = None + end_cursor: typing.Optional[str] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/pipedream/types/project_info_response.py b/src/pipedream/types/project_info_response.py new file mode 100644 index 0000000..24c1c65 --- /dev/null +++ b/src/pipedream/types/project_info_response.py @@ -0,0 +1,24 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from .project_info_response_apps_item import ProjectInfoResponseAppsItem + + +class ProjectInfoResponse(UniversalBaseModel): + """ + Response received when retrieving project info + """ + + apps: typing.List[ProjectInfoResponseAppsItem] + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/pipedream/types/project_info_response_apps_item.py b/src/pipedream/types/project_info_response_apps_item.py new file mode 100644 index 0000000..e8b0f61 --- /dev/null +++ b/src/pipedream/types/project_info_response_apps_item.py @@ -0,0 +1,27 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel + + +class ProjectInfoResponseAppsItem(UniversalBaseModel): + id: typing.Optional[str] = pydantic.Field(default=None) + """ + ID of the app. Only applies for OAuth apps. + """ + + name_slug: str = pydantic.Field() + """ + The name slug of the target app + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/pipedream/types/prop_option.py b/src/pipedream/types/prop_option.py new file mode 100644 index 0000000..652f746 --- /dev/null +++ b/src/pipedream/types/prop_option.py @@ -0,0 +1,28 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel + + +class PropOption(UniversalBaseModel): + """ + A configuration option for a component's prop + """ + + label: str = pydantic.Field() + """ + The human-readable label for the option + """ + + value: typing.Optional[typing.Any] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/pipedream/types/proxy_response.py b/src/pipedream/types/proxy_response.py new file mode 100644 index 0000000..dea284e --- /dev/null +++ b/src/pipedream/types/proxy_response.py @@ -0,0 +1,33 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel + + +class ProxyResponse(UniversalBaseModel): + """ + The parsed response body from a proxied API request + """ + + status: typing.Optional[int] = pydantic.Field(default=None) + """ + HTTP status code + """ + + headers: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = pydantic.Field(default=None) + """ + Response headers + """ + + body: typing.Optional[typing.Optional[typing.Any]] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/pipedream/types/reload_props_opts.py b/src/pipedream/types/reload_props_opts.py new file mode 100644 index 0000000..409e0fa --- /dev/null +++ b/src/pipedream/types/reload_props_opts.py @@ -0,0 +1,51 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel + + +class ReloadPropsOpts(UniversalBaseModel): + """ + Request options for reloading a component's props when dealing with dynamic props + """ + + id: str = pydantic.Field() + """ + The component ID + """ + + external_user_id: str = pydantic.Field() + """ + The external user ID + """ + + blocking: typing.Optional[bool] = pydantic.Field(default=None) + """ + Whether this operation should block until completion + """ + + configured_props: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = pydantic.Field(default=None) + """ + The configured properties for the component + """ + + dynamic_props_id: typing.Optional[str] = pydantic.Field(default=None) + """ + The ID for dynamic props + """ + + async_handle: typing.Optional[str] = pydantic.Field(default=None) + """ + Handle for async operations + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/pipedream/types/reload_props_response.py b/src/pipedream/types/reload_props_response.py new file mode 100644 index 0000000..206ef9d --- /dev/null +++ b/src/pipedream/types/reload_props_response.py @@ -0,0 +1,27 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from .configurable_prop import ConfigurableProp + + +class ReloadPropsResponse(UniversalBaseModel): + """ + Response from reloading component props + """ + + configurable_props: typing.Optional[typing.List[ConfigurableProp]] = pydantic.Field(default=None) + """ + The updated configurable properties + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/pipedream/types/run_action_response.py b/src/pipedream/types/run_action_response.py new file mode 100644 index 0000000..337017d --- /dev/null +++ b/src/pipedream/types/run_action_response.py @@ -0,0 +1,29 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel + + +class RunActionResponse(UniversalBaseModel): + """ + The response received after running an action. See https://pipedream.com/docs/components/api#returning-data-from-steps for more details. + """ + + exports: typing.Optional[typing.Optional[typing.Any]] = None + os: typing.Optional[typing.Optional[typing.Any]] = None + ret: typing.Optional[typing.Optional[typing.Any]] = None + stash_id: typing.Optional[str] = pydantic.Field(default=None) + """ + The ID of the File Stash that was used to sync the action's /tmp directory + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/pipedream/types/start_connect_opts.py b/src/pipedream/types/start_connect_opts.py new file mode 100644 index 0000000..b68eef9 --- /dev/null +++ b/src/pipedream/types/start_connect_opts.py @@ -0,0 +1,26 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel + + +class StartConnectOpts(UniversalBaseModel): + """ + Options for starting the connection process + """ + + iframe: typing.Optional[str] = pydantic.Field(default=None) + """ + ID of the iframe element to use + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/pipedream/types/validate_token_params.py b/src/pipedream/types/validate_token_params.py new file mode 100644 index 0000000..8599aa4 --- /dev/null +++ b/src/pipedream/types/validate_token_params.py @@ -0,0 +1,31 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel + + +class ValidateTokenParams(UniversalBaseModel): + """ + Parameters for token validation + """ + + app_id: str = pydantic.Field() + """ + The app ID to validate against + """ + + oauth_app_id: typing.Optional[str] = pydantic.Field(default=None) + """ + The OAuth app ID + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/pipedream/types/validate_token_response.py b/src/pipedream/types/validate_token_response.py new file mode 100644 index 0000000..a304140 --- /dev/null +++ b/src/pipedream/types/validate_token_response.py @@ -0,0 +1,68 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from .app import App + + +class ValidateTokenResponse(UniversalBaseModel): + """ + Response received when validating a connect token + """ + + app: typing.Optional[App] = None + error: typing.Optional[str] = pydantic.Field(default=None) + """ + Error message if validation failed + """ + + error_redirect_uri: typing.Optional[str] = pydantic.Field(default=None) + """ + URI to redirect to on error + """ + + oauth_app_id: typing.Optional[str] = pydantic.Field(default=None) + """ + OAuth app ID if applicable + """ + + project_app_name: typing.Optional[str] = pydantic.Field(default=None) + """ + Name of the project app + """ + + project_environment: typing.Optional[str] = pydantic.Field(default=None) + """ + Environment of the project + """ + + project_id: typing.Optional[str] = pydantic.Field(default=None) + """ + ID of the project + """ + + project_support_email: typing.Optional[str] = pydantic.Field(default=None) + """ + Support email for the project + """ + + success: bool = pydantic.Field() + """ + Whether the token validation was successful + """ + + success_redirect_uri: typing.Optional[str] = pydantic.Field(default=None) + """ + URI to redirect to on success + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/pipedream/users/__init__.py b/src/pipedream/users/__init__.py new file mode 100644 index 0000000..5cde020 --- /dev/null +++ b/src/pipedream/users/__init__.py @@ -0,0 +1,4 @@ +# This file was auto-generated by Fern from our API Definition. + +# isort: skip_file + diff --git a/src/pipedream/users/client.py b/src/pipedream/users/client.py new file mode 100644 index 0000000..a7a8dc7 --- /dev/null +++ b/src/pipedream/users/client.py @@ -0,0 +1,119 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ..core.request_options import RequestOptions +from .raw_client import AsyncRawUsersClient, RawUsersClient + + +class UsersClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._raw_client = RawUsersClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> RawUsersClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + RawUsersClient + """ + return self._raw_client + + def delete_external_user( + self, project_id: str, external_user_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> None: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + external_user_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + None + + Examples + -------- + from pipedream import Pipedream + + client = Pipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + client.users.delete_external_user( + project_id="project_id", + external_user_id="external_user_id", + ) + """ + _response = self._raw_client.delete_external_user(project_id, external_user_id, request_options=request_options) + return _response.data + + +class AsyncUsersClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._raw_client = AsyncRawUsersClient(client_wrapper=client_wrapper) + + @property + def with_raw_response(self) -> AsyncRawUsersClient: + """ + Retrieves a raw implementation of this client that returns raw responses. + + Returns + ------- + AsyncRawUsersClient + """ + return self._raw_client + + async def delete_external_user( + self, project_id: str, external_user_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> None: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + external_user_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + None + + Examples + -------- + import asyncio + + from pipedream import AsyncPipedream + + client = AsyncPipedream( + x_pd_environment="YOUR_X_PD_ENVIRONMENT", + client_id="YOUR_CLIENT_ID", + client_secret="YOUR_CLIENT_SECRET", + ) + + + async def main() -> None: + await client.users.delete_external_user( + project_id="project_id", + external_user_id="external_user_id", + ) + + + asyncio.run(main()) + """ + _response = await self._raw_client.delete_external_user( + project_id, external_user_id, request_options=request_options + ) + return _response.data diff --git a/src/pipedream/users/raw_client.py b/src/pipedream/users/raw_client.py new file mode 100644 index 0000000..fbe5e52 --- /dev/null +++ b/src/pipedream/users/raw_client.py @@ -0,0 +1,82 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing +from json.decoder import JSONDecodeError + +from ..core.api_error import ApiError +from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper +from ..core.http_response import AsyncHttpResponse, HttpResponse +from ..core.jsonable_encoder import jsonable_encoder +from ..core.request_options import RequestOptions + + +class RawUsersClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def delete_external_user( + self, project_id: str, external_user_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> HttpResponse[None]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + external_user_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + HttpResponse[None] + """ + _response = self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/users/{jsonable_encoder(external_user_id)}", + method="DELETE", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return HttpResponse(response=_response, data=None) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) + + +class AsyncRawUsersClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def delete_external_user( + self, project_id: str, external_user_id: str, *, request_options: typing.Optional[RequestOptions] = None + ) -> AsyncHttpResponse[None]: + """ + Parameters + ---------- + project_id : str + The project ID, which starts with 'proj_'. + + external_user_id : str + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + AsyncHttpResponse[None] + """ + _response = await self._client_wrapper.httpx_client.request( + f"v1/connect/{jsonable_encoder(project_id)}/users/{jsonable_encoder(external_user_id)}", + method="DELETE", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return AsyncHttpResponse(response=_response, data=None) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text) + raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) diff --git a/src/pipedream/version.py b/src/pipedream/version.py new file mode 100644 index 0000000..3bb862e --- /dev/null +++ b/src/pipedream/version.py @@ -0,0 +1,3 @@ +from importlib import metadata + +__version__ = metadata.version("pipedream") diff --git a/tests/custom/test_client.py b/tests/custom/test_client.py new file mode 100644 index 0000000..ab04ce6 --- /dev/null +++ b/tests/custom/test_client.py @@ -0,0 +1,7 @@ +import pytest + + +# Get started with writing tests with pytest at https://docs.pytest.org +@pytest.mark.skip(reason="Unimplemented") +def test_client() -> None: + assert True diff --git a/tests/utils/__init__.py b/tests/utils/__init__.py new file mode 100644 index 0000000..f3ea265 --- /dev/null +++ b/tests/utils/__init__.py @@ -0,0 +1,2 @@ +# This file was auto-generated by Fern from our API Definition. + diff --git a/tests/utils/assets/models/__init__.py b/tests/utils/assets/models/__init__.py new file mode 100644 index 0000000..2cf0126 --- /dev/null +++ b/tests/utils/assets/models/__init__.py @@ -0,0 +1,21 @@ +# This file was auto-generated by Fern from our API Definition. + +# This file was auto-generated by Fern from our API Definition. + +from .circle import CircleParams +from .object_with_defaults import ObjectWithDefaultsParams +from .object_with_optional_field import ObjectWithOptionalFieldParams +from .shape import Shape_CircleParams, Shape_SquareParams, ShapeParams +from .square import SquareParams +from .undiscriminated_shape import UndiscriminatedShapeParams + +__all__ = [ + "CircleParams", + "ObjectWithDefaultsParams", + "ObjectWithOptionalFieldParams", + "ShapeParams", + "Shape_CircleParams", + "Shape_SquareParams", + "SquareParams", + "UndiscriminatedShapeParams", +] diff --git a/tests/utils/assets/models/circle.py b/tests/utils/assets/models/circle.py new file mode 100644 index 0000000..fb4fdc6 --- /dev/null +++ b/tests/utils/assets/models/circle.py @@ -0,0 +1,11 @@ +# This file was auto-generated by Fern from our API Definition. + +# This file was auto-generated by Fern from our API Definition. + +import typing_extensions + +from pipedream.core.serialization import FieldMetadata + + +class CircleParams(typing_extensions.TypedDict): + radius_measurement: typing_extensions.Annotated[float, FieldMetadata(alias="radiusMeasurement")] diff --git a/tests/utils/assets/models/color.py b/tests/utils/assets/models/color.py new file mode 100644 index 0000000..2aa2c4c --- /dev/null +++ b/tests/utils/assets/models/color.py @@ -0,0 +1,7 @@ +# This file was auto-generated by Fern from our API Definition. + +# This file was auto-generated by Fern from our API Definition. + +import typing + +Color = typing.Union[typing.Literal["red", "blue"], typing.Any] diff --git a/tests/utils/assets/models/object_with_defaults.py b/tests/utils/assets/models/object_with_defaults.py new file mode 100644 index 0000000..a977b1d --- /dev/null +++ b/tests/utils/assets/models/object_with_defaults.py @@ -0,0 +1,15 @@ +# This file was auto-generated by Fern from our API Definition. + +# This file was auto-generated by Fern from our API Definition. + +import typing_extensions + + +class ObjectWithDefaultsParams(typing_extensions.TypedDict): + """ + Defines properties with default values and validation rules. + """ + + decimal: typing_extensions.NotRequired[float] + string: typing_extensions.NotRequired[str] + required_string: str diff --git a/tests/utils/assets/models/object_with_optional_field.py b/tests/utils/assets/models/object_with_optional_field.py new file mode 100644 index 0000000..d61cc7e --- /dev/null +++ b/tests/utils/assets/models/object_with_optional_field.py @@ -0,0 +1,35 @@ +# This file was auto-generated by Fern from our API Definition. + +# This file was auto-generated by Fern from our API Definition. + +import datetime as dt +import typing +import uuid + +import typing_extensions +from .color import Color +from .shape import ShapeParams +from .undiscriminated_shape import UndiscriminatedShapeParams + +from pipedream.core.serialization import FieldMetadata + + +class ObjectWithOptionalFieldParams(typing_extensions.TypedDict): + literal: typing.Literal["lit_one"] + string: typing_extensions.NotRequired[str] + integer: typing_extensions.NotRequired[int] + long_: typing_extensions.NotRequired[typing_extensions.Annotated[int, FieldMetadata(alias="long")]] + double: typing_extensions.NotRequired[float] + bool_: typing_extensions.NotRequired[typing_extensions.Annotated[bool, FieldMetadata(alias="bool")]] + datetime: typing_extensions.NotRequired[dt.datetime] + date: typing_extensions.NotRequired[dt.date] + uuid_: typing_extensions.NotRequired[typing_extensions.Annotated[uuid.UUID, FieldMetadata(alias="uuid")]] + base_64: typing_extensions.NotRequired[typing_extensions.Annotated[str, FieldMetadata(alias="base64")]] + list_: typing_extensions.NotRequired[typing_extensions.Annotated[typing.Sequence[str], FieldMetadata(alias="list")]] + set_: typing_extensions.NotRequired[typing_extensions.Annotated[typing.Set[str], FieldMetadata(alias="set")]] + map_: typing_extensions.NotRequired[typing_extensions.Annotated[typing.Dict[int, str], FieldMetadata(alias="map")]] + enum: typing_extensions.NotRequired[Color] + union: typing_extensions.NotRequired[ShapeParams] + second_union: typing_extensions.NotRequired[ShapeParams] + undiscriminated_union: typing_extensions.NotRequired[UndiscriminatedShapeParams] + any: typing.Optional[typing.Any] diff --git a/tests/utils/assets/models/shape.py b/tests/utils/assets/models/shape.py new file mode 100644 index 0000000..e1124a6 --- /dev/null +++ b/tests/utils/assets/models/shape.py @@ -0,0 +1,28 @@ +# This file was auto-generated by Fern from our API Definition. + +# This file was auto-generated by Fern from our API Definition. + +from __future__ import annotations + +import typing + +import typing_extensions + +from pipedream.core.serialization import FieldMetadata + + +class Base(typing_extensions.TypedDict): + id: str + + +class Shape_CircleParams(Base): + shape_type: typing_extensions.Annotated[typing.Literal["circle"], FieldMetadata(alias="shapeType")] + radius_measurement: typing_extensions.Annotated[float, FieldMetadata(alias="radiusMeasurement")] + + +class Shape_SquareParams(Base): + shape_type: typing_extensions.Annotated[typing.Literal["square"], FieldMetadata(alias="shapeType")] + length_measurement: typing_extensions.Annotated[float, FieldMetadata(alias="lengthMeasurement")] + + +ShapeParams = typing.Union[Shape_CircleParams, Shape_SquareParams] diff --git a/tests/utils/assets/models/square.py b/tests/utils/assets/models/square.py new file mode 100644 index 0000000..9f0e361 --- /dev/null +++ b/tests/utils/assets/models/square.py @@ -0,0 +1,11 @@ +# This file was auto-generated by Fern from our API Definition. + +# This file was auto-generated by Fern from our API Definition. + +import typing_extensions + +from pipedream.core.serialization import FieldMetadata + + +class SquareParams(typing_extensions.TypedDict): + length_measurement: typing_extensions.Annotated[float, FieldMetadata(alias="lengthMeasurement")] diff --git a/tests/utils/assets/models/undiscriminated_shape.py b/tests/utils/assets/models/undiscriminated_shape.py new file mode 100644 index 0000000..99f12b3 --- /dev/null +++ b/tests/utils/assets/models/undiscriminated_shape.py @@ -0,0 +1,10 @@ +# This file was auto-generated by Fern from our API Definition. + +# This file was auto-generated by Fern from our API Definition. + +import typing + +from .circle import CircleParams +from .square import SquareParams + +UndiscriminatedShapeParams = typing.Union[CircleParams, SquareParams] diff --git a/tests/utils/test_http_client.py b/tests/utils/test_http_client.py new file mode 100644 index 0000000..c9ccb3b --- /dev/null +++ b/tests/utils/test_http_client.py @@ -0,0 +1,61 @@ +# This file was auto-generated by Fern from our API Definition. + +from pipedream.core.http_client import get_request_body +from pipedream.core.request_options import RequestOptions + + +def get_request_options() -> RequestOptions: + return {"additional_body_parameters": {"see you": "later"}} + + +def test_get_json_request_body() -> None: + json_body, data_body = get_request_body(json={"hello": "world"}, data=None, request_options=None, omit=None) + assert json_body == {"hello": "world"} + assert data_body is None + + json_body_extras, data_body_extras = get_request_body( + json={"goodbye": "world"}, data=None, request_options=get_request_options(), omit=None + ) + + assert json_body_extras == {"goodbye": "world", "see you": "later"} + assert data_body_extras is None + + +def test_get_files_request_body() -> None: + json_body, data_body = get_request_body(json=None, data={"hello": "world"}, request_options=None, omit=None) + assert data_body == {"hello": "world"} + assert json_body is None + + json_body_extras, data_body_extras = get_request_body( + json=None, data={"goodbye": "world"}, request_options=get_request_options(), omit=None + ) + + assert data_body_extras == {"goodbye": "world", "see you": "later"} + assert json_body_extras is None + + +def test_get_none_request_body() -> None: + json_body, data_body = get_request_body(json=None, data=None, request_options=None, omit=None) + assert data_body is None + assert json_body is None + + json_body_extras, data_body_extras = get_request_body( + json=None, data=None, request_options=get_request_options(), omit=None + ) + + assert json_body_extras == {"see you": "later"} + assert data_body_extras is None + + +def test_get_empty_json_request_body() -> None: + unrelated_request_options: RequestOptions = {"max_retries": 3} + json_body, data_body = get_request_body(json=None, data=None, request_options=unrelated_request_options, omit=None) + assert json_body is None + assert data_body is None + + json_body_extras, data_body_extras = get_request_body( + json={}, data=None, request_options=unrelated_request_options, omit=None + ) + + assert json_body_extras is None + assert data_body_extras is None diff --git a/tests/utils/test_query_encoding.py b/tests/utils/test_query_encoding.py new file mode 100644 index 0000000..b363d84 --- /dev/null +++ b/tests/utils/test_query_encoding.py @@ -0,0 +1,37 @@ +# This file was auto-generated by Fern from our API Definition. + + +from pipedream.core.query_encoder import encode_query + + +def test_query_encoding_deep_objects() -> None: + assert encode_query({"hello world": "hello world"}) == [("hello world", "hello world")] + assert encode_query({"hello_world": {"hello": "world"}}) == [("hello_world[hello]", "world")] + assert encode_query({"hello_world": {"hello": {"world": "today"}, "test": "this"}, "hi": "there"}) == [ + ("hello_world[hello][world]", "today"), + ("hello_world[test]", "this"), + ("hi", "there"), + ] + + +def test_query_encoding_deep_object_arrays() -> None: + assert encode_query({"objects": [{"key": "hello", "value": "world"}, {"key": "foo", "value": "bar"}]}) == [ + ("objects[key]", "hello"), + ("objects[value]", "world"), + ("objects[key]", "foo"), + ("objects[value]", "bar"), + ] + assert encode_query( + {"users": [{"name": "string", "tags": ["string"]}, {"name": "string2", "tags": ["string2", "string3"]}]} + ) == [ + ("users[name]", "string"), + ("users[tags]", "string"), + ("users[name]", "string2"), + ("users[tags]", "string2"), + ("users[tags]", "string3"), + ] + + +def test_encode_query_with_none() -> None: + encoded = encode_query(None) + assert encoded is None diff --git a/tests/utils/test_serialization.py b/tests/utils/test_serialization.py new file mode 100644 index 0000000..aae7272 --- /dev/null +++ b/tests/utils/test_serialization.py @@ -0,0 +1,72 @@ +# This file was auto-generated by Fern from our API Definition. + +from typing import Any, List + +from .assets.models import ObjectWithOptionalFieldParams, ShapeParams + +from pipedream.core.serialization import convert_and_respect_annotation_metadata + +UNION_TEST: ShapeParams = {"radius_measurement": 1.0, "shape_type": "circle", "id": "1"} +UNION_TEST_CONVERTED = {"shapeType": "circle", "radiusMeasurement": 1.0, "id": "1"} + + +def test_convert_and_respect_annotation_metadata() -> None: + data: ObjectWithOptionalFieldParams = { + "string": "string", + "long_": 12345, + "bool_": True, + "literal": "lit_one", + "any": "any", + } + converted = convert_and_respect_annotation_metadata( + object_=data, annotation=ObjectWithOptionalFieldParams, direction="write" + ) + assert converted == {"string": "string", "long": 12345, "bool": True, "literal": "lit_one", "any": "any"} + + +def test_convert_and_respect_annotation_metadata_in_list() -> None: + data: List[ObjectWithOptionalFieldParams] = [ + {"string": "string", "long_": 12345, "bool_": True, "literal": "lit_one", "any": "any"}, + {"string": "another string", "long_": 67890, "list_": [], "literal": "lit_one", "any": "any"}, + ] + converted = convert_and_respect_annotation_metadata( + object_=data, annotation=List[ObjectWithOptionalFieldParams], direction="write" + ) + + assert converted == [ + {"string": "string", "long": 12345, "bool": True, "literal": "lit_one", "any": "any"}, + {"string": "another string", "long": 67890, "list": [], "literal": "lit_one", "any": "any"}, + ] + + +def test_convert_and_respect_annotation_metadata_in_nested_object() -> None: + data: ObjectWithOptionalFieldParams = { + "string": "string", + "long_": 12345, + "union": UNION_TEST, + "literal": "lit_one", + "any": "any", + } + converted = convert_and_respect_annotation_metadata( + object_=data, annotation=ObjectWithOptionalFieldParams, direction="write" + ) + + assert converted == { + "string": "string", + "long": 12345, + "union": UNION_TEST_CONVERTED, + "literal": "lit_one", + "any": "any", + } + + +def test_convert_and_respect_annotation_metadata_in_union() -> None: + converted = convert_and_respect_annotation_metadata(object_=UNION_TEST, annotation=ShapeParams, direction="write") + + assert converted == UNION_TEST_CONVERTED + + +def test_convert_and_respect_annotation_metadata_with_empty_object() -> None: + data: Any = {} + converted = convert_and_respect_annotation_metadata(object_=data, annotation=ShapeParams, direction="write") + assert converted == data